diff --git a/pkg/cmd/issue/pin/pin.go b/pkg/cmd/issue/pin/pin.go index dfb11a881..290bec507 100644 --- a/pkg/cmd/issue/pin/pin.go +++ b/pkg/cmd/issue/pin/pin.go @@ -20,7 +20,7 @@ type PinOptions struct { Config func() (gh.Config, error) IO *iostreams.IOStreams BaseRepo func() (ghrepo.Interface, error) - SelectorArg string + IssueNumber int } func NewCmdPin(f *cmdutil.Factory, runF func(*PinOptions) error) *cobra.Command { @@ -51,8 +51,22 @@ func NewCmdPin(f *cmdutil.Factory, runF func(*PinOptions) error) *cobra.Command `), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - opts.BaseRepo = f.BaseRepo - opts.SelectorArg = args[0] + issueNumber, baseRepo, err := shared.ParseIssueFromArg(args[0]) + if err != nil { + return err + } + + // If the args provided the base repo then use that directly. + if baseRepo, present := baseRepo.Value(); present { + opts.BaseRepo = func() (ghrepo.Interface, error) { + return baseRepo, nil + } + } else { + // support `-R, --repo` override + opts.BaseRepo = f.BaseRepo + } + + opts.IssueNumber = issueNumber if runF != nil { return runF(opts) @@ -73,7 +87,12 @@ func pinRun(opts *PinOptions) error { return err } - issue, baseRepo, err := shared.IssueFromArgWithFields(httpClient, opts.BaseRepo, opts.SelectorArg, []string{"id", "number", "title", "isPinned"}) + baseRepo, err := opts.BaseRepo() + if err != nil { + return err + } + + issue, err := shared.FindIssueOrPR(httpClient, baseRepo, opts.IssueNumber, []string{"id", "number", "title", "isPinned"}) if err != nil { return err } diff --git a/pkg/cmd/issue/pin/pin_test.go b/pkg/cmd/issue/pin/pin_test.go index d4979a30d..67b767b32 100644 --- a/pkg/cmd/issue/pin/pin_test.go +++ b/pkg/cmd/issue/pin/pin_test.go @@ -1,80 +1,21 @@ package pin import ( - "bytes" "net/http" "testing" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/gh" "github.com/cli/cli/v2/internal/ghrepo" - "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/cmd/issue/argparsetest" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/google/shlex" "github.com/stretchr/testify/assert" ) func TestNewCmdPin(t *testing.T) { - tests := []struct { - name string - input string - output PinOptions - wantErr bool - errMsg string - }{ - { - name: "no argument", - input: "", - wantErr: true, - errMsg: "accepts 1 arg(s), received 0", - }, - { - name: "issue number", - input: "6", - output: PinOptions{ - SelectorArg: "6", - }, - }, - { - name: "issue url", - input: "https://github.com/cli/cli/6", - output: PinOptions{ - SelectorArg: "https://github.com/cli/cli/6", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ios, _, _, _ := iostreams.Test() - ios.SetStdinTTY(true) - ios.SetStdoutTTY(true) - f := &cmdutil.Factory{ - IOStreams: ios, - } - argv, err := shlex.Split(tt.input) - assert.NoError(t, err) - var gotOpts *PinOptions - cmd := NewCmdPin(f, func(opts *PinOptions) error { - gotOpts = opts - return nil - }) - cmd.SetArgs(argv) - cmd.SetIn(&bytes.Buffer{}) - cmd.SetOut(&bytes.Buffer{}) - cmd.SetErr(&bytes.Buffer{}) - - _, err = cmd.ExecuteC() - if tt.wantErr { - assert.Error(t, err) - assert.Equal(t, tt.errMsg, err.Error()) - return - } - - assert.NoError(t, err) - assert.Equal(t, tt.output.SelectorArg, gotOpts.SelectorArg) - }) - } + // Test shared parsing of issue number / URL. + argparsetest.TestArgParsing(t, NewCmdPin) } func TestPinRun(t *testing.T) { @@ -89,7 +30,7 @@ func TestPinRun(t *testing.T) { { name: "pin issue", tty: true, - opts: &PinOptions{SelectorArg: "20"}, + opts: &PinOptions{IssueNumber: 20}, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query IssueByNumber\b`), @@ -113,7 +54,7 @@ func TestPinRun(t *testing.T) { { name: "issue already pinned", tty: true, - opts: &PinOptions{SelectorArg: "20"}, + opts: &PinOptions{IssueNumber: 20}, httpStubs: func(reg *httpmock.Registry) { reg.Register( httpmock.GraphQL(`query IssueByNumber\b`),