Merge branch 'sg/completion-refs-speedup'

The refs completion for large number of refs has been sped up,
partly by giving up disambiguating ambiguous refs and partly by
eliminating most of the shell processing between 'git for-each-ref'
and 'ls-remote' and Bash's completion facility.

* sg/completion-refs-speedup:
  completion: speed up branch and tag completion
  completion: fill COMPREPLY directly when completing fetch refspecs
  completion: fill COMPREPLY directly when completing refs
  completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMery
  completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMery
  completion: let 'for-each-ref' strip the remote name from remote branches
  completion: let 'for-each-ref' and 'ls-remote' filter matching refs
  completion: don't disambiguate short refs
  completion: don't disambiguate tags and branches
  completion: support excluding full refs
  completion: support completing fully qualified non-fast-forward refspecs
  completion: support completing full refs after '--option=refs/<TAB>'
  completion: wrap __git_refs() for better option parsing
  completion: remove redundant __gitcomp_nl() options from _git_commit()
This commit is contained in:
Junio C Hamano 2017-03-30 14:07:14 -07:00
commit bf650608be
3 changed files with 577 additions and 71 deletions

View File

@ -213,6 +213,20 @@ _get_comp_words_by_ref ()
}
fi
# Fills the COMPREPLY array with prefiltered words without any additional
# processing.
# Callers must take care of providing only words that match the current word
# to be completed and adding any prefix and/or suffix (trailing space!), if
# necessary.
# 1: List of newline-separated matching completion words, complete with
# prefix and suffix.
__gitcomp_direct ()
{
local IFS=$'\n'
COMPREPLY=($1)
}
__gitcompappend ()
{
local x i=${#COMPREPLY[@]}
@ -338,14 +352,27 @@ __git_index_files ()
done | sort | uniq
}
# Lists branches from the local repository.
# 1: A prefix to be added to each listed branch (optional).
# 2: List only branches matching this word (optional; list all branches if
# unset or empty).
# 3: A suffix to be appended to each listed branch (optional).
__git_heads ()
{
__git for-each-ref --format='%(refname:short)' refs/heads
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
"refs/heads/$cur_*" "refs/heads/$cur_*/**"
}
# Lists tags from the local repository.
# Accepts the same positional parameters as __git_heads() above.
__git_tags ()
{
__git for-each-ref --format='%(refname:short)' refs/tags
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
"refs/tags/$cur_*" "refs/tags/$cur_*/**"
}
# Lists refs from the local (by default) or from a remote repository.
@ -354,11 +381,21 @@ __git_tags ()
# Can be the name of a configured remote, a path, or a URL.
# 2: In addition to local refs, list unique branches from refs/remotes/ for
# 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
# 3: A prefix to be added to each listed ref (optional).
# 4: List only refs matching this word (optional; list all refs if unset or
# empty).
# 5: A suffix to be appended to each listed ref (optional; ignored, if set
# but empty).
#
# Use __git_complete_refs() instead.
__git_refs ()
{
local i hash dir track="${2-}"
local list_refs_from=path remote="${1-}"
local format refs pfx
local format refs
local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
local match="${4-}"
local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
__git_find_repo_path
dir="$__git_repo_path"
@ -382,63 +419,78 @@ __git_refs ()
fi
if [ "$list_refs_from" = path ]; then
case "$cur" in
if [[ "$cur_" == ^* ]]; then
pfx="$pfx^"
fer_pfx="$fer_pfx^"
cur_=${cur_#^}
match=${match#^}
fi
case "$cur_" in
refs|refs/*)
format="refname"
refs="${cur%/*}"
refs=("$match*" "$match*/**")
track=""
;;
*)
[[ "$cur" == ^* ]] && pfx="^"
for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
if [ -e "$dir/$i" ]; then echo $pfx$i; fi
case "$i" in
$match*)
if [ -e "$dir/$i" ]; then
echo "$pfx$i$sfx"
fi
;;
esac
done
format="refname:short"
refs="refs/tags refs/heads refs/remotes"
format="refname:strip=2"
refs=("refs/tags/$match*" "refs/tags/$match*/**"
"refs/heads/$match*" "refs/heads/$match*/**"
"refs/remotes/$match*" "refs/remotes/$match*/**")
;;
esac
__git_dir="$dir" __git for-each-ref --format="$pfx%($format)" \
$refs
__git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
"${refs[@]}"
if [ -n "$track" ]; then
# employ the heuristic used by git checkout
# Try to find a remote branch that matches the completion word
# but only output if the branch name is unique
local ref entry
__git for-each-ref --shell --format="ref=%(refname:short)" \
"refs/remotes/" | \
while read -r entry; do
eval "$entry"
ref="${ref#*/}"
if [[ "$ref" == "$cur"* ]]; then
echo "$ref"
fi
done | sort | uniq -u
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
--sort="refname:strip=3" \
"refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \
uniq -u
fi
return
fi
case "$cur" in
case "$cur_" in
refs|refs/*)
__git ls-remote "$remote" "$cur*" | \
__git ls-remote "$remote" "$match*" | \
while read -r hash i; do
case "$i" in
*^{}) ;;
*) echo "$i" ;;
*) echo "$pfx$i$sfx" ;;
esac
done
;;
*)
if [ "$list_refs_from" = remote ]; then
echo "HEAD"
__git for-each-ref --format="%(refname:short)" \
"refs/remotes/$remote/" | sed -e "s#^$remote/##"
case "HEAD" in
$match*) echo "${pfx}HEAD$sfx" ;;
esac
__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
"refs/remotes/$remote/$match*" \
"refs/remotes/$remote/$match*/**"
else
__git ls-remote "$remote" HEAD \
"refs/tags/*" "refs/heads/*" "refs/remotes/*" |
local query_symref
case "HEAD" in
$match*) query_symref="HEAD" ;;
esac
__git ls-remote "$remote" $query_symref \
"refs/tags/$match*" "refs/heads/$match*" \
"refs/remotes/$match*" |
while read -r hash i; do
case "$i" in
*^{}) ;;
refs/*) echo "${i#refs/*/}" ;;
*) echo "$i" ;; # symbolic refs
refs/*) echo "$pfx${i#refs/*/}$sfx" ;;
*) echo "$pfx$i$sfx" ;; # symbolic refs
esac
done
fi
@ -446,7 +498,38 @@ __git_refs ()
esac
}
# Completes refs, short and long, local and remote, symbolic and pseudo.
#
# Usage: __git_complete_refs [<option>]...
# --remote=<remote>: The remote to list refs from, can be the name of a
# configured remote, a path, or a URL.
# --track: List unique remote branches for 'git checkout's tracking DWIMery.
# --pfx=<prefix>: A prefix to be added to each ref.
# --cur=<word>: The current ref to be completed. Defaults to the current
# word to be completed.
# --sfx=<suffix>: A suffix to be appended to each ref instead of the default
# space.
__git_complete_refs ()
{
local remote track pfx cur_="$cur" sfx=" "
while test $# != 0; do
case "$1" in
--remote=*) remote="${1##--remote=}" ;;
--track) track="yes" ;;
--pfx=*) pfx="${1##--pfx=}" ;;
--cur=*) cur_="${1##--cur=}" ;;
--sfx=*) sfx="${1##--sfx=}" ;;
*) return 1 ;;
esac
shift
done
__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
}
# __git_refs2 requires 1 argument (to pass to __git_refs)
# Deprecated: use __git_complete_fetch_refspecs() instead.
__git_refs2 ()
{
local i
@ -455,6 +538,24 @@ __git_refs2 ()
done
}
# Completes refspecs for fetching from a remote repository.
# 1: The remote repository.
# 2: A prefix to be added to each listed refspec (optional).
# 3: The ref to be completed as a refspec instead of the current word to be
# completed (optional)
# 4: A suffix to be appended to each listed refspec instead of the default
# space (optional).
__git_complete_fetch_refspecs ()
{
local i remote="$1" pfx="${2-}" cur_="${3-$cur}" sfx="${4- }"
__gitcomp_direct "$(
for i in $(__git_refs "$remote" "" "" "$cur_") ; do
echo "$pfx$i:$i$sfx"
done
)"
}
# __git_refs_remotes requires 1 argument (to pass to ls-remote)
__git_refs_remotes ()
{
@ -554,15 +655,15 @@ __git_complete_revlist_file ()
*...*)
pfx="${cur_%...*}..."
cur_="${cur_#*...}"
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
__git_complete_refs --pfx="$pfx" --cur="$cur_"
;;
*..*)
pfx="${cur_%..*}.."
cur_="${cur_#*..}"
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
__git_complete_refs --pfx="$pfx" --cur="$cur_"
;;
*)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
esac
}
@ -647,23 +748,23 @@ __git_complete_remote_or_refspec ()
case "$cmd" in
fetch)
if [ $lhs = 1 ]; then
__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
__git_complete_fetch_refspecs "$remote" "$pfx" "$cur_"
else
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
__git_complete_refs --pfx="$pfx" --cur="$cur_"
fi
;;
pull|remote)
if [ $lhs = 1 ]; then
__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
else
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
__git_complete_refs --pfx="$pfx" --cur="$cur_"
fi
;;
push)
if [ $lhs = 1 ]; then
__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
__git_complete_refs --pfx="$pfx" --cur="$cur_"
else
__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
fi
;;
esac
@ -1066,7 +1167,7 @@ _git_bisect ()
case "$subcommand" in
bad|good|reset|skip|start)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
*)
;;
@ -1088,7 +1189,7 @@ _git_branch ()
case "$cur" in
--set-upstream-to=*)
__gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
__git_complete_refs --cur="${cur##--set-upstream-to=}"
;;
--*)
__gitcomp "
@ -1101,9 +1202,9 @@ _git_branch ()
;;
*)
if [ $only_local_ref = "y" -a $has_r = "n" ]; then
__gitcomp_nl "$(__git_heads)"
__gitcomp_direct "$(__git_heads "" "$cur" " ")"
else
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
fi
;;
esac
@ -1146,18 +1247,18 @@ _git_checkout ()
*)
# check if --track, --no-track, or --no-guess was specified
# if so, disable DWIM mode
local flags="--track --no-track --no-guess" track=1
local flags="--track --no-track --no-guess" track_opt="--track"
if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
track=''
track_opt=''
fi
__gitcomp_nl "$(__git_refs '' $track)"
__git_complete_refs $track_opt
;;
esac
}
_git_cherry ()
{
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_cherry_pick ()
@ -1172,7 +1273,7 @@ _git_cherry_pick ()
__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
;;
*)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
esac
}
@ -1224,7 +1325,7 @@ _git_commit ()
{
case "$prev" in
-c|-C)
__gitcomp_nl "$(__git_refs)" "" "${cur}"
__git_complete_refs
return
;;
esac
@ -1237,7 +1338,7 @@ _git_commit ()
;;
--reuse-message=*|--reedit-message=*|\
--fixup=*|--squash=*)
__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
__git_complete_refs --cur="${cur#*=}"
return
;;
--untracked-files=*)
@ -1277,7 +1378,7 @@ _git_describe ()
"
return
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
__git_diff_algorithms="myers minimal patience histogram"
@ -1466,7 +1567,7 @@ _git_grep ()
;;
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_help ()
@ -1640,7 +1741,7 @@ _git_merge ()
--rerere-autoupdate --no-rerere-autoupdate --abort --continue"
return
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_mergetool ()
@ -1665,7 +1766,7 @@ _git_merge_base ()
return
;;
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_mv ()
@ -1703,7 +1804,7 @@ _git_notes ()
,*)
case "$prev" in
--ref)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
*)
__gitcomp "$subcommands --ref"
@ -1712,7 +1813,7 @@ _git_notes ()
;;
add,--reuse-message=*|append,--reuse-message=*|\
add,--reedit-message=*|append,--reedit-message=*)
__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
__git_complete_refs --cur="${cur#*=}"
;;
add,--*|append,--*)
__gitcomp '--file= --message= --reedit-message=
@ -1731,7 +1832,7 @@ _git_notes ()
-m|-F)
;;
*)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
esac
;;
@ -1769,10 +1870,10 @@ __git_complete_force_with_lease ()
--*=)
;;
*:*)
__gitcomp_nl "$(__git_refs)" "" "${cur_#*:}"
__git_complete_refs --cur="${cur_#*:}"
;;
*)
__gitcomp_nl "$(__git_refs)" "" "$cur_"
__git_complete_refs --cur="$cur_"
;;
esac
}
@ -1848,7 +1949,7 @@ _git_rebase ()
return
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_reflog ()
@ -1859,7 +1960,7 @@ _git_reflog ()
if [ -z "$subcommand" ]; then
__gitcomp "$subcommands"
else
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
fi
}
@ -2005,7 +2106,7 @@ _git_config ()
return
;;
branch.*.merge)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
return
;;
branch.*.rebase)
@ -2109,7 +2210,7 @@ _git_config ()
;;
branch.*)
local pfx="${cur%.*}." cur_="${cur#*.}"
__gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
__gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
return
;;
@ -2516,7 +2617,7 @@ _git_replace ()
return
;;
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_rerere ()
@ -2540,7 +2641,7 @@ _git_reset ()
return
;;
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_revert ()
@ -2559,7 +2660,7 @@ _git_revert ()
return
;;
esac
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
}
_git_rm ()
@ -2667,7 +2768,7 @@ _git_stash ()
;;
branch,*)
if [ $cword -eq 3 ]; then
__gitcomp_nl "$(__git_refs)";
__git_complete_refs
else
__gitcomp_nl "$(__git stash list \
| sed -n -e 's/:.*//p')"
@ -2834,7 +2935,7 @@ _git_tag ()
i="${words[c]}"
case "$i" in
-d|-v)
__gitcomp_nl "$(__git_tags)"
__gitcomp_direct "$(__git_tags "" "$cur" " ")"
return
;;
-f)
@ -2849,11 +2950,11 @@ _git_tag ()
;;
-*|tag)
if [ $f = 1 ]; then
__gitcomp_nl "$(__git_tags)"
__gitcomp_direct "$(__git_tags "" "$cur" " ")"
fi
;;
*)
__gitcomp_nl "$(__git_refs)"
__git_complete_refs
;;
esac
@ -3024,6 +3125,15 @@ if [[ -n ${ZSH_VERSION-} ]]; then
esac
}
__gitcomp_direct ()
{
emulate -L zsh
local IFS=$'\n'
compset -P '*[=:]'
compadd -Q -- ${=1} && _ret=0
}
__gitcomp_nl ()
{
emulate -L zsh

View File

@ -67,6 +67,15 @@ __gitcomp ()
esac
}
__gitcomp_direct ()
{
emulate -L zsh
local IFS=$'\n'
compset -P '*[=:]'
compadd -Q -- ${=1} && _ret=0
}
__gitcomp_nl ()
{
emulate -L zsh

View File

@ -400,6 +400,22 @@ test_expect_success '__gitdir - remote as argument' '
test_cmp expected "$actual"
'
test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' '
sed -e "s/Z$//g" >expected <<-EOF &&
with-trailing-space Z
without-trailing-spaceZ
--option Z
--option=Z
$invalid_variable_name Z
EOF
(
cur=should_be_ignored &&
__gitcomp_direct "$(cat expected)" &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__gitcomp - trailing space - options' '
test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
--reset-author" <<-EOF
@ -555,6 +571,9 @@ test_expect_success '__git_refs - full refs' '
cat >expected <<-EOF &&
refs/heads/master
refs/heads/matching-branch
refs/remotes/other/branch-in-other
refs/remotes/other/master-in-other
refs/tags/matching-tag
EOF
(
cur=refs/heads/ &&
@ -620,6 +639,7 @@ test_expect_success '__git_refs - configured remote' '
test_expect_success '__git_refs - configured remote - full refs' '
cat >expected <<-EOF &&
HEAD
refs/heads/branch-in-other
refs/heads/master-in-other
refs/tags/tag-in-other
@ -648,6 +668,7 @@ test_expect_success '__git_refs - configured remote - repo given on the command
test_expect_success '__git_refs - configured remote - full refs - repo given on the command line' '
cat >expected <<-EOF &&
HEAD
refs/heads/branch-in-other
refs/heads/master-in-other
refs/tags/tag-in-other
@ -692,6 +713,7 @@ test_expect_success '__git_refs - URL remote' '
test_expect_success '__git_refs - URL remote - full refs' '
cat >expected <<-EOF &&
HEAD
refs/heads/branch-in-other
refs/heads/master-in-other
refs/tags/tag-in-other
@ -775,6 +797,371 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer
test_cmp expected "$actual"
'
test_expect_success '__git_refs - after --opt=' '
cat >expected <<-EOF &&
HEAD
master
matching-branch
other/branch-in-other
other/master-in-other
matching-tag
EOF
(
cur="--opt=" &&
__git_refs "" "" "" "" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - after --opt= - full refs' '
cat >expected <<-EOF &&
refs/heads/master
refs/heads/matching-branch
refs/remotes/other/branch-in-other
refs/remotes/other/master-in-other
refs/tags/matching-tag
EOF
(
cur="--opt=refs/" &&
__git_refs "" "" "" refs/ >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git refs - exluding refs' '
cat >expected <<-EOF &&
^HEAD
^master
^matching-branch
^other/branch-in-other
^other/master-in-other
^matching-tag
EOF
(
cur=^ &&
__git_refs >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git refs - exluding full refs' '
cat >expected <<-EOF &&
^refs/heads/master
^refs/heads/matching-branch
^refs/remotes/other/branch-in-other
^refs/remotes/other/master-in-other
^refs/tags/matching-tag
EOF
(
cur=^refs/ &&
__git_refs >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'setup for filtering matching refs' '
git branch matching/branch &&
git tag matching/tag &&
git -C otherrepo branch matching/branch-in-other &&
git fetch --no-tags other &&
rm -f .git/FETCH_HEAD
'
test_expect_success '__git_refs - dont filter refs unless told so' '
cat >expected <<-EOF &&
HEAD
master
matching-branch
matching/branch
other/branch-in-other
other/master-in-other
other/matching/branch-in-other
matching-tag
matching/tag
EOF
(
cur=master &&
__git_refs >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs' '
cat >expected <<-EOF &&
matching-branch
matching/branch
matching-tag
matching/tag
EOF
(
cur=mat &&
__git_refs "" "" "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs - full refs' '
cat >expected <<-EOF &&
refs/heads/matching-branch
refs/heads/matching/branch
EOF
(
cur=refs/heads/mat &&
__git_refs "" "" "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs - remote on local file system' '
cat >expected <<-EOF &&
master-in-other
matching/branch-in-other
EOF
(
cur=ma &&
__git_refs otherrepo "" "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs - configured remote' '
cat >expected <<-EOF &&
master-in-other
matching/branch-in-other
EOF
(
cur=ma &&
__git_refs other "" "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs - remote - full refs' '
cat >expected <<-EOF &&
refs/heads/master-in-other
refs/heads/matching/branch-in-other
EOF
(
cur=refs/heads/ma &&
__git_refs other "" "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_refs - only matching refs - checkout DWIMery' '
cat >expected <<-EOF &&
matching-branch
matching/branch
matching-tag
matching/tag
matching/branch-in-other
EOF
for remote_ref in refs/remotes/other/ambiguous \
refs/remotes/remote/ambiguous \
refs/remotes/remote/branch-in-remote
do
git update-ref $remote_ref master &&
test_when_finished "git update-ref -d $remote_ref"
done &&
(
cur=mat &&
__git_refs "" 1 "" "$cur" >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success 'teardown after filtering matching refs' '
git branch -d matching/branch &&
git tag -d matching/tag &&
git update-ref -d refs/remotes/other/matching/branch-in-other &&
git -C otherrepo branch -D matching/branch-in-other
'
test_expect_success '__git_refs - for-each-ref format specifiers in prefix' '
cat >expected <<-EOF &&
evil-%%-%42-%(refname)..master
EOF
(
cur="evil-%%-%42-%(refname)..mas" &&
__git_refs "" "" "evil-%%-%42-%(refname).." mas >"$actual"
) &&
test_cmp expected "$actual"
'
test_expect_success '__git_complete_refs - simple' '
sed -e "s/Z$//" >expected <<-EOF &&
HEAD Z
master Z
matching-branch Z
other/branch-in-other Z
other/master-in-other Z
matching-tag Z
EOF
(
cur= &&
__git_complete_refs &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - matching' '
sed -e "s/Z$//" >expected <<-EOF &&
matching-branch Z
matching-tag Z
EOF
(
cur=mat &&
__git_complete_refs &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - remote' '
sed -e "s/Z$//" >expected <<-EOF &&
HEAD Z
branch-in-other Z
master-in-other Z
EOF
(
cur=
__git_complete_refs --remote=other &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - track' '
sed -e "s/Z$//" >expected <<-EOF &&
HEAD Z
master Z
matching-branch Z
other/branch-in-other Z
other/master-in-other Z
matching-tag Z
branch-in-other Z
master-in-other Z
EOF
(
cur=
__git_complete_refs --track &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - current word' '
sed -e "s/Z$//" >expected <<-EOF &&
matching-branch Z
matching-tag Z
EOF
(
cur="--option=mat" &&
__git_complete_refs --cur="${cur#*=}" &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - prefix' '
sed -e "s/Z$//" >expected <<-EOF &&
v1.0..matching-branch Z
v1.0..matching-tag Z
EOF
(
cur=v1.0..mat &&
__git_complete_refs --pfx=v1.0.. --cur=mat &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_refs - suffix' '
cat >expected <<-EOF &&
HEAD.
master.
matching-branch.
other/branch-in-other.
other/master-in-other.
matching-tag.
EOF
(
cur= &&
__git_complete_refs --sfx=. &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_fetch_refspecs - simple' '
sed -e "s/Z$//" >expected <<-EOF &&
HEAD:HEAD Z
branch-in-other:branch-in-other Z
master-in-other:master-in-other Z
EOF
(
cur= &&
__git_complete_fetch_refspecs other &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_fetch_refspecs - matching' '
sed -e "s/Z$//" >expected <<-EOF &&
branch-in-other:branch-in-other Z
EOF
(
cur=br &&
__git_complete_fetch_refspecs other "" br &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_fetch_refspecs - prefix' '
sed -e "s/Z$//" >expected <<-EOF &&
+HEAD:HEAD Z
+branch-in-other:branch-in-other Z
+master-in-other:master-in-other Z
EOF
(
cur="+" &&
__git_complete_fetch_refspecs other "+" "" &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_fetch_refspecs - fully qualified' '
sed -e "s/Z$//" >expected <<-EOF &&
refs/heads/branch-in-other:refs/heads/branch-in-other Z
refs/heads/master-in-other:refs/heads/master-in-other Z
refs/tags/tag-in-other:refs/tags/tag-in-other Z
EOF
(
cur=refs/ &&
__git_complete_fetch_refspecs other "" refs/ &&
print_comp
) &&
test_cmp expected out
'
test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' '
sed -e "s/Z$//" >expected <<-EOF &&
+refs/heads/branch-in-other:refs/heads/branch-in-other Z
+refs/heads/master-in-other:refs/heads/master-in-other Z
+refs/tags/tag-in-other:refs/tags/tag-in-other Z
EOF
(
cur=+refs/ &&
__git_complete_fetch_refspecs other + refs/ &&
print_comp
) &&
test_cmp expected out
'
test_expect_success 'teardown after ref completion' '
git branch -d matching-branch &&
git tag -d matching-tag &&