diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index c3408d4143..1a7bc05a72 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1483,12 +1483,32 @@ _git_bisect () { __git_has_doubledash && return - local subcommands="start bad good skip reset visualize replay log run" - local subcommand="$(__git_find_on_cmdline "$subcommands")" + __git_find_repo_path + + # If a bisection is in progress get the terms being used. + local term_bad term_good + if [ -f "$__git_repo_path"/BISECT_TERMS ]; then + term_bad=$(__git bisect terms --term-bad) + term_good=$(__git bisect terms --term-good) + fi + + # We will complete any custom terms, but still always complete the + # more usual bad/new/good/old because git bisect gives a good error + # message if these are given when not in use, and that's better than + # silent refusal to complete if the user is confused. + # + # We want to recognize 'view' but not complete it, because it overlaps + # with 'visualize' too much and is just an alias for it. + # + local completable_subcommands="start bad new $term_bad good old $term_good terms skip reset visualize replay log run help" + local all_subcommands="$completable_subcommands view" + + local subcommand="$(__git_find_on_cmdline "$all_subcommands")" + if [ -z "$subcommand" ]; then __git_find_repo_path if [ -f "$__git_repo_path"/BISECT_START ]; then - __gitcomp "$subcommands" + __gitcomp "$completable_subcommands" else __gitcomp "replay start" fi @@ -1496,7 +1516,26 @@ _git_bisect () fi case "$subcommand" in - bad|good|reset|skip|start) + start) + case "$cur" in + --*) + __gitcomp "--first-parent --no-checkout --term-new --term-bad --term-old --term-good" + return + ;; + *) + __git_complete_refs + ;; + esac + ;; + terms) + __gitcomp "--term-good --term-old --term-bad --term-new" + return + ;; + visualize|view) + __git_complete_log_opts + return + ;; + bad|new|"$term_bad"|good|old|"$term_good"|reset|skip) __git_complete_refs ;; *) @@ -2105,10 +2144,12 @@ __git_diff_merges_opts="off none on first-parent 1 separate m combined c dense-c __git_log_pretty_formats="oneline short medium full fuller reference email raw format: tformat: mboxrd" __git_log_date_formats="relative iso8601 iso8601-strict rfc2822 short local default human raw unix auto: format:" -_git_log () +# Complete porcelain (i.e. not git-rev-list) options and at least some +# option arguments accepted by git-log. Note that this same set of options +# are also accepted by some other git commands besides git-log. +__git_complete_log_opts () { - __git_has_doubledash && return - __git_find_repo_path + COMPREPLY=() local merge="" if __git_pseudoref_exists MERGE_HEAD; then @@ -2204,6 +2245,16 @@ _git_log () return ;; esac +} + +_git_log () +{ + __git_has_doubledash && return + __git_find_repo_path + + __git_complete_log_opts + [ ${#COMPREPLY[@]} -eq 0 ] || return + __git_complete_revlist } diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 35eb534fdd..d744883d5c 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -11,6 +11,11 @@ test_description='test bash completion' # untraceable with such ancient Bash versions. test_untraceable=UnfortunatelyYes +# Override environment and always use master for the default initial branch +# name for these tests, so that rev completion candidates are as expected. +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + . ./lib-bash.sh complete () @@ -1267,6 +1272,142 @@ test_expect_success 'git switch - with no options, complete local branches and u EOF ' +test_expect_success 'git bisect - when not bisecting, complete only replay and start subcommands' ' + test_completion "git bisect " <<-\EOF + replay Z + start Z + EOF +' + +test_expect_success 'git bisect - complete options to start subcommand' ' + test_completion "git bisect start --" <<-\EOF + --term-new Z + --term-bad Z + --term-old Z + --term-good Z + --no-checkout Z + --first-parent Z + EOF +' + +test_expect_success 'setup for git-bisect tests requiring a repo' ' + git init git-bisect && + ( + cd git-bisect && + echo "initial contents" >file && + git add file && + git commit -am "Initial commit" && + git tag initial && + echo "new line" >>file && + git commit -am "First change" && + echo "another new line" >>file && + git commit -am "Second change" && + git tag final + ) +' + +test_expect_success 'git bisect - start subcommand arguments before double-dash are completed as revs' ' + ( + cd git-bisect && + test_completion "git bisect start " <<-\EOF + HEAD Z + final Z + initial Z + master Z + EOF + ) +' + +# Note that these arguments are s, which in practice the fallback +# completion (not the git completion) later ends up completing as paths. +test_expect_success 'git bisect - start subcommand arguments after double-dash are not completed' ' + ( + cd git-bisect && + test_completion "git bisect start final initial -- " "" + ) +' + +test_expect_success 'setup for git-bisect tests requiring ongoing bisection' ' + ( + cd git-bisect && + git bisect start --term-new=custom_new --term-old=custom_old final initial + ) +' + +test_expect_success 'git-bisect - when bisecting all subcommands are candidates' ' + ( + cd git-bisect && + test_completion "git bisect " <<-\EOF + start Z + bad Z + custom_new Z + custom_old Z + new Z + good Z + old Z + terms Z + skip Z + reset Z + visualize Z + replay Z + log Z + run Z + help Z + EOF + ) +' + +test_expect_success 'git-bisect - options to terms subcommand are candidates' ' + ( + cd git-bisect && + test_completion "git bisect terms --" <<-\EOF + --term-bad Z + --term-good Z + --term-new Z + --term-old Z + EOF + ) +' + +test_expect_success 'git-bisect - git-log options to visualize subcommand are candidates' ' + ( + cd git-bisect && + # The completion used for git-log and here does not complete + # every git-log option, so rather than hope to stay in sync + # with exactly what it does we will just spot-test here. + test_completion "git bisect visualize --sta" <<-\EOF && + --stat Z + EOF + test_completion "git bisect visualize --summar" <<-\EOF + --summary Z + EOF + ) +' + +test_expect_success 'git-bisect - view subcommand is not a candidate' ' + ( + cd git-bisect && + test_completion "git bisect vi" <<-\EOF + visualize Z + EOF + ) +' + +test_expect_success 'git-bisect - existing view subcommand is recognized and enables completion of git-log options' ' + ( + cd git-bisect && + # The completion used for git-log and here does not complete + # every git-log option, so rather than hope to stay in sync + # with exactly what it does we will just spot-test here. + test_completion "git bisect view --sta" <<-\EOF && + --stat Z + EOF + test_completion "git bisect view --summar" <<-\EOF + --summary Z + EOF + ) +' + test_expect_success 'git checkout - completes refs and unique remote branches for DWIM' ' test_completion "git checkout " <<-\EOF HEAD Z