completion: support completing full refs after '--option=refs/<TAB>'

Completing full refs currently only works when the full ref stands on in its own on the command line, but doesn't work when the current word to be completed contains a prefix before the full ref, e.g. '--option=refs/<TAB>' or 'master..refs/bis<TAB>'. The reason is that __git_refs() looks at the current word to be completed ($cur) as a whole to decide whether it has to list full (if it starts with 'refs/') or short refs (otherwise). However, $cur also holds said '--option=' or 'master..' prefixes, which of course throw off this decision. Luckily, the default action is to list short refs, that's why completing short refs happens to work even after a 'master..<TAB>' prefix and similar cases. Pass only the ref part of the current word to be completed to __git_refs() as a new positional parameter, so it can make the right decision even if the whole current word contains some kind of a prefix. Make this new parameter the 4. positional parameter and leave the 3. as an ignored placeholder for now (it will be used later in this patch series). Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

SZEDER Gábor committed Mar 23, 2017 at 16:29 UTC 2ea328a119709a2a94b16cea28ef0e5d7405c5f9
2 files changed +45 -7
contrib/completion/git-completion.bash
+14 -7
@@ -354,6 +354,8 @@ __git_tags ()
354 # Can be the name of a configured remote, a path, or a URL.
355 # 2: In addition to local refs, list unique branches from refs/remotes/ for
356 # 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
357 +# 3: Currently ignored.
358 +# 4: The current ref to be completed (optional).
359 #
360 # Use __git_complete_refs() instead.
361 __git_refs ()
@@ -361,6 +363,7 @@ __git_refs ()
363 local i hash dir track="${2-}"
364 local list_refs_from=path remote="${1-}"
365 local format refs pfx
366 + local cur_="${4-$cur}"
367
368 __git_find_repo_path
369 dir="$__git_repo_path"
@@ -384,14 +387,17 @@ __git_refs ()
387 fi
388
389 if [ "$list_refs_from" = path ]; then
387 - case "$cur" in
390 + case "$cur_" in
391 refs|refs/*)
392 format="refname"
390 - refs="${cur%/*}"
393 + refs="${cur_%/*}"
394 track=""
395 ;;
396 *)
394 - [[ "$cur" == ^* ]] && pfx="^"
397 + if [[ "$cur_" == ^* ]]; then
398 + pfx="^"
399 + cur_=${cur_#^}
400 + fi
401 for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
402 if [ -e "$dir/$i" ]; then echo $pfx$i; fi
403 done
@@ -411,16 +417,16 @@ __git_refs ()
417 while read -r entry; do
418 eval "$entry"
419 ref="${ref#*/}"
414 - if [[ "$ref" == "$cur"* ]]; then
420 + if [[ "$ref" == "$cur_"* ]]; then
421 echo "$ref"
422 fi
423 done | sort | uniq -u
424 fi
425 return
426 fi
421 - case "$cur" in
427 + case "$cur_" in
428 refs|refs/*)
423 - __git ls-remote "$remote" "$cur*" | \
429 + __git ls-remote "$remote" "$cur_*" | \
430 while read -r hash i; do
431 case "$i" in
432 *^{}) ;;
@@ -475,7 +481,8 @@ __git_complete_refs ()
481 shift
482 done
483
478 - __gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx"
484 + __gitcomp_nl "$(__git_refs "$remote" "$track" "" "$cur_")" \
485 + "$pfx" "$cur_" "$sfx"
486 }
487
488 # __git_refs2 requires 1 argument (to pass to __git_refs)
t/t9902-completion.sh
+31
@@ -775,6 +775,37 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer
775 test_cmp expected "$actual"
776 '
777
778 +test_expect_success '__git_refs - after --opt=' '
779 + cat >expected <<-EOF &&
780 + HEAD
781 + master
782 + matching-branch
783 + other/branch-in-other
784 + other/master-in-other
785 + matching-tag
786 + EOF
787 + (
788 + cur="--opt=" &&
789 + __git_refs "" "" "" "" >"$actual"
790 + ) &&
791 + test_cmp expected "$actual"
792 +'
793 +
794 +test_expect_success '__git_refs - after --opt= - full refs' '
795 + cat >expected <<-EOF &&
796 + refs/heads/master
797 + refs/heads/matching-branch
798 + refs/remotes/other/branch-in-other
799 + refs/remotes/other/master-in-other
800 + refs/tags/matching-tag
801 + EOF
802 + (
803 + cur="--opt=refs/" &&
804 + __git_refs "" "" "" refs/ >"$actual"
805 + ) &&
806 + test_cmp expected "$actual"
807 +'
808 +
809 test_expect_success '__git_complete_refs - simple' '
810 sed -e "s/Z$//" >expected <<-EOF &&
811 HEAD Z