completion: address sparse-checkout issues

Correct multiple issues with tab completion of the git sparse-checkout command. These issues were: 1. git sparse-checkout <TAB> previously resulted in an incomplete list of subcommands (it was missing reapply and add). 2. Subcommand options were not tab-completable. 3. git sparse-checkout set <TAB> and git sparse-checkout add <TAB> showed both file names and directory names. While this may be a less surprising behavior for non-cone mode, cone mode sparse checkouts should complete only directory names. Note that while the new strategy of just using git ls-tree to complete on directory names is simple and a step in the right direction, it does have some caveats. These are: 1. Likelihood of poor performance in large monorepos (as a result of recursively completing directory names). 2. Inability to handle paths containing unusual characters. These caveats will be fixed by subsequent commits in this series. Signed-off-by: Lessley Dennington <lessleydennington@gmail.com> Reviewed-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lessley Dennington committed Feb 7, 2022 at 17:31 UTC fd6d9bec145924ba704b34f0788b239bff9d2898
2 files changed +91 -8
contrib/completion/git-completion.bash
+8 -8
@@ -2988,7 +2988,7 @@ _git_show_branch ()
2988
2989 _git_sparse_checkout ()
2990 {
2991 - local subcommands="list init set disable"
2991 + local subcommands="list init set disable add reapply"
2992 local subcommand="$(__git_find_on_cmdline "$subcommands")"
2993 if [ -z "$subcommand" ]; then
2994 __gitcomp "$subcommands"
@@ -2996,14 +2996,14 @@ _git_sparse_checkout ()
2996 fi
2997
2998 case "$subcommand,$cur" in
2999 - init,--*)
3000 - __gitcomp "--cone"
3001 - ;;
3002 - set,--*)
3003 - __gitcomp "--stdin"
3004 - ;;
3005 - *)
2999 + *,--*)
3000 + __gitcomp_builtin sparse-checkout_$subcommand "" "--"
3001 ;;
3002 + set,*|add,*)
3003 + if [ "$(__git config core.sparseCheckoutCone)" == "true" ] ||
3004 + [ -n "$(__git_find_on_cmdline --cone)" ]; then
3005 + __gitcomp "$(git ls-tree -d -r HEAD --name-only)"
3006 + fi
3007 esac
3008 }
3009
t/t9902-completion.sh
+83
@@ -1444,6 +1444,89 @@ test_expect_success 'git checkout - with --detach, complete only references' '
1444 EOF
1445 '
1446
1447 +test_expect_success 'setup sparse-checkout tests' '
1448 + # set up sparse-checkout repo
1449 + git init sparse-checkout &&
1450 + (
1451 + cd sparse-checkout &&
1452 + mkdir -p folder1/0/1 folder2/0 folder3 &&
1453 + touch folder1/0/1/t.txt &&
1454 + touch folder2/0/t.txt &&
1455 + touch folder3/t.txt &&
1456 + git add . &&
1457 + git commit -am "Initial commit"
1458 + )
1459 +'
1460 +
1461 +test_expect_success 'sparse-checkout completes subcommands' '
1462 + test_completion "git sparse-checkout " <<-\EOF
1463 + list Z
1464 + init Z
1465 + set Z
1466 + add Z
1467 + reapply Z
1468 + disable Z
1469 + EOF
1470 +'
1471 +
1472 +test_expect_success 'cone mode sparse-checkout completes directory names' '
1473 + # initialize sparse-checkout definitions
1474 + git -C sparse-checkout sparse-checkout set --cone folder1/0 folder3 &&
1475 +
1476 + # test tab completion
1477 + (
1478 + cd sparse-checkout &&
1479 + test_completion "git sparse-checkout set f" <<-\EOF
1480 + folder1 Z
1481 + folder1/0 Z
1482 + folder1/0/1 Z
1483 + folder2 Z
1484 + folder2/0 Z
1485 + folder3 Z
1486 + EOF
1487 + ) &&
1488 +
1489 + (
1490 + cd sparse-checkout/folder1 &&
1491 + test_completion "git sparse-checkout add " <<-\EOF
1492 + ./ Z
1493 + 0 Z
1494 + 0/1 Z
1495 + EOF
1496 + )
1497 +'
1498 +
1499 +test_expect_success 'non-cone mode sparse-checkout uses bash completion' '
1500 + # reset sparse-checkout repo to non-cone mode
1501 + git -C sparse-checkout sparse-checkout disable &&
1502 + git -C sparse-checkout sparse-checkout set --no-cone &&
1503 +
1504 + (
1505 + cd sparse-checkout &&
1506 + # expected to be empty since we have not configured
1507 + # custom completion for non-cone mode
1508 + test_completion "git sparse-checkout set f" <<-\EOF
1509 +
1510 + EOF
1511 + )
1512 +'
1513 +
1514 +test_expect_success 'git sparse-checkout set --cone completes directory names' '
1515 + git -C sparse-checkout sparse-checkout disable &&
1516 +
1517 + (
1518 + cd sparse-checkout &&
1519 + test_completion "git sparse-checkout set --cone f" <<-\EOF
1520 + folder1 Z
1521 + folder1/0 Z
1522 + folder1/0/1 Z
1523 + folder2 Z
1524 + folder2/0 Z
1525 + folder3 Z
1526 + EOF
1527 + )
1528 +'
1529 +
1530 test_expect_success 'git switch - with -d, complete all references' '
1531 test_completion "git switch -d " <<-\EOF
1532 HEAD Z