github.com/sudo-bmitch/version-bump@v0.0.0-20240503123857-70b0e3f646dd/internal/source/git.go (about) 1 package source 2 3 import ( 4 "fmt" 5 6 "github.com/go-git/go-git/v5" 7 gitConfig "github.com/go-git/go-git/v5/config" 8 "github.com/go-git/go-git/v5/plumbing" 9 "github.com/go-git/go-git/v5/storage/memory" 10 "github.com/sudo-bmitch/version-bump/internal/config" 11 ) 12 13 const () 14 15 type gitSource struct { 16 conf config.Source 17 } 18 19 func newGit(conf config.Source) Source { 20 return gitSource{conf: conf} 21 } 22 23 func (g gitSource) Get(data config.SourceTmplData) (string, error) { 24 confExp, err := g.conf.ExpandTemplate(data) 25 if err != nil { 26 return "", fmt.Errorf("failed to expand template: %w", err) 27 } 28 if _, ok := confExp.Args["url"]; !ok { 29 return "", fmt.Errorf("url argument is required") 30 } 31 32 if confExp.Args["type"] == "tag" { 33 return g.getTag(confExp) 34 } 35 return g.getCommit(confExp) 36 } 37 38 func (g gitSource) getRefs(confExp config.Source) ([]*plumbing.Reference, error) { 39 rem := git.NewRemote(memory.NewStorage(), &gitConfig.RemoteConfig{ 40 Name: "origin", 41 URLs: []string{confExp.Args["url"]}, 42 }) 43 return rem.List(&git.ListOptions{ 44 PeelingOption: git.AppendPeeled, 45 }) 46 } 47 48 func (g gitSource) getCommit(confExp config.Source) (string, error) { 49 refs, err := g.getRefs(confExp) 50 if err != nil { 51 return "", err 52 } 53 verData := VersionTmplData{ 54 VerMap: map[string]string{}, 55 } 56 for _, ref := range refs { 57 verData.VerMap[ref.Name().Short()] = ref.Hash().String() 58 } 59 // loop over the map entries to prefer the peeled hash (underlying commit vs signed/annotated tag hash) 60 for k := range verData.VerMap { 61 if _, ok := verData.VerMap[k+"^{}"]; ok { 62 verData.VerMap[k] = verData.VerMap[k+"^{}"] 63 delete(verData.VerMap, k+"^{}") 64 } 65 } 66 if len(verData.VerMap) == 0 { 67 return "", fmt.Errorf("ref %s not found on %s", confExp.Args["ref"], confExp.Args["url"]) 68 } 69 return procResult(confExp, verData) 70 } 71 72 func (g gitSource) getTag(confExp config.Source) (string, error) { 73 refs, err := g.getRefs(confExp) 74 if err != nil { 75 return "", err 76 } 77 verData := VersionTmplData{ 78 VerMap: map[string]string{}, 79 } 80 // find matching tags 81 for _, ref := range refs { 82 verData.VerMap[ref.Name().Short()] = ref.Name().Short() 83 } 84 if len(verData.VerMap) == 0 { 85 return "", fmt.Errorf("no matching tags found") 86 } 87 return procResult(confExp, verData) 88 } 89 90 func (g gitSource) Key(data config.SourceTmplData) (string, error) { 91 confExp, err := g.conf.ExpandTemplate(data) 92 if err != nil { 93 return "", fmt.Errorf("failed to expand template: %w", err) 94 } 95 return confExp.Key, nil 96 }