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