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>
This commit is contained in:
SZEDER Gábor 2017-03-23 16:29:13 +01:00 коммит произвёл Junio C Hamano
Родитель 15b4a16395
Коммит 2ea328a119
2 изменённых файлов: 45 добавлений и 7 удалений

Просмотреть файл

@ -354,6 +354,8 @@ __git_tags ()
# Can be the name of a configured remote, a path, or a URL. # 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 # 2: In addition to local refs, list unique branches from refs/remotes/ for
# 'git checkout's tracking DWIMery (optional; ignored, if set but empty). # 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
# 3: Currently ignored.
# 4: The current ref to be completed (optional).
# #
# Use __git_complete_refs() instead. # Use __git_complete_refs() instead.
__git_refs () __git_refs ()
@ -361,6 +363,7 @@ __git_refs ()
local i hash dir track="${2-}" local i hash dir track="${2-}"
local list_refs_from=path remote="${1-}" local list_refs_from=path remote="${1-}"
local format refs pfx local format refs pfx
local cur_="${4-$cur}"
__git_find_repo_path __git_find_repo_path
dir="$__git_repo_path" dir="$__git_repo_path"
@ -384,14 +387,17 @@ __git_refs ()
fi fi
if [ "$list_refs_from" = path ]; then if [ "$list_refs_from" = path ]; then
case "$cur" in case "$cur_" in
refs|refs/*) refs|refs/*)
format="refname" format="refname"
refs="${cur%/*}" refs="${cur_%/*}"
track="" track=""
;; ;;
*) *)
[[ "$cur" == ^* ]] && pfx="^" if [[ "$cur_" == ^* ]]; then
pfx="^"
cur_=${cur_#^}
fi
for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
if [ -e "$dir/$i" ]; then echo $pfx$i; fi if [ -e "$dir/$i" ]; then echo $pfx$i; fi
done done
@ -411,16 +417,16 @@ __git_refs ()
while read -r entry; do while read -r entry; do
eval "$entry" eval "$entry"
ref="${ref#*/}" ref="${ref#*/}"
if [[ "$ref" == "$cur"* ]]; then if [[ "$ref" == "$cur_"* ]]; then
echo "$ref" echo "$ref"
fi fi
done | sort | uniq -u done | sort | uniq -u
fi fi
return return
fi fi
case "$cur" in case "$cur_" in
refs|refs/*) refs|refs/*)
__git ls-remote "$remote" "$cur*" | \ __git ls-remote "$remote" "$cur_*" | \
while read -r hash i; do while read -r hash i; do
case "$i" in case "$i" in
*^{}) ;; *^{}) ;;
@ -475,7 +481,8 @@ __git_complete_refs ()
shift shift
done done
__gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx" __gitcomp_nl "$(__git_refs "$remote" "$track" "" "$cur_")" \
"$pfx" "$cur_" "$sfx"
} }
# __git_refs2 requires 1 argument (to pass to __git_refs) # __git_refs2 requires 1 argument (to pass to __git_refs)

Просмотреть файл

@ -775,6 +775,37 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer
test_cmp expected "$actual" 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_complete_refs - simple' ' test_expect_success '__git_complete_refs - simple' '
sed -e "s/Z$//" >expected <<-EOF && sed -e "s/Z$//" >expected <<-EOF &&
HEAD Z HEAD Z