@matheusbsbs / matheus-bagliano / commits / 4e79adf4e5
Fork 0

completion: improve handling of DWIM mode for switch/checkout

A new helper, __git_find_last_on_cmdline is introduced, similar to the already existing __git_find_on_cmdline, but which operates in reverse, finding the *last* matching word of the provided wordlist. Use this in a new __git_checkout_default_dwim_mode() function that will determine when to enable listing of DWIM remote branches. The __git_find_last_on_cmdline() function is used to determine which --guess or --no-guess is in effect. If either one is provided, then we unconditionally enable or disable the DWIM mode based on the last provided option. If neither --guess nor --no-guess is provided, then we check for --no-track, and finally for GIT_COMPLETION_CHECKOUT_NO_GUESS=1. This function is then used in _git_switch and _git_checkout to improve the handling for when we enable listing of these DWIM remote branches. This new logic is more robust, as we will correctly identify superseded options, and ensure that both _git_switch and _git_checkout enable DWIM in similar ways. We can now update a few tests to indicate they pass. A few of the tests previously added to highlight issues with the old DWIM logic still fail. This is because of a separate issue related to the default completion behavior of git switch, which will be addressed in a future change. Additionally, due to this change, a few tests for the -b/-B handling of git checkout now fail. This is a minor regression, and will be fixed by a following change that improves the overall handling of -b/-B. Mark these tests as known breakages for now. Signed-off-by: Jacob Keller <jacob.keller@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jacob Keller committed May 28, 2020 at 11:10 UTC 4e79adf4e57cbb514e026f9fa2b1f4f7f7a0a2ae
2 files changed +83 -29
contrib/completion/git-completion.bash
+76 -19
@@ -1135,6 +1135,40 @@ __git_find_on_cmdline ()
1135 done
1136 }
1137
1138 +# Similar to __git_find_on_cmdline, except that it loops backwards and thus
1139 +# prints the *last* word found. Useful for finding which of two options that
1140 +# supersede each other came last, such as "--guess" and "--no-guess".
1141 +#
1142 +# Usage: __git_find_last_on_cmdline [<option>]... "<wordlist>"
1143 +# --show-idx: Optionally show the index of the found word in the $words array.
1144 +__git_find_last_on_cmdline ()
1145 +{
1146 + local word c=$cword show_idx
1147 +
1148 + while test $# -gt 1; do
1149 + case "$1" in
1150 + --show-idx) show_idx=y ;;
1151 + *) return 1 ;;
1152 + esac
1153 + shift
1154 + done
1155 + local wordlist="$1"
1156 +
1157 + while [ $c -gt 1 ]; do
1158 + ((c--))
1159 + for word in $wordlist; do
1160 + if [ "$word" = "${words[c]}" ]; then
1161 + if [ -n "$show_idx" ]; then
1162 + echo "$c $word"
1163 + else
1164 + echo "$word"
1165 + fi
1166 + return
1167 + fi
1168 + done
1169 + done
1170 +}
1171 +
1172 # Echo the value of an option set on the command line or config
1173 #
1174 # $1: short option name
@@ -1389,6 +1423,46 @@ _git_bundle ()
1423 esac
1424 }
1425
1426 +# Helper function to decide whether or not we should enable DWIM logic for
1427 +# git-switch and git-checkout.
1428 +#
1429 +# To decide between the following rules in priority order
1430 +# 1) the last provided of "--guess" or "--no-guess" explicitly enable or
1431 +# disable completion of DWIM logic respectively.
1432 +# 2) If the --no-track option is provided, take this as a hint to disable the
1433 +# DWIM completion logic
1434 +# 3) If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
1435 +# logic, as requested by the user.
1436 +# 4) Enable DWIM logic otherwise.
1437 +#
1438 +__git_checkout_default_dwim_mode ()
1439 +{
1440 + local last_option dwim_opt="--dwim"
1441 +
1442 + if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ]; then
1443 + dwim_opt=""
1444 + fi
1445 +
1446 + # --no-track disables DWIM, but with lower priority than
1447 + # --guess/--no-guess
1448 + if [ -n "$(__git_find_on_cmdline "--no-track")" ]; then
1449 + dwim_opt=""
1450 + fi
1451 +
1452 + # Find the last provided --guess or --no-guess
1453 + last_option="$(__git_find_last_on_cmdline "--guess --no-guess")"
1454 + case "$last_option" in
1455 + --guess)
1456 + dwim_opt="--dwim"
1457 + ;;
1458 + --no-guess)
1459 + dwim_opt=""
1460 + ;;
1461 + esac
1462 +
1463 + echo "$dwim_opt"
1464 +}
1465 +
1466 _git_checkout ()
1467 {
1468 __git_has_doubledash && return
@@ -1401,13 +1475,7 @@ _git_checkout ()
1475 __gitcomp_builtin checkout
1476 ;;
1477 *)
1404 - # check if --track, --no-track, or --no-guess was specified
1405 - # if so, disable DWIM mode
1406 - local flags="--track --no-track --no-guess" dwim_opt="--dwim"
1407 - if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
1408 - [ -n "$(__git_find_on_cmdline "$flags")" ]; then
1409 - dwim_opt=''
1410 - fi
1478 + local dwim_opt="$(__git_checkout_default_dwim_mode)"
1479 __git_complete_refs $dwim_opt
1480 ;;
1481 esac
@@ -2256,18 +2324,7 @@ _git_switch ()
2324 __gitcomp_builtin switch
2325 ;;
2326 *)
2259 - # check if --track, --no-track, or --no-guess was specified
2260 - # if so, disable DWIM mode
2261 - local dwim_opt="--dwim" only_local_ref=n
2262 - if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
2263 - [ -n "$(__git_find_on_cmdline "--track --no-track --no-guess")" ]; then
2264 - dwim_opt=''
2265 - fi
2266 - # explicit --guess enables DWIM mode regardless of
2267 - # $GIT_COMPLETION_CHECKOUT_NO_GUESS
2268 - if [ -n "$(__git_find_on_cmdline "--guess")" ]; then
2269 - dwim_opt='--dwim'
2270 - fi
2327 + local dwim_opt="$(__git_checkout_default_dwim_mode)" only_local_ref=n
2328 if [ -z "$(__git_find_on_cmdline "-d --detach")" ]; then
2329 only_local_ref=y
2330 else
t/t9902-completion.sh
+7 -10
@@ -1277,7 +1277,6 @@ test_expect_success 'git switch - with GIT_COMPLETION_CHECKOUT_NO_GUESS=1, compl
1277 EOF
1278 '
1279
1280 -#TODO: --guess/--no-guess ordering is not taken into account
1280 #TODO: git switch completion includes unexpected references
1281 test_expect_failure 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_GUESS=1, complete local branches and unique remote names for DWIM logic' '
1282 GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git switch --guess " <<-\EOF
@@ -1288,7 +1287,6 @@ test_expect_failure 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_G
1287 EOF
1288 '
1289
1291 -#TODO: --guess/--no-guess ordering is not taken into account
1290 #TODO: git switch completion includes unexpected references
1291 test_expect_failure 'git switch - a later --guess overrides previous --no-guess, complete local and remote unique branches for DWIM' '
1292 test_completion "git switch --no-guess --guess " <<-\EOF
@@ -1299,8 +1297,7 @@ test_expect_failure 'git switch - a later --guess overrides previous --no-guess,
1297 EOF
1298 '
1299
1302 -#TODO: --guess/--no-guess ordering is not taken into account
1303 -test_expect_failure 'git switch - a later --no-guess overrides previous --guess, complete only local branches' '
1300 +test_expect_success 'git switch - a later --no-guess overrides previous --guess, complete only local branches' '
1301 test_completion "git switch --guess --no-guess " <<-\EOF
1302 master Z
1303 matching-branch Z
@@ -1318,8 +1315,7 @@ test_expect_success 'git checkout - with GIT_COMPLETION_NO_GUESS=1 only complete
1315 EOF
1316 '
1317
1321 -#TODO: git checkout does not override variable when --guess is provided
1322 -test_expect_failure 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' '
1318 +test_expect_success 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' '
1319 GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git checkout --guess " <<-\EOF
1320 HEAD Z
1321 branch-in-other Z
@@ -1343,8 +1339,7 @@ test_expect_success 'git checkout - with --no-guess, only completes refs' '
1339 EOF
1340 '
1341
1346 -#TODO: --guess/--no-guess ordering is not taken into account
1347 -test_expect_failure 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' '
1342 +test_expect_success 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' '
1343 test_completion "git checkout --no-guess --guess " <<-\EOF
1344 HEAD Z
1345 branch-in-other Z
@@ -1544,7 +1539,8 @@ test_expect_failure 'git checkout - with -B, complete all references' '
1539 EOF
1540 '
1541
1547 -test_expect_success 'git checkout - with -b and --track, complete all references' '
1542 +#TODO: completing the start point of -b/-B should not include DWIM references
1543 +test_expect_failure 'git checkout - with -b and --track, complete all references' '
1544 test_completion "git checkout -b new-branch --track " <<-EOF
1545 HEAD Z
1546 master Z
@@ -1555,7 +1551,8 @@ test_expect_success 'git checkout - with -b and --track, complete all references
1551 EOF
1552 '
1553
1558 -test_expect_success 'git checkout - with -B and --track, complete all references' '
1554 +#TODO: completing the start point of -b/-B should not include DWIM references
1555 +test_expect_failure 'git checkout - with -B and --track, complete all references' '
1556 test_completion "git checkout -B new-branch --track " <<-EOF
1557 HEAD Z
1558 master Z