github.com/abdfnx/gh-api@v0.0.0-20210414084727-f5432eec23b8/pkg/cmd/factory/remote_resolver.go (about) 1 package factory 2 3 import ( 4 "errors" 5 "net/url" 6 "sort" 7 8 "github.com/abdfnx/gh-api/context" 9 "github.com/abdfnx/gh-api/git" 10 "github.com/abdfnx/gh-api/internal/config" 11 "github.com/abdfnx/gh-api/internal/ghinstance" 12 "github.com/abdfnx/gh-api/pkg/set" 13 ) 14 15 const GH_HOST = "GH_HOST" 16 17 type remoteResolver struct { 18 readRemotes func() (git.RemoteSet, error) 19 getConfig func() (config.Config, error) 20 urlTranslator func(*url.URL) *url.URL 21 } 22 23 func (rr *remoteResolver) Resolver() func() (context.Remotes, error) { 24 var cachedRemotes context.Remotes 25 var remotesError error 26 27 return func() (context.Remotes, error) { 28 if cachedRemotes != nil || remotesError != nil { 29 return cachedRemotes, remotesError 30 } 31 32 gitRemotes, err := rr.readRemotes() 33 if err != nil { 34 remotesError = err 35 return nil, err 36 } 37 if len(gitRemotes) == 0 { 38 remotesError = errors.New("no git remotes found") 39 return nil, remotesError 40 } 41 42 sshTranslate := rr.urlTranslator 43 if sshTranslate == nil { 44 sshTranslate = git.ParseSSHConfig().Translator() 45 } 46 resolvedRemotes := context.TranslateRemotes(gitRemotes, sshTranslate) 47 48 cfg, err := rr.getConfig() 49 if err != nil { 50 return nil, err 51 } 52 53 authedHosts, err := cfg.Hosts() 54 if err != nil { 55 return nil, err 56 } 57 defaultHost, src, err := cfg.DefaultHostWithSource() 58 if err != nil { 59 return nil, err 60 } 61 // Use set to dedupe list of hosts 62 hostsSet := set.NewStringSet() 63 hostsSet.AddValues(authedHosts) 64 hostsSet.AddValues([]string{defaultHost, ghinstance.Default()}) 65 hosts := hostsSet.ToSlice() 66 67 // Sort remotes 68 sort.Sort(resolvedRemotes) 69 70 // Filter remotes by hosts 71 cachedRemotes := resolvedRemotes.FilterByHosts(hosts) 72 73 // Filter again by default host if one is set 74 // For config file default host fallback to cachedRemotes if none match 75 // For enviornment default host (GH_HOST) do not fallback to cachedRemotes if none match 76 if src != "" { 77 filteredRemotes := cachedRemotes.FilterByHosts([]string{defaultHost}) 78 if src == GH_HOST || len(filteredRemotes) > 0 { 79 cachedRemotes = filteredRemotes 80 } 81 } 82 83 if len(cachedRemotes) == 0 { 84 if src == GH_HOST { 85 remotesError = errors.New("none of the git remotes configured for this repository correspond to the GH_HOST environment variable. Try adding a matching remote or unsetting the variable.") 86 } else { 87 remotesError = errors.New("none of the git remotes configured for this repository point to a known GitHub host. To tell gh about a new GitHub host, please use `gh auth login`") 88 } 89 return nil, remotesError 90 } 91 92 return cachedRemotes, nil 93 } 94 }