__git_heads ()
{
- __git for-each-ref --format='%(refname:short)' refs/heads
+ __git for-each-ref --format='%(refname:strip=2)' refs/heads
}
__git_tags ()
{
- __git for-each-ref --format='%(refname:short)' refs/tags
+ __git for-each-ref --format='%(refname:strip=2)' refs/tags
}
# Lists refs from the local (by default) or from a remote repository.
# 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: Currently ignored.
-# 4: The current ref to be completed (optional).
+# 4: List only refs matching this word (optional; list all refs if unset or
+# empty).
#
# Use __git_complete_refs() instead.
__git_refs ()
local list_refs_from=path remote="${1-}"
local format refs pfx
local cur_="${4-$cur}"
+ local match="${4-}"
__git_find_repo_path
dir="$__git_repo_path"
fi
if [ "$list_refs_from" = path ]; then
+ if [[ "$cur_" == ^* ]]; then
+ pfx="^"
+ cur_=${cur_#^}
+ match=${match#^}
+ fi
case "$cur_" in
refs|refs/*)
format="refname"
- refs="${cur_%/*}"
+ refs=("$match*" "$match*/**")
track=""
;;
*)
- if [[ "$cur_" == ^* ]]; then
- pfx="^"
- cur_=${cur_#^}
- fi
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
+ 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
+ "${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="%(refname:strip=3)" \
+ --sort="refname:strip=3" \
+ "refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \
+ uniq -u
fi
return
fi
case "$cur_" in
refs|refs/*)
- __git ls-remote "$remote" "$cur_*" | \
+ __git ls-remote "$remote" "$match*" | \
while read -r hash i; do
case "$i" in
*^{}) ;;
;;
*)
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 "HEAD" ;;
+ esac
+ __git for-each-ref --format="%(refname:strip=3)" \
+ "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
*^{}) ;;