diff options
| author | Fuwn <[email protected]> | 2024-10-11 00:36:28 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-10-11 00:36:28 -0700 |
| commit | 756d44530f1411f35a532318a377a6fa76efa090 (patch) | |
| tree | 08d548e0652c2cc3d24ae260d4bdc872e78b2741 /yae.go | |
| parent | a4645b34d92fef94350b570b8e99e8cc13195f41 (diff) | |
| download | yae-756d44530f1411f35a532318a377a6fa76efa090.tar.xz yae-756d44530f1411f35a532318a377a6fa76efa090.zip | |
feat(yae): git sources and remote git source updater
Diffstat (limited to 'yae.go')
| -rw-r--r-- | yae.go | 167 |
1 files changed, 126 insertions, 41 deletions
@@ -13,7 +13,7 @@ import ( func main() { sources := Sources{} - (&cli.App{ + if err := (&cli.App{ Name: "yae", Usage: "Nix Dependency Manager", Description: "Nix Dependency Manager", @@ -42,6 +42,7 @@ func main() { ExitErrHandler: func(c *cli.Context, err error) { if err != nil { fmt.Println(err) + os.Exit(1) } }, Suggest: true, @@ -68,6 +69,26 @@ func main() { Usage: "Unpack the source into the Nix Store", Value: true, }, + &cli.StringFlag{ + Name: "type", + Usage: "Source type", + Required: true, + Action: func(c *cli.Context, value string) error { + if value != "binary" && value != "git" { + return fmt.Errorf("invalid source type: must be 'binary' or 'git'") + } + + return nil + }, + }, + &cli.StringFlag{ + Name: "version", + Usage: "Source version used in identifying latest git source", + }, + &cli.StringFlag{ + Name: "tag-predicate", + Usage: "Git tag predicate used in identifying latest git source", + }, }, Action: func(c *cli.Context) error { if c.Args().Len() != 2 { @@ -78,17 +99,34 @@ func main() { return fmt.Errorf("source already exists") } - sha256, err := fetchSHA256(c.Args().Get(1), c.Bool("unpack")) + source := Source{ + Unpack: c.Bool("unpack"), + Type: c.String("type"), + } + version := c.String("version") + + if version != "" { + source.URITemplate = c.Args().Get(1) + source.Version = c.String("version") - if err != nil { + if strings.Contains(source.URITemplate, "{version}") { + source.URI = strings.Replace(source.URITemplate, "{version}", source.Version, 1) + } + } else { + source.URI = c.Args().Get(1) + } + + if source.Type == "git" && c.String("tag-predicate") != "" { + source.TagPredicate = c.String("tag-predicate") + } + + if sha256, err := fetchSHA256(source.URI, c.Bool("unpack")); err != nil { return err + } else { + source.SHA256 = sha256 } - if err = sources.Add(c.Args().Get(0), Source{ - URI: c.Args().Get(1), - SHA256: sha256, - Unpack: c.Bool("unpack"), - }); err != nil { + if err := sources.Add(c.Args().Get(0), source); err != nil { return err } @@ -127,53 +165,30 @@ func main() { Action: func(c *cli.Context) error { if c.Args().Len() == 0 { for key, value := range sources { - sha256, err := fetchSHA256(value.URI, value.Unpack) - - if err != nil { - return err - } - - if sha256 != value.SHA256 { - sources[key] = Source{ - URI: value.URI, - SHA256: sha256, - Unpack: value.Unpack, - } - - fmt.Println("updated hash for", key) - } - - if err = sources.Save(c.String("sources")); err != nil { + if err := updateSource(&sources, key, value); err != nil { return err } } } else { - if !sources.Exists(c.Args().Get(0)) { - return fmt.Errorf("source does not exist") - } + name := c.Args().Get(0) - sha256, err := fetchSHA256(sources[c.Args().Get(0)].URI, c.Bool("unpack")) - - if err != nil { + if err := updateSource(&sources, name, sources[name]); err != nil { return err } + } - sources[c.Args().Get(0)] = Source{ - URI: sources[c.Args().Get(0)].URI, - SHA256: sha256, - Unpack: c.Bool("unpack"), - } - - if err = sources.Save(c.String("sources")); err != nil { - return err - } + if err := sources.Save(c.String("sources")); err != nil { + return err } return nil }, }, }, - }).Run(os.Args) + }).Run(os.Args); err != nil { + fmt.Println(err) + os.Exit(1) + } } func fetchSHA256(uri string, unpack bool) (string, error) { @@ -204,3 +219,73 @@ func commandOutput(name string, args ...string) (string, error) { return string(out), err } + +func fetchLatestGitTag(source Source) (string, error) { + if source.Type == "git" { + repository := "https://github.com/" + strings.Split(source.URI, "/")[3] + "/" + strings.Split(source.URI, "/")[4] + remotes, err := commandOutput("git", "ls-remote", "--tags", repository) + + if err != nil { + return "", err + } + + refs := strings.Split(remotes, "\n") + var latest string + + if source.TagPredicate == "" { + latest = refs[len(refs)-2] + } else { + for i := len(refs) - 2; i >= 0; i-- { + if strings.Contains(refs[i], source.TagPredicate) { + latest = strings.Split(refs[i], "/")[2] + + break + } + } + } + + return latest, nil + } + + return "", fmt.Errorf("source is not a git repository") +} + +func updateSource(sources *Sources, name string, source Source) error { + if !sources.Exists(name) { + return fmt.Errorf("source does not exist") + } + + if source.Type == "git" { + tag, err := fetchLatestGitTag(source) + + if err != nil { + return err + } + + if tag != source.Version { + fmt.Println("updated version for", name, "from", source.Version, "to", tag) + + source.Version = tag + + if strings.Contains(source.URITemplate, "{version}") { + source.URI = strings.Replace(source.URITemplate, "{version}", source.Version, 1) + } + } + } + + sha256, err := fetchSHA256(source.URI, source.Unpack) + + if err != nil { + return err + } + + if sha256 != source.SHA256 { + fmt.Println("updated hash for", name, "from", source.SHA256, "to", sha256) + + source.SHA256 = sha256 + } + + (*sources)[name] = source + + return nil +} |