completion: speed up branch and tag completion

Modify __git_heads() and __git_tags() and the few callsites they have, so we can let 'git for-each-ref' do all the hard work and these functions' output won't need any further processing or filtering before being handed over to Bash, resulting in faster branch and tag completion. These are some of the same tricks used in the previous commits to speed up refs completion, namely: - Extend both functions to accept prefix, current word and suffix positional parameters, all optional and all empty by default to keep the parameterless behavior unaltered. - Specify appropriate globbing patterns to 'git for-each-ref' to list only branches or tags matching the given current word parameter. - Modify the 'git for-each-ref --format=<...>' to include the given prefix and suffix. - Adjust all callsites to specify the proper prefix, current word and suffix parameters, and to fill COMPREPLY using __gitcomp_direct(). 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 227307a639c96b3579b7fe60840fdae123d1ee88
1 file changed +19 -6
contrib/completion/git-completion.bash
+19 -6
@@ -352,14 +352,27 @@ __git_index_files ()
352 done | sort | uniq
353 }
354
355 +# Lists branches from the local repository.
356 +# 1: A prefix to be added to each listed branch (optional).
357 +# 2: List only branches matching this word (optional; list all branches if
358 +# unset or empty).
359 +# 3: A suffix to be appended to each listed branch (optional).
360 __git_heads ()
361 {
357 - __git for-each-ref --format='%(refname:strip=2)' refs/heads
362 + local pfx="${1-}" cur_="${2-}" sfx="${3-}"
363 +
364 + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
365 + "refs/heads/$cur_*" "refs/heads/$cur_*/**"
366 }
367
368 +# Lists tags from the local repository.
369 +# Accepts the same positional parameters as __git_heads() above.
370 __git_tags ()
371 {
362 - __git for-each-ref --format='%(refname:strip=2)' refs/tags
372 + local pfx="${1-}" cur_="${2-}" sfx="${3-}"
373 +
374 + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
375 + "refs/tags/$cur_*" "refs/tags/$cur_*/**"
376 }
377
378 # Lists refs from the local (by default) or from a remote repository.
@@ -1183,7 +1196,7 @@ _git_branch ()
1196 ;;
1197 *)
1198 if [ $only_local_ref = "y" -a $has_r = "n" ]; then
1186 - __gitcomp_nl "$(__git_heads)"
1199 + __gitcomp_direct "$(__git_heads "" "$cur" " ")"
1200 else
1201 __git_complete_refs
1202 fi
@@ -2178,7 +2191,7 @@ _git_config ()
2191 ;;
2192 branch.*)
2193 local pfx="${cur%.*}." cur_="${cur#*.}"
2181 - __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
2194 + __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
2195 __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
2196 return
2197 ;;
@@ -2824,7 +2837,7 @@ _git_tag ()
2837 i="${words[c]}"
2838 case "$i" in
2839 -d|-v)
2827 - __gitcomp_nl "$(__git_tags)"
2840 + __gitcomp_direct "$(__git_tags "" "$cur" " ")"
2841 return
2842 ;;
2843 -f)
@@ -2839,7 +2852,7 @@ _git_tag ()
2852 ;;
2853 -*|tag)
2854 if [ $f = 1 ]; then
2842 - __gitcomp_nl "$(__git_tags)"
2855 + __gitcomp_direct "$(__git_tags "" "$cur" " ")"
2856 fi
2857 ;;
2858 *)