Skip to content

Commit 67ffa11

Browse files
spearceJunio C Hamano
authored andcommitted
Fix broken bash completion of local refs.
Commit 35e65ec broke completion of local refs, e.g. "git pull . fo<tab>" no longer would complete to "foo". Instead it printed out an internal git error ("fatal: Not a git repository: '.'"). The break occurred when I tried to improve performance by switching from git-peek-remote to git-for-each-ref. Apparently git-peek-remote will drop into directory "$1/.git" (where $1 is its first parameter) if it is given a repository with a working directory. This allowed the bash completion code to work properly even though it was not handing over the true repository directory. So now we do a stat in bash to see if we need to add "/.git" to the path string before running any command with --git-dir. I also tried to optimize away two "git rev-parse --git-dir" invocations in common cases like "git log fo<tab>" as typically the user is in the top level directory of their project and therefore the .git subdirectory is in the current working directory. This should make a difference on systems where fork+exec might take a little while. Signed-off-by: Shawn O. Pearce <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4548e85 commit 67ffa11

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

contrib/completion/git-completion.bash

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,19 @@
3434

3535
__gitdir ()
3636
{
37-
echo "${__git_dir:-$(git rev-parse --git-dir 2>/dev/null)}"
37+
if [ -z "$1" ]; then
38+
if [ -n "$__git_dir" ]; then
39+
echo "$__git_dir"
40+
elif [ -d .git ]; then
41+
echo .git
42+
else
43+
git rev-parse --git-dir 2>/dev/null
44+
fi
45+
elif [ -d "$1/.git" ]; then
46+
echo "$1/.git"
47+
else
48+
echo "$1"
49+
fi
3850
}
3951

4052
__git_ps1 ()
@@ -51,7 +63,7 @@ __git_ps1 ()
5163

5264
__git_heads ()
5365
{
54-
local cmd i is_hash=y dir="${1:-$(__gitdir)}"
66+
local cmd i is_hash=y dir="$(__gitdir "$1")"
5567
if [ -d "$dir" ]; then
5668
for i in $(git --git-dir="$dir" \
5769
for-each-ref --format='%(refname)' \
@@ -60,7 +72,7 @@ __git_heads ()
6072
done
6173
return
6274
fi
63-
for i in $(git-ls-remote "$dir" 2>/dev/null); do
75+
for i in $(git-ls-remote "$1" 2>/dev/null); do
6476
case "$is_hash,$i" in
6577
y,*) is_hash=n ;;
6678
n,*^{}) is_hash=y ;;
@@ -72,7 +84,7 @@ __git_heads ()
7284

7385
__git_refs ()
7486
{
75-
local cmd i is_hash=y dir="${1:-$(__gitdir)}"
87+
local cmd i is_hash=y dir="$(__gitdir "$1")"
7688
if [ -d "$dir" ]; then
7789
if [ -e "$dir/HEAD" ]; then echo HEAD; fi
7890
for i in $(git --git-dir="$dir" \
@@ -101,20 +113,9 @@ __git_refs ()
101113

102114
__git_refs2 ()
103115
{
104-
local cmd i is_hash=y dir="${1:-$(__gitdir)}"
105-
if [ -d "$dir" ]; then
106-
cmd=git-peek-remote
107-
else
108-
cmd=git-ls-remote
109-
fi
110-
for i in $($cmd "$dir" 2>/dev/null); do
111-
case "$is_hash,$i" in
112-
y,*) is_hash=n ;;
113-
n,*^{}) is_hash=y ;;
114-
n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}:${i#refs/tags/}" ;;
115-
n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}:${i#refs/heads/}" ;;
116-
n,*) is_hash=y; echo "$i:$i" ;;
117-
esac
116+
local i
117+
for i in $(__git_refs "$1"); do
118+
echo "$i:$i"
118119
done
119120
}
120121

0 commit comments

Comments
 (0)