Fix set-default interactive not showing all remotes (#6969)

This commit is contained in:
Des Preston 2023-02-07 18:11:38 -05:00 committed by GitHub
parent 801c38a24f
commit 94fe6c7764
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 10 deletions

View file

@ -11,9 +11,9 @@ import (
"github.com/cli/cli/v2/pkg/iostreams"
)
// cap the number of git remotes looked up, since the user might have an
// unusually large number of git remotes
const maxRemotesForLookup = 5
// Cap the number of git remotes to look up, since the user might have an
// unusually large number of git remotes.
const defaultRemotesForLookup = 5
func ResolveRemotesToRepos(remotes Remotes, client *api.Client, base string) (*ResolvedRemotes, error) {
sort.Stable(remotes)
@ -36,11 +36,11 @@ func ResolveRemotesToRepos(remotes Remotes, client *api.Client, base string) (*R
return result, nil
}
func resolveNetwork(result *ResolvedRemotes) error {
func resolveNetwork(result *ResolvedRemotes, remotesForLookup int) error {
var repos []ghrepo.Interface
for _, r := range result.remotes {
repos = append(repos, r)
if len(repos) == maxRemotesForLookup {
if len(repos) == remotesForLookup {
break
}
}
@ -84,7 +84,7 @@ func (r *ResolvedRemotes) BaseRepo(io *iostreams.IOStreams) (ghrepo.Interface, e
return r.remotes[0], nil
}
repos, err := r.NetworkRepos()
repos, err := r.NetworkRepos(defaultRemotesForLookup)
if err != nil {
return nil, err
}
@ -109,7 +109,7 @@ func (r *ResolvedRemotes) BaseRepo(io *iostreams.IOStreams) (ghrepo.Interface, e
func (r *ResolvedRemotes) HeadRepos() ([]*api.Repository, error) {
if r.network == nil {
err := resolveNetwork(r)
err := resolveNetwork(r, defaultRemotesForLookup)
if err != nil {
return nil, err
}
@ -124,9 +124,11 @@ func (r *ResolvedRemotes) HeadRepos() ([]*api.Repository, error) {
return results, nil
}
func (r *ResolvedRemotes) NetworkRepos() ([]*api.Repository, error) {
// NetworkRepos fetches info about remotes for the network of repos.
// Pass a value of 0 to fetch info on all remotes.
func (r *ResolvedRemotes) NetworkRepos(remotesForLookup int) ([]*api.Repository, error) {
if r.network == nil {
err := resolveNetwork(r)
err := resolveNetwork(r, remotesForLookup)
if err != nil {
return nil, err
}

View file

@ -160,7 +160,7 @@ func setDefaultRun(opts *SetDefaultOptions) error {
return err
}
knownRepos, err := resolvedRemotes.NetworkRepos()
knownRepos, err := resolvedRemotes.NetworkRepos(0)
if err != nil {
return err
}

View file

@ -122,6 +122,9 @@ func TestDefaultRun(t *testing.T) {
repo1, _ := ghrepo.FromFullName("OWNER/REPO")
repo2, _ := ghrepo.FromFullName("OWNER2/REPO2")
repo3, _ := ghrepo.FromFullName("OWNER3/REPO3")
repo4, _ := ghrepo.FromFullName("OWNER4/REPO4")
repo5, _ := ghrepo.FromFullName("OWNER5/REPO5")
repo6, _ := ghrepo.FromFullName("OWNER6/REPO6")
tests := []struct {
name string
@ -392,6 +395,55 @@ func TestDefaultRun(t *testing.T) {
},
wantStdout: "Found only one known remote repo, OWNER2/REPO2 on github.com.\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n",
},
{
name: "interactive mode more than five remotes",
tty: true,
opts: SetDefaultOptions{},
remotes: []*context.Remote{
{Remote: &git.Remote{Name: "origin"}, Repo: repo1},
{Remote: &git.Remote{Name: "upstream"}, Repo: repo2},
{Remote: &git.Remote{Name: "other1"}, Repo: repo3},
{Remote: &git.Remote{Name: "other2"}, Repo: repo4},
{Remote: &git.Remote{Name: "other3"}, Repo: repo5},
{Remote: &git.Remote{Name: "other4"}, Repo: repo6},
},
httpStubs: func(reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`query RepositoryNetwork\b`),
httpmock.GraphQLQuery(`{"data":{
"repo_000":{"name":"REPO","owner":{"login":"OWNER"}},
"repo_001":{"name":"REPO2","owner":{"login":"OWNER2"}},
"repo_002":{"name":"REPO3","owner":{"login":"OWNER3"}},
"repo_003":{"name":"REPO4","owner":{"login":"OWNER4"}},
"repo_004":{"name":"REPO5","owner":{"login":"OWNER5"}},
"repo_005":{"name":"REPO6","owner":{"login":"OWNER6"}}
}}`,
func(query string, inputs map[string]interface{}) {
assert.Contains(t, query, "repo_000")
assert.Contains(t, query, "repo_001")
assert.Contains(t, query, "repo_002")
assert.Contains(t, query, "repo_003")
assert.Contains(t, query, "repo_004")
assert.Contains(t, query, "repo_005")
}),
)
},
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git config --add remote.upstream.gh-resolved base`, 0, "")
},
prompterStubs: func(pm *prompter.PrompterMock) {
pm.SelectFunc = func(p, d string, opts []string) (int, error) {
switch p {
case "Which repository should be the default?":
prompter.AssertOptions(t, []string{"OWNER/REPO", "OWNER2/REPO2", "OWNER3/REPO3", "OWNER4/REPO4", "OWNER5/REPO5", "OWNER6/REPO6"}, opts)
return prompter.IndexFor(opts, "OWNER2/REPO2")
default:
return -1, prompter.NoSuchPromptErr(p)
}
}
},
wantStdout: "This command sets the default remote repository to use when querying the\nGitHub API for the locally cloned repository.\n\ngh uses the default repository for things like:\n\n - viewing and creating pull requests\n - viewing and creating issues\n - viewing and creating releases\n - working with Actions\n - adding repository and environment secrets\n\n✓ Set OWNER2/REPO2 as the default repository for the current directory\n",
},
}
for _, tt := range tests {