aboutsummaryrefslogtreecommitdiff
path: root/internal/yae/source.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/yae/source.go')
-rw-r--r--internal/yae/source.go124
1 files changed, 124 insertions, 0 deletions
diff --git a/internal/yae/source.go b/internal/yae/source.go
new file mode 100644
index 0000000..185aba7
--- /dev/null
+++ b/internal/yae/source.go
@@ -0,0 +1,124 @@
+package yae
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/charmbracelet/log"
+)
+
+type Source struct {
+ URL string `json:"url"`
+ SHA256 string `json:"sha256"`
+ Unpack bool `json:"unpack"`
+ Type string `json:"type"`
+ Version string `json:"version,omitempty"`
+ URLTemplate string `json:"url_template,omitempty"`
+ TagPredicate string `json:"tag_predicate,omitempty"`
+ TrimTagPrefix string `json:"trim_tag_prefix,omitempty"`
+ Pinned bool `json:"pinned,omitempty"`
+ Force bool `json:"force,omitempty"`
+}
+
+func (source *Source) Update(sources *Sources, name string, force bool, forcePinned bool) (bool, error) {
+ log.Infof("checking %s", name)
+
+ updated := false
+
+ if !sources.Exists(name) {
+ log.Warnf("skipped %s: source does not exist", name)
+
+ return updated, nil
+ }
+
+ if source.Pinned && !forcePinned {
+ log.Infof("skipped %s: source is pinned", name)
+
+ return updated, nil
+ }
+
+ if source.Type == "git" {
+ log.Debugf("checking %s: remote git tag", name)
+
+ tag, err := source.fetchLatestGitTag()
+
+ if err != nil {
+ return updated, err
+ }
+
+ if tag != source.Version || force || source.Force {
+ if tag != source.Version {
+ log.Infof("bumped %s: %s -> %s", name, source.Version, tag)
+ }
+
+ if tag != source.Version {
+ updated = true
+ }
+
+ source.Version = tag
+
+ if strings.Contains(source.URLTemplate, "{version}") {
+ source.URL = strings.ReplaceAll(source.URLTemplate, "{version}", source.Version)
+
+ log.Debugf("patched %s: substituted url template", name)
+ }
+ } else {
+ log.Infof("skipped %s: version remains unchanged", name)
+
+ return updated, nil
+ }
+ }
+
+ log.Debugf("checking %s: sha256", name)
+
+ sha256, err := FetchSHA256(source.URL, source.Unpack)
+
+ if err != nil {
+ return updated, err
+ }
+
+ if sha256 != source.SHA256 {
+ log.Infof("rehashed %s: %s -> %s", name, source.SHA256, sha256)
+
+ source.SHA256 = sha256
+ updated = true
+ }
+
+ (*sources)[name] = *source
+
+ return updated, nil
+}
+
+func (source *Source) fetchLatestGitTag() (string, error) {
+ if source.Type == "git" {
+ repository := "https://github.com/" + strings.Split(source.URL, "/")[3] + "/" + strings.Split(source.URL, "/")[4]
+ remotes, err := command("bash", false, "-c", fmt.Sprintf("git ls-remote %s | awk -F'/' '{print $NF}' | sort -V", 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 = refs[i]
+
+ break
+ }
+ }
+ }
+
+ if source.TrimTagPrefix != "" {
+ latest = strings.TrimPrefix(latest, source.TrimTagPrefix)
+ }
+
+ return latest, nil
+ }
+
+ return "", fmt.Errorf("source is not a git repository")
+}