Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7d7c240
feat: let user select pr to checkout
nilvng Nov 3, 2024
49b10b7
Merge branch 'trunk' into nil/fix-2329
nilvng Nov 17, 2024
4386fcb
issue #2329: fix the unit tests issue - ensure its backward compatible
nilvng Nov 17, 2024
1832c1a
issue #2329: fix the linting issue
nilvng Nov 17, 2024
c6c2711
issue #2329: add happy path unit test
nilvng Nov 17, 2024
36eaf14
issue #2329: improve UI/UX
nilvng Nov 17, 2024
9c55099
Merge branch 'trunk' into nil/fix-2329
BagToad Nov 28, 2024
e4dced0
issue #2329: fix missing stub
nilvng Nov 30, 2024
d92e529
issue #2329: return error when not running interactively
nilvng Dec 1, 2024
985118e
fix: update the copy
nilvng Dec 3, 2024
9c82156
issue #2329: move Interactive check to RunE
nilvng Dec 3, 2024
2a1f27e
issue cli#2329: fix unsufficent properties required for PR checkout
nilvng Dec 4, 2024
1d19878
Merge branch 'trunk' into nil/fix-2329
BagToad Dec 4, 2024
490bfda
issue cli#2329: Fix linter
BagToad Dec 4, 2024
12479e3
issue #2329: fix unit tests
nilvng Dec 6, 2024
eced54c
issue #2329: update the prompt's format
nilvng Dec 6, 2024
409e3ca
issue #2329: simplify the UI of the prompt
nilvng Dec 6, 2024
4bc9010
issue #2329: fix prompt header getting duplicated
nilvng Dec 9, 2024
5109336
issue #2329: include PR status in the prompt's options
nilvng Dec 9, 2024
2679821
Merge branch 'trunk' into nil/fix-2329
nilvng Dec 9, 2024
de13d7b
Merge branch 'trunk' into nil/fix-2329
nilvng Dec 14, 2024
1f525bf
issue #2329: handle empty list of PR
nilvng Dec 15, 2024
d7cabf1
fix: tab format may break checkout prompts
nilvng Dec 15, 2024
91b3b99
issue #2329: create shared PRLister
nilvng Dec 15, 2024
55598d0
feat: integrate new PRLister into pr list command
nilvng Dec 15, 2024
3987f4a
chore: remove unused file
nilvng Dec 15, 2024
ef3a1ce
Merge branch 'trunk' into nil/fix-2329
nilvng Jan 10, 2025
59031c6
Revert color changes
nilvng Feb 1, 2025
7311b5c
revert isEqualSet to private
nilvng Feb 1, 2025
42c9d24
remove duplicated Prompter type
nilvng Feb 1, 2025
026672e
Merge branch 'trunk' into nil/fix-2329
BagToad Feb 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 104 additions & 7 deletions pkg/cmd/pr/checkout/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"net/http"
"strings"

"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/api"
cliContext "github.com/cli/cli/v2/context"
"github.com/cli/cli/v2/git"
"github.com/cli/cli/v2/internal/gh"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/internal/text"
"github.com/cli/cli/v2/pkg/cmd/pr/shared"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
Expand All @@ -25,8 +27,12 @@ type CheckoutOptions struct {
Remotes func() (cliContext.Remotes, error)
Branch func() (string, error)

Finder shared.PRFinder
Finder shared.PRFinder
Prompter shared.Prompt
Lister shared.PRLister

Interactive bool
BaseRepo func() (ghrepo.Interface, error)
SelectorArg string
RecurseSubmodules bool
Force bool
Expand All @@ -42,17 +48,33 @@ func NewCmdCheckout(f *cmdutil.Factory, runF func(*CheckoutOptions) error) *cobr
Config: f.Config,
Remotes: f.Remotes,
Branch: f.Branch,
Prompter: f.Prompter,
BaseRepo: f.BaseRepo,
}

cmd := &cobra.Command{
Use: "checkout {<number> | <url> | <branch>}",
Use: "checkout [<number> | <url> | <branch>]",
Short: "Check out a pull request in git",
Args: cmdutil.ExactArgs(1, "argument required"),
Example: heredoc.Doc(`
# Interactively select a PR from the 10 most recent to check out
$ gh pr checkout

# Checkout a specific PR
$ gh pr checkout 32
$ gh pr checkout https://github.com/OWNER/REPO/pull/32
$ gh pr checkout feature
`),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Finder = shared.NewFinder(f)
opts.Lister = shared.NewLister(f)

if len(args) > 0 {
opts.SelectorArg = args[0]
} else if !opts.IO.CanPrompt() {
return cmdutil.FlagErrorf("pull request number, URL, or branch required when not running interactively")
} else {
opts.Interactive = true
}

if runF != nil {
Expand All @@ -71,11 +93,12 @@ func NewCmdCheckout(f *cmdutil.Factory, runF func(*CheckoutOptions) error) *cobr
}

func checkoutRun(opts *CheckoutOptions) error {
findOptions := shared.FindOptions{
Selector: opts.SelectorArg,
Fields: []string{"number", "headRefName", "headRepository", "headRepositoryOwner", "isCrossRepository", "maintainerCanModify"},
baseRepo, err := opts.BaseRepo()
if err != nil {
return err
}
pr, baseRepo, err := opts.Finder.Find(findOptions)

pr, err := resolvePR(baseRepo, opts.Prompter, opts.SelectorArg, opts.Interactive, opts.Finder, opts.Lister, opts.IO)
if err != nil {
return err
}
Expand Down Expand Up @@ -263,3 +286,77 @@ func executeCmds(client *git.Client, credentialPattern git.CredentialPattern, cm
}
return nil
}

func resolvePR(baseRepo ghrepo.Interface, prompter shared.Prompt, pullRequestSelector string, isInteractive bool, pullRequestFinder shared.PRFinder, prLister shared.PRLister, io *iostreams.IOStreams) (*api.PullRequest, error) {
// When non-interactive
if pullRequestSelector != "" {
pr, _, err := pullRequestFinder.Find(shared.FindOptions{
Selector: pullRequestSelector,
Fields: []string{
"number",
"headRefName",
"headRepository",
"headRepositoryOwner",
"isCrossRepository",
"maintainerCanModify",
},
})
if err != nil {
return nil, err
}
return pr, nil
}
if !isInteractive {
return nil, cmdutil.FlagErrorf("pull request number, URL, or branch required when not running interactively")
}
// When interactive
io.StartProgressIndicator()
listResult, err := prLister.List(shared.ListOptions{
State: "open",
Fields: []string{
"number",
"title",
"state",
"isDraft",

"headRefName",
"headRepository",
"headRepositoryOwner",
"isCrossRepository",
"maintainerCanModify",
},
LimitResults: 10})
io.StopProgressIndicator()
if err != nil {
return nil, err
}
if len(listResult.PullRequests) == 0 {
return nil, shared.ListNoResults(ghrepo.FullName(baseRepo), "pull request", false)
}

pr, err := promptForPR(prompter, *listResult)
return pr, err
}

func promptForPR(prompter shared.Prompt, jobs api.PullRequestAndTotalCount) (*api.PullRequest, error) {
candidates := []string{}
for _, pr := range jobs.PullRequests {
candidates = append(candidates, fmt.Sprintf("%d\t%s %s [%s]",
pr.Number,
shared.PrStateWithDraft(&pr),
text.RemoveExcessiveWhitespace(pr.Title),
pr.HeadLabel(),
))
}

selected, err := prompter.Select("Select a pull request", "", candidates)
if err != nil {
return nil, err
}

if selected >= 0 {
return &jobs.PullRequests[selected], nil
}

return nil, nil
}
Loading
Loading