Skip to content

Commit acb658f

Browse files
jacob-kellergitster
authored andcommitted
completion: improve handling of -c/-C and -b/-B in switch/checkout
A previous commit added several test cases highlighting the subpar completion logic for -c/-C and -b/-B when completing git switch and git checkout. In order to distinguish completing the argument vs the start-point for this option, we now use the wordlist to determine the previous full word on the command line. If it's -c or -C (-b/-B for checkout), then we know that we are completing the argument for the branch name. Given that a user who already knows the branch name they want to complete will simply not use completion, it makes sense to complete the small subset of local branches when completing the argument for -c/-C. In all other cases, if -c/-C are on the command line but are not the most recent option, then we must be completing a start-point, and should allow completing against all references. Update the -c/-C and -b/-B tests to indicate they now pass. Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 00e7bd2 commit acb658f

File tree

2 files changed

+63
-34
lines changed

2 files changed

+63
-34
lines changed

contrib/completion/git-completion.bash

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,8 +1505,31 @@ _git_checkout ()
15051505
;;
15061506
*)
15071507
local dwim_opt="$(__git_checkout_default_dwim_mode)"
1508+
local prevword prevword="${words[cword-1]}"
1509+
1510+
case "$prevword" in
1511+
-b|-B)
1512+
# Complete local branches (and DWIM branch
1513+
# remote branch names) for an option argument
1514+
# specifying a new branch name. This is for
1515+
# convenience, assuming new branches are
1516+
# possibly based on pre-existing branch names.
1517+
__git_complete_refs $dwim_opt --mode="heads"
1518+
return
1519+
;;
1520+
*)
1521+
;;
1522+
esac
1523+
1524+
# At this point, we've already handled special completion for
1525+
# the arguments to -b/-B. There are 3 main things left we can
1526+
# possibly complete:
1527+
# 1) a start-point for -b/-B or -d/--detach
1528+
# 2) a remote head, for --track
1529+
# 3) an arbitrary reference, possibly including DWIM names
1530+
#
15081531

1509-
if [ -n "$(__git_find_on_cmdline "-d --detach")" ]; then
1532+
if [ -n "$(__git_find_on_cmdline "-b -B -d --detach")" ]; then
15101533
__git_complete_refs --mode="refs"
15111534
elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
15121535
__git_complete_refs --mode="remote-heads"
@@ -2361,8 +2384,30 @@ _git_switch ()
23612384
;;
23622385
*)
23632386
local dwim_opt="$(__git_checkout_default_dwim_mode)"
2387+
local prevword prevword="${words[cword-1]}"
2388+
2389+
case "$prevword" in
2390+
-c|-C)
2391+
# Complete local branches (and DWIM branch
2392+
# remote branch names) for an option argument
2393+
# specifying a new branch name. This is for
2394+
# convenience, assuming new branches are
2395+
# possibly based on pre-existing branch names.
2396+
__git_complete_refs $dwim_opt --mode="heads"
2397+
return
2398+
;;
2399+
*)
2400+
;;
2401+
esac
2402+
2403+
# At this point, we've already handled special completion for
2404+
# -c/-C. There are 3 main things left to
2405+
# complete:
2406+
# 1) a start-point for -c/-C or -d/--detach
2407+
# 2) a remote head, for --track
2408+
# 3) a branch name, possibly including DWIM remote branches
23642409

2365-
if [ -n "$(__git_find_on_cmdline "-d --detach")" ]; then
2410+
if [ -n "$(__git_find_on_cmdline "-c -C -d --detach")" ]; then
23662411
__git_complete_refs --mode="refs"
23672412
elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
23682413
__git_complete_refs --mode="remote-heads"

t/t9902-completion.sh

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,8 +1436,7 @@ test_expect_success 'git checkout - with --no-track, complete only local referen
14361436
EOF
14371437
'
14381438

1439-
#TODO: completing the start point of -c/-C should not include DWIM references
1440-
test_expect_failure 'git switch - with -c, complete all references' '
1439+
test_expect_success 'git switch - with -c, complete all references' '
14411440
test_completion "git switch -c new-branch " <<-\EOF
14421441
HEAD Z
14431442
master Z
@@ -1448,8 +1447,7 @@ test_expect_failure 'git switch - with -c, complete all references' '
14481447
EOF
14491448
'
14501449

1451-
#TODO: completing the start point of -c/-C should not include DWIM references
1452-
test_expect_failure 'git switch - with -C, complete all references' '
1450+
test_expect_success 'git switch - with -C, complete all references' '
14531451
test_completion "git switch -C new-branch " <<-\EOF
14541452
HEAD Z
14551453
master Z
@@ -1460,8 +1458,7 @@ test_expect_failure 'git switch - with -C, complete all references' '
14601458
EOF
14611459
'
14621460

1463-
#TODO: completing the start point of -c/-C should include all references, not just local branches
1464-
test_expect_failure 'git switch - with -c and --track, complete all references' '
1461+
test_expect_success 'git switch - with -c and --track, complete all references' '
14651462
test_completion "git switch -c new-branch --track " <<-EOF
14661463
HEAD Z
14671464
master Z
@@ -1472,8 +1469,7 @@ test_expect_failure 'git switch - with -c and --track, complete all references'
14721469
EOF
14731470
'
14741471

1475-
#TODO: completing the start point of -c/-C should include all references, not just local branches
1476-
test_expect_failure 'git switch - with -C and --track, complete all references' '
1472+
test_expect_success 'git switch - with -C and --track, complete all references' '
14771473
test_completion "git switch -C new-branch --track " <<-EOF
14781474
HEAD Z
14791475
master Z
@@ -1484,8 +1480,7 @@ test_expect_failure 'git switch - with -C and --track, complete all references'
14841480
EOF
14851481
'
14861482

1487-
#TODO: completing the start point of -c/-C should include all references, not just local branches
1488-
test_expect_failure 'git switch - with -c and --no-track, complete all references' '
1483+
test_expect_success 'git switch - with -c and --no-track, complete all references' '
14891484
test_completion "git switch -c new-branch --no-track " <<-\EOF
14901485
HEAD Z
14911486
master Z
@@ -1496,8 +1491,7 @@ test_expect_failure 'git switch - with -c and --no-track, complete all reference
14961491
EOF
14971492
'
14981493

1499-
#TODO: completing the start point of -c/-C should include all references, not just local branches
1500-
test_expect_failure 'git switch - with -C and --no-track, complete all references' '
1494+
test_expect_success 'git switch - with -C and --no-track, complete all references' '
15011495
test_completion "git switch -C new-branch --no-track " <<-\EOF
15021496
HEAD Z
15031497
master Z
@@ -1508,8 +1502,7 @@ test_expect_failure 'git switch - with -C and --no-track, complete all reference
15081502
EOF
15091503
'
15101504

1511-
#TODO: completing the start point of -b/-B should not include DWIM references
1512-
test_expect_failure 'git checkout - with -b, complete all references' '
1505+
test_expect_success 'git checkout - with -b, complete all references' '
15131506
test_completion "git checkout -b new-branch " <<-\EOF
15141507
HEAD Z
15151508
master Z
@@ -1520,8 +1513,7 @@ test_expect_failure 'git checkout - with -b, complete all references' '
15201513
EOF
15211514
'
15221515

1523-
#TODO: completing the start point of -b/-B should not include DWIM references
1524-
test_expect_failure 'git checkout - with -B, complete all references' '
1516+
test_expect_success 'git checkout - with -B, complete all references' '
15251517
test_completion "git checkout -B new-branch " <<-\EOF
15261518
HEAD Z
15271519
master Z
@@ -1532,8 +1524,7 @@ test_expect_failure 'git checkout - with -B, complete all references' '
15321524
EOF
15331525
'
15341526

1535-
#TODO: completing the start point of -b/-B should not include DWIM references
1536-
test_expect_failure 'git checkout - with -b and --track, complete all references' '
1527+
test_expect_success 'git checkout - with -b and --track, complete all references' '
15371528
test_completion "git checkout -b new-branch --track " <<-EOF
15381529
HEAD Z
15391530
master Z
@@ -1544,8 +1535,7 @@ test_expect_failure 'git checkout - with -b and --track, complete all references
15441535
EOF
15451536
'
15461537

1547-
#TODO: completing the start point of -b/-B should not include DWIM references
1548-
test_expect_failure 'git checkout - with -B and --track, complete all references' '
1538+
test_expect_success 'git checkout - with -B and --track, complete all references' '
15491539
test_completion "git checkout -B new-branch --track " <<-EOF
15501540
HEAD Z
15511541
master Z
@@ -1624,8 +1614,7 @@ test_expect_success 'git switch - for -C with --no-track, complete local branche
16241614
EOF
16251615
'
16261616

1627-
#TODO: -b/-B argument completion should not include all references
1628-
test_expect_failure 'git checkout - for -b, complete local branches and unique remote branches' '
1617+
test_expect_success 'git checkout - for -b, complete local branches and unique remote branches' '
16291618
test_completion "git checkout -b " <<-\EOF
16301619
branch-in-other Z
16311620
master Z
@@ -1634,8 +1623,7 @@ test_expect_failure 'git checkout - for -b, complete local branches and unique r
16341623
EOF
16351624
'
16361625

1637-
#TODO: -b/-B argument completion should not include all references
1638-
test_expect_failure 'git checkout - for -B, complete local branches and unique remote branches' '
1626+
test_expect_success 'git checkout - for -B, complete local branches and unique remote branches' '
16391627
test_completion "git checkout -B " <<-\EOF
16401628
branch-in-other Z
16411629
master Z
@@ -1644,32 +1632,28 @@ test_expect_failure 'git checkout - for -B, complete local branches and unique r
16441632
EOF
16451633
'
16461634

1647-
#TODO: -b/-B argument completion should not include all references
1648-
test_expect_failure 'git checkout - for -b with --no-guess, complete local branches only' '
1635+
test_expect_success 'git checkout - for -b with --no-guess, complete local branches only' '
16491636
test_completion "git checkout --no-guess -b " <<-\EOF
16501637
master Z
16511638
matching-branch Z
16521639
EOF
16531640
'
16541641

1655-
#TODO: -b/-B argument completion should not include all references
1656-
test_expect_failure 'git checkout - for -B with --no-guess, complete local branches only' '
1642+
test_expect_success 'git checkout - for -B with --no-guess, complete local branches only' '
16571643
test_completion "git checkout --no-guess -B " <<-\EOF
16581644
master Z
16591645
matching-branch Z
16601646
EOF
16611647
'
16621648

1663-
#TODO: -b/-B argument completion should not include all references
1664-
test_expect_failure 'git checkout - for -b with --no-track, complete local branches only' '
1649+
test_expect_success 'git checkout - for -b with --no-track, complete local branches only' '
16651650
test_completion "git checkout --no-track -b " <<-\EOF
16661651
master Z
16671652
matching-branch Z
16681653
EOF
16691654
'
16701655

1671-
#TODO: -b/-B argument completion should not include all references
1672-
test_expect_failure 'git checkout - for -B with --no-track, complete local branches only' '
1656+
test_expect_success 'git checkout - for -B with --no-track, complete local branches only' '
16731657
test_completion "git checkout --no-track -B " <<-\EOF
16741658
master Z
16751659
matching-branch Z

0 commit comments

Comments
 (0)