{"thread":{"id":"34266","subject":"[PATCHv3 00/16] bash prompt speedup","startedAt":"2013-06-24T16:39:10Z","lastAt":"2013-06-25T02:00:48Z","messageCount":19,"participants":["SZEDER Gábor","Junio C Hamano","Eduardo R. D'Avila"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"221831","messageId":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":null,"subject":"[PATCHv3 00/16] bash prompt speedup","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:10Z","receivedAt":"2013-06-24T16:39:10Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Hi,\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 command\nexecutions in __git_ps1() from top to bottom by replacing them with\nbash builtins or consolidating them.  A few timing results are shown\nin the log message of the last patch.\n\nChanges since v2 [1]:\n\n - The detached HEAD abbreviated object name is now unique and\n   respects core.abbrev; see patches 5 and 11, replacing v2's patch 9.\n   (This is why I asked the detached HEAD before root commit thing\n   yesterday.)  \n - Patches 12 and 16 are new.\n - Incorporated Peff's suggestion about using the 'write_script'\n   helper into patch 2.\n - Incorporated Eric's typofix.\n - Rephrased a few commit messages.\n\nIt applies on top of current master; 2847cae8 (prompt: squelch error\noutput from cat, 2013-06-14) graduated recently.\n\nThis patch series will conflict with Eduardo's work on refactoring the\ncolorizing function, and the conflict is not trivial.  Although there\nare still some open questions left with that series (using tput, zsh\ntests), those won't affect the conflicts between the two patch series.\nSo, for the convenience of our maintainer, I picked up Eduardo's\nseries, took the liberty to apply a fixup commit on top with my\nsuggestions from [2], merged the two series, and published the result\nat:\n\n  https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization\n\nEduardo, could you please also check that my conflict resolution is\ncorrect?  Thanks.\n\n\nBest,\nGábor\n\n\n[1] - http://thread.gmane.org/gmane.comp.version-control.git/228132\n[2] - http://article.gmane.org/gmane.comp.version-control.git/228707\n\n\nSZEDER Gábor (16):\n  bash prompt: fix redirection coding style in tests\n  bash prompt: use 'write_script' helper 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: print unique detached HEAD abbreviated object name\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: combine 'git rev-parse' executions in the main code path\n  bash prompt: combine 'git rev-parse' for detached head\n  bash prompt: use bash builtins to check for unborn branch for dirty\n    state\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  bash prompt: mention that PROMPT_COMMAND mode is faster\n\n contrib/completion/git-completion.bash |   2 -\n contrib/completion/git-prompt.sh       | 241 ++++++++++++------------\n t/t9902-completion.sh                  | 134 ++++++++++++++\n t/t9903-bash-prompt.sh                 | 323 +++++++++++----------------------\n 4 files changed, 367 insertions(+), 333 deletions(-)\n\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221832","messageId":"1372091966-19315-2-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 01/16] bash prompt: fix redirection coding style in tests","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:11Z","receivedAt":"2013-06-24T16:39:11Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Use '>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.599.g4459181\n"},{"id":"221833","messageId":"1372091966-19315-3-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 02/16] bash prompt: use 'write_script' helper in interactive rebase test","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:12Z","receivedAt":"2013-06-24T16:39:12Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Helped-by: Jeff King <peff@peff.net>\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n t/t9903-bash-prompt.sh | 12 +++++-------\n 1 file changed, 5 insertions(+), 7 deletions(-)\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 7c7f8b97..442b9a20 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -248,14 +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+\twrite_script fake_editor.sh <<-\\EOF &&\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 \tgit checkout b1 &&\n \ttest_when_finished \"git checkout master\" &&\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221834","messageId":"1372091966-19315-4-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 03/16] completion, bash prompt: move __gitdir() tests to completion test suite","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:13Z","receivedAt":"2013-06-24T16:39:13Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Currently __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() tests 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 442b9a20..df36239a 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.599.g4459181\n"},{"id":"221835","messageId":"1372091966-19315-5-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 04/16] bash prompt: add a test for symbolic link symbolic refs","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:14Z","receivedAt":"2013-06-24T16:39:14Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Signed-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 df36239a..416e6219 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.599.g4459181\n"},{"id":"221836","messageId":"1372091966-19315-6-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 05/16] bash prompt: print unique detached HEAD abbreviated object name","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:15Z","receivedAt":"2013-06-24T16:39:15Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When describing a detached HEAD according to the $GIT_PS1_DESCRIBE\nenvironment variable fails, __git_ps1() runs 'cut -c1-7 .git/HEAD' to\nshow the 7 hexdigits abbreviated commit object name in the prompt.\nObviously, this neither respects core.abbrev nor produces a unique\nobject name.\n\nFix this by using 'git rev-parse --short HEAD' instead and adjust the\ncorresponding test to use non-standard number of hexdigits.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 2 +-\n t/t9903-bash-prompt.sh           | 3 ++-\n 2 files changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 07a6218d..3c5e62bb 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -392,7 +392,7 @@ __git_ps1 ()\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=\"$(git rev-parse --short HEAD 2>/dev/null)...\" ||\n \t\t\t\tb=\"unknown\"\n \t\t\t\tb=\"($b)\"\n \t\t\t}\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 416e6219..0d53aa6d 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -50,7 +50,8 @@ test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '\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\" --abbrev=13 b1^) >expected &&\n+\ttest_config core.abbrev 13 &&\n \tgit checkout b1^ &&\n \ttest_when_finished \"git checkout master\" &&\n \t__git_ps1 >\"$actual\" &&\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221837","messageId":"1372091966-19315-7-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 06/16] 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-24T16:39:16Z","receivedAt":"2013-06-24T16:39:16Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"... 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 3c5e62bb..a915b04c 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=\"$(git rev-parse --short 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=\"$(git rev-parse --short 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.599.g4459181\n"},{"id":"221839","messageId":"1372091966-19315-8-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 07/16] bash prompt: run 'git rev-parse --git-dir' directly instead of __gitdir()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:17Z","receivedAt":"2013-06-24T16:39:17Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"__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 outweigh 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       | 26 +-------------------------\n 2 files changed, 1 insertion(+), 27 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6c3bafee..ebc40d48 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 a915b04c..0563dea8 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,7 +311,7 @@ __git_ps1 ()\n \t\t;;\n \tesac\n \n-\tlocal g=\"$(__gitdir)\"\n+\tlocal g=\"$(git rev-parse --git-dir 2>/dev/null)\"\n \tif [ -z \"$g\" ]; then\n \t\tif [ $pcmode = yes ]; then\n \t\t\t#In PC mode PS1 always needs to be set\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221841","messageId":"1372091966-19315-9-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 08/16] bash prompt: use bash builtins to find out rebase state","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:18Z","receivedAt":"2013-06-24T16:39:18Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"During 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 0563dea8..bc402f56 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.599.g4459181\n"},{"id":"221840","messageId":"1372091966-19315-10-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 09/16] bash prompt: use bash builtins to find out current branch","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:19Z","receivedAt":"2013-06-24T16:39:19Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"__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.\nDon't display the git prompt if reading HEAD fails, because a readable\nHEAD is required for a git repository.  HEAD can also be a symlink\nsymbolic ref (due to 'core.preferSymlinkRefs'), so use bash builtins\nfor reading HEAD only when HEAD is not a symlink.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 51 ++++++++++++++++++++++++++--------------\n 1 file changed, 33 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex bc402f56..c2050b69 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -355,25 +355,40 @@ __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\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+\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=\"$(git rev-parse --short HEAD 2>/dev/null)...\" ||\n-\t\t\tb=\"unknown\"\n-\t\t\tb=\"($b)\"\n-\t\t}\n+\t\t\t\tb=\"$(git rev-parse --short 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.599.g4459181\n"},{"id":"221842","messageId":"1372091966-19315-11-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 10/16] bash prompt: combine 'git rev-parse' executions in the main code path","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:20Z","receivedAt":"2013-06-24T16:39:20Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"There are a couple of '$(git rev-parse --<opt>)' command substitutions\nin __git_ps1() and three of them are executed in the 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 a single one and use\nbash parameter expansions to parse the combined output, i.e. to\nseparate the 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\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 c2050b69..7d226251 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=\"$(git rev-parse --git-dir 2>/dev/null)\"\n-\tif [ -z \"$g\" ]; then\n+\tlocal repo_info=\"$(git rev-parse --git-dir --is-inside-git-dir \\\n+\t\t--is-bare-repository --is-inside-work-tree 2>/dev/null)\"\n+\tif [ -z \"$repo_info\" ]; 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@@ -402,13 +410,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.599.g4459181\n"},{"id":"221843","messageId":"1372091966-19315-12-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 11/16] bash prompt: combine 'git rev-parse' for detached head","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:21Z","receivedAt":"2013-06-24T16:39:21Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When describing a detached HEAD according to the $GIT_PS1_DESCRIBE\nenvironment variable fails, __git_ps1() now runs the '$(git rev-parse\n--short HEAD)' command substitution to get the abbreviated detached\nHEAD commit object name.  This imposes the overhead of fork()ing a\nsubshell and fork()+exec()ing a git process.\n\nAvoid this overhead by combining this command substitution with the\n\"main\" 'git rev-parse' execution for getting the path to the .git\ndirectory & co.  This means that we'll look for the abbreviated commit\nobject name even when it's not necessary, because we're on a branch or\nthe detached HEAD can be described.  It doesn't matter, however,\nbecause once 'git rev-parse' is up and running to fulfill all those\nother queries, the additional overhead of looking for the abbreviated\ncommit object name is not measurable because it's lost in the noise.\n\nThere is a caveat, however, when we are on an unborn branch, because\nin that case HEAD doesn't point to a valid commit, hence the query for\nthe abbreviated commit object name fails.  Therefore, '--short HEAD'\nmust be the last options to 'git rev-parse' in order to get all the\nother necessary information for the prompt even on an unborn branch.\nFurthermore, in that case, and in that case only, 'git rev-parse'\ndoesn't output the last line containing the abbreviated commit object\nname, obviously, so we have to take care to only parse it if 'git\nrev-parse' exited without any error.\n\nAlthough there are tests already excercising __git_ps1() on unborn\nbranches, they all do so implicitly.  Add a test that checks this\nexplicitly.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 16 ++++++++++++----\n t/t9903-bash-prompt.sh           |  8 ++++++++\n 2 files changed, 20 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 7d226251..88d6121d 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -311,8 +311,12 @@ __git_ps1 ()\n \t\t;;\n \tesac\n \n-\tlocal repo_info=\"$(git rev-parse --git-dir --is-inside-git-dir \\\n-\t\t--is-bare-repository --is-inside-work-tree 2>/dev/null)\"\n+\tlocal repo_info rev_parse_exit_code\n+\trepo_info=\"$(git rev-parse --git-dir --is-inside-git-dir \\\n+\t\t--is-bare-repository --is-inside-work-tree \\\n+\t\t--short HEAD 2>/dev/null)\"\n+\trev_parse_exit_code=\"$?\"\n+\n \tif [ -z \"$repo_info\" ]; then\n \t\tif [ $pcmode = yes ]; then\n \t\t\t#In PC mode PS1 always needs to be set\n@@ -321,6 +325,11 @@ __git_ps1 ()\n \t\treturn\n \tfi\n \n+\tlocal short_sha\n+\tif [ \"$rev_parse_exit_code\" = \"0\" ]; then\n+\t\tshort_sha=\"${repo_info##*$'\\n'}\"\n+\t\trepo_info=\"${repo_info%$'\\n'*}\"\n+\tfi\n \tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n \trepo_info=\"${repo_info%$'\\n'*}\"\n \tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n@@ -392,8 +401,7 @@ __git_ps1 ()\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=\"$(git rev-parse --short HEAD 2>/dev/null)...\" ||\n-\t\t\t\tb=\"unknown\"\n+\t\t\t\tb=\"$short_sha...\"\n \t\t\t\tb=\"($b)\"\n \t\t\tfi\n \t\tfi\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 0d53aa6d..b9895c79 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -49,6 +49,14 @@ test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '\n \ttest_cmp expected \"$actual\"\n '\n \n+test_expect_success 'prompt - unborn branch' '\n+\tprintf \" (unborn)\" >expected &&\n+\tgit checkout --orphan unborn &&\n+\ttest_when_finished \"git 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\" --abbrev=13 b1^) >expected &&\n \ttest_config core.abbrev 13 &&\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221844","messageId":"1372091966-19315-13-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 12/16] bash prompt: use bash builtins to check for unborn branch for dirty state","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:22Z","receivedAt":"2013-06-24T16:39:22Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When the dirty work tree and index status indicator is enabled,\n__git_ps1() checks for changes in the index by running 'git diff-index\n--cached --quiet HEAD --' and looking at its exit code.  However, that\nmakes sense only when HEAD points to a valid commit: on an unborn\nbranch the failure of said command would be caused by the invalid\nHEAD, not by changes in the index.  Therefore, __git_ps1() first\nchecks for a valid HEAD by running 'git rev-parse --quiet --verify\nHEAD'.\n\nSince the previous patch we implicitly check HEAD's validity by\nrunning 'git rev-parse ... --short HEAD', making the dirty status\nindicator's 'git rev-parse' check redundant.  It's sufficient to check\nfor non-emptyness of the variable holding the abbreviated commit\nobject name, thereby sparing 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 | 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 88d6121d..6e8f486e 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -429,7 +429,7 @@ __git_ps1 ()\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\tif [ -n \"$short_sha\" ]; then\n \t\t\t\tgit diff-index --cached --quiet HEAD -- || i=\"+\"\n \t\t\telse\n \t\t\t\ti=\"#\"\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221845","messageId":"1372091966-19315-14-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 13/16] bash prompt: use bash builtins to check stash state","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:23Z","receivedAt":"2013-06-24T16:39:23Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When 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\nAlso run 'git pack-refs --all' in the corresponding test to document\nthat the prompt script depends on 'git pack-refs' not packing\n'refs/stash' and to catch possible breakages should this behavior ever\nchange.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 5 +++--\n t/t9903-bash-prompt.sh           | 1 +\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 6e8f486e..afa86703 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -435,8 +435,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-}\" ] &&\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex b9895c79..c05458cb 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -328,6 +328,7 @@ test_expect_success 'prompt - stash status indicator - stash' '\n \techo 2 >file &&\n \tgit stash &&\n \ttest_when_finished \"git stash drop\" &&\n+\tgit pack-refs --all &&\n \t(\n \t\tGIT_PS1_SHOWSTASHSTATE=y &&\n \t\t__git_ps1 >\"$actual\"\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221846","messageId":"1372091966-19315-15-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 14/16] bash prompt: avoid command substitution when checking for untracked files","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:24Z","receivedAt":"2013-06-24T16:39:24Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When 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 afa86703..5ea6a68b 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -442,7 +442,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.599.g4459181\n"},{"id":"221847","messageId":"1372091966-19315-16-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 15/16] bash prompt: avoid command substitution when finalizing gitstring","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:25Z","receivedAt":"2013-06-24T16:39:25Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Before 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 that 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 5ea6a68b..7152ae49 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -461,7 +461,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.599.g4459181\n"},{"id":"221848","messageId":"1372091966-19315-17-git-send-email-szeder@ira.uka.de","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"[PATCHv3 16/16] bash prompt: mention that PROMPT_COMMAND mode is faster","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2013-06-24T16:39:26Z","receivedAt":"2013-06-24T16:39:26Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"__git_ps1() is usually added to the prompt inside a command\nsubstitution, imposing the overhead of fork()ing a subshell.  Using\n__git_ps1() for $PROMPT_COMMAND is slightly faster, because it avoids\nthat command substitution.\n\nMention this in the comments about setting up the git prompt.\n\nThe whole series speeds up the bash prompt on Windows/MSysGit\nconsiderably.  Here are some timing results in three scenarios, each\nrepeated 10 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.687s\n    user    0m0.075s\n    sys     0m0.396s\n\n  After, from $PROMPT_COMMAND:\n\n    $ time for i in {0..9} ; do __git_ps1 '\\h:\\w' '$ ' ; done\n\n    real    0m0.546s\n    user    0m0.075s\n    sys     0m0.181s\n\nAt the top of the work tree, detached head, before:\n\n    real    0m2.574s\n    user    0m0.376s\n    sys     0m1.207s\n\n  After:\n\n    real    0m1.139s\n    user    0m0.151s\n    sys     0m0.500s\n\n  After, from $PROMPT_COMMAND:\n\n    real    0m1.030s\n    user    0m0.245s\n    sys     0m0.336s\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.717s\n    user    0m0.120s\n    sys     0m0.300s\n\n  After, from $PROMPT_COMMAND:\n\n    real    0m0.577s\n    user    0m0.047s\n    sys     0m0.258s\n\nOn Linux the speedup ratio is comparable to Windows, but overall it\nwas about an order of magnitude faster to begin with.  The last case\nfrom above, repeated 100 times, before:\n\n    $ time for i in {0..99} ; do prompt=\"$(__git_ps1)\" ; done\n\n    real    0m2.806s\n    user    0m0.180s\n    sys     0m0.264s\n\n  After:\n\n    real    0m0.857s\n    user    0m0.020s\n    sys     0m0.028s\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-prompt.sh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 7152ae49..daed6a1d 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -15,11 +15,11 @@\n #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n #        ZSH:  PS1='[%n@%m %c$(__git_ps1 \" (%s)\")]\\$ '\n #        the optional argument will be used as format string.\n-#    3b) Alternatively, if you are using bash, __git_ps1 can be\n-#        used for PROMPT_COMMAND with two parameters, <pre> and\n-#        <post>, which are strings you would put in $PS1 before\n-#        and after the status string generated by the git-prompt\n-#        machinery.  e.g.\n+#    3b) Alternatively, for a slighly faster prompt, if you are\n+#        using bash, __git_ps1 can be used for PROMPT_COMMAND\n+#        with two parameters, <pre> and <post>, which are strings\n+#        you would put in $PS1 before and after the status string\n+#        generated by the git-prompt machinery.  e.g.\n #        Bash: PROMPT_COMMAND='__git_ps1 \"\\u@\\h:\\w\" \"\\\\\\$ \"'\n #        ZSH:  precmd () { __git_ps1 \"%n\" \":%~$ \" \"|%s\" }\n #        will show username, at-sign, host, colon, cwd, then\n-- \n1.8.3.1.599.g4459181\n"},{"id":"221885","messageId":"7vzjuf71lq.fsf@alter.siamese.dyndns.org","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCHv3 00/16] bash prompt speedup","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-06-24T19:25:21Z","receivedAt":"2013-06-24T19:25:21Z","isPatch":false,"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> 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 command\n> executions in __git_ps1() from top to bottom by replacing them with\n> bash builtins or consolidating them.  A few timing results are shown\n> in the log message of the last patch.\n>\n> Changes since v2 [1]:\n>\n>  - The detached HEAD abbreviated object name is now unique and\n>    respects core.abbrev; see patches 5 and 11, replacing v2's patch 9.\n>    (This is why I asked the detached HEAD before root commit thing\n>    yesterday.)  \n>  - Patches 12 and 16 are new.\n>  - Incorporated Peff's suggestion about using the 'write_script'\n>    helper into patch 2.\n>  - Incorporated Eric's typofix.\n>  - Rephrased a few commit messages.\n>\n> It applies on top of current master; 2847cae8 (prompt: squelch error\n> output from cat, 2013-06-14) graduated recently.\n>\n> This patch series will conflict with Eduardo's work on refactoring the\n> colorizing function, and the conflict is not trivial.  Although there\n> are still some open questions left with that series (using tput, zsh\n> tests), those won't affect the conflicts between the two patch series.\n> So, for the convenience of our maintainer, I picked up Eduardo's\n> series, took the liberty to apply a fixup commit on top with my\n> suggestions from [2], merged the two series, and published the result\n> at:\n>\n>   https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization\n>\n> Eduardo, could you please also check that my conflict resolution is\n> correct?  Thanks.\n\nWell, then I'll fetch that premerged result and queue it on 'pu',\nwait for a while just in case if you need to reroll based on\nsomebody else's input and otherwise merge that down to 'next' and\nthen to 'master'.\n\nThanks.\n"},{"id":"221919","messageId":"CAOz-D1LN08R3hJeNMop+_POADC=iP8MLTXUZR5VW5jBtrVppzQ@mail.gmail.com","threadId":"34266","inReplyTo":"1372091966-19315-1-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCHv3 00/16] bash prompt speedup","fromName":"Eduardo R. D'Avila","fromEmail":"erdavila@gmail.com","sentAt":"2013-06-25T02:00:48Z","receivedAt":"2013-06-25T02:00:48Z","isPatch":false,"sender":{"key":"erdavila@gmail.com","avatar":"https://avatars.githubusercontent.com/u/341488?v=4"},"body":"2013/6/24 SZEDER Gábor <szeder@ira.uka.de>:\n> This patch series will conflict with Eduardo's work on refactoring the\n> colorizing function, and the conflict is not trivial.  Although there\n> are still some open questions left with that series (using tput, zsh\n> tests), those won't affect the conflicts between the two patch series.\n> So, for the convenience of our maintainer, I picked up Eduardo's\n> series, took the liberty to apply a fixup commit on top with my\n> suggestions from [2], merged the two series, and published the result\n> at:\n>\n>   https://github.com/szeder/git.git bash-prompt-speedup-and-color-refactorization\n>\n> Eduardo, could you please also check that my conflict resolution is\n> correct?  Thanks.\n\nGábor, the conflict resolution is quite correct.\n\nThanks,\n\nEduardo\n"}]}