github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/context/remote.go (about) 1 package context 2 3 import ( 4 "fmt" 5 "net/url" 6 "strings" 7 8 "github.com/ungtb10d/cli/v2/git" 9 "github.com/ungtb10d/cli/v2/internal/ghrepo" 10 ) 11 12 // Remotes represents a set of git remotes 13 type Remotes []*Remote 14 15 // FindByName returns the first Remote whose name matches the list 16 func (r Remotes) FindByName(names ...string) (*Remote, error) { 17 for _, name := range names { 18 for _, rem := range r { 19 if rem.Name == name || name == "*" { 20 return rem, nil 21 } 22 } 23 } 24 return nil, fmt.Errorf("no GitHub remotes found") 25 } 26 27 // FindByRepo returns the first Remote that points to a specific GitHub repository 28 func (r Remotes) FindByRepo(owner, name string) (*Remote, error) { 29 for _, rem := range r { 30 if strings.EqualFold(rem.RepoOwner(), owner) && strings.EqualFold(rem.RepoName(), name) { 31 return rem, nil 32 } 33 } 34 return nil, fmt.Errorf("no matching remote found") 35 } 36 37 func remoteNameSortScore(name string) int { 38 switch strings.ToLower(name) { 39 case "upstream": 40 return 3 41 case "github": 42 return 2 43 case "origin": 44 return 1 45 default: 46 return 0 47 } 48 } 49 50 // https://golang.org/pkg/sort/#Interface 51 func (r Remotes) Len() int { return len(r) } 52 func (r Remotes) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 53 func (r Remotes) Less(i, j int) bool { 54 return remoteNameSortScore(r[i].Name) > remoteNameSortScore(r[j].Name) 55 } 56 57 // Filter remotes by given hostnames, maintains original order 58 func (r Remotes) FilterByHosts(hosts []string) Remotes { 59 filtered := make(Remotes, 0) 60 for _, rr := range r { 61 for _, host := range hosts { 62 if strings.EqualFold(rr.RepoHost(), host) { 63 filtered = append(filtered, rr) 64 break 65 } 66 } 67 } 68 return filtered 69 } 70 71 // Remote represents a git remote mapped to a GitHub repository 72 type Remote struct { 73 *git.Remote 74 Repo ghrepo.Interface 75 } 76 77 // RepoName is the name of the GitHub repository 78 func (r Remote) RepoName() string { 79 return r.Repo.RepoName() 80 } 81 82 // RepoOwner is the name of the GitHub account that owns the repo 83 func (r Remote) RepoOwner() string { 84 return r.Repo.RepoOwner() 85 } 86 87 // RepoHost is the GitHub hostname that the remote points to 88 func (r Remote) RepoHost() string { 89 return r.Repo.RepoHost() 90 } 91 92 type Translator interface { 93 Translate(*url.URL) *url.URL 94 } 95 96 func TranslateRemotes(gitRemotes git.RemoteSet, translator Translator) (remotes Remotes) { 97 for _, r := range gitRemotes { 98 var repo ghrepo.Interface 99 if r.FetchURL != nil { 100 repo, _ = ghrepo.FromURL(translator.Translate(r.FetchURL)) 101 } 102 if r.PushURL != nil && repo == nil { 103 repo, _ = ghrepo.FromURL(translator.Translate(r.PushURL)) 104 } 105 if repo == nil { 106 continue 107 } 108 remotes = append(remotes, &Remote{ 109 Remote: r, 110 Repo: repo, 111 }) 112 } 113 return 114 }