From a9d92b3074dbc541fc4bc0db2fb55d71840068b8 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Sat, 14 Jan 2023 00:02:25 -0600 Subject: [PATCH] feat: working version Signed-off-by: jolheiser --- disk/disk.go | 23 +++++++-------- forge/forge.go | 7 +++-- main.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++--- meta/meta.go | 32 +++++++++++---------- shell/nu.go | 25 +++++++++++++++++ 5 files changed, 130 insertions(+), 33 deletions(-) create mode 100644 shell/nu.go diff --git a/disk/disk.go b/disk/disk.go index c0909c6..9803168 100644 --- a/disk/disk.go +++ b/disk/disk.go @@ -7,7 +7,6 @@ import ( "net/http" "os" "path/filepath" - "regexp" "runtime" "strings" @@ -17,13 +16,7 @@ import ( "github.com/mholt/archiver/v3" ) -var ( - amd64Re = regexp.MustCompile(`amd64|x86_64|64`) - linuxRe = regexp.MustCompile(`linux|linux64`) - windowsRe = regexp.MustCompile(`windows|win64`) -) - -func Install(asset forge.Asset) error { +func Install(name string, asset forge.Asset) error { tmp, err := os.MkdirTemp(os.TempDir(), "eget-*") if err != nil { return err @@ -49,7 +42,7 @@ func Install(asset forge.Asset) error { return err } - if err := unpack(tmpDest, asset.Name); err != nil { + if err := unpack(tmpDest, name); err != nil { return fmt.Errorf("could not unpack download: %w", err) } @@ -57,7 +50,7 @@ func Install(asset forge.Asset) error { } func unpack(src, name string) error { - dest := filepath.Join(xdg.DataHome, "eget", name) + dest := Path(name) if err := os.MkdirAll(dest, os.ModePerm); err != nil { return fmt.Errorf("could not make all dest dirs: %w", err) } @@ -68,7 +61,11 @@ func unpack(src, name string) error { uaIface, err := archiver.ByExtension(src) if err != nil { if filepath.Ext(src) == binExt { - return os.Rename(src, filepath.Join(dest, name+binExt)) + dest = filepath.Join(dest, name+binExt) + if err := os.Rename(src, dest); err != nil { + return err + } + return os.Chmod(dest, 0o755) } return err } @@ -120,3 +117,7 @@ func moveDir(src, dest string) error { return os.Rename(walkPath, destPath) }) } + +func Path(name string) string { + return filepath.Join(xdg.DataHome, "eget", name) +} diff --git a/forge/forge.go b/forge/forge.go index 40c73e1..4a092a1 100644 --- a/forge/forge.go +++ b/forge/forge.go @@ -10,9 +10,9 @@ import ( ) var ( - amd64Re = regexp.MustCompile(`amd64|x86_64|64`) - linuxRe = regexp.MustCompile(`linux|linux64`) - windowsRe = regexp.MustCompile(`windows|win64`) + amd64Re = regexp.MustCompile(`amd64|x86_64|64-bit|[^m]64`) + linuxRe = regexp.MustCompile(`linux`) + windowsRe = regexp.MustCompile(`windows|\Awin`) ) type Release struct { @@ -66,6 +66,7 @@ func Latest(f Forger) (Asset, error) { if amd64Re.MatchString(a.Name) && re.MatchString(a.Name) { fmt.Printf("found %q\n", a.Name) asset = a + break } } diff --git a/main.go b/main.go index 6f7d6c3..47f9bf8 100644 --- a/main.go +++ b/main.go @@ -1,25 +1,52 @@ package main import ( + "flag" "fmt" "os" "strings" "go.jolheiser.com/eget/disk" "go.jolheiser.com/eget/forge" + "go.jolheiser.com/eget/meta" + "go.jolheiser.com/eget/shell" ) var Version = "develop" func main() { - if len(os.Args) < 2 { - fmt.Println("eget ") + fs := flag.NewFlagSet("eget", flag.ExitOnError) + fs.Usage = func() { + fmt.Fprintln(fs.Output(), "eget ") + fs.PrintDefaults() + } + updateFlag := fs.Bool("update", false, "Update package") + fs.BoolVar(updateFlag, "u", *updateFlag, "--update") + deleteFlag := flag.Bool("delete", false, "Delete package") + fs.BoolVar(deleteFlag, "d", *deleteFlag, "--delete") + nuFlag := fs.Bool("nu", false, "Write out Nu environment") + if err := fs.Parse(os.Args[1:]); err != nil { + fs.Usage() + return + } + + if *nuFlag { + nu, err := shell.Nu() + if err != nil { + panic(err) + } + fmt.Println(nu) + return + } + + if fs.NArg() < 1 { + fs.Usage() return } var f forge.Forger var err error - uri := os.Args[1] + uri := fs.Arg(0) f, err = forge.NewGitea(uri) if strings.HasPrefix(uri, "github") { @@ -29,12 +56,53 @@ func main() { panic(err) } + name := uriName(uri) + if *deleteFlag { + if err := os.RemoveAll(disk.Path(name)); err != nil { + panic(err) + } + if err := meta.Remove(name); err != nil { + panic(err) + } + fmt.Printf("removed %q\n", name) + return + } + asset, err := forge.Latest(f) if err != nil { panic(err) } - if err := disk.Install(asset); err != nil { + if *updateFlag { + m, err := meta.Read() + if err != nil { + panic(err) + } + if strings.EqualFold(asset.Name, m.Packages[name]) { + fmt.Printf("%q is up-to-date\n", name) + return + } + if err := os.RemoveAll(disk.Path(name)); err != nil { + panic(err) + } + } + + if err := disk.Install(name, asset); err != nil { panic(err) } + + if err := meta.Upsert(name, asset.Name); err != nil { + panic(err) + } + + verb := "installed" + if *updateFlag { + verb = "updated" + } + fmt.Printf("%s %q\n", verb, uri) +} + +func uriName(uri string) string { + parts := strings.FieldsFunc(uri, func(r rune) bool { return r == '/' }) + return parts[len(parts)-1] } diff --git a/meta/meta.go b/meta/meta.go index 331bdb4..f67fc8e 100644 --- a/meta/meta.go +++ b/meta/meta.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "io/fs" "os" "strings" @@ -11,36 +12,37 @@ import ( ) type Meta struct { - Packages []Package `json:"packages"` + Packages map[string]string `json:"packages"` } -type Package struct { - Name string `json:"name"` - Version string `json:"version"` -} - -func Add(pkg Package) error { +func Upsert(name, version string) error { m, err := Read() if err != nil { return err } - for _, p := range m.Packages { - if strings.EqualFold(pkg.Name, p.Name) { - return errors.New("package already exists locally") + for n := range m.Packages { + if strings.EqualFold(n, name) { + m.Packages[n] = version + return save(m) } } - m.Packages = append(m.Packages, pkg) + m.Packages[name] = version return save(m) } func Read() (Meta, error) { - var m Meta + m := Meta{ + Packages: make(map[string]string), + } fp, err := metaPath() if err != nil { return m, fmt.Errorf("could not get meta file: %w", err) } fi, err := os.Open(fp) if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return m, json.Unmarshal([]byte(`{}`), &m) + } return m, fmt.Errorf("could not open meta file: %w", err) } defer fi.Close() @@ -56,9 +58,9 @@ func Remove(name string) error { if err != nil { return err } - for idx, p := range m.Packages { - if strings.EqualFold(name, p.Name) { - m.Packages = append(m.Packages[:idx], m.Packages[idx+1:]...) + for n := range m.Packages { + if strings.EqualFold(n, name) { + delete(m.Packages, name) return save(m) } } diff --git a/shell/nu.go b/shell/nu.go new file mode 100644 index 0000000..e498851 --- /dev/null +++ b/shell/nu.go @@ -0,0 +1,25 @@ +package shell + +import ( + "fmt" + "strings" + + "go.jolheiser.com/eget/disk" + "go.jolheiser.com/eget/meta" +) + +func Nu() (string, error) { + tmpl := "let-env PATH = ($env.PATH | append '%s')\n" + m, err := meta.Read() + if err != nil { + return "", err + } + + var out strings.Builder + out.WriteString("# managed by eget; DO NOT EDIT\n\n") + for name := range m.Packages { + out.WriteString(fmt.Sprintf(tmpl, disk.Path(name))) + } + + return out.String(), nil +}