diff --git a/pkg/cmd/repo/setdefault/setdefault.go b/pkg/cmd/repo/setdefault/setdefault.go index f2b4b52670f..d4abac30925 100644 --- a/pkg/cmd/repo/setdefault/setdefault.go +++ b/pkg/cmd/repo/setdefault/setdefault.go @@ -70,6 +70,9 @@ func NewCmdSetDefault(f *cmdutil.Factory, runF func(*SetDefaultOptions) error) * # Set a repository explicitly $ gh repo set-default owner/repo + # Set a repository using a git remote name + $ gh repo set-default origin + # View the current default repository $ gh repo set-default --view @@ -79,11 +82,26 @@ func NewCmdSetDefault(f *cmdutil.Factory, runF func(*SetDefaultOptions) error) * `), Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if isLocal, err := opts.GitClient.IsLocalGitRepo(cmd.Context()); err != nil { + return err + } else if !isLocal { + return errors.New("must be run from inside a git repository") + } + if len(args) > 0 { var err error opts.Repo, err = ghrepo.FromFullName(args[0]) if err != nil { - return err + remotes, remoteErr := opts.Remotes() + if remoteErr != nil { + return remoteErr + } + + remote, findErr := remotes.FindByName(args[0]) + if findErr != nil { + return fmt.Errorf("given arg is not a valid repo or git remote: %w", err) + } + opts.Repo = remote.Repo } } @@ -91,12 +109,6 @@ func NewCmdSetDefault(f *cmdutil.Factory, runF func(*SetDefaultOptions) error) * return cmdutil.FlagErrorf("repository required when not running interactively") } - if isLocal, err := opts.GitClient.IsLocalGitRepo(cmd.Context()); err != nil { - return err - } else if !isLocal { - return errors.New("must be run from inside a git repository") - } - if runF != nil { return runF(opts) } diff --git a/pkg/cmd/repo/setdefault/setdefault_test.go b/pkg/cmd/repo/setdefault/setdefault_test.go index 0d2e2ddaacc..5b2c4d6a30b 100644 --- a/pkg/cmd/repo/setdefault/setdefault_test.go +++ b/pkg/cmd/repo/setdefault/setdefault_test.go @@ -21,6 +21,7 @@ func TestNewCmdSetDefault(t *testing.T) { tests := []struct { name string gitStubs func(*run.CommandStubber) + remotes func() (context.Remotes, error) input string output SetDefaultOptions wantErr bool @@ -43,11 +44,13 @@ func TestNewCmdSetDefault(t *testing.T) { output: SetDefaultOptions{Repo: ghrepo.New("cli", "cli")}, }, { - name: "invalid repo argument", - gitStubs: func(cs *run.CommandStubber) {}, - input: "some_invalid_format", - wantErr: true, - errMsg: `expected the "[HOST/]OWNER/REPO" format, got "some_invalid_format"`, + name: "invalid repo argument", + gitStubs: func(cs *run.CommandStubber) { + cs.Register(`git rev-parse --git-dir`, 0, ".git") + }, + input: "some_invalid_format", + wantErr: true, + errMsg: `given arg is not a valid repo or git remote: expected the "[HOST/]OWNER/REPO" format, got "some_invalid_format"`, }, { name: "view flag", @@ -74,6 +77,38 @@ func TestNewCmdSetDefault(t *testing.T) { wantErr: true, errMsg: "must be run from inside a git repository", }, + { + name: "remote name argument", + gitStubs: func(cs *run.CommandStubber) { + cs.Register(`git rev-parse --git-dir`, 0, ".git") + }, + remotes: func() (context.Remotes, error) { + return context.Remotes{ + { + Remote: &git.Remote{Name: "origin"}, + Repo: ghrepo.New("OWNER", "REPO"), + }, + }, nil + }, + input: "origin", + output: SetDefaultOptions{Repo: ghrepo.New("OWNER", "REPO")}, + }, + { + name: "repo argument despite remote name matching owner/repo", + gitStubs: func(cs *run.CommandStubber) { + cs.Register(`git rev-parse --git-dir`, 0, ".git") + }, + remotes: func() (context.Remotes, error) { + return context.Remotes{ + { + Remote: &git.Remote{Name: "OWNER/REPO"}, + Repo: ghrepo.New("OTHER", "REPO"), + }, + }, nil + }, + input: "OWNER/REPO", + output: SetDefaultOptions{Repo: ghrepo.New("OWNER", "REPO")}, + }, } for _, tt := range tests { @@ -81,9 +116,17 @@ func TestNewCmdSetDefault(t *testing.T) { io.SetStdoutTTY(true) io.SetStdinTTY(true) io.SetStderrTTY(true) + remotesFunc := tt.remotes + if remotesFunc == nil { + remotesFunc = func() (context.Remotes, error) { + return context.Remotes{}, nil + } + } + f := &cmdutil.Factory{ IOStreams: io, GitClient: &git.Client{GitPath: "/fake/path/to/git"}, + Remotes: remotesFunc, } var gotOpts *SetDefaultOptions