parent
41750c0200
commit
a0a1189921
2
Makefile
2
Makefile
|
@ -14,7 +14,7 @@ else
|
|||
LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||
endif
|
||||
|
||||
LDFLAGS := $(LDFLAGS) -X "main.Version=$(LONG_VERSION)"
|
||||
LDFLAGS := $(LDFLAGS) -X "gitea.com/jolheiser/gpm/modules/config.Version=$(LONG_VERSION)"
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
|
|
15
README.md
15
README.md
|
@ -16,16 +16,19 @@ Using either a GPM server or local config, I can instead `gpm get cli` which fin
|
|||
* `add` - Add a local package
|
||||
* `remove` - Remove a local package
|
||||
* `list` - List local packages
|
||||
* `config` - Change local configuration (GPM server)
|
||||
* `config` - Change local configuration
|
||||
* `export` - Export local packages to JSON
|
||||
* `import` - Import JSON to local packages
|
||||
* `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)
|
||||
* `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)
|
||||
* `server` - Start a gpm server
|
||||
|
||||
|
||||
### Server
|
||||
|
||||
If GPM doesn't find a package locally, it can call out to a configurable [gpm server](https://gitea.com/jolheiser/gpm-server) to find a package there.
|
||||
If GPM doesn't find a package locally, it can call out to a configurable gpm server to find a package there instead.
|
||||
This makes it much simpler to have a central library of packages rather than exporting and importing between environments.
|
||||
|
||||
The `import` and `export` commands should work between the CLI and server for easy transitions.
|
||||
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!
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
"regexp"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -17,7 +17,7 @@ var Config = cli.Command{
|
|||
func doConfig(ctx *cli.Context) error {
|
||||
urlQuestion := &survey.Input{
|
||||
Message: "gpm URL",
|
||||
Default: "gpm.jolheiser.com",
|
||||
Default: config.GPMURL,
|
||||
}
|
||||
var urlAnswer string
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
16
cmd/get.go
16
cmd/get.go
|
@ -3,8 +3,8 @@ package cmd
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
"io/ioutil"
|
||||
|
@ -49,7 +49,7 @@ func doGet(ctx *cli.Context) error {
|
|||
for _, pkg := range pkgs {
|
||||
var url string
|
||||
if u, ok := local[pkg]; ok && !ctx.Bool("ignore-local") {
|
||||
url = u
|
||||
url = u.Import
|
||||
} else if !ctx.Bool("offline") {
|
||||
u, err := queryServer(ctx.String("url"), pkg)
|
||||
if err != nil {
|
||||
|
@ -73,12 +73,8 @@ func doGet(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type response struct {
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func queryServer(server, name string) (string, error) {
|
||||
endpoint := fmt.Sprintf("%s/%s", server, name)
|
||||
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)
|
||||
|
@ -94,12 +90,12 @@ func queryServer(server, name string) (string, error) {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var data response
|
||||
if err := json.Unmarshal(body, &data); err != nil {
|
||||
var pkg config.Package
|
||||
if err := json.Unmarshal(body, &pkg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return data.URL, nil
|
||||
return pkg.Import, nil
|
||||
}
|
||||
|
||||
func goGet(url string) error {
|
||||
|
|
|
@ -3,10 +3,12 @@ package cmd
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var Import = cli.Command{
|
||||
|
@ -23,26 +25,45 @@ var Import = cli.Command{
|
|||
}
|
||||
|
||||
func doImport(ctx *cli.Context) error {
|
||||
files := ctx.Args().Slice()
|
||||
if len(files) == 0 {
|
||||
return errors.New("must provide a list of JSON files to import from")
|
||||
if ctx.NArg() == 0 {
|
||||
return errors.New("must point to either a JSON file or gpm server export endpoint")
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
body, err := ioutil.ReadFile(file)
|
||||
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
|
||||
var err error
|
||||
if isJSON {
|
||||
data, err = ioutil.ReadFile(arg)
|
||||
if err != nil {
|
||||
beaver.Error(err)
|
||||
continue
|
||||
return err
|
||||
}
|
||||
} else if isHTTP {
|
||||
resp, err := http.Get(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg config.Config
|
||||
if err := json.Unmarshal(body, &cfg); err != nil {
|
||||
beaver.Error(err)
|
||||
continue
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.AddPackages(ctx.Bool("force"), cfg.Packages...)
|
||||
defer resp.Body.Close()
|
||||
|
||||
}
|
||||
|
||||
var cfg config.Config
|
||||
if err := json.Unmarshal(data, &cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
config.AddPackages(ctx.Bool("force"), cfg.Packages...)
|
||||
|
||||
if err := config.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.com/gpm/gpm/modules/config"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
"strings"
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/router"
|
||||
"github.com/urfave/cli/v2"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var Server = cli.Command{
|
||||
Name: "server",
|
||||
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",
|
||||
},
|
||||
},
|
||||
Action: doServer,
|
||||
}
|
||||
|
||||
func doServer(ctx *cli.Context) error {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
3
go.mod
3
go.mod
|
@ -1,4 +1,4 @@
|
|||
module gitea.com/gpm/gpm
|
||||
module gitea.com/jolheiser/gpm
|
||||
|
||||
go 1.13
|
||||
|
||||
|
@ -6,6 +6,7 @@ require (
|
|||
gitea.com/jolheiser/beaver v1.0.0
|
||||
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
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -10,6 +10,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/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/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=
|
||||
|
|
8
main.go
8
main.go
|
@ -1,14 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"gitea.com/gpm/gpm/cmd"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/cmd"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/urfave/cli/v2"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Version = "develop"
|
||||
|
||||
func main() {
|
||||
|
||||
// config loads on init
|
||||
|
@ -16,7 +15,7 @@ func main() {
|
|||
app := cli.NewApp()
|
||||
app.Name = "gpm"
|
||||
app.Usage = "Go Package Manager"
|
||||
app.Version = Version
|
||||
app.Version = config.Version
|
||||
app.Commands = []*cli.Command{
|
||||
&cmd.Add,
|
||||
&cmd.Remove,
|
||||
|
@ -25,6 +24,7 @@ func main() {
|
|||
&cmd.Import,
|
||||
&cmd.Export,
|
||||
&cmd.Config,
|
||||
&cmd.Server,
|
||||
}
|
||||
app.Flags = cmd.Flags
|
||||
app.EnableBashCompletion = true
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
var (
|
||||
configPath string
|
||||
cfg *Config
|
||||
Version = "develop"
|
||||
|
||||
// Config items
|
||||
|
||||
|
@ -42,16 +43,16 @@ func init() {
|
|||
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(path.Dir(configPath), os.ModePerm); err != nil {
|
||||
beaver.Fatalf("could not create Sip home: %v", err)
|
||||
beaver.Fatalf("could not create gpm home: %v", err)
|
||||
}
|
||||
|
||||
if _, err := os.Create(configPath); err != nil {
|
||||
beaver.Fatalf("could not create Sip config: %v", err)
|
||||
beaver.Fatalf("could not create gpm config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := toml.DecodeFile(configPath, &cfg); err != nil {
|
||||
beaver.Fatalf("could not decode Sip config: %v", err)
|
||||
beaver.Fatalf("could not decode gpm config: %v", err)
|
||||
}
|
||||
|
||||
dupe := make(map[string]bool)
|
||||
|
@ -85,14 +86,14 @@ func Save() error {
|
|||
}
|
||||
|
||||
func Export() (string, error) {
|
||||
data, err := json.Marshal(cfg)
|
||||
data, err := json.Marshal(Packages)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
func PackageMap() map[string]string {
|
||||
pkgs := make(map[string]string)
|
||||
func PackageMap() map[string]Package {
|
||||
pkgs := make(map[string]Package)
|
||||
for _, pkg := range Packages {
|
||||
pkgs[pkg.Name] = pkg.Import
|
||||
pkgs[pkg.Name] = pkg
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gitea.com/jolheiser/beaver"
|
||||
"gitea.com/jolheiser/gpm/modules/config"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"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("/status", handleStatus)
|
||||
r.Get("/export", handleExport)
|
||||
r.Get("/package/{name}", handlePackage)
|
||||
|
||||
cache = config.PackageMap()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func handleStatus(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("{}"))
|
||||
}
|
Loading…
Reference in New Issue