{"thread":{"id":"34187","subject":"[PATCH v2 00/13] bash prompt speedup","startedAt":"2013-06-18T02:16:53Z","lastAt":"2013-06-18T19:35:51Z","messageCount":22,"participants":["SZEDER Gábor","Eric Sunshine","Jeff King","Junio C Hamano","Simon Oosthoek"],"isPatch":true,"patchVersion":2,"patchTotal":13},"messages":[{"id":"221121","messageId":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":null,"subject":"[PATCH v2 00/13] bash prompt speedup","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:53Z","receivedAt":"2013-06-18T02:16:53Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nHi,\n\ndisplaying the git-specific bash prompt on Windows/MinGW takes quite\nlong, long enough to be noticeable.  This is mainly caused by the\nnumerous fork()s and exec()s to create subshells and run git or other\ncommands, which are rather expensive on Windows.\n\nThis patch series eliminates many command substitutions and commands\nin __git_ps1() from top to bottom by replacing them with bash builtins\nor consolidating them.  A few timing results are shown in the log\nmessage of patch 10.\n\n\nSZEDER Gábor (13):\n  bash prompt: fix redirection coding style in tests\n  bash prompt: fix here document indentation in interactive rebase test\n  completion, bash prompt: move __gitdir() tests to completion test\n    suite\n  bash prompt: add a test for symbolic link symbolic refs\n  bash prompt: return early from __git_ps1() when not in a git\n    repository\n  bash prompt: run 'git rev-parse --git-dir' directly instead of\n    __gitdir()\n  bash prompt: use bash builtins to find out rebase state\n  bash prompt: use bash builtins to find out current branch\n  bash prompt: use bash builtins to get detached HEAD abbrev. object\n    name\n  bash prompt: combine 'git rev-parse' executions\n  bash prompt: use bash builtins to check stash state\n  bash prompt: avoid command substitution when checking for untracked\n    files\n  bash prompt: avoid command substitution when finalizing gitstring\n\n contrib/completion/git-completion.bash |   2 -\n contrib/completion/git-prompt.sh       | 223 ++++++++++++-----------\n t/t9902-completion.sh                  | 134 ++++++++++++++\n t/t9903-bash-prompt.sh                 | 319 +++++++++++----------------------\n 4 files changed, 345 insertions(+), 333 deletions(-)\n\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221122","messageId":"1371521826-3225-2-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 01/13] bash prompt: fix redirection coding style in tests","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:54Z","receivedAt":"2013-06-18T02:16:54Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nUse '>file' instead of '> file', in accordance with the coding\nguidelines.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n t/t9903-bash-prompt.sh | 232 ++++++++++++++++++++++++-------------------------\n 1 file changed, 116 insertions(+), 116 deletions(-)\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 15521cc4..7c7f8b97 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -14,98 +14,98 @@ actual=\"$TRASH_DIRECTORY/actual\"\n test_expect_success 'setup for prompt tests' '\n \tmkdir -p subdir/subsubdir &&\n \tgit init otherrepo &&\n-\techo 1 > file &&\n+\techo 1 >file &&\n \tgit add file &&\n \ttest_tick &&\n \tgit commit -m initial &&\n \tgit tag -a -m msg1 t1 &&\n \tgit checkout -b b1 &&\n-\techo 2 > file &&\n+\techo 2 >file &&\n \tgit commit -m \"second b1\" file &&\n-\techo 3 > file &&\n+\techo 3 >file &&\n \tgit commit -m \"third b1\" file &&\n \tgit tag -a -m msg2 t2 &&\n \tgit checkout -b b2 master &&\n-\techo 0 > file &&\n+\techo 0 >file &&\n \tgit commit -m \"second b2\" file &&\n-\techo 00 > file &&\n+\techo 00 >file &&\n \tgit commit -m \"another b2\" file &&\n-\techo 000 > file &&\n+\techo 000 >file &&\n \tgit commit -m \"yet another b2\" file &&\n \tgit checkout master\n '\n \n test_expect_success 'gitdir - from command line (through $__git_dir)' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" > expected &&\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n \t(\n \t\t__git_dir=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - repo as argument' '\n-\techo \"otherrepo/.git\" > expected &&\n-\t__gitdir \"otherrepo\" > \"$actual\" &&\n+\techo \"otherrepo/.git\" >expected &&\n+\t__gitdir \"otherrepo\" >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - remote as argument' '\n-\techo \"remote\" > expected &&\n-\t__gitdir \"remote\" > \"$actual\" &&\n+\techo \"remote\" >expected &&\n+\t__gitdir \"remote\" >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - .git directory in cwd' '\n-\techo \".git\" > expected &&\n-\t__gitdir > \"$actual\" &&\n+\techo \".git\" >expected &&\n+\t__gitdir >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - .git directory in parent' '\n-\techo \"$(pwd -P)/.git\" > expected &&\n+\techo \"$(pwd -P)/.git\" >expected &&\n \t(\n \t\tcd subdir/subsubdir &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - cwd is a .git directory' '\n-\techo \".\" > expected &&\n+\techo \".\" >expected &&\n \t(\n \t\tcd .git &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - parent is a .git directory' '\n-\techo \"$(pwd -P)/.git\" > expected &&\n+\techo \"$(pwd -P)/.git\" >expected &&\n \t(\n \t\tcd .git/refs/heads &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" > expected &&\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n \t(\n \t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n \t\texport GIT_DIR &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" > expected &&\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n \t(\n \t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n \t\texport GIT_DIR &&\n \t\tcd subdir &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n@@ -119,36 +119,36 @@ test_expect_success 'gitdir - non-existing $GIT_DIR' '\n '\n \n test_expect_success 'gitdir - gitfile in cwd' '\n-\techo \"$(pwd -P)/otherrepo/.git\" > expected &&\n-\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" > subdir/.git &&\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n+\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n \ttest_when_finished \"rm -f subdir/.git\" &&\n \t(\n \t\tcd subdir &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'gitdir - gitfile in parent' '\n-\techo \"$(pwd -P)/otherrepo/.git\" > expected &&\n-\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" > subdir/.git &&\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n+\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n \ttest_when_finished \"rm -f subdir/.git\" &&\n \t(\n \t\tcd subdir/subsubdir &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '\n-\techo \"$(pwd -P)/otherrepo/.git\" > expected &&\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n \tmkdir otherrepo/dir &&\n \ttest_when_finished \"rm -rf otherrepo/dir\" &&\n \tln -s otherrepo/dir link &&\n \ttest_when_finished \"rm -f link\" &&\n \t(\n \t\tcd link &&\n-\t\t__gitdir > \"$actual\"\n+\t\t__gitdir >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n@@ -163,96 +163,96 @@ test_expect_success 'gitdir - not a git repository' '\n '\n \n test_expect_success 'prompt - branch name' '\n-\tprintf \" (master)\" > expected &&\n-\t__git_ps1 > \"$actual\" &&\n+\tprintf \" (master)\" >expected &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - detached head' '\n-\tprintf \" ((%s...))\" $(git log -1 --format=\"%h\" b1^) > expected &&\n+\tprintf \" ((%s...))\" $(git log -1 --format=\"%h\" b1^) >expected &&\n \tgit checkout b1^ &&\n \ttest_when_finished \"git checkout master\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - describe detached head - contains' '\n-\tprintf \" ((t2~1))\" > expected &&\n+\tprintf \" ((t2~1))\" >expected &&\n \tgit checkout b1^ &&\n \ttest_when_finished \"git checkout master\" &&\n \t(\n \t\tGIT_PS1_DESCRIBE_STYLE=contains &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - describe detached head - branch' '\n-\tprintf \" ((b1~1))\" > expected &&\n+\tprintf \" ((b1~1))\" >expected &&\n \tgit checkout b1^ &&\n \ttest_when_finished \"git checkout master\" &&\n \t(\n \t\tGIT_PS1_DESCRIBE_STYLE=branch &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - describe detached head - describe' '\n-\tprintf \" ((t1-1-g%s))\" $(git log -1 --format=\"%h\" b1^) > expected &&\n+\tprintf \" ((t1-1-g%s))\" $(git log -1 --format=\"%h\" b1^) >expected &&\n \tgit checkout b1^ &&\n \ttest_when_finished \"git checkout master\" &&\n \t(\n \t\tGIT_PS1_DESCRIBE_STYLE=describe &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - describe detached head - default' '\n-\tprintf \" ((t2))\" > expected &&\n+\tprintf \" ((t2))\" >expected &&\n \tgit checkout --detach b1 &&\n \ttest_when_finished \"git checkout master\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - inside .git directory' '\n-\tprintf \" (GIT_DIR!)\" > expected &&\n+\tprintf \" (GIT_DIR!)\" >expected &&\n \t(\n \t\tcd .git &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - deep inside .git directory' '\n-\tprintf \" (GIT_DIR!)\" > expected &&\n+\tprintf \" (GIT_DIR!)\" >expected &&\n \t(\n \t\tcd .git/refs/heads &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - inside bare repository' '\n-\tprintf \" (BARE:master)\" > expected &&\n+\tprintf \" (BARE:master)\" >expected &&\n \tgit init --bare bare.git &&\n \ttest_when_finished \"rm -rf bare.git\" &&\n \t(\n \t\tcd bare.git &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - interactive rebase' '\n-\tprintf \" (b1|REBASE-i 2/3)\" > expected\n+\tprintf \" (b1|REBASE-i 2/3)\" >expected\n \techo \"#!$SHELL_PATH\" >fake_editor.sh &&\n \tcat >>fake_editor.sh <<\\EOF &&\n-echo \"exec echo\" > \"$1\"\n-echo \"edit $(git log -1 --format=\"%h\")\" >> \"$1\"\n-echo \"exec echo\" >> \"$1\"\n+echo \"exec echo\" >\"$1\"\n+echo \"edit $(git log -1 --format=\"%h\")\" >>\"$1\"\n+echo \"exec echo\" >>\"$1\"\n EOF\n \ttest_when_finished \"rm -f fake_editor.sh\" &&\n \tchmod a+x fake_editor.sh &&\n@@ -261,277 +261,277 @@ EOF\n \ttest_when_finished \"git checkout master\" &&\n \tgit rebase -i HEAD^ &&\n \ttest_when_finished \"git rebase --abort\"\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - rebase merge' '\n-\tprintf \" (b2|REBASE-m 1/3)\" > expected &&\n+\tprintf \" (b2|REBASE-m 1/3)\" >expected &&\n \tgit checkout b2 &&\n \ttest_when_finished \"git checkout master\" &&\n \ttest_must_fail git rebase --merge b1 b2 &&\n \ttest_when_finished \"git rebase --abort\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - rebase' '\n-\tprintf \" (b2|REBASE 1/3)\" > expected &&\n+\tprintf \" (b2|REBASE 1/3)\" >expected &&\n \tgit checkout b2 &&\n \ttest_when_finished \"git checkout master\" &&\n \ttest_must_fail git rebase b1 b2 &&\n \ttest_when_finished \"git rebase --abort\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - merge' '\n-\tprintf \" (b1|MERGING)\" > expected &&\n+\tprintf \" (b1|MERGING)\" >expected &&\n \tgit checkout b1 &&\n \ttest_when_finished \"git checkout master\" &&\n \ttest_must_fail git merge b2 &&\n \ttest_when_finished \"git reset --hard\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - cherry-pick' '\n-\tprintf \" (master|CHERRY-PICKING)\" > expected &&\n+\tprintf \" (master|CHERRY-PICKING)\" >expected &&\n \ttest_must_fail git cherry-pick b1 &&\n \ttest_when_finished \"git reset --hard\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - bisect' '\n-\tprintf \" (master|BISECTING)\" > expected &&\n+\tprintf \" (master|BISECTING)\" >expected &&\n \tgit bisect start &&\n \ttest_when_finished \"git bisect reset\" &&\n-\t__git_ps1 > \"$actual\" &&\n+\t__git_ps1 >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - clean' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - dirty worktree' '\n-\tprintf \" (master *)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master *)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - dirty index' '\n-\tprintf \" (master +)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master +)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \tgit add -u &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - dirty index and worktree' '\n-\tprintf \" (master *+)\" > expected &&\n-\techo \"dirty index\" > file &&\n+\tprintf \" (master *+)\" >expected &&\n+\techo \"dirty index\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \tgit add -u &&\n-\techo \"dirty worktree\" > file &&\n+\techo \"dirty worktree\" >file &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - before root commit' '\n-\tprintf \" (master #)\" > expected &&\n+\tprintf \" (master #)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n \t\tcd otherrepo &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - shell variable unset with config disabled' '\n-\tprintf \" (master)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \ttest_config bash.showDirtyState false &&\n \t(\n \t\tsane_unset GIT_PS1_SHOWDIRTYSTATE &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - shell variable unset with config enabled' '\n-\tprintf \" (master)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \ttest_config bash.showDirtyState true &&\n \t(\n \t\tsane_unset GIT_PS1_SHOWDIRTYSTATE &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - shell variable set with config disabled' '\n-\tprintf \" (master)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \ttest_config bash.showDirtyState false &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - shell variable set with config enabled' '\n-\tprintf \" (master *)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (master *)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \ttest_config bash.showDirtyState true &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - dirty status indicator - not shown inside .git directory' '\n-\tprintf \" (GIT_DIR!)\" > expected &&\n-\techo \"dirty\" > file &&\n+\tprintf \" (GIT_DIR!)\" >expected &&\n+\techo \"dirty\" >file &&\n \ttest_when_finished \"git reset --hard\" &&\n \t(\n \t\tGIT_PS1_SHOWDIRTYSTATE=y &&\n \t\tcd .git &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - stash status indicator - no stash' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWSTASHSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - stash status indicator - stash' '\n-\tprintf \" (master $)\" > expected &&\n+\tprintf \" (master $)\" >expected &&\n \techo 2 >file &&\n \tgit stash &&\n \ttest_when_finished \"git stash drop\" &&\n \t(\n \t\tGIT_PS1_SHOWSTASHSTATE=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - stash status indicator - not shown inside .git directory' '\n-\tprintf \" (GIT_DIR!)\" > expected &&\n+\tprintf \" (GIT_DIR!)\" >expected &&\n \techo 2 >file &&\n \tgit stash &&\n \ttest_when_finished \"git stash drop\" &&\n \t(\n \t\tGIT_PS1_SHOWSTASHSTATE=y &&\n \t\tcd .git &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - no untracked files' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWUNTRACKEDFILES=y &&\n \t\tcd otherrepo &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - untracked files' '\n-\tprintf \" (master %%)\" > expected &&\n+\tprintf \" (master %%)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWUNTRACKEDFILES=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \ttest_config bash.showUntrackedFiles false &&\n \t(\n \t\tsane_unset GIT_PS1_SHOWUNTRACKEDFILES &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - shell variable unset with config enabled' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \ttest_config bash.showUntrackedFiles true &&\n \t(\n \t\tsane_unset GIT_PS1_SHOWUNTRACKEDFILES &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - shell variable set with config disabled' '\n-\tprintf \" (master)\" > expected &&\n+\tprintf \" (master)\" >expected &&\n \ttest_config bash.showUntrackedFiles false &&\n \t(\n \t\tGIT_PS1_SHOWUNTRACKEDFILES=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - shell variable set with config enabled' '\n-\tprintf \" (master %%)\" > expected &&\n+\tprintf \" (master %%)\" >expected &&\n \ttest_config bash.showUntrackedFiles true &&\n \t(\n \t\tGIT_PS1_SHOWUNTRACKEDFILES=y &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - untracked files status indicator - not shown inside .git directory' '\n-\tprintf \" (GIT_DIR!)\" > expected &&\n+\tprintf \" (GIT_DIR!)\" >expected &&\n \t(\n \t\tGIT_PS1_SHOWUNTRACKEDFILES=y &&\n \t\tcd .git &&\n-\t\t__git_ps1 > \"$actual\"\n+\t\t__git_ps1 >\"$actual\"\n \t) &&\n \ttest_cmp expected \"$actual\"\n '\n \n test_expect_success 'prompt - format string starting with dash' '\n-\tprintf -- \"-master\" > expected &&\n-\t__git_ps1 \"-%s\" > \"$actual\" &&\n+\tprintf -- \"-master\" >expected &&\n+\t__git_ps1 \"-%s\" >\"$actual\" &&\n \ttest_cmp expected \"$actual\"\n '\n \n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221123","messageId":"1371521826-3225-3-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 02/13] bash prompt: fix here document indentation in interactive rebase test","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:55Z","receivedAt":"2013-06-18T02:16:55Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nAlso move the shebang line into the here document.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n t/t9903-bash-prompt.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 7c7f8b97..b0af5d5f 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -248,12 +248,12 @@ test_expect_success 'prompt - inside bare repository' '\n \n test_expect_success 'prompt - interactive rebase' '\n \tprintf \" (b1|REBASE-i 2/3)\" >expected\n-\techo \"#!$SHELL_PATH\" >fake_editor.sh &&\n-\tcat >>fake_editor.sh <<\\EOF &&\n-echo \"exec echo\" >\"$1\"\n-echo \"edit $(git log -1 --format=\"%h\")\" >>\"$1\"\n-echo \"exec echo\" >>\"$1\"\n-EOF\n+\tcat >fake_editor.sh <<-EOF &&\n+\t\t#!$SHELL_PATH\n+\t\techo \"exec echo\" >\"\\$1\"\n+\t\techo \"edit \\$(git log -1 --format=\"%h\")\" >>\"\\$1\"\n+\t\techo \"exec echo\" >>\"\\$1\"\n+\tEOF\n \ttest_when_finished \"rm -f fake_editor.sh\" &&\n \tchmod a+x fake_editor.sh &&\n \ttest_set_editor \"$TRASH_DIRECTORY/fake_editor.sh\" &&\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221124","messageId":"1371521826-3225-4-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 03/13] completion, bash prompt: move __gitdir() tests to completion test suite","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:56Z","receivedAt":"2013-06-18T02:16:56Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nCurrently __gitdir() is duplicated in the git completion and prompt\nscripts, while its tests are in the prompt test suite.  This patch\nseries is about to change __git_ps1() in a way that it won't need\n__gitdir() anymore and __gitdir() will be removed from the prompt\nscript.\n\nSo move all __gitdir() test from the prompt test suite over to the\ncompletion test suite.  Update the setup tests so that they perform\nonly those steps that are necessary for each test suite.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n t/t9902-completion.sh  | 134 +++++++++++++++++++++++++++++++++++++++++++++++++\n t/t9903-bash-prompt.sh | 128 ----------------------------------------------\n 2 files changed, 134 insertions(+), 128 deletions(-)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 81a1657e..5469dee8 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -122,6 +122,140 @@ test_gitcomp_nl ()\n \n invalid_variable_name='${foo.bar}'\n \n+actual=\"$TRASH_DIRECTORY/actual\"\n+\n+test_expect_success 'setup for __gitdir tests' '\n+\tmkdir -p subdir/subsubdir &&\n+\tgit init otherrepo\n+'\n+\n+test_expect_success '__gitdir - from command line (through $__git_dir)' '\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n+\t(\n+\t\t__git_dir=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - repo as argument' '\n+\techo \"otherrepo/.git\" >expected &&\n+\t__gitdir \"otherrepo\" >\"$actual\" &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - remote as argument' '\n+\techo \"remote\" >expected &&\n+\t__gitdir \"remote\" >\"$actual\" &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - .git directory in cwd' '\n+\techo \".git\" >expected &&\n+\t__gitdir >\"$actual\" &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - .git directory in parent' '\n+\techo \"$(pwd -P)/.git\" >expected &&\n+\t(\n+\t\tcd subdir/subsubdir &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - cwd is a .git directory' '\n+\techo \".\" >expected &&\n+\t(\n+\t\tcd .git &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - parent is a .git directory' '\n+\techo \"$(pwd -P)/.git\" >expected &&\n+\t(\n+\t\tcd .git/refs/heads &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n+\t(\n+\t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n+\t\texport GIT_DIR &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '\n+\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n+\t(\n+\t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n+\t\texport GIT_DIR &&\n+\t\tcd subdir &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - non-existing $GIT_DIR' '\n+\t(\n+\t\tGIT_DIR=\"$TRASH_DIRECTORY/non-existing\" &&\n+\t\texport GIT_DIR &&\n+\t\ttest_must_fail __gitdir\n+\t)\n+'\n+\n+test_expect_success '__gitdir - gitfile in cwd' '\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n+\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n+\ttest_when_finished \"rm -f subdir/.git\" &&\n+\t(\n+\t\tcd subdir &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - gitfile in parent' '\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n+\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n+\ttest_when_finished \"rm -f subdir/.git\" &&\n+\t(\n+\t\tcd subdir/subsubdir &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '\n+\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n+\tmkdir otherrepo/dir &&\n+\ttest_when_finished \"rm -rf otherrepo/dir\" &&\n+\tln -s otherrepo/dir link &&\n+\ttest_when_finished \"rm -f link\" &&\n+\t(\n+\t\tcd link &&\n+\t\t__gitdir >\"$actual\"\n+\t) &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n+test_expect_success '__gitdir - not a git repository' '\n+\t(\n+\t\tcd subdir/subsubdir &&\n+\t\tGIT_CEILING_DIRECTORIES=\"$TRASH_DIRECTORY\" &&\n+\t\texport GIT_CEILING_DIRECTORIES &&\n+\t\ttest_must_fail __gitdir\n+\t)\n+'\n+\n test_expect_success '__gitcomp - trailing space - options' '\n \ttest_gitcomp \"--re\" \"--dry-run --reuse-message= --reedit-message=\n \t\t--reset-author\" <<-EOF\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex b0af5d5f..1047c664 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -12,7 +12,6 @@ test_description='test git-specific bash prompt functions'\n actual=\"$TRASH_DIRECTORY/actual\"\n \n test_expect_success 'setup for prompt tests' '\n-\tmkdir -p subdir/subsubdir &&\n \tgit init otherrepo &&\n \techo 1 >file &&\n \tgit add file &&\n@@ -35,133 +34,6 @@ test_expect_success 'setup for prompt tests' '\n \tgit checkout master\n '\n \n-test_expect_success 'gitdir - from command line (through $__git_dir)' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n-\t(\n-\t\t__git_dir=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - repo as argument' '\n-\techo \"otherrepo/.git\" >expected &&\n-\t__gitdir \"otherrepo\" >\"$actual\" &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - remote as argument' '\n-\techo \"remote\" >expected &&\n-\t__gitdir \"remote\" >\"$actual\" &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - .git directory in cwd' '\n-\techo \".git\" >expected &&\n-\t__gitdir >\"$actual\" &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - .git directory in parent' '\n-\techo \"$(pwd -P)/.git\" >expected &&\n-\t(\n-\t\tcd subdir/subsubdir &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - cwd is a .git directory' '\n-\techo \".\" >expected &&\n-\t(\n-\t\tcd .git &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - parent is a .git directory' '\n-\techo \"$(pwd -P)/.git\" >expected &&\n-\t(\n-\t\tcd .git/refs/heads &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n-\t(\n-\t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n-\t\texport GIT_DIR &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '\n-\techo \"$TRASH_DIRECTORY/otherrepo/.git\" >expected &&\n-\t(\n-\t\tGIT_DIR=\"$TRASH_DIRECTORY/otherrepo/.git\" &&\n-\t\texport GIT_DIR &&\n-\t\tcd subdir &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - non-existing $GIT_DIR' '\n-\t(\n-\t\tGIT_DIR=\"$TRASH_DIRECTORY/non-existing\" &&\n-\t\texport GIT_DIR &&\n-\t\ttest_must_fail __gitdir\n-\t)\n-'\n-\n-test_expect_success 'gitdir - gitfile in cwd' '\n-\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n-\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n-\ttest_when_finished \"rm -f subdir/.git\" &&\n-\t(\n-\t\tcd subdir &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - gitfile in parent' '\n-\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n-\techo \"gitdir: $TRASH_DIRECTORY/otherrepo/.git\" >subdir/.git &&\n-\ttest_when_finished \"rm -f subdir/.git\" &&\n-\t(\n-\t\tcd subdir/subsubdir &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '\n-\techo \"$(pwd -P)/otherrepo/.git\" >expected &&\n-\tmkdir otherrepo/dir &&\n-\ttest_when_finished \"rm -rf otherrepo/dir\" &&\n-\tln -s otherrepo/dir link &&\n-\ttest_when_finished \"rm -f link\" &&\n-\t(\n-\t\tcd link &&\n-\t\t__gitdir >\"$actual\"\n-\t) &&\n-\ttest_cmp expected \"$actual\"\n-'\n-\n-test_expect_success 'gitdir - not a git repository' '\n-\t(\n-\t\tcd subdir/subsubdir &&\n-\t\tGIT_CEILING_DIRECTORIES=\"$TRASH_DIRECTORY\" &&\n-\t\texport GIT_CEILING_DIRECTORIES &&\n-\t\ttest_must_fail __gitdir\n-\t)\n-'\n-\n test_expect_success 'prompt - branch name' '\n \tprintf \" (master)\" >expected &&\n \t__git_ps1 >\"$actual\" &&\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221125","messageId":"1371521826-3225-5-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 04/13] bash prompt: add a test for symbolic link symbolic refs","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:57Z","receivedAt":"2013-06-18T02:16:57Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n t/t9903-bash-prompt.sh | 9 +++++++++\n 1 file changed, 9 insertions(+)\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 1047c664..48460ef6 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -40,6 +40,15 @@ test_expect_success 'prompt - branch name' '\n \ttest_cmp expected \"$actual\"\n '\n \n+test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '\n+\tprintf \" (master)\" >expected &&\n+\ttest_when_finished \"git checkout master\" &&\n+\ttest_config core.preferSymlinkRefs true &&\n+\tgit checkout master &&\n+\t__git_ps1 >\"$actual\" &&\n+\ttest_cmp expected \"$actual\"\n+'\n+\n test_expect_success 'prompt - detached head' '\n \tprintf \" ((%s...))\" $(git log -1 --format=\"%h\" b1^) >expected &&\n \tgit checkout b1^ &&\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221126","messageId":"1371521826-3225-6-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 05/13] bash prompt: return early from __git_ps1() when not in a git repository","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:58Z","receivedAt":"2013-06-18T02:16:58Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\n... to gain one level of indentation for the bulk of the function.\n\n(The patch looks quite unreadable, you'd better check it with 'git\ndiff -w'.)\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 201 ++++++++++++++++++++-------------------\n 1 file changed, 101 insertions(+), 100 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 07a6218d..96b496cc 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -341,121 +341,122 @@ __git_ps1 ()\n \t\t\t#In PC mode PS1 always needs to be set\n \t\t\tPS1=\"$ps1pc_start$ps1pc_end\"\n \t\tfi\n+\t\treturn\n+\tfi\n+\n+\tlocal r=\"\"\n+\tlocal b=\"\"\n+\tlocal step=\"\"\n+\tlocal total=\"\"\n+\tif [ -d \"$g/rebase-merge\" ]; then\n+\t\tb=\"$(cat \"$g/rebase-merge/head-name\" 2>/dev/null)\"\n+\t\tstep=$(cat \"$g/rebase-merge/msgnum\" 2>/dev/null)\n+\t\ttotal=$(cat \"$g/rebase-merge/end\" 2>/dev/null)\n+\t\tif [ -f \"$g/rebase-merge/interactive\" ]; then\n+\t\t\tr=\"|REBASE-i\"\n+\t\telse\n+\t\t\tr=\"|REBASE-m\"\n+\t\tfi\n \telse\n-\t\tlocal r=\"\"\n-\t\tlocal b=\"\"\n-\t\tlocal step=\"\"\n-\t\tlocal total=\"\"\n-\t\tif [ -d \"$g/rebase-merge\" ]; then\n-\t\t\tb=\"$(cat \"$g/rebase-merge/head-name\" 2>/dev/null)\"\n-\t\t\tstep=$(cat \"$g/rebase-merge/msgnum\" 2>/dev/null)\n-\t\t\ttotal=$(cat \"$g/rebase-merge/end\" 2>/dev/null)\n-\t\t\tif [ -f \"$g/rebase-merge/interactive\" ]; then\n-\t\t\t\tr=\"|REBASE-i\"\n+\t\tif [ -d \"$g/rebase-apply\" ]; then\n+\t\t\tstep=$(cat \"$g/rebase-apply/next\" 2>/dev/null)\n+\t\t\ttotal=$(cat \"$g/rebase-apply/last\" 2>/dev/null)\n+\t\t\tif [ -f \"$g/rebase-apply/rebasing\" ]; then\n+\t\t\t\tb=\"$(cat \"$g/rebase-apply/head-name\" 2>/dev/null)\"\n+\t\t\t\tr=\"|REBASE\"\n+\t\t\telif [ -f \"$g/rebase-apply/applying\" ]; then\n+\t\t\t\tr=\"|AM\"\n \t\t\telse\n-\t\t\t\tr=\"|REBASE-m\"\n-\t\t\tfi\n-\t\telse\n-\t\t\tif [ -d \"$g/rebase-apply\" ]; then\n-\t\t\t\tstep=$(cat \"$g/rebase-apply/next\" 2>/dev/null)\n-\t\t\t\ttotal=$(cat \"$g/rebase-apply/last\" 2>/dev/null)\n-\t\t\t\tif [ -f \"$g/rebase-apply/rebasing\" ]; then\n-\t\t\t\t\tb=\"$(cat \"$g/rebase-apply/head-name\" 2>/dev/null)\"\n-\t\t\t\t\tr=\"|REBASE\"\n-\t\t\t\telif [ -f \"$g/rebase-apply/applying\" ]; then\n-\t\t\t\t\tr=\"|AM\"\n-\t\t\t\telse\n-\t\t\t\t\tr=\"|AM/REBASE\"\n-\t\t\t\tfi\n-\t\t\telif [ -f \"$g/MERGE_HEAD\" ]; then\n-\t\t\t\tr=\"|MERGING\"\n-\t\t\telif [ -f \"$g/CHERRY_PICK_HEAD\" ]; then\n-\t\t\t\tr=\"|CHERRY-PICKING\"\n-\t\t\telif [ -f \"$g/REVERT_HEAD\" ]; then\n-\t\t\t\tr=\"|REVERTING\"\n-\t\t\telif [ -f \"$g/BISECT_LOG\" ]; then\n-\t\t\t\tr=\"|BISECTING\"\n+\t\t\t\tr=\"|AM/REBASE\"\n \t\t\tfi\n+\t\telif [ -f \"$g/MERGE_HEAD\" ]; then\n+\t\t\tr=\"|MERGING\"\n+\t\telif [ -f \"$g/CHERRY_PICK_HEAD\" ]; then\n+\t\t\tr=\"|CHERRY-PICKING\"\n+\t\telif [ -f \"$g/REVERT_HEAD\" ]; then\n+\t\t\tr=\"|REVERTING\"\n+\t\telif [ -f \"$g/BISECT_LOG\" ]; then\n+\t\t\tr=\"|BISECTING\"\n+\t\tfi\n \n-\t\t\ttest -n \"$b\" ||\n-\t\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\" || {\n-\t\t\t\tdetached=yes\n-\t\t\t\tb=\"$(\n-\t\t\t\tcase \"${GIT_PS1_DESCRIBE_STYLE-}\" in\n-\t\t\t\t(contains)\n-\t\t\t\t\tgit describe --contains HEAD ;;\n-\t\t\t\t(branch)\n-\t\t\t\t\tgit describe --contains --all HEAD ;;\n-\t\t\t\t(describe)\n-\t\t\t\t\tgit describe HEAD ;;\n-\t\t\t\t(* | default)\n-\t\t\t\t\tgit describe --tags --exact-match HEAD ;;\n-\t\t\t\tesac 2>/dev/null)\" ||\n+\t\ttest -n \"$b\" ||\n+\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\" || {\n+\t\t\tdetached=yes\n+\t\t\tb=\"$(\n+\t\t\tcase \"${GIT_PS1_DESCRIBE_STYLE-}\" in\n+\t\t\t(contains)\n+\t\t\t\tgit describe --contains HEAD ;;\n+\t\t\t(branch)\n+\t\t\t\tgit describe --contains --all HEAD ;;\n+\t\t\t(describe)\n+\t\t\t\tgit describe HEAD ;;\n+\t\t\t(* | default)\n+\t\t\t\tgit describe --tags --exact-match HEAD ;;\n+\t\t\tesac 2>/dev/null)\" ||\n \n-\t\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n-\t\t\t\tb=\"unknown\"\n-\t\t\t\tb=\"($b)\"\n-\t\t\t}\n-\t\tfi\n+\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n+\t\t\tb=\"unknown\"\n+\t\t\tb=\"($b)\"\n+\t\t}\n+\tfi\n \n-\t\tif [ -n \"$step\" ] && [ -n \"$total\" ]; then\n-\t\t\tr=\"$r $step/$total\"\n-\t\tfi\n+\tif [ -n \"$step\" ] && [ -n \"$total\" ]; then\n+\t\tr=\"$r $step/$total\"\n+\tfi\n \n-\t\tlocal w=\"\"\n-\t\tlocal i=\"\"\n-\t\tlocal s=\"\"\n-\t\tlocal u=\"\"\n-\t\tlocal c=\"\"\n-\t\tlocal p=\"\"\n+\tlocal w=\"\"\n+\tlocal i=\"\"\n+\tlocal s=\"\"\n+\tlocal u=\"\"\n+\tlocal c=\"\"\n+\tlocal p=\"\"\n \n-\t\tif [ \"true\" = \"$(git rev-parse --is-inside-git-dir 2>/dev/null)\" ]; then\n-\t\t\tif [ \"true\" = \"$(git rev-parse --is-bare-repository 2>/dev/null)\" ]; then\n-\t\t\t\tc=\"BARE:\"\n+\tif [ \"true\" = \"$(git rev-parse --is-inside-git-dir 2>/dev/null)\" ]; then\n+\t\tif [ \"true\" = \"$(git rev-parse --is-bare-repository 2>/dev/null)\" ]; then\n+\t\t\tc=\"BARE:\"\n+\t\telse\n+\t\t\tb=\"GIT_DIR!\"\n+\t\tfi\n+\telif [ \"true\" = \"$(git rev-parse --is-inside-work-tree 2>/dev/null)\" ]; then\n+\t\tif [ -n \"${GIT_PS1_SHOWDIRTYSTATE-}\" ] &&\n+\t\t   [ \"$(git config --bool bash.showDirtyState)\" != \"false\" ]\n+\t\tthen\n+\t\t\tgit diff --no-ext-diff --quiet --exit-code || w=\"*\"\n+\t\t\tif git rev-parse --quiet --verify HEAD >/dev/null; then\n+\t\t\t\tgit diff-index --cached --quiet HEAD -- || i=\"+\"\n \t\t\telse\n-\t\t\t\tb=\"GIT_DIR!\"\n-\t\t\tfi\n-\t\telif [ \"true\" = \"$(git rev-parse --is-inside-work-tree 2>/dev/null)\" ]; then\n-\t\t\tif [ -n \"${GIT_PS1_SHOWDIRTYSTATE-}\" ] &&\n-\t\t\t   [ \"$(git config --bool bash.showDirtyState)\" != \"false\" ]\n-\t\t\tthen\n-\t\t\t\tgit diff --no-ext-diff --quiet --exit-code || w=\"*\"\n-\t\t\t\tif git rev-parse --quiet --verify HEAD >/dev/null; then\n-\t\t\t\t\tgit diff-index --cached --quiet HEAD -- || i=\"+\"\n-\t\t\t\telse\n-\t\t\t\t\ti=\"#\"\n-\t\t\t\tfi\n-\t\t\tfi\n-\t\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE-}\" ]; then\n-\t\t\t\tgit rev-parse --verify refs/stash >/dev/null 2>&1 && s=\"$\"\n+\t\t\t\ti=\"#\"\n \t\t\tfi\n+\t\tfi\n+\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE-}\" ]; then\n+\t\t\tgit rev-parse --verify refs/stash >/dev/null 2>&1 && s=\"$\"\n+\t\tfi\n \n-\t\t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES-}\" ] &&\n-\t\t\t   [ \"$(git config --bool bash.showUntrackedFiles)\" != \"false\" ] &&\n-\t\t\t   [ -n \"$(git ls-files --others --exclude-standard)\" ]\n-\t\t\tthen\n-\t\t\t\tu=\"%${ZSH_VERSION+%}\"\n-\t\t\tfi\n+\t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES-}\" ] &&\n+\t\t   [ \"$(git config --bool bash.showUntrackedFiles)\" != \"false\" ] &&\n+\t\t   [ -n \"$(git ls-files --others --exclude-standard)\" ]\n+\t\tthen\n+\t\t\tu=\"%${ZSH_VERSION+%}\"\n+\t\tfi\n \n-\t\t\tif [ -n \"${GIT_PS1_SHOWUPSTREAM-}\" ]; then\n-\t\t\t\t__git_ps1_show_upstream\n-\t\t\tfi\n+\t\tif [ -n \"${GIT_PS1_SHOWUPSTREAM-}\" ]; then\n+\t\t\t__git_ps1_show_upstream\n \t\tfi\n+\tfi\n \n-\t\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n-\t\tlocal f=\"$w$i$s$u\"\n-\t\tif [ $pcmode = yes ]; then\n-\t\t\tlocal gitstring=\n-\t\t\tif [ -n \"${GIT_PS1_SHOWCOLORHINTS-}\" ]; then\n-\t\t\t\t__git_ps1_colorize_gitstring\n-\t\t\telse\n-\t\t\t\tgitstring=\"$c${b##refs/heads/}${f:+$z$f}$r$p\"\n-\t\t\tfi\n-\t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n-\t\t\tPS1=\"$ps1pc_start$gitstring$ps1pc_end\"\n+\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n+\tlocal f=\"$w$i$s$u\"\n+\tif [ $pcmode = yes ]; then\n+\t\tlocal gitstring=\n+\t\tif [ -n \"${GIT_PS1_SHOWCOLORHINTS-}\" ]; then\n+\t\t\t__git_ps1_colorize_gitstring\n \t\telse\n-\t\t\t# NO color option unless in PROMPT_COMMAND mode\n-\t\t\tprintf -- \"$printf_format\" \"$c${b##refs/heads/}${f:+$z$f}$r$p\"\n+\t\t\tgitstring=\"$c${b##refs/heads/}${f:+$z$f}$r$p\"\n \t\tfi\n+\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n+\t\tPS1=\"$ps1pc_start$gitstring$ps1pc_end\"\n+\telse\n+\t\t# NO color option unless in PROMPT_COMMAND mode\n+\t\tprintf -- \"$printf_format\" \"$c${b##refs/heads/}${f:+$z$f}$r$p\"\n \tfi\n }\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221128","messageId":"1371521826-3225-7-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 06/13] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:16:59Z","receivedAt":"2013-06-18T02:16:59Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\n__git_ps1() finds out the path to the repository by using the\n__gitdir() helper function.  __gitdir() is basically just a wrapper\naround 'git rev-parse --git-dir', extended with support for\nrecognizing a remote repository given as argument, to use the path\ngiven on the command line, and with a few shortcuts to recognize a git\nrepository in cwd or at $GIT_DIR quickly without actually running 'git\nrev-parse'.  However, the former two is only necessary for the\ncompletion script but makes no sense for the bash prompt, while the\nlatter shortcuts are performance optimizations __git_ps1() can do\nwithout (they just avoid the overhead of fork()+exec()ing a git\nprocess).\n\nRun 'git rev-parse --git-dir' directly in __git_ps1(), because it will\nallow this patch series to combine several $(git rev-parse ...)\ncommand substitutions in the main code path, and the overall\nperformance benefit will far outweight the loss of those few shortcuts\nin __gitdir().  Furthermore, since __gitdir() is not needed anymore\nfor the prompt, remove it from the prompt script finally eliminating\nits duplication between the prompt and completion scripts.  Also\nremove the comment from the completion script warning about this code\nduplication.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |  2 --\n contrib/completion/git-prompt.sh       | 28 ++--------------------------\n 2 files changed, 2 insertions(+), 28 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 56c52c66..e0c8d6a1 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -33,8 +33,6 @@ esac\n # returns location of .git repo\n __gitdir ()\n {\n-\t# Note: this function is duplicated in git-prompt.sh\n-\t# When updating it, make sure you update the other one to match.\n \tif [ -z \"${1-}\" ]; then\n \t\tif [ -n \"${__git_dir-}\" ]; then\n \t\t\techo \"$__git_dir\"\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 96b496cc..0fc1d317 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -80,30 +80,6 @@\n # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on\n # the colored output of \"git status -sb\".\n \n-# __gitdir accepts 0 or 1 arguments (i.e., location)\n-# returns location of .git repo\n-__gitdir ()\n-{\n-\t# Note: this function is duplicated in git-completion.bash\n-\t# When updating it, make sure you update the other one to match.\n-\tif [ -z \"${1-}\" ]; then\n-\t\tif [ -n \"${__git_dir-}\" ]; then\n-\t\t\techo \"$__git_dir\"\n-\t\telif [ -n \"${GIT_DIR-}\" ]; then\n-\t\t\ttest -d \"${GIT_DIR-}\" || return 1\n-\t\t\techo \"$GIT_DIR\"\n-\t\telif [ -d .git ]; then\n-\t\t\techo .git\n-\t\telse\n-\t\t\tgit rev-parse --git-dir 2>/dev/null\n-\t\tfi\n-\telif [ -d \"$1/.git\" ]; then\n-\t\techo \"$1/.git\"\n-\telse\n-\t\techo \"$1\"\n-\tfi\n-}\n-\n # stores the divergence from upstream in $p\n # used by GIT_PS1_SHOWUPSTREAM\n __git_ps1_show_upstream ()\n@@ -335,8 +311,8 @@ __git_ps1 ()\n \t\t;;\n \tesac\n \n-\tlocal g=\"$(__gitdir)\"\n-\tif [ -z \"$g\" ]; then\n+\tlocal g=\n+\tif ! g=\"$(git rev-parse --git-dir 2>/dev/null)\"; then\n \t\tif [ $pcmode = yes ]; then\n \t\t\t#In PC mode PS1 always needs to be set\n \t\t\tPS1=\"$ps1pc_start$ps1pc_end\"\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221129","messageId":"1371521826-3225-8-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 07/13] bash prompt: use bash builtins to find out rebase state","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:00Z","receivedAt":"2013-06-18T02:17:00Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nDuring an ongoing interactive rebase __git_ps1() finds out the name of\nthe rebased branch, the total number of patches and the number of the\ncurrent patch by executing a '$(cat .git/rebase-merge/<FILE>)' command\nsubstitution for each.  That is not quite the most efficient way to\nread single line single word files, because it imposes the overhead of\nfork()ing a subshell and fork()+exec()ing 'cat' several times.\n\nUse the 'read' bash builtin instead to avoid those overheads.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 0fc1d317..26380787 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -325,9 +325,9 @@ __git_ps1 ()\n \tlocal step=\"\"\n \tlocal total=\"\"\n \tif [ -d \"$g/rebase-merge\" ]; then\n-\t\tb=\"$(cat \"$g/rebase-merge/head-name\" 2>/dev/null)\"\n-\t\tstep=$(cat \"$g/rebase-merge/msgnum\" 2>/dev/null)\n-\t\ttotal=$(cat \"$g/rebase-merge/end\" 2>/dev/null)\n+\t\tread b 2>/dev/null <\"$g/rebase-merge/head-name\"\n+\t\tread step 2>/dev/null <\"$g/rebase-merge/msgnum\"\n+\t\tread total 2>/dev/null <\"$g/rebase-merge/end\"\n \t\tif [ -f \"$g/rebase-merge/interactive\" ]; then\n \t\t\tr=\"|REBASE-i\"\n \t\telse\n@@ -335,10 +335,10 @@ __git_ps1 ()\n \t\tfi\n \telse\n \t\tif [ -d \"$g/rebase-apply\" ]; then\n-\t\t\tstep=$(cat \"$g/rebase-apply/next\" 2>/dev/null)\n-\t\t\ttotal=$(cat \"$g/rebase-apply/last\" 2>/dev/null)\n+\t\t\tread step 2>/dev/null <\"$g/rebase-apply/next\"\n+\t\t\tread total 2>/dev/null <\"$g/rebase-apply/last\"\n \t\t\tif [ -f \"$g/rebase-apply/rebasing\" ]; then\n-\t\t\t\tb=\"$(cat \"$g/rebase-apply/head-name\" 2>/dev/null)\"\n+\t\t\t\tread b 2>/dev/null <\"$g/rebase-apply/head-name\"\n \t\t\t\tr=\"|REBASE\"\n \t\t\telif [ -f \"$g/rebase-apply/applying\" ]; then\n \t\t\t\tr=\"|AM\"\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221130","messageId":"1371521826-3225-9-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 08/13] bash prompt: use bash builtins to find out current branch","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:01Z","receivedAt":"2013-06-18T02:17:01Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\n__git_ps1() runs the '$(git symbolic-ref HEAD)' command substitution\nto find out whether we are on a branch and to find out the name of\nthat branch.  This imposes the overhead of fork()ing a subshell and\nfork()+exec()ing a git process.\n\nSince HEAD is in most cases a single-line file and the symbolic ref\nformat is quite simple to recognize and parse, read and parse it using\nonly bash builtins, thereby sparing all that fork()+exec() overhead.\nHowever, HEAD can also be a symlink symbolic ref (due to\n'core.preferSymlinkRefs'), so do this only if HEAD is not a symlink.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 46 ++++++++++++++++++++++++----------------\n 1 file changed, 28 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 26380787..4e5c8efa 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -355,25 +355,35 @@ __git_ps1 ()\n \t\t\tr=\"|BISECTING\"\n \t\tfi\n \n-\t\ttest -n \"$b\" ||\n-\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\" || {\n-\t\t\tdetached=yes\n-\t\t\tb=\"$(\n-\t\t\tcase \"${GIT_PS1_DESCRIBE_STYLE-}\" in\n-\t\t\t(contains)\n-\t\t\t\tgit describe --contains HEAD ;;\n-\t\t\t(branch)\n-\t\t\t\tgit describe --contains --all HEAD ;;\n-\t\t\t(describe)\n-\t\t\t\tgit describe HEAD ;;\n-\t\t\t(* | default)\n-\t\t\t\tgit describe --tags --exact-match HEAD ;;\n-\t\t\tesac 2>/dev/null)\" ||\n+\t\tif [ -n \"$b\" ]; then\n+\t\t\t:\n+\t\telif [ -h \"$g/HEAD\" ]; then\n+\t\t\t# symlink symbolic ref\n+\t\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n+\t\telse\n+\t\t\tlocal head=\"\"\n+\t\t\tread head 2>/dev/null <\"$g/HEAD\" || return\n+\t\t\t# is it a symbolic ref?\n+\t\t\tb=\"${head#ref: }\"\n+\t\t\tif [ \"$head\" = \"$b\" ]; then\n+\t\t\t\tdetached=yes\n+\t\t\t\tb=\"$(\n+\t\t\t\tcase \"${GIT_PS1_DESCRIBE_STYLE-}\" in\n+\t\t\t\t(contains)\n+\t\t\t\t\tgit describe --contains HEAD ;;\n+\t\t\t\t(branch)\n+\t\t\t\t\tgit describe --contains --all HEAD ;;\n+\t\t\t\t(describe)\n+\t\t\t\t\tgit describe HEAD ;;\n+\t\t\t\t(* | default)\n+\t\t\t\t\tgit describe --tags --exact-match HEAD ;;\n+\t\t\t\tesac 2>/dev/null)\" ||\n \n-\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n-\t\t\tb=\"unknown\"\n-\t\t\tb=\"($b)\"\n-\t\t}\n+\t\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n+\t\t\t\tb=\"unknown\"\n+\t\t\t\tb=\"($b)\"\n+\t\t\tfi\n+\t\tfi\n \tfi\n \n \tif [ -n \"$step\" ] && [ -n \"$total\" ]; then\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221131","messageId":"1371521826-3225-10-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 09/13] bash prompt: use bash builtins to get detached HEAD abbrev. object name","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:02Z","receivedAt":"2013-06-18T02:17:02Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nWhen describing a detached HEAD according to the $GIT_PS1_DESCRIBE\nenvironment variable fails, __git_ps1() runs the '$(cut -c1-7\n.git/HEAD)' command substitution to put the 7 hexdigits abbreviated\ncommit object name in the prompt.  This imposes the overhead of\nfork()ing a subshell and fork()+exec()ing 'cut'.\n\nThanks to the previous patch at this point the contents of HEAD has\nalready been read into a variable, so we can get the 7 hexdigits using\nonly parameter expansions, sparing the fork()+exec() overhead.\n\nSince zsh doesn't implement substring expansion we can't just use\n${head:0:7}, hence the \"remove everything except the first 7 chars\"\nparameter expansion combination.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4e5c8efa..10ec6902 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -378,9 +378,8 @@ __git_ps1 ()\n \t\t\t\t(* | default)\n \t\t\t\t\tgit describe --tags --exact-match HEAD ;;\n \t\t\t\tesac 2>/dev/null)\" ||\n-\n-\t\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n-\t\t\t\tb=\"unknown\"\n+\t\t\t\t# detached head abbreviated object name\n+\t\t\t\tb=\"${head%${head#???????}}...\"\n \t\t\t\tb=\"($b)\"\n \t\t\tfi\n \t\tfi\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221133","messageId":"1371521826-3225-11-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 10/13] bash prompt: combine 'git rev-parse' executions","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:03Z","receivedAt":"2013-06-18T02:17:03Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\n>From the four '$(git rev-parse --<opt>)' command substitutions\n__git_ps1() executes three in its main code path:\n\n - the first to get the path to the .git directory ('--git-dir'),\n - the second to check whether we're inside the .git directory\n   ('--is-inside-git-dir'),\n - and the last, depending on the results of the second, either\n   * to check whether it's a bare repo ('--is-bare-repository'), or\n   * to check whether inside a work tree ('--is-inside-work-tree').\n\nNaturally, this imposes the overhead of fork()ing three subshells and\nfork()+exec()ing three git commands.\n\nCombine these four 'git rev-parse' queries into one and use bash\nparameter expansions to parse the combined output, i.e. to separate\nthe path to the .git directory from the true/false of\n'--is-inside-git-dir', etc.  This way we can eliminate two of the\nthree subshells and git commands.\n\nThe whole series speeds up the bash prompt on Windows/MSysGit\nconsiderably.  Here are some timing results in two scenarios, repeated\n10 times:\n\nAt the top of the work tree, before:\n\n    $ time for i in {0..9} ; do prompt=\"$(__git_ps1)\" ; done\n\n    real    0m1.716s\n    user    0m0.301s\n    sys     0m0.772s\n\n  After:\n\n    real    0m0.686s\n    user    0m0.075s\n    sys     0m0.287s\n\nIn a subdirectory, during rebase, stash status indicator enabled,\nbefore:\n\n    real    0m3.557s\n    user    0m0.495s\n    sys     0m1.767s\n\n  After:\n\n    real    0m0.702s\n    user    0m0.045s\n    sys     0m0.409s\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 18 +++++++++++++-----\n 1 file changed, 13 insertions(+), 5 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 10ec6902..b73cebf7 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -311,8 +311,9 @@ __git_ps1 ()\n \t\t;;\n \tesac\n \n-\tlocal g=\n-\tif ! g=\"$(git rev-parse --git-dir 2>/dev/null)\"; then\n+\tlocal repo_info=\n+\tif ! repo_info=\"$(git rev-parse --git-dir --is-inside-git-dir \\\n+\t\t--is-bare-repository --is-inside-work-tree 2>/dev/null)\"; then\n \t\tif [ $pcmode = yes ]; then\n \t\t\t#In PC mode PS1 always needs to be set\n \t\t\tPS1=\"$ps1pc_start$ps1pc_end\"\n@@ -320,6 +321,13 @@ __git_ps1 ()\n \t\treturn\n \tfi\n \n+\tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n+\trepo_info=\"${repo_info%$'\\n'*}\"\n+\tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n+\trepo_info=\"${repo_info%$'\\n'*}\"\n+\tlocal inside_gitdir=\"${repo_info##*$'\\n'}\"\n+\tlocal g=\"${repo_info%$'\\n'*}\"\n+\n \tlocal r=\"\"\n \tlocal b=\"\"\n \tlocal step=\"\"\n@@ -396,13 +404,13 @@ __git_ps1 ()\n \tlocal c=\"\"\n \tlocal p=\"\"\n \n-\tif [ \"true\" = \"$(git rev-parse --is-inside-git-dir 2>/dev/null)\" ]; then\n-\t\tif [ \"true\" = \"$(git rev-parse --is-bare-repository 2>/dev/null)\" ]; then\n+\tif [ \"true\" = \"$inside_gitdir\" ]; then\n+\t\tif [ \"true\" = \"$bare_repo\" ]; then\n \t\t\tc=\"BARE:\"\n \t\telse\n \t\t\tb=\"GIT_DIR!\"\n \t\tfi\n-\telif [ \"true\" = \"$(git rev-parse --is-inside-work-tree 2>/dev/null)\" ]; then\n+\telif [ \"true\" = \"$inside_worktree\" ]; then\n \t\tif [ -n \"${GIT_PS1_SHOWDIRTYSTATE-}\" ] &&\n \t\t   [ \"$(git config --bool bash.showDirtyState)\" != \"false\" ]\n \t\tthen\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221132","messageId":"1371521826-3225-12-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 11/13] bash prompt: use bash builtins to check stash state","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:04Z","receivedAt":"2013-06-18T02:17:04Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nWhen the environment variable $GIT_PS1_SHOWSTASHSTATE is set\n__git_ps1() checks the presence of stashes by running 'git rev-parse\n--verify refs/stash'.  This command not only checks that the\n'refs/stash' ref exists but also, well, verifies that it's a valid\nref.\n\nHowever, we don't need to be that thorough for the bash prompt.  We\ncan omit that verification and only check whether 'refs/stash' exists\nor not.  Since 'git pack-refs' never packs 'refs/stash', it's a matter\nof checking the existence of a ref file.  Perform this check using\nonly bash builtins to spare the overhead of fork()+exec()ing a git\nprocess.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex b73cebf7..208e2ec7 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -421,8 +421,9 @@ __git_ps1 ()\n \t\t\t\ti=\"#\"\n \t\t\tfi\n \t\tfi\n-\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE-}\" ]; then\n-\t\t\tgit rev-parse --verify refs/stash >/dev/null 2>&1 && s=\"$\"\n+\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE-}\" ] &&\n+\t\t   [ -r \"$g/refs/stash\" ]; then\n+\t\t\ts=\"$\"\n \t\tfi\n \n \t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES-}\" ] &&\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221134","messageId":"1371521826-3225-13-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 12/13] bash prompt: avoid command substitution when checking for untracked files","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:05Z","receivedAt":"2013-06-18T02:17:05Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nWhen enabled, the bash prompt can indicate the presence of untracked\nfiles with a '%' sign.  __git_ps1() checks for untracked files by running the\n'$(git ls-files --others --exclude-standard)' command substitution,\nand displays the indicator when there is no output.\n\nAvoid this command substitution by additionally passing\n'--error-unmatch *', and checking the command's return value.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 208e2ec7..77575b2d 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -428,7 +428,7 @@ __git_ps1 ()\n \n \t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES-}\" ] &&\n \t\t   [ \"$(git config --bool bash.showUntrackedFiles)\" != \"false\" ] &&\n-\t\t   [ -n \"$(git ls-files --others --exclude-standard)\" ]\n+\t\t   git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null\n \t\tthen\n \t\t\tu=\"%${ZSH_VERSION+%}\"\n \t\tfi\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221135","messageId":"1371521826-3225-14-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH v2 13/13] bash prompt: avoid command substitution when finalizing gitstring","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:17:06Z","receivedAt":"2013-06-18T02:17:06Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\nBefore setting $PS1, __git_ps1() uses a command substitution to\nredirect the output from a printf into a variable.  Spare the overhead\nof fork()ing a subshell by using 'printf -v <var>' to directly assign\nthe output to a variable.\n\nzsh's printf doesn't support the '-v <var>' option, so stick with the\ncommand substitution when under zsh.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 77575b2d..a8e78f42 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -447,7 +447,11 @@ __git_ps1 ()\n \t\telse\n \t\t\tgitstring=\"$c${b##refs/heads/}${f:+$z$f}$r$p\"\n \t\tfi\n-\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n+\t\tif [[ -n ${ZSH_VERSION-} ]]; then\n+\t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n+\t\telse\n+\t\t\tprintf -v gitstring -- \"$printf_format\" \"$gitstring\"\n+\t\tfi\n \t\tPS1=\"$ps1pc_start$gitstring$ps1pc_end\"\n \telse\n \t\t# NO color option unless in PROMPT_COMMAND mode\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221137","messageId":"20130618022826.GA2204@goldbirke","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH v2 00/13] bash prompt speedup","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T02:28:26Z","receivedAt":"2013-06-18T02:28:26Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Forgot to mention that it's built on top of 2847cae8 (prompt: squelch\nerror output from cat, 2013-06-14).\n\n\nBest,\nGábor\n\n\nOn Tue, Jun 18, 2013 at 04:16:53AM +0200, SZEDER Gábor wrote:\n> Hi,\n> \n> displaying the git-specific bash prompt on Windows/MinGW takes quite\n> long, long enough to be noticeable.  This is mainly caused by the\n> numerous fork()s and exec()s to create subshells and run git or other\n> commands, which are rather expensive on Windows.\n> \n> This patch series eliminates many command substitutions and commands\n> in __git_ps1() from top to bottom by replacing them with bash builtins\n> or consolidating them.  A few timing results are shown in the log\n> message of patch 10.\n> \n> \n> SZEDER Gábor (13):\n>   bash prompt: fix redirection coding style in tests\n>   bash prompt: fix here document indentation in interactive rebase test\n>   completion, bash prompt: move __gitdir() tests to completion test\n>     suite\n>   bash prompt: add a test for symbolic link symbolic refs\n>   bash prompt: return early from __git_ps1() when not in a git\n>     repository\n>   bash prompt: run 'git rev-parse --git-dir' directly instead of\n>     __gitdir()\n>   bash prompt: use bash builtins to find out rebase state\n>   bash prompt: use bash builtins to find out current branch\n>   bash prompt: use bash builtins to get detached HEAD abbrev. object\n>     name\n>   bash prompt: combine 'git rev-parse' executions\n>   bash prompt: use bash builtins to check stash state\n>   bash prompt: avoid command substitution when checking for untracked\n>     files\n>   bash prompt: avoid command substitution when finalizing gitstring\n> \n>  contrib/completion/git-completion.bash |   2 -\n>  contrib/completion/git-prompt.sh       | 223 ++++++++++++-----------\n>  t/t9902-completion.sh                  | 134 ++++++++++++++\n>  t/t9903-bash-prompt.sh                 | 319 +++++++++++----------------------\n>  4 files changed, 345 insertions(+), 333 deletions(-)\n> \n> -- \n> 1.8.3.1.487.g8f4672d\n> \n"},{"id":"221139","messageId":"CAPig+cTXxxkburz1PySnYptN70QUM3JwkKq9g5ULRYpUai4MrQ@mail.gmail.com","threadId":"34187","inReplyTo":"1371521826-3225-7-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH v2 06/13] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir()","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-06-18T04:16:32Z","receivedAt":"2013-06-18T04:16:32Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Jun 17, 2013 at 10:16 PM, SZEDER Gábor <szeder@ira.uka.de> wrote:\n> From: SZEDER Gábor <szeder@ira.uka.de>\n>\n> __git_ps1() finds out the path to the repository by using the\n> __gitdir() helper function.  __gitdir() is basically just a wrapper\n> around 'git rev-parse --git-dir', extended with support for\n> recognizing a remote repository given as argument, to use the path\n> given on the command line, and with a few shortcuts to recognize a git\n> repository in cwd or at $GIT_DIR quickly without actually running 'git\n> rev-parse'.  However, the former two is only necessary for the\n> completion script but makes no sense for the bash prompt, while the\n> latter shortcuts are performance optimizations __git_ps1() can do\n> without (they just avoid the overhead of fork()+exec()ing a git\n> process).\n>\n> Run 'git rev-parse --git-dir' directly in __git_ps1(), because it will\n> allow this patch series to combine several $(git rev-parse ...)\n> command substitutions in the main code path, and the overall\n> performance benefit will far outweight the loss of those few shortcuts\n\ns/outweight/outweigh/\n\n> in __gitdir().  Furthermore, since __gitdir() is not needed anymore\n> for the prompt, remove it from the prompt script finally eliminating\n> its duplication between the prompt and completion scripts.  Also\n> remove the comment from the completion script warning about this code\n> duplication.\n>\n> Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>\n"},{"id":"221145","messageId":"20130618055439.GD5916@sigill.intra.peff.net","threadId":"34187","inReplyTo":"1371521826-3225-3-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH v2 02/13] bash prompt: fix here document indentation in interactive rebase test","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-06-18T05:54:39Z","receivedAt":"2013-06-18T05:54:39Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jun 18, 2013 at 04:16:55AM +0200, SZEDER Gábor wrote:\n\n> -\techo \"#!$SHELL_PATH\" >fake_editor.sh &&\n> -\tcat >>fake_editor.sh <<\\EOF &&\n> -echo \"exec echo\" >\"$1\"\n> -echo \"edit $(git log -1 --format=\"%h\")\" >>\"$1\"\n> -echo \"exec echo\" >>\"$1\"\n> -EOF\n> +\tcat >fake_editor.sh <<-EOF &&\n> +\t\t#!$SHELL_PATH\n> +\t\techo \"exec echo\" >\"\\$1\"\n> +\t\techo \"edit \\$(git log -1 --format=\"%h\")\" >>\"\\$1\"\n> +\t\techo \"exec echo\" >>\"\\$1\"\n> +\tEOF\n\nThese days we the \"write_script\" helper, so I think you can write this\neven nicer as:\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 9e51263..91da313 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -248,14 +248,12 @@ EOF\n \n test_expect_success 'prompt - interactive rebase' '\n \tprintf \" (b1|REBASE-i 2/3)\" >expected\n-\techo \"#!$SHELL_PATH\" >fake_editor.sh &&\n-\tcat >>fake_editor.sh <<\\EOF &&\n-echo \"exec echo\" >\"$1\"\n-echo \"edit $(git log -1 --format=\"%h\")\" >>\"$1\"\n-echo \"exec echo\" >>\"$1\"\n-EOF\n+\twrite_script fake_editor.sh <<-\\EOF &&\n+\techo \"exec echo\" >\"$1\"\n+\techo \"edit $(git log -1 --format=\"%h\")\" >>\"$1\"\n+\techo \"exec echo\" >>\"$1\"\n+\tEOF\n \ttest_when_finished \"rm -f fake_editor.sh\" &&\n-\tchmod a+x fake_editor.sh &&\n \ttest_set_editor \"$TRASH_DIRECTORY/fake_editor.sh\" &&\n \tgit checkout b1 &&\n \ttest_when_finished \"git checkout master\" &&\n\n-Peff\n"},{"id":"221146","messageId":"20130618060535.GE5916@sigill.intra.peff.net","threadId":"34187","inReplyTo":"1371521826-3225-11-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH v2 10/13] bash prompt: combine 'git rev-parse' executions","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-06-18T06:05:35Z","receivedAt":"2013-06-18T06:05:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jun 18, 2013 at 04:17:03AM +0200, SZEDER Gábor wrote:\n\n> The whole series speeds up the bash prompt on Windows/MSysGit\n> considerably.  Here are some timing results in two scenarios, repeated\n> 10 times:\n> \n> At the top of the work tree, before:\n> \n>     $ time for i in {0..9} ; do prompt=\"$(__git_ps1)\" ; done\n> \n>     real    0m1.716s\n>     user    0m0.301s\n>     sys     0m0.772s\n> \n>   After:\n> \n>     real    0m0.686s\n>     user    0m0.075s\n>     sys     0m0.287s\n> \n> In a subdirectory, during rebase, stash status indicator enabled,\n> before:\n> \n>     real    0m3.557s\n>     user    0m0.495s\n>     sys     0m1.767s\n> \n>   After:\n> \n>     real    0m0.702s\n>     user    0m0.045s\n>     sys     0m0.409s\n\nVery nice speedup (or perhaps it is a testament to how bad fork() is on\nmsys). Reading patches 8 and 9, I can't help but feel that \"git status\"\nis letting us down a little by making us parse all of this data\nourselves. In theory, __git_ps1() could just be something like:\n\n  eval \"$(git status --shell)\"\n  printf ...\n\nand the heavy lifting could be done in a single C process which does not\nhave to worry about fork overhead. But that is quite far from where we\nare now, so while it might be an interesting place to go in the future,\nI do not think such dreams would want to hold up current work.\n\n-Peff\n"},{"id":"221169","messageId":"20130618094931.GB2204@goldbirke","threadId":"34187","inReplyTo":"20130618060535.GE5916@sigill.intra.peff.net","subject":"Re: [PATCH v2 10/13] bash prompt: combine 'git rev-parse' executions","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T09:49:31Z","receivedAt":"2013-06-18T09:49:31Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Tue, Jun 18, 2013 at 02:05:35AM -0400, Jeff King wrote:\n> On Tue, Jun 18, 2013 at 04:17:03AM +0200, SZEDER Gábor wrote:\n> \n> > The whole series speeds up the bash prompt on Windows/MSysGit\n> > considerably.  Here are some timing results in two scenarios, repeated\n> > 10 times:\n> > \n> > At the top of the work tree, before:\n> > \n> >     $ time for i in {0..9} ; do prompt=\"$(__git_ps1)\" ; done\n> > \n> >     real    0m1.716s\n> >     user    0m0.301s\n> >     sys     0m0.772s\n> > \n> >   After:\n> > \n> >     real    0m0.686s\n> >     user    0m0.075s\n> >     sys     0m0.287s\n> > \n> > In a subdirectory, during rebase, stash status indicator enabled,\n> > before:\n> > \n> >     real    0m3.557s\n> >     user    0m0.495s\n> >     sys     0m1.767s\n> > \n> >   After:\n> > \n> >     real    0m0.702s\n> >     user    0m0.045s\n> >     sys     0m0.409s\n> \n> Very nice speedup (or perhaps it is a testament to how bad fork() is on\n> msys).\n\nWell, it seems it's not just fork() & friends.  The latter case on\nLinux, before:\n\n  $ time for i in {0..99}; do prompt=\"$(__git_ps1)\" ; done\n  \n    real    0m2.819s\n    user    0m0.180s\n    sys     0m0.272s\n\n  After:\n  \n    real    0m0.787s\n    user    0m0.000s\n    sys     0m0.044s\n\nIf you look solely at speedup (Win/MSys: 80%, Linux: 72%), Linux isn't\nthat much better either, but overall it's about an order of magnitude\nfaster to begin with (100 repetitions vs. 10).\n\nBtw, it could still be a bit faster in you would care to change your\nprompt to run from $PROMPT_COMMAND, because it would avoid that final\n$(__git_ps1) command sunstitution, too.  But I didn't measured that\nbecause I find the interface awful ;)  (Hmm, speaking of which, the\npatch reading HEAD might break setups using $PROMPT_COMMAND, because\nit might do a simple return without updating $PS1...)\n\n> Reading patches 8 and 9, I can't help but feel that \"git status\"\n> is letting us down a little by making us parse all of this data\n> ourselves. In theory, __git_ps1() could just be something like:\n> \n>   eval \"$(git status --shell)\"\n>   printf ...\n> \n> and the heavy lifting could be done in a single C process which does not\n> have to worry about fork overhead. But that is quite far from where we\n> are now, so while it might be an interesting place to go in the future,\n> I do not think such dreams would want to hold up current work.\n\nYeah, that would be one way to go.  It would have the added benefit\nthat it could support 'core.abbrev' in the non-describable detached\nHEAD case without noticable overhead.\n\nOTOH it still requires a command substitution and a git command, so\nit's less than ideal.  The previous version of this series more than a\nyear ago did some tricky things to create a prompt without a single\nfork(), let alone exec(), e.g. looking for .git directory with bash\nbuiltins, comparing pwd's prefix with path to .git dir to find out\nwhether inside .git dir, etc.  As a result even that\nsubdir+rebase+stash case could be done in 10ms on Windows.  Too bad\nthat that \"inside .git dir\" check could misfire on case insensitive\nfile systems, so we have to do that check with '$(git rev-parse)'.\n\n  http://thread.gmane.org/gmane.comp.version-control.git/197432/focus=197450\n\n\nGábor\n"},{"id":"221172","messageId":"1371549698-16826-1-git-send-email-szeder@ira.uka.de","threadId":"34187","inReplyTo":"20130618094931.GB2204@goldbirke","subject":"[PATCH] fixup! bash prompt: use bash builtins to find out current branch","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-18T10:01:38Z","receivedAt":"2013-06-18T10:01:38Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"From: SZEDER Gábor <szeder@ira.uka.de>\n\n---\nOn Tue, Jun 18, 2013 at 11:49:31AM +0200, SZEDER Gábor wrote:\n> (Hmm, speaking of which, the\n> patch reading HEAD might break setups using $PROMPT_COMMAND, because\n> it might do a simple return without updating $PS1...)\n\nIndeed.  Here's the fixup.\n\n contrib/completion/git-prompt.sh | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4e5c8efa..3c8c7b0d 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -362,7 +362,12 @@ __git_ps1 ()\n \t\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n \t\telse\n \t\t\tlocal head=\"\"\n-\t\t\tread head 2>/dev/null <\"$g/HEAD\" || return\n+\t\t\tif ! read head 2>/dev/null <\"$g/HEAD\"; then\n+\t\t\t\tif [ $pcmode = yes ]; then\n+\t\t\t\t\tPS1=\"$ps1pc_start$ps1pc_end\"\n+\t\t\t\tfi\n+\t\t\t\treturn\n+\t\t\tfi\n \t\t\t# is it a symbolic ref?\n \t\t\tb=\"${head#ref: }\"\n \t\t\tif [ \"$head\" = \"$b\" ]; then\n-- \n1.8.3.1.487.g8f4672d\n"},{"id":"221258","messageId":"7vsj0f5pr7.fsf@alter.siamese.dyndns.org","threadId":"34187","inReplyTo":"1371521826-3225-1-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH v2 00/13] bash prompt speedup","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-06-18T16:48:28Z","receivedAt":"2013-06-18T16:48:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder@ira.uka.de> writes:\n\n> This patch series eliminates many command substitutions and commands\n> in __git_ps1() from top to bottom by replacing them with bash builtins\n> or consolidating them.  A few timing results are shown in the log\n> message of patch 10.\n\nNice.  I think I saw Peff's comment and discussion between you two\nalready resuted in a fixup, so perhaps I'll see a reroll sometime\nlater when the dust settles?\n\nAlso, could you help review the other topic by Eduardo R. D'Avila\nabout colored prompt (Sion Oosthoek, who did the color support,\nCC'ed)?\n\n    http://thread.gmane.org/gmane.comp.version-control.git/228017\n\nThe impression I got when the PROMPT_COMMAND series was discussed\nlast October was that you need to use \\[...\\] pairs to get the\ncursor position right for the purpose of command line editing, and\nD'Avila's series seemed to only do so in PROMPT_COMMAND mode.\n"},{"id":"221296","messageId":"20130618193551.GB13480@xs4all.nl","threadId":"34187","inReplyTo":"7vsj0f5pr7.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2 00/13] bash prompt speedup","fromName":"Simon Oosthoek","fromEmail":"s.oosthoek@xs4all.nl","sentAt":"2013-06-18T19:35:51Z","receivedAt":"2013-06-18T19:35:51Z","isPatch":true,"sender":{"key":"s.oosthoek@xs4all.nl","avatar":"https://avatars.githubusercontent.com/u/11677720?v=4"},"body":"* Junio C Hamano <gitster@pobox.com> [2013-06-18 09:48:28 -0700]:\n\n> SZEDER Gábor <szeder@ira.uka.de> writes:\n> \n> > This patch series eliminates many command substitutions and commands\n> > in __git_ps1() from top to bottom by replacing them with bash builtins\n> > or consolidating them.  A few timing results are shown in the log\n> > message of patch 10.\n> \n> Nice.  I think I saw Peff's comment and discussion between you two\n> already resuted in a fixup, so perhaps I'll see a reroll sometime\n> later when the dust settles?\n> \n> Also, could you help review the other topic by Eduardo R. D'Avila\n> about colored prompt (Sion Oosthoek, who did the color support,\n> CC'ed)?\n> \n>     http://thread.gmane.org/gmane.comp.version-control.git/228017\n> \n> The impression I got when the PROMPT_COMMAND series was discussed\n> last October was that you need to use \\[...\\] pairs to get the\n> cursor position right for the purpose of command line editing, and\n> D'Avila's series seemed to only do so in PROMPT_COMMAND mode.\n> \n\nHi Junio e.a.\n\nUnfortunately I'm very busy with lots of stuff, so hardly time to look at this. (I didn't read the full patch or resulting file)\n\nThe PROMPT_COMMAND business was not something I was glad to use, I was unable to get command substitution mode to work with colours and keep bash happy about the prompt string length. The thing to test is not whether or not colours appear when using substitution in PS1, but to see whether bash will not mess up the commandline when browsing through the history. This is especially inconvenient with very long commandlines (as you can imagine).\n\nAn optimisation which I've not yet had time to work on would be to do a lot of the processing in separate functions and use the result in separate functions for pcmode and subst. mode. The idea being that the maintainability of the logic for generating the prompt goes up (no duplicate code, clear separation, etc.) and the size of the called functions to gerenate the prompt goes down. And perhaps most important that it would be very easy to build a customised version of __git_ps1() using those functions from the standard code. \n\nI know this is pretty vague, I wish it wasn't so...\n\nIf it's somehow possible to eliminate the PROMPT_COMMAND mode, I'm all for it. But I doubt it can be done while keeping commandline browsing working ok... (please go ahead and prove me wrong!)\n\nCheers\n\nSimon\n"}]}