From 732a7108dbfdbbe0d6ba66b82d32ea10a1d3608e Mon Sep 17 00:00:00 2001 From: jolheiser Date: Tue, 6 Oct 2020 23:05:29 -0500 Subject: [PATCH 1/9] Code improvements Signed-off-by: jolheiser --- Earthfile | 10 +++ Makefile | 76 +------------------- cmd/add.go | 16 +++-- cmd/cmd.go | 19 ++--- cmd/config.go | 16 +++-- cmd/export.go | 12 +++- cmd/get.go | 17 +++-- cmd/import.go | 23 +++--- cmd/list.go | 12 +++- cmd/remove.go | 21 ++++-- cmd/search.go | 89 ++++++++++++++++++++++++ cmd/server.go | 14 +++- config/config.go | 146 +++++++++++++++++++++++++++++++++++++++ go.mod | 19 +++-- go.sum | 37 +++++++--- main.go | 21 +++--- modules/config/config.go | 132 ----------------------------------- modules/router/router.go | 70 ------------------- router/router.go | 76 ++++++++++++++++++++ 19 files changed, 476 insertions(+), 350 deletions(-) create mode 100644 Earthfile create mode 100644 cmd/search.go create mode 100644 config/config.go delete mode 100644 modules/config/config.go delete mode 100644 modules/router/router.go create mode 100644 router/router.go diff --git a/Earthfile b/Earthfile new file mode 100644 index 0000000..6bd3e59 --- /dev/null +++ b/Earthfile @@ -0,0 +1,10 @@ +# To lint, install Earthly and run `earth +lint` +# This ensures the usage of the same version of golangci-lint + +FROM golangci/golangci-lint:v1.31 + +WORKDIR /gpm + +lint: + COPY . . + RUN golangci-lint run \ No newline at end of file diff --git a/Makefile b/Makefile index ba99758..7472947 100644 --- a/Makefile +++ b/Makefile @@ -1,32 +1,9 @@ -DIST := dist GO ?= go -SHASUM ?= shasum -a 256 - -ifneq ($(DRONE_TAG),) - VERSION ?= $(subst v,,$(DRONE_TAG)) - LONG_VERSION ?= $(VERSION) -else - ifneq ($(DRONE_BRANCH),) - VERSION ?= $(subst release/v,,$(DRONE_BRANCH)) - else - VERSION ?= master - endif - LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') -endif - -LDFLAGS := $(LDFLAGS) -X "go.jolheiser.com/gpm/modules/config.Version=$(LONG_VERSION)" +VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') .PHONY: build build: - $(GO) build -ldflags '-s -w $(LDFLAGS)' - -.PHONY: lint -lint: - @hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - export BINARY="golangci-lint"; \ - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.23.1; \ - fi - golangci-lint run --timeout 5m + $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/modules/config.Version=$(VERSION)"' .PHONY: fmt fmt: @@ -35,52 +12,3 @@ fmt: .PHONY: test test: $(GO) test -race ./... - -.PHONY: release -release: release-dirs check-xgo release-windows release-linux release-darwin release-copy release-compress release-check - -.PHONY: check-xgo -check-xgo: - @hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - $(GO) get -u src.techknowlogick.com/xgo; \ - fi - -.PHONY: release-dirs -release-dirs: - mkdir -p $(DIST)/binaries $(DIST)/release - -.PHONY: release-windows -release-windows: - xgo -dest $(DIST)/binaries -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-linux -release-linux: - xgo -dest $(DIST)/binaries -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-darwin -release-darwin: - xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-copy -release-copy: - cd $(DIST); for file in `find /build -type f -name "*"`; do cp $${file} ./release/; done; - -.PHONY: release-check -release-check: - cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done; - -.PHONY: release-compress -release-compress: - @hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - $(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \ - fi - cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done; \ No newline at end of file diff --git a/cmd/add.go b/cmd/add.go index bece38d..2ee2e71 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -1,12 +1,14 @@ package cmd import ( + "regexp" + "strings" + + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "regexp" - "strings" ) var Add = cli.Command{ @@ -25,6 +27,10 @@ var Add = cli.Command{ var vPattern = regexp.MustCompile(`v\d+$`) func doAdd(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } goGetQuestion := &survey.Input{ Message: "Package go-get import", @@ -56,9 +62,9 @@ func doAdd(ctx *cli.Context) error { Name: nameAnswer, Import: goGetAnswer, } - config.AddPackages(ctx.Bool("force"), pkg) + cfg.AddPackages(ctx.Bool("force"), pkg) - if err := config.Save(); err != nil { + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/cmd.go b/cmd/cmd.go index 95c25c7..b574758 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,15 +1,18 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" - "go.jolheiser.com/gpm/modules/config" ) -var Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "url", - Aliases: []string{"u"}, - Usage: "gpm server to use", - Value: config.GPMURL, - }, +func NewFlags(cfg *config.Config) []cli.Flag { + return []cli.Flag{ + &cli.StringFlag{ + Name: "url", + Aliases: []string{"u"}, + Usage: "gpm server to use", + Value: cfg.GPMURL, + }, + } } diff --git a/cmd/config.go b/cmd/config.go index 513b32d..04be274 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -1,10 +1,11 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" ) var Config = cli.Command{ @@ -14,10 +15,15 @@ var Config = cli.Command{ Action: doConfig, } -func doConfig(ctx *cli.Context) error { +func doConfig(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + urlQuestion := &survey.Input{ Message: "gpm URL", - Default: config.GPMURL, + Default: cfg.GPMURL, } var urlAnswer string @@ -25,8 +31,8 @@ func doConfig(ctx *cli.Context) error { return err } - config.GPMURL = urlAnswer - if err := config.Save(); err != nil { + cfg.GPMURL = urlAnswer + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/export.go b/cmd/export.go index 2366c0b..c699a63 100644 --- a/cmd/export.go +++ b/cmd/export.go @@ -2,8 +2,10 @@ package cmd import ( "fmt" + + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" - "go.jolheiser.com/gpm/modules/config" ) var Export = cli.Command{ @@ -12,9 +14,13 @@ var Export = cli.Command{ Action: doExport, } -func doExport(ctx *cli.Context) error { +func doExport(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } - export, err := config.Export() + export, err := cfg.Export() if err != nil { return err } diff --git a/cmd/get.go b/cmd/get.go index f9a5373..e8d14a0 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -3,15 +3,17 @@ package cmd import ( "encoding/json" "fmt" - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" "io/ioutil" "net/http" "os" "os/exec" "strings" + + "go.jolheiser.com/gpm/config" + + "github.com/AlecAivazis/survey/v2" + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" ) var Get = cli.Command{ @@ -31,6 +33,11 @@ var Get = cli.Command{ } func doGet(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + pkgs := ctx.Args().Slice() if len(pkgs) == 0 { pkgsQuestion := &survey.Multiline{ @@ -45,7 +52,7 @@ func doGet(ctx *cli.Context) error { pkgs = strings.Split(pkgsAnswer, "\n") } - local := config.PackageMap() + local := cfg.Packages.Map() for _, pkg := range pkgs { var url string if u, ok := local[pkg]; ok && !ctx.Bool("ignore-local") { diff --git a/cmd/import.go b/cmd/import.go index 8cd3f52..264aa0f 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -3,12 +3,14 @@ package cmd import ( "encoding/json" "errors" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" "io/ioutil" "net/http" "strings" + + "go.jolheiser.com/gpm/config" + + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" ) var Import = cli.Command{ @@ -25,6 +27,11 @@ var Import = cli.Command{ } func doImport(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + if ctx.NArg() == 0 { return errors.New("must point to either a JSON file or gpm server export endpoint") } @@ -38,7 +45,6 @@ func doImport(ctx *cli.Context) error { } var data []byte - var err error if isJSON { data, err = ioutil.ReadFile(arg) if err != nil { @@ -55,16 +61,15 @@ func doImport(ctx *cli.Context) error { return err } defer resp.Body.Close() - } - var cfg config.Config - if err := json.Unmarshal(data, &cfg); err != nil { + var importPkgs []config.Package + if err := json.Unmarshal(data, &importPkgs); err != nil { return err } - config.AddPackages(ctx.Bool("force"), cfg.Packages...) + cfg.AddPackages(ctx.Bool("force"), importPkgs...) - if err := config.Save(); err != nil { + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/list.go b/cmd/list.go index 87c1331..bdf825b 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1,9 +1,10 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" ) var List = cli.Command{ @@ -13,8 +14,13 @@ var List = cli.Command{ Action: doList, } -func doList(ctx *cli.Context) error { - for _, pkg := range config.Packages { +func doList(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + + for _, pkg := range cfg.Packages { beaver.Infof("%s -> %s", pkg.Name, pkg.Import) } return nil diff --git a/cmd/remove.go b/cmd/remove.go index 79c18b8..ea38461 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -2,21 +2,28 @@ package cmd import ( "fmt" + "strings" + + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "strings" ) var Remove = cli.Command{ Name: "remove", Aliases: []string{"rm"}, - Usage: "Remove a package", + Usage: "Remove package(s)", Action: doRemove, } -func doRemove(ctx *cli.Context) error { +func doRemove(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + pkgQuestion := &survey.Input{ Message: "Package name", } @@ -26,7 +33,7 @@ func doRemove(ctx *cli.Context) error { return err } - for idx, p := range config.Packages { + for idx, p := range cfg.Packages { if strings.EqualFold(p.Name, pkgAnswer) { confirm := &survey.Confirm{ Message: fmt.Sprintf("Are you sure you want to remove %s (%s) ?", p.Name, p.Import), @@ -39,8 +46,8 @@ func doRemove(ctx *cli.Context) error { } if answer { - config.Packages = append(config.Packages[:idx], config.Packages[idx+1:]...) - if err := config.Save(); err != nil { + cfg.Packages = append(cfg.Packages[:idx], cfg.Packages[idx+1:]...) + if err := cfg.Save(); err != nil { return err } beaver.Infof("Removed `%s` from local gpm.", p.Name) diff --git a/cmd/search.go b/cmd/search.go new file mode 100644 index 0000000..796e121 --- /dev/null +++ b/cmd/search.go @@ -0,0 +1,89 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "go.jolheiser.com/gpm/config" + + "github.com/AlecAivazis/survey/v2" + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" +) + +var Search = cli.Command{ + Name: "search", + Aliases: []string{"s"}, + Usage: "Search packages", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "local", + Usage: "Search locally", + }, + }, + Action: doSearch, +} + +func doSearch(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + + packageMap := cfg.Packages.Map() + packageSlice := cfg.Packages.Slice() + if !ctx.Bool("local") { + export, err := queryExport(ctx.String("url")) + if err != nil { + return err + } + packageMap = export.Map() + packageSlice = export.Slice() + } + + q := &survey.MultiSelect{ + Message: "Select packages", + Options: packageSlice, + } + + var a []string + if err := survey.AskOne(q, &a); err != nil { + return err + } + + for _, name := range a { + pkg, ok := packageMap[name] + if !ok { + beaver.Errorf("could not find package for `%s`", name) + continue + } + beaver.Infof("getting `%s`...", name) + if err := goGet(pkg.Import); err != nil { + beaver.Error(err) + } + } + + return nil +} + +func queryExport(server string) (config.Packages, error) { + resp, err := http.Get(fmt.Sprintf("%s/export", server)) + if err != nil { + return nil, err + } + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var importPkgs config.Packages + if err := json.Unmarshal(data, &importPkgs); err != nil { + return nil, err + } + + return importPkgs, nil +} diff --git a/cmd/server.go b/cmd/server.go index e24ffcf..f592e32 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -2,10 +2,13 @@ package cmd import ( "fmt" + "net/http" + + "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/router" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/router" - "net/http" ) var Server = cli.Command{ @@ -23,8 +26,13 @@ var Server = cli.Command{ } func doServer(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + beaver.Infof("Running gpm server at http://localhost:%s", ctx.String("port")) - if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.Init()); err != nil { + if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.New(cfg)); err != nil { return err } return nil diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..a3d6ef5 --- /dev/null +++ b/config/config.go @@ -0,0 +1,146 @@ +package config + +import ( + "encoding/json" + "fmt" + "os" + "path" + "strings" + + "github.com/AlecAivazis/survey/v2" + "github.com/pelletier/go-toml" + "go.jolheiser.com/beaver" +) + +var Version = "develop" + +type Config struct { + path string + GPMURL string `toml:"gpm-url" json:"gpm_url"` + Packages Packages `toml:"package" json:"packages"` +} + +type Package struct { + Name string `toml:"name" json:"name"` + Import string `toml:"import" json:"import"` +} + +type Packages []Package + +func Load() (*Config, error) { + home, err := os.UserHomeDir() + if err != nil { + return nil, fmt.Errorf("could not get user home dir: %v", err) + } + + home = path.Join(home, ".gpm") + homeEnv := os.Getenv("GPM_HOME") + if homeEnv != "" { + home = homeEnv + } + + configPath := path.Join(home, "gpm.toml") + configEnv := os.Getenv("GPM_CONFIG") + if configEnv != "" { + configPath = configEnv + } + + if _, err := os.Stat(configPath); os.IsNotExist(err) { + if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil { + return nil, fmt.Errorf("could not create gpm home: %v", err) + } + + if _, err := os.Create(configPath); err != nil { + return nil, fmt.Errorf("could not create gpm config: %v", err) + } + } + + var cfg Config + tree, err := toml.LoadFile(configPath) + if err != nil { + return nil, fmt.Errorf("could not decode gpm config: %v", err) + } + if err = tree.Unmarshal(&cfg); err != nil { + return nil, fmt.Errorf("could not unmarshal config: %v", err) + } + + dupe := make(map[string]bool) + for _, pkg := range cfg.Packages { + name := strings.ToLower(pkg.Name) + if ok := dupe[name]; ok { + return nil, fmt.Errorf("duplicate package for %s", pkg.Name) + } + dupe[name] = true + } + + cfg.path = configPath + return &cfg, nil +} + +func (c *Config) Save() error { + fi, err := os.Create(c.path) + if err != nil { + return err + } + defer fi.Close() + + if err := toml.NewEncoder(fi).Encode(c); err != nil { + return err + } + + return nil +} + +func (c *Config) Export() (string, error) { + data, err := json.Marshal(c.Packages) + return string(data), err +} + +func (p Packages) Slice() []string { + pkgs := make([]string, len(p)) + for idx, pkg := range p { + pkgs[idx] = fmt.Sprintf("%s (%s)", pkg.Name, pkg.Import) + } + return pkgs +} + +func (p Packages) Map() map[string]Package { + pkgs := make(map[string]Package) + for _, pkg := range p { + pkgs[pkg.Name] = pkg + } + return pkgs +} + +func (c *Config) AddPackages(force bool, pkgs ...Package) { + for _, pkg := range pkgs { + for idx, p := range c.Packages { + if strings.EqualFold(p.Name, pkg.Name) { + if force { + c.Packages[idx] = pkg + break + } + + forceQuestion := &survey.Confirm{ + Message: fmt.Sprintf("Package `%s` (%s) already exists. Overwrite with `%s`?", p.Name, p.Import, p.Import), + Default: false, + } + var forceAnswer bool + + if err := survey.AskOne(forceQuestion, &forceAnswer); err != nil { + beaver.Error(err) + break + } + + if !forceAnswer { + beaver.Errorf("leaving package `%s` as-is", pkg.Name) + break + } + + c.Packages[idx] = pkg + break + } + } + c.Packages = append(c.Packages, pkg) + } +} diff --git a/go.mod b/go.mod index b69925b..b3af50d 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,17 @@ module go.jolheiser.com/gpm -go 1.13 +go 1.15 require ( - github.com/AlecAivazis/survey/v2 v2.0.5 - github.com/BurntSushi/toml v0.3.1 - github.com/go-chi/chi v4.0.3+incompatible - github.com/mitchellh/go-homedir v1.1.0 - github.com/urfave/cli/v2 v2.1.1 - go.jolheiser.com/beaver v1.0.1 + github.com/AlecAivazis/survey/v2 v2.1.1 + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/go-chi/chi v4.1.2+incompatible + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/pelletier/go-toml v1.8.1 + github.com/urfave/cli/v2 v2.2.0 + go.jolheiser.com/beaver v1.0.2 + golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect + golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect + golang.org/x/text v0.3.3 // indirect ) diff --git a/go.sum b/go.sum index 333fa82..07a26ef 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,17 @@ -github.com/AlecAivazis/survey/v2 v2.0.5 h1:xpZp+Q55wi5C7Iaze+40onHnEkex1jSc34CltJjOoPM= -github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74= +github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI= +github.com/AlecAivazis/survey/v2 v2.1.1/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= -github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= +github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -18,12 +20,18 @@ github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -32,13 +40,15 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.jolheiser.com/beaver v1.0.1 h1:gt3aGEr5Bj4ZjDF1g8t8OYOGRCRXGaanGR9CmXUxez8= -go.jolheiser.com/beaver v1.0.1/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= +go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -47,7 +57,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf h1:Bg47KQy0JhTHuf4sLiQwTMKwUMfSDwgSGatrxGR7nLM= +golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 12e1501..4225082 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,20 @@ package main import ( + "os" + + "go.jolheiser.com/gpm/cmd" + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/cmd" - "go.jolheiser.com/gpm/modules/config" - "os" ) func main() { - - // config loads on init + cfg, err := config.Load() + if err != nil { + beaver.Fatal(err) + } app := cli.NewApp() app.Name = "gpm" @@ -25,11 +29,10 @@ func main() { &cmd.Export, &cmd.Config, &cmd.Server, + &cmd.Search, } - app.Flags = cmd.Flags - app.EnableBashCompletion = true - err := app.Run(os.Args) - if err != nil { + app.Flags = cmd.NewFlags(cfg) + if err := app.Run(os.Args); err != nil { beaver.Error(err) } } diff --git a/modules/config/config.go b/modules/config/config.go deleted file mode 100644 index 94246e5..0000000 --- a/modules/config/config.go +++ /dev/null @@ -1,132 +0,0 @@ -package config - -import ( - "encoding/json" - "fmt" - "github.com/AlecAivazis/survey/v2" - "github.com/BurntSushi/toml" - "github.com/mitchellh/go-homedir" - "go.jolheiser.com/beaver" - "os" - "path" - "strings" -) - -var ( - configPath string - cfg *Config - Version = "develop" - - // Config items - - GPMURL string - Packages []Package -) - -type Config struct { - GPMURL string `toml:"gpm-url" json:"gpm_url"` - Packages []Package `toml:"package" json:"packages"` -} - -type Package struct { - Name string `toml:"name" json:"name"` - Import string `toml:"import" json:"import"` -} - -// Load on init so that CLI contexts are correctly populated -func init() { - home, err := homedir.Dir() - if err != nil { - beaver.Fatalf("could not locate home directory: %v", err) - } - configPath = fmt.Sprintf("%s/.gpm/config.toml", home) - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil { - beaver.Fatalf("could not create gpm home: %v", err) - } - - if _, err := os.Create(configPath); err != nil { - beaver.Fatalf("could not create gpm config: %v", err) - } - } - - if _, err := toml.DecodeFile(configPath, &cfg); err != nil { - beaver.Fatalf("could not decode gpm config: %v", err) - } - - dupe := make(map[string]bool) - for _, pkg := range cfg.Packages { - name := strings.ToLower(pkg.Name) - if ok := dupe[name]; ok { - beaver.Fatalf("duplicate package for %s", pkg.Name) - } - dupe[name] = true - } - - GPMURL = cfg.GPMURL - Packages = cfg.Packages -} - -func Save() error { - cfg.GPMURL = GPMURL - cfg.Packages = Packages - - fi, err := os.Create(configPath) - if err != nil { - return err - } - defer fi.Close() - - if err := toml.NewEncoder(fi).Encode(cfg); err != nil { - return err - } - - return nil -} - -func Export() (string, error) { - data, err := json.Marshal(Packages) - return string(data), err -} - -func PackageMap() map[string]Package { - pkgs := make(map[string]Package) - for _, pkg := range Packages { - pkgs[pkg.Name] = pkg - } - return pkgs -} - -func AddPackages(force bool, pkgs ...Package) { - for _, pkg := range pkgs { - for idx, p := range Packages { - if strings.EqualFold(p.Name, pkg.Name) { - if force { - Packages[idx] = pkg - break - } - - forceQuestion := &survey.Confirm{ - Message: fmt.Sprintf("Package `%s` (%s) already exists. Overwrite with `%s`?", p.Name, p.Import, p.Import), - Default: false, - } - var forceAnswer bool - - if err := survey.AskOne(forceQuestion, &forceAnswer); err != nil { - beaver.Error(err) - break - } - - if !forceAnswer { - beaver.Errorf("leaving package `%s` as-is", pkg.Name) - break - } - - Packages[idx] = pkg - break - } - } - Packages = append(Packages, pkg) - } -} diff --git a/modules/router/router.go b/modules/router/router.go deleted file mode 100644 index bc6942b..0000000 --- a/modules/router/router.go +++ /dev/null @@ -1,70 +0,0 @@ -package router - -import ( - "encoding/json" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "net/http" - "time" -) - -var cache map[string]config.Package - -func Init() *chi.Mux { - r := chi.NewRouter() - r.Use(middleware.RedirectSlashes) - r.Use(middleware.Recoverer) - r.Use(middleware.Timeout(30 * time.Second)) - - r.Get("/", handleHome) - r.Get("/export", handleExport) - r.Get("/package/{name}", handlePackage) - - cache = config.PackageMap() - - return r -} - -func handleHome(res http.ResponseWriter, _ *http.Request) { - status, err := json.Marshal(map[string]interface{}{ - "version": config.Version, - "packages": len(config.Packages), - }) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) - _, _ = res.Write([]byte("{}")) - return - } - - _, _ = res.Write(status) -} - -func handleExport(res http.ResponseWriter, _ *http.Request) { - export, err := config.Export() - if err != nil { - beaver.Error(err) - return - } - - _, _ = res.Write([]byte(export)) -} - -func handlePackage(res http.ResponseWriter, req *http.Request) { - name := chi.URLParam(req, "name") - - if pkg, ok := cache[name]; ok { - data, err := json.Marshal(pkg) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) - _, _ = res.Write([]byte("{}")) - return - } - _, _ = res.Write(data) - return - } - - res.WriteHeader(http.StatusNotFound) - _, _ = res.Write([]byte("{}")) -} diff --git a/router/router.go b/router/router.go new file mode 100644 index 0000000..3697034 --- /dev/null +++ b/router/router.go @@ -0,0 +1,76 @@ +package router + +import ( + "encoding/json" + "net/http" + "time" + + "go.jolheiser.com/gpm/config" + + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "go.jolheiser.com/beaver" +) + +var cache map[string]config.Package + +func New(cfg *config.Config) *chi.Mux { + r := chi.NewRouter() + r.Use(middleware.RedirectSlashes) + r.Use(middleware.Recoverer) + r.Use(middleware.Timeout(30 * time.Second)) + + r.Get("/", handleHome(cfg)) + r.Get("/export", handleExport(cfg)) + r.Get("/package/{name}", handlePackage) + + cache = cfg.Packages.Map() + + return r +} + +func handleHome(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { + return func(res http.ResponseWriter, _ *http.Request) { + status, err := json.Marshal(map[string]interface{}{ + "version": config.Version, + "packages": len(cfg.Packages), + }) + if err != nil { + res.WriteHeader(http.StatusInternalServerError) + _, _ = res.Write([]byte("{}")) + return + } + + _, _ = res.Write(status) + } +} + +func handleExport(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { + return func(res http.ResponseWriter, _ *http.Request) { + export, err := cfg.Export() + if err != nil { + beaver.Error(err) + return + } + + _, _ = res.Write([]byte(export)) + } +} + +func handlePackage(res http.ResponseWriter, req *http.Request) { + name := chi.URLParam(req, "name") + + if pkg, ok := cache[name]; ok { + data, err := json.Marshal(pkg) + if err != nil { + res.WriteHeader(http.StatusInternalServerError) + _, _ = res.Write([]byte("{}")) + return + } + _, _ = res.Write(data) + return + } + + res.WriteHeader(http.StatusNotFound) + _, _ = res.Write([]byte("{}")) +} -- 2.41.0 From 0577fb4dbcf01d086521e7afce9c00935fcdbdfb Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Wed, 7 Oct 2020 04:11:36 +0000 Subject: [PATCH 2/9] Code improvements (#2) Code improvements Signed-off-by: jolheiser Co-authored-by: jolheiser Reviewed-on: https://gitea.com/jolheiser/gpm/pulls/2 --- Earthfile | 10 +++ Makefile | 76 +------------------- cmd/add.go | 16 +++-- cmd/cmd.go | 19 ++--- cmd/config.go | 16 +++-- cmd/export.go | 12 +++- cmd/get.go | 17 +++-- cmd/import.go | 23 +++--- cmd/list.go | 12 +++- cmd/remove.go | 21 ++++-- cmd/search.go | 89 ++++++++++++++++++++++++ cmd/server.go | 14 +++- config/config.go | 146 +++++++++++++++++++++++++++++++++++++++ go.mod | 19 +++-- go.sum | 37 +++++++--- main.go | 21 +++--- modules/config/config.go | 132 ----------------------------------- modules/router/router.go | 70 ------------------- router/router.go | 76 ++++++++++++++++++++ 19 files changed, 476 insertions(+), 350 deletions(-) create mode 100644 Earthfile create mode 100644 cmd/search.go create mode 100644 config/config.go delete mode 100644 modules/config/config.go delete mode 100644 modules/router/router.go create mode 100644 router/router.go diff --git a/Earthfile b/Earthfile new file mode 100644 index 0000000..6bd3e59 --- /dev/null +++ b/Earthfile @@ -0,0 +1,10 @@ +# To lint, install Earthly and run `earth +lint` +# This ensures the usage of the same version of golangci-lint + +FROM golangci/golangci-lint:v1.31 + +WORKDIR /gpm + +lint: + COPY . . + RUN golangci-lint run \ No newline at end of file diff --git a/Makefile b/Makefile index ba99758..7472947 100644 --- a/Makefile +++ b/Makefile @@ -1,32 +1,9 @@ -DIST := dist GO ?= go -SHASUM ?= shasum -a 256 - -ifneq ($(DRONE_TAG),) - VERSION ?= $(subst v,,$(DRONE_TAG)) - LONG_VERSION ?= $(VERSION) -else - ifneq ($(DRONE_BRANCH),) - VERSION ?= $(subst release/v,,$(DRONE_BRANCH)) - else - VERSION ?= master - endif - LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') -endif - -LDFLAGS := $(LDFLAGS) -X "go.jolheiser.com/gpm/modules/config.Version=$(LONG_VERSION)" +VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') .PHONY: build build: - $(GO) build -ldflags '-s -w $(LDFLAGS)' - -.PHONY: lint -lint: - @hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - export BINARY="golangci-lint"; \ - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.23.1; \ - fi - golangci-lint run --timeout 5m + $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/modules/config.Version=$(VERSION)"' .PHONY: fmt fmt: @@ -35,52 +12,3 @@ fmt: .PHONY: test test: $(GO) test -race ./... - -.PHONY: release -release: release-dirs check-xgo release-windows release-linux release-darwin release-copy release-compress release-check - -.PHONY: check-xgo -check-xgo: - @hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - $(GO) get -u src.techknowlogick.com/xgo; \ - fi - -.PHONY: release-dirs -release-dirs: - mkdir -p $(DIST)/binaries $(DIST)/release - -.PHONY: release-windows -release-windows: - xgo -dest $(DIST)/binaries -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-linux -release-linux: - xgo -dest $(DIST)/binaries -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-darwin -release-darwin: - xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gpm-$(VERSION) . -ifeq ($(CI),drone) - cp /build/* $(DIST)/binaries -endif - -.PHONY: release-copy -release-copy: - cd $(DIST); for file in `find /build -type f -name "*"`; do cp $${file} ./release/; done; - -.PHONY: release-check -release-check: - cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done; - -.PHONY: release-compress -release-compress: - @hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - $(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \ - fi - cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done; \ No newline at end of file diff --git a/cmd/add.go b/cmd/add.go index bece38d..2ee2e71 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -1,12 +1,14 @@ package cmd import ( + "regexp" + "strings" + + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "regexp" - "strings" ) var Add = cli.Command{ @@ -25,6 +27,10 @@ var Add = cli.Command{ var vPattern = regexp.MustCompile(`v\d+$`) func doAdd(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } goGetQuestion := &survey.Input{ Message: "Package go-get import", @@ -56,9 +62,9 @@ func doAdd(ctx *cli.Context) error { Name: nameAnswer, Import: goGetAnswer, } - config.AddPackages(ctx.Bool("force"), pkg) + cfg.AddPackages(ctx.Bool("force"), pkg) - if err := config.Save(); err != nil { + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/cmd.go b/cmd/cmd.go index 95c25c7..b574758 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,15 +1,18 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" - "go.jolheiser.com/gpm/modules/config" ) -var Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "url", - Aliases: []string{"u"}, - Usage: "gpm server to use", - Value: config.GPMURL, - }, +func NewFlags(cfg *config.Config) []cli.Flag { + return []cli.Flag{ + &cli.StringFlag{ + Name: "url", + Aliases: []string{"u"}, + Usage: "gpm server to use", + Value: cfg.GPMURL, + }, + } } diff --git a/cmd/config.go b/cmd/config.go index 513b32d..04be274 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -1,10 +1,11 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" ) var Config = cli.Command{ @@ -14,10 +15,15 @@ var Config = cli.Command{ Action: doConfig, } -func doConfig(ctx *cli.Context) error { +func doConfig(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + urlQuestion := &survey.Input{ Message: "gpm URL", - Default: config.GPMURL, + Default: cfg.GPMURL, } var urlAnswer string @@ -25,8 +31,8 @@ func doConfig(ctx *cli.Context) error { return err } - config.GPMURL = urlAnswer - if err := config.Save(); err != nil { + cfg.GPMURL = urlAnswer + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/export.go b/cmd/export.go index 2366c0b..c699a63 100644 --- a/cmd/export.go +++ b/cmd/export.go @@ -2,8 +2,10 @@ package cmd import ( "fmt" + + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" - "go.jolheiser.com/gpm/modules/config" ) var Export = cli.Command{ @@ -12,9 +14,13 @@ var Export = cli.Command{ Action: doExport, } -func doExport(ctx *cli.Context) error { +func doExport(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } - export, err := config.Export() + export, err := cfg.Export() if err != nil { return err } diff --git a/cmd/get.go b/cmd/get.go index f9a5373..e8d14a0 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -3,15 +3,17 @@ package cmd import ( "encoding/json" "fmt" - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" "io/ioutil" "net/http" "os" "os/exec" "strings" + + "go.jolheiser.com/gpm/config" + + "github.com/AlecAivazis/survey/v2" + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" ) var Get = cli.Command{ @@ -31,6 +33,11 @@ var Get = cli.Command{ } func doGet(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + pkgs := ctx.Args().Slice() if len(pkgs) == 0 { pkgsQuestion := &survey.Multiline{ @@ -45,7 +52,7 @@ func doGet(ctx *cli.Context) error { pkgs = strings.Split(pkgsAnswer, "\n") } - local := config.PackageMap() + local := cfg.Packages.Map() for _, pkg := range pkgs { var url string if u, ok := local[pkg]; ok && !ctx.Bool("ignore-local") { diff --git a/cmd/import.go b/cmd/import.go index 8cd3f52..264aa0f 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -3,12 +3,14 @@ package cmd import ( "encoding/json" "errors" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" "io/ioutil" "net/http" "strings" + + "go.jolheiser.com/gpm/config" + + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" ) var Import = cli.Command{ @@ -25,6 +27,11 @@ var Import = cli.Command{ } func doImport(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + if ctx.NArg() == 0 { return errors.New("must point to either a JSON file or gpm server export endpoint") } @@ -38,7 +45,6 @@ func doImport(ctx *cli.Context) error { } var data []byte - var err error if isJSON { data, err = ioutil.ReadFile(arg) if err != nil { @@ -55,16 +61,15 @@ func doImport(ctx *cli.Context) error { return err } defer resp.Body.Close() - } - var cfg config.Config - if err := json.Unmarshal(data, &cfg); err != nil { + var importPkgs []config.Package + if err := json.Unmarshal(data, &importPkgs); err != nil { return err } - config.AddPackages(ctx.Bool("force"), cfg.Packages...) + cfg.AddPackages(ctx.Bool("force"), importPkgs...) - if err := config.Save(); err != nil { + if err := cfg.Save(); err != nil { return err } diff --git a/cmd/list.go b/cmd/list.go index 87c1331..bdf825b 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1,9 +1,10 @@ package cmd import ( + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" ) var List = cli.Command{ @@ -13,8 +14,13 @@ var List = cli.Command{ Action: doList, } -func doList(ctx *cli.Context) error { - for _, pkg := range config.Packages { +func doList(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + + for _, pkg := range cfg.Packages { beaver.Infof("%s -> %s", pkg.Name, pkg.Import) } return nil diff --git a/cmd/remove.go b/cmd/remove.go index 79c18b8..ea38461 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -2,21 +2,28 @@ package cmd import ( "fmt" + "strings" + + "go.jolheiser.com/gpm/config" + "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "strings" ) var Remove = cli.Command{ Name: "remove", Aliases: []string{"rm"}, - Usage: "Remove a package", + Usage: "Remove package(s)", Action: doRemove, } -func doRemove(ctx *cli.Context) error { +func doRemove(_ *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + pkgQuestion := &survey.Input{ Message: "Package name", } @@ -26,7 +33,7 @@ func doRemove(ctx *cli.Context) error { return err } - for idx, p := range config.Packages { + for idx, p := range cfg.Packages { if strings.EqualFold(p.Name, pkgAnswer) { confirm := &survey.Confirm{ Message: fmt.Sprintf("Are you sure you want to remove %s (%s) ?", p.Name, p.Import), @@ -39,8 +46,8 @@ func doRemove(ctx *cli.Context) error { } if answer { - config.Packages = append(config.Packages[:idx], config.Packages[idx+1:]...) - if err := config.Save(); err != nil { + cfg.Packages = append(cfg.Packages[:idx], cfg.Packages[idx+1:]...) + if err := cfg.Save(); err != nil { return err } beaver.Infof("Removed `%s` from local gpm.", p.Name) diff --git a/cmd/search.go b/cmd/search.go new file mode 100644 index 0000000..796e121 --- /dev/null +++ b/cmd/search.go @@ -0,0 +1,89 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + "go.jolheiser.com/gpm/config" + + "github.com/AlecAivazis/survey/v2" + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" +) + +var Search = cli.Command{ + Name: "search", + Aliases: []string{"s"}, + Usage: "Search packages", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "local", + Usage: "Search locally", + }, + }, + Action: doSearch, +} + +func doSearch(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + + packageMap := cfg.Packages.Map() + packageSlice := cfg.Packages.Slice() + if !ctx.Bool("local") { + export, err := queryExport(ctx.String("url")) + if err != nil { + return err + } + packageMap = export.Map() + packageSlice = export.Slice() + } + + q := &survey.MultiSelect{ + Message: "Select packages", + Options: packageSlice, + } + + var a []string + if err := survey.AskOne(q, &a); err != nil { + return err + } + + for _, name := range a { + pkg, ok := packageMap[name] + if !ok { + beaver.Errorf("could not find package for `%s`", name) + continue + } + beaver.Infof("getting `%s`...", name) + if err := goGet(pkg.Import); err != nil { + beaver.Error(err) + } + } + + return nil +} + +func queryExport(server string) (config.Packages, error) { + resp, err := http.Get(fmt.Sprintf("%s/export", server)) + if err != nil { + return nil, err + } + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var importPkgs config.Packages + if err := json.Unmarshal(data, &importPkgs); err != nil { + return nil, err + } + + return importPkgs, nil +} diff --git a/cmd/server.go b/cmd/server.go index e24ffcf..f592e32 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -2,10 +2,13 @@ package cmd import ( "fmt" + "net/http" + + "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/router" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/router" - "net/http" ) var Server = cli.Command{ @@ -23,8 +26,13 @@ var Server = cli.Command{ } func doServer(ctx *cli.Context) error { + cfg, err := config.Load() + if err != nil { + return err + } + beaver.Infof("Running gpm server at http://localhost:%s", ctx.String("port")) - if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.Init()); err != nil { + if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.New(cfg)); err != nil { return err } return nil diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..a3d6ef5 --- /dev/null +++ b/config/config.go @@ -0,0 +1,146 @@ +package config + +import ( + "encoding/json" + "fmt" + "os" + "path" + "strings" + + "github.com/AlecAivazis/survey/v2" + "github.com/pelletier/go-toml" + "go.jolheiser.com/beaver" +) + +var Version = "develop" + +type Config struct { + path string + GPMURL string `toml:"gpm-url" json:"gpm_url"` + Packages Packages `toml:"package" json:"packages"` +} + +type Package struct { + Name string `toml:"name" json:"name"` + Import string `toml:"import" json:"import"` +} + +type Packages []Package + +func Load() (*Config, error) { + home, err := os.UserHomeDir() + if err != nil { + return nil, fmt.Errorf("could not get user home dir: %v", err) + } + + home = path.Join(home, ".gpm") + homeEnv := os.Getenv("GPM_HOME") + if homeEnv != "" { + home = homeEnv + } + + configPath := path.Join(home, "gpm.toml") + configEnv := os.Getenv("GPM_CONFIG") + if configEnv != "" { + configPath = configEnv + } + + if _, err := os.Stat(configPath); os.IsNotExist(err) { + if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil { + return nil, fmt.Errorf("could not create gpm home: %v", err) + } + + if _, err := os.Create(configPath); err != nil { + return nil, fmt.Errorf("could not create gpm config: %v", err) + } + } + + var cfg Config + tree, err := toml.LoadFile(configPath) + if err != nil { + return nil, fmt.Errorf("could not decode gpm config: %v", err) + } + if err = tree.Unmarshal(&cfg); err != nil { + return nil, fmt.Errorf("could not unmarshal config: %v", err) + } + + dupe := make(map[string]bool) + for _, pkg := range cfg.Packages { + name := strings.ToLower(pkg.Name) + if ok := dupe[name]; ok { + return nil, fmt.Errorf("duplicate package for %s", pkg.Name) + } + dupe[name] = true + } + + cfg.path = configPath + return &cfg, nil +} + +func (c *Config) Save() error { + fi, err := os.Create(c.path) + if err != nil { + return err + } + defer fi.Close() + + if err := toml.NewEncoder(fi).Encode(c); err != nil { + return err + } + + return nil +} + +func (c *Config) Export() (string, error) { + data, err := json.Marshal(c.Packages) + return string(data), err +} + +func (p Packages) Slice() []string { + pkgs := make([]string, len(p)) + for idx, pkg := range p { + pkgs[idx] = fmt.Sprintf("%s (%s)", pkg.Name, pkg.Import) + } + return pkgs +} + +func (p Packages) Map() map[string]Package { + pkgs := make(map[string]Package) + for _, pkg := range p { + pkgs[pkg.Name] = pkg + } + return pkgs +} + +func (c *Config) AddPackages(force bool, pkgs ...Package) { + for _, pkg := range pkgs { + for idx, p := range c.Packages { + if strings.EqualFold(p.Name, pkg.Name) { + if force { + c.Packages[idx] = pkg + break + } + + forceQuestion := &survey.Confirm{ + Message: fmt.Sprintf("Package `%s` (%s) already exists. Overwrite with `%s`?", p.Name, p.Import, p.Import), + Default: false, + } + var forceAnswer bool + + if err := survey.AskOne(forceQuestion, &forceAnswer); err != nil { + beaver.Error(err) + break + } + + if !forceAnswer { + beaver.Errorf("leaving package `%s` as-is", pkg.Name) + break + } + + c.Packages[idx] = pkg + break + } + } + c.Packages = append(c.Packages, pkg) + } +} diff --git a/go.mod b/go.mod index b69925b..b3af50d 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,17 @@ module go.jolheiser.com/gpm -go 1.13 +go 1.15 require ( - github.com/AlecAivazis/survey/v2 v2.0.5 - github.com/BurntSushi/toml v0.3.1 - github.com/go-chi/chi v4.0.3+incompatible - github.com/mitchellh/go-homedir v1.1.0 - github.com/urfave/cli/v2 v2.1.1 - go.jolheiser.com/beaver v1.0.1 + github.com/AlecAivazis/survey/v2 v2.1.1 + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/go-chi/chi v4.1.2+incompatible + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/pelletier/go-toml v1.8.1 + github.com/urfave/cli/v2 v2.2.0 + go.jolheiser.com/beaver v1.0.2 + golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect + golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect + golang.org/x/text v0.3.3 // indirect ) diff --git a/go.sum b/go.sum index 333fa82..07a26ef 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,17 @@ -github.com/AlecAivazis/survey/v2 v2.0.5 h1:xpZp+Q55wi5C7Iaze+40onHnEkex1jSc34CltJjOoPM= -github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74= +github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI= +github.com/AlecAivazis/survey/v2 v2.1.1/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY= -github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= +github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -18,12 +20,18 @@ github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= +github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -32,13 +40,15 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.jolheiser.com/beaver v1.0.1 h1:gt3aGEr5Bj4ZjDF1g8t8OYOGRCRXGaanGR9CmXUxez8= -go.jolheiser.com/beaver v1.0.1/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= +go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -47,7 +57,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf h1:Bg47KQy0JhTHuf4sLiQwTMKwUMfSDwgSGatrxGR7nLM= +golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index 12e1501..4225082 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,20 @@ package main import ( + "os" + + "go.jolheiser.com/gpm/cmd" + "go.jolheiser.com/gpm/config" + "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/cmd" - "go.jolheiser.com/gpm/modules/config" - "os" ) func main() { - - // config loads on init + cfg, err := config.Load() + if err != nil { + beaver.Fatal(err) + } app := cli.NewApp() app.Name = "gpm" @@ -25,11 +29,10 @@ func main() { &cmd.Export, &cmd.Config, &cmd.Server, + &cmd.Search, } - app.Flags = cmd.Flags - app.EnableBashCompletion = true - err := app.Run(os.Args) - if err != nil { + app.Flags = cmd.NewFlags(cfg) + if err := app.Run(os.Args); err != nil { beaver.Error(err) } } diff --git a/modules/config/config.go b/modules/config/config.go deleted file mode 100644 index 94246e5..0000000 --- a/modules/config/config.go +++ /dev/null @@ -1,132 +0,0 @@ -package config - -import ( - "encoding/json" - "fmt" - "github.com/AlecAivazis/survey/v2" - "github.com/BurntSushi/toml" - "github.com/mitchellh/go-homedir" - "go.jolheiser.com/beaver" - "os" - "path" - "strings" -) - -var ( - configPath string - cfg *Config - Version = "develop" - - // Config items - - GPMURL string - Packages []Package -) - -type Config struct { - GPMURL string `toml:"gpm-url" json:"gpm_url"` - Packages []Package `toml:"package" json:"packages"` -} - -type Package struct { - Name string `toml:"name" json:"name"` - Import string `toml:"import" json:"import"` -} - -// Load on init so that CLI contexts are correctly populated -func init() { - home, err := homedir.Dir() - if err != nil { - beaver.Fatalf("could not locate home directory: %v", err) - } - configPath = fmt.Sprintf("%s/.gpm/config.toml", home) - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil { - beaver.Fatalf("could not create gpm home: %v", err) - } - - if _, err := os.Create(configPath); err != nil { - beaver.Fatalf("could not create gpm config: %v", err) - } - } - - if _, err := toml.DecodeFile(configPath, &cfg); err != nil { - beaver.Fatalf("could not decode gpm config: %v", err) - } - - dupe := make(map[string]bool) - for _, pkg := range cfg.Packages { - name := strings.ToLower(pkg.Name) - if ok := dupe[name]; ok { - beaver.Fatalf("duplicate package for %s", pkg.Name) - } - dupe[name] = true - } - - GPMURL = cfg.GPMURL - Packages = cfg.Packages -} - -func Save() error { - cfg.GPMURL = GPMURL - cfg.Packages = Packages - - fi, err := os.Create(configPath) - if err != nil { - return err - } - defer fi.Close() - - if err := toml.NewEncoder(fi).Encode(cfg); err != nil { - return err - } - - return nil -} - -func Export() (string, error) { - data, err := json.Marshal(Packages) - return string(data), err -} - -func PackageMap() map[string]Package { - pkgs := make(map[string]Package) - for _, pkg := range Packages { - pkgs[pkg.Name] = pkg - } - return pkgs -} - -func AddPackages(force bool, pkgs ...Package) { - for _, pkg := range pkgs { - for idx, p := range Packages { - if strings.EqualFold(p.Name, pkg.Name) { - if force { - Packages[idx] = pkg - break - } - - forceQuestion := &survey.Confirm{ - Message: fmt.Sprintf("Package `%s` (%s) already exists. Overwrite with `%s`?", p.Name, p.Import, p.Import), - Default: false, - } - var forceAnswer bool - - if err := survey.AskOne(forceQuestion, &forceAnswer); err != nil { - beaver.Error(err) - break - } - - if !forceAnswer { - beaver.Errorf("leaving package `%s` as-is", pkg.Name) - break - } - - Packages[idx] = pkg - break - } - } - Packages = append(Packages, pkg) - } -} diff --git a/modules/router/router.go b/modules/router/router.go deleted file mode 100644 index bc6942b..0000000 --- a/modules/router/router.go +++ /dev/null @@ -1,70 +0,0 @@ -package router - -import ( - "encoding/json" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" - "go.jolheiser.com/beaver" - "go.jolheiser.com/gpm/modules/config" - "net/http" - "time" -) - -var cache map[string]config.Package - -func Init() *chi.Mux { - r := chi.NewRouter() - r.Use(middleware.RedirectSlashes) - r.Use(middleware.Recoverer) - r.Use(middleware.Timeout(30 * time.Second)) - - r.Get("/", handleHome) - r.Get("/export", handleExport) - r.Get("/package/{name}", handlePackage) - - cache = config.PackageMap() - - return r -} - -func handleHome(res http.ResponseWriter, _ *http.Request) { - status, err := json.Marshal(map[string]interface{}{ - "version": config.Version, - "packages": len(config.Packages), - }) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) - _, _ = res.Write([]byte("{}")) - return - } - - _, _ = res.Write(status) -} - -func handleExport(res http.ResponseWriter, _ *http.Request) { - export, err := config.Export() - if err != nil { - beaver.Error(err) - return - } - - _, _ = res.Write([]byte(export)) -} - -func handlePackage(res http.ResponseWriter, req *http.Request) { - name := chi.URLParam(req, "name") - - if pkg, ok := cache[name]; ok { - data, err := json.Marshal(pkg) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) - _, _ = res.Write([]byte("{}")) - return - } - _, _ = res.Write(data) - return - } - - res.WriteHeader(http.StatusNotFound) - _, _ = res.Write([]byte("{}")) -} diff --git a/router/router.go b/router/router.go new file mode 100644 index 0000000..3697034 --- /dev/null +++ b/router/router.go @@ -0,0 +1,76 @@ +package router + +import ( + "encoding/json" + "net/http" + "time" + + "go.jolheiser.com/gpm/config" + + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "go.jolheiser.com/beaver" +) + +var cache map[string]config.Package + +func New(cfg *config.Config) *chi.Mux { + r := chi.NewRouter() + r.Use(middleware.RedirectSlashes) + r.Use(middleware.Recoverer) + r.Use(middleware.Timeout(30 * time.Second)) + + r.Get("/", handleHome(cfg)) + r.Get("/export", handleExport(cfg)) + r.Get("/package/{name}", handlePackage) + + cache = cfg.Packages.Map() + + return r +} + +func handleHome(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { + return func(res http.ResponseWriter, _ *http.Request) { + status, err := json.Marshal(map[string]interface{}{ + "version": config.Version, + "packages": len(cfg.Packages), + }) + if err != nil { + res.WriteHeader(http.StatusInternalServerError) + _, _ = res.Write([]byte("{}")) + return + } + + _, _ = res.Write(status) + } +} + +func handleExport(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { + return func(res http.ResponseWriter, _ *http.Request) { + export, err := cfg.Export() + if err != nil { + beaver.Error(err) + return + } + + _, _ = res.Write([]byte(export)) + } +} + +func handlePackage(res http.ResponseWriter, req *http.Request) { + name := chi.URLParam(req, "name") + + if pkg, ok := cache[name]; ok { + data, err := json.Marshal(pkg) + if err != nil { + res.WriteHeader(http.StatusInternalServerError) + _, _ = res.Write([]byte("{}")) + return + } + _, _ = res.Write(data) + return + } + + res.WriteHeader(http.StatusNotFound) + _, _ = res.Write([]byte("{}")) +} -- 2.41.0 From a4cc44723fc8cb3586952231cf8b90a6abbcd4ec Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Wed, 7 Oct 2020 04:16:27 +0000 Subject: [PATCH 3/9] Fix version in Makefile (#4) Fix version in Makefile Signed-off-by: jolheiser Co-authored-by: jolheiser Reviewed-on: https://gitea.com/jolheiser/gpm/pulls/4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7472947..64cc957 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') .PHONY: build build: - $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/modules/config.Version=$(VERSION)"' + $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/config.Version=$(VERSION)"' .PHONY: fmt fmt: -- 2.41.0 From b23be07d5ea1415d98c984db1dedde576b2783a2 Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Wed, 17 Feb 2021 13:19:29 +0800 Subject: [PATCH 4/9] Update dependencies and deprecate ioutil (#5) Co-authored-by: jolheiser Reviewed-on: https://gitea.com/jolheiser/gpm/pulls/5 Co-authored-by: John Olheiser Co-committed-by: John Olheiser --- cmd/get.go | 4 ++-- cmd/import.go | 7 ++++--- cmd/search.go | 4 ++-- go.mod | 16 +++++++++------- go.sum | 48 ++++++++++++++++++++++-------------------------- 5 files changed, 39 insertions(+), 40 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index e8d14a0..95e9ee6 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -3,7 +3,7 @@ package cmd import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" "os/exec" @@ -91,7 +91,7 @@ func queryServer(server, name string) (string, error) { return "", fmt.Errorf("could not find server package for `%s`", name) } - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return "", err } diff --git a/cmd/import.go b/cmd/import.go index 264aa0f..5a40e9b 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -3,8 +3,9 @@ package cmd import ( "encoding/json" "errors" - "io/ioutil" + "io" "net/http" + "os" "strings" "go.jolheiser.com/gpm/config" @@ -46,7 +47,7 @@ func doImport(ctx *cli.Context) error { var data []byte if isJSON { - data, err = ioutil.ReadFile(arg) + data, err = os.ReadFile(arg) if err != nil { return err } @@ -56,7 +57,7 @@ func doImport(ctx *cli.Context) error { return err } - data, err = ioutil.ReadAll(resp.Body) + data, err = io.ReadAll(resp.Body) if err != nil { return err } diff --git a/cmd/search.go b/cmd/search.go index 796e121..b07d490 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -3,7 +3,7 @@ package cmd import ( "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "go.jolheiser.com/gpm/config" @@ -74,7 +74,7 @@ func queryExport(server string) (config.Packages, error) { return nil, err } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index b3af50d..48d4374 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,17 @@ module go.jolheiser.com/gpm go 1.15 require ( - github.com/AlecAivazis/survey/v2 v2.1.1 + github.com/AlecAivazis/survey/v2 v2.2.7 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/go-chi/chi v4.1.2+incompatible + github.com/go-chi/chi v1.5.2 github.com/mattn/go-colorable v0.1.8 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/pelletier/go-toml v1.8.1 - github.com/urfave/cli/v2 v2.2.0 - go.jolheiser.com/beaver v1.0.2 - golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect - golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect - golang.org/x/text v0.3.3 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/urfave/cli/v2 v2.3.0 + go.jolheiser.com/beaver v1.1.0 + golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect + golang.org/x/sys v0.0.0-20210216224549-f992740a1bac // indirect + golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect + golang.org/x/text v0.3.5 // indirect ) diff --git a/go.sum b/go.sum index 07a26ef..7b557ae 100644 --- a/go.sum +++ b/go.sum @@ -1,32 +1,27 @@ -github.com/AlecAivazis/survey/v2 v2.1.1 h1:LEMbHE0pLj75faaVEKClEX1TM4AJmmnOh9eimREzLWI= -github.com/AlecAivazis/survey/v2 v2.1.1/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/AlecAivazis/survey/v2 v2.2.7 h1:5NbxkF4RSKmpywYdcRgUmos1o+roJY8duCLZXbVjoig= +github.com/AlecAivazis/survey/v2 v2.2.7/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= -github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v1.5.2 h1:YcLIBANL4OTaAOcTdp//sskGa0yGACQMCtbnr7YEn0Q= +github.com/go-chi/chi v1.5.2/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -34,37 +29,38 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= -go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +go.jolheiser.com/beaver v1.1.0 h1:Igz73y+jJQoe8Uteewf14mOMnozGAo2vxjzyqU8v9kA= +go.jolheiser.com/beaver v1.1.0/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5 h1:8dUaAV7K4uHsF56JQWkprecIQKdPHtR9jCHF5nB8uzc= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf h1:Bg47KQy0JhTHuf4sLiQwTMKwUMfSDwgSGatrxGR7nLM= -golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210216224549-f992740a1bac h1:9glrpwtNjBYgRpb67AZJKHfzj1stG/8BL5H7In2oTC4= +golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -- 2.41.0 From ef0d29afa351fda4c70eafaad13db7150a91a19a Mon Sep 17 00:00:00 2001 From: John Olheiser Date: Sun, 28 Feb 2021 13:04:05 +0800 Subject: [PATCH 5/9] Rewrite (#7) Closes #6 This is, more or less, a fundamental rewrite of gpm. Co-authored-by: jolheiser Reviewed-on: https://gitea.com/jolheiser/gpm/pulls/7 Co-authored-by: John Olheiser Co-committed-by: John Olheiser --- Earthfile | 8 +- LICENSE | 19 ++++ Makefile | 35 ++++++- README.md | 15 +-- cmd/add.go | 51 ++++++---- cmd/cmd.go | 100 ++++++++++++++++-- cmd/config.go | 41 -------- cmd/export.go | 30 ------ cmd/flags/flags.go | 11 ++ cmd/get.go | 78 +++----------- cmd/import.go | 79 --------------- cmd/list.go | 18 ++-- cmd/remove.go | 65 ++++++------ cmd/search.go | 57 ++--------- cmd/server.go | 37 ++++--- cmd/update.go | 86 ++++++++++++++++ config/config.go | 146 --------------------------- database/database.go | 79 +++++++++++++++ database/database_test.go | 87 ++++++++++++++++ docker/Dockerfile | 12 +++ docker/docker-compose.yml | 9 ++ docs.go | 33 ++++++ go-gpm/client.go | 59 +++++++++++ go-gpm/go.mod | 3 + go-gpm/gpm_test.go | 207 ++++++++++++++++++++++++++++++++++++++ go-gpm/package.go | 124 +++++++++++++++++++++++ go.mod | 9 +- go.sum | 13 +-- main.go | 25 +---- router/router.go | 145 +++++++++++++++++++------- router/router_test.go | 166 ++++++++++++++++++++++++++++++ 31 files changed, 1284 insertions(+), 563 deletions(-) create mode 100644 LICENSE delete mode 100644 cmd/config.go delete mode 100644 cmd/export.go create mode 100644 cmd/flags/flags.go delete mode 100644 cmd/import.go create mode 100644 cmd/update.go delete mode 100644 config/config.go create mode 100644 database/database.go create mode 100644 database/database_test.go create mode 100644 docker/Dockerfile create mode 100644 docker/docker-compose.yml create mode 100644 docs.go create mode 100644 go-gpm/client.go create mode 100644 go-gpm/go.mod create mode 100644 go-gpm/gpm_test.go create mode 100644 go-gpm/package.go create mode 100644 router/router_test.go diff --git a/Earthfile b/Earthfile index 6bd3e59..3ad4128 100644 --- a/Earthfile +++ b/Earthfile @@ -1,10 +1,14 @@ # To lint, install Earthly and run `earth +lint` # This ensures the usage of the same version of golangci-lint -FROM golangci/golangci-lint:v1.31 +FROM golangci/golangci-lint:v1.37 WORKDIR /gpm -lint: +lint-cli: COPY . . + RUN golangci-lint run + +lint-lib: + COPY ./go-gpm . RUN golangci-lint run \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..433f7db --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021 John Olheiser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index 64cc957..5cdd052 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,39 @@ VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') .PHONY: build build: - $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/config.Version=$(VERSION)"' + $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/router.Version=$(VERSION)"' + +.PHONY: lint +lint: + earth +lint-cli + earth +lint-lib .PHONY: fmt -fmt: - $(GO) fmt ./... +fmt: fmt-cli fmt-lib .PHONY: test -test: +test: test-cli test-lib + +.PHONY: fmt-cli +fmt-cli: + $(GO) fmt ./... + +.PHONY: test-cli +test-cli: $(GO) test -race ./... + +.PHONY: fmt-lib +fmt-lib: + @cd go-gpm && $(GO) fmt ./... + +.PHONY: test-lib +test-lib: + @cd go-gpm && $(GO) test -race ./... + +.PHONY: docker-build +docker-build: + docker build -f docker/Dockerfile -t jolheiser/gpm . + +.PHONY: docker-push +docker-push: docker-build + docker push jolheiser/gpm \ No newline at end of file diff --git a/README.md b/README.md index 3b27702..926d6fc 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,21 @@ Using either a GPM server or local config, I can instead `gpm get cli` which fin * `remove` - Remove a local package * `list` - List local packages * `config` - Change local configuration -* `export` - Export local packages to JSON -* `import` - Import JSON to local packages. Either give a path to a `.json` file, or a URL to a GPM server export endpoint - * e.g. `https://gpm.jolheiser.com/export` * `get` - Get a list of packages - * e.g. `gpm get beaver survey toml homedir cli` to get all the modules needed for gpm itself (assuming the map resolves to the same packages) + * e.g. `gpm get beaver survey bbolt cli chi` to get all the modules needed for gpm itself (assuming the map resolves to the same packages) * `server` - Start a gpm server ### Server -If GPM doesn't find a package locally, it can call out to a configurable gpm server to find a package there instead. +gpm will call out to a gpm server to find a package. This makes it much simpler to have a central library of packages rather than exporting and importing between environments. Want to run your own server? It's very easy! This CLI comes packaged with the server inside, simply run `gpm server` to start up a GPM server. -Put it behind your favorite reverse proxy and it's ready to go! +Remember to set a `--token`! +Put it behind your favorite reverse proxy, and it's ready to go! + + +## License + +[MIT](LICENSE) \ No newline at end of file diff --git a/cmd/add.go b/cmd/add.go index 2ee2e71..8e6cd0a 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -1,10 +1,13 @@ package cmd import ( + "context" "regexp" "strings" - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" @@ -12,26 +15,30 @@ import ( ) var Add = cli.Command{ - Name: "add", - Usage: "Add a package", + Name: "add", + Aliases: []string{"a"}, + Usage: "Add a package", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "force", - Aliases: []string{"f"}, - Usage: "Overwrite existing package without prompt", + Name: "force", + Aliases: []string{"f"}, + Usage: "Overwrite existing package without prompt", + Destination: &flags.Force, + }, + &cli.BoolFlag{ + Name: "local", + Aliases: []string{"l"}, + Usage: "local mode", + Destination: &flags.Local, }, }, + Before: localOrToken, Action: doAdd, } var vPattern = regexp.MustCompile(`v\d+$`) -func doAdd(ctx *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err - } - +func doAdd(_ *cli.Context) error { goGetQuestion := &survey.Input{ Message: "Package go-get import", } @@ -58,16 +65,26 @@ func doAdd(ctx *cli.Context) error { return err } - pkg := config.Package{ + pkg := gpm.Package{ Name: nameAnswer, Import: goGetAnswer, } - cfg.AddPackages(ctx.Bool("force"), pkg) - if err := cfg.Save(); err != nil { - return err + if flags.Local { + db, err := database.Load(flags.Database) + if err != nil { + return err + } + if err := db.PutPackage(pkg); err != nil { + return err + } + } else { + client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + if err := client.Add(context.Background(), pkg); err != nil { + return err + } } - beaver.Infof("Added `%s` to local gpm.", nameAnswer) + beaver.Infof("Added %s", yellow.Format(nameAnswer)) return nil } diff --git a/cmd/cmd.go b/cmd/cmd.go index b574758..6c99021 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,18 +1,104 @@ package cmd import ( - "go.jolheiser.com/gpm/config" + "context" + "errors" + "os" + "path/filepath" + + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm/router" "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver/color" ) -func NewFlags(cfg *config.Config) []cli.Flag { - return []cli.Flag{ +var yellow = color.FgYellow + +func New() *cli.App { + app := cli.NewApp() + app.Name = "gpm" + app.Usage = "Go Package Manager" + app.Version = router.Version + app.Commands = []*cli.Command{ + &Add, + &Get, + &List, + &Remove, + &Search, + &Server, + &Update, + } + app.Flags = []cli.Flag{ &cli.StringFlag{ - Name: "url", - Aliases: []string{"u"}, - Usage: "gpm server to use", - Value: cfg.GPMURL, + Name: "server", + Aliases: []string{"s"}, + Usage: "gpm server to use", + Value: gpm.DefaultServer, + EnvVars: []string{"GPM_SERVER"}, + Destination: &flags.Server, + }, + &cli.StringFlag{ + Name: "token", + Aliases: []string{"t"}, + Usage: "gpm auth token to use", + DefaultText: "${GPM_TOKEN}", + EnvVars: []string{"GPM_TOKEN"}, + Destination: &flags.Token, + }, + &cli.StringFlag{ + Name: "database", + Aliases: []string{"d"}, + Usage: "path to gpm database for server", + Value: dbPath(), + DefaultText: "`${HOME}/gpm.db` or `${BINPATH}/gpm.db`", + EnvVars: []string{"GPM_DATABASE"}, + Destination: &flags.Database, }, } + return app +} + +func dbPath() string { + fn := "gpm.db" + home, err := os.UserHomeDir() + if err != nil { + bin, err := os.Executable() + if err != nil { + return fn + } + return filepath.Join(filepath.Dir(bin), fn) + } + return filepath.Join(home, fn) +} + +func localOrToken(_ *cli.Context) error { + if flags.Local && flags.Token == "" { + return errors.New("server interaaction requires --token") + } + return nil +} + +func listPackages() ([]gpm.Package, error) { + var pkgs []gpm.Package + if flags.Local { + db, err := database.Load(flags.Database) + if err != nil { + return pkgs, err + } + pkgs, err = db.Packages() + if err != nil { + return pkgs, err + } + } else { + client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + info, err := client.Info(context.Background()) + if err != nil { + return pkgs, err + } + pkgs = info.Packages + } + return pkgs, nil } diff --git a/cmd/config.go b/cmd/config.go deleted file mode 100644 index 04be274..0000000 --- a/cmd/config.go +++ /dev/null @@ -1,41 +0,0 @@ -package cmd - -import ( - "go.jolheiser.com/gpm/config" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Config = cli.Command{ - Name: "config", - Aliases: []string{"cfg"}, - Usage: "Configure local gpm", - Action: doConfig, -} - -func doConfig(_ *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err - } - - urlQuestion := &survey.Input{ - Message: "gpm URL", - Default: cfg.GPMURL, - } - var urlAnswer string - - if err := survey.AskOne(urlQuestion, &urlAnswer); err != nil { - return err - } - - cfg.GPMURL = urlAnswer - if err := cfg.Save(); err != nil { - return err - } - - beaver.Info("gpm URL saved!") - return nil -} diff --git a/cmd/export.go b/cmd/export.go deleted file mode 100644 index c699a63..0000000 --- a/cmd/export.go +++ /dev/null @@ -1,30 +0,0 @@ -package cmd - -import ( - "fmt" - - "go.jolheiser.com/gpm/config" - - "github.com/urfave/cli/v2" -) - -var Export = cli.Command{ - Name: "export", - Usage: "Export JSON for local packages", - Action: doExport, -} - -func doExport(_ *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err - } - - export, err := cfg.Export() - if err != nil { - return err - } - - fmt.Println(export) - return nil -} diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go new file mode 100644 index 0000000..e4a4f67 --- /dev/null +++ b/cmd/flags/flags.go @@ -0,0 +1,11 @@ +package flags + +var ( + Server string + Token string + Database string + + Local bool + Force bool + Port int +) diff --git a/cmd/get.go b/cmd/get.go index 95e9ee6..ba6e39e 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -1,15 +1,13 @@ package cmd import ( - "encoding/json" - "fmt" - "io" - "net/http" + "context" "os" "os/exec" "strings" - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/go-gpm" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" @@ -17,27 +15,13 @@ import ( ) var Get = cli.Command{ - Name: "get", - Usage: "Get package(s)", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "ignore-local", - Usage: "Ignore local packages", - }, - &cli.BoolFlag{ - Name: "offline", - Usage: "Offline mode, return error instead of querying server", - }, - }, - Action: doGet, + Name: "get", + Aliases: []string{"g"}, + Usage: "Get package(s)", + Action: doGet, } func doGet(ctx *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err - } - pkgs := ctx.Args().Slice() if len(pkgs) == 0 { pkgsQuestion := &survey.Multiline{ @@ -52,27 +36,16 @@ func doGet(ctx *cli.Context) error { pkgs = strings.Split(pkgsAnswer, "\n") } - local := cfg.Packages.Map() - for _, pkg := range pkgs { - var url string - if u, ok := local[pkg]; ok && !ctx.Bool("ignore-local") { - url = u.Import - } else if !ctx.Bool("offline") { - u, err := queryServer(ctx.String("url"), pkg) - if err != nil { - beaver.Error(err) - continue - } - url = u - } - - if url == "" { - beaver.Errorf("no package found for `%s`", pkg) + client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + for _, p := range pkgs { + pkg, err := client.Get(context.Background(), p) + if err != nil { + beaver.Error(err) continue } beaver.Infof("getting `%s`...", pkg) - if err := goGet(url); err != nil { + if err := goGet(pkg.Import); err != nil { beaver.Error(err) } } @@ -80,31 +53,6 @@ func doGet(ctx *cli.Context) error { return nil } -func queryServer(server, name string) (string, error) { - endpoint := fmt.Sprintf("%s/package/%s", server, name) - resp, err := http.Get(endpoint) - if err != nil { - return "", fmt.Errorf("could not query server at `%s`", endpoint) - } - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("could not find server package for `%s`", name) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - defer resp.Body.Close() - - var pkg config.Package - if err := json.Unmarshal(body, &pkg); err != nil { - return "", err - } - - return pkg.Import, nil -} - func goGet(url string) error { cmd := exec.Command("go", "get", url) cmd.Stdout = os.Stdout diff --git a/cmd/import.go b/cmd/import.go deleted file mode 100644 index 5a40e9b..0000000 --- a/cmd/import.go +++ /dev/null @@ -1,79 +0,0 @@ -package cmd - -import ( - "encoding/json" - "errors" - "io" - "net/http" - "os" - "strings" - - "go.jolheiser.com/gpm/config" - - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Import = cli.Command{ - Name: "import", - Usage: "Import JSON for local packages", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "force", - Aliases: []string{"f"}, - Usage: "Overwrite any existing packages without prompt", - }, - }, - Action: doImport, -} - -func doImport(ctx *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err - } - - if ctx.NArg() == 0 { - return errors.New("must point to either a JSON file or gpm server export endpoint") - } - - arg := ctx.Args().First() - isJSON := strings.HasSuffix(arg, ".json") - isHTTP := strings.HasPrefix(arg, "http") - - if !isJSON && !isHTTP { - return errors.New("must point to either a JSON file or gpm server export endpoint") - } - - var data []byte - if isJSON { - data, err = os.ReadFile(arg) - if err != nil { - return err - } - } else if isHTTP { - resp, err := http.Get(arg) - if err != nil { - return err - } - - data, err = io.ReadAll(resp.Body) - if err != nil { - return err - } - defer resp.Body.Close() - } - - var importPkgs []config.Package - if err := json.Unmarshal(data, &importPkgs); err != nil { - return err - } - cfg.AddPackages(ctx.Bool("force"), importPkgs...) - - if err := cfg.Save(); err != nil { - return err - } - - beaver.Info("Import complete") - return nil -} diff --git a/cmd/list.go b/cmd/list.go index bdf825b..9d53d85 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1,27 +1,29 @@ package cmd import ( - "go.jolheiser.com/gpm/config" + "fmt" + "os" + "text/tabwriter" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var List = cli.Command{ Name: "list", - Aliases: []string{"l"}, + Aliases: []string{"ls", "l"}, Usage: "List local packages", Action: doList, } func doList(_ *cli.Context) error { - cfg, err := config.Load() + pkgs, err := listPackages() if err != nil { return err } - - for _, pkg := range cfg.Packages { - beaver.Infof("%s -> %s", pkg.Name, pkg.Import) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) + for _, pkg := range pkgs { + s := fmt.Sprintf("%s\t%s\n", pkg.Name, pkg.Import) + _, _ = w.Write([]byte(s)) } - return nil + return w.Flush() } diff --git a/cmd/remove.go b/cmd/remove.go index ea38461..ad15807 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -1,10 +1,11 @@ package cmd import ( - "fmt" - "strings" + "context" - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" @@ -15,49 +16,53 @@ var Remove = cli.Command{ Name: "remove", Aliases: []string{"rm"}, Usage: "Remove package(s)", + Before: localOrToken, Action: doRemove, } func doRemove(_ *cli.Context) error { - cfg, err := config.Load() + pkgs, err := listPackages() if err != nil { return err } - pkgQuestion := &survey.Input{ - Message: "Package name", + pkgSlice := make([]string, len(pkgs)) + pkgMap := make(map[string]gpm.Package) + for idx, pkg := range pkgs { + pkgSlice[idx] = pkg.Name + pkgMap[pkg.Name] = pkg } - var pkgAnswer string - if err := survey.AskOne(pkgQuestion, &pkgAnswer); err != nil { + pkgQuestion := &survey.Select{ + Message: "Select package to remove", + Options: pkgSlice, + } + + var pkgName string + if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { return err } - for idx, p := range cfg.Packages { - if strings.EqualFold(p.Name, pkgAnswer) { - confirm := &survey.Confirm{ - Message: fmt.Sprintf("Are you sure you want to remove %s (%s) ?", p.Name, p.Import), - Default: false, - } - var answer bool + pkg := gpm.Package{ + Name: pkgName, + Import: pkgMap[pkgName].Import, + } - if err := survey.AskOne(confirm, &answer); err != nil { - return err - } - - if answer { - cfg.Packages = append(cfg.Packages[:idx], cfg.Packages[idx+1:]...) - if err := cfg.Save(); err != nil { - return err - } - beaver.Infof("Removed `%s` from local gpm.", p.Name) - break - } - - beaver.Infof("Did not remove `%s` from local gpm.", p.Name) - break + if flags.Local { + db, err := database.Load(flags.Database) + if err != nil { + return err + } + if err := db.RemovePackage(pkg.Name); err != nil { + return err + } + } else { + client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + if err := client.Remove(context.Background(), pkg); err != nil { + return err } } + beaver.Infof("Removed %s", yellow.Format(pkgName)) return nil } diff --git a/cmd/search.go b/cmd/search.go index b07d490..7aef35d 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -1,12 +1,7 @@ package cmd import ( - "encoding/json" - "fmt" - "io" - "net/http" - - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/go-gpm" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" @@ -17,35 +12,25 @@ var Search = cli.Command{ Name: "search", Aliases: []string{"s"}, Usage: "Search packages", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "local", - Usage: "Search locally", - }, - }, - Action: doSearch, + Action: doSearch, } -func doSearch(ctx *cli.Context) error { - cfg, err := config.Load() +func doSearch(_ *cli.Context) error { + pkgs, err := listPackages() if err != nil { return err } - packageMap := cfg.Packages.Map() - packageSlice := cfg.Packages.Slice() - if !ctx.Bool("local") { - export, err := queryExport(ctx.String("url")) - if err != nil { - return err - } - packageMap = export.Map() - packageSlice = export.Slice() + pkgSlice := make([]string, len(pkgs)) + pkgMap := make(map[string]gpm.Package) + for idx, pkg := range pkgs { + pkgSlice[idx] = pkg.Name + pkgMap[pkg.Name] = pkg } q := &survey.MultiSelect{ Message: "Select packages", - Options: packageSlice, + Options: pkgSlice, } var a []string @@ -54,7 +39,7 @@ func doSearch(ctx *cli.Context) error { } for _, name := range a { - pkg, ok := packageMap[name] + pkg, ok := pkgMap[name] if !ok { beaver.Errorf("could not find package for `%s`", name) continue @@ -67,23 +52,3 @@ func doSearch(ctx *cli.Context) error { return nil } - -func queryExport(server string) (config.Packages, error) { - resp, err := http.Get(fmt.Sprintf("%s/export", server)) - if err != nil { - return nil, err - } - - data, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var importPkgs config.Packages - if err := json.Unmarshal(data, &importPkgs); err != nil { - return nil, err - } - - return importPkgs, nil -} diff --git a/cmd/server.go b/cmd/server.go index f592e32..9931fbc 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,10 +1,12 @@ package cmd import ( + "errors" "fmt" "net/http" - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/database" "go.jolheiser.com/gpm/router" "github.com/urfave/cli/v2" @@ -12,27 +14,34 @@ import ( ) var Server = cli.Command{ - Name: "server", - Usage: "Start the gpm server", + Name: "server", + Aliases: []string{"web"}, + Usage: "Start the gpm server", Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "port", - Aliases: []string{"p"}, - Usage: "Port to run the gpm server on", - Value: "3333", + &cli.IntFlag{ + Name: "port", + Aliases: []string{"p"}, + Usage: "Port to run the gpm server on", + Value: 3333, + EnvVars: []string{"GPM_PORT"}, + Destination: &flags.Port, }, }, Action: doServer, } -func doServer(ctx *cli.Context) error { - cfg, err := config.Load() - if err != nil { - return err +func doServer(_ *cli.Context) error { + if flags.Token == "" { + return errors.New("gpm server requires --token") } - beaver.Infof("Running gpm server at http://localhost:%s", ctx.String("port")) - if err := http.ListenAndServe(fmt.Sprintf(":%s", ctx.String("port")), router.New(cfg)); err != nil { + db, err := database.Load(flags.Database) + if err != nil { + beaver.Fatalf("could not load database at %s: %v", flags.Database, err) + } + + beaver.Infof("Running gpm server at http://localhost:%d", flags.Port) + if err := http.ListenAndServe(fmt.Sprintf(":%d", flags.Port), router.New(flags.Token, db)); err != nil { return err } return nil diff --git a/cmd/update.go b/cmd/update.go new file mode 100644 index 0000000..690e235 --- /dev/null +++ b/cmd/update.go @@ -0,0 +1,86 @@ +package cmd + +import ( + "context" + + "go.jolheiser.com/gpm/cmd/flags" + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" + + "github.com/AlecAivazis/survey/v2" + "github.com/urfave/cli/v2" + "go.jolheiser.com/beaver" +) + +var Update = cli.Command{ + Name: "update", + Aliases: []string{"u"}, + Usage: "Update a package", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "local", + Aliases: []string{"l"}, + Usage: "local mode", + Destination: &flags.Local, + }, + }, + Before: localOrToken, + Action: doUpdate, +} + +func doUpdate(_ *cli.Context) error { + pkgs, err := listPackages() + if err != nil { + return err + } + + pkgSlice := make([]string, len(pkgs)) + pkgMap := make(map[string]gpm.Package) + for idx, pkg := range pkgs { + pkgSlice[idx] = pkg.Name + pkgMap[pkg.Name] = pkg + } + + pkgQuestion := &survey.Select{ + Message: "Select package to update", + Options: pkgSlice, + } + + var pkgName string + if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { + return err + } + + importQuestion := &survey.Input{ + Message: "New import path", + Default: pkgMap[pkgName].Import, + } + + var importPath string + if err := survey.AskOne(importQuestion, &importPath); err != nil { + return err + } + + pkg := gpm.Package{ + Name: pkgName, + Import: importPath, + } + + if flags.Local { + db, err := database.Load(flags.Database) + if err != nil { + return err + } + if err := db.PutPackage(pkg); err != nil { + return err + } + } else { + client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + if err := client.Update(context.Background(), pkg); err != nil { + return err + } + } + + beaver.Infof("Updated %s", yellow.Format(pkgName)) + return nil +} diff --git a/config/config.go b/config/config.go deleted file mode 100644 index a3d6ef5..0000000 --- a/config/config.go +++ /dev/null @@ -1,146 +0,0 @@ -package config - -import ( - "encoding/json" - "fmt" - "os" - "path" - "strings" - - "github.com/AlecAivazis/survey/v2" - "github.com/pelletier/go-toml" - "go.jolheiser.com/beaver" -) - -var Version = "develop" - -type Config struct { - path string - GPMURL string `toml:"gpm-url" json:"gpm_url"` - Packages Packages `toml:"package" json:"packages"` -} - -type Package struct { - Name string `toml:"name" json:"name"` - Import string `toml:"import" json:"import"` -} - -type Packages []Package - -func Load() (*Config, error) { - home, err := os.UserHomeDir() - if err != nil { - return nil, fmt.Errorf("could not get user home dir: %v", err) - } - - home = path.Join(home, ".gpm") - homeEnv := os.Getenv("GPM_HOME") - if homeEnv != "" { - home = homeEnv - } - - configPath := path.Join(home, "gpm.toml") - configEnv := os.Getenv("GPM_CONFIG") - if configEnv != "" { - configPath = configEnv - } - - if _, err := os.Stat(configPath); os.IsNotExist(err) { - if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil { - return nil, fmt.Errorf("could not create gpm home: %v", err) - } - - if _, err := os.Create(configPath); err != nil { - return nil, fmt.Errorf("could not create gpm config: %v", err) - } - } - - var cfg Config - tree, err := toml.LoadFile(configPath) - if err != nil { - return nil, fmt.Errorf("could not decode gpm config: %v", err) - } - if err = tree.Unmarshal(&cfg); err != nil { - return nil, fmt.Errorf("could not unmarshal config: %v", err) - } - - dupe := make(map[string]bool) - for _, pkg := range cfg.Packages { - name := strings.ToLower(pkg.Name) - if ok := dupe[name]; ok { - return nil, fmt.Errorf("duplicate package for %s", pkg.Name) - } - dupe[name] = true - } - - cfg.path = configPath - return &cfg, nil -} - -func (c *Config) Save() error { - fi, err := os.Create(c.path) - if err != nil { - return err - } - defer fi.Close() - - if err := toml.NewEncoder(fi).Encode(c); err != nil { - return err - } - - return nil -} - -func (c *Config) Export() (string, error) { - data, err := json.Marshal(c.Packages) - return string(data), err -} - -func (p Packages) Slice() []string { - pkgs := make([]string, len(p)) - for idx, pkg := range p { - pkgs[idx] = fmt.Sprintf("%s (%s)", pkg.Name, pkg.Import) - } - return pkgs -} - -func (p Packages) Map() map[string]Package { - pkgs := make(map[string]Package) - for _, pkg := range p { - pkgs[pkg.Name] = pkg - } - return pkgs -} - -func (c *Config) AddPackages(force bool, pkgs ...Package) { - for _, pkg := range pkgs { - for idx, p := range c.Packages { - if strings.EqualFold(p.Name, pkg.Name) { - if force { - c.Packages[idx] = pkg - break - } - - forceQuestion := &survey.Confirm{ - Message: fmt.Sprintf("Package `%s` (%s) already exists. Overwrite with `%s`?", p.Name, p.Import, p.Import), - Default: false, - } - var forceAnswer bool - - if err := survey.AskOne(forceQuestion, &forceAnswer); err != nil { - beaver.Error(err) - break - } - - if !forceAnswer { - beaver.Errorf("leaving package `%s` as-is", pkg.Name) - break - } - - c.Packages[idx] = pkg - break - } - } - c.Packages = append(c.Packages, pkg) - } -} diff --git a/database/database.go b/database/database.go new file mode 100644 index 0000000..d7827d0 --- /dev/null +++ b/database/database.go @@ -0,0 +1,79 @@ +package database + +import ( + "bytes" + "encoding/json" + "os" + "path/filepath" + + "go.jolheiser.com/gpm/go-gpm" + + "go.etcd.io/bbolt" +) + +var packageBucket = []byte("packages") + +type Database struct { + db *bbolt.DB +} + +func Load(dbPath string) (*Database, error) { + if err := os.MkdirAll(filepath.Dir(dbPath), os.ModePerm); err != nil { + return nil, err + } + db, err := bbolt.Open(dbPath, os.ModePerm, nil) + if err != nil { + return nil, err + } + return &Database{ + db: db, + }, db.Update(func(tx *bbolt.Tx) error { + _, err := tx.CreateBucketIfNotExists(packageBucket) + return err + }) +} + +func (d *Database) Package(name string) (gpm.Package, error) { + var pkg gpm.Package + data, err := d.PackageJSON(name) + if err != nil { + return pkg, err + } + return pkg, json.NewDecoder(bytes.NewReader(data)).Decode(&pkg) +} + +func (d *Database) PackageJSON(name string) (pkg []byte, err error) { + return pkg, d.db.View(func(tx *bbolt.Tx) error { + pkg = tx.Bucket(packageBucket).Get([]byte(name)) + return nil + }) +} + +func (d *Database) Packages() (pkgs []gpm.Package, err error) { + return pkgs, d.db.View(func(tx *bbolt.Tx) error { + return tx.Bucket(packageBucket).ForEach(func(key, val []byte) error { + var pkg gpm.Package + if err := json.NewDecoder(bytes.NewReader(val)).Decode(&pkg); err != nil { + return err + } + pkgs = append(pkgs, pkg) + return nil + }) + }) +} + +func (d *Database) PutPackage(pkg gpm.Package) error { + return d.db.Update(func(tx *bbolt.Tx) error { + data, err := json.Marshal(pkg) + if err != nil { + return err + } + return tx.Bucket(packageBucket).Put([]byte(pkg.Name), data) + }) +} + +func (d *Database) RemovePackage(name string) error { + return d.db.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(packageBucket).Delete([]byte(name)) + }) +} diff --git a/database/database_test.go b/database/database_test.go new file mode 100644 index 0000000..b6e1f92 --- /dev/null +++ b/database/database_test.go @@ -0,0 +1,87 @@ +package database + +import ( + "os" + "path/filepath" + "testing" + + "go.jolheiser.com/gpm/go-gpm" +) + +var db *Database + +func TestMain(m *testing.M) { + tmp, err := os.MkdirTemp(os.TempDir(), "gpm") + if err != nil { + panic(err) + } + dbPath := filepath.Join(tmp, "gpm.db") + + db, err = Load(dbPath) + if err != nil { + panic(err) + } + + code := m.Run() + + // Cleanup + if err := os.RemoveAll(tmp); err != nil { + panic(err) + } + + os.Exit(code) +} + +func TestPackage(t *testing.T) { + + // Does not exist + _, err := db.Package("test") + if err == nil { + t.Log("test package should not exist") + t.FailNow() + } + + // Add + pkg := gpm.Package{ + Name: "test", + Import: "gitea.com/test/testing", + } + err = db.PutPackage(pkg) + if err != nil { + t.Logf("could not put test package: %v\n", err) + t.FailNow() + } + + // Update + pkg.Import = "gitea.com/testing/test" + err = db.PutPackage(pkg) + if err != nil { + t.Logf("could not put test package: %v\n", err) + t.FailNow() + } + + // Check + p, err := db.Package("test") + if err != nil { + t.Logf("should find test package: %v\n", err) + t.FailNow() + } + if p.Import != pkg.Import { + t.Logf("test package did not match update:\n\texpected: %s\n\t got: %s\n", pkg.Import, p.Import) + t.FailNow() + } + + // Remove + err = db.RemovePackage("test") + if err != nil { + t.Log("could not remove test package") + t.FailNow() + } + + // Check + _, err = db.Package("test") + if err == nil { + t.Log("test package should not exist after being removed") + t.FailNow() + } +} diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..5431a7b --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.16-alpine as builder +RUN apk --no-cache add build-base git +COPY . /app +WORKDIR /app +RUN make build + +FROM alpine:latest +LABEL maintainer="john.olheiser@gmail.com" +COPY --from=builder /app/gpm gpm +EXPOSE 3333 +ENV GPM_TOKEN="" +ENTRYPOINT exec gpm --token $GPM_TOKEN server \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..394e21f --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,9 @@ +version: "2" +services: + vanity: + image: jolheiser/gpm:latest + environment: + - GPM_TOKEN= + restart: always + ports: + - "80:3333" \ No newline at end of file diff --git a/docs.go b/docs.go new file mode 100644 index 0000000..a2a6fd8 --- /dev/null +++ b/docs.go @@ -0,0 +1,33 @@ +//+build docs + +package main + +import ( + "os" + "strings" + + "go.jolheiser.com/gpm/cmd" +) + +func main() { + app := cmd.New() + + md, err := app.ToMarkdown() + if err != nil { + panic(err) + } + + // FIXME Why is this not fixed yet?? + md = md[strings.Index(md, "#"):] + + fi, err := os.Create("DOCS.md") + if err != nil { + panic(err) + } + if _, err := fi.WriteString(md); err != nil { + panic(err) + } + if err := fi.Close(); err != nil { + panic(err) + } +} diff --git a/go-gpm/client.go b/go-gpm/client.go new file mode 100644 index 0000000..bfcc334 --- /dev/null +++ b/go-gpm/client.go @@ -0,0 +1,59 @@ +package gpm + +import ( + "context" + "io" + "net/http" + "strings" +) + +const ( + DefaultServer = "https://gpm.jolheiser.com" + TokenHeader = "X-GPM-Token" +) + +// Client is a gpm client +type Client struct { + token string + server string + http *http.Client +} + +// New returns a new Client +func New(token string, opts ...ClientOption) *Client { + c := &Client{ + token: token, + server: DefaultServer, + http: http.DefaultClient, + } + for _, opt := range opts { + opt(c) + } + return c +} + +// ClientOption is an option for a Client +type ClientOption func(*Client) + +// WithHTTP sets the http.Client for a Client +func WithHTTP(client *http.Client) ClientOption { + return func(c *Client) { + c.http = client + } +} + +// WithServer sets the gpm server for a Client +func WithServer(server string) ClientOption { + return func(c *Client) { + c.server = strings.TrimSuffix(server, "/") + } +} + +func (c *Client) newRequest(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) { + req, err := http.NewRequestWithContext(ctx, method, url, body) + if err != nil { + return nil, err + } + req.Header.Set(TokenHeader, c.token) + return req, nil +} diff --git a/go-gpm/go.mod b/go-gpm/go.mod new file mode 100644 index 0000000..a2558d4 --- /dev/null +++ b/go-gpm/go.mod @@ -0,0 +1,3 @@ +module go.jolheiser.com/gpm/go-gpm + +go 1.16 diff --git a/go-gpm/gpm_test.go b/go-gpm/gpm_test.go new file mode 100644 index 0000000..925a0bc --- /dev/null +++ b/go-gpm/gpm_test.go @@ -0,0 +1,207 @@ +package gpm + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" +) + +var ( + server *httptest.Server + token = "TestingLibrary" + version = "GPMTest" + + packages = []Package{ + { + Name: "test1", + Import: "gitea.com/test/testing", + }, + } +) + +func TestMain(m *testing.M) { + server = httptest.NewServer(http.HandlerFunc(testServer)) + os.Exit(m.Run()) +} + +func TestClient(t *testing.T) { + ctx := context.Background() + client := New("", WithServer(server.URL)) + + // Info + checkInfo(t, client, 1) + + pkg1 := Package{ + Name: "test1", + Import: "gitea.com/test/testing", + } + pkg2 := Package{ + Name: "test2", + Import: "gitea.com/testing/test", + } + + // Add (without token) + if err := client.Add(ctx, pkg1); err == nil { + t.Log("adding without token should fail") + t.Fail() + } + + // Add (with token) + client = New(token, WithServer(server.URL)) + checkAdd(t, client, pkg1, pkg2) + + // Info (after second package) + checkInfo(t, client, 2) + + // Check package + checkGet(t, client, pkg2) + + // Update package + checkUpdate(t, client, pkg1) + + // Remove + checkRemove(t, client, pkg1) + + // Info (final) + checkInfo(t, client, 1) +} + +func checkInfo(t *testing.T, client *Client, numPackages int) { + info, err := client.Info(context.Background()) + if err != nil { + t.Logf("info should not return error: %v\n", err) + t.Fail() + } + if info.Version != version || info.NumPackages != numPackages { + t.Log("info did not match expected") + t.Fail() + } +} + +func checkGet(t *testing.T, client *Client, pkg Package) { + ctx := context.Background() + _, err := client.Get(ctx, "test3") + if err == nil { + t.Log("should not be able to get invalid package") + t.Fail() + } + + // Check valid package + p, err := client.Get(ctx, "test2") + if err != nil { + t.Logf("should not be able to get invalid package: %v\n", err) + t.Fail() + } + if p != pkg { + t.Log("valid package should match pkg") + t.Fail() + } +} + +func checkAdd(t *testing.T, client *Client, pkg1, pkg2 Package) { + ctx := context.Background() + if err := client.Add(ctx, pkg2); err != nil { + t.Logf("pkg2 should be added: %v\n", err) + t.Fail() + } + // Duplicate package + if err := client.Add(ctx, pkg1); err == nil { + t.Log("pkg1 should already exist") + t.Fail() + } +} + +func checkUpdate(t *testing.T, client *Client, pkg Package) { + ctx := context.Background() + // Update invalid package + if err := client.Update(ctx, Package{Name: "test4", Import: "gitea.com/invalid"}); err == nil { + t.Log("should not be able to update invalid package") + t.Fail() + } + + // Update valid package + pkg.Import = "gitea.com/tester/testing" + if err := client.Update(ctx, pkg); err != nil { + t.Logf("should be able to update valid package: %v\n", err) + t.Fail() + } +} + +func checkRemove(t *testing.T, client *Client, pkg Package) { + ctx := context.Background() + if err := client.Remove(ctx, pkg); err != nil { + t.Logf("should be able to remove package: %v\n", err) + t.Fail() + } + + // Remove (idempotent) + if err := client.Remove(ctx, pkg); err != nil { + t.Logf("should be able to remove package idempotently: %v\n", err) + t.Fail() + } +} + +func testServer(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/": + switch r.Method { + case http.MethodGet: + resp := Info{ + Version: version, + NumPackages: len(packages), + Packages: packages, + } + _ = json.NewEncoder(w).Encode(resp) + case http.MethodPost, http.MethodPatch, http.MethodDelete: + if r.Header.Get(TokenHeader) != token { + w.WriteHeader(http.StatusUnauthorized) + return + } + var pkg Package + if err := json.NewDecoder(r.Body).Decode(&pkg); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + switch r.Method { + case http.MethodPost: + for _, p := range packages { + if p.Name == pkg.Name { + w.WriteHeader(http.StatusConflict) + return + } + } + packages = append(packages, pkg) + w.WriteHeader(http.StatusCreated) + case http.MethodPatch: + for idx, p := range packages { + if p.Name == pkg.Name { + packages[idx] = pkg + return + } + } + w.WriteHeader(http.StatusNotFound) + case http.MethodDelete: + for idx, p := range packages { + if p.Name == pkg.Name { + packages = append(packages[:idx], packages[idx+1:]...) + } + } + } + return + } + return + default: + name := strings.TrimPrefix(r.URL.Path, "/") + for _, pkg := range packages { + if pkg.Name == name { + _ = json.NewEncoder(w).Encode(pkg) + return + } + } + } + w.WriteHeader(http.StatusNotImplemented) +} diff --git a/go-gpm/package.go b/go-gpm/package.go new file mode 100644 index 0000000..d93df2e --- /dev/null +++ b/go-gpm/package.go @@ -0,0 +1,124 @@ +package gpm + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" +) + +// Package is a gpm package +type Package struct { + Name string `json:"name"` + Import string `json:"import"` +} + +// Info is gpm information, such as version and list of packages +type Info struct { + Version string `json:"version"` + NumPackages int `json:"num_packages"` + Packages []Package `json:"packages"` +} + +// Info gets Info from a gpm server +func (c *Client) Info(ctx context.Context) (Info, error) { + var info Info + resp, err := c.crud(ctx, Package{}, http.MethodGet) + if err != nil { + return info, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return info, fmt.Errorf("could not get info: %s", resp.Status) + } + + if err := json.NewDecoder(resp.Body).Decode(&info); err != nil { + return info, err + } + + return info, nil +} + +// Add adds a new Package to a gpm server +func (c *Client) Add(ctx context.Context, pkg Package) error { + resp, err := c.crud(ctx, pkg, http.MethodPost) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusCreated { + return fmt.Errorf("could not add package: %s", resp.Status) + } + return nil +} + +// Update updates a Package on a gpm server +func (c *Client) Update(ctx context.Context, pkg Package) error { + resp, err := c.crud(ctx, pkg, http.MethodPatch) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("could not update package: %s", resp.Status) + } + + return nil +} + +// Remove removes a Package from a gpm server +func (c *Client) Remove(ctx context.Context, pkg Package) error { + resp, err := c.crud(ctx, pkg, http.MethodDelete) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("could not remove package: %s", resp.Status) + } + + return nil +} + +// Get gets a Package from a server +func (c *Client) Get(ctx context.Context, name string) (Package, error) { + var pkg Package + uri := fmt.Sprintf("%s/%s", c.server, name) + + req, err := c.newRequest(ctx, http.MethodGet, uri, nil) + if err != nil { + return pkg, err + } + + resp, err := c.http.Do(req) + if err != nil { + return pkg, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return pkg, fmt.Errorf("package not found for %s", name) + } + + if err := json.NewDecoder(resp.Body).Decode(&pkg); err != nil { + return pkg, err + } + + return pkg, nil +} + +func (c *Client) crud(ctx context.Context, pkg Package, method string) (*http.Response, error) { + payload, err := json.Marshal(pkg) + if err != nil { + return nil, err + } + + req, err := c.newRequest(ctx, method, c.server, bytes.NewReader(payload)) + if err != nil { + return nil, err + } + + return c.http.Do(req) +} diff --git a/go.mod b/go.mod index 48d4374..0715a09 100644 --- a/go.mod +++ b/go.mod @@ -2,18 +2,21 @@ module go.jolheiser.com/gpm go 1.15 +replace go.jolheiser.com/gpm/go-gpm => ./go-gpm + require ( github.com/AlecAivazis/survey/v2 v2.2.7 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/go-chi/chi v1.5.2 github.com/mattn/go-colorable v0.1.8 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/pelletier/go-toml v1.8.1 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/urfave/cli/v2 v2.3.0 - go.jolheiser.com/beaver v1.1.0 + go.etcd.io/bbolt v1.3.5 + go.jolheiser.com/beaver v1.1.1 + go.jolheiser.com/gpm/go-gpm v0.0.0-00010101000000-000000000000 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect - golang.org/x/sys v0.0.0-20210216224549-f992740a1bac // indirect + golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect golang.org/x/text v0.3.5 // indirect ) diff --git a/go.sum b/go.sum index 7b557ae..40a724e 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -37,8 +35,10 @@ github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7 github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -go.jolheiser.com/beaver v1.1.0 h1:Igz73y+jJQoe8Uteewf14mOMnozGAo2vxjzyqU8v9kA= -go.jolheiser.com/beaver v1.1.0/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= +go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.jolheiser.com/beaver v1.1.1 h1:py8Zj3tjT52dUzsvnu97aiLj1fBJjDJiK6kHjKJejMQ= +go.jolheiser.com/beaver v1.1.1/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= @@ -51,10 +51,11 @@ golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210216224549-f992740a1bac h1:9glrpwtNjBYgRpb67AZJKHfzj1stG/8BL5H7In2oTC4= -golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/main.go b/main.go index 4225082..b0166e6 100644 --- a/main.go +++ b/main.go @@ -4,35 +4,12 @@ import ( "os" "go.jolheiser.com/gpm/cmd" - "go.jolheiser.com/gpm/config" - "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" ) func main() { - cfg, err := config.Load() - if err != nil { - beaver.Fatal(err) - } - - app := cli.NewApp() - app.Name = "gpm" - app.Usage = "Go Package Manager" - app.Version = config.Version - app.Commands = []*cli.Command{ - &cmd.Add, - &cmd.Remove, - &cmd.List, - &cmd.Get, - &cmd.Import, - &cmd.Export, - &cmd.Config, - &cmd.Server, - &cmd.Search, - } - app.Flags = cmd.NewFlags(cfg) - if err := app.Run(os.Args); err != nil { + if err := cmd.New().Run(os.Args); err != nil { beaver.Error(err) } } diff --git a/router/router.go b/router/router.go index 3697034..a6de33f 100644 --- a/router/router.go +++ b/router/router.go @@ -2,38 +2,47 @@ package router import ( "encoding/json" + "io" "net/http" "time" - "go.jolheiser.com/gpm/config" + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "go.jolheiser.com/beaver" ) -var cache map[string]config.Package +var Version = "develop" -func New(cfg *config.Config) *chi.Mux { +func New(token string, db *database.Database) *chi.Mux { r := chi.NewRouter() r.Use(middleware.RedirectSlashes) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(30 * time.Second)) - r.Get("/", handleHome(cfg)) - r.Get("/export", handleExport(cfg)) - r.Get("/package/{name}", handlePackage) - - cache = cfg.Packages.Map() + r.Get("/", handleHome(db)) + r.Post("/", addUpdatePackage(db, token)) + r.Patch("/", addUpdatePackage(db, token)) + r.Delete("/", removePackage(db, token)) + r.Get("/{name}", getPackage(db)) return r } -func handleHome(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { +func handleHome(db *database.Database) func(res http.ResponseWriter, _ *http.Request) { return func(res http.ResponseWriter, _ *http.Request) { - status, err := json.Marshal(map[string]interface{}{ - "version": config.Version, - "packages": len(cfg.Packages), + pkgs, err := db.Packages() + if err != nil { + beaver.Error(err) + return + } + + status, err := json.Marshal(gpm.Info{ + Version: Version, + NumPackages: len(pkgs), + Packages: pkgs, }) if err != nil { res.WriteHeader(http.StatusInternalServerError) @@ -45,32 +54,98 @@ func handleHome(cfg *config.Config) func(res http.ResponseWriter, _ *http.Reques } } -func handleExport(cfg *config.Config) func(res http.ResponseWriter, _ *http.Request) { - return func(res http.ResponseWriter, _ *http.Request) { - export, err := cfg.Export() +func getPackage(db *database.Database) func(http.ResponseWriter, *http.Request) { + return func(res http.ResponseWriter, req *http.Request) { + name := chi.URLParam(req, "name") + + pkg, err := db.PackageJSON(name) if err != nil { - beaver.Error(err) - return - } - - _, _ = res.Write([]byte(export)) - } -} - -func handlePackage(res http.ResponseWriter, req *http.Request) { - name := chi.URLParam(req, "name") - - if pkg, ok := cache[name]; ok { - data, err := json.Marshal(pkg) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) + res.WriteHeader(http.StatusNotFound) _, _ = res.Write([]byte("{}")) return } - _, _ = res.Write(data) - return - } - res.WriteHeader(http.StatusNotFound) - _, _ = res.Write([]byte("{}")) + _, _ = res.Write(pkg) + } +} + +func addUpdatePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { + return func(res http.ResponseWriter, req *http.Request) { + if req.Header.Get(gpm.TokenHeader) != token { + res.WriteHeader(http.StatusUnauthorized) + return + } + + data, err := io.ReadAll(req.Body) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + return + } + defer req.Body.Close() + + var pkg gpm.Package + if err := json.Unmarshal(data, &pkg); err != nil { + res.WriteHeader(http.StatusBadRequest) + return + } + + exists, err := db.PackageJSON(pkg.Name) + if err != nil { + res.WriteHeader(http.StatusInternalServerError) + return + } + switch req.Method { + case http.MethodPost: + if exists != nil { + res.WriteHeader(http.StatusConflict) + return + } + case http.MethodPatch: + if exists == nil { + res.WriteHeader(http.StatusNotFound) + return + } + } + + if err := db.PutPackage(pkg); err != nil { + res.WriteHeader(http.StatusInternalServerError) + return + } + + switch req.Method { + case http.MethodPost: + res.WriteHeader(http.StatusCreated) + case http.MethodPatch: + res.WriteHeader(http.StatusOK) + } + } +} + +func removePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { + return func(res http.ResponseWriter, req *http.Request) { + if req.Header.Get(gpm.TokenHeader) != token { + res.WriteHeader(http.StatusUnauthorized) + return + } + + data, err := io.ReadAll(req.Body) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + return + } + defer req.Body.Close() + + var pkg gpm.Package + if err := json.Unmarshal(data, &pkg); err != nil { + res.WriteHeader(http.StatusBadRequest) + return + } + + if err := db.RemovePackage(pkg.Name); err != nil { + res.WriteHeader(http.StatusInternalServerError) + return + } + + res.WriteHeader(http.StatusOK) + } } diff --git a/router/router_test.go b/router/router_test.go new file mode 100644 index 0000000..ff34fb0 --- /dev/null +++ b/router/router_test.go @@ -0,0 +1,166 @@ +package router + +import ( + "context" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "go.jolheiser.com/gpm/database" + "go.jolheiser.com/gpm/go-gpm" + + "go.jolheiser.com/beaver" +) + +var ( + server *httptest.Server + token = "TestingRouter" +) + +// NOTE: The router test is more or less a copy/paste from go-gpm +// However, this ensures that testing is the same with the "real" router and DB +func TestMain(m *testing.M) { + tmp, err := os.MkdirTemp(os.TempDir(), "gpm") + if err != nil { + panic(err) + } + dbPath := filepath.Join(tmp, "gpm.db") + + db, err := database.Load(dbPath) + if err != nil { + beaver.Fatalf("could not load database at %s: %v", dbPath, err) + } + + server = httptest.NewServer(New(token, db)) + + code := m.Run() + + // Cleanup + if err := os.RemoveAll(tmp); err != nil { + panic(err) + } + + os.Exit(code) +} + +func TestRouter(t *testing.T) { + ctx := context.Background() + client := gpm.New("", gpm.WithServer(server.URL)) + + // Info + checkInfo(t, client, 0) + + pkg1 := gpm.Package{ + Name: "test1", + Import: "gitea.com/test/testing", + } + pkg2 := gpm.Package{ + Name: "test2", + Import: "gitea.com/testing/test", + } + + // Add (without token) + if err := client.Add(ctx, pkg1); err == nil { + t.Log("adding without token should fail") + t.Fail() + } + + // Add (with token) + client = gpm.New(token, gpm.WithServer(server.URL)) + checkAdd(t, client, pkg1, pkg2) + + // Info (after second package) + checkInfo(t, client, 2) + + // Check package + checkGet(t, client, pkg2) + + // Update package + checkUpdate(t, client, pkg1) + + // Remove + checkRemove(t, client, pkg1) + + // Info (final) + checkInfo(t, client, 1) +} + +func checkInfo(t *testing.T, client *gpm.Client, numPackages int) { + info, err := client.Info(context.Background()) + if err != nil { + t.Logf("info should not return error: %v\n", err) + t.Fail() + } + if info.Version != Version || info.NumPackages != numPackages { + t.Log("info did not match expected") + t.Fail() + } +} + +func checkGet(t *testing.T, client *gpm.Client, pkg gpm.Package) { + ctx := context.Background() + _, err := client.Get(ctx, "test3") + if err == nil { + t.Log("should not be able to get invalid package") + t.Fail() + } + + // Check valid package + p, err := client.Get(ctx, "test2") + if err != nil { + t.Logf("should not be able to get invalid package: %v\n", err) + t.Fail() + } + if p != pkg { + t.Log("valid package should match pkg") + t.Fail() + } +} + +func checkAdd(t *testing.T, client *gpm.Client, pkg1, pkg2 gpm.Package) { + ctx := context.Background() + if err := client.Add(ctx, pkg1); err != nil { + t.Logf("pkg1 should be added: %v\n", err) + t.Fail() + } + if err := client.Add(ctx, pkg2); err != nil { + t.Logf("pkg2 should be added: %v\n", err) + t.Fail() + } + // Duplicate package + if err := client.Add(ctx, pkg1); err == nil { + t.Log("pkg1 should already exist") + t.Fail() + } +} + +func checkUpdate(t *testing.T, client *gpm.Client, pkg gpm.Package) { + ctx := context.Background() + // Update invalid package + if err := client.Update(ctx, gpm.Package{Name: "test4", Import: "gitea.com/invalid"}); err == nil { + t.Log("should not be able to update invalid package") + t.Fail() + } + + // Update valid package + pkg.Import = "gitea.com/tester/testing" + if err := client.Update(ctx, pkg); err != nil { + t.Logf("should be able to update valid package: %v\n", err) + t.Fail() + } +} + +func checkRemove(t *testing.T, client *gpm.Client, pkg gpm.Package) { + ctx := context.Background() + if err := client.Remove(ctx, pkg); err != nil { + t.Logf("should be able to remove package: %v\n", err) + t.Fail() + } + + // Remove (idempotent) + if err := client.Remove(ctx, pkg); err != nil { + t.Logf("should be able to remove package idempotently: %v\n", err) + t.Fail() + } +} -- 2.41.0 From a5d46fe7a2075bd0c3537d536e513172cfcc0be9 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Fri, 29 Oct 2021 01:09:23 +0000 Subject: [PATCH 6/9] Remove extra go mod (#8) Reviewed-on: https://git.jojodev.com/jolheiser/gpm/pulls/8 Co-authored-by: jolheiser Co-committed-by: jolheiser --- go-gpm/go.mod | 3 --- go.mod | 3 --- go.sum | 6 ++++++ 3 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 go-gpm/go.mod diff --git a/go-gpm/go.mod b/go-gpm/go.mod deleted file mode 100644 index a2558d4..0000000 --- a/go-gpm/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module go.jolheiser.com/gpm/go-gpm - -go 1.16 diff --git a/go.mod b/go.mod index 0715a09..27a014d 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module go.jolheiser.com/gpm go 1.15 -replace go.jolheiser.com/gpm/go-gpm => ./go-gpm - require ( github.com/AlecAivazis/survey/v2 v2.2.7 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect @@ -14,7 +12,6 @@ require ( github.com/urfave/cli/v2 v2.3.0 go.etcd.io/bbolt v1.3.5 go.jolheiser.com/beaver v1.1.1 - go.jolheiser.com/gpm/go-gpm v0.0.0-00010101000000-000000000000 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect diff --git a/go.sum b/go.sum index 40a724e..96fb965 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ github.com/AlecAivazis/survey/v2 v2.2.7 h1:5NbxkF4RSKmpywYdcRgUmos1o+roJY8duCLZXbVjoig= github.com/AlecAivazis/survey/v2 v2.2.7/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= @@ -30,6 +31,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -43,6 +45,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -62,6 +65,9 @@ golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -- 2.41.0 From 2da056a909b4fb0899e12b6454a70b15d0a5c87c Mon Sep 17 00:00:00 2001 From: jolheiser Date: Wed, 3 Nov 2021 04:37:57 +0000 Subject: [PATCH 7/9] Refactor (#9) Reviewed-on: https://git.jojodev.com/jolheiser/gpm/pulls/9 Co-authored-by: jolheiser Co-committed-by: jolheiser --- .golangci.yml | 23 --------------- .woodpecker.yml | 59 ++++++++++++++++++++++++++++++++++++++ DOCS.md | 66 +++++++++++++++++++++++++++++++++++++++++++ Earthfile | 14 --------- Makefile | 41 --------------------------- README.md | 2 +- cmd/add.go | 4 +-- cmd/cmd.go | 7 ++--- cmd/get.go | 8 +++--- cmd/remove.go | 4 +-- cmd/search.go | 8 +++--- cmd/server.go | 6 ++-- cmd/update.go | 4 +-- docs.go | 4 ++- go.mod | 7 ++--- go.sum | 49 +++++++++++++++++++------------- main.go | 8 ++++-- router/router.go | 53 +++++++++++----------------------- router/router_test.go | 5 ++-- tools.go | 8 ++++++ 20 files changed, 212 insertions(+), 168 deletions(-) delete mode 100644 .golangci.yml create mode 100644 .woodpecker.yml create mode 100644 DOCS.md delete mode 100644 Earthfile delete mode 100644 Makefile create mode 100644 tools.go diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 6d71439..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,23 +0,0 @@ -linters: - enable: - - deadcode - - dogsled - - dupl - - errcheck - - funlen - - gocognit - - goconst - - gocritic - - gocyclo - - gofmt - - golint - - gosimple - - govet - - misspell - - prealloc - - staticcheck - - structcheck - - typecheck - - unparam - - unused - - varcheck \ No newline at end of file diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..90155bb --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,59 @@ +clone: + git: + image: woodpeckerci/plugin-git:next + +pipeline: + compliance: + image: golang:1.17 + commands: + - go test -race ./... + - go vet ./... + - go run github.com/rs/zerolog/cmd/lint go.jolheiser.com/gpm + - go build + when: + event: pull_request + + build: + image: golang:1.17 + commands: + - GOOS="windows" go build + - GOOS="linux" go build + when: + event: [ push, tag ] + branch: main + + release-main: + image: jolheiser/drone-gitea-main:latest + secrets: + - source: gitea_token + target: plugin_token + base: https://git.jojodev.com + files: + - "gpm" + - "gpm.exe" + when: + event: push + branch: main + + release-tag: + image: plugins/gitea-release:1 + secrets: + - source: gitea_token + target: plugin_api_key + base_url: https://git.jojodev.com + files: + - "gpm" + - "gpm.exe" + when: + event: tag + tag: v* + + prune: + image: jolheiser/drone-gitea-prune + secrets: + - source: gitea_token + target: plugin_token + base: https://git.jojodev.com + when: + event: tag + tag: v* diff --git a/DOCS.md b/DOCS.md new file mode 100644 index 0000000..d29b8d2 --- /dev/null +++ b/DOCS.md @@ -0,0 +1,66 @@ +# NAME + +gpm - Go Package Manager + +# SYNOPSIS + +gpm + +``` +[--database|-d]=[value] +[--server|-s]=[value] +[--token|-t]=[value] +``` + +**Usage**: + +``` +gpm [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +``` + +# GLOBAL OPTIONS + +**--database, -d**="": path to gpm database for server (default: `${USERCONFIG}/gpm.db` or `${BINPATH}/gpm.db`) + +**--server, -s**="": gpm server to use (default: https://gpm.jolheiser.com) + +**--token, -t**="": gpm auth token to use + + +# COMMANDS + +## add, a + +Add a package + +**--force, -f**: Overwrite existing package without prompt + +**--local, -l**: local mode + +## get, g + +Get package(s) + +## list, ls, l + +List local packages + +## remove, rm + +Remove package(s) + +## search, s + +Search packages + +## server, web + +Start the gpm server + +**--port, -p**="": Port to run the gpm server on (default: 3333) + +## update, u + +Update a package + +**--local, -l**: local mode diff --git a/Earthfile b/Earthfile deleted file mode 100644 index 3ad4128..0000000 --- a/Earthfile +++ /dev/null @@ -1,14 +0,0 @@ -# To lint, install Earthly and run `earth +lint` -# This ensures the usage of the same version of golangci-lint - -FROM golangci/golangci-lint:v1.37 - -WORKDIR /gpm - -lint-cli: - COPY . . - RUN golangci-lint run - -lint-lib: - COPY ./go-gpm . - RUN golangci-lint run \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 5cdd052..0000000 --- a/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -GO ?= go -VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') - -.PHONY: build -build: - $(GO) build -ldflags '-s -w -X "go.jolheiser.com/gpm/router.Version=$(VERSION)"' - -.PHONY: lint -lint: - earth +lint-cli - earth +lint-lib - -.PHONY: fmt -fmt: fmt-cli fmt-lib - -.PHONY: test -test: test-cli test-lib - -.PHONY: fmt-cli -fmt-cli: - $(GO) fmt ./... - -.PHONY: test-cli -test-cli: - $(GO) test -race ./... - -.PHONY: fmt-lib -fmt-lib: - @cd go-gpm && $(GO) fmt ./... - -.PHONY: test-lib -test-lib: - @cd go-gpm && $(GO) test -race ./... - -.PHONY: docker-build -docker-build: - docker build -f docker/Dockerfile -t jolheiser/gpm . - -.PHONY: docker-push -docker-push: docker-build - docker push jolheiser/gpm \ No newline at end of file diff --git a/README.md b/README.md index 926d6fc..079ba4d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Using either a GPM server or local config, I can instead `gpm get cli` which fin * `list` - List local packages * `config` - Change local configuration * `get` - Get a list of packages - * e.g. `gpm get beaver survey bbolt cli chi` to get all the modules needed for gpm itself (assuming the map resolves to the same packages) + * e.g. `gpm get zerolog survey bbolt cli chi` to get all the modules needed for gpm itself (assuming the map resolves to the same packages) * `server` - Start a gpm server diff --git a/cmd/add.go b/cmd/add.go index 8e6cd0a..1739655 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "github.com/rs/zerolog/log" "regexp" "strings" @@ -11,7 +12,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Add = cli.Command{ @@ -85,6 +85,6 @@ func doAdd(_ *cli.Context) error { } } - beaver.Infof("Added %s", yellow.Format(nameAnswer)) + log.Info().Msgf("Added %q", nameAnswer) return nil } diff --git a/cmd/cmd.go b/cmd/cmd.go index 6c99021..4b498cf 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -12,11 +12,8 @@ import ( "go.jolheiser.com/gpm/router" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver/color" ) -var yellow = color.FgYellow - func New() *cli.App { app := cli.NewApp() app.Name = "gpm" @@ -53,7 +50,7 @@ func New() *cli.App { Aliases: []string{"d"}, Usage: "path to gpm database for server", Value: dbPath(), - DefaultText: "`${HOME}/gpm.db` or `${BINPATH}/gpm.db`", + DefaultText: "`${USERCONFIG}/gpm.db` or `${BINPATH}/gpm.db`", EnvVars: []string{"GPM_DATABASE"}, Destination: &flags.Database, }, @@ -63,7 +60,7 @@ func New() *cli.App { func dbPath() string { fn := "gpm.db" - home, err := os.UserHomeDir() + home, err := os.UserConfigDir() if err != nil { bin, err := os.Executable() if err != nil { diff --git a/cmd/get.go b/cmd/get.go index ba6e39e..ca4cb6b 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "github.com/rs/zerolog/log" "os" "os/exec" "strings" @@ -11,7 +12,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Get = cli.Command{ @@ -40,13 +40,13 @@ func doGet(ctx *cli.Context) error { for _, p := range pkgs { pkg, err := client.Get(context.Background(), p) if err != nil { - beaver.Error(err) + log.Err(err).Msg("") continue } - beaver.Infof("getting `%s`...", pkg) + log.Info().Msgf("getting %q...", pkg.Import) if err := goGet(pkg.Import); err != nil { - beaver.Error(err) + log.Err(err).Msg("") } } diff --git a/cmd/remove.go b/cmd/remove.go index ad15807..b066dac 100644 --- a/cmd/remove.go +++ b/cmd/remove.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "github.com/rs/zerolog/log" "go.jolheiser.com/gpm/cmd/flags" "go.jolheiser.com/gpm/database" @@ -9,7 +10,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Remove = cli.Command{ @@ -63,6 +63,6 @@ func doRemove(_ *cli.Context) error { } } - beaver.Infof("Removed %s", yellow.Format(pkgName)) + log.Info().Msgf("Removed %q", pkgName) return nil } diff --git a/cmd/search.go b/cmd/search.go index 7aef35d..f3d9ff4 100644 --- a/cmd/search.go +++ b/cmd/search.go @@ -1,11 +1,11 @@ package cmd import ( + "github.com/rs/zerolog/log" "go.jolheiser.com/gpm/go-gpm" "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Search = cli.Command{ @@ -41,12 +41,12 @@ func doSearch(_ *cli.Context) error { for _, name := range a { pkg, ok := pkgMap[name] if !ok { - beaver.Errorf("could not find package for `%s`", name) + log.Error().Msgf("could not find package for %q", name) continue } - beaver.Infof("getting `%s`...", name) + log.Info().Msgf("getting %q...", name) if err := goGet(pkg.Import); err != nil { - beaver.Error(err) + log.Err(err).Msg("") } } diff --git a/cmd/server.go b/cmd/server.go index 9931fbc..3b25448 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "fmt" + "github.com/rs/zerolog/log" "net/http" "go.jolheiser.com/gpm/cmd/flags" @@ -10,7 +11,6 @@ import ( "go.jolheiser.com/gpm/router" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Server = cli.Command{ @@ -37,10 +37,10 @@ func doServer(_ *cli.Context) error { db, err := database.Load(flags.Database) if err != nil { - beaver.Fatalf("could not load database at %s: %v", flags.Database, err) + log.Fatal().Msgf("could not load database at %q: %v", flags.Database, err) } - beaver.Infof("Running gpm server at http://localhost:%d", flags.Port) + log.Info().Msgf("Running gpm server at http://localhost:%d", flags.Port) if err := http.ListenAndServe(fmt.Sprintf(":%d", flags.Port), router.New(flags.Token, db)); err != nil { return err } diff --git a/cmd/update.go b/cmd/update.go index 690e235..3639bce 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "github.com/rs/zerolog/log" "go.jolheiser.com/gpm/cmd/flags" "go.jolheiser.com/gpm/database" @@ -9,7 +10,6 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" ) var Update = cli.Command{ @@ -81,6 +81,6 @@ func doUpdate(_ *cli.Context) error { } } - beaver.Infof("Updated %s", yellow.Format(pkgName)) + log.Info().Msgf("Updated %q", pkgName) return nil } diff --git a/docs.go b/docs.go index a2a6fd8..c7cbd42 100644 --- a/docs.go +++ b/docs.go @@ -1,4 +1,5 @@ -//+build docs +//go:build generate +// +build generate package main @@ -9,6 +10,7 @@ import ( "go.jolheiser.com/gpm/cmd" ) +//go:generate go run docs.go func main() { app := cmd.New() diff --git a/go.mod b/go.mod index 27a014d..5ba33f3 100644 --- a/go.mod +++ b/go.mod @@ -6,14 +6,11 @@ require ( github.com/AlecAivazis/survey/v2 v2.2.7 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/go-chi/chi v1.5.2 + github.com/go-chi/render v1.0.1 github.com/mattn/go-colorable v0.1.8 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/rs/zerolog v1.26.0 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/urfave/cli/v2 v2.3.0 go.etcd.io/bbolt v1.3.5 - go.jolheiser.com/beaver v1.1.1 - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect - golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 // indirect - golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect - golang.org/x/text v0.3.5 // indirect ) diff --git a/go.sum b/go.sum index 96fb965..f06889a 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ github.com/AlecAivazis/survey/v2 v2.2.7 h1:5NbxkF4RSKmpywYdcRgUmos1o+roJY8duCLZXbVjoig= github.com/AlecAivazis/survey/v2 v2.2.7/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -11,6 +11,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-chi/chi v1.5.2 h1:YcLIBANL4OTaAOcTdp//sskGa0yGACQMCtbnr7YEn0Q= github.com/go-chi/chi v1.5.2/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k= +github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= +github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -26,48 +29,56 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= +github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.jolheiser.com/beaver v1.1.1 h1:py8Zj3tjT52dUzsvnu97aiLj1fBJjDJiK6kHjKJejMQ= -go.jolheiser.com/beaver v1.1.1/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index b0166e6..9d23860 100644 --- a/main.go +++ b/main.go @@ -1,15 +1,17 @@ package main import ( + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "os" "go.jolheiser.com/gpm/cmd" - - "go.jolheiser.com/beaver" ) func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + if err := cmd.New().Run(os.Args); err != nil { - beaver.Error(err) + log.Err(err).Msg("") } } diff --git a/router/router.go b/router/router.go index a6de33f..69424b7 100644 --- a/router/router.go +++ b/router/router.go @@ -1,8 +1,8 @@ package router import ( - "encoding/json" - "io" + "github.com/go-chi/render" + "github.com/rs/zerolog/log" "net/http" "time" @@ -11,7 +11,6 @@ import ( "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" - "go.jolheiser.com/beaver" ) var Version = "develop" @@ -31,41 +30,35 @@ func New(token string, db *database.Database) *chi.Mux { return r } -func handleHome(db *database.Database) func(res http.ResponseWriter, _ *http.Request) { - return func(res http.ResponseWriter, _ *http.Request) { +func handleHome(db *database.Database) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { pkgs, err := db.Packages() if err != nil { - beaver.Error(err) + log.Err(err).Msg("") return } - status, err := json.Marshal(gpm.Info{ + render.JSON(w, r, gpm.Info{ Version: Version, NumPackages: len(pkgs), Packages: pkgs, }) - if err != nil { - res.WriteHeader(http.StatusInternalServerError) - _, _ = res.Write([]byte("{}")) - return - } - - _, _ = res.Write(status) } } func getPackage(db *database.Database) func(http.ResponseWriter, *http.Request) { - return func(res http.ResponseWriter, req *http.Request) { - name := chi.URLParam(req, "name") + return func(w http.ResponseWriter, r *http.Request) { + name := chi.URLParam(r, "name") - pkg, err := db.PackageJSON(name) + + pkg, err := db.Package(name) if err != nil { - res.WriteHeader(http.StatusNotFound) - _, _ = res.Write([]byte("{}")) + w.WriteHeader(http.StatusNotFound) + render.JSON(w, r, struct{}{}) return } - _, _ = res.Write(pkg) + render.JSON(w, r, pkg) } } @@ -76,19 +69,13 @@ func addUpdatePackage(db *database.Database, token string) func(http.ResponseWri return } - data, err := io.ReadAll(req.Body) - if err != nil { + var pkg gpm.Package + if err := render.DecodeJSON(req.Body, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() - var pkg gpm.Package - if err := json.Unmarshal(data, &pkg); err != nil { - res.WriteHeader(http.StatusBadRequest) - return - } - exists, err := db.PackageJSON(pkg.Name) if err != nil { res.WriteHeader(http.StatusInternalServerError) @@ -128,19 +115,13 @@ func removePackage(db *database.Database, token string) func(http.ResponseWriter return } - data, err := io.ReadAll(req.Body) - if err != nil { + var pkg gpm.Package + if err := render.DecodeJSON(req.Body, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return } defer req.Body.Close() - var pkg gpm.Package - if err := json.Unmarshal(data, &pkg); err != nil { - res.WriteHeader(http.StatusBadRequest) - return - } - if err := db.RemovePackage(pkg.Name); err != nil { res.WriteHeader(http.StatusInternalServerError) return diff --git a/router/router_test.go b/router/router_test.go index ff34fb0..7ac3348 100644 --- a/router/router_test.go +++ b/router/router_test.go @@ -2,6 +2,7 @@ package router import ( "context" + "github.com/rs/zerolog/log" "net/http/httptest" "os" "path/filepath" @@ -9,8 +10,6 @@ import ( "go.jolheiser.com/gpm/database" "go.jolheiser.com/gpm/go-gpm" - - "go.jolheiser.com/beaver" ) var ( @@ -29,7 +28,7 @@ func TestMain(m *testing.M) { db, err := database.Load(dbPath) if err != nil { - beaver.Fatalf("could not load database at %s: %v", dbPath, err) + log.Fatal().Msgf("could not load database at %q: %v", dbPath, err) } server = httptest.NewServer(New(token, db)) diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..048b2fa --- /dev/null +++ b/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package main + +import ( + _ "github.com/rs/zerolog/cmd/lint" +) -- 2.41.0 From 0d6109a4be9834a08f4b81ecdeddbcb5b57dbbc8 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Mon, 25 Jul 2022 03:49:44 +0000 Subject: [PATCH 8/9] Update for goreleaser (#10) Co-authored-by: jolheiser Reviewed-on: https://git.jojodev.com/jolheiser/gpm/pulls/10 --- .goreleaser.yaml | 26 +++ .woodpecker.yml | 59 ----- .woodpecker/goreleaser.yml | 39 ++++ DOCS.md | 2 +- go-gpm/client.go => client.go | 0 cmd/flags/flags.go | 11 - main.go => cmd/gpm/main.go | 11 +- docker/Dockerfile | 2 +- docs.go | 9 +- go-gpm/gpm_test.go | 207 ------------------ go.mod | 19 +- go.sum | 49 ++++- {cmd => internal/cli}/add.go | 19 +- {cmd => internal/cli}/cmd.go | 26 +-- internal/cli/flags.go | 11 + {cmd => internal/cli}/get.go | 9 +- {cmd => internal/cli}/list.go | 2 +- {cmd => internal/cli}/remove.go | 15 +- {cmd => internal/cli}/search.go | 6 +- {cmd => internal/cli}/server.go | 23 +- {cmd => internal/cli}/update.go | 17 +- {database => internal/database}/database.go | 2 +- .../database}/database_test.go | 3 +- {router => internal/router}/router.go | 23 +- {router => internal/router}/router_test.go | 11 +- go-gpm/package.go => package.go | 0 tools.go | 8 - 27 files changed, 216 insertions(+), 393 deletions(-) create mode 100644 .goreleaser.yaml delete mode 100644 .woodpecker.yml create mode 100644 .woodpecker/goreleaser.yml rename go-gpm/client.go => client.go (100%) delete mode 100644 cmd/flags/flags.go rename main.go => cmd/gpm/main.go (62%) delete mode 100644 go-gpm/gpm_test.go rename {cmd => internal/cli}/add.go (84%) rename {cmd => internal/cli}/cmd.go (78%) create mode 100644 internal/cli/flags.go rename {cmd => internal/cli}/get.go (87%) rename {cmd => internal/cli}/list.go (97%) rename {cmd => internal/cli}/remove.go (82%) rename {cmd => internal/cli}/search.go (95%) rename {cmd => internal/cli}/server.go (52%) rename {cmd => internal/cli}/update.go (84%) rename {database => internal/database}/database.go (98%) rename {database => internal/database}/database_test.go (97%) rename {router => internal/router}/router.go (87%) rename {router => internal/router}/router_test.go (95%) rename go-gpm/package.go => package.go (100%) delete mode 100644 tools.go diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..d195971 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,26 @@ +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + main: ./cmd/gpm + ldflags: + - "-s -w -X go.jolheiser.com/gpm/cmd.Version={{.Version}}" +archives: + - replacements: + 386: i386 + amd64: x86_64 + format_overrides: + - goos: windows + format: zip +checksum: + name_template: 'checksums.txt' +release: + gitea: + owner: jolheiser + name: gpm +gitea_urls: + api: https://git.jojodev.com/api/v1/ + download: https://git.jojodev.com diff --git a/.woodpecker.yml b/.woodpecker.yml deleted file mode 100644 index 90155bb..0000000 --- a/.woodpecker.yml +++ /dev/null @@ -1,59 +0,0 @@ -clone: - git: - image: woodpeckerci/plugin-git:next - -pipeline: - compliance: - image: golang:1.17 - commands: - - go test -race ./... - - go vet ./... - - go run github.com/rs/zerolog/cmd/lint go.jolheiser.com/gpm - - go build - when: - event: pull_request - - build: - image: golang:1.17 - commands: - - GOOS="windows" go build - - GOOS="linux" go build - when: - event: [ push, tag ] - branch: main - - release-main: - image: jolheiser/drone-gitea-main:latest - secrets: - - source: gitea_token - target: plugin_token - base: https://git.jojodev.com - files: - - "gpm" - - "gpm.exe" - when: - event: push - branch: main - - release-tag: - image: plugins/gitea-release:1 - secrets: - - source: gitea_token - target: plugin_api_key - base_url: https://git.jojodev.com - files: - - "gpm" - - "gpm.exe" - when: - event: tag - tag: v* - - prune: - image: jolheiser/drone-gitea-prune - secrets: - - source: gitea_token - target: plugin_token - base: https://git.jojodev.com - when: - event: tag - tag: v* diff --git a/.woodpecker/goreleaser.yml b/.woodpecker/goreleaser.yml new file mode 100644 index 0000000..261ee53 --- /dev/null +++ b/.woodpecker/goreleaser.yml @@ -0,0 +1,39 @@ +clone: + git: + image: woodpeckerci/plugin-git + settings: + tags: true + +pipeline: + compliance: + image: golang:1.18 + commands: + - go test -race ./... + - go vet ./... + - go run github.com/rs/zerolog/cmd/lint@latest go.jolheiser.com/gpm/cmd/gpm + when: + event: pull_request + + build: + image: goreleaser/goreleaser + commands: + - goreleaser build --snapshot + when: + event: pull_request + + release: + image: goreleaser/goreleaser + commands: + - goreleaser release + secrets: [ gitea_token ] + when: + event: tag + + prune: + image: jolheiser/drone-gitea-prune + settings: + base: https://git.jojodev.com + token: + from_secret: gitea_token + when: + event: tag diff --git a/DOCS.md b/DOCS.md index d29b8d2..4fc41a7 100644 --- a/DOCS.md +++ b/DOCS.md @@ -20,7 +20,7 @@ gpm [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] # GLOBAL OPTIONS -**--database, -d**="": path to gpm database for server (default: `${USERCONFIG}/gpm.db` or `${BINPATH}/gpm.db`) +**--database, -d**="": path to gpm database for server (default: /home/jolheiser/.config/gpm.db) **--server, -s**="": gpm server to use (default: https://gpm.jolheiser.com) diff --git a/go-gpm/client.go b/client.go similarity index 100% rename from go-gpm/client.go rename to client.go diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go deleted file mode 100644 index e4a4f67..0000000 --- a/cmd/flags/flags.go +++ /dev/null @@ -1,11 +0,0 @@ -package flags - -var ( - Server string - Token string - Database string - - Local bool - Force bool - Port int -) diff --git a/main.go b/cmd/gpm/main.go similarity index 62% rename from main.go rename to cmd/gpm/main.go index 9d23860..bfbe2de 100644 --- a/main.go +++ b/cmd/gpm/main.go @@ -1,17 +1,20 @@ package main import ( - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" "os" - "go.jolheiser.com/gpm/cmd" + "go.jolheiser.com/gpm/internal/cli" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" ) +var Version = "develop" + func main() { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) - if err := cmd.New().Run(os.Args); err != nil { + if err := cli.New(Version).Run(os.Args); err != nil { log.Err(err).Msg("") } } diff --git a/docker/Dockerfile b/docker/Dockerfile index 5431a7b..3492098 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,7 @@ FROM golang:1.16-alpine as builder RUN apk --no-cache add build-base git COPY . /app WORKDIR /app -RUN make build +RUN go build ./cmd/gpm FROM alpine:latest LABEL maintainer="john.olheiser@gmail.com" diff --git a/docs.go b/docs.go index c7cbd42..96d9e78 100644 --- a/docs.go +++ b/docs.go @@ -4,24 +4,19 @@ package main import ( + "go.jolheiser.com/gpm/internal/cli" "os" - "strings" - - "go.jolheiser.com/gpm/cmd" ) //go:generate go run docs.go func main() { - app := cmd.New() + app := cli.New("docs") md, err := app.ToMarkdown() if err != nil { panic(err) } - // FIXME Why is this not fixed yet?? - md = md[strings.Index(md, "#"):] - fi, err := os.Create("DOCS.md") if err != nil { panic(err) diff --git a/go-gpm/gpm_test.go b/go-gpm/gpm_test.go deleted file mode 100644 index 925a0bc..0000000 --- a/go-gpm/gpm_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package gpm - -import ( - "context" - "encoding/json" - "net/http" - "net/http/httptest" - "os" - "strings" - "testing" -) - -var ( - server *httptest.Server - token = "TestingLibrary" - version = "GPMTest" - - packages = []Package{ - { - Name: "test1", - Import: "gitea.com/test/testing", - }, - } -) - -func TestMain(m *testing.M) { - server = httptest.NewServer(http.HandlerFunc(testServer)) - os.Exit(m.Run()) -} - -func TestClient(t *testing.T) { - ctx := context.Background() - client := New("", WithServer(server.URL)) - - // Info - checkInfo(t, client, 1) - - pkg1 := Package{ - Name: "test1", - Import: "gitea.com/test/testing", - } - pkg2 := Package{ - Name: "test2", - Import: "gitea.com/testing/test", - } - - // Add (without token) - if err := client.Add(ctx, pkg1); err == nil { - t.Log("adding without token should fail") - t.Fail() - } - - // Add (with token) - client = New(token, WithServer(server.URL)) - checkAdd(t, client, pkg1, pkg2) - - // Info (after second package) - checkInfo(t, client, 2) - - // Check package - checkGet(t, client, pkg2) - - // Update package - checkUpdate(t, client, pkg1) - - // Remove - checkRemove(t, client, pkg1) - - // Info (final) - checkInfo(t, client, 1) -} - -func checkInfo(t *testing.T, client *Client, numPackages int) { - info, err := client.Info(context.Background()) - if err != nil { - t.Logf("info should not return error: %v\n", err) - t.Fail() - } - if info.Version != version || info.NumPackages != numPackages { - t.Log("info did not match expected") - t.Fail() - } -} - -func checkGet(t *testing.T, client *Client, pkg Package) { - ctx := context.Background() - _, err := client.Get(ctx, "test3") - if err == nil { - t.Log("should not be able to get invalid package") - t.Fail() - } - - // Check valid package - p, err := client.Get(ctx, "test2") - if err != nil { - t.Logf("should not be able to get invalid package: %v\n", err) - t.Fail() - } - if p != pkg { - t.Log("valid package should match pkg") - t.Fail() - } -} - -func checkAdd(t *testing.T, client *Client, pkg1, pkg2 Package) { - ctx := context.Background() - if err := client.Add(ctx, pkg2); err != nil { - t.Logf("pkg2 should be added: %v\n", err) - t.Fail() - } - // Duplicate package - if err := client.Add(ctx, pkg1); err == nil { - t.Log("pkg1 should already exist") - t.Fail() - } -} - -func checkUpdate(t *testing.T, client *Client, pkg Package) { - ctx := context.Background() - // Update invalid package - if err := client.Update(ctx, Package{Name: "test4", Import: "gitea.com/invalid"}); err == nil { - t.Log("should not be able to update invalid package") - t.Fail() - } - - // Update valid package - pkg.Import = "gitea.com/tester/testing" - if err := client.Update(ctx, pkg); err != nil { - t.Logf("should be able to update valid package: %v\n", err) - t.Fail() - } -} - -func checkRemove(t *testing.T, client *Client, pkg Package) { - ctx := context.Background() - if err := client.Remove(ctx, pkg); err != nil { - t.Logf("should be able to remove package: %v\n", err) - t.Fail() - } - - // Remove (idempotent) - if err := client.Remove(ctx, pkg); err != nil { - t.Logf("should be able to remove package idempotently: %v\n", err) - t.Fail() - } -} - -func testServer(w http.ResponseWriter, r *http.Request) { - switch r.URL.Path { - case "/": - switch r.Method { - case http.MethodGet: - resp := Info{ - Version: version, - NumPackages: len(packages), - Packages: packages, - } - _ = json.NewEncoder(w).Encode(resp) - case http.MethodPost, http.MethodPatch, http.MethodDelete: - if r.Header.Get(TokenHeader) != token { - w.WriteHeader(http.StatusUnauthorized) - return - } - var pkg Package - if err := json.NewDecoder(r.Body).Decode(&pkg); err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - switch r.Method { - case http.MethodPost: - for _, p := range packages { - if p.Name == pkg.Name { - w.WriteHeader(http.StatusConflict) - return - } - } - packages = append(packages, pkg) - w.WriteHeader(http.StatusCreated) - case http.MethodPatch: - for idx, p := range packages { - if p.Name == pkg.Name { - packages[idx] = pkg - return - } - } - w.WriteHeader(http.StatusNotFound) - case http.MethodDelete: - for idx, p := range packages { - if p.Name == pkg.Name { - packages = append(packages[:idx], packages[idx+1:]...) - } - } - } - return - } - return - default: - name := strings.TrimPrefix(r.URL.Path, "/") - for _, pkg := range packages { - if pkg.Name == name { - _ = json.NewEncoder(w).Encode(pkg) - return - } - } - } - w.WriteHeader(http.StatusNotImplemented) -} diff --git a/go.mod b/go.mod index 5ba33f3..f9d4b94 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,19 @@ module go.jolheiser.com/gpm go 1.15 require ( - github.com/AlecAivazis/survey/v2 v2.2.7 - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/go-chi/chi v1.5.2 + github.com/AlecAivazis/survey/v2 v2.3.5 + github.com/go-chi/chi/v5 v5.0.7 github.com/go-chi/render v1.0.1 - github.com/mattn/go-colorable v0.1.8 // indirect + github.com/kr/pty v1.1.4 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/rs/zerolog v1.26.0 + github.com/rs/zerolog v1.27.0 github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/urfave/cli/v2 v2.3.0 - go.etcd.io/bbolt v1.3.5 + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/urfave/cli/v2 v2.11.1 + go.etcd.io/bbolt v1.3.6 + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect + golang.org/x/tools v0.1.7 // indirect + gopkg.in/yaml.v2 v2.2.3 // indirect ) diff --git a/go.sum b/go.sum index f06889a..f176327 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,31 @@ github.com/AlecAivazis/survey/v2 v2.2.7 h1:5NbxkF4RSKmpywYdcRgUmos1o+roJY8duCLZXbVjoig= github.com/AlecAivazis/survey/v2 v2.2.7/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= +github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5E/9wRQ= +github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= +github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi v1.5.2 h1:YcLIBANL4OTaAOcTdp//sskGa0yGACQMCtbnr7YEn0Q= -github.com/go-chi/chi v1.5.2/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= +github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ= @@ -23,9 +33,13 @@ github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -35,26 +49,38 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= +github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= +github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/cli/v2 v2.11.1 h1:UKK6SP7fV3eKOefbS87iT9YHefv7iB/53ih6e+GNAsE= +github.com/urfave/cli/v2 v2.11.1/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -64,21 +90,34 @@ golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/add.go b/internal/cli/add.go similarity index 84% rename from cmd/add.go rename to internal/cli/add.go index 1739655..168d622 100644 --- a/cmd/add.go +++ b/internal/cli/add.go @@ -1,16 +1,15 @@ -package cmd +package cli import ( "context" - "github.com/rs/zerolog/log" "regexp" "strings" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -23,13 +22,13 @@ var Add = cli.Command{ Name: "force", Aliases: []string{"f"}, Usage: "Overwrite existing package without prompt", - Destination: &flags.Force, + Destination: &forceFlag, }, &cli.BoolFlag{ Name: "local", Aliases: []string{"l"}, Usage: "local mode", - Destination: &flags.Local, + Destination: &localFlag, }, }, Before: localOrToken, @@ -70,8 +69,8 @@ func doAdd(_ *cli.Context) error { Import: goGetAnswer, } - if flags.Local { - db, err := database.Load(flags.Database) + if localFlag { + db, err := database.Load(databaseFlag) if err != nil { return err } @@ -79,7 +78,7 @@ func doAdd(_ *cli.Context) error { return err } } else { - client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + client := gpm.New(tokenFlag, gpm.WithServer(serverFlag)) if err := client.Add(context.Background(), pkg); err != nil { return err } diff --git a/cmd/cmd.go b/internal/cli/cmd.go similarity index 78% rename from cmd/cmd.go rename to internal/cli/cmd.go index 4b498cf..9073675 100644 --- a/cmd/cmd.go +++ b/internal/cli/cmd.go @@ -1,4 +1,4 @@ -package cmd +package cli import ( "context" @@ -6,19 +6,17 @@ import ( "os" "path/filepath" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" - "go.jolheiser.com/gpm/router" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" "github.com/urfave/cli/v2" ) -func New() *cli.App { +func New(version string) *cli.App { app := cli.NewApp() app.Name = "gpm" app.Usage = "Go Package Manager" - app.Version = router.Version + app.Version = version app.Commands = []*cli.Command{ &Add, &Get, @@ -35,7 +33,7 @@ func New() *cli.App { Usage: "gpm server to use", Value: gpm.DefaultServer, EnvVars: []string{"GPM_SERVER"}, - Destination: &flags.Server, + Destination: &serverFlag, }, &cli.StringFlag{ Name: "token", @@ -43,7 +41,7 @@ func New() *cli.App { Usage: "gpm auth token to use", DefaultText: "${GPM_TOKEN}", EnvVars: []string{"GPM_TOKEN"}, - Destination: &flags.Token, + Destination: &tokenFlag, }, &cli.StringFlag{ Name: "database", @@ -52,7 +50,7 @@ func New() *cli.App { Value: dbPath(), DefaultText: "`${USERCONFIG}/gpm.db` or `${BINPATH}/gpm.db`", EnvVars: []string{"GPM_DATABASE"}, - Destination: &flags.Database, + Destination: &databaseFlag, }, } return app @@ -72,7 +70,7 @@ func dbPath() string { } func localOrToken(_ *cli.Context) error { - if flags.Local && flags.Token == "" { + if localFlag && tokenFlag == "" { return errors.New("server interaaction requires --token") } return nil @@ -80,8 +78,8 @@ func localOrToken(_ *cli.Context) error { func listPackages() ([]gpm.Package, error) { var pkgs []gpm.Package - if flags.Local { - db, err := database.Load(flags.Database) + if localFlag { + db, err := database.Load(databaseFlag) if err != nil { return pkgs, err } @@ -90,7 +88,7 @@ func listPackages() ([]gpm.Package, error) { return pkgs, err } } else { - client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + client := gpm.New(tokenFlag, gpm.WithServer(serverFlag)) info, err := client.Info(context.Background()) if err != nil { return pkgs, err diff --git a/internal/cli/flags.go b/internal/cli/flags.go new file mode 100644 index 0000000..ea0c67a --- /dev/null +++ b/internal/cli/flags.go @@ -0,0 +1,11 @@ +package cli + +var ( + serverFlag string + tokenFlag string + databaseFlag string + + localFlag bool + forceFlag bool + portFlag int +) diff --git a/cmd/get.go b/internal/cli/get.go similarity index 87% rename from cmd/get.go rename to internal/cli/get.go index ca4cb6b..421bec6 100644 --- a/cmd/get.go +++ b/internal/cli/get.go @@ -1,16 +1,15 @@ -package cmd +package cli import ( "context" - "github.com/rs/zerolog/log" "os" "os/exec" "strings" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -36,7 +35,7 @@ func doGet(ctx *cli.Context) error { pkgs = strings.Split(pkgsAnswer, "\n") } - client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + client := gpm.New(tokenFlag, gpm.WithServer(serverFlag)) for _, p := range pkgs { pkg, err := client.Get(context.Background(), p) if err != nil { diff --git a/cmd/list.go b/internal/cli/list.go similarity index 97% rename from cmd/list.go rename to internal/cli/list.go index 9d53d85..8302ca4 100644 --- a/cmd/list.go +++ b/internal/cli/list.go @@ -1,4 +1,4 @@ -package cmd +package cli import ( "fmt" diff --git a/cmd/remove.go b/internal/cli/remove.go similarity index 82% rename from cmd/remove.go rename to internal/cli/remove.go index b066dac..874c990 100644 --- a/cmd/remove.go +++ b/internal/cli/remove.go @@ -1,14 +1,13 @@ -package cmd +package cli import ( "context" - "github.com/rs/zerolog/log" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -48,8 +47,8 @@ func doRemove(_ *cli.Context) error { Import: pkgMap[pkgName].Import, } - if flags.Local { - db, err := database.Load(flags.Database) + if localFlag { + db, err := database.Load(databaseFlag) if err != nil { return err } @@ -57,7 +56,7 @@ func doRemove(_ *cli.Context) error { return err } } else { - client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + client := gpm.New(tokenFlag, gpm.WithServer(serverFlag)) if err := client.Remove(context.Background(), pkg); err != nil { return err } diff --git a/cmd/search.go b/internal/cli/search.go similarity index 95% rename from cmd/search.go rename to internal/cli/search.go index f3d9ff4..cb72767 100644 --- a/cmd/search.go +++ b/internal/cli/search.go @@ -1,10 +1,10 @@ -package cmd +package cli import ( - "github.com/rs/zerolog/log" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) diff --git a/cmd/server.go b/internal/cli/server.go similarity index 52% rename from cmd/server.go rename to internal/cli/server.go index 3b25448..21ac91d 100644 --- a/cmd/server.go +++ b/internal/cli/server.go @@ -1,15 +1,14 @@ -package cmd +package cli import ( "errors" "fmt" - "github.com/rs/zerolog/log" "net/http" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/router" + "go.jolheiser.com/gpm/internal/database" + "go.jolheiser.com/gpm/internal/router" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -24,24 +23,24 @@ var Server = cli.Command{ Usage: "Port to run the gpm server on", Value: 3333, EnvVars: []string{"GPM_PORT"}, - Destination: &flags.Port, + Destination: &portFlag, }, }, Action: doServer, } -func doServer(_ *cli.Context) error { - if flags.Token == "" { +func doServer(ctx *cli.Context) error { + if tokenFlag == "" { return errors.New("gpm server requires --token") } - db, err := database.Load(flags.Database) + db, err := database.Load(databaseFlag) if err != nil { - log.Fatal().Msgf("could not load database at %q: %v", flags.Database, err) + log.Fatal().Msgf("could not load database at %q: %v", databaseFlag, err) } - log.Info().Msgf("Running gpm server at http://localhost:%d", flags.Port) - if err := http.ListenAndServe(fmt.Sprintf(":%d", flags.Port), router.New(flags.Token, db)); err != nil { + log.Info().Msgf("Running gpm server at http://localhost:%d", portFlag) + if err := http.ListenAndServe(fmt.Sprintf(":%d", portFlag), router.New(tokenFlag, ctx.App.Version, db)); err != nil { return err } return nil diff --git a/cmd/update.go b/internal/cli/update.go similarity index 84% rename from cmd/update.go rename to internal/cli/update.go index 3639bce..e92949c 100644 --- a/cmd/update.go +++ b/internal/cli/update.go @@ -1,14 +1,13 @@ -package cmd +package cli import ( "context" - "github.com/rs/zerolog/log" - "go.jolheiser.com/gpm/cmd/flags" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" ) @@ -21,7 +20,7 @@ var Update = cli.Command{ Name: "local", Aliases: []string{"l"}, Usage: "local mode", - Destination: &flags.Local, + Destination: &localFlag, }, }, Before: localOrToken, @@ -66,8 +65,8 @@ func doUpdate(_ *cli.Context) error { Import: importPath, } - if flags.Local { - db, err := database.Load(flags.Database) + if localFlag { + db, err := database.Load(databaseFlag) if err != nil { return err } @@ -75,7 +74,7 @@ func doUpdate(_ *cli.Context) error { return err } } else { - client := gpm.New(flags.Token, gpm.WithServer(flags.Server)) + client := gpm.New(tokenFlag, gpm.WithServer(serverFlag)) if err := client.Update(context.Background(), pkg); err != nil { return err } diff --git a/database/database.go b/internal/database/database.go similarity index 98% rename from database/database.go rename to internal/database/database.go index d7827d0..10c138b 100644 --- a/database/database.go +++ b/internal/database/database.go @@ -6,7 +6,7 @@ import ( "os" "path/filepath" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" "go.etcd.io/bbolt" ) diff --git a/database/database_test.go b/internal/database/database_test.go similarity index 97% rename from database/database_test.go rename to internal/database/database_test.go index b6e1f92..950ba65 100644 --- a/database/database_test.go +++ b/internal/database/database_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" ) var db *Database @@ -33,7 +33,6 @@ func TestMain(m *testing.M) { } func TestPackage(t *testing.T) { - // Does not exist _, err := db.Package("test") if err == nil { diff --git a/router/router.go b/internal/router/router.go similarity index 87% rename from router/router.go rename to internal/router/router.go index 69424b7..85c20fb 100644 --- a/router/router.go +++ b/internal/router/router.go @@ -1,27 +1,25 @@ package router import ( - "github.com/go-chi/render" - "github.com/rs/zerolog/log" "net/http" "time" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "github.com/go-chi/render" + "github.com/rs/zerolog/log" ) -var Version = "develop" - -func New(token string, db *database.Database) *chi.Mux { +func New(token, version string, db *database.Database) *chi.Mux { r := chi.NewRouter() r.Use(middleware.RedirectSlashes) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(30 * time.Second)) - r.Get("/", handleHome(db)) + r.Get("/", handleHome(version, db)) r.Post("/", addUpdatePackage(db, token)) r.Patch("/", addUpdatePackage(db, token)) r.Delete("/", removePackage(db, token)) @@ -30,7 +28,7 @@ func New(token string, db *database.Database) *chi.Mux { return r } -func handleHome(db *database.Database) func(http.ResponseWriter, *http.Request) { +func handleHome(version string, db *database.Database) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { pkgs, err := db.Packages() if err != nil { @@ -39,7 +37,7 @@ func handleHome(db *database.Database) func(http.ResponseWriter, *http.Request) } render.JSON(w, r, gpm.Info{ - Version: Version, + Version: version, NumPackages: len(pkgs), Packages: pkgs, }) @@ -50,7 +48,6 @@ func getPackage(db *database.Database) func(http.ResponseWriter, *http.Request) return func(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") - pkg, err := db.Package(name) if err != nil { w.WriteHeader(http.StatusNotFound) diff --git a/router/router_test.go b/internal/router/router_test.go similarity index 95% rename from router/router_test.go rename to internal/router/router_test.go index 7ac3348..a4018c6 100644 --- a/router/router_test.go +++ b/internal/router/router_test.go @@ -2,14 +2,15 @@ package router import ( "context" - "github.com/rs/zerolog/log" "net/http/httptest" "os" "path/filepath" "testing" - "go.jolheiser.com/gpm/database" - "go.jolheiser.com/gpm/go-gpm" + "go.jolheiser.com/gpm" + "go.jolheiser.com/gpm/internal/database" + + "github.com/rs/zerolog/log" ) var ( @@ -31,7 +32,7 @@ func TestMain(m *testing.M) { log.Fatal().Msgf("could not load database at %q: %v", dbPath, err) } - server = httptest.NewServer(New(token, db)) + server = httptest.NewServer(New(token, "test", db)) code := m.Run() @@ -91,7 +92,7 @@ func checkInfo(t *testing.T, client *gpm.Client, numPackages int) { t.Logf("info should not return error: %v\n", err) t.Fail() } - if info.Version != Version || info.NumPackages != numPackages { + if info.Version != "test" || info.NumPackages != numPackages { t.Log("info did not match expected") t.Fail() } diff --git a/go-gpm/package.go b/package.go similarity index 100% rename from go-gpm/package.go rename to package.go diff --git a/tools.go b/tools.go deleted file mode 100644 index 048b2fa..0000000 --- a/tools.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build tools -// +build tools - -package main - -import ( - _ "github.com/rs/zerolog/cmd/lint" -) -- 2.41.0 From b26f95ab49d7d3efb879979bd490df348f38f42d Mon Sep 17 00:00:00 2001 From: jolheiser Date: Mon, 25 Jul 2022 04:43:32 +0000 Subject: [PATCH 9/9] Fix version (#11) Co-authored-by: jolheiser Reviewed-on: https://git.jojodev.com/jolheiser/gpm/pulls/11 --- .goreleaser.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index d195971..4b97984 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -7,7 +7,7 @@ builds: - darwin main: ./cmd/gpm ldflags: - - "-s -w -X go.jolheiser.com/gpm/cmd.Version={{.Version}}" + - "-s -w -X main.Version={{.Version}}" archives: - replacements: 386: i386 -- 2.41.0