git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCHv3 00/16] bash prompt speedup
@ 2013-06-24 16:39 SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 01/16] bash prompt: fix redirection coding style in tests SZEDER Gábor
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Hi,

displaying the git-specific bash prompt on Windows/MinGW takes quite
long, long enough to be noticeable.  This is mainly caused by the
numerous fork()s and exec()s to create subshells and run git or other
commands, which are rather expensive on Windows.

This patch series eliminates many command substitutions and command
executions in __git_ps1() from top to bottom by replacing them with
bash builtins or consolidating them.  A few timing results are shown
in the log message of the last patch.

Changes since v2 [1]:

 - The detached HEAD abbreviated object name is now unique and
   respects core.abbrev; see patches 5 and 11, replacing v2's patch 9.
   (This is why I asked the detached HEAD before root commit thing
   yesterday.)  
 - Patches 12 and 16 are new.
 - Incorporated Peff's suggestion about using the 'write_script'
   helper into patch 2.
 - Incorporated Eric's typofix.
 - Rephrased a few commit messages.

It applies on top of current master; 2847cae8 (prompt: squelch error
output from cat, 2013-06-14) graduated recently.

This patch series will conflict with Eduardo's work on refactoring the
colorizing function, and the conflict is not trivial.  Although there
are still some open questions left with that series (using tput, zsh
tests), those won't affect the conflicts between the two patch series.
So, for the convenience of our maintainer, I picked up Eduardo's
series, took the liberty to apply a fixup commit on top with my
suggestions from [2], merged the two series, and published the result
at:

  https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization

Eduardo, could you please also check that my conflict resolution is
correct?  Thanks.


Best,
Gábor


[1] - http://thread.gmane.org/gmane.comp.version-control.git/228132
[2] - http://article.gmane.org/gmane.comp.version-control.git/228707


SZEDER Gábor (16):
  bash prompt: fix redirection coding style in tests
  bash prompt: use 'write_script' helper in interactive rebase test
  completion, bash prompt: move __gitdir() tests to completion test
    suite
  bash prompt: add a test for symbolic link symbolic refs
  bash prompt: print unique detached HEAD abbreviated object name
  bash prompt: return early from __git_ps1() when not in a git
    repository
  bash prompt: run 'git rev-parse --git-dir' directly instead of
    __gitdir()
  bash prompt: use bash builtins to find out rebase state
  bash prompt: use bash builtins to find out current branch
  bash prompt: combine 'git rev-parse' executions in the main code path
  bash prompt: combine 'git rev-parse' for detached head
  bash prompt: use bash builtins to check for unborn branch for dirty
    state
  bash prompt: use bash builtins to check stash state
  bash prompt: avoid command substitution when checking for untracked
    files
  bash prompt: avoid command substitution when finalizing gitstring
  bash prompt: mention that PROMPT_COMMAND mode is faster

 contrib/completion/git-completion.bash |   2 -
 contrib/completion/git-prompt.sh       | 241 ++++++++++++------------
 t/t9902-completion.sh                  | 134 ++++++++++++++
 t/t9903-bash-prompt.sh                 | 323 +++++++++++----------------------
 4 files changed, 367 insertions(+), 333 deletions(-)

-- 
1.8.3.1.599.g4459181

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCHv3 01/16] bash prompt: fix redirection coding style in tests
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 02/16] bash prompt: use 'write_script' helper in interactive rebase test SZEDER Gábor
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Use '>file' instead of '> file', in accordance with the coding
guidelines.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 t/t9903-bash-prompt.sh | 232 ++++++++++++++++++++++++-------------------------
 1 file changed, 116 insertions(+), 116 deletions(-)

diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 15521cc4..7c7f8b97 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -14,98 +14,98 @@ actual="$TRASH_DIRECTORY/actual"
 test_expect_success 'setup for prompt tests' '
 	mkdir -p subdir/subsubdir &&
 	git init otherrepo &&
-	echo 1 > file &&
+	echo 1 >file &&
 	git add file &&
 	test_tick &&
 	git commit -m initial &&
 	git tag -a -m msg1 t1 &&
 	git checkout -b b1 &&
-	echo 2 > file &&
+	echo 2 >file &&
 	git commit -m "second b1" file &&
-	echo 3 > file &&
+	echo 3 >file &&
 	git commit -m "third b1" file &&
 	git tag -a -m msg2 t2 &&
 	git checkout -b b2 master &&
-	echo 0 > file &&
+	echo 0 >file &&
 	git commit -m "second b2" file &&
-	echo 00 > file &&
+	echo 00 >file &&
 	git commit -m "another b2" file &&
-	echo 000 > file &&
+	echo 000 >file &&
 	git commit -m "yet another b2" file &&
 	git checkout master
 '
 
 test_expect_success 'gitdir - from command line (through $__git_dir)' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
 	(
 		__git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - repo as argument' '
-	echo "otherrepo/.git" > expected &&
-	__gitdir "otherrepo" > "$actual" &&
+	echo "otherrepo/.git" >expected &&
+	__gitdir "otherrepo" >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - remote as argument' '
-	echo "remote" > expected &&
-	__gitdir "remote" > "$actual" &&
+	echo "remote" >expected &&
+	__gitdir "remote" >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - .git directory in cwd' '
-	echo ".git" > expected &&
-	__gitdir > "$actual" &&
+	echo ".git" >expected &&
+	__gitdir >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - .git directory in parent' '
-	echo "$(pwd -P)/.git" > expected &&
+	echo "$(pwd -P)/.git" >expected &&
 	(
 		cd subdir/subsubdir &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - cwd is a .git directory' '
-	echo "." > expected &&
+	echo "." >expected &&
 	(
 		cd .git &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - parent is a .git directory' '
-	echo "$(pwd -P)/.git" > expected &&
+	echo "$(pwd -P)/.git" >expected &&
 	(
 		cd .git/refs/heads &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
 	(
 		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
 		export GIT_DIR &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
 	(
 		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
 		export GIT_DIR &&
 		cd subdir &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
@@ -119,36 +119,36 @@ test_expect_success 'gitdir - non-existing $GIT_DIR' '
 '
 
 test_expect_success 'gitdir - gitfile in cwd' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
 	test_when_finished "rm -f subdir/.git" &&
 	(
 		cd subdir &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'gitdir - gitfile in parent' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
 	test_when_finished "rm -f subdir/.git" &&
 	(
 		cd subdir/subsubdir &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
 	mkdir otherrepo/dir &&
 	test_when_finished "rm -rf otherrepo/dir" &&
 	ln -s otherrepo/dir link &&
 	test_when_finished "rm -f link" &&
 	(
 		cd link &&
-		__gitdir > "$actual"
+		__gitdir >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
@@ -163,96 +163,96 @@ test_expect_success 'gitdir - not a git repository' '
 '
 
 test_expect_success 'prompt - branch name' '
-	printf " (master)" > expected &&
-	__git_ps1 > "$actual" &&
+	printf " (master)" >expected &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - detached head' '
-	printf " ((%s...))" $(git log -1 --format="%h" b1^) > expected &&
+	printf " ((%s...))" $(git log -1 --format="%h" b1^) >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - contains' '
-	printf " ((t2~1))" > expected &&
+	printf " ((t2~1))" >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=contains &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - branch' '
-	printf " ((b1~1))" > expected &&
+	printf " ((b1~1))" >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=branch &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - describe' '
-	printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) > expected &&
+	printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=describe &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - default' '
-	printf " ((t2))" > expected &&
+	printf " ((t2))" >expected &&
 	git checkout --detach b1 &&
 	test_when_finished "git checkout master" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - deep inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		cd .git/refs/heads &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside bare repository' '
-	printf " (BARE:master)" > expected &&
+	printf " (BARE:master)" >expected &&
 	git init --bare bare.git &&
 	test_when_finished "rm -rf bare.git" &&
 	(
 		cd bare.git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - interactive rebase' '
-	printf " (b1|REBASE-i 2/3)" > expected
+	printf " (b1|REBASE-i 2/3)" >expected
 	echo "#!$SHELL_PATH" >fake_editor.sh &&
 	cat >>fake_editor.sh <<\EOF &&
-echo "exec echo" > "$1"
-echo "edit $(git log -1 --format="%h")" >> "$1"
-echo "exec echo" >> "$1"
+echo "exec echo" >"$1"
+echo "edit $(git log -1 --format="%h")" >>"$1"
+echo "exec echo" >>"$1"
 EOF
 	test_when_finished "rm -f fake_editor.sh" &&
 	chmod a+x fake_editor.sh &&
@@ -261,277 +261,277 @@ EOF
 	test_when_finished "git checkout master" &&
 	git rebase -i HEAD^ &&
 	test_when_finished "git rebase --abort"
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase merge' '
-	printf " (b2|REBASE-m 1/3)" > expected &&
+	printf " (b2|REBASE-m 1/3)" >expected &&
 	git checkout b2 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git rebase --merge b1 b2 &&
 	test_when_finished "git rebase --abort" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase' '
-	printf " (b2|REBASE 1/3)" > expected &&
+	printf " (b2|REBASE 1/3)" >expected &&
 	git checkout b2 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git rebase b1 b2 &&
 	test_when_finished "git rebase --abort" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - merge' '
-	printf " (b1|MERGING)" > expected &&
+	printf " (b1|MERGING)" >expected &&
 	git checkout b1 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git merge b2 &&
 	test_when_finished "git reset --hard" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - cherry-pick' '
-	printf " (master|CHERRY-PICKING)" > expected &&
+	printf " (master|CHERRY-PICKING)" >expected &&
 	test_must_fail git cherry-pick b1 &&
 	test_when_finished "git reset --hard" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - bisect' '
-	printf " (master|BISECTING)" > expected &&
+	printf " (master|BISECTING)" >expected &&
 	git bisect start &&
 	test_when_finished "git bisect reset" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - clean' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty worktree' '
-	printf " (master *)" > expected &&
-	echo "dirty" > file &&
+	printf " (master *)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index' '
-	printf " (master +)" > expected &&
-	echo "dirty" > file &&
+	printf " (master +)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	git add -u &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index and worktree' '
-	printf " (master *+)" > expected &&
-	echo "dirty index" > file &&
+	printf " (master *+)" >expected &&
+	echo "dirty index" >file &&
 	test_when_finished "git reset --hard" &&
 	git add -u &&
-	echo "dirty worktree" > file &&
+	echo "dirty worktree" >file &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - before root commit' '
-	printf " (master #)" > expected &&
+	printf " (master #)" >expected &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
 		cd otherrepo &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config disabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState false &&
 	(
 		sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config enabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState true &&
 	(
 		sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config disabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState false &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config enabled' '
-	printf " (master *)" > expected &&
-	echo "dirty" > file &&
+	printf " (master *)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState true &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
-	echo "dirty" > file &&
+	printf " (GIT_DIR!)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - no stash' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - stash' '
-	printf " (master $)" > expected &&
+	printf " (master $)" >expected &&
 	echo 2 >file &&
 	git stash &&
 	test_when_finished "git stash drop" &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	echo 2 >file &&
 	git stash &&
 	test_when_finished "git stash drop" &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - no untracked files' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
 		cd otherrepo &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - untracked files' '
-	printf " (master %%)" > expected &&
+	printf " (master %%)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles false &&
 	(
 		sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config enabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles true &&
 	(
 		sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config disabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles false &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config enabled' '
-	printf " (master %%)" > expected &&
+	printf " (master %%)" >expected &&
 	test_config bash.showUntrackedFiles true &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - format string starting with dash' '
-	printf -- "-master" > expected &&
-	__git_ps1 "-%s" > "$actual" &&
+	printf -- "-master" >expected &&
+	__git_ps1 "-%s" >"$actual" &&
 	test_cmp expected "$actual"
 '
 
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 02/16] bash prompt: use 'write_script' helper in interactive rebase test
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 01/16] bash prompt: fix redirection coding style in tests SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 03/16] completion, bash prompt: move __gitdir() tests to completion test suite SZEDER Gábor
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 t/t9903-bash-prompt.sh | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 7c7f8b97..442b9a20 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -248,14 +248,12 @@ test_expect_success 'prompt - inside bare repository' '
 
 test_expect_success 'prompt - interactive rebase' '
 	printf " (b1|REBASE-i 2/3)" >expected
-	echo "#!$SHELL_PATH" >fake_editor.sh &&
-	cat >>fake_editor.sh <<\EOF &&
-echo "exec echo" >"$1"
-echo "edit $(git log -1 --format="%h")" >>"$1"
-echo "exec echo" >>"$1"
-EOF
+	write_script fake_editor.sh <<-\EOF &&
+		echo "exec echo" >"$1"
+		echo "edit $(git log -1 --format="%h")" >>"$1"
+		echo "exec echo" >>"$1"
+	EOF
 	test_when_finished "rm -f fake_editor.sh" &&
-	chmod a+x fake_editor.sh &&
 	test_set_editor "$TRASH_DIRECTORY/fake_editor.sh" &&
 	git checkout b1 &&
 	test_when_finished "git checkout master" &&
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 03/16] completion, bash prompt: move __gitdir() tests to completion test suite
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 01/16] bash prompt: fix redirection coding style in tests SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 02/16] bash prompt: use 'write_script' helper in interactive rebase test SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 04/16] bash prompt: add a test for symbolic link symbolic refs SZEDER Gábor
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Currently __gitdir() is duplicated in the git completion and prompt
scripts, while its tests are in the prompt test suite.  This patch
series is about to change __git_ps1() in a way that it won't need
__gitdir() anymore and __gitdir() will be removed from the prompt
script.

So move all __gitdir() tests from the prompt test suite over to the
completion test suite.  Update the setup tests so that they perform
only those steps that are necessary for each test suite.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 t/t9902-completion.sh  | 134 +++++++++++++++++++++++++++++++++++++++++++++++++
 t/t9903-bash-prompt.sh | 128 ----------------------------------------------
 2 files changed, 134 insertions(+), 128 deletions(-)

diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 81a1657e..5469dee8 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -122,6 +122,140 @@ test_gitcomp_nl ()
 
 invalid_variable_name='${foo.bar}'
 
+actual="$TRASH_DIRECTORY/actual"
+
+test_expect_success 'setup for __gitdir tests' '
+	mkdir -p subdir/subsubdir &&
+	git init otherrepo
+'
+
+test_expect_success '__gitdir - from command line (through $__git_dir)' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		__git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - repo as argument' '
+	echo "otherrepo/.git" >expected &&
+	__gitdir "otherrepo" >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - remote as argument' '
+	echo "remote" >expected &&
+	__gitdir "remote" >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in cwd' '
+	echo ".git" >expected &&
+	__gitdir >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in parent' '
+	echo "$(pwd -P)/.git" >expected &&
+	(
+		cd subdir/subsubdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - cwd is a .git directory' '
+	echo "." >expected &&
+	(
+		cd .git &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - parent is a .git directory' '
+	echo "$(pwd -P)/.git" >expected &&
+	(
+		cd .git/refs/heads &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+		export GIT_DIR &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+		export GIT_DIR &&
+		cd subdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - non-existing $GIT_DIR' '
+	(
+		GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
+		export GIT_DIR &&
+		test_must_fail __gitdir
+	)
+'
+
+test_expect_success '__gitdir - gitfile in cwd' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+	test_when_finished "rm -f subdir/.git" &&
+	(
+		cd subdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - gitfile in parent' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+	test_when_finished "rm -f subdir/.git" &&
+	(
+		cd subdir/subsubdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	mkdir otherrepo/dir &&
+	test_when_finished "rm -rf otherrepo/dir" &&
+	ln -s otherrepo/dir link &&
+	test_when_finished "rm -f link" &&
+	(
+		cd link &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - not a git repository' '
+	(
+		cd subdir/subsubdir &&
+		GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
+		export GIT_CEILING_DIRECTORIES &&
+		test_must_fail __gitdir
+	)
+'
+
 test_expect_success '__gitcomp - trailing space - options' '
 	test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 		--reset-author" <<-EOF
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 442b9a20..df36239a 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -12,7 +12,6 @@ test_description='test git-specific bash prompt functions'
 actual="$TRASH_DIRECTORY/actual"
 
 test_expect_success 'setup for prompt tests' '
-	mkdir -p subdir/subsubdir &&
 	git init otherrepo &&
 	echo 1 >file &&
 	git add file &&
@@ -35,133 +34,6 @@ test_expect_success 'setup for prompt tests' '
 	git checkout master
 '
 
-test_expect_success 'gitdir - from command line (through $__git_dir)' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
-	(
-		__git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - repo as argument' '
-	echo "otherrepo/.git" >expected &&
-	__gitdir "otherrepo" >"$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - remote as argument' '
-	echo "remote" >expected &&
-	__gitdir "remote" >"$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in cwd' '
-	echo ".git" >expected &&
-	__gitdir >"$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in parent' '
-	echo "$(pwd -P)/.git" >expected &&
-	(
-		cd subdir/subsubdir &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - cwd is a .git directory' '
-	echo "." >expected &&
-	(
-		cd .git &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - parent is a .git directory' '
-	echo "$(pwd -P)/.git" >expected &&
-	(
-		cd .git/refs/heads &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
-	(
-		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-		export GIT_DIR &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
-	(
-		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-		export GIT_DIR &&
-		cd subdir &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - non-existing $GIT_DIR' '
-	(
-		GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
-		export GIT_DIR &&
-		test_must_fail __gitdir
-	)
-'
-
-test_expect_success 'gitdir - gitfile in cwd' '
-	echo "$(pwd -P)/otherrepo/.git" >expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
-	test_when_finished "rm -f subdir/.git" &&
-	(
-		cd subdir &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - gitfile in parent' '
-	echo "$(pwd -P)/otherrepo/.git" >expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
-	test_when_finished "rm -f subdir/.git" &&
-	(
-		cd subdir/subsubdir &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '
-	echo "$(pwd -P)/otherrepo/.git" >expected &&
-	mkdir otherrepo/dir &&
-	test_when_finished "rm -rf otherrepo/dir" &&
-	ln -s otherrepo/dir link &&
-	test_when_finished "rm -f link" &&
-	(
-		cd link &&
-		__gitdir >"$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - not a git repository' '
-	(
-		cd subdir/subsubdir &&
-		GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
-		export GIT_CEILING_DIRECTORIES &&
-		test_must_fail __gitdir
-	)
-'
-
 test_expect_success 'prompt - branch name' '
 	printf " (master)" >expected &&
 	__git_ps1 >"$actual" &&
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 04/16] bash prompt: add a test for symbolic link symbolic refs
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (2 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 03/16] completion, bash prompt: move __gitdir() tests to completion test suite SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 05/16] bash prompt: print unique detached HEAD abbreviated object name SZEDER Gábor
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 t/t9903-bash-prompt.sh | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index df36239a..416e6219 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -40,6 +40,15 @@ test_expect_success 'prompt - branch name' '
 	test_cmp expected "$actual"
 '
 
+test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
+	printf " (master)" >expected &&
+	test_when_finished "git checkout master" &&
+	test_config core.preferSymlinkRefs true &&
+	git checkout master &&
+	__git_ps1 >"$actual" &&
+	test_cmp expected "$actual"
+'
+
 test_expect_success 'prompt - detached head' '
 	printf " ((%s...))" $(git log -1 --format="%h" b1^) >expected &&
 	git checkout b1^ &&
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 05/16] bash prompt: print unique detached HEAD abbreviated object name
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (3 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 04/16] bash prompt: add a test for symbolic link symbolic refs SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 06/16] bash prompt: return early from __git_ps1() when not in a git repository SZEDER Gábor
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

When describing a detached HEAD according to the $GIT_PS1_DESCRIBE
environment variable fails, __git_ps1() runs 'cut -c1-7 .git/HEAD' to
show the 7 hexdigits abbreviated commit object name in the prompt.
Obviously, this neither respects core.abbrev nor produces a unique
object name.

Fix this by using 'git rev-parse --short HEAD' instead and adjust the
corresponding test to use non-standard number of hexdigits.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 2 +-
 t/t9903-bash-prompt.sh           | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 07a6218d..3c5e62bb 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -392,7 +392,7 @@ __git_ps1 ()
 					git describe --tags --exact-match HEAD ;;
 				esac 2>/dev/null)" ||
 
-				b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
+				b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
 				b="unknown"
 				b="($b)"
 			}
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 416e6219..0d53aa6d 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -50,7 +50,8 @@ test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
 '
 
 test_expect_success 'prompt - detached head' '
-	printf " ((%s...))" $(git log -1 --format="%h" b1^) >expected &&
+	printf " ((%s...))" $(git log -1 --format="%h" --abbrev=13 b1^) >expected &&
+	test_config core.abbrev 13 &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	__git_ps1 >"$actual" &&
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 06/16] bash prompt: return early from __git_ps1() when not in a git repository
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (4 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 05/16] bash prompt: print unique detached HEAD abbreviated object name SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 07/16] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir() SZEDER Gábor
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

... to gain one level of indentation for the bulk of the function.

(The patch looks quite unreadable, you'd better check it with 'git
diff -w'.)

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 201 ++++++++++++++++++++-------------------
 1 file changed, 101 insertions(+), 100 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 3c5e62bb..a915b04c 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -341,121 +341,122 @@ __git_ps1 ()
 			#In PC mode PS1 always needs to be set
 			PS1="$ps1pc_start$ps1pc_end"
 		fi
+		return
+	fi
+
+	local r=""
+	local b=""
+	local step=""
+	local total=""
+	if [ -d "$g/rebase-merge" ]; then
+		b="$(cat "$g/rebase-merge/head-name" 2>/dev/null)"
+		step=$(cat "$g/rebase-merge/msgnum" 2>/dev/null)
+		total=$(cat "$g/rebase-merge/end" 2>/dev/null)
+		if [ -f "$g/rebase-merge/interactive" ]; then
+			r="|REBASE-i"
+		else
+			r="|REBASE-m"
+		fi
 	else
-		local r=""
-		local b=""
-		local step=""
-		local total=""
-		if [ -d "$g/rebase-merge" ]; then
-			b="$(cat "$g/rebase-merge/head-name" 2>/dev/null)"
-			step=$(cat "$g/rebase-merge/msgnum" 2>/dev/null)
-			total=$(cat "$g/rebase-merge/end" 2>/dev/null)
-			if [ -f "$g/rebase-merge/interactive" ]; then
-				r="|REBASE-i"
+		if [ -d "$g/rebase-apply" ]; then
+			step=$(cat "$g/rebase-apply/next" 2>/dev/null)
+			total=$(cat "$g/rebase-apply/last" 2>/dev/null)
+			if [ -f "$g/rebase-apply/rebasing" ]; then
+				b="$(cat "$g/rebase-apply/head-name" 2>/dev/null)"
+				r="|REBASE"
+			elif [ -f "$g/rebase-apply/applying" ]; then
+				r="|AM"
 			else
-				r="|REBASE-m"
-			fi
-		else
-			if [ -d "$g/rebase-apply" ]; then
-				step=$(cat "$g/rebase-apply/next" 2>/dev/null)
-				total=$(cat "$g/rebase-apply/last" 2>/dev/null)
-				if [ -f "$g/rebase-apply/rebasing" ]; then
-					b="$(cat "$g/rebase-apply/head-name" 2>/dev/null)"
-					r="|REBASE"
-				elif [ -f "$g/rebase-apply/applying" ]; then
-					r="|AM"
-				else
-					r="|AM/REBASE"
-				fi
-			elif [ -f "$g/MERGE_HEAD" ]; then
-				r="|MERGING"
-			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
-				r="|CHERRY-PICKING"
-			elif [ -f "$g/REVERT_HEAD" ]; then
-				r="|REVERTING"
-			elif [ -f "$g/BISECT_LOG" ]; then
-				r="|BISECTING"
+				r="|AM/REBASE"
 			fi
+		elif [ -f "$g/MERGE_HEAD" ]; then
+			r="|MERGING"
+		elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+			r="|CHERRY-PICKING"
+		elif [ -f "$g/REVERT_HEAD" ]; then
+			r="|REVERTING"
+		elif [ -f "$g/BISECT_LOG" ]; then
+			r="|BISECTING"
+		fi
 
-			test -n "$b" ||
-			b="$(git symbolic-ref HEAD 2>/dev/null)" || {
-				detached=yes
-				b="$(
-				case "${GIT_PS1_DESCRIBE_STYLE-}" in
-				(contains)
-					git describe --contains HEAD ;;
-				(branch)
-					git describe --contains --all HEAD ;;
-				(describe)
-					git describe HEAD ;;
-				(* | default)
-					git describe --tags --exact-match HEAD ;;
-				esac 2>/dev/null)" ||
+		test -n "$b" ||
+		b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+			detached=yes
+			b="$(
+			case "${GIT_PS1_DESCRIBE_STYLE-}" in
+			(contains)
+				git describe --contains HEAD ;;
+			(branch)
+				git describe --contains --all HEAD ;;
+			(describe)
+				git describe HEAD ;;
+			(* | default)
+				git describe --tags --exact-match HEAD ;;
+			esac 2>/dev/null)" ||
 
-				b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
-				b="unknown"
-				b="($b)"
-			}
-		fi
+			b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
+			b="unknown"
+			b="($b)"
+		}
+	fi
 
-		if [ -n "$step" ] && [ -n "$total" ]; then
-			r="$r $step/$total"
-		fi
+	if [ -n "$step" ] && [ -n "$total" ]; then
+		r="$r $step/$total"
+	fi
 
-		local w=""
-		local i=""
-		local s=""
-		local u=""
-		local c=""
-		local p=""
+	local w=""
+	local i=""
+	local s=""
+	local u=""
+	local c=""
+	local p=""
 
-		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
-			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
-				c="BARE:"
+	if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
+		if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
+			c="BARE:"
+		else
+			b="GIT_DIR!"
+		fi
+	elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
+		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
+		then
+			git diff --no-ext-diff --quiet --exit-code || w="*"
+			if git rev-parse --quiet --verify HEAD >/dev/null; then
+				git diff-index --cached --quiet HEAD -- || i="+"
 			else
-				b="GIT_DIR!"
-			fi
-		elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
-			if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
-			   [ "$(git config --bool bash.showDirtyState)" != "false" ]
-			then
-				git diff --no-ext-diff --quiet --exit-code || w="*"
-				if git rev-parse --quiet --verify HEAD >/dev/null; then
-					git diff-index --cached --quiet HEAD -- || i="+"
-				else
-					i="#"
-				fi
-			fi
-			if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
-				git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+				i="#"
 			fi
+		fi
+		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
+			git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+		fi
 
-			if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
-			   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
-			   [ -n "$(git ls-files --others --exclude-standard)" ]
-			then
-				u="%${ZSH_VERSION+%}"
-			fi
+		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+		   [ -n "$(git ls-files --others --exclude-standard)" ]
+		then
+			u="%${ZSH_VERSION+%}"
+		fi
 
-			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
-				__git_ps1_show_upstream
-			fi
+		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+			__git_ps1_show_upstream
 		fi
+	fi
 
-		local z="${GIT_PS1_STATESEPARATOR-" "}"
-		local f="$w$i$s$u"
-		if [ $pcmode = yes ]; then
-			local gitstring=
-			if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
-				__git_ps1_colorize_gitstring
-			else
-				gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
-			fi
-			gitstring=$(printf -- "$printf_format" "$gitstring")
-			PS1="$ps1pc_start$gitstring$ps1pc_end"
+	local z="${GIT_PS1_STATESEPARATOR-" "}"
+	local f="$w$i$s$u"
+	if [ $pcmode = yes ]; then
+		local gitstring=
+		if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+			__git_ps1_colorize_gitstring
 		else
-			# NO color option unless in PROMPT_COMMAND mode
-			printf -- "$printf_format" "$c${b##refs/heads/}${f:+$z$f}$r$p"
+			gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
 		fi
+		gitstring=$(printf -- "$printf_format" "$gitstring")
+		PS1="$ps1pc_start$gitstring$ps1pc_end"
+	else
+		# NO color option unless in PROMPT_COMMAND mode
+		printf -- "$printf_format" "$c${b##refs/heads/}${f:+$z$f}$r$p"
 	fi
 }
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 07/16] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir()
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (5 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 06/16] bash prompt: return early from __git_ps1() when not in a git repository SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 08/16] bash prompt: use bash builtins to find out rebase state SZEDER Gábor
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

__git_ps1() finds out the path to the repository by using the
__gitdir() helper function.  __gitdir() is basically just a wrapper
around 'git rev-parse --git-dir', extended with support for
recognizing a remote repository given as argument, to use the path
given on the command line, and with a few shortcuts to recognize a git
repository in cwd or at $GIT_DIR quickly without actually running 'git
rev-parse'.  However, the former two is only necessary for the
completion script but makes no sense for the bash prompt, while the
latter shortcuts are performance optimizations __git_ps1() can do
without (they just avoid the overhead of fork()+exec()ing a git
process).

Run 'git rev-parse --git-dir' directly in __git_ps1(), because it will
allow this patch series to combine several $(git rev-parse ...)
command substitutions in the main code path, and the overall
performance benefit will far outweigh the loss of those few shortcuts
in __gitdir().  Furthermore, since __gitdir() is not needed anymore
for the prompt, remove it from the prompt script finally eliminating
its duplication between the prompt and completion scripts.  Also
remove the comment from the completion script warning about this code
duplication.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-completion.bash |  2 --
 contrib/completion/git-prompt.sh       | 26 +-------------------------
 2 files changed, 1 insertion(+), 27 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 6c3bafee..ebc40d48 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -33,8 +33,6 @@ esac
 # returns location of .git repo
 __gitdir ()
 {
-	# Note: this function is duplicated in git-prompt.sh
-	# When updating it, make sure you update the other one to match.
 	if [ -z "${1-}" ]; then
 		if [ -n "${__git_dir-}" ]; then
 			echo "$__git_dir"
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index a915b04c..0563dea8 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -80,30 +80,6 @@
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
 # the colored output of "git status -sb".
 
-# __gitdir accepts 0 or 1 arguments (i.e., location)
-# returns location of .git repo
-__gitdir ()
-{
-	# Note: this function is duplicated in git-completion.bash
-	# When updating it, make sure you update the other one to match.
-	if [ -z "${1-}" ]; then
-		if [ -n "${__git_dir-}" ]; then
-			echo "$__git_dir"
-		elif [ -n "${GIT_DIR-}" ]; then
-			test -d "${GIT_DIR-}" || return 1
-			echo "$GIT_DIR"
-		elif [ -d .git ]; then
-			echo .git
-		else
-			git rev-parse --git-dir 2>/dev/null
-		fi
-	elif [ -d "$1/.git" ]; then
-		echo "$1/.git"
-	else
-		echo "$1"
-	fi
-}
-
 # stores the divergence from upstream in $p
 # used by GIT_PS1_SHOWUPSTREAM
 __git_ps1_show_upstream ()
@@ -335,7 +311,7 @@ __git_ps1 ()
 		;;
 	esac
 
-	local g="$(__gitdir)"
+	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	if [ -z "$g" ]; then
 		if [ $pcmode = yes ]; then
 			#In PC mode PS1 always needs to be set
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 08/16] bash prompt: use bash builtins to find out rebase state
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (6 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 07/16] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir() SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 09/16] bash prompt: use bash builtins to find out current branch SZEDER Gábor
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

During an ongoing interactive rebase __git_ps1() finds out the name of
the rebased branch, the total number of patches and the number of the
current patch by executing a '$(cat .git/rebase-merge/<FILE>)' command
substitution for each.  That is not quite the most efficient way to
read single line single word files, because it imposes the overhead of
fork()ing a subshell and fork()+exec()ing 'cat' several times.

Use the 'read' bash builtin instead to avoid those overheads.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 0563dea8..bc402f56 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -325,9 +325,9 @@ __git_ps1 ()
 	local step=""
 	local total=""
 	if [ -d "$g/rebase-merge" ]; then
-		b="$(cat "$g/rebase-merge/head-name" 2>/dev/null)"
-		step=$(cat "$g/rebase-merge/msgnum" 2>/dev/null)
-		total=$(cat "$g/rebase-merge/end" 2>/dev/null)
+		read b 2>/dev/null <"$g/rebase-merge/head-name"
+		read step 2>/dev/null <"$g/rebase-merge/msgnum"
+		read total 2>/dev/null <"$g/rebase-merge/end"
 		if [ -f "$g/rebase-merge/interactive" ]; then
 			r="|REBASE-i"
 		else
@@ -335,10 +335,10 @@ __git_ps1 ()
 		fi
 	else
 		if [ -d "$g/rebase-apply" ]; then
-			step=$(cat "$g/rebase-apply/next" 2>/dev/null)
-			total=$(cat "$g/rebase-apply/last" 2>/dev/null)
+			read step 2>/dev/null <"$g/rebase-apply/next"
+			read total 2>/dev/null <"$g/rebase-apply/last"
 			if [ -f "$g/rebase-apply/rebasing" ]; then
-				b="$(cat "$g/rebase-apply/head-name" 2>/dev/null)"
+				read b 2>/dev/null <"$g/rebase-apply/head-name"
 				r="|REBASE"
 			elif [ -f "$g/rebase-apply/applying" ]; then
 				r="|AM"
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 09/16] bash prompt: use bash builtins to find out current branch
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (7 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 08/16] bash prompt: use bash builtins to find out rebase state SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 10/16] bash prompt: combine 'git rev-parse' executions in the main code path SZEDER Gábor
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

__git_ps1() runs the '$(git symbolic-ref HEAD)' command substitution
to find out whether we are on a branch and to find out the name of
that branch.  This imposes the overhead of fork()ing a subshell and
fork()+exec()ing a git process.

Since HEAD is in most cases a single-line file and the symbolic ref
format is quite simple to recognize and parse, read and parse it using
only bash builtins, thereby sparing all that fork()+exec() overhead.
Don't display the git prompt if reading HEAD fails, because a readable
HEAD is required for a git repository.  HEAD can also be a symlink
symbolic ref (due to 'core.preferSymlinkRefs'), so use bash builtins
for reading HEAD only when HEAD is not a symlink.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 51 ++++++++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index bc402f56..c2050b69 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -355,25 +355,40 @@ __git_ps1 ()
 			r="|BISECTING"
 		fi
 
-		test -n "$b" ||
-		b="$(git symbolic-ref HEAD 2>/dev/null)" || {
-			detached=yes
-			b="$(
-			case "${GIT_PS1_DESCRIBE_STYLE-}" in
-			(contains)
-				git describe --contains HEAD ;;
-			(branch)
-				git describe --contains --all HEAD ;;
-			(describe)
-				git describe HEAD ;;
-			(* | default)
-				git describe --tags --exact-match HEAD ;;
-			esac 2>/dev/null)" ||
+		if [ -n "$b" ]; then
+			:
+		elif [ -h "$g/HEAD" ]; then
+			# symlink symbolic ref
+			b="$(git symbolic-ref HEAD 2>/dev/null)"
+		else
+			local head=""
+			if ! read head 2>/dev/null <"$g/HEAD"; then
+				if [ $pcmode = yes ]; then
+					PS1="$ps1pc_start$ps1pc_end"
+				fi
+				return
+			fi
+			# is it a symbolic ref?
+			b="${head#ref: }"
+			if [ "$head" = "$b" ]; then
+				detached=yes
+				b="$(
+				case "${GIT_PS1_DESCRIBE_STYLE-}" in
+				(contains)
+					git describe --contains HEAD ;;
+				(branch)
+					git describe --contains --all HEAD ;;
+				(describe)
+					git describe HEAD ;;
+				(* | default)
+					git describe --tags --exact-match HEAD ;;
+				esac 2>/dev/null)" ||
 
-			b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
-			b="unknown"
-			b="($b)"
-		}
+				b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
+				b="unknown"
+				b="($b)"
+			fi
+		fi
 	fi
 
 	if [ -n "$step" ] && [ -n "$total" ]; then
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 10/16] bash prompt: combine 'git rev-parse' executions in the main code path
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (8 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 09/16] bash prompt: use bash builtins to find out current branch SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 11/16] bash prompt: combine 'git rev-parse' for detached head SZEDER Gábor
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

There are a couple of '$(git rev-parse --<opt>)' command substitutions
in __git_ps1() and three of them are executed in the main code path:

 - the first to get the path to the .git directory ('--git-dir'),
 - the second to check whether we're inside the .git directory
   ('--is-inside-git-dir'),
 - and the last, depending on the results of the second, either
   * to check whether it's a bare repo ('--is-bare-repository'), or
   * to check whether inside a work tree ('--is-inside-work-tree').

Naturally, this imposes the overhead of fork()ing three subshells and
fork()+exec()ing three git commands.

Combine these four 'git rev-parse' queries into a single one and use
bash parameter expansions to parse the combined output, i.e. to
separate the path to the .git directory from the true/false of
'--is-inside-git-dir', etc.  This way we can eliminate two of the
three subshells and git commands.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index c2050b69..7d226251 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -311,8 +311,9 @@ __git_ps1 ()
 		;;
 	esac
 
-	local g="$(git rev-parse --git-dir 2>/dev/null)"
-	if [ -z "$g" ]; then
+	local repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+		--is-bare-repository --is-inside-work-tree 2>/dev/null)"
+	if [ -z "$repo_info" ]; then
 		if [ $pcmode = yes ]; then
 			#In PC mode PS1 always needs to be set
 			PS1="$ps1pc_start$ps1pc_end"
@@ -320,6 +321,13 @@ __git_ps1 ()
 		return
 	fi
 
+	local inside_worktree="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local bare_repo="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local inside_gitdir="${repo_info##*$'\n'}"
+	local g="${repo_info%$'\n'*}"
+
 	local r=""
 	local b=""
 	local step=""
@@ -402,13 +410,13 @@ __git_ps1 ()
 	local c=""
 	local p=""
 
-	if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
-		if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
+	if [ "true" = "$inside_gitdir" ]; then
+		if [ "true" = "$bare_repo" ]; then
 			c="BARE:"
 		else
 			b="GIT_DIR!"
 		fi
-	elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
+	elif [ "true" = "$inside_worktree" ]; then
 		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
 		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
 		then
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 11/16] bash prompt: combine 'git rev-parse' for detached head
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (9 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 10/16] bash prompt: combine 'git rev-parse' executions in the main code path SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 12/16] bash prompt: use bash builtins to check for unborn branch for dirty state SZEDER Gábor
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

When describing a detached HEAD according to the $GIT_PS1_DESCRIBE
environment variable fails, __git_ps1() now runs the '$(git rev-parse
--short HEAD)' command substitution to get the abbreviated detached
HEAD commit object name.  This imposes the overhead of fork()ing a
subshell and fork()+exec()ing a git process.

Avoid this overhead by combining this command substitution with the
"main" 'git rev-parse' execution for getting the path to the .git
directory & co.  This means that we'll look for the abbreviated commit
object name even when it's not necessary, because we're on a branch or
the detached HEAD can be described.  It doesn't matter, however,
because once 'git rev-parse' is up and running to fulfill all those
other queries, the additional overhead of looking for the abbreviated
commit object name is not measurable because it's lost in the noise.

There is a caveat, however, when we are on an unborn branch, because
in that case HEAD doesn't point to a valid commit, hence the query for
the abbreviated commit object name fails.  Therefore, '--short HEAD'
must be the last options to 'git rev-parse' in order to get all the
other necessary information for the prompt even on an unborn branch.
Furthermore, in that case, and in that case only, 'git rev-parse'
doesn't output the last line containing the abbreviated commit object
name, obviously, so we have to take care to only parse it if 'git
rev-parse' exited without any error.

Although there are tests already excercising __git_ps1() on unborn
branches, they all do so implicitly.  Add a test that checks this
explicitly.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 16 ++++++++++++----
 t/t9903-bash-prompt.sh           |  8 ++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 7d226251..88d6121d 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -311,8 +311,12 @@ __git_ps1 ()
 		;;
 	esac
 
-	local repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
-		--is-bare-repository --is-inside-work-tree 2>/dev/null)"
+	local repo_info rev_parse_exit_code
+	repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+		--is-bare-repository --is-inside-work-tree \
+		--short HEAD 2>/dev/null)"
+	rev_parse_exit_code="$?"
+
 	if [ -z "$repo_info" ]; then
 		if [ $pcmode = yes ]; then
 			#In PC mode PS1 always needs to be set
@@ -321,6 +325,11 @@ __git_ps1 ()
 		return
 	fi
 
+	local short_sha
+	if [ "$rev_parse_exit_code" = "0" ]; then
+		short_sha="${repo_info##*$'\n'}"
+		repo_info="${repo_info%$'\n'*}"
+	fi
 	local inside_worktree="${repo_info##*$'\n'}"
 	repo_info="${repo_info%$'\n'*}"
 	local bare_repo="${repo_info##*$'\n'}"
@@ -392,8 +401,7 @@ __git_ps1 ()
 					git describe --tags --exact-match HEAD ;;
 				esac 2>/dev/null)" ||
 
-				b="$(git rev-parse --short HEAD 2>/dev/null)..." ||
-				b="unknown"
+				b="$short_sha..."
 				b="($b)"
 			fi
 		fi
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 0d53aa6d..b9895c79 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -49,6 +49,14 @@ test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
 	test_cmp expected "$actual"
 '
 
+test_expect_success 'prompt - unborn branch' '
+	printf " (unborn)" >expected &&
+	git checkout --orphan unborn &&
+	test_when_finished "git checkout master" &&
+	__git_ps1 >"$actual" &&
+	test_cmp expected "$actual"
+'
+
 test_expect_success 'prompt - detached head' '
 	printf " ((%s...))" $(git log -1 --format="%h" --abbrev=13 b1^) >expected &&
 	test_config core.abbrev 13 &&
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 12/16] bash prompt: use bash builtins to check for unborn branch for dirty state
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (10 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 11/16] bash prompt: combine 'git rev-parse' for detached head SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 13/16] bash prompt: use bash builtins to check stash state SZEDER Gábor
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

When the dirty work tree and index status indicator is enabled,
__git_ps1() checks for changes in the index by running 'git diff-index
--cached --quiet HEAD --' and looking at its exit code.  However, that
makes sense only when HEAD points to a valid commit: on an unborn
branch the failure of said command would be caused by the invalid
HEAD, not by changes in the index.  Therefore, __git_ps1() first
checks for a valid HEAD by running 'git rev-parse --quiet --verify
HEAD'.

Since the previous patch we implicitly check HEAD's validity by
running 'git rev-parse ... --short HEAD', making the dirty status
indicator's 'git rev-parse' check redundant.  It's sufficient to check
for non-emptyness of the variable holding the abbreviated commit
object name, thereby sparing the overhead of fork()+exec()ing a git
process.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 88d6121d..6e8f486e 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -429,7 +429,7 @@ __git_ps1 ()
 		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
 		then
 			git diff --no-ext-diff --quiet --exit-code || w="*"
-			if git rev-parse --quiet --verify HEAD >/dev/null; then
+			if [ -n "$short_sha" ]; then
 				git diff-index --cached --quiet HEAD -- || i="+"
 			else
 				i="#"
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 13/16] bash prompt: use bash builtins to check stash state
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (11 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 12/16] bash prompt: use bash builtins to check for unborn branch for dirty state SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 14/16] bash prompt: avoid command substitution when checking for untracked files SZEDER Gábor
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

When the environment variable $GIT_PS1_SHOWSTASHSTATE is set
__git_ps1() checks the presence of stashes by running 'git rev-parse
--verify refs/stash'.  This command not only checks that the
'refs/stash' ref exists but also, well, verifies that it's a valid
ref.

However, we don't need to be that thorough for the bash prompt.  We
can omit that verification and only check whether 'refs/stash' exists
or not.  Since 'git pack-refs' never packs 'refs/stash', it's a matter
of checking the existence of a ref file.  Perform this check using
only bash builtins to spare the overhead of fork()+exec()ing a git
process.

Also run 'git pack-refs --all' in the corresponding test to document
that the prompt script depends on 'git pack-refs' not packing
'refs/stash' and to catch possible breakages should this behavior ever
change.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 5 +++--
 t/t9903-bash-prompt.sh           | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 6e8f486e..afa86703 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -435,8 +435,9 @@ __git_ps1 ()
 				i="#"
 			fi
 		fi
-		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
-			git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
+		   [ -r "$g/refs/stash" ]; then
+			s="$"
 		fi
 
 		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index b9895c79..c05458cb 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -328,6 +328,7 @@ test_expect_success 'prompt - stash status indicator - stash' '
 	echo 2 >file &&
 	git stash &&
 	test_when_finished "git stash drop" &&
+	git pack-refs --all &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
 		__git_ps1 >"$actual"
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 14/16] bash prompt: avoid command substitution when checking for untracked files
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (12 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 13/16] bash prompt: use bash builtins to check stash state SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 15/16] bash prompt: avoid command substitution when finalizing gitstring SZEDER Gábor
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

When enabled, the bash prompt can indicate the presence of untracked
files with a '%' sign.  __git_ps1() checks for untracked files by running the
'$(git ls-files --others --exclude-standard)' command substitution,
and displays the indicator when there is no output.

Avoid this command substitution by additionally passing
'--error-unmatch *', and checking the command's return value.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index afa86703..5ea6a68b 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -442,7 +442,7 @@ __git_ps1 ()
 
 		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
 		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
-		   [ -n "$(git ls-files --others --exclude-standard)" ]
+		   git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
 		then
 			u="%${ZSH_VERSION+%}"
 		fi
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 15/16] bash prompt: avoid command substitution when finalizing gitstring
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (13 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 14/16] bash prompt: avoid command substitution when checking for untracked files SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 16:39 ` [PATCHv3 16/16] bash prompt: mention that PROMPT_COMMAND mode is faster SZEDER Gábor
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

Before setting $PS1, __git_ps1() uses a command substitution to
redirect the output from a printf into a variable.  Spare the overhead
of fork()ing a subshell by using 'printf -v <var>' to directly assign
the output to that variable.

zsh's printf doesn't support the '-v <var>' option, so stick with the
command substitution when under zsh.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 5ea6a68b..7152ae49 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -461,7 +461,11 @@ __git_ps1 ()
 		else
 			gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
 		fi
-		gitstring=$(printf -- "$printf_format" "$gitstring")
+		if [[ -n ${ZSH_VERSION-} ]]; then
+			gitstring=$(printf -- "$printf_format" "$gitstring")
+		else
+			printf -v gitstring -- "$printf_format" "$gitstring"
+		fi
 		PS1="$ps1pc_start$gitstring$ps1pc_end"
 	else
 		# NO color option unless in PROMPT_COMMAND mode
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv3 16/16] bash prompt: mention that PROMPT_COMMAND mode is faster
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (14 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 15/16] bash prompt: avoid command substitution when finalizing gitstring SZEDER Gábor
@ 2013-06-24 16:39 ` SZEDER Gábor
  2013-06-24 19:25 ` [PATCHv3 00/16] bash prompt speedup Junio C Hamano
  2013-06-25  2:00 ` Eduardo R. D'Avila
  17 siblings, 0 replies; 19+ messages in thread
From: SZEDER Gábor @ 2013-06-24 16:39 UTC (permalink / raw)
  To: git; +Cc: Eduardo D'Avila, SZEDER Gábor

__git_ps1() is usually added to the prompt inside a command
substitution, imposing the overhead of fork()ing a subshell.  Using
__git_ps1() for $PROMPT_COMMAND is slightly faster, because it avoids
that command substitution.

Mention this in the comments about setting up the git prompt.

The whole series speeds up the bash prompt on Windows/MSysGit
considerably.  Here are some timing results in three scenarios, each
repeated 10 times:

At the top of the work tree, before:

    $ time for i in {0..9} ; do prompt="$(__git_ps1)" ; done

    real    0m1.716s
    user    0m0.301s
    sys     0m0.772s

  After:

    real    0m0.687s
    user    0m0.075s
    sys     0m0.396s

  After, from $PROMPT_COMMAND:

    $ time for i in {0..9} ; do __git_ps1 '\h:\w' '$ ' ; done

    real    0m0.546s
    user    0m0.075s
    sys     0m0.181s

At the top of the work tree, detached head, before:

    real    0m2.574s
    user    0m0.376s
    sys     0m1.207s

  After:

    real    0m1.139s
    user    0m0.151s
    sys     0m0.500s

  After, from $PROMPT_COMMAND:

    real    0m1.030s
    user    0m0.245s
    sys     0m0.336s

In a subdirectory, during rebase, stash status indicator enabled,
before:

    real    0m3.557s
    user    0m0.495s
    sys     0m1.767s

  After:

    real    0m0.717s
    user    0m0.120s
    sys     0m0.300s

  After, from $PROMPT_COMMAND:

    real    0m0.577s
    user    0m0.047s
    sys     0m0.258s

On Linux the speedup ratio is comparable to Windows, but overall it
was about an order of magnitude faster to begin with.  The last case
from above, repeated 100 times, before:

    $ time for i in {0..99} ; do prompt="$(__git_ps1)" ; done

    real    0m2.806s
    user    0m0.180s
    sys     0m0.264s

  After:

    real    0m0.857s
    user    0m0.020s
    sys     0m0.028s

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-prompt.sh | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 7152ae49..daed6a1d 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -15,11 +15,11 @@
 #        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
 #        ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
 #        the optional argument will be used as format string.
-#    3b) Alternatively, if you are using bash, __git_ps1 can be
-#        used for PROMPT_COMMAND with two parameters, <pre> and
-#        <post>, which are strings you would put in $PS1 before
-#        and after the status string generated by the git-prompt
-#        machinery.  e.g.
+#    3b) Alternatively, for a slighly faster prompt, if you are
+#        using bash, __git_ps1 can be used for PROMPT_COMMAND
+#        with two parameters, <pre> and <post>, which are strings
+#        you would put in $PS1 before and after the status string
+#        generated by the git-prompt machinery.  e.g.
 #        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
 #        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
 #        will show username, at-sign, host, colon, cwd, then
-- 
1.8.3.1.599.g4459181

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCHv3 00/16] bash prompt speedup
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (15 preceding siblings ...)
  2013-06-24 16:39 ` [PATCHv3 16/16] bash prompt: mention that PROMPT_COMMAND mode is faster SZEDER Gábor
@ 2013-06-24 19:25 ` Junio C Hamano
  2013-06-25  2:00 ` Eduardo R. D'Avila
  17 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2013-06-24 19:25 UTC (permalink / raw)
  To: SZEDER Gábor; +Cc: git, Eduardo D'Avila

SZEDER Gábor <szeder@ira.uka.de> writes:

> Hi,
>
> displaying the git-specific bash prompt on Windows/MinGW takes quite
> long, long enough to be noticeable.  This is mainly caused by the
> numerous fork()s and exec()s to create subshells and run git or other
> commands, which are rather expensive on Windows.
>
> This patch series eliminates many command substitutions and command
> executions in __git_ps1() from top to bottom by replacing them with
> bash builtins or consolidating them.  A few timing results are shown
> in the log message of the last patch.
>
> Changes since v2 [1]:
>
>  - The detached HEAD abbreviated object name is now unique and
>    respects core.abbrev; see patches 5 and 11, replacing v2's patch 9.
>    (This is why I asked the detached HEAD before root commit thing
>    yesterday.)  
>  - Patches 12 and 16 are new.
>  - Incorporated Peff's suggestion about using the 'write_script'
>    helper into patch 2.
>  - Incorporated Eric's typofix.
>  - Rephrased a few commit messages.
>
> It applies on top of current master; 2847cae8 (prompt: squelch error
> output from cat, 2013-06-14) graduated recently.
>
> This patch series will conflict with Eduardo's work on refactoring the
> colorizing function, and the conflict is not trivial.  Although there
> are still some open questions left with that series (using tput, zsh
> tests), those won't affect the conflicts between the two patch series.
> So, for the convenience of our maintainer, I picked up Eduardo's
> series, took the liberty to apply a fixup commit on top with my
> suggestions from [2], merged the two series, and published the result
> at:
>
>   https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization
>
> Eduardo, could you please also check that my conflict resolution is
> correct?  Thanks.

Well, then I'll fetch that premerged result and queue it on 'pu',
wait for a while just in case if you need to reroll based on
somebody else's input and otherwise merge that down to 'next' and
then to 'master'.

Thanks.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv3 00/16] bash prompt speedup
  2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
                   ` (16 preceding siblings ...)
  2013-06-24 19:25 ` [PATCHv3 00/16] bash prompt speedup Junio C Hamano
@ 2013-06-25  2:00 ` Eduardo R. D'Avila
  17 siblings, 0 replies; 19+ messages in thread
From: Eduardo R. D'Avila @ 2013-06-25  2:00 UTC (permalink / raw)
  To: SZEDER Gábor; +Cc: git

2013/6/24 SZEDER Gábor <szeder@ira.uka.de>:
> This patch series will conflict with Eduardo's work on refactoring the
> colorizing function, and the conflict is not trivial.  Although there
> are still some open questions left with that series (using tput, zsh
> tests), those won't affect the conflicts between the two patch series.
> So, for the convenience of our maintainer, I picked up Eduardo's
> series, took the liberty to apply a fixup commit on top with my
> suggestions from [2], merged the two series, and published the result
> at:
>
>   https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization
>
> Eduardo, could you please also check that my conflict resolution is
> correct?  Thanks.

Gábor, the conflict resolution is quite correct.

Thanks,

Eduardo

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2013-06-25  2:01 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-24 16:39 [PATCHv3 00/16] bash prompt speedup SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 01/16] bash prompt: fix redirection coding style in tests SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 02/16] bash prompt: use 'write_script' helper in interactive rebase test SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 03/16] completion, bash prompt: move __gitdir() tests to completion test suite SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 04/16] bash prompt: add a test for symbolic link symbolic refs SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 05/16] bash prompt: print unique detached HEAD abbreviated object name SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 06/16] bash prompt: return early from __git_ps1() when not in a git repository SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 07/16] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir() SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 08/16] bash prompt: use bash builtins to find out rebase state SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 09/16] bash prompt: use bash builtins to find out current branch SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 10/16] bash prompt: combine 'git rev-parse' executions in the main code path SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 11/16] bash prompt: combine 'git rev-parse' for detached head SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 12/16] bash prompt: use bash builtins to check for unborn branch for dirty state SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 13/16] bash prompt: use bash builtins to check stash state SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 14/16] bash prompt: avoid command substitution when checking for untracked files SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 15/16] bash prompt: avoid command substitution when finalizing gitstring SZEDER Gábor
2013-06-24 16:39 ` [PATCHv3 16/16] bash prompt: mention that PROMPT_COMMAND mode is faster SZEDER Gábor
2013-06-24 19:25 ` [PATCHv3 00/16] bash prompt speedup Junio C Hamano
2013-06-25  2:00 ` Eduardo R. D'Avila

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).