{"thread":{"id":"12657","subject":"[PATCH 01/16] tr portability fixes","startedAt":"2008-03-12T21:29:57Z","lastAt":"2008-03-19T22:56:17Z","messageCount":59,"participants":["Jeff King","Jakub Narebski","Junio C Hamano","Johannes Sixt","Adam Piatyszek","Frank Lichtenheld","Brandon Casey","Alex Riesen"],"isPatch":true,"patchVersion":1,"patchTotal":16},"messages":[{"id":"71847","messageId":"20080312212957.GB26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 01/16] tr portability fixes","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:29:57Z","receivedAt":"2008-03-12T21:29:57Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Specifying character ranges in tr differs between System V\nand POSIX. In System V, brackets are required (e.g.,\n'[A-Z]'), whereas in POSIX they are not.\n\nWe can mostly get around this by just using the bracket form\nfor both sets, as in:\n\n  tr '[A-Z] '[a-z]'\n\nin which case POSIX interpets this as \"'[' becomes '['\",\nwhich is OK.\n\nHowever, this doesn't work with multiple sequences, like:\n\n  # rot13\n  tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]'\n\nwhere the POSIX version does not behave the same as the\nSystem V version. In this case, we must simply enumerate the\nsequence.\n\nThis patch fixes problematic uses of tr in git scripts and\ntest scripts in one of three ways:\n\n  - if a single sequence, make sure it uses brackets\n  - if multiple sequences, enumerate\n  - if extra brackets (e.g., tr '[A]' 'a'), eliminate\n    brackets\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis was posted earlier, but mid-thread.\n\n git-bisect.sh            |    4 ++--\n git-filter-branch.sh     |    4 ++--\n t/t4022-diff-rewrite.sh  |    5 ++++-\n t/t7003-filter-branch.sh |    2 +-\n 4 files changed, 9 insertions(+), 6 deletions(-)\n\ndiff --git a/git-bisect.sh b/git-bisect.sh\nindex 2c32d0b..48fb92d 100755\n--- a/git-bisect.sh\n+++ b/git-bisect.sh\n@@ -293,14 +293,14 @@ bisect_next() {\n \tbisect_next_check good\n \n \tskip=$(git for-each-ref --format='%(objectname)' \\\n-\t\t\"refs/bisect/skip-*\" | tr '[\\012]' ' ') || exit\n+\t\t\"refs/bisect/skip-*\" | tr '\\012' ' ') || exit\n \n \tBISECT_OPT=''\n \ttest -n \"$skip\" && BISECT_OPT='--bisect-all'\n \n \tbad=$(git rev-parse --verify refs/bisect/bad) &&\n \tgood=$(git for-each-ref --format='^%(objectname)' \\\n-\t\t\"refs/bisect/good-*\" | tr '[\\012]' ' ') &&\n+\t\t\"refs/bisect/good-*\" | tr '\\012' ' ') &&\n \teval=\"git rev-list --bisect-vars $BISECT_OPT $good $bad --\" &&\n \teval=\"$eval $(cat \"$GIT_DIR/BISECT_NAMES\")\" &&\n \teval=$(filter_skipped \"$eval\" \"$skip\") &&\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 010353a..59cf023 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -58,8 +58,8 @@ eval \"$functions\"\n # \"author\" or \"committer\n \n set_ident () {\n-\tlid=\"$(echo \"$1\" | tr \"A-Z\" \"a-z\")\"\n-\tuid=\"$(echo \"$1\" | tr \"a-z\" \"A-Z\")\"\n+\tlid=\"$(echo \"$1\" | tr \"[A-Z]\" \"[a-z]\")\"\n+\tuid=\"$(echo \"$1\" | tr \"[a-z]\" \"[A-Z]\")\"\n \tpick_id_script='\n \t\t/^'$lid' /{\n \t\t\ts/'\\''/'\\''\\\\'\\'\\''/g\ndiff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh\nindex 6de4acb..bf996fc 100755\n--- a/t/t4022-diff-rewrite.sh\n+++ b/t/t4022-diff-rewrite.sh\n@@ -8,7 +8,10 @@ test_expect_success setup '\n \n \tcat ../../COPYING >test &&\n \tgit add test &&\n-\ttr 'a-zA-Z' 'n-za-mN-ZA-M' <../../COPYING >test\n+\ttr \\\n+\t  \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n+\t  \"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM\" \\\n+\t  <../../COPYING >test\n \n '\n \ndiff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh\nindex 6e14bf1..553131f 100755\n--- a/t/t7003-filter-branch.sh\n+++ b/t/t7003-filter-branch.sh\n@@ -4,7 +4,7 @@ test_description='git-filter-branch'\n . ./test-lib.sh\n \n make_commit () {\n-\tlower=$(echo $1 | tr A-Z a-z)\n+\tlower=$(echo $1 | tr '[A-Z]' '[a-z]')\n \techo $lower > $lower\n \tgit add $lower\n \ttest_tick\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71848","messageId":"20080312213010.GC26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 02/16] t0050: perl portability fix","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:30:10Z","receivedAt":"2008-03-12T21:30:10Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Older versions of perl (such as 5.005) don't understand -CO, nor\ndo they understand the \"U\" pack specifier. Instead of using perl,\nlet's just printf the binary bytes we are interested in.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n t/t0050-filesystem.sh |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh\nindex cd088b3..3fbad77 100755\n--- a/t/t0050-filesystem.sh\n+++ b/t/t0050-filesystem.sh\n@@ -4,8 +4,8 @@ test_description='Various filesystem issues'\n \n . ./test-lib.sh\n \n-auml=`perl -CO -e 'print pack(\"U\",0x00E4)'`\n-aumlcdiar=`perl -CO -e 'print pack(\"U\",0x0061).pack(\"U\",0x0308)'`\n+auml=`printf '\\xc3\\xa4'`\n+aumlcdiar=`printf '\\x61\\xcc\\x88'`\n \n test_expect_success 'see if we expect ' '\n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71849","messageId":"20080312213106.GD26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 03/16] more tr portability test script fixes","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:31:06Z","receivedAt":"2008-03-12T21:31:06Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Dealing with NULs is not always safe with tr. On Solaris,\nincoming NULs are silently deleted by both the System V and\nUCB versions of tr. When converting to NULs, the System V\nversion works fine, but the UCB version silently ignores the\nrequest to convert the character.\n\nThis patch changes all instances of tr using NULs to use\n\"perl -pe 'y///'\" instead.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis dramatically increases the amount of perl in the testsuite.\nHowever, it is a portable subset of perl, and it isn't the first perl in\nthe testsuite.\n\n t/diff-lib.sh            |    4 ++--\n t/t0020-crlf.sh          |    2 +-\n t/t1300-repo-config.sh   |    4 ++--\n t/t3300-funny-names.sh   |    6 +++---\n t/t4020-diff-external.sh |    2 +-\n t/t4103-apply-binary.sh  |    4 ++--\n t/t4116-apply-reverse.sh |    4 ++--\n t/t4200-rerere.sh        |    2 +-\n t/t5300-pack-object.sh   |    2 +-\n test-sha1.sh             |    4 ++--\n 10 files changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/t/diff-lib.sh b/t/diff-lib.sh\nindex 7dc6d7e..28b941c 100644\n--- a/t/diff-lib.sh\n+++ b/t/diff-lib.sh\n@@ -21,8 +21,8 @@ compare_diff_raw_z () {\n     # Also we do not check SHA1 hash generation in this test, which\n     # is a job for t0000-basic.sh\n \n-    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n-    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n+    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n+    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n     git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n }\n \ndiff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh\nindex 90ea081..2bfeac9 100755\n--- a/t/t0020-crlf.sh\n+++ b/t/t0020-crlf.sh\n@@ -5,7 +5,7 @@ test_description='CRLF conversion'\n . ./test-lib.sh\n \n q_to_nul () {\n-\ttr Q '\\000'\n+\tperl -pe 'y/Q/\\000/'\n }\n \n q_to_cr () {\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 4928a57..b36a901 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -657,12 +657,12 @@ Qsection.sub=section.val4\n Qsection.sub=section.val5Q\n EOF\n \n-git config --null --list | tr '\\000' 'Q' > result\n+git config --null --list | perl -pe 'y/\\000/Q/' > result\n echo >>result\n \n test_expect_success '--null --list' 'cmp result expect'\n \n-git config --null --get-regexp 'val[0-9]' | tr '\\000' 'Q' > result\n+git config --null --get-regexp 'val[0-9]' | perl -pe 'y/\\000/Q/' > result\n echo >>result\n \n test_expect_success '--null --get-regexp' 'cmp result expect'\ndiff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh\nindex 98c133d..24a00a9 100755\n--- a/t/t3300-funny-names.sh\n+++ b/t/t3300-funny-names.sh\n@@ -54,7 +54,7 @@ echo 'just space\n no-funny\n tabs\t,\" (dq) and spaces' >expected\n test_expect_success 'git ls-files -z with-funny' \\\n-\t'git ls-files -z | tr \\\\000 \\\\012 >current &&\n+\t'git ls-files -z | perl -pe y/\\\\000/\\\\012/ >current &&\n \tgit diff expected current'\n \n t1=`git write-tree`\n@@ -83,11 +83,11 @@ test_expect_success 'git diff-tree with-funny' \\\n echo 'A\n tabs\t,\" (dq) and spaces' >expected\n test_expect_success 'git diff-index -z with-funny' \\\n-\t'git diff-index -z --name-status $t0 | tr \\\\000 \\\\012 >current &&\n+\t'git diff-index -z --name-status $t0 | perl -pe y/\\\\000/\\\\012/ >current &&\n \tgit diff expected current'\n \n test_expect_success 'git diff-tree -z with-funny' \\\n-\t'git diff-tree -z --name-status $t0 $t1 | tr \\\\000 \\\\012 >current &&\n+\t'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\\\000/\\\\012/ >current &&\n \tgit diff expected current'\n \n cat > expected <<\\EOF\ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex 8882933..bf8f778 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -99,7 +99,7 @@ test_expect_success 'no diff with -diff' '\n \tgit diff | grep Binary\n '\n \n-echo NULZbetweenZwords | tr Z '\\000' > file\n+echo NULZbetweenZwords | perl -pe 'y/Z/\\000/' > file\n \n test_expect_success 'force diff with \"diff\"' '\n \techo >.gitattributes \"file diff\" &&\ndiff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh\nindex 7c25634..1b58233 100755\n--- a/t/t4103-apply-binary.sh\n+++ b/t/t4103-apply-binary.sh\n@@ -24,10 +24,10 @@ git update-index --add --remove file1 file2 file4\n git-commit -m 'Initial Version' 2>/dev/null\n \n git-checkout -b binary\n-tr 'x' '\\000' <file1 >file3\n+perl -pe 'y/x/\\000/' <file1 >file3\n cat file3 >file4\n git add file2\n-tr '\\000' 'v' <file3 >file1\n+perl -pe 'y/\\000/v/' <file3 >file1\n rm -f file2\n git update-index --add --remove file1 file2 file3 file4\n git-commit -m 'Second Version'\ndiff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh\nindex b1d35ab..c3f4579 100755\n--- a/t/t4116-apply-reverse.sh\n+++ b/t/t4116-apply-reverse.sh\n@@ -12,14 +12,14 @@ test_description='git apply in reverse\n test_expect_success setup '\n \n \tfor i in a b c d e f g h i j k l m n; do echo $i; done >file1 &&\n-\ttr \"ijk\" '\\''\\000\\001\\002'\\'' <file1 >file2 &&\n+\tperl -pe \"y/ijk/\\\\000\\\\001\\\\002/\" <file1 >file2 &&\n \n \tgit add file1 file2 &&\n \tgit commit -m initial &&\n \tgit tag initial &&\n \n \tfor i in a b c g h i J K L m o n p q; do echo $i; done >file1 &&\n-\ttr \"mon\" '\\''\\000\\001\\002'\\'' <file1 >file2 &&\n+\tperl -pe \"y/mon/\\\\000\\\\001\\\\002/\" <file1 >file2 &&\n \n \tgit commit -a -m second &&\n \tgit tag second &&\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex eeff3c9..3cbfee7 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -129,7 +129,7 @@ test_expect_success 'rerere kicked in' \"! grep ======= a1\"\n test_expect_success 'rerere prefers first change' 'git diff a1 expect'\n \n rm $rr/postimage\n-echo \"$sha1\ta1\" | tr '\\012' '\\000' > .git/rr-cache/MERGE_RR\n+echo \"$sha1\ta1\" | perl -pe 'y/\\012/\\000/' > .git/rr-cache/MERGE_RR\n \n test_expect_success 'rerere clear' 'git rerere clear'\n \ndiff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh\nindex cd3c149..c955fe4 100755\n--- a/t/t5300-pack-object.sh\n+++ b/t/t5300-pack-object.sh\n@@ -15,7 +15,7 @@ test_expect_success \\\n     'rm -f .git/index*\n      for i in a b c\n      do\n-\t     dd if=/dev/zero bs=4k count=1 | tr \"\\\\000\" $i >$i &&\n+\t     dd if=/dev/zero bs=4k count=1 | perl -pe \"y/\\\\000/$i/\" >$i &&\n \t     git update-index --add $i || return 1\n      done &&\n      cat c >d && echo foo >>d && git update-index --add d &&\ndiff --git a/test-sha1.sh b/test-sha1.sh\nindex bf526c8..0f0bc5d 100755\n--- a/test-sha1.sh\n+++ b/test-sha1.sh\n@@ -10,7 +10,7 @@ do\n \t\t{\n \t\t\ttest -z \"$pfx\" || echo \"$pfx\"\n \t\t\tdd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |\n-\t\t\ttr '\\000' 'g'\n+\t\t\tperl -pe 'y/\\000/g/'\n \t\t} | ./test-sha1 $cnt\n \t`\n \tif test \"$expect\" = \"$actual\"\n@@ -55,7 +55,7 @@ do\n \t\t{\n \t\t\ttest -z \"$pfx\" || echo \"$pfx\"\n \t\t\tdd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |\n-\t\t\ttr '\\000' 'g'\n+\t\t\tperl -pe 'y/\\000/g/'\n \t\t} | sha1sum |\n \t\tsed -e 's/ .*//'\n \t`\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71850","messageId":"20080312213217.GE26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 04/16] grep portability fix: don't use \"-e\" or \"-q\"","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:32:17Z","receivedAt":"2008-03-12T21:32:17Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"System V versions of grep (such as Solaris /usr/bin/grep)\ndon't understand either of these options. git's usage of\n\"grep -e pattern\" fell into one of two categories:\n\n 1. equivalent to \"grep pattern\". -e is only useful here if\n    the pattern begins with a \"-\", but all of the patterns\n    are hardcoded and do not begin with a dash.\n\n 2. stripping comments and blank lines with\n\n      grep -v -e \"^$\" -e \"^#\"\n\n    We can fortunately do this in the affirmative as\n\n      grep '^[^#]'\n\nUses of \"-q\" can be replaced with redirection to /dev/null.\nIn many tests, however, \"grep -q\" is used as \"if this string\nis in the expected output, we are OK\". In this case, it is\nfine to just remove the \"-q\" entirely; it simply makes the\n\"verbose\" mode of the test slightly more verbose.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nOne might disagree with my \"grep without -q actually shows useful\nverbose output in tests\" statement. In that case, we can >/dev/null all\nof those instances.\n\n git-rebase--interactive.sh      |    6 +++---\n git-submodule.sh                |    6 +++---\n t/t0030-stripspace.sh           |   34 +++++++++++++++++-----------------\n t/t3404-rebase-interactive.sh   |    3 +--\n t/t3800-mktag.sh                |    2 +-\n t/t5400-send-pack.sh            |    2 +-\n t/t7502-status.sh               |    2 +-\n t/t7600-merge.sh                |    4 ++--\n t/t9400-git-cvsserver-server.sh |   26 +++++++++++++-------------\n 9 files changed, 42 insertions(+), 43 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex c2bedd6..4c3280a 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -78,8 +78,8 @@ mark_action_done () {\n \tsed -e 1q < \"$TODO\" >> \"$DONE\"\n \tsed -e 1d < \"$TODO\" >> \"$TODO\".new\n \tmv -f \"$TODO\".new \"$TODO\"\n-\tcount=$(($(grep -ve '^$' -e '^#' < \"$DONE\" | wc -l)))\n-\ttotal=$(($count+$(grep -ve '^$' -e '^#' < \"$TODO\" | wc -l)))\n+\tcount=$(grep -c '^[^#]' < \"$DONE\")\n+\ttotal=$(($count+$(grep -c '^[^#]' < \"$TODO\")))\n \tif test \"$last_count\" != \"$count\"\n \tthen\n \t\tlast_count=$count\n@@ -110,7 +110,7 @@ die_abort () {\n }\n \n has_action () {\n-\tgrep -vqe '^$' -e '^#' \"$1\"\n+\tgrep '^[^#]' \"$1\" >/dev/null\n }\n \n pick_one () {\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 7171cb6..ceb2295 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -230,7 +230,7 @@ cmd_init()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n+\tgit ls-files --stage -- \"$@\" | grep '^160000 ' |\n \twhile read mode sha1 stage path\n \tdo\n \t\t# Skip already registered paths\n@@ -284,7 +284,7 @@ cmd_update()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n+\tgit ls-files --stage -- \"$@\" | grep '^160000 ' |\n \twhile read mode sha1 stage path\n \tdo\n \t\tname=$(module_name \"$path\") || exit\n@@ -367,7 +367,7 @@ cmd_status()\n \t\tshift\n \tdone\n \n-\tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n+\tgit ls-files --stage -- \"$@\" | grep '^160000 ' |\n \twhile read mode sha1 stage path\n \tdo\n \t\tname=$(module_name \"$path\") || exit\ndiff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh\nindex 818c862..3ecdd66 100755\n--- a/t/t0030-stripspace.sh\n+++ b/t/t0030-stripspace.sh\n@@ -245,12 +245,12 @@ test_expect_success \\\n \n test_expect_success \\\n     'text plus spaces without newline at end should not show spaces' '\n-    ! (printf \"$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (printf \"$ttt$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (printf \"$ttt$ttt$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (printf \"$ttt$sss$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (printf \"$ttt$ttt$sss$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (printf \"$ttt$sss$sss$sss\" | git stripspace | grep -q \"  \")\n+    ! (printf \"$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (printf \"$ttt$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (printf \"$ttt$ttt$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (printf \"$ttt$sss$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (printf \"$ttt$ttt$sss$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (printf \"$ttt$sss$sss$sss\" | git stripspace | grep \"  \" >/dev/null)\n '\n \n test_expect_success \\\n@@ -282,12 +282,12 @@ test_expect_success \\\n \n test_expect_success \\\n     'text plus spaces at end should not show spaces' '\n-    ! (echo \"$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (echo \"$ttt$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (echo \"$ttt$ttt$ttt$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (echo \"$ttt$sss$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (echo \"$ttt$ttt$sss$sss\" | git stripspace | grep -q \"  \") &&\n-    ! (echo \"$ttt$sss$sss$sss\" | git stripspace | grep -q \"  \")\n+    ! (echo \"$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (echo \"$ttt$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (echo \"$ttt$ttt$ttt$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (echo \"$ttt$sss$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (echo \"$ttt$ttt$sss$sss\" | git stripspace | grep \"  \" >/dev/null) &&\n+    ! (echo \"$ttt$sss$sss$sss\" | git stripspace | grep \"  \" >/dev/null)\n '\n \n test_expect_success \\\n@@ -341,11 +341,11 @@ test_expect_success \\\n \n test_expect_success \\\n     'spaces without newline at end should not show spaces' '\n-    ! (printf \"\" | git stripspace | grep -q \" \") &&\n-    ! (printf \"$sss\" | git stripspace | grep -q \" \") &&\n-    ! (printf \"$sss$sss\" | git stripspace | grep -q \" \") &&\n-    ! (printf \"$sss$sss$sss\" | git stripspace | grep -q \" \") &&\n-    ! (printf \"$sss$sss$sss$sss\" | git stripspace | grep -q \" \")\n+    ! (printf \"\" | git stripspace | grep \" \" >/dev/null) &&\n+    ! (printf \"$sss\" | git stripspace | grep \" \" >/dev/null) &&\n+    ! (printf \"$sss$sss\" | git stripspace | grep \" \" >/dev/null) &&\n+    ! (printf \"$sss$sss$sss\" | git stripspace | grep \" \" >/dev/null) &&\n+    ! (printf \"$sss$sss$sss$sss\" | git stripspace | grep \" \" >/dev/null)\n '\n \n test_expect_success \\\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 049aa37..f098231 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -149,8 +149,7 @@ test_expect_success 'stop on conflicting pick' '\n \tdiff -u expect .git/.dotest-merge/patch &&\n \tdiff -u expect2 file1 &&\n \ttest 4 = $(grep -v \"^#\" < .git/.dotest-merge/done | wc -l) &&\n-\ttest 0 = $(grep -ve \"^#\" -e \"^$\" < .git/.dotest-merge/git-rebase-todo |\n-\t\twc -l)\n+\ttest 0 = $(grep -c \"^[^#]\" < .git/.dotest-merge/git-rebase-todo)\n '\n \n test_expect_success 'abort' '\ndiff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh\nindex f280320..2780758 100755\n--- a/t/t3800-mktag.sh\n+++ b/t/t3800-mktag.sh\n@@ -15,7 +15,7 @@ check_verify_failure () {\n \texpect=\"$2\"\n \ttest_expect_success \"$1\" '\n \t\t( ! git-mktag <tag.sig 2>message ) &&\n-\t\tgrep -q \"$expect\" message\n+\t\tgrep \"$expect\" message\n \t'\n }\n \ndiff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh\nindex 2d0c07f..2b6b6e3 100755\n--- a/t/t5400-send-pack.sh\n+++ b/t/t5400-send-pack.sh\n@@ -120,7 +120,7 @@ test_expect_success \\\n \tcd .. &&\n \tgit-clone parent child && cd child && git-push --all &&\n \tcd ../parent &&\n-\tgit-branch -a >branches && ! grep -q origin/master branches\n+\tgit-branch -a >branches && ! grep origin/master branches\n '\n \n rewound_push_setup() {\ndiff --git a/t/t7502-status.sh b/t/t7502-status.sh\nindex e006074..70b802b 100755\n--- a/t/t7502-status.sh\n+++ b/t/t7502-status.sh\n@@ -33,7 +33,7 @@ test_expect_success 'setup' '\n \n test_expect_success 'status (1)' '\n \n-\tgrep -e \"use \\\"git rm --cached <file>\\.\\.\\.\\\" to unstage\" output\n+\tgrep \"use \\\"git rm --cached <file>\\.\\.\\.\\\" to unstage\" output\n \n '\n \ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex 5d16628..590505b 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -371,7 +371,7 @@ test_expect_success 'override config option -n' '\n \tgit merge --summary c2 >diffstat.txt &&\n \tverify_merge file result.1-5 msg.1-5 &&\n \tverify_parents $c1 $c2 &&\n-\tif ! grep -e \"^ file |  *2 +-$\" diffstat.txt\n+\tif ! grep \"^ file |  *2 +-$\" diffstat.txt\n \tthen\n \t\techo \"[OOPS] diffstat was not generated\"\n \tfi\n@@ -386,7 +386,7 @@ test_expect_success 'override config option --summary' '\n \tgit merge -n c2 >diffstat.txt &&\n \tverify_merge file result.1-5 msg.1-5 &&\n \tverify_parents $c1 $c2 &&\n-\tif grep -e \"^ file |  *2 +-$\" diffstat.txt\n+\tif grep \"^ file |  *2 +-$\" diffstat.txt\n \tthen\n \t\techo \"[OOPS] diffstat was generated\"\n \t\tfalse\ndiff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh\nindex 0a20971..e82b365 100755\n--- a/t/t9400-git-cvsserver-server.sh\n+++ b/t/t9400-git-cvsserver-server.sh\n@@ -94,7 +94,7 @@ EOF\n \n test_expect_success 'pserver authentication' \\\n   'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'pserver authentication failure (non-anonymous user)' \\\n   'if cat request-git | git-cvsserver pserver >log 2>&1\n@@ -103,11 +103,11 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \\\n    else\n        true\n    fi &&\n-   tail -n1 log | grep -q \"^I HATE YOU$\"'\n+   tail -n1 log | grep \"^I HATE YOU$\"'\n \n test_expect_success 'pserver authentication (login)' \\\n   'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'pserver authentication failure (login/non-anonymous user)' \\\n   'if cat login-git | git-cvsserver pserver >log 2>&1\n@@ -116,7 +116,7 @@ test_expect_success 'pserver authentication failure (login/non-anonymous user)'\n    else\n        true\n    fi &&\n-   tail -n1 log | grep -q \"^I HATE YOU$\"'\n+   tail -n1 log | grep \"^I HATE YOU$\"'\n \n \n # misuse pserver authentication for testing of req_Root\n@@ -146,15 +146,15 @@ test_expect_success 'req_Root failure (relative pathname)' \\\n    else\n        true\n    fi &&\n-   tail log | grep -q \"^error 1 Root must be an absolute pathname$\"'\n+   tail log | grep \"^error 1 Root must be an absolute pathname$\"'\n \n test_expect_success 'req_Root failure (conflicting roots)' \\\n   'cat request-conflict | git-cvsserver pserver >log 2>&1 &&\n-   tail log | grep -q \"^error 1 Conflicting roots specified$\"'\n+   tail log | grep \"^error 1 Conflicting roots specified$\"'\n \n test_expect_success 'req_Root (strict paths)' \\\n   'cat request-anonymous | git-cvsserver --strict-paths pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (strict-paths)' '\n     ! cat request-anonymous |\n@@ -163,7 +163,7 @@ test_expect_success 'req_Root failure (strict-paths)' '\n \n test_expect_success 'req_Root (w/o strict-paths)' \\\n   'cat request-anonymous | git-cvsserver pserver $WORKDIR/ >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (w/o strict-paths)' '\n     ! cat request-anonymous |\n@@ -181,7 +181,7 @@ EOF\n \n test_expect_success 'req_Root (base-path)' \\\n   'cat request-base | git-cvsserver --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (base-path)' '\n     ! cat request-anonymous |\n@@ -192,14 +192,14 @@ GIT_DIR=\"$SERVERDIR\" git config --bool gitcvs.enabled false || exit 1\n \n test_expect_success 'req_Root (export-all)' \\\n   'cat request-anonymous | git-cvsserver --export-all pserver $WORKDIR >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (export-all w/o whitelist)' \\\n   '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'\n \n test_expect_success 'req_Root (everything together)' \\\n   'cat request-base | git-cvsserver --export-all --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep -q \"^I LOVE YOU$\"'\n+   tail -n1 log | grep \"^I LOVE YOU$\"'\n \n GIT_DIR=\"$SERVERDIR\" git config --bool gitcvs.enabled true || exit 1\n \n@@ -216,7 +216,7 @@ test_expect_success 'gitcvs.enabled = false' \\\n    else\n      true\n    fi &&\n-   cat cvs.log | grep -q \"GITCVS emulation disabled\" &&\n+   grep \"GITCVS emulation disabled\" cvs.log &&\n    test ! -d cvswork2'\n \n rm -fr cvswork2\n@@ -237,7 +237,7 @@ test_expect_success 'gitcvs.ext.enabled = false' \\\n    else\n      true\n    fi &&\n-   cat cvs.log | grep -q \"GITCVS emulation disabled\" &&\n+   grep \"GITCVS emulation disabled\" cvs.log &&\n    test ! -d cvswork2'\n \n rm -fr cvswork2\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71851","messageId":"20080312213434.GF26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 05/16] remove use of \"tail -n 1\" and \"tail -1\"","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:34:34Z","receivedAt":"2008-03-12T21:34:34Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The \"-n\" syntax is not supported by System V versions of\ntail (which prefer \"tail -1\"). Unfortunately \"tail -1\" is\nnot actually POSIX.  We had some of both forms in our\nscripts.\n\nSince neither form works everywhere, this patch replaces\nboth with the equivalent sed invocation:\n\n  sed -ne '$p'\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nActually, \"tail -1\" _does_ seem to be accepted everywhere, even though\nit isn't POSIX. I remember the GNU utils complaining about it (but maybe\njust with POSIXLY_CORRECT?) a while back, but that seems to have been\nreverted. But certainly this sed invocation should work everywhere.\n\n git-am.sh                       |    2 +-\n git-rebase--interactive.sh      |    2 +-\n t/t3404-rebase-interactive.sh   |    4 ++--\n t/t5302-pack-index.sh           |    4 ++--\n t/t6030-bisect-porcelain.sh     |    6 +++---\n t/t7600-merge.sh                |    2 +-\n t/t9400-git-cvsserver-server.sh |   20 ++++++++++----------\n 7 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/git-am.sh b/git-am.sh\nindex 1f6b5e0..ac5c388 100755\n--- a/git-am.sh\n+++ b/git-am.sh\n@@ -357,7 +357,7 @@ do\n \t\tLAST_SIGNED_OFF_BY=`\n \t\t    sed -ne '/^Signed-off-by: /p' \\\n \t\t    \"$dotest/msg-clean\" |\n-\t\t    tail -n 1\n+\t\t    sed -ne '$p'\n \t\t`\n \t\tADD_SIGNOFF=`\n \t\t    test \"$LAST_SIGNED_OFF_BY\" = \"$SIGNOFF\" || {\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 4c3280a..8aa7371 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -218,7 +218,7 @@ nth_string () {\n make_squash_message () {\n \tif test -f \"$SQUASH_MSG\"; then\n \t\tCOUNT=$(($(sed -n \"s/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p\" \\\n-\t\t\t< \"$SQUASH_MSG\" | tail -n 1)+1))\n+\t\t\t< \"$SQUASH_MSG\" | sed -ne '$p')+1))\n \t\techo \"# This is a combination of $COUNT commits.\"\n \t\tsed -e 1d -e '2,/^./{\n \t\t\t/^$/d\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex f098231..9c0acc5 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -122,8 +122,8 @@ test_expect_success 'reflog for the branch shows state before rebase' '\n \n test_expect_success 'exchange two commits' '\n \tFAKE_LINES=\"2 1\" git rebase -i HEAD~2 &&\n-\ttest H = $(git cat-file commit HEAD^ | tail -n 1) &&\n-\ttest G = $(git cat-file commit HEAD | tail -n 1)\n+\ttest H = $(git cat-file commit HEAD^ | sed -ne \\$p) &&\n+\ttest G = $(git cat-file commit HEAD | sed -ne \\$p)\n '\n \n cat > expect << EOF\ndiff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh\nindex 67b9a7b..b88b5bb 100755\n--- a/t/t5302-pack-index.sh\n+++ b/t/t5302-pack-index.sh\n@@ -103,7 +103,7 @@ test_expect_success \\\n test_expect_success \\\n     '[index v1] 2) create a stealth corruption in a delta base reference' \\\n     '# this test assumes a delta smaller than 16 bytes at the end of the pack\n-     git show-index <1.idx | sort -n | tail -n 1 | (\n+     git show-index <1.idx | sort -n | sed -ne \\$p | (\n        read delta_offs delta_sha1 &&\n        git cat-file blob \"$delta_sha1\" > blob_1 &&\n        chmod +w \".git/objects/pack/pack-${pack1}.pack\" &&\n@@ -141,7 +141,7 @@ test_expect_success \\\n test_expect_success \\\n     '[index v2] 2) create a stealth corruption in a delta base reference' \\\n     '# this test assumes a delta smaller than 16 bytes at the end of the pack\n-     git show-index <1.idx | sort -n | tail -n 1 | (\n+     git show-index <1.idx | sort -n | sed -ne \\$p | (\n        read delta_offs delta_sha1 delta_crc &&\n        git cat-file blob \"$delta_sha1\" > blob_3 &&\n        chmod +w \".git/objects/pack/pack-${pack1}.pack\" &&\ndiff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh\nindex 4908e87..f471c15 100755\n--- a/t/t6030-bisect-porcelain.sh\n+++ b/t/t6030-bisect-porcelain.sh\n@@ -219,7 +219,7 @@ test_expect_success 'bisect run & skip: cannot tell between 2' '\n \tadd_line_into_file \"6: Yet a line.\" hello &&\n \tHASH6=$(git rev-parse --verify HEAD) &&\n \techo \"#\"\\!\"/bin/sh\" > test_script.sh &&\n-\techo \"tail -1 hello | grep Ciao > /dev/null && exit 125\" >> test_script.sh &&\n+\techo \"sed -ne \\\\\\$p hello | grep Ciao > /dev/null && exit 125\" >> test_script.sh &&\n \techo \"grep line hello > /dev/null\" >> test_script.sh &&\n \techo \"test \\$? -ne 0\" >> test_script.sh &&\n \tchmod +x test_script.sh &&\n@@ -244,8 +244,8 @@ test_expect_success 'bisect run & skip: find first bad' '\n \tadd_line_into_file \"7: Should be the last line.\" hello &&\n \tHASH7=$(git rev-parse --verify HEAD) &&\n \techo \"#\"\\!\"/bin/sh\" > test_script.sh &&\n-\techo \"tail -1 hello | grep Ciao > /dev/null && exit 125\" >> test_script.sh &&\n-\techo \"tail -1 hello | grep day > /dev/null && exit 125\" >> test_script.sh &&\n+\techo \"sed -ne \\\\\\$p hello | grep Ciao > /dev/null && exit 125\" >> test_script.sh &&\n+\techo \"sed -ne \\\\\\$p hello | grep day > /dev/null && exit 125\" >> test_script.sh &&\n \techo \"grep Yet hello > /dev/null\" >> test_script.sh &&\n \techo \"test \\$? -ne 0\" >> test_script.sh &&\n \tchmod +x test_script.sh &&\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex 590505b..219411f 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -165,7 +165,7 @@ verify_mergeheads() {\n \tfi &&\n \twhile test $# -gt 0\n \tdo\n-\t\thead=$(head -n $i .git/MERGE_HEAD | tail -n 1)\n+\t\thead=$(head -n $i .git/MERGE_HEAD | sed -ne \\$p)\n \t\tif test \"$1\" != \"$head\"\n \t\tthen\n \t\t\techo \"[OOPS] MERGE_HEAD $i != $1\"\ndiff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh\nindex e82b365..b91b151 100755\n--- a/t/t9400-git-cvsserver-server.sh\n+++ b/t/t9400-git-cvsserver-server.sh\n@@ -54,7 +54,7 @@ test_expect_success 'setup' '\n test_expect_success 'basic checkout' \\\n   'GIT_CONFIG=\"$git_config\" cvs -Q co -d cvswork master &&\n    test \"$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))\" = \"empty/1.1/\"\n-   test \"$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | tail -n 1))\" = \"secondrootfile/1.1/\"'\n+   test \"$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \\$p))\" = \"secondrootfile/1.1/\"'\n \n #------------------------\n # PSERVER AUTHENTICATION\n@@ -94,7 +94,7 @@ EOF\n \n test_expect_success 'pserver authentication' \\\n   'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'pserver authentication failure (non-anonymous user)' \\\n   'if cat request-git | git-cvsserver pserver >log 2>&1\n@@ -103,11 +103,11 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \\\n    else\n        true\n    fi &&\n-   tail -n1 log | grep \"^I HATE YOU$\"'\n+   sed -ne \\$p log | grep \"^I HATE YOU$\"'\n \n test_expect_success 'pserver authentication (login)' \\\n   'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'pserver authentication failure (login/non-anonymous user)' \\\n   'if cat login-git | git-cvsserver pserver >log 2>&1\n@@ -116,7 +116,7 @@ test_expect_success 'pserver authentication failure (login/non-anonymous user)'\n    else\n        true\n    fi &&\n-   tail -n1 log | grep \"^I HATE YOU$\"'\n+   sed -ne \\$p log | grep \"^I HATE YOU$\"'\n \n \n # misuse pserver authentication for testing of req_Root\n@@ -154,7 +154,7 @@ test_expect_success 'req_Root failure (conflicting roots)' \\\n \n test_expect_success 'req_Root (strict paths)' \\\n   'cat request-anonymous | git-cvsserver --strict-paths pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (strict-paths)' '\n     ! cat request-anonymous |\n@@ -163,7 +163,7 @@ test_expect_success 'req_Root failure (strict-paths)' '\n \n test_expect_success 'req_Root (w/o strict-paths)' \\\n   'cat request-anonymous | git-cvsserver pserver $WORKDIR/ >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (w/o strict-paths)' '\n     ! cat request-anonymous |\n@@ -181,7 +181,7 @@ EOF\n \n test_expect_success 'req_Root (base-path)' \\\n   'cat request-base | git-cvsserver --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (base-path)' '\n     ! cat request-anonymous |\n@@ -192,14 +192,14 @@ GIT_DIR=\"$SERVERDIR\" git config --bool gitcvs.enabled false || exit 1\n \n test_expect_success 'req_Root (export-all)' \\\n   'cat request-anonymous | git-cvsserver --export-all pserver $WORKDIR >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n test_expect_success 'req_Root failure (export-all w/o whitelist)' \\\n   '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)'\n \n test_expect_success 'req_Root (everything together)' \\\n   'cat request-base | git-cvsserver --export-all --strict-paths --base-path $WORKDIR/ pserver $SERVERDIR >log 2>&1 &&\n-   tail -n1 log | grep \"^I LOVE YOU$\"'\n+   sed -ne \\$p log | grep \"^I LOVE YOU$\"'\n \n GIT_DIR=\"$SERVERDIR\" git config --bool gitcvs.enabled true || exit 1\n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71852","messageId":"20080312213636.GG26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 06/16] add test_cmp function for test scripts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:36:36Z","receivedAt":"2008-03-12T21:36:36Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Many scripts compare actual and expected output using\n\"diff -u\". This is nicer than \"cmp\" because the output shows\nhow the two differ. However, not all versions of diff\nunderstand -u, leading to unnecessary test failure.\n\nThis adds a test_cmp function to the test scripts and\nswitches all \"diff -u\" invocations to use it. The function\nuses the contents of \"$GIT_TEST_CMP\" to compare its\narguments; the default is \"diff -u\".\n\nOn systems with a less-capable diff, you can do:\n\n  GIT_TEST_CMP=cmp make test\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThe replacements were done mechanically with:\n\n  perl -pi -e 's/(?<!git.)diff -u/test_cmp/' t/*.sh\n\nPerhaps this should be a command-line option instead of an environment\nvariable? Maybe it should be auto-detected or set up in the Makefile?\n\n t/t0003-attributes.sh              |    2 +-\n t/t0022-crlf-rename.sh             |    2 +-\n t/t1005-read-tree-reset.sh         |    2 +-\n t/t2200-add-update.sh              |    2 +-\n t/t3001-ls-files-others-exclude.sh |    2 +-\n t/t3050-subprojects-fetch.sh       |    4 ++--\n t/t3060-ls-files-with-tree.sh      |    2 +-\n t/t3201-branch-contains.sh         |    6 +++---\n t/t3404-rebase-interactive.sh      |    4 ++--\n t/t3405-rebase-malformed.sh        |    4 ++--\n t/t3406-rebase-message.sh          |    2 +-\n t/t3701-add-interactive.sh         |    4 ++--\n t/t3902-quoted.sh                  |   16 ++++++++--------\n t/t3903-stash.sh                   |    2 +-\n t/t4023-diff-rename-typechange.sh  |    6 +++---\n t/t4024-diff-optimize-common.sh    |    2 +-\n t/t4025-hunk-header.sh             |    2 +-\n t/t4027-diff-submodule.sh          |    6 +++---\n t/t4105-apply-fuzz.sh              |    2 +-\n t/t4125-apply-ws-fuzz.sh           |    8 ++++----\n t/t4150-am-subdir.sh               |   10 +++++-----\n t/t4201-shortlog.sh                |    2 +-\n t/t5505-remote.sh                  |    6 +++---\n t/t5510-fetch.sh                   |    2 +-\n t/t5512-ls-remote.sh               |    8 ++++----\n t/t6004-rev-list-path-optim.sh     |    2 +-\n t/t6009-rev-list-parent.sh         |    2 +-\n t/t6027-merge-binary.sh            |    4 ++--\n t/t6029-merge-subtree.sh           |    2 +-\n t/t7010-setup.sh                   |   18 +++++++++---------\n t/t7201-co.sh                      |   18 +++++++++---------\n t/t7501-commit.sh                  |   14 +++++++-------\n t/t7502-commit.sh                  |   14 +++++++-------\n t/t7502-status.sh                  |    2 +-\n t/t7600-merge.sh                   |    2 +-\n t/t8003-blame.sh                   |    4 ++--\n t/t9001-send-email.sh              |    2 +-\n t/t9116-git-svn-log.sh             |   24 ++++++++++++------------\n t/t9200-git-cvsexportcommit.sh     |   14 +++++++-------\n t/test-lib.sh                      |   18 ++++++++++++++++++\n 40 files changed, 133 insertions(+), 115 deletions(-)\n\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 47f08a4..3faf135 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -11,7 +11,7 @@ attr_check () {\n \n \tgit check-attr test -- \"$path\" >actual &&\n \techo \"$path: test: $2\" >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n }\n \ndiff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh\nindex 430a1d1..7d1ce2d 100755\n--- a/t/t0022-crlf-rename.sh\n+++ b/t/t0022-crlf-rename.sh\n@@ -26,7 +26,7 @@ test_expect_success 'diff -M' '\n \tgit diff-tree -M -r --name-status HEAD^ HEAD |\n \tsed -e \"s/R[0-9]*/RNUM/\" >actual &&\n \techo \"RNUM\tsample\telpmas\" >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh\nindex 8c45564..b0d31f5 100755\n--- a/t/t1005-read-tree-reset.sh\n+++ b/t/t1005-read-tree-reset.sh\n@@ -24,7 +24,7 @@ test_expect_success 'setup' '\n test_expect_success 'reset should work' '\n   git read-tree -u --reset HEAD^ &&\n   git ls-files >actual &&\n-  diff -u expect actual\n+  test_cmp expect actual\n '\n \n test_done\ndiff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh\nindex 24f892f..b664341 100755\n--- a/t/t2200-add-update.sh\n+++ b/t/t2200-add-update.sh\n@@ -62,7 +62,7 @@ test_expect_success 'cache tree has not been corrupted' '\n \tsed -e \"s/ 0\t/\t/\" >expect &&\n \tgit ls-tree -r $(git write-tree) |\n \tsed -e \"s/ blob / /\" >current &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \ndiff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh\nindex b4297ba..55f057c 100755\n--- a/t/t3001-ls-files-others-exclude.sh\n+++ b/t/t3001-ls-files-others-exclude.sh\n@@ -97,7 +97,7 @@ cat > expect << EOF\n EOF\n \n test_expect_success 'git-status honours core.excludesfile' \\\n-\t'diff -u expect output'\n+\t'test_cmp expect output'\n \n test_expect_success 'trailing slash in exclude allows directory match(1)' '\n \ndiff --git a/t/t3050-subprojects-fetch.sh b/t/t3050-subprojects-fetch.sh\nindex 34f26a8..2b21b10 100755\n--- a/t/t3050-subprojects-fetch.sh\n+++ b/t/t3050-subprojects-fetch.sh\n@@ -26,7 +26,7 @@ test_expect_success clone '\n \t\tcd cloned &&\n \t\t(git rev-parse HEAD; git ls-files -s) >../actual\n \t) &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n '\n \n test_expect_success advance '\n@@ -46,7 +46,7 @@ test_expect_success fetch '\n \t\tgit pull &&\n \t\t(git rev-parse HEAD; git ls-files -s) >../actual\n \t) &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n '\n \n test_done\ndiff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh\nindex 68eb266..3ce501b 100755\n--- a/t/t3060-ls-files-with-tree.sh\n+++ b/t/t3060-ls-files-with-tree.sh\n@@ -66,6 +66,6 @@ test_expect_success 'git -ls-files --with-tree should succeed from subdir' '\n cd ..\n test_expect_success \\\n     'git -ls-files --with-tree should add entries from named tree.' \\\n-    'diff -u expected output'\n+    'test_cmp expected output'\n \n test_done\ndiff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh\nindex 9ef593f..b4cf628 100755\n--- a/t/t3201-branch-contains.sh\n+++ b/t/t3201-branch-contains.sh\n@@ -31,7 +31,7 @@ test_expect_success 'branch --contains=master' '\n \t{\n \t\techo \"  master\" && echo \"* side\"\n \t} >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -41,7 +41,7 @@ test_expect_success 'branch --contains master' '\n \t{\n \t\techo \"  master\" && echo \"* side\"\n \t} >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -51,7 +51,7 @@ test_expect_success 'branch --contains=side' '\n \t{\n \t\techo \"* side\"\n \t} >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 9c0acc5..9cf873f 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -146,8 +146,8 @@ EOF\n test_expect_success 'stop on conflicting pick' '\n \tgit tag new-branch1 &&\n \t! git rebase -i master &&\n-\tdiff -u expect .git/.dotest-merge/patch &&\n-\tdiff -u expect2 file1 &&\n+\ttest_cmp expect .git/.dotest-merge/patch &&\n+\ttest_cmp expect2 file1 &&\n \ttest 4 = $(grep -v \"^#\" < .git/.dotest-merge/done | wc -l) &&\n \ttest 0 = $(grep -c \"^[^#]\" < .git/.dotest-merge/git-rebase-todo)\n '\ndiff --git a/t/t3405-rebase-malformed.sh b/t/t3405-rebase-malformed.sh\nindex e4e2e64..e5ad67c 100755\n--- a/t/t3405-rebase-malformed.sh\n+++ b/t/t3405-rebase-malformed.sh\n@@ -41,8 +41,8 @@ test_expect_success rebase '\n \tgit rebase master side &&\n \tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >F1 &&\n \n-\tdiff -u F0 F1 &&\n-\tdiff -u F F0\n+\ttest_cmp F0 F1 &&\n+\ttest_cmp F F0\n '\n \n test_done\ndiff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh\nindex 332b2b2..5391080 100755\n--- a/t/t3406-rebase-message.sh\n+++ b/t/t3406-rebase-message.sh\n@@ -37,7 +37,7 @@ test_expect_success 'rebase -m' '\n \tgit rebase -m master >report &&\n \tsed -n -e \"/^Already applied: /p\" \\\n \t\t-e \"/^Committed: /p\" report >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh\nindex c8dc1ac..77c90f6 100755\n--- a/t/t3701-add-interactive.sh\n+++ b/t/t3701-add-interactive.sh\n@@ -24,7 +24,7 @@ EOF\n test_expect_success 'diff works (initial)' '\n \t(echo d; echo 1) | git add -i >output &&\n \tsed -ne \"/new file/,/content/p\" <output >diff &&\n-\tdiff -u expected diff\n+\ttest_cmp expected diff\n '\n test_expect_success 'revert works (initial)' '\n \tgit add file &&\n@@ -57,7 +57,7 @@ EOF\n test_expect_success 'diff works (commit)' '\n \t(echo d; echo 1) | git add -i >output &&\n \tsed -ne \"/^index/,/content/p\" <output >diff &&\n-\tdiff -u expected diff\n+\ttest_cmp expected diff\n '\n test_expect_success 'revert works (commit)' '\n \tgit add file &&\ndiff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh\nindex 73da45f..fe4fb51 100755\n--- a/t/t3902-quoted.sh\n+++ b/t/t3902-quoted.sh\n@@ -78,28 +78,28 @@ EOF\n \n test_expect_success 'check fully quoted output from ls-files' '\n \n-\tgit ls-files >current && diff -u expect.quoted current\n+\tgit ls-files >current && test_cmp expect.quoted current\n \n '\n \n test_expect_success 'check fully quoted output from diff-files' '\n \n \tgit diff --name-only >current &&\n-\tdiff -u expect.quoted current\n+\ttest_cmp expect.quoted current\n \n '\n \n test_expect_success 'check fully quoted output from diff-index' '\n \n \tgit diff --name-only HEAD >current &&\n-\tdiff -u expect.quoted current\n+\ttest_cmp expect.quoted current\n \n '\n \n test_expect_success 'check fully quoted output from diff-tree' '\n \n \tgit diff --name-only HEAD^ HEAD >current &&\n-\tdiff -u expect.quoted current\n+\ttest_cmp expect.quoted current\n \n '\n \n@@ -111,28 +111,28 @@ test_expect_success 'setting core.quotepath' '\n \n test_expect_success 'check fully quoted output from ls-files' '\n \n-\tgit ls-files >current && diff -u expect.raw current\n+\tgit ls-files >current && test_cmp expect.raw current\n \n '\n \n test_expect_success 'check fully quoted output from diff-files' '\n \n \tgit diff --name-only >current &&\n-\tdiff -u expect.raw current\n+\ttest_cmp expect.raw current\n \n '\n \n test_expect_success 'check fully quoted output from diff-index' '\n \n \tgit diff --name-only HEAD >current &&\n-\tdiff -u expect.raw current\n+\ttest_cmp expect.raw current\n \n '\n \n test_expect_success 'check fully quoted output from diff-tree' '\n \n \tgit diff --name-only HEAD^ HEAD >current &&\n-\tdiff -u expect.raw current\n+\ttest_cmp expect.raw current\n \n '\n \ndiff --git a/t/t3903-stash.sh b/t/t3903-stash.sh\nindex aa282e1..2d3ee3b 100755\n--- a/t/t3903-stash.sh\n+++ b/t/t3903-stash.sh\n@@ -34,7 +34,7 @@ EOF\n test_expect_success 'parents of stash' '\n \ttest $(git rev-parse stash^) = $(git rev-parse HEAD) &&\n \tgit diff stash^2..stash > output &&\n-\tdiff -u output expect\n+\ttest_cmp output expect\n '\n \n test_expect_success 'apply needs clean working directory' '\ndiff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh\nindex 255604e..4dbfc6e 100755\n--- a/t/t4023-diff-rename-typechange.sh\n+++ b/t/t4023-diff-rename-typechange.sh\n@@ -57,7 +57,7 @@ test_expect_success 'cross renames to be detected for regular files' '\n \t\techo \"R100\tfoo\tbar\"\n \t\techo \"R100\tbar\tfoo\"\n \t} | sort >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -68,7 +68,7 @@ test_expect_success 'cross renames to be detected for typechange' '\n \t\techo \"R100\tfoo\tbar\"\n \t\techo \"R100\tbar\tfoo\"\n \t} | sort >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -79,7 +79,7 @@ test_expect_success 'moves and renames' '\n \t\techo \"R100\tfoo\tbar\"\n \t\techo \"T100\tfoo\"\n \t} | sort >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t4024-diff-optimize-common.sh b/t/t4024-diff-optimize-common.sh\nindex 3c66102..c4d733f 100755\n--- a/t/t4024-diff-optimize-common.sh\n+++ b/t/t4024-diff-optimize-common.sh\n@@ -150,7 +150,7 @@ test_expect_success 'diff -U0' '\n \tdo\n \t\tgit diff -U0 file-?$n\n \tdone | zc >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t4025-hunk-header.sh b/t/t4025-hunk-header.sh\nindex 9ba06b7..7a3dbc1 100755\n--- a/t/t4025-hunk-header.sh\n+++ b/t/t4025-hunk-header.sh\n@@ -37,7 +37,7 @@ test_expect_success 'hunk header truncation with an overly long line' '\n \t\techo \" A $N$N$N$N$N$N$N$N$N2\"\n \t\techo \" L  $N$N$N$N$N$N$N$N$N1\"\n \t) >expected &&\n-\tdiff -u actual expected\n+\ttest_cmp actual expected\n \n '\n \ndiff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh\nindex 3d2d081..1fd3fb7 100755\n--- a/t/t4027-diff-submodule.sh\n+++ b/t/t4027-diff-submodule.sh\n@@ -37,17 +37,17 @@ test_expect_success setup '\n \n test_expect_success 'git diff --raw HEAD' '\n \tgit diff --raw --abbrev=40 HEAD >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git diff-index --raw HEAD' '\n \tgit diff-index --raw HEAD >actual.index &&\n-\tdiff -u expect actual.index\n+\ttest_cmp expect actual.index\n '\n \n test_expect_success 'git diff-files --raw' '\n \tgit diff-files --raw >actual.files &&\n-\tdiff -u expect actual.files\n+\ttest_cmp expect actual.files\n '\n \n test_done\ndiff --git a/t/t4105-apply-fuzz.sh b/t/t4105-apply-fuzz.sh\nindex 0e8d25f..3266e39 100755\n--- a/t/t4105-apply-fuzz.sh\n+++ b/t/t4105-apply-fuzz.sh\n@@ -9,7 +9,7 @@ dotest () {\n \ttest_expect_success \"$name\" \"\n \t\tgit checkout-index -f -q -u file &&\n \t\tgit apply $* &&\n-\t\tdiff -u expect file\n+\t\ttest_cmp expect file\n \t\"\n }\n \ndiff --git a/t/t4125-apply-ws-fuzz.sh b/t/t4125-apply-ws-fuzz.sh\nindex d6f15be..3b471b6 100755\n--- a/t/t4125-apply-ws-fuzz.sh\n+++ b/t/t4125-apply-ws-fuzz.sh\n@@ -56,7 +56,7 @@ test_expect_success nofix '\n \tgit apply --whitespace=nowarn patch-1 &&\n \n \t# The result should obviously match.\n-\tdiff -u file-1 file\n+\ttest_cmp file-1 file\n '\n \n test_expect_success 'withfix (forward)' '\n@@ -70,7 +70,7 @@ test_expect_success 'withfix (forward)' '\n \tgit apply --whitespace=fix patch-0 &&\n \tgit apply --whitespace=fix patch-1 &&\n \n-\tdiff -u file-fixed file\n+\ttest_cmp file-fixed file\n '\n \n test_expect_success 'withfix (backward)' '\n@@ -91,12 +91,12 @@ test_expect_success 'withfix (backward)' '\n \n \tsed -e /h/d file-fixed >fixed-head &&\n \tsed -e /h/d file >file-head &&\n-\tdiff -u fixed-head file-head &&\n+\ttest_cmp fixed-head file-head &&\n \n \tsed -n -e /h/p file-fixed >fixed-tail &&\n \tsed -n -e /h/p file >file-tail &&\n \n-\t! diff -u fixed-tail file-tail\n+\t! test_cmp fixed-tail file-tail\n \n '\n \ndiff --git a/t/t4150-am-subdir.sh b/t/t4150-am-subdir.sh\nindex 929d2cb..52069b4 100755\n--- a/t/t4150-am-subdir.sh\n+++ b/t/t4150-am-subdir.sh\n@@ -22,14 +22,14 @@ test_expect_success 'am regularly from stdin' '\n \tgit checkout initial &&\n \tgit am <patchfile &&\n \tgit diff master >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'am regularly from file' '\n \tgit checkout initial &&\n \tgit am patchfile &&\n \tgit diff master >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'am regularly from stdin in subdirectory' '\n@@ -41,7 +41,7 @@ test_expect_success 'am regularly from stdin in subdirectory' '\n \t\tgit am <../patchfile\n \t) &&\n \tgit diff master>actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'am regularly from file in subdirectory' '\n@@ -53,7 +53,7 @@ test_expect_success 'am regularly from file in subdirectory' '\n \t\tgit am ../patchfile\n \t) &&\n \tgit diff master >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'am regularly from file in subdirectory with full path' '\n@@ -66,7 +66,7 @@ test_expect_success 'am regularly from file in subdirectory with full path' '\n \t\tgit am \"$P/patchfile\"\n \t) &&\n \tgit diff master >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n '\n \n test_done\ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 6d12efb..91ea696 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -45,6 +45,6 @@ A U Thor (5):\n \n EOF\n \n-test_expect_success 'shortlog wrapping' 'diff -u expect out'\n+test_expect_success 'shortlog wrapping' 'test_cmp expect out'\n \n test_done\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 2822a65..ecfc999 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -24,7 +24,7 @@ setup_repository () {\n tokens_match () {\n \techo \"$1\" | tr ' ' '\\012' | sort | sed -e '/^$/d' >expect &&\n \techo \"$2\" | tr ' ' '\\012' | sort | sed -e '/^$/d' >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n }\n \n check_remote_track () {\n@@ -73,7 +73,7 @@ test_expect_success 'add another remote' '\n \tsed -e \"/^refs\\/remotes\\/origin\\//d\" \\\n \t    -e \"/^refs\\/remotes\\/second\\//d\" >actual &&\n \t>expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n )\n '\n \n@@ -93,7 +93,7 @@ test_expect_success 'remove remote' '\n \tgit for-each-ref \"--format=%(refname)\" refs/remotes |\n \tsed -e \"/^refs\\/remotes\\/origin\\//d\" >actual &&\n \t>expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n )\n '\n \ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex 9b948c1..6946557 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -249,7 +249,7 @@ test_expect_success 'bundle should record HEAD correctly' '\n \tdo\n \t\techo \"$(git rev-parse --verify $h) $h\"\n \tdone >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh\nindex 6ec5f7c..c0dc949 100755\n--- a/t/t5512-ls-remote.sh\n+++ b/t/t5512-ls-remote.sh\n@@ -24,28 +24,28 @@ test_expect_success setup '\n test_expect_success 'ls-remote --tags .git' '\n \n \tgit ls-remote --tags .git >actual &&\n-\tdiff -u expected.tag actual\n+\ttest_cmp expected.tag actual\n \n '\n \n test_expect_success 'ls-remote .git' '\n \n \tgit ls-remote .git >actual &&\n-\tdiff -u expected.all actual\n+\ttest_cmp expected.all actual\n \n '\n \n test_expect_success 'ls-remote --tags self' '\n \n \tgit ls-remote --tags self >actual &&\n-\tdiff -u expected.tag actual\n+\ttest_cmp expected.tag actual\n \n '\n \n test_expect_success 'ls-remote self' '\n \n \tgit ls-remote self >actual &&\n-\tdiff -u expected.all actual\n+\ttest_cmp expected.all actual\n \n '\n \ndiff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh\nindex 80d7198..5dabf1c 100755\n--- a/t/t6004-rev-list-path-optim.sh\n+++ b/t/t6004-rev-list-path-optim.sh\n@@ -45,7 +45,7 @@ test_expect_success 'further setup' '\n test_expect_success 'path optimization 2' '\n \t( echo \"$side\"; echo \"$initial\" ) >expected &&\n \tgit rev-list HEAD -- a >actual &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n '\n \n test_done\ndiff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh\nindex be3d238..f248a32 100755\n--- a/t/t6009-rev-list-parent.sh\n+++ b/t/t6009-rev-list-parent.sh\n@@ -31,7 +31,7 @@ test_expect_failure 'one is ancestor of others and should not be shown' '\n \n \tgit rev-list one --not four >result &&\n \t>expect &&\n-\tdiff -u expect result\n+\ttest_cmp expect result\n \n '\n \ndiff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh\nindex a7358f7..92ca1f0 100755\n--- a/t/t6027-merge-binary.sh\n+++ b/t/t6027-merge-binary.sh\n@@ -45,7 +45,7 @@ test_expect_success resolve '\n \t\tfalse\n \telse\n \t\tgit ls-files -s >current\n-\t\tdiff -u current expect\n+\t\ttest_cmp current expect\n \tfi\n '\n \n@@ -60,7 +60,7 @@ test_expect_success recursive '\n \t\tfalse\n \telse\n \t\tgit ls-files -s >current\n-\t\tdiff -u current expect\n+\t\ttest_cmp current expect\n \tfi\n '\n \ndiff --git a/t/t6029-merge-subtree.sh b/t/t6029-merge-subtree.sh\nindex 35d66e8..43f5459 100755\n--- a/t/t6029-merge-subtree.sh\n+++ b/t/t6029-merge-subtree.sh\n@@ -25,7 +25,7 @@ test_expect_success 'subtree available and works like recursive' '\n \n \tgit merge -s subtree side &&\n \tfor i in mundo $s world; do echo $i; done >expect &&\n-\tdiff -u expect hello\n+\ttest_cmp expect hello\n \n '\n \ndiff --git a/t/t7010-setup.sh b/t/t7010-setup.sh\nindex bc8ab6a..02cf7c5 100755\n--- a/t/t7010-setup.sh\n+++ b/t/t7010-setup.sh\n@@ -18,7 +18,7 @@ test_expect_success 'git add (absolute)' '\n \tgit add \"$D/a/b/c/d\" &&\n \tgit ls-files >current &&\n \techo a/b/c/d >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -32,7 +32,7 @@ test_expect_success 'git add (funny relative)' '\n \t) &&\n \tgit ls-files >current &&\n \techo a/e/f >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -43,7 +43,7 @@ test_expect_success 'git rm (absolute)' '\n \tgit rm -f --cached \"$D/a/b/c/d\" &&\n \tgit ls-files >current &&\n \techo a/e/f >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -57,7 +57,7 @@ test_expect_success 'git rm (funny relative)' '\n \t) &&\n \tgit ls-files >current &&\n \techo a/b/c/d >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -67,7 +67,7 @@ test_expect_success 'git ls-files (absolute)' '\n \tgit add a &&\n \tgit ls-files \"$D/a/e/../b\" >current &&\n \techo a/b/c/d >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -80,7 +80,7 @@ test_expect_success 'git ls-files (relative #1)' '\n \t\tgit ls-files \"../b/c\"\n \t)  >current &&\n \techo c/d >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -93,7 +93,7 @@ test_expect_success 'git ls-files (relative #2)' '\n \t\tgit ls-files --full-name \"../e/f\"\n \t)  >current &&\n \techo a/e/f >expect &&\n-\tdiff -u expect current\n+\ttest_cmp expect current\n \n '\n \n@@ -126,13 +126,13 @@ test_expect_success 'log using absolute path names' '\n \n \tgit log a/b/c/d >f1.txt &&\n \tgit log \"$(pwd)/a/b/c/d\" >f2.txt &&\n-\tdiff -u f1.txt f2.txt\n+\ttest_cmp f1.txt f2.txt\n '\n \n test_expect_success 'blame using absolute path names' '\n \tgit blame a/b/c/d >f1.txt &&\n \tgit blame \"$(pwd)/a/b/c/d\" >f2.txt &&\n-\tdiff -u f1.txt f2.txt\n+\ttest_cmp f1.txt f2.txt\n '\n \n test_expect_success 'setup deeper work tree' '\ndiff --git a/t/t7201-co.sh b/t/t7201-co.sh\nindex 63915cd..3111baa 100755\n--- a/t/t7201-co.sh\n+++ b/t/t7201-co.sh\n@@ -83,13 +83,13 @@ test_expect_success \"checkout with unrelated dirty tree without -m\" '\n \tfill 0 1 2 3 4 5 6 7 8 >same &&\n \tcp same kept\n \tgit checkout side >messages &&\n-\tdiff -u same kept\n+\ttest_cmp same kept\n \t(cat > messages.expect <<EOF\n M\tsame\n EOF\n ) &&\n \ttouch messages.expect &&\n-\tdiff -u messages.expect messages\n+\ttest_cmp messages.expect messages\n '\n \n test_expect_success \"checkout -m with dirty tree\" '\n@@ -106,19 +106,19 @@ test_expect_success \"checkout -m with dirty tree\" '\n M\tone\n EOF\n ) &&\n-\tdiff -u expect.messages messages &&\n+\ttest_cmp expect.messages messages &&\n \n \tfill \"M\tone\" \"A\tthree\" \"D\ttwo\" >expect.master &&\n \tgit diff --name-status master >current.master &&\n-\tdiff -u expect.master current.master &&\n+\ttest_cmp expect.master current.master &&\n \n \tfill \"M\tone\" >expect.side &&\n \tgit diff --name-status side >current.side &&\n-\tdiff -u expect.side current.side &&\n+\ttest_cmp expect.side current.side &&\n \n \t: >expect.index &&\n \tgit diff --cached >current.index &&\n-\tdiff -u expect.index current.index\n+\ttest_cmp expect.index current.index\n '\n \n test_expect_success \"checkout -m with dirty tree, renamed\" '\n@@ -136,7 +136,7 @@ test_expect_success \"checkout -m with dirty tree, renamed\" '\n \n \tgit checkout -m renamer &&\n \tfill 1 3 4 5 7 8 >expect &&\n-\tdiff -u expect uno &&\n+\ttest_cmp expect uno &&\n \t! test -f one &&\n \tgit diff --cached >current &&\n \t! test -s current\n@@ -161,7 +161,7 @@ test_expect_success 'checkout -m with merge conflict' '\n \tgit diff master:one :3:uno |\n \tsed -e \"1,/^@@/d\" -e \"/^ /d\" -e \"s/^-/d/\" -e \"s/^+/a/\" >current &&\n \tfill d2 aT d7 aS >expect &&\n-\tdiff -u current expect &&\n+\ttest_cmp current expect &&\n \tgit diff --cached two >current &&\n \t! test -s current\n '\n@@ -178,7 +178,7 @@ If you want to create a new branch from this checkout, you may do so\n HEAD is now at 7329388... Initial A one, A two\n EOF\n ) &&\n-\tdiff -u messages.expect messages &&\n+\ttest_cmp messages.expect messages &&\n \tH=$(git rev-parse --verify HEAD) &&\n \tM=$(git show-ref -s --verify refs/heads/master) &&\n \ttest \"z$H\" = \"z$M\" &&\ndiff --git a/t/t7501-commit.sh b/t/t7501-commit.sh\nindex 361886c..c0288f3 100755\n--- a/t/t7501-commit.sh\n+++ b/t/t7501-commit.sh\n@@ -203,7 +203,7 @@ test_expect_success 'sign off (1)' '\n \t\tgit var GIT_COMMITTER_IDENT |\n \t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n \t) >expected &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \n@@ -223,7 +223,7 @@ $existing\" &&\n \t\tgit var GIT_COMMITTER_IDENT |\n \t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n \t) >expected &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \n@@ -240,7 +240,7 @@ test_expect_success 'multiple -m' '\n \t\techo\n \t\techo three\n \t) >expected &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \n@@ -301,12 +301,12 @@ test_expect_success 'same tree (merge and amend merge)' '\n \tgit merge -s ours side -m \"empty ok\" &&\n \tgit diff HEAD^ HEAD >actual &&\n \t: >expected &&\n-\tdiff -u expected actual &&\n+\ttest_cmp expected actual &&\n \n \tgit commit --amend -m \"empty really ok\" &&\n \tgit diff HEAD^ HEAD >actual &&\n \t: >expected &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \n@@ -323,7 +323,7 @@ test_expect_success 'amend using the message from another commit' '\n \tgit commit --allow-empty --amend -C \"$old\" &&\n \tgit show --pretty=\"format:%ad %s\" \"$old\" >expected &&\n \tgit show --pretty=\"format:%ad %s\" HEAD >actual &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \n@@ -341,7 +341,7 @@ test_expect_success 'amend using the message from a commit named with tag' '\n \tgit commit --allow-empty --amend -C tagged-old &&\n \tgit show --pretty=\"format:%ad %s\" \"$old\" >expected &&\n \tgit show --pretty=\"format:%ad %s\" HEAD >actual &&\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n \n '\n \ndiff --git a/t/t7502-commit.sh b/t/t7502-commit.sh\nindex b780fdd..284c941 100755\n--- a/t/t7502-commit.sh\n+++ b/t/t7502-commit.sh\n@@ -85,7 +85,7 @@ test_expect_success 'verbose' '\n \tgit add negative &&\n \tgit status -v | sed -ne \"/^diff --git /p\" >actual &&\n \techo \"diff --git a/negative b/negative\" >expect &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -95,7 +95,7 @@ test_expect_success 'cleanup commit messages (verbatim,-t)' '\n \t{ echo;echo \"# text\";echo; } >expect &&\n \tgit commit --cleanup=verbatim -t expect -a &&\n \tgit cat-file -p HEAD |sed -e \"1,/^\\$/d\" |head -n 3 >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -104,7 +104,7 @@ test_expect_success 'cleanup commit messages (verbatim,-F)' '\n \techo >>negative &&\n \tgit commit --cleanup=verbatim -F expect -a &&\n \tgit cat-file -p HEAD |sed -e \"1,/^\\$/d\">actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -113,7 +113,7 @@ test_expect_success 'cleanup commit messages (verbatim,-m)' '\n \techo >>negative &&\n \tgit commit --cleanup=verbatim -m \"$(cat expect)\" -a &&\n \tgit cat-file -p HEAD |sed -e \"1,/^\\$/d\">actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -124,7 +124,7 @@ test_expect_success 'cleanup commit messages (whitespace,-F)' '\n \techo \"# text\" >expect &&\n \tgit commit --cleanup=whitespace -F text -a &&\n \tgit cat-file -p HEAD |sed -e \"1,/^\\$/d\">actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -135,7 +135,7 @@ test_expect_success 'cleanup commit messages (strip,-F)' '\n \techo sample >expect &&\n \tgit commit --cleanup=strip -F text -a &&\n \tgit cat-file -p HEAD |sed -e \"1,/^\\$/d\">actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \n@@ -150,7 +150,7 @@ test_expect_success 'cleanup commit messages (strip,-F,-e)' '\n \t{ echo;echo sample;echo; } >text &&\n \tgit commit -e -F text -a &&\n \thead -n 4 .git/COMMIT_EDITMSG >actual &&\n-\tdiff -u expect actual\n+\ttest_cmp expect actual\n \n '\n \ndiff --git a/t/t7502-status.sh b/t/t7502-status.sh\nindex 70b802b..cd08516 100755\n--- a/t/t7502-status.sh\n+++ b/t/t7502-status.sh\n@@ -146,7 +146,7 @@ cat <<EOF >expect\n EOF\n test_expect_success 'status of partial commit excluding new file in index' '\n \tgit status dir1/modified >output &&\n-\tdiff -u expect output\n+\ttest_cmp expect output\n '\n \n test_done\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex 219411f..56869ac 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -108,7 +108,7 @@ create_merge_msgs() {\n }\n \n verify_diff() {\n-\tif ! diff -u \"$1\" \"$2\"\n+\tif ! test_cmp \"$1\" \"$2\"\n \tthen\n \t\techo \"$3\"\n \t\tfalse\ndiff --git a/t/t8003-blame.sh b/t/t8003-blame.sh\nindex db51b3a..966bb0a 100755\n--- a/t/t8003-blame.sh\n+++ b/t/t8003-blame.sh\n@@ -112,7 +112,7 @@ test_expect_success 'blame wholesale copy' '\n \t\techo mouse-Second\n \t\techo mouse-Third\n \t} >expected &&\n-\tdiff -u expected current\n+\ttest_cmp expected current\n \n '\n \n@@ -125,7 +125,7 @@ test_expect_success 'blame wholesale copy and more' '\n \t\techo cow-Fifth\n \t\techo mouse-Third\n \t} >expected &&\n-\tdiff -u expected current\n+\ttest_cmp expected current\n \n '\n \ndiff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh\nindex cbbfa9c..c0973b4 100755\n--- a/t/t9001-send-email.sh\n+++ b/t/t9001-send-email.sh\n@@ -81,7 +81,7 @@ test_expect_success 'Show all headers' '\n \t\t-e \"s/^\\(Message-Id:\\).*/\\1 MESSAGE-ID-STRING/\" \\\n \t\t-e \"s/^\\(X-Mailer:\\).*/\\1 X-MAILER-STRING/\" \\\n \t\t>actual-show-all-headers &&\n-\tdiff -u expected-show-all-headers actual-show-all-headers\n+\ttest_cmp expected-show-all-headers actual-show-all-headers\n '\n \n z8=zzzzzzzz\ndiff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh\nindex 902ed41..e1e8bdf 100755\n--- a/t/t9116-git-svn-log.sh\n+++ b/t/t9116-git-svn-log.sh\n@@ -55,74 +55,74 @@ printf 'r1 \\nr2 \\nr4 \\n' > expected-range-r1-r2-r4\n \n test_expect_success 'test ascending revision range' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r1-r2-r4 -\n+\tgit svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2-r4 -\n \t\"\n \n printf 'r4 \\nr2 \\nr1 \\n' > expected-range-r4-r2-r1\n \n test_expect_success 'test descending revision range' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4-r2-r1 -\n+\tgit svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4-r2-r1 -\n \t\"\n \n printf 'r1 \\nr2 \\n' > expected-range-r1-r2\n \n test_expect_success 'test ascending revision range with unreachable revision' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 1:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r1-r2 -\n+\tgit svn log -r 1:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r1-r2 -\n \t\"\n \n printf 'r2 \\nr1 \\n' > expected-range-r2-r1\n \n test_expect_success 'test descending revision range with unreachable revision' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 3:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2-r1 -\n+\tgit svn log -r 3:1 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2-r1 -\n \t\"\n \n printf 'r2 \\n' > expected-range-r2\n \n test_expect_success 'test ascending revision range with unreachable upper boundary revision and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 2:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2 -\n+\tgit svn log -r 2:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 -\n \t\"\n \n test_expect_success 'test descending revision range with unreachable upper boundary revision and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 3:2 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2 -\n+\tgit svn log -r 3:2 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r2 -\n \t\"\n \n printf 'r4 \\n' > expected-range-r4\n \n test_expect_success 'test ascending revision range with unreachable lower boundary revision and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 3:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -\n+\tgit svn log -r 3:4 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -\n \t\"\n \n test_expect_success 'test descending revision range with unreachable lower boundary revision and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 4:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -\n+\tgit svn log -r 4:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -\n \t\"\n \n printf -- '------------------------------------------------------------------------\\n' > expected-separator\n \n test_expect_success 'test ascending revision range with unreachable boundary revisions and no commits' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 5:6 | diff -u expected-separator -\n+\tgit svn log -r 5:6 | test_cmp expected-separator -\n \t\"\n \n test_expect_success 'test descending revision range with unreachable boundary revisions and no commits' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 6:5 | diff -u expected-separator -\n+\tgit svn log -r 6:5 | test_cmp expected-separator -\n \t\"\n \n test_expect_success 'test ascending revision range with unreachable boundary revisions and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 3:5 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -\n+\tgit svn log -r 3:5 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -\n \t\"\n \n test_expect_success 'test descending revision range with unreachable boundary revisions and 1 commit' \"\n \tgit reset --hard trunk &&\n-\tgit svn log -r 5:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -\n+\tgit svn log -r 5:3 | grep '^r[0-9]' | cut -d'|' -f1 | test_cmp expected-range-r4 -\n \t\"\n \n test_done\ndiff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh\nindex 58c59ed..42b144b 100755\n--- a/t/t9200-git-cvsexportcommit.sh\n+++ b/t/t9200-git-cvsexportcommit.sh\n@@ -37,7 +37,7 @@ check_entries () {\n \telse\n \t\tprintf '%s\\n' \"$2\" | tr '|' '\\012' >expected\n \tfi\n-\tdiff -u expected actual\n+\ttest_cmp expected actual\n }\n \n test_expect_success \\\n@@ -257,8 +257,8 @@ test_expect_success '-w option should work with relative GIT_DIR' '\n       (cd \"$GIT_DIR\" &&\n       GIT_DIR=. git cvsexportcommit -w \"$CVSWORK\" -c $id &&\n       check_entries \"$CVSWORK/W\" \"file1.txt/1.1/|file2.txt/1.1/\" &&\n-      diff -u \"$CVSWORK/W/file1.txt\" ../W/file1.txt &&\n-      diff -u \"$CVSWORK/W/file2.txt\" ../W/file2.txt\n+      test_cmp \"$CVSWORK/W/file1.txt\" ../W/file1.txt &&\n+      test_cmp \"$CVSWORK/W/file2.txt\" ../W/file2.txt\n       )\n '\n \n@@ -279,9 +279,9 @@ test_expect_success 'check files before directories' '\n \tgit cvsexportcommit -w \"$CVSWORK\" -c $id &&\n \tcheck_entries \"$CVSWORK/E\" \"DS/1.1/|newfile5.txt/1.1/\" &&\n \tcheck_entries \"$CVSWORK\" \"DS/1.1/|release-notes/1.2/\" &&\n-\tdiff -u \"$CVSWORK/DS\" DS &&\n-\tdiff -u \"$CVSWORK/E/DS\" E/DS &&\n-\tdiff -u \"$CVSWORK/release-notes\" release-notes\n+\ttest_cmp \"$CVSWORK/DS\" DS &&\n+\ttest_cmp \"$CVSWORK/E/DS\" E/DS &&\n+\ttest_cmp \"$CVSWORK/release-notes\" release-notes\n \n '\n \n@@ -293,7 +293,7 @@ test_expect_success 'commit a file with leading spaces in the name' '\n \tid=$(git rev-parse HEAD) &&\n \tgit cvsexportcommit -w \"$CVSWORK\" -c $id &&\n \tcheck_entries \"$CVSWORK\" \" space/1.1/|DS/1.1/|release-notes/1.2/\" &&\n-\tdiff -u \"$CVSWORK/ space\" \" space\"\n+\ttest_cmp \"$CVSWORK/ space\" \" space\"\n \n '\n \ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 6aea0ea..268b26c 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -42,6 +42,7 @@ export GIT_MERGE_VERBOSITY\n export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME\n export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME\n export EDITOR VISUAL\n+GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}\n \n # Protect ourselves from common misconfiguration to export\n # CDPATH into the environment\n@@ -302,6 +303,23 @@ test_must_fail () {\n \ttest $? -gt 0 -a $? -le 128\n }\n \n+# test_cmp is a helper function to compare actual and expected output.\n+# You can use it like:\n+#\n+#\ttest_expect_success 'foo works' '\n+#\t\techo expected >expected &&\n+#\t\tfoo >actual &&\n+#\t\ttest_cmp expected actual\n+#\t'\n+#\n+# This could be written as either \"cmp\" or \"diff -u\", but:\n+# - cmp's output is not nearly as easy to read as diff -u\n+# - not all diff versions understand \"-u\"\n+\n+test_cmp() {\n+\t$GIT_TEST_CMP \"$@\"\n+}\n+\n # Most tests can use the created repository, but some may need to create more.\n # Usage: test_create_repo <directory>\n test_create_repo () {\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71854","messageId":"20080312213737.GH26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 07/16] t4020: don't use grep -a","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:37:37Z","receivedAt":"2008-03-12T21:37:37Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Solaris /usr/bin/grep doesn't understand \"-a\". In this case\nwe can just include the expected output with the test, which\nis a better test anyway.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nOoh, we get to use binary patches.\n\n t/t4020-diff-external.sh |    3 ++-\n t/t4020/diff.NUL         |  Bin 0 -> 116 bytes\n 2 files changed, 2 insertions(+), 1 deletions(-)\n create mode 100644 t/t4020/diff.NUL\n\ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex bf8f778..637b4e1 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -103,7 +103,8 @@ echo NULZbetweenZwords | perl -pe 'y/Z/\\000/' > file\n \n test_expect_success 'force diff with \"diff\"' '\n \techo >.gitattributes \"file diff\" &&\n-\tgit diff | grep -a second\n+\tgit diff >actual &&\n+\ttest_cmp ../t4020/diff.NUL actual\n '\n \n test_done\ndiff --git a/t/t4020/diff.NUL b/t/t4020/diff.NUL\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..db2f89090c1c4de05e4f82ea39ea118fccfd48dd\nGIT binary patch\nliteral 116\nzcmXxbF$#k~5Jq9^ImPtD=#EH8x;=oT%K;qs->?u?P{ABu2(fz2_fpB3Ro`XjsmtX9\nz_Ft&fgfAo5!x7pxTMzd;TL`ydAXWW)5|QhPk=0m?V<g=$FEx=oUt{Cg51=;3vZjqr\nDo_`?W\n\nliteral 0\nHcmV?d00001\n\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71855","messageId":"20080312213756.GI26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 08/16] t4200: use cut instead of sed","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:37:56Z","receivedAt":"2008-03-12T21:37:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Some versions of sed (like the one on Solaris) don't like to\nmatch literal tabs, and simply print nothing. Instead, let's\nuse cut.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n t/t4200-rerere.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex 3cbfee7..d3dea2a 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -53,7 +53,7 @@ test_expect_success 'conflicting merge' '\n \t! git merge first\n '\n \n-sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR)\n+sha1=$(cut -d'\t' -f1 .git/rr-cache/MERGE_RR)\n rr=.git/rr-cache/$sha1\n test_expect_success 'recorded preimage' \"grep ======= $rr/preimage\"\n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71856","messageId":"20080312213831.GJ26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 09/16] t6000lib: tr portability fix","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:38:31Z","receivedAt":"2008-03-12T21:38:31Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Some versions of tr complain if the number of characters in\nboth sets isn't the same. So here we must manually expand\nthe dashes in set2.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis almost makes me want to just use sed instead. But quoting that line\nnoise would probably make it less readable.\n\n t/t6000lib.sh |    5 ++++-\n 1 files changed, 4 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t6000lib.sh b/t/t6000lib.sh\nindex 180633e..b69f7c4 100755\n--- a/t/t6000lib.sh\n+++ b/t/t6000lib.sh\n@@ -97,7 +97,10 @@ check_output()\n # from front and back.\n name_from_description()\n {\n-        tr \"'\" '-' | tr '~`!@#$%^&*()_+={}[]|\\;:\"<>,/? ' '-' | tr -s '-' | tr '[A-Z]' '[a-z]' | sed \"s/^-*//;s/-*\\$//\"\n+        tr \"'\" '-' |\n+\t\ttr '~`!@#$%^&*()_+={}[]|\\;:\"<>,/? ' \\\n+\t\t   '------------------------------' |\n+\t\ttr -s '-' | tr '[A-Z]' '[a-z]' | sed \"s/^-*//;s/-*\\$//\"\n }\n \n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71857","messageId":"20080312213916.GK26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:39:16Z","receivedAt":"2008-03-12T21:39:16Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Previously, we just chose whether to allow external grep\nbased on the __unix__ define. However, there are systems\nwhich define this macro but which have an inferior group\n(e.g., one that does not support all options used by t7002).\nThis allows users to accept the potential speed penalty to\nget a more consistent grep experience (and to pass the\ntestsuite).\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis might have fallouts for msysgit (i.e., they need to define\nNO_EXTERNAL_GREP instead of relying on __unix__ not being defined).\n\n Makefile       |    7 +++++++\n builtin-grep.c |    4 ++--\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex e3eaa6a..8e80225 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -148,6 +148,9 @@ all::\n # is a simplified version of the merge sort used in glibc. This is\n # recommended if Git triggers O(n^2) behavior in your platform's qsort().\n #\n+# Define NO_EXTERNAL_GREP if you don't want \"git grep\" to ever call\n+# your external grep (e.g., if your system lacks grep, or if its grep is\n+# not very featureful).\n \n GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE\n \t@$(SHELL_PATH) ./GIT-VERSION-GEN\n@@ -467,6 +470,7 @@ ifeq ($(uname_O),Cygwin)\n \tNO_STRCASESTR = YesPlease\n \tNO_MEMMEM = YesPlease\n \tNO_SYMLINK_HEAD = YesPlease\n+\tNO_EXTERNAL_GREP = YesPlease\n \tNEEDS_LIBICONV = YesPlease\n \tNO_FAST_WORKING_DIRECTORY = UnfortunatelyYes\n \tNO_TRUSTABLE_FILEMODE = UnfortunatelyYes\n@@ -760,6 +764,9 @@ endif\n ifdef DIR_HAS_BSD_GROUP_SEMANTICS\n \tCOMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS\n endif\n+ifdef NO_EXTERNAL_GREP\n+\tBASIC_CFLAGS += -DNO_EXTERNAL_GREP\n+endif\n \n ifeq ($(TCLTK_PATH),)\n NO_TCLTK=NoThanks\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex f4f4ecb..f215b28 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -153,7 +153,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)\n \treturn i;\n }\n \n-#ifdef __unix__\n+#ifndef NO_EXTERNAL_GREP\n static int exec_grep(int argc, const char **argv)\n {\n \tpid_t pid;\n@@ -372,7 +372,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)\n \tint nr;\n \tread_cache();\n \n-#ifdef __unix__\n+#ifndef NO_EXTERNAL_GREP\n \t/*\n \t * Use the external \"grep\" command for the case where\n \t * we grep through the checked-out files. It tends to\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71858","messageId":"20080312214019.GL26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 11/16] config: add --literal-match option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:40:19Z","receivedAt":"2008-03-12T21:40:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"When limiting the values to be set (or returned), the user\npreviously had the option of specifying a regex. In some\ncases, however, they may want to find a literal value. The\noption --literal-match converts any matching regex into a\nliteral string comparison.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI think this is a nice addition regardless, but it is used by the next\npatch.\n\nThe patch is about twice as long as it needs to be since getting and\nsetting in builtin-config follow two almost-the-same parallel codepaths.\nI suspect this could be cleaned up, but I didn't look too closely.\n\n Documentation/git-config.txt |    7 ++++\n builtin-config.c             |   50 +++++++++++++++++++++++--------\n builtin-remote.c             |    2 +-\n cache.h                      |    2 +-\n config.c                     |   67 ++++++++++++++++++++++++++++--------------\n t/t1300-repo-config.sh       |   13 ++++++++\n 6 files changed, 104 insertions(+), 37 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex fa16171..5dc1af2 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -152,6 +152,13 @@ See also <<FILES>>.\n \toutput.  The optional `default` parameter is used instead, if\n \tthere is no color configured for `name`.\n \n+--literal-match::\n+\n+\tSome invocations of git-config will limit their actions based on\n+\tmatching a config value to a regular expression. If this option\n+\tis used, then any such matches are done as a string comparison\n+\trather than as a regular expression match.\n+\n [[FILES]]\n FILES\n -----\ndiff --git a/builtin-config.c b/builtin-config.c\nindex 2b9a426..ed318dc 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -8,6 +8,7 @@ static const char git_config_set_usage[] =\n static char *key;\n static regex_t *key_regexp;\n static regex_t *regexp;\n+const char *value_match;\n static int show_keys;\n static int use_key_regexp;\n static int do_all;\n@@ -17,6 +18,7 @@ static char delim = '=';\n static char key_delim = ' ';\n static char term = '\\n';\n static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;\n+static int literal_match = 0;\n \n static int show_all_config(const char *key_, const char *value_)\n {\n@@ -40,6 +42,9 @@ static int show_config(const char* key_, const char* value_)\n \tif (regexp != NULL &&\n \t    (do_not_match ^ !!regexec(regexp, (value_?value_:\"\"), 0, NULL, 0)))\n \t\treturn 0;\n+\tif (value_match != NULL &&\n+\t\tdo_not_match ^ !!strcmp(value_match, (value_ ? value_ : \"\")))\n+\t\treturn 0;\n \n \tif (show_keys) {\n \t\tif (value_)\n@@ -66,7 +71,7 @@ static int show_config(const char* key_, const char* value_)\n \treturn 0;\n }\n \n-static int get_value(const char* key_, const char* regex_)\n+static int get_value(const char* key_, const char* match_)\n {\n \tint ret = -1;\n \tchar *tl;\n@@ -99,18 +104,28 @@ static int get_value(const char* key_, const char* regex_)\n \t\t}\n \t}\n \n-\tif (regex_) {\n-\t\tif (regex_[0] == '!') {\n+\tif (match_ && literal_match) {\n+\t\tvalue_match = match_;\n+\t\tdo_not_match = 0;\n+\t\tregexp = NULL;\n+\t}\n+\telse if(match_) {\n+\t\tvalue_match = NULL;\n+\t\tif (match_[0] == '!') {\n \t\t\tdo_not_match = 1;\n-\t\t\tregex_++;\n+\t\t\tmatch_++;\n \t\t}\n \n \t\tregexp = (regex_t*)xmalloc(sizeof(regex_t));\n-\t\tif (regcomp(regexp, regex_, REG_EXTENDED)) {\n-\t\t\tfprintf(stderr, \"Invalid pattern: %s\\n\", regex_);\n+\t\tif (regcomp(regexp, match_, REG_EXTENDED)) {\n+\t\t\tfprintf(stderr, \"Invalid pattern: %s\\n\", match_);\n \t\t\tgoto free_strings;\n \t\t}\n \t}\n+\telse {\n+\t\tvalue_match = NULL;\n+\t\tregexp = NULL;\n+\t}\n \n \tif (do_all && system_wide)\n \t\tgit_config_from_file(show_config, system_wide);\n@@ -339,6 +354,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\treturn get_color(argc-2, argv+2);\n \t\t} else if (!strcmp(argv[1], \"--get-colorbool\")) {\n \t\t\treturn get_colorbool(argc-2, argv+2);\n+\t\t} else if (!strcmp(argv[1], \"--literal-match\")) {\n+\t\t\tliteral_match = 1;\n \t\t} else\n \t\t\tbreak;\n \t\targc--;\n@@ -352,7 +369,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\tif (!strcmp(argv[1], \"--unset\"))\n \t\t\treturn git_config_set(argv[2], NULL);\n \t\telse if (!strcmp(argv[1], \"--unset-all\"))\n-\t\t\treturn git_config_set_multivar(argv[2], NULL, NULL, 1);\n+\t\t\treturn git_config_set_multivar(argv[2], NULL, NULL,\n+\t\t\t\t\tliteral_match, 1);\n \t\telse if (!strcmp(argv[1], \"--get\"))\n \t\t\treturn get_value(argv[2], NULL);\n \t\telse if (!strcmp(argv[1], \"--get-all\")) {\n@@ -369,9 +387,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t}\n \tcase 4:\n \t\tif (!strcmp(argv[1], \"--unset\"))\n-\t\t\treturn git_config_set_multivar(argv[2], NULL, argv[3], 0);\n+\t\t\treturn git_config_set_multivar(argv[2], NULL, argv[3],\n+\t\t\t\t\tliteral_match, 0);\n \t\telse if (!strcmp(argv[1], \"--unset-all\"))\n-\t\t\treturn git_config_set_multivar(argv[2], NULL, argv[3], 1);\n+\t\t\treturn git_config_set_multivar(argv[2], NULL, argv[3],\n+\t\t\t\t\tliteral_match, 1);\n \t\telse if (!strcmp(argv[1], \"--get\"))\n \t\t\treturn get_value(argv[2], argv[3]);\n \t\telse if (!strcmp(argv[1], \"--get-all\")) {\n@@ -384,18 +404,22 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\treturn get_value(argv[2], argv[3]);\n \t\t} else if (!strcmp(argv[1], \"--add\")) {\n \t\t\tvalue = normalize_value(argv[2], argv[3]);\n-\t\t\treturn git_config_set_multivar(argv[2], value, \"^$\", 0);\n+\t\t\treturn git_config_set_multivar(argv[2], value, \"^$\",\n+\t\t\t\t\t0, 0);\n \t\t} else if (!strcmp(argv[1], \"--replace-all\")) {\n \t\t\tvalue = normalize_value(argv[2], argv[3]);\n-\t\t\treturn git_config_set_multivar(argv[2], value, NULL, 1);\n+\t\t\treturn git_config_set_multivar(argv[2], value, NULL,\n+\t\t\t\t\t0, 1);\n \t\t} else {\n \t\t\tvalue = normalize_value(argv[1], argv[2]);\n-\t\t\treturn git_config_set_multivar(argv[1], value, argv[3], 0);\n+\t\t\treturn git_config_set_multivar(argv[1], value, argv[3],\n+\t\t\t\t       literal_match, 0);\n \t\t}\n \tcase 5:\n \t\tif (!strcmp(argv[1], \"--replace-all\")) {\n \t\t\tvalue = normalize_value(argv[2], argv[3]);\n-\t\t\treturn git_config_set_multivar(argv[2], value, argv[4], 1);\n+\t\t\treturn git_config_set_multivar(argv[2], value, argv[4],\n+\t\t\t\t\tliteral_match, 1);\n \t\t}\n \tcase 1:\n \tdefault:\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex 24e6929..4eae74b 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -107,7 +107,7 @@ static int add(int argc, const char **argv)\n \t\telse\n \t\t\tstrbuf_addf(&buf2, \"refs/heads/%s:refs/remotes/%s/%s\",\n \t\t\t\t\titem->path, name, item->path);\n-\t\tif (git_config_set_multivar(buf.buf, buf2.buf, \"^$\", 0))\n+\t\tif (git_config_set_multivar(buf.buf, buf2.buf, \"^$\", 0, 0))\n \t\t\treturn 1;\n \t}\n \ndiff --git a/cache.h b/cache.h\nindex 2a1e7ec..30830b0 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -695,7 +695,7 @@ extern unsigned long git_config_ulong(const char *, const char *);\n extern int git_config_bool(const char *, const char *);\n extern int git_config_string(const char **, const char *, const char *);\n extern int git_config_set(const char *, const char *);\n-extern int git_config_set_multivar(const char *, const char *, const char *, int);\n+extern int git_config_set_multivar(const char *, const char *, const char *, int, int);\n extern int git_config_rename_section(const char *, const char *);\n extern const char *git_etc_gitconfig(void);\n extern int check_repository_format_version(const char *var, const char *value);\ndiff --git a/config.c b/config.c\nindex 0624494..862b0e6 100644\n--- a/config.c\n+++ b/config.c\n@@ -575,7 +575,15 @@ static struct {\n \tint baselen;\n \tchar* key;\n \tint do_not_match;\n-\tregex_t* value_regex;\n+\tenum {\n+\t\tVALUE_NONE,\n+\t\tVALUE_REGEX,\n+\t\tVALUE_STRING,\n+\t} value_type;\n+\tunion {\n+\t\tregex_t* regex;\n+\t\tconst char *string;\n+\t} value;\n \tint multi_replace;\n \tsize_t offset[MAX_MATCHES];\n \tenum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;\n@@ -584,10 +592,19 @@ static struct {\n \n static int matches(const char* key, const char* value)\n {\n-\treturn !strcmp(key, store.key) &&\n-\t\t(store.value_regex == NULL ||\n-\t\t (store.do_not_match ^\n-\t\t  !regexec(store.value_regex, value, 0, NULL, 0)));\n+\tif (strcmp(key, store.key))\n+\t\treturn 0;\n+\tswitch(store.value_type) {\n+\tcase VALUE_NONE:\n+\t\treturn 1;\n+\tcase VALUE_REGEX:\n+\t\treturn store.do_not_match ^\n+\t\t\t!regexec(store.value.regex, value, 0, NULL, 0);\n+\tcase VALUE_STRING:\n+\t\treturn store.do_not_match ^\n+\t\t\t!strcmp(value, store.value.string);\n+\t}\n+\tdie(\"bug in config.c:matches\");\n }\n \n static int store_aux(const char* key, const char* value)\n@@ -764,12 +781,12 @@ contline:\n \n int git_config_set(const char* key, const char* value)\n {\n-\treturn git_config_set_multivar(key, value, NULL, 0);\n+\treturn git_config_set_multivar(key, value, NULL, 0, 0);\n }\n \n /*\n  * If value==NULL, unset in (remove from) config,\n- * if value_regex!=NULL, disregard key/value pairs where value does not match.\n+ * if value_match!=NULL, disregard key/value pairs where value does not match.\n  * if multi_replace==0, nothing, or only one matching key/value is replaced,\n  *     else all matching key/values (regardless how many) are removed,\n  *     before the new pair is written.\n@@ -791,7 +808,7 @@ int git_config_set(const char* key, const char* value)\n  *\n  */\n int git_config_set_multivar(const char* key, const char* value,\n-\tconst char* value_regex, int multi_replace)\n+\tconst char* value_match, int literal_match, int multi_replace)\n {\n \tint i, dot;\n \tint fd = -1, in_fd;\n@@ -892,21 +909,27 @@ int git_config_set_multivar(const char* key, const char* value,\n \t\tsize_t contents_sz, copy_begin, copy_end;\n \t\tint i, new_line = 0;\n \n-\t\tif (value_regex == NULL)\n-\t\t\tstore.value_regex = NULL;\n+\t\tif (value_match == NULL)\n+\t\t\tstore.value_type = VALUE_NONE;\n+\t\telse if(literal_match) {\n+\t\t\tstore.value_type = VALUE_STRING;\n+\t\t\tstore.do_not_match = 0;\n+\t\t\tstore.value.string = value_match;\n+\t\t}\n \t\telse {\n-\t\t\tif (value_regex[0] == '!') {\n+\t\t\tstore.value_type = VALUE_REGEX;\n+\t\t\tif (value_match[0] == '!') {\n \t\t\t\tstore.do_not_match = 1;\n-\t\t\t\tvalue_regex++;\n+\t\t\t\tvalue_match++;\n \t\t\t} else\n \t\t\t\tstore.do_not_match = 0;\n \n-\t\t\tstore.value_regex = (regex_t*)xmalloc(sizeof(regex_t));\n-\t\t\tif (regcomp(store.value_regex, value_regex,\n+\t\t\tstore.value.regex = (regex_t*)xmalloc(sizeof(regex_t));\n+\t\t\tif (regcomp(store.value.regex, value_match,\n \t\t\t\t\tREG_EXTENDED)) {\n \t\t\t\tfprintf(stderr, \"Invalid pattern: %s\\n\",\n-\t\t\t\t\tvalue_regex);\n-\t\t\t\tfree(store.value_regex);\n+\t\t\t\t\tvalue_match);\n+\t\t\t\tfree(store.value.regex);\n \t\t\t\tret = 6;\n \t\t\t\tgoto out_free;\n \t\t\t}\n@@ -925,18 +948,18 @@ int git_config_set_multivar(const char* key, const char* value,\n \t\tif (git_config_from_file(store_aux, config_filename)) {\n \t\t\tfprintf(stderr, \"invalid config file\\n\");\n \t\t\tfree(store.key);\n-\t\t\tif (store.value_regex != NULL) {\n-\t\t\t\tregfree(store.value_regex);\n-\t\t\t\tfree(store.value_regex);\n+\t\t\tif (store.value_type == VALUE_REGEX) {\n+\t\t\t\tregfree(store.value.regex);\n+\t\t\t\tfree(store.value.regex);\n \t\t\t}\n \t\t\tret = 3;\n \t\t\tgoto out_free;\n \t\t}\n \n \t\tfree(store.key);\n-\t\tif (store.value_regex != NULL) {\n-\t\t\tregfree(store.value_regex);\n-\t\t\tfree(store.value_regex);\n+\t\tif (store.value_type == VALUE_REGEX) {\n+\t\t\tregfree(store.value.regex);\n+\t\t\tfree(store.value.regex);\n \t\t}\n \n \t\t/* if nothing to unset, or too many matches, error out */\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex b36a901..6c5ccdd 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -682,4 +682,17 @@ test_expect_success 'symlinked configuration' '\n \n '\n \n+test_expect_success 'literal matching works' '\n+\n+\tgit config literal.key1 value &&\n+\tgit config literal.key2 va..e &&\n+\tgit config --get-regexp \"literal..*\" va..e >output &&\n+\tgrep key1 output &&\n+\tgrep key2 output &&\n+\tgit config --literal-match --get-regexp \"literal..*\" va..e >output &&\n+\t! grep key1 output &&\n+\tgrep key2 output\n+\n+'\n+\n test_done\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71859","messageId":"20080312214044.GM26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 12/16] git-submodule: avoid sed input with no newline","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:40:44Z","receivedAt":"2008-03-12T21:40:44Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Some versions of sed don't like this, and give no output at\nall. Instead, we can use git-config to pare down the matches\nfor us.\n\nThe content of the last three lines of the patch aren't\nchanged at all; they merely fix a bogus 7-space indentation.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nAnd this is safe because of the --literal-match from the last patch.\n\n git-submodule.sh |   13 ++++++-------\n 1 files changed, 6 insertions(+), 7 deletions(-)\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex ceb2295..fb01d94 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -71,13 +71,12 @@ resolve_relative_url ()\n module_name()\n {\n \t# Do we have \"submodule.<something>.path = $1\" defined in .gitmodules file?\n-\tre=$(printf '%s' \"$1\" | sed -e 's/[].[^$\\\\*]/\\\\&/g')\n-\tname=$( GIT_CONFIG=.gitmodules \\\n-\t\tgit config --get-regexp '^submodule\\..*\\.path$' |\n-\t\tsed -n -e 's|^submodule\\.\\(.*\\)\\.path '\"$re\"'$|\\1|p' )\n-       test -z \"$name\" &&\n-       die \"No submodule mapping found in .gitmodules for path '$path'\"\n-       echo \"$name\"\n+\tname=$(git config --literal-match -f .gitmodules \\\n+\t\t--get-regexp 'submodule\\..*\\.path$' \"$1\" |\n+\t\tsed -e 's/submodule\\.//' -e 's/\\.path.*//')\n+\ttest -z \"$name\" &&\n+\tdie \"No submodule mapping found in .gitmodules for path '$path'\"\n+\techo \"$name\"\n }\n \n #\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71860","messageId":"20080312214102.GN26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 13/16] filter-branch: don't use xargs -0","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:41:02Z","receivedAt":"2008-03-12T21:41:02Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Some versions of xargs don't understand \"-0\"; fortunately in\nthis case we can get the same effect by using \"git clean\".\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n git-filter-branch.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex 59cf023..efef732 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -281,7 +281,7 @@ while read commit parents; do\n \t\t\tdie \"Could not checkout the index\"\n \t\t# files that $commit removed are now still in the working tree;\n \t\t# remove them, else they would be added again\n-\t\tgit ls-files -z --others | xargs -0 rm -f\n+\t\tgit clean -q -f -x\n \t\teval \"$filter_tree\" < /dev/null ||\n \t\t\tdie \"tree filter failed: $filter_tree\"\n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71861","messageId":"20080312214139.GO26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 14/16] filter-branch: use $SHELL_PATH instead of 'sh'","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:41:39Z","receivedAt":"2008-03-12T21:41:39Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On some systems, 'sh' isn't very friendly. In particular,\nt7003 fails on Solaris because it doesn't understand $().\nInstead, use the specified SHELL_PATH to run shell code.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI think this makes sense regardless of the Solaris shell. We should be\nconsistent about which SHELL_PATH we use in scripts.\n\n Makefile             |    1 +\n git-filter-branch.sh |    2 +-\n 2 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 8e80225..bd5a623 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -874,6 +874,7 @@ common-cmds.h: $(wildcard Documentation/git-*.txt)\n $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh\n \t$(QUIET_GEN)$(RM) $@ $@+ && \\\n \tsed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \\\n+\t    -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \\\n \t    -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \\\n \t    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \\\n \t    -e 's/@@NO_CURL@@/$(NO_CURL)/g' \\\ndiff --git a/git-filter-branch.sh b/git-filter-branch.sh\nindex efef732..22b6ed4 100755\n--- a/git-filter-branch.sh\n+++ b/git-filter-branch.sh\n@@ -309,7 +309,7 @@ while read commit parents; do\n \tsed -e '1,/^$/d' <../commit | \\\n \t\teval \"$filter_msg\" > ../message ||\n \t\t\tdie \"msg filter failed: $filter_msg\"\n-\tsh -c \"$filter_commit\" \"git commit-tree\" \\\n+\t@SHELL_PATH@ -c \"$filter_commit\" \"git commit-tree\" \\\n \t\t$(git write-tree) $parentstr < ../message > ../map/$commit\n done <../revs\n \n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71862","messageId":"20080312214215.GP26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 15/16] t9112: add missing #!/bin/sh header","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:42:15Z","receivedAt":"2008-03-12T21:42:15Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis causes the test to barf under Solaris, even though the \"correct\"\nbehavior for me was to just start it and skip the tests.\n\n t/t9112-git-svn-md5less-file.sh |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh\nindex 08313bb..646a5f0 100755\n--- a/t/t9112-git-svn-md5less-file.sh\n+++ b/t/t9112-git-svn-md5less-file.sh\n@@ -1,3 +1,5 @@\n+#!/bin/sh\n+\n test_description='test that git handles an svn repository with missing md5sums'\n \n . ./lib-git-svn.sh\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71863","messageId":"20080312214243.GQ26286@coredump.intra.peff.net","threadId":"12657","inReplyTo":"cover.1205356737.git.peff@peff.net","subject":"[PATCH 16/16] t7505: use SHELL_PATH in hook","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-12T21:42:43Z","receivedAt":"2008-03-12T21:42:43Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The hook doesn't run properly under Solaris /bin/sh. Let's\nuse the SHELL_PATH the user told us about already instead.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI discussed this before, but I never followed up with a patch. So here\nit is.\n\n t/t7505-prepare-commit-msg-hook.sh |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh\nindex 7ddec99..fd67996 100755\n--- a/t/t7505-prepare-commit-msg-hook.sh\n+++ b/t/t7505-prepare-commit-msg-hook.sh\n@@ -25,7 +25,8 @@ export FAKE_EDITOR\n HOOKDIR=\"$(git rev-parse --git-dir)/hooks\"\n HOOK=\"$HOOKDIR/prepare-commit-msg\"\n mkdir -p \"$HOOKDIR\"\n-cat > \"$HOOK\" <<'EOF'\n+echo \"#!$SHELL_PATH\" > \"$HOOK\"\n+cat >> \"$HOOK\" <<'EOF'\n #!/bin/sh\n if test \"$2\" = commit; then\n   source=$(git-rev-parse \"$3\")\n-- \n1.5.4.4.543.g30fdd.dirty\n"},{"id":"71864","messageId":"fr9ivq$eh0$1@ger.gmane.org","threadId":"12657","inReplyTo":"20080312214019.GL26286@coredump.intra.peff.net","subject":"Re: [PATCH 11/16] config: add --literal-match option","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-03-12T21:46:43Z","receivedAt":"2008-03-12T21:46:43Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jeff King wrote:\n\n> +--literal-match::\n> +\n> +       Some invocations of git-config will limit their actions based on\n> +       matching a config value to a regular expression. If this option\n> +       is used, then any such matches are done as a string comparison\n> +       rather than as a regular expression match.\n> +\n\nWhy this option is not named --fixed-strings, as everywhere else, then?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"71866","messageId":"7vr6ef4mqa.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312213217.GE26286@coredump.intra.peff.net","subject":"Re: [PATCH 04/16] grep portability fix: don't use \"-e\" or \"-q\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:10:53Z","receivedAt":"2008-03-12T22:10:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> System V versions of grep (such as Solaris /usr/bin/grep)\n> don't understand either of these options. git's usage of\n\nIt might be fair for other System V people to qualify the above statement\nwith \"Historic System V\" (personally I felt that Solaris without xpg4 was\nunusable, and I wish you luck tackling it).\n\nMore seriously, you would need to disable \"when grepping work-tree,\nrunning the native grep is faster and just as capable\" optimization in\nbuiltin-grep.c::grep_cache().  Treat these problematic System V platforms\nas if they are not __unix__.\n\nI am surprised that you did not have issues with \"tail -n$number\".\nHistoric way to spell it was \"tail -$number\" wasn't it?\n"},{"id":"71867","messageId":"7vmyp34mn6.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312213636.GG26286@coredump.intra.peff.net","subject":"Re: [PATCH 06/16] add test_cmp function for test scripts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:12:45Z","receivedAt":"2008-03-12T22:12:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I think I have an earlier round of this in 'pu'.\n"},{"id":"71869","messageId":"7viqzr4lua.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312213916.GK26286@coredump.intra.peff.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:30:05Z","receivedAt":"2008-03-12T22:30:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Previously, we just chose whether to allow external grep\n> based on the __unix__ define. However, there are systems\n> which define this macro but which have an inferior group\n> (e.g., one that does not support all options used by t7002).\n> This allows users to accept the potential speed penalty to\n> get a more consistent grep experience (and to pass the\n> testsuite).\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n> This might have fallouts for msysgit (i.e., they need to define\n> NO_EXTERNAL_GREP instead of relying on __unix__ not being defined).\n> ...\n> diff --git a/builtin-grep.c b/builtin-grep.c\n> index f4f4ecb..f215b28 100644\n> --- a/builtin-grep.c\n> +++ b/builtin-grep.c\n> @@ -153,7 +153,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)\n>  \treturn i;\n>  }\n>  \n> -#ifdef __unix__\n> +#ifndef NO_EXTERNAL_GREP\n\nPerhaps place\n\n    #ifndef NO_EXTERNAL_GREP\n    #ifndef __unix__\n    #define NO_EXTERNAL_GREP 1\n    #else\n    #define NO_EXTERNAL_GREP 0\n    #endif\n    #endif\n\nin git-compat-util.h, and make the in-code reference to\n\n    #if NO_EXTERNAL_GREP\n            ... optimization using external grep ...\n    #endif\n"},{"id":"71870","messageId":"7vejaf4lmc.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312214019.GL26286@coredump.intra.peff.net","subject":"Re: [PATCH 11/16] config: add --literal-match option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:34:51Z","receivedAt":"2008-03-12T22:34:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> When limiting the values to be set (or returned), the user\n> previously had the option of specifying a regex. In some\n> cases, however, they may want to find a literal value. The\n> option --literal-match converts any matching regex into a\n> literal string comparison.\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n> I think this is a nice addition regardless, but it is used by the next\n> patch.\n>\n> The patch is about twice as long as it needs to be since getting and\n> setting in builtin-config follow two almost-the-same parallel codepaths.\n> I suspect this could be cleaned up, but I didn't look too closely.\n\nI think that is a good new feature to propose.\n\nHistorically, the config_set_multivar() function has been one of the most\nbuggy part of the then-current codebase.  It might be a good idea to\nclean-up first and then enhance.\n\nBut in either case I am quite reluctant to touch this part of the code\nright now before 1.5.5, especially without extra sets of eyeballs.\n"},{"id":"71872","messageId":"7vabl34lc0.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312214044.GM26286@coredump.intra.peff.net","subject":"Re: [PATCH 12/16] git-submodule: avoid sed input with no newline","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:41:03Z","receivedAt":"2008-03-12T22:41:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Some versions of sed don't like this, and give no output at\n> all. Instead, we can use git-config to pare down the matches\n> for us.\n\nGood use of --literal.\n\nBut doesn't this make you wonder if \"--literal-match --get-regexp\" is\nquite a strange combination?  \"Literal\" covers the value part but the key\nis still regexp (and we do want it to behave that way).  However, maybe we\nwould want to also allow \"give entries whose key is this literal key and\nwhose value matches this regexp\"?\n\n> +\tname=$(git config --literal-match -f .gitmodules \\\n> +\t\t--get-regexp 'submodule\\..*\\.path$' \"$1\" |\n> +\t\tsed -e 's/submodule\\.//' -e 's/\\.path.*//')\n> +\ttest -z \"$name\" &&\n> +\tdie \"No submodule mapping found in .gitmodules for path '$path'\"\n> +\techo \"$name\"\n>  }\n"},{"id":"71873","messageId":"7v63vr4l48.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"7vr6ef4mqa.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 04/16] grep portability fix: don't use \"-e\" or \"-q\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-12T22:45:43Z","receivedAt":"2008-03-12T22:45:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Jeff King <peff@peff.net> writes:\n>\n>> System V versions of grep (such as Solaris /usr/bin/grep)\n>> don't understand either of these options. git's usage of\n>\n> It might be fair for other System V people to qualify the above statement\n> with \"Historic System V\" (personally I felt that Solaris without xpg4 was\n> unusable, and I wish you luck tackling it).\n>\n> More seriously, you would need to disable \"when grepping work-tree,\n> running the native grep is faster and just as capable\" optimization in\n> builtin-grep.c::grep_cache().  Treat these problematic System V platforms\n> as if they are not __unix__.\n>\n> I am surprised that you did not have issues with \"tail -n$number\".\n> Historic way to spell it was \"tail -$number\" wasn't it?\n\nHeh, I notice you had to deal with these issues in the later patches ;-)\n"},{"id":"71889","messageId":"7vejaf1b0d.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312213756.GI26286@coredump.intra.peff.net","subject":"Re: [PATCH 08/16] t4200: use cut instead of sed","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-13T04:52:18Z","receivedAt":"2008-03-13T04:52:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Some versions of sed (like the one on Solaris) don't like to\n> match literal tabs, and simply print nothing. Instead, let's\n> use cut.\n\n> -sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR)\n\nThis is a bit hard to believe.  On one of my ancient Sun box:\n\n$ uname -a\nSunOS sic.twinsun.com 5.8 Generic_117350-45 sun4u sparc SUNW,UltraSPARC-IIi-Engine\n$ ls -l /bin/sed\n-r-xr-xr-x   1 root     bin        28748 Aug  2  2005 /bin/sed\n\nthe above \"sed\" does not misbehave (/bin/sh does, of course, on $(...),\nbut that is a different story).\n"},{"id":"71905","messageId":"47D8D39C.3070904@users.sourceforge.net","threadId":"12657","inReplyTo":"20080312214243.GQ26286@coredump.intra.peff.net","subject":"Re: [PATCH 16/16] t7505: use SHELL_PATH in hook","fromName":"Adam Piatyszek","fromEmail":"ediap@users.sourceforge.net","sentAt":"2008-03-13T07:11:24Z","receivedAt":"2008-03-13T07:11:24Z","isPatch":true,"sender":{"key":"ediap@users.sourceforge.net","avatar":null},"body":"Hi!\n\n* Jeff King [12 III 2008 22:42]:\n> The hook doesn't run properly under Solaris /bin/sh. Let's\n> use the SHELL_PATH the user told us about already instead.\n[...]\n> --- a/t/t7505-prepare-commit-msg-hook.sh\n> +++ b/t/t7505-prepare-commit-msg-hook.sh\n> @@ -25,7 +25,8 @@ export FAKE_EDITOR\n>  HOOKDIR=\"$(git rev-parse --git-dir)/hooks\"\n>  HOOK=\"$HOOKDIR/prepare-commit-msg\"\n>  mkdir -p \"$HOOKDIR\"\n> -cat > \"$HOOK\" <<'EOF'\n> +echo \"#!$SHELL_PATH\" > \"$HOOK\"\n> +cat >> \"$HOOK\" <<'EOF'\n>  #!/bin/sh\n    ^^^^^^^^^\nThe above line should be removed in my humble opinion.\n\nBR,\n/Adam\n\n-- \n.:.  Adam Piatyszek (ediap)  .:.....................................:.\n.:.  ediap@users.sourceforge.net  .:................................:.\n"},{"id":"71901","messageId":"47D8D895.4030309@viscovery.net","threadId":"12657","inReplyTo":"20080312212957.GB26286@coredump.intra.peff.net","subject":"Re: [PATCH 01/16] tr portability fixes","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-13T07:32:37Z","receivedAt":"2008-03-13T07:32:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> We can mostly get around this by just using the bracket form\n> for both sets, as in:\n> \n>   tr '[A-Z] '[a-z]'\n> \n> in which case POSIX interpets this as \"'[' becomes '['\",\n> which is OK.\n> \n> However, this doesn't work with multiple sequences, like:\n> \n>   # rot13\n>   tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]'\n\nNot that it matters a lot, but I wonder whether\n\n   tr '[A-M][N-Z][a-m][n-z]' '[N-Z][A-M][n-z][a-m]'\n\nwould have done the trick.\n\n-- Hannes\n"},{"id":"71904","messageId":"47D8D9DE.1050901@viscovery.net","threadId":"12657","inReplyTo":"20080312213010.GC26286@coredump.intra.peff.net","subject":"Re: [PATCH 02/16] t0050: perl portability fix","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-13T07:38:06Z","receivedAt":"2008-03-13T07:38:06Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> Older versions of perl (such as 5.005) don't understand -CO, nor\n> do they understand the \"U\" pack specifier. Instead of using perl,\n> let's just printf the binary bytes we are interested in.\n> \n> Signed-off-by: Jeff King <peff@peff.net>\n\nYay! We need this on Windows with MSYS's perl, too. Works great:\n\nTested-by: Johannes Sixt <johannes.sixt@telecom.at>\n\n-- Hannes\n"},{"id":"71906","messageId":"47D8DCC0.9090303@viscovery.net","threadId":"12657","inReplyTo":"20080312213916.GK26286@coredump.intra.peff.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-13T07:50:24Z","receivedAt":"2008-03-13T07:50:24Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> Previously, we just chose whether to allow external grep\n> based on the __unix__ define. However, there are systems\n> which define this macro but which have an inferior group\n> (e.g., one that does not support all options used by t7002).\n> This allows users to accept the potential speed penalty to\n> get a more consistent grep experience (and to pass the\n> testsuite).\n> \n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n> This might have fallouts for msysgit (i.e., they need to define\n> NO_EXTERNAL_GREP instead of relying on __unix__ not being defined).\n\nYou name it. Would you mind converting exec_grep() to use run_command(),\ntoo? Or better inline it since it won't do a lot more than run_command()?\nThat way we at least won't get a broken git when I merge git.git that has\nthis patch.\n\nThanks,\n-- Hannes\n"},{"id":"71908","messageId":"7vy78nxdjl.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080312213916.GK26286@coredump.intra.peff.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-13T07:56:30Z","receivedAt":"2008-03-13T07:56:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"There is one more reason other than you said in the Makefile patch one\nmight want to avoid external grep.  Cygwin may have perfectly well working\ngrep, but the reason they avoid external grep is because forking is too\nslow there.\n\n---\n\n Makefile       |    5 ++---\n builtin-grep.c |   12 ++++++++++--\n 2 files changed, 12 insertions(+), 5 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 8e80225..bc46fd4 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -149,8 +149,8 @@ all::\n # recommended if Git triggers O(n^2) behavior in your platform's qsort().\n #\n # Define NO_EXTERNAL_GREP if you don't want \"git grep\" to ever call\n-# your external grep (e.g., if your system lacks grep, or if its grep is\n-# not very featureful).\n+# your external grep (e.g., if your system lacks grep, if its grep is\n+# broken, or spawning external process is slower than built-in grep git has).\n \n GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE\n \t@$(SHELL_PATH) ./GIT-VERSION-GEN\n@@ -470,7 +470,6 @@ ifeq ($(uname_O),Cygwin)\n \tNO_STRCASESTR = YesPlease\n \tNO_MEMMEM = YesPlease\n \tNO_SYMLINK_HEAD = YesPlease\n-\tNO_EXTERNAL_GREP = YesPlease\n \tNEEDS_LIBICONV = YesPlease\n \tNO_FAST_WORKING_DIRECTORY = UnfortunatelyYes\n \tNO_TRUSTABLE_FILEMODE = UnfortunatelyYes\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex f215b28..ef29910 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -12,6 +12,14 @@\n #include \"builtin.h\"\n #include \"grep.h\"\n \n+#ifndef NO_EXTERNAL_GREP\n+#ifdef __unix__\n+#define NO_EXTERNAL_GREP 0\n+#else\n+#define NO_EXTERNAL_GREP 1\n+#endif\n+#endif\n+\n /*\n  * git grep pathspecs are somewhat different from diff-tree pathspecs;\n  * pathname wildcards are allowed.\n@@ -153,7 +161,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)\n \treturn i;\n }\n \n-#ifndef NO_EXTERNAL_GREP\n+#if !NO_EXTERNAL_GREP\n static int exec_grep(int argc, const char **argv)\n {\n \tpid_t pid;\n@@ -372,7 +380,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)\n \tint nr;\n \tread_cache();\n \n-#ifndef NO_EXTERNAL_GREP\n+#if !NO_EXTERNAL_GREP\n \t/*\n \t * Use the external \"grep\" command for the case where\n \t * we grep through the checked-out files. It tends to\n"},{"id":"71909","messageId":"20080313082807.GT10103@mail-vs.djpig.de","threadId":"12657","inReplyTo":"20080312213106.GD26286@coredump.intra.peff.net","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Frank Lichtenheld","fromEmail":"frank@lichtenheld.de","sentAt":"2008-03-13T08:28:07Z","receivedAt":"2008-03-13T08:28:07Z","isPatch":true,"sender":{"key":"frank@lichtenheld.de","avatar":"https://gravatar.com/avatar/b9f1d4b120e138f157c9e480d0818197c474628923786adb98f30017cdb99c3c?d=mp&s=160"},"body":"On Wed, Mar 12, 2008 at 05:31:06PM -0400, Jeff King wrote:\n> --- a/t/diff-lib.sh\n> +++ b/t/diff-lib.sh\n> @@ -21,8 +21,8 @@ compare_diff_raw_z () {\n>      # Also we do not check SHA1 hash generation in this test, which\n>      # is a job for t0000-basic.sh\n>  \n> -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n\nIt might make sense performance-wise to integrate the job of the sed call into the perl\ncall here. Haven't tested it, though.\n\nGruesse,\n-- \nFrank Lichtenheld <frank@lichtenheld.de>\nwww: http://www.djpig.de/\n"},{"id":"71921","messageId":"20080313120821.GA19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7vmyp34mn6.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 06/16] add test_cmp function for test scripts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:08:21Z","receivedAt":"2008-03-13T12:08:21Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 03:12:45PM -0700, Junio C Hamano wrote:\n\n> I think I have an earlier round of this in 'pu'.\n\nOops, so you do. I remember discussing it but didn't recall a patch\ncoming out of it.\n\nI see you have queued mine now in pu over yours. I actually think yours\nlooks a little nicer (you sanity-check the comparator, and you are more\ncareful with stdin (something that I considered, but figured we could\nadd if something actually broke)).\n\nAny reason not to keep your existing one over mine?\n\n-Peff\n"},{"id":"71922","messageId":"20080313121000.GB19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7viqzr4lua.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:10:00Z","receivedAt":"2008-03-13T12:10:00Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 03:30:05PM -0700, Junio C Hamano wrote:\n\n> Perhaps place\n> \n>     #ifndef NO_EXTERNAL_GREP\n>     #ifndef __unix__\n>     #define NO_EXTERNAL_GREP 1\n>     #else\n>     #define NO_EXTERNAL_GREP 0\n>     #endif\n>     #endif\n> \n> in git-compat-util.h, and make the in-code reference to\n> \n>     #if NO_EXTERNAL_GREP\n>             ... optimization using external grep ...\n>     #endif\n\nI agree that is much nicer. Looks like you have already marked it up in\npu; what is there looks sane.\n\n-Peff\n"},{"id":"71924","messageId":"20080313124103.GC19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47D8DCC0.9090303@viscovery.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:41:03Z","receivedAt":"2008-03-13T12:41:03Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 08:50:24AM +0100, Johannes Sixt wrote:\n\n> > This might have fallouts for msysgit (i.e., they need to define\n> > NO_EXTERNAL_GREP instead of relying on __unix__ not being defined).\n> \n> You name it. Would you mind converting exec_grep() to use run_command(),\n> too? Or better inline it since it won't do a lot more than run_command()?\n> That way we at least won't get a broken git when I merge git.git that has\n> this patch.\n\nJunio's fixups should restore the automagic behavior, so you shouldn't\nsee any problems now, I think. But the run_command cleanup is sensible.\n\nThis is on top of what Junio has in pu.\n\n-- >8 --\nuse run_command for external grep\n\nThe behavior should be identical, but there's no good reason\nnot to use our abstraction library.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n builtin-grep.c |   32 ++++----------------------------\n 1 files changed, 4 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex ef29910..44d9bac 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -11,6 +11,7 @@\n #include \"tree-walk.h\"\n #include \"builtin.h\"\n #include \"grep.h\"\n+#include \"run-command.h\"\n \n #ifndef NO_EXTERNAL_GREP\n #ifdef __unix__\n@@ -162,32 +163,6 @@ static int grep_file(struct grep_opt *opt, const char *filename)\n }\n \n #if !NO_EXTERNAL_GREP\n-static int exec_grep(int argc, const char **argv)\n-{\n-\tpid_t pid;\n-\tint status;\n-\n-\targv[argc] = NULL;\n-\tpid = fork();\n-\tif (pid < 0)\n-\t\treturn pid;\n-\tif (!pid) {\n-\t\texecvp(\"grep\", (char **) argv);\n-\t\texit(255);\n-\t}\n-\twhile (waitpid(pid, &status, 0) < 0) {\n-\t\tif (errno == EINTR)\n-\t\t\tcontinue;\n-\t\treturn -1;\n-\t}\n-\tif (WIFEXITED(status)) {\n-\t\tif (!WEXITSTATUS(status))\n-\t\t\treturn 1;\n-\t\treturn 0;\n-\t}\n-\treturn -1;\n-}\n-\n #define MAXARGS 1000\n #define ARGBUF 4096\n #define push_arg(a) do { \\\n@@ -253,7 +228,8 @@ static int flush_grep(struct grep_opt *opt,\n \t\targc -= 2;\n \t}\n \n-\tstatus = exec_grep(argc, argv);\n+\targv[argc] = NULL;\n+\tstatus = run_command_v_opt(argv, 0);\n \n \tif (kept_0) {\n \t\t/*\n@@ -264,7 +240,7 @@ static int flush_grep(struct grep_opt *opt,\n \t\targv[arg0++] = kept_0;\n \t\targv[arg0] = argv[argc+1];\n \t}\n-\treturn status;\n+\treturn status == 0 ? 1 : -1;\n }\n \n static int external_grep(struct grep_opt *opt, const char **paths, int cached)\n-- \n1.5.4.4.553.g83e84.dirty\n"},{"id":"71925","messageId":"20080313124250.GD19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7vejaf4lmc.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 11/16] config: add --literal-match option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:42:50Z","receivedAt":"2008-03-13T12:42:50Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 03:34:51PM -0700, Junio C Hamano wrote:\n\n> > The patch is about twice as long as it needs to be since getting and\n> > setting in builtin-config follow two almost-the-same parallel codepaths.\n> > I suspect this could be cleaned up, but I didn't look too closely.\n> \n> I think that is a good new feature to propose.\n> \n> Historically, the config_set_multivar() function has been one of the most\n> buggy part of the then-current codebase.  It might be a good idea to\n> clean-up first and then enhance.\n> \n> But in either case I am quite reluctant to touch this part of the code\n> right now before 1.5.5, especially without extra sets of eyeballs.\n\nThat sounds sensible. I will throw this on the backburner until\npost-1.5.5, then, and try to respin it with some config cleanups.\n\n-Peff\n"},{"id":"71926","messageId":"20080313124614.GE19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7vabl34lc0.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 12/16] git-submodule: avoid sed input with no newline","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:46:14Z","receivedAt":"2008-03-13T12:46:14Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 03:41:03PM -0700, Junio C Hamano wrote:\n\n> Good use of --literal.\n> \n> But doesn't this make you wonder if \"--literal-match --get-regexp\" is\n> quite a strange combination?  \"Literal\" covers the value part but the key\n> is still regexp (and we do want it to behave that way).  However, maybe we\n> would want to also allow \"give entries whose key is this literal key and\n> whose value matches this regexp\"?\n\ngit config --get?\n\nThe problem is that we are matching on two elements: key and value. The\nmatching style of the key element is chosen by --get versus\n--get-regexp.  However, the value_regex is selected implicitly by its\npresence, so there is no room to modify the flag in the same way.\nPerhaps --literal-value-match or just --literal-value would be a better\nname.\n\n-Peff\n"},{"id":"71928","messageId":"20080313125920.GF19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7vejaf1b0d.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 08/16] t4200: use cut instead of sed","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T12:59:20Z","receivedAt":"2008-03-13T12:59:20Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 09:52:18PM -0700, Junio C Hamano wrote:\n\n> > Some versions of sed (like the one on Solaris) don't like to\n> > match literal tabs, and simply print nothing. Instead, let's\n> > use cut.\n> \n> > -sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR)\n> \n> This is a bit hard to believe.  On one of my ancient Sun box:\n\nAh, sorry. I tested this line by hand, found it didn't work, and\nstupidly jumped to the assumption that it was the literal tab (that\nbeing the only interesting thing in the input).\n\nBut the actual problem is that MERGE_RR lacks a trailing newline. I\ndon't see any code to add newlines, even though it seems possible that\nwe will write out several paths. So I think we need a newline here:\n\ndiff --git a/builtin-rerere.c b/builtin-rerere.c\nindex c607aad..e4a1dc1 100644\n--- a/builtin-rerere.c\n+++ b/builtin-rerere.c\n@@ -58,7 +58,8 @@ static int write_rr(struct path_list *rr, int out_fd)\n \t\tint length = strlen(path) + 1;\n \t\tif (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||\n \t\t    write_in_full(out_fd, \"\\t\", 1) != 1 ||\n-\t\t    write_in_full(out_fd, path, length) != length)\n+\t\t    write_in_full(out_fd, path, length) != length ||\n+\t\t    write_in_full(out_fd, \"\\n\", 1) != 1)\n \t\t\tdie(\"unable to write rerere record\");\n \t}\n \tif (commit_lock_file(&write_lock) != 0)\n\nAnd unless I am missing something, rerere on multiple paths is very\nbroken (but that seems weird, since this code is so old).\n\n-Peff\n"},{"id":"71930","messageId":"20080313130041.GG19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47D8D39C.3070904@users.sourceforge.net","subject":"Re: [PATCH 16/16] t7505: use SHELL_PATH in hook","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T13:00:41Z","receivedAt":"2008-03-13T13:00:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 08:11:24AM +0100, Adam Piatyszek wrote:\n\n>> -cat > \"$HOOK\" <<'EOF'\n>> +echo \"#!$SHELL_PATH\" > \"$HOOK\"\n>> +cat >> \"$HOOK\" <<'EOF'\n>>  #!/bin/sh\n>    ^^^^^^^^^\n> The above line should be removed in my humble opinion.\n\nOops, yes. I did delete it, but then accidentally editor-typo'd it back\ninto existence. Good eyes.\n\n-Peff\n"},{"id":"71932","messageId":"20080313130625.GH19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47D8D895.4030309@viscovery.net","subject":"Re: [PATCH 01/16] tr portability fixes","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T13:06:25Z","receivedAt":"2008-03-13T13:06:25Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 08:32:37AM +0100, Johannes Sixt wrote:\n\n> > However, this doesn't work with multiple sequences, like:\n> > \n> >   # rot13\n> >   tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]'\n> \n> Not that it matters a lot, but I wonder whether\n> \n>    tr '[A-M][N-Z][a-m][n-z]' '[N-Z][A-M][n-z][a-m]'\n> \n> would have done the trick.\n\nFor the record, it does on Solaris (and I really can't imagine it _not_\nworking anywhere else, but then I couldn't imagine my example not\nworking, either. ;) ).\n\n-Peff\n"},{"id":"71933","messageId":"20080313130918.GI19485@coredump.intra.peff.net","threadId":"12657","inReplyTo":"20080313082807.GT10103@mail-vs.djpig.de","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T13:09:18Z","receivedAt":"2008-03-13T13:09:18Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 09:28:07AM +0100, Frank Lichtenheld wrote:\n\n> > -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> > +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> \n> It might make sense performance-wise to integrate the job of the sed\n> call into the perl call here. Haven't tested it, though.\n\nProbably. My changes were pretty mechanical, and I tried to keep them as\nsmall as possible.\n\nI'm not sure we care too much about an extra fork in a test script for\nperformance, though it would probably end up more readable.\n\n-Peff\n"},{"id":"71935","messageId":"20080313132419.GA28564@coredump.intra.peff.net","threadId":"12657","inReplyTo":"fr9ivq$eh0$1@ger.gmane.org","subject":"Re: [PATCH 11/16] config: add --literal-match option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T13:24:19Z","receivedAt":"2008-03-13T13:24:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Mar 12, 2008 at 10:46:43PM +0100, Jakub Narebski wrote:\n\n> > +--literal-match::\n> > +\n> > +       Some invocations of git-config will limit their actions based on\n> > +       matching a config value to a regular expression. If this option\n> > +       is used, then any such matches are done as a string comparison\n> > +       rather than as a regular expression match.\n> > +\n> \n> Why this option is not named --fixed-strings, as everywhere else, then?\n\nBecause I never use --fixed-strings anywhere else and didn't think of\nit? :)\n\nI think, though, that there is a key difference, and using that name\nwould lead to confusion. In grep, --fixed-strings means \"find this fixed\n_substring_ within the input\" whereas this option means \"find the value\nthat is byte-for-byte equal to this.\"\n\n-Peff\n"},{"id":"71943","messageId":"47D9332C.4020904@viscovery.net","threadId":"12657","inReplyTo":"20080313124103.GC19485@coredump.intra.peff.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-13T13:59:08Z","receivedAt":"2008-03-13T13:59:08Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> Junio's fixups should restore the automagic behavior, so you shouldn't\n> see any problems now, I think. But the run_command cleanup is sensible.\n\nThanks. But it turns out that things are not /that/ trivial. We better\nlive with Junio's fixup.\n\n> -\twhile (waitpid(pid, &status, 0) < 0) {\n> -\t\tif (errno == EINTR)\n> -\t\t\tcontinue;\n> -\t\treturn -1;\n> -\t}\n> -\tif (WIFEXITED(status)) {\n> -\t\tif (!WEXITSTATUS(status))\n> -\t\t\treturn 1;\n> -\t\treturn 0;\n> -\t}\n> -\treturn -1;\n> -}\n> -\n...\n> +\tstatus = run_command_v_opt(argv, 0);\n...\n> +\treturn status == 0 ? 1 : -1;\n\ngrep can return 0 (success, something found), 1 (nothing found), and other\nvalues for \"real\" failures like usage errors or crashes. This conditional\nthrows the latter two into the same pot, which makes git-grep unable to\ndistinguish \"nothing found\" from failure; cf. the call sites of\nflush_grep(), where want to set the flag 'hit'.\n\n-- Hannes\n"},{"id":"71945","messageId":"20080313140415.GB30348@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47D9332C.4020904@viscovery.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-13T14:04:15Z","receivedAt":"2008-03-13T14:04:15Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 02:59:08PM +0100, Johannes Sixt wrote:\n\n> > +\tstatus = run_command_v_opt(argv, 0);\n> ...\n> > +\treturn status == 0 ? 1 : -1;\n> \n> grep can return 0 (success, something found), 1 (nothing found), and other\n> values for \"real\" failures like usage errors or crashes. This conditional\n> throws the latter two into the same pot, which makes git-grep unable to\n> distinguish \"nothing found\" from failure; cf. the call sites of\n> flush_grep(), where want to set the flag 'hit'.\n\nI noticed that, as well, while writing it. But if you look at\nexternal_grep, it just lumps the two cases together anyway. It only ever\ncompares \"0 < status\", so I think the behavior should be identical.\n\nWhich isn't to say that the code couldn't be _improved_ by noting grep\nfailures and crashes, but I don't think it is any worse.\n\n-Peff\n"},{"id":"71946","messageId":"47D935B4.2070504@viscovery.net","threadId":"12657","inReplyTo":"20080313140415.GB30348@coredump.intra.peff.net","subject":"Re: [PATCH 10/16] add NO_EXTERNAL_GREP build option","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-03-13T14:09:56Z","receivedAt":"2008-03-13T14:09:56Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Jeff King schrieb:\n> On Thu, Mar 13, 2008 at 02:59:08PM +0100, Johannes Sixt wrote:\n> \n>>> +\tstatus = run_command_v_opt(argv, 0);\n>> ...\n>>> +\treturn status == 0 ? 1 : -1;\n>> grep can return 0 (success, something found), 1 (nothing found), and other\n>> values for \"real\" failures like usage errors or crashes. This conditional\n>> throws the latter two into the same pot, which makes git-grep unable to\n>> distinguish \"nothing found\" from failure; cf. the call sites of\n>> flush_grep(), where want to set the flag 'hit'.\n> \n> I noticed that, as well, while writing it. But if you look at\n> external_grep, it just lumps the two cases together anyway. It only ever\n> compares \"0 < status\", so I think the behavior should be identical.\n\nYes, indeed. I missed that status < 0 is not checked for.\n\n-- Hannes\n"},{"id":"71974","messageId":"7vtzjay05k.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080313125920.GF19485@coredump.intra.peff.net","subject":"Re: [PATCH 08/16] t4200: use cut instead of sed","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-13T18:00:23Z","receivedAt":"2008-03-13T18:00:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> But the actual problem is that MERGE_RR lacks a trailing newline. I\n> don't see any code to add newlines, even though it seems possible that\n> we will write out several paths. So I think we need a newline here:\n>\n> diff --git a/builtin-rerere.c b/builtin-rerere.c\n> index c607aad..e4a1dc1 100644\n> --- a/builtin-rerere.c\n> +++ b/builtin-rerere.c\n> @@ -58,7 +58,8 @@ static int write_rr(struct path_list *rr, int out_fd)\n>  \t\tint length = strlen(path) + 1;\n>  \t\tif (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||\n>  \t\t    write_in_full(out_fd, \"\\t\", 1) != 1 ||\n> -\t\t    write_in_full(out_fd, path, length) != length)\n> +\t\t    write_in_full(out_fd, path, length) != length ||\n> +\t\t    write_in_full(out_fd, \"\\n\", 1) != 1)\n>  \t\t\tdie(\"unable to write rerere record\");\n>  \t}\n>  \tif (commit_lock_file(&write_lock) != 0)\n\nNo, check 3f43d72392b6c0477debd7edbd49bae9b7f41e60^:git-rerere.perl; the\nrecords in this file are supposed to be NUL terminated (the paths are\nallowed to have LF in them).\n\n> And unless I am missing something, rerere on multiple paths is very\n> broken (but that seems weird, since this code is so old).\n\nI do not recall offhand an example of multi-path rerere working or not\nworking correctly, but I am not surprised if the C re-implementation is\nbroken.  Will need to check.\n"},{"id":"71992","messageId":"7v63vqxsd8.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080313120821.GA19485@coredump.intra.peff.net","subject":"Re: [PATCH 06/16] add test_cmp function for test scripts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-13T20:48:35Z","receivedAt":"2008-03-13T20:48:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Wed, Mar 12, 2008 at 03:12:45PM -0700, Junio C Hamano wrote:\n>\n>> I think I have an earlier round of this in 'pu'.\n>\n> Oops, so you do. I remember discussing it but didn't recall a patch\n> coming out of it.\n>\n> I see you have queued mine now in pu over yours. I actually think yours\n> looks a little nicer (you sanity-check the comparator, and you are more\n> careful with stdin (something that I considered, but figured we could\n> add if something actually broke)).\n>\n> Any reason not to keep your existing one over mine?\n\nYours is much simpler.\n\nAnd it is tested on the field, so if it ever breaks I have somebody else\nto blame ;-)\n"},{"id":"72136","messageId":"47DAE469.7080409@nrlssc.navy.mil","threadId":"12657","inReplyTo":"20080312213831.GJ26286@coredump.intra.peff.net","subject":"[PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2008-03-14T20:47:37Z","receivedAt":"2008-03-14T20:47:37Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Some versions of tr have a problem with character sets which begin with\nmultiple dashes and attempt to interpret them as long options. Use the\n'--' notation to signal the end of command line options.\n\nSigned-off-by: Brandon Casey <casey@nrlssc.navy.mil>\n---\n\n\nJeff King wrote:\n> Some versions of tr complain if the number of characters in\n> both sets isn't the same. So here we must manually expand\n> the dashes in set2.\n> \n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n> This almost makes me want to just use sed instead. But quoting that line\n> noise would probably make it less readable.\n\nI get the following error on t6002-rev-list-bisect.sh:\n\n*   ok 31: bisection diff --bisect u3 ^U <= 0\n*   ok 32: bisection diff --bisect u4 ^U <= 0\n*   ok 33: bisection diff --bisect u5 ^U <= 0\ntr: unrecognized option `------------------------------'\nTry `tr --help' for more information.\n* FAIL 34: --bisect l5 ^root\n        check_output  \"git rev-list $_bisect_option l5 ^root\"\ntr: unrecognized option `------------------------------'\nTry `tr --help' for more information.\n* FAIL 35: --bisect l5 ^root ^c3\n...\n\n\nThis is tr version 5.2.1.\n\nThis patch fixes things. If the dashdash notation is not portable, then\nbackslashing each dash also works. i.e. '\\-\\-\\-\\-.. etc. but as you\nmentioned something like that is less readable, but possibly not as bad\nas a sed version.\n\n-brandon\n\n\n t/t6000lib.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t6000lib.sh b/t/t6000lib.sh\nindex b69f7c4..aac6a31 100755\n--- a/t/t6000lib.sh\n+++ b/t/t6000lib.sh\n@@ -98,7 +98,7 @@ check_output()\n name_from_description()\n {\n         tr \"'\" '-' |\n-\t\ttr '~`!@#$%^&*()_+={}[]|\\;:\"<>,/? ' \\\n+\t\ttr -- '~`!@#$%^&*()_+={}[]|\\;:\"<>,/? ' \\\n \t\t   '------------------------------' |\n \t\ttr -s '-' | tr '[A-Z]' '[a-z]' | sed \"s/^-*//;s/-*\\$//\"\n }\n-- \n1.5.4.4.481.g5075\n"},{"id":"72137","messageId":"20080314205415.GA17728@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47DAE469.7080409@nrlssc.navy.mil","subject":"Re: [PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-14T20:54:15Z","receivedAt":"2008-03-14T20:54:15Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 14, 2008 at 03:47:37PM -0500, Brandon Casey wrote:\n\n> This patch fixes things. If the dashdash notation is not portable, then\n> backslashing each dash also works. i.e. '\\-\\-\\-\\-.. etc. but as you\n> mentioned something like that is less readable, but possibly not as bad\n> as a sed version.\n\nIt seems to work fine on Solaris with all versions of tr. I did just\nblindly extend the '-' without thinking, though...I wonder if there are\nsystems that will get confused about it being a range. It might be\nsafer to just use sed anyway.\n\n-Peff\n"},{"id":"72139","messageId":"47DAE78B.6050602@nrlssc.navy.mil","threadId":"12657","inReplyTo":"20080314205415.GA17728@coredump.intra.peff.net","subject":"Re: [PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2008-03-14T21:00:59Z","receivedAt":"2008-03-14T21:00:59Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Jeff King wrote:\n> On Fri, Mar 14, 2008 at 03:47:37PM -0500, Brandon Casey wrote:\n>> If the dashdash notation is not portable, then\n>> backslashing each dash also works. i.e. '\\-\\-\\-\\-..\n\n> I wonder if there are\n> systems that will get confused about it being a range.\n\nOh, now I understand _why_ backslashing the dashes worked. When your\nemail arrived I was still trying to figure out why\n\n  echo hello | tr aeiou '\\-\\-\\-\\-\\-'\n\ncorrectly converted the e and o into dashes. Because tr must have a\nway for the user to escape the range notation. I don't use tr very\noften.\n\n-brandon\n"},{"id":"72142","messageId":"47DAED87.1000408@nrlssc.navy.mil","threadId":"12657","inReplyTo":"20080314205415.GA17728@coredump.intra.peff.net","subject":"[PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2008-03-14T21:26:31Z","receivedAt":"2008-03-14T21:26:31Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Some versions of tr have a problem with character sets which begin with\nmultiple dashes and attempt to interpret them as long options. Escape\neach dash to avoid this confusion and also prevent a possible\ninterpretation of the dashes as a range.\n\nSigned-off-by: Brandon Casey <casey@nrlssc.navy.mil>\n---\n\nJeff King wrote:\n> On Fri, Mar 14, 2008 at 03:47:37PM -0500, Brandon Casey wrote:\n> \n>> This patch fixes things. If the dashdash notation is not portable, then\n>> backslashing each dash also works. i.e. '\\-\\-\\-\\-.. etc. but as you\n>> mentioned something like that is less readable, but possibly not as bad\n>> as a sed version.\n> \n> It seems to work fine on Solaris with all versions of tr. I did just\n> blindly extend the '-' without thinking, though...I wonder if there are\n> systems that will get confused about it being a range. It might be\n> safer to just use sed anyway.\n\nHere's the version with escaped dashes. If you do the sed version, it's\nsomething to compare to for readability.\n\n-brandon\n\n\n t/t6000lib.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t6000lib.sh b/t/t6000lib.sh\nindex b69f7c4..71f2140 100755\n--- a/t/t6000lib.sh\n+++ b/t/t6000lib.sh\n@@ -99,7 +99,7 @@ name_from_description()\n {\n         tr \"'\" '-' |\n \t\ttr '~`!@#$%^&*()_+={}[]|\\;:\"<>,/? ' \\\n-\t\t   '------------------------------' |\n+\t\t   '\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-' |\n \t\ttr -s '-' | tr '[A-Z]' '[a-z]' | sed \"s/^-*//;s/-*\\$//\"\n }\n \n-- \n1.5.4.4.481.g5075\n"},{"id":"72144","messageId":"20080314214000.GA15093@coredump.intra.peff.net","threadId":"12657","inReplyTo":"7vtzjay05k.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 08/16] t4200: use cut instead of sed","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-14T21:40:00Z","receivedAt":"2008-03-14T21:40:00Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Mar 13, 2008 at 11:00:23AM -0700, Junio C Hamano wrote:\n\n> > index c607aad..e4a1dc1 100644\n> > --- a/builtin-rerere.c\n> > +++ b/builtin-rerere.c\n> > @@ -58,7 +58,8 @@ static int write_rr(struct path_list *rr, int out_fd)\n> >  \t\tint length = strlen(path) + 1;\n> >  \t\tif (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||\n> >  \t\t    write_in_full(out_fd, \"\\t\", 1) != 1 ||\n> > -\t\t    write_in_full(out_fd, path, length) != length)\n> > +\t\t    write_in_full(out_fd, path, length) != length ||\n> > +\t\t    write_in_full(out_fd, \"\\n\", 1) != 1)\n> >  \t\t\tdie(\"unable to write rerere record\");\n> >  \t}\n> >  \tif (commit_lock_file(&write_lock) != 0)\n> \n> No, check 3f43d72392b6c0477debd7edbd49bae9b7f41e60^:git-rerere.perl; the\n> records in this file are supposed to be NUL terminated (the paths are\n> allowed to have LF in them).\n\nAh, OK. And it actually does do that correctly (\"length = strlen(path) +\n1\"). So I think there isn't a bug there in rerere.\n\nBut if it's NUL-terminated, then using sed _definitely_ isn't portable\nhere. cut does work on Solaris in this case, but that might or might not\nbe portable to other systems with similar NUL problems. I'm not sure\nwhat is the best route. We really just want to grab the sha1 from the\nbeginning of the first line. dd count=40? :)\n\n-Peff\n"},{"id":"72145","messageId":"20080314214550.GA18326@coredump.intra.peff.net","threadId":"12657","inReplyTo":"47DAED87.1000408@nrlssc.navy.mil","subject":"Re: [PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-14T21:45:50Z","receivedAt":"2008-03-14T21:45:50Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 14, 2008 at 04:26:31PM -0500, Brandon Casey wrote:\n\n> Here's the version with escaped dashes. If you do the sed version, it's\n> something to compare to for readability.\n>\n> [...]\n>\n> -\t\t   '------------------------------' |\n> +\t\t   '\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-' |\n\nUgh. How about:\n\n  sed 'yA~`!@#$%^&*()_+={}[]|\\;:\"<>,/? A------------------------------A'\n\nThe 'A' delimiter is because in my test, Solaris sed didn't seem to\nunderstand \\/ to include the literal '/'. And all of the other\npunctuation is already used in the pattern. ;)\n\n-Peff\n"},{"id":"72149","messageId":"47DAF6D2.7050808@nrlssc.navy.mil","threadId":"12657","inReplyTo":"20080314214550.GA18326@coredump.intra.peff.net","subject":"Re: [PATCH] t/t6000lib.sh: tr portability fix fix","fromName":"Brandon Casey","fromEmail":"casey@nrlssc.navy.mil","sentAt":"2008-03-14T22:06:10Z","receivedAt":"2008-03-14T22:06:10Z","isPatch":true,"sender":{"key":"drafnel@gmail.com","avatar":"https://avatars.githubusercontent.com/u/921167?v=4"},"body":"Jeff King wrote:\n> On Fri, Mar 14, 2008 at 04:26:31PM -0500, Brandon Casey wrote:\n> \n>> Here's the version with escaped dashes. If you do the sed version, it's\n>> something to compare to for readability.\n>>\n>> [...]\n>>\n>> -\t\t   '------------------------------' |\n>> +\t\t   '\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-' |\n> \n> Ugh. How about:\n> \n>   sed 'yA~`!@#$%^&*()_+={}[]|\\;:\"<>,/? A------------------------------A'\n\nNot working. I get:\n\n*   ok 33: bisection diff --bisect u5 ^U <= 0\nsed: -e expression #1, char 64: unterminated `y' command\n* FAIL 34: --bisect l5 ^root\n        check_output  \"git rev-list $_bisect_option l5 ^root\"\nsed: -e expression #1, char 64: unterminated `y' command\n* FAIL 35: --bisect l5 ^root ^c3\n        check_output  \"git rev-list $_bisect_option l5 ^root ^c3\"\nsed: -e expression #1, char 64: unterminated `y' command\n* FAIL 36: --bisect l5 ^root ^c3 ^b4\n\n\nBut this does:\n\nsed 'yA~`!@#$%^&*()_+={}\\[]|\\\\;:\"<>,/? A------------------------------A'\n\nI have to escape open bracket and backslash on my end (linux). :(\n\nHave to leave now, so if that doesn't work for you (which I'm thinking it\nwon't), I won't be able to test on my end for a while.\n\n-brandon\n"},{"id":"72433","messageId":"20080318222302.GA3450@steel.home","threadId":"12657","inReplyTo":"20080312213106.GD26286@coredump.intra.peff.net","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-03-18T22:23:02Z","receivedAt":"2008-03-18T22:23:02Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Jeff King, Wed, Mar 12, 2008 22:31:06 +0100:\n> -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n\nThese break in presence of ActiveState Perl on Windows.\n\nI suggest replacing such simple construction with a simplified,\nin-tree, version of tr.\n\nPatches follow\n"},{"id":"72434","messageId":"20080318222428.GB3450@steel.home","threadId":"12657","inReplyTo":"20080318222302.GA3450@steel.home","subject":"[PATCH] Add test-tr: poor-man tr for the test suite","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-03-18T22:24:28Z","receivedAt":"2008-03-18T22:24:28Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"It offers a limited set of POSIX tr, in particular: no character class\nsupport and no [n*m] operators. Only 8bit. C-escapes supported, and\ncharacter ranges. Deletion and squeezing should work, but -s does not\nmatch what the GNU tr from coreutils (which, in turn, does not match\nSuSv2).\n\nSigned-off-by: Alex Riesen <raa.lkml@gmail.com>\n---\n\n Makefile              |    2 +-\n t/t0000-test-progs.sh |   72 +++++++++++++++\n test-tr.c             |  236 +++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 309 insertions(+), 1 deletions(-)\n create mode 100755 t/t0000-test-progs.sh\n create mode 100644 test-tr.c\n\ndiff --git a/Makefile b/Makefile\nindex 7c70b00..a458c30 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1177,7 +1177,7 @@ endif\n \n ### Testing rules\n \n-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X\n+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X test-tr$X\n \n all:: $(TEST_PROGRAMS)\n \ndiff --git a/t/t0000-test-progs.sh b/t/t0000-test-progs.sh\nnew file mode 100755\nindex 0000000..d8d339a\n--- /dev/null\n+++ b/t/t0000-test-progs.sh\n@@ -0,0 +1,72 @@\n+#!/bin/sh\n+\n+test_description='Test the test support programs for sanity'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'test-tr character range' '\n+\n+\techo def >expected &&\n+\techo abc | test-tr a-c d-f >result &&\n+\tcmp expected result &&\n+\n+\tprintf def >expected &&\n+\tprintf def | test-tr a-c d-f >result &&\n+\tcmp expected result\n+\n+\tprintf def >expected &&\n+\tprintf abc | test-tr \\\\141-\\\\143 \\\\144-\\\\146 >result &&\n+\tcmp expected result\n+\n+\tprintf \\\\r\\\\n >expected &&\n+\tprintf \\\\r\\\\n | test-tr rn \\\\r\\\\n >result &&\n+\tcmp expected result\n+\n+\tprintf \\\\000\\\\n >expected &&\n+\tprintf 0n | test-tr 0n \\\\000\\\\n >result &&\n+\tcmp expected result\n+\n+\tprintf 0n >expected &&\n+\tprintf \\\\000\\\\n | test-tr \\\\000\\\\n 0n >result &&\n+\tcmp expected result &&\n+\n+\techo nopqrstuvwxyzbcdefghklm >expected &&\n+\techo abcdefghijklmopqrstuxyz | test-tr A-Za-z N-ZA-Mn-za-m >result &&\n+\tcmp expected result\n+'\n+\n+test_expect_success 'test-tr delete characters' '\n+\n+\techo ac >expected &&\n+\techo abc | test-tr -d b >result &&\n+\tcmp expected result &&\n+\n+\techo abcghijk >expected &&\n+\techo abcdefghijk | test-tr -d d-f >result &&\n+\tcmp expected result\n+\n+'\n+\n+test_expect_success 'test-tr squeeze repeating characters' '\n+\n+\techo abc >expected &&\n+\techo abbbbc | test-tr -s b >result &&\n+\tcmp expected result &&\n+\n+\techo def >expected &&\n+\techo abbbbc | test-tr -s a-c d-f >result &&\n+\tcmp expected result\n+\n+'\n+\n+test_expect_success 'test-tr sanity' '\n+\n+\ttest_must_fail test-tr -d a-z A-Z &&\n+\ttest_must_fail test-tr \\\\477 a &&\n+\ttest_must_fail test-tr z-a a &&\n+\ttest_must_fail test-tr a-z \"\" &&\n+\ttest_must_fail test-tr a-z\n+\n+'\n+\n+test_done\ndiff --git a/test-tr.c b/test-tr.c\nnew file mode 100644\nindex 0000000..477ae16\n--- /dev/null\n+++ b/test-tr.c\n@@ -0,0 +1,236 @@\n+/*\n+ *  Simplified tr\n+ *\n+ *  Supports:\n+ *\n+ *  CHAR1-CHAR2\n+ *  Escape sequences\n+ *  -d (delete)\n+ *  -s (squeeze)\n+ *\n+ *  No unicode\n+ *  No characters classes\n+ *  No -c (complement) support\n+ *  Behavior of \"-s -d\" not tested (never used in tests)\n+ *\n+ *  Squeeze of of repeating characters follows the behavior\n+ *  described in the Single Unix Specification (as good as I\n+ *  understand it), not what tr does (it squeezes every character\n+ *  found in set1 OR set2, whereas the SuS says:\n+ *\n+ *  \"When the -s option is specified, after any deletions or\n+ *  translations have taken place, repeated sequences of the same\n+ *  character will be replaced by one occurrence of the same\n+ *  character, if the character is found in the array specified by the\n+ *  last operand.\"\n+ *\n+ *  So this tr squeezes only characters matched the set1.\n+ *\n+ */\n+#include \"cache.h\"\n+\n+static int squeeze, delete;\n+\n+static unsigned char *unquote(const char *s, unsigned *len)\n+{\n+\tunsigned char *result = malloc(strlen(s)), *r = result;\n+\n+\twhile (*s) {\n+\t\tswitch (*s) {\n+\t\tcase '\\\\':\n+\t\t\t++s;\n+#define ISOCT(c) (((c) >= '0' && (c) <= '7'))\n+\t\t\tif (ISOCT(*s)) {\n+\t\t\t\tunsigned int c;\n+\t\t\t\tchar oct[4] = {0, 0, 0, 0};\n+\t\t\t\toct[0] = *s++;\n+\t\t\t\tc = (oct[0] - '0');\n+\t\t\t\tif (ISOCT(*s)) {\n+\t\t\t\t\toct[1] = *s++;\n+\t\t\t\t\tc = (c << 3) |(oct[1] - '0');\n+\t\t\t\t\tif (ISOCT(*s)) {\n+\t\t\t\t\t\toct[2] = *s++;\n+\t\t\t\t\t\tc = (c << 3) |(oct[2] - '0');\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tif (c > 255) {\n+\t\t\t\t\tfprintf(stderr, \"invalid octal character specification: \\\\%s\\n\", oct);\n+\t\t\t\t\texit(1);\n+\t\t\t\t}\n+\t\t\t\t*r++ = c & 0xff;\n+\t\t\t} else {\n+\t\t\t\tswitch (*s) {\n+\t\t\t\tcase '\\0':\n+\t\t\t\t\t*r++ = '\\\\';\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase '\\\\':\n+\t\t\t\t\t*r++ = *s++;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'a':\n+\t\t\t\t\t*r++ = '\\a';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'b':\n+\t\t\t\t\t*r++ = '\\b';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'f':\n+\t\t\t\t\t*r++ = '\\f';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'n':\n+\t\t\t\t\t*r++ = '\\n';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'r':\n+\t\t\t\t\t*r++ = '\\r';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 't':\n+\t\t\t\t\t*r++ = '\\t';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase 'v':\n+\t\t\t\t\t*r++ = '\\v';\n+\t\t\t\t\t++s;\n+\t\t\t\t\tbreak;\n+\t\t\t\tdefault:\n+\t\t\t\t\t*r++ = '\\\\';\n+\t\t\t\t\t*r++ = *s++;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\t*r++ = *s++;\n+\t\t}\n+\t}\n+\n+\t*len = r - result;\n+\t*r = '\\0';\n+\treturn result;\n+}\n+\n+#define MAX_PATTERN 256\n+static void put_ch(unsigned char *conv, unsigned char ch, unsigned *len)\n+{\n+\tunsigned i = (*len)++;\n+\tif (*len > MAX_PATTERN) {\n+\t\tfprintf(stderr, \"pattern too long\\n\");\n+\t\texit(1);\n+\t}\n+\tconv[i] = ch;\n+}\n+\n+static void parse(const unsigned char *rule, unsigned rule_len,\n+\t\t  unsigned char *set, unsigned *set_len)\n+{\n+\tconst unsigned char *p = rule;\n+\twhile (p < rule + rule_len) {\n+\t\tif ('-' == *p && p > rule && p[1]) {\n+\t\t\tunsigned c;\n+\t\t\tif (p[-1] > p[1]) {\n+\t\t\t\tfprintf(stderr, \"%c%c%c: range is reversed\\n\",\n+\t\t\t\t\tp[-1], *p, p[1]);\n+\t\t\t\texit(1);\n+\t\t\t}\n+\t\t\tc = p[-1] + 1u;\n+\t\t\tfor (; c <= p[1]; ++c)\n+\t\t\t\tput_ch(set, c, set_len);\n+\t\t\t++p;\n+\t\t\t++p;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tput_ch(set, *p, set_len);\n+\t\t++p;\n+\t}\n+}\n+\n+int main(int argc, char *argv[])\n+{\n+\tunsigned set1_len = 0, set2_len = 0;\n+\tunsigned char set1[MAX_PATTERN];\n+\tunsigned char set2[MAX_PATTERN];\n+\n+\tssize_t n;\n+\tunsigned char last = 0, have_last = 0;\n+\tunsigned char buf[BUFSIZ];\n+\n+\tchar *rule1 = NULL, *rule2 = NULL;\n+\tunsigned char *urule1, *urule2;\n+\tunsigned urule1_len, urule2_len;\n+\tint opt;\n+\n+\tfor (opt = 1; opt < argc; ++opt) {\n+\t\tif (!strcmp(\"-s\", argv[opt]))\n+\t\t\tsqueeze = 1;\n+\t\telse if (!strcmp(\"-d\", argv[opt]))\n+\t\t\tdelete = 1;\n+\t\telse if (!rule1) {\n+\t\t\trule1 = argv[opt];\n+\t\t} else if (!rule2)\n+\t\t\trule2 = argv[opt];\n+\t}\n+\tif (!rule1) {\n+\t    fprintf(stderr, \"no source set given\\n\"\n+\t\t    \"test-tr [-s] [-d] set1 [set2]\\n\"\n+\t\t    \"\\\"set\\\" supports only \\\\NNN, \\\\a-\\\\v and CHAR1-CHAR2 rules\\n\");\n+\t    exit(1);\n+\t}\n+\tif (delete && rule2) {\n+\t\tfprintf(stderr, \"extra operand %s when deleting\\n\", rule2);\n+\t\texit(1);\n+\t}\n+\turule1 = unquote(rule1, &urule1_len);\n+\turule2 = NULL;\n+\turule2_len = 0;\n+\tif ((!rule2 || !*rule2) && !delete && !squeeze) {\n+\t\tfprintf(stderr, \"set2 must be non-empty\\n\");\n+\t\texit(1);\n+\t}\n+\n+\tparse(urule1, urule1_len, set1, &set1_len);\n+\n+\tif (rule2) {\n+\t\tunsigned i;\n+\t\turule2 = unquote(rule2, &urule2_len);\n+\t\tparse(urule2, urule2_len, set2, &set2_len);\n+\t\ti = set2[set2_len - 1];\n+\t\twhile (set2_len < set1_len)\n+\t\t\tput_ch(set2, i, &set2_len);\n+\t}\n+\n+\twhile ((n = read(STDIN_FILENO, buf, sizeof(buf)))) {\n+\t\tif (n < 0) {\n+\t\t\tint err = errno;\n+\t\t\tif (EINTR == err || EAGAIN == err)\n+\t\t\t\tcontinue;\n+\t\t\tfprintf(stderr, \"%s: %s\\n\", argv[0], strerror(err));\n+\t\t\texit(1);\n+\t\t}\n+\t\tif (set1_len) {\n+\t\t\tunsigned i, o = 0;\n+\t\t\tfor (i = 0; i < (unsigned)n; ++i) {\n+\t\t\t\tunsigned char *p, ch = buf[i];\n+\t\t\t\tp = memchr(set1, ch, set1_len);\n+\t\t\t\tif (p) {\n+\t\t\t\t\tif (delete)\n+\t\t\t\t\t\tcontinue;\n+\t\t\t\t\tif (set2_len)\n+\t\t\t\t\t\tch = set2[p - set1];\n+\t\t\t\t\tif (!(squeeze &&\n+\t\t\t\t\t      have_last &&\n+\t\t\t\t\t      ch == last))\n+\t\t\t\t\t\tbuf[o++] = ch;\n+\t\t\t\t} else\n+\t\t\t\t\tbuf[o++] = ch;\n+\n+\t\t\t\thave_last = 1;\n+\t\t\t\tlast = ch;\n+\t\t\t}\n+\t\t\tn = o;\n+\t\t}\n+\t\twrite(STDOUT_FILENO, buf, n);\n+\t}\n+\treturn 0;\n+}\n-- \n1.5.5.rc0.53.g97734\n"},{"id":"72436","messageId":"20080318222459.GC3450@steel.home","threadId":"12657","inReplyTo":"20080318222428.GB3450@steel.home","subject":"[PATCH] Use test-tr in the test suite","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-03-18T22:24:59Z","receivedAt":"2008-03-18T22:24:59Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Signed-off-by: Alex Riesen <raa.lkml@gmail.com>\n---\n t/annotate-tests.sh            |    4 ++--\n t/diff-lib.sh                  |    4 ++--\n t/t0000-basic.sh               |    2 +-\n t/t0020-crlf.sh                |   10 +++++-----\n t/t0021-conversion.sh          |    2 +-\n t/t1300-repo-config.sh         |    4 ++--\n t/t3300-funny-names.sh         |    6 +++---\n t/t3402-rebase-merge.sh        |    4 ++--\n t/t4004-diff-rename-symlink.sh |    2 +-\n t/t4015-diff-whitespace.sh     |    6 +++---\n t/t4019-diff-wserror.sh        |    2 +-\n t/t4020-diff-external.sh       |    2 +-\n t/t4022-diff-rewrite.sh        |    2 +-\n t/t4101-apply-nonl.sh          |    4 ++--\n t/t4103-apply-binary.sh        |    4 ++--\n t/t4116-apply-reverse.sh       |    4 ++--\n t/t4118-apply-empty-context.sh |    4 ++--\n t/t4200-rerere.sh              |    2 +-\n t/t4201-shortlog.sh            |    4 ++--\n t/t5300-pack-object.sh         |    2 +-\n t/t5500-fetch-pack.sh          |    2 +-\n t/t5505-remote.sh              |    4 ++--\n t/t6003-rev-list-topo-order.sh |    2 +-\n t/t7003-filter-branch.sh       |    2 +-\n t/t9200-git-cvsexportcommit.sh |    2 +-\n t/test-lib.sh                  |   12 +++++++-----\n 26 files changed, 50 insertions(+), 48 deletions(-)\n\ndiff --git a/t/annotate-tests.sh b/t/annotate-tests.sh\nindex cacb273..8e10323 100644\n--- a/t/annotate-tests.sh\n+++ b/t/annotate-tests.sh\n@@ -104,7 +104,7 @@ test_expect_success \\\n \n test_expect_success \\\n     'an incomplete line added' \\\n-    'echo \"incomplete\" | tr -d \"\\\\012\" >>file &&\n+    'echo \"incomplete\" | test-tr -d \"\\\\012\" >>file &&\n     GIT_AUTHOR_NAME=\"C\" git commit -a -m \"Incomplete\"'\n \n test_expect_success \\\n@@ -115,7 +115,7 @@ test_expect_success \\\n     'some edit' \\\n     'mv file file.orig &&\n     sed -e \"s/^3A/99/\" -e \"/^1A/d\" -e \"/^incomplete/d\" < file.orig > file &&\n-    echo \"incomplete\" | tr -d \"\\\\012\" >>file &&\n+    echo \"incomplete\" | test-tr -d \"\\\\012\" >>file &&\n     GIT_AUTHOR_NAME=\"D\" git commit -a -m \"edit\"'\n \n test_expect_success \\\ndiff --git a/t/diff-lib.sh b/t/diff-lib.sh\nindex 28b941c..257e123 100644\n--- a/t/diff-lib.sh\n+++ b/t/diff-lib.sh\n@@ -21,8 +21,8 @@ compare_diff_raw_z () {\n     # Also we do not check SHA1 hash generation in this test, which\n     # is a job for t0000-basic.sh\n \n-    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n-    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n+    test-tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n+    test-tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n     git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2\n }\n \ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex 27b54cb..a1f60eb 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -324,7 +324,7 @@ test_expect_success 'very long name in the index handled sanely' '\n \t(\n \t\tgit ls-files -s path4 |\n \t\tsed -e \"s/\t.*/\t/\" |\n-\t\ttr -d \"\\012\"\n+\t\ttest-tr -d \"\\012\"\n \t\techo \"$a\"\n \t) | git update-index --index-info &&\n \tlen=$(git ls-files \"a*\" | wc -c) &&\ndiff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh\nindex 2bfeac9..7427d59 100755\n--- a/t/t0020-crlf.sh\n+++ b/t/t0020-crlf.sh\n@@ -5,20 +5,20 @@ test_description='CRLF conversion'\n . ./test-lib.sh\n \n q_to_nul () {\n-\tperl -pe 'y/Q/\\000/'\n+\ttest-tr Q '\\000'\n }\n \n q_to_cr () {\n-\ttr Q '\\015'\n+\ttest-tr Q '\\015'\n }\n \n append_cr () {\n-\tsed -e 's/$/Q/' | tr Q '\\015'\n+\tsed -e 's/$/Q/' | test-tr Q '\\015'\n }\n \n remove_cr () {\n-\ttr '\\015' Q <\"$1\" | grep Q >/dev/null &&\n-\ttr '\\015' Q <\"$1\" | sed -ne 's/Q$//p'\n+\ttest-tr '\\015' Q <\"$1\" | grep Q >/dev/null &&\n+\ttest-tr '\\015' Q <\"$1\" | sed -ne 's/Q$//p'\n }\n \n test_expect_success setup '\ndiff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh\nindex 8fc39d7..d146db4 100755\n--- a/t/t0021-conversion.sh\n+++ b/t/t0021-conversion.sh\n@@ -5,7 +5,7 @@ test_description='blob conversion via gitattributes'\n . ./test-lib.sh\n \n cat <<\\EOF >rot13.sh\n-tr \\\n+test-tr \\\n   'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \\\n   'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'\n EOF\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex b36a901..42c3f15 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -657,12 +657,12 @@ Qsection.sub=section.val4\n Qsection.sub=section.val5Q\n EOF\n \n-git config --null --list | perl -pe 'y/\\000/Q/' > result\n+git config --null --list | test-tr '\\000' Q > result\n echo >>result\n \n test_expect_success '--null --list' 'cmp result expect'\n \n-git config --null --get-regexp 'val[0-9]' | perl -pe 'y/\\000/Q/' > result\n+git config --null --get-regexp 'val[0-9]' | test-tr '\\000' Q > result\n echo >>result\n \n test_expect_success '--null --get-regexp' 'cmp result expect'\ndiff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh\nindex 24a00a9..10c5217 100755\n--- a/t/t3300-funny-names.sh\n+++ b/t/t3300-funny-names.sh\n@@ -54,7 +54,7 @@ echo 'just space\n no-funny\n tabs\t,\" (dq) and spaces' >expected\n test_expect_success 'git ls-files -z with-funny' \\\n-\t'git ls-files -z | perl -pe y/\\\\000/\\\\012/ >current &&\n+\t'git ls-files -z | test-tr \"\\000\" \"\\012\" >current &&\n \tgit diff expected current'\n \n t1=`git write-tree`\n@@ -83,11 +83,11 @@ test_expect_success 'git diff-tree with-funny' \\\n echo 'A\n tabs\t,\" (dq) and spaces' >expected\n test_expect_success 'git diff-index -z with-funny' \\\n-\t'git diff-index -z --name-status $t0 | perl -pe y/\\\\000/\\\\012/ >current &&\n+\t'git diff-index -z --name-status $t0 | test-tr \"\\000\" \"\\012\" >current &&\n \tgit diff expected current'\n \n test_expect_success 'git diff-tree -z with-funny' \\\n-\t'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\\\000/\\\\012/ >current &&\n+\t'git diff-tree -z --name-status $t0 $t1 | test-tr \"\\000\" \"\\012\" >current &&\n \tgit diff expected current'\n \n cat > expected <<\\EOF\ndiff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh\nindex 7b7d072..704f9a3 100755\n--- a/t/t3402-rebase-merge.sh\n+++ b/t/t3402-rebase-merge.sh\n@@ -30,11 +30,11 @@ test_expect_success setup '\n \tgit update-index --force-remove original &&\n \tgit commit -a -m\"side renames and edits.\" &&\n \n-\ttr \"[a-z]\" \"[A-Z]\" <original >newfile &&\n+\ttest-tr a-z A-Z <original >newfile &&\n \tgit add newfile &&\n \tgit commit -a -m\"side edits further.\" &&\n \n-\ttr \"[a-m]\" \"[A-M]\" <original >newfile &&\n+\ttest-tr a-m A-M <original >newfile &&\n \trm -f original &&\n \tgit commit -a -m\"side edits once again.\" &&\n \ndiff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh\nindex 3d25be7..b49efa4 100755\n--- a/t/t4004-diff-rename-symlink.sh\n+++ b/t/t4004-diff-rename-symlink.sh\n@@ -14,7 +14,7 @@ by an edit for them.\n \n test_expect_success \\\n     'prepare reference tree' \\\n-    'echo xyzzy | tr -d '\\\\\\\\'012 >yomin &&\n+    'echo xyzzy | test-tr -d \"\\012\" >yomin &&\n      ln -s xyzzy frotz &&\n     git update-index --add frotz yomin &&\n     tree=$(git write-tree) &&\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 83c54b7..595c5e2 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -51,7 +51,7 @@ test_expect_success \"Ray's example with -w\" 'git diff expect out'\n git diff -b > out\n test_expect_success \"Ray's example with -b\" 'git diff expect out'\n \n-tr 'Q' '\\015' << EOF > x\n+test-tr 'Q' '\\015' << EOF > x\n whitespace at beginning\n whitespace change\n whitespace in the middle\n@@ -71,7 +71,7 @@ unchanged line\n CR at end\n EOF\n \n-tr 'Q' '\\015' << EOF > expect\n+test-tr 'Q' '\\015' << EOF > expect\n diff --git a/x b/x\n index d99af23..8b32fb5 100644\n --- a/x\n@@ -99,7 +99,7 @@ EOF\n git diff -w > out\n test_expect_success 'another test, with -w' 'git diff expect out'\n \n-tr 'Q' '\\015' << EOF > expect\n+test-tr 'Q' '\\015' << EOF > expect\n diff --git a/x b/x\n index d99af23..8b32fb5 100644\n --- a/x\ndiff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh\nindex 0d9cbb6..4967026 100755\n--- a/t/t4019-diff-wserror.sh\n+++ b/t/t4019-diff-wserror.sh\n@@ -12,7 +12,7 @@ test_expect_success setup '\n \techo \"         Eight SP indent\" >>F &&\n \techo \" \tHT and SP indent\" >>F &&\n \techo \"With trailing SP \" >>F &&\n-\techo \"Carriage ReturnQ\" | tr Q \"\\015\" >>F &&\n+\techo \"Carriage ReturnQ\" | test-tr Q \"\\015\" >>F &&\n \techo \"No problem\" >>F\n \n '\ndiff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh\nindex 637b4e1..3ae3165 100755\n--- a/t/t4020-diff-external.sh\n+++ b/t/t4020-diff-external.sh\n@@ -99,7 +99,7 @@ test_expect_success 'no diff with -diff' '\n \tgit diff | grep Binary\n '\n \n-echo NULZbetweenZwords | perl -pe 'y/Z/\\000/' > file\n+echo NULZbetweenZwords | test-tr 'Z' '\\000' > file\n \n test_expect_success 'force diff with \"diff\"' '\n \techo >.gitattributes \"file diff\" &&\ndiff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh\nindex bf996fc..01d221b 100755\n--- a/t/t4022-diff-rewrite.sh\n+++ b/t/t4022-diff-rewrite.sh\n@@ -8,7 +8,7 @@ test_expect_success setup '\n \n \tcat ../../COPYING >test &&\n \tgit add test &&\n-\ttr \\\n+\ttest-tr \\\n \t  \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n \t  \"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM\" \\\n \t  <../../COPYING >test\ndiff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh\nindex da8abcf..53277e6 100755\n--- a/t/t4101-apply-nonl.sh\n+++ b/t/t4101-apply-nonl.sh\n@@ -12,8 +12,8 @@ test_description='git apply should handle files with incomplete lines.\n \n (echo a; echo b) >frotz.0\n (echo a; echo b; echo c) >frotz.1\n-(echo a; echo b | tr -d '\\012') >frotz.2\n-(echo a; echo c; echo b | tr -d '\\012') >frotz.3\n+(echo a; echo b | test-tr -d '\\012') >frotz.2\n+(echo a; echo c; echo b | test-tr -d '\\012') >frotz.3\n \n for i in 0 1 2 3\n do\ndiff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh\nindex 1b58233..f7542a0 100755\n--- a/t/t4103-apply-binary.sh\n+++ b/t/t4103-apply-binary.sh\n@@ -24,10 +24,10 @@ git update-index --add --remove file1 file2 file4\n git-commit -m 'Initial Version' 2>/dev/null\n \n git-checkout -b binary\n-perl -pe 'y/x/\\000/' <file1 >file3\n+test-tr x '\\000' <file1 >file3\n cat file3 >file4\n git add file2\n-perl -pe 'y/\\000/v/' <file3 >file1\n+test-tr '\\000' v <file3 >file1\n rm -f file2\n git update-index --add --remove file1 file2 file3 file4\n git-commit -m 'Second Version'\ndiff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh\nindex c3f4579..bf01619 100755\n--- a/t/t4116-apply-reverse.sh\n+++ b/t/t4116-apply-reverse.sh\n@@ -12,14 +12,14 @@ test_description='git apply in reverse\n test_expect_success setup '\n \n \tfor i in a b c d e f g h i j k l m n; do echo $i; done >file1 &&\n-\tperl -pe \"y/ijk/\\\\000\\\\001\\\\002/\" <file1 >file2 &&\n+\ttest-tr \"ijk\" \"\\000\\001\\002\" <file1 >file2 &&\n \n \tgit add file1 file2 &&\n \tgit commit -m initial &&\n \tgit tag initial &&\n \n \tfor i in a b c g h i J K L m o n p q; do echo $i; done >file1 &&\n-\tperl -pe \"y/mon/\\\\000\\\\001\\\\002/\" <file1 >file2 &&\n+\ttest-tr \"mon\" \"\\000\\001\\002\" <file1 >file2 &&\n \n \tgit commit -a -m second &&\n \tgit tag second &&\ndiff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh\nindex 1d531ca..5083100 100755\n--- a/t/t4118-apply-empty-context.sh\n+++ b/t/t4118-apply-empty-context.sh\n@@ -18,13 +18,13 @@ test_expect_success setup '\n \tcat file1 >file1.orig &&\n \t{\n \t\tcat file1 &&\n-\t\techo Q | tr -d \"\\\\012\"\n+\t\techo Q | test-tr -d \"\\012\"\n \t} >file2 &&\n \tcat file2 >file2.orig\n \tgit add file1 file2 &&\n \tsed -e \"/^B/d\" <file1.orig >file1 &&\n \tsed -e \"/^[BQ]/d\" <file2.orig >file2 &&\n-\techo Q | tr -d \"\\\\012\" >>file2 &&\n+\techo Q | test-tr -d \"\\012\" >>file2 &&\n \tcat file1 >file1.mods &&\n \tcat file2 >file2.mods &&\n \tgit diff |\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex 3cbfee7..58fc740 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -129,7 +129,7 @@ test_expect_success 'rerere kicked in' \"! grep ======= a1\"\n test_expect_success 'rerere prefers first change' 'git diff a1 expect'\n \n rm $rr/postimage\n-echo \"$sha1\ta1\" | perl -pe 'y/\\012/\\000/' > .git/rr-cache/MERGE_RR\n+echo \"$sha1\ta1\" | test-tr '\\012' '\\000' > .git/rr-cache/MERGE_RR\n \n test_expect_success 'rerere clear' 'git rerere clear'\n \ndiff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh\nindex 405b971..1a4b88d 100755\n--- a/t/t4201-shortlog.sh\n+++ b/t/t4201-shortlog.sh\n@@ -19,12 +19,12 @@ git commit --quiet -m \"This is a very, very long first line for the commit messa\n \n # test if the wrapping is still valid when replacing all i's by treble clefs.\n echo 3 > a1\n-git commit --quiet -m \"$(echo \"This is a very, very long first line for the commit message to see if it is wrapped correctly\" | sed \"s/i/1234/g\" | tr 1234 '\\360\\235\\204\\236')\" a1\n+git commit --quiet -m \"$(echo \"This is a very, very long first line for the commit message to see if it is wrapped correctly\" | sed \"s/i/1234/g\" | test-tr 1234 '\\360\\235\\204\\236')\" a1\n \n # now fsck up the utf8\n git config i18n.commitencoding non-utf-8\n echo 4 > a1\n-git commit --quiet -m \"$(echo \"This is a very, very long first line for the commit message to see if it is wrapped correctly\" | sed \"s/i/1234/g\" | tr 1234 '\\370\\235\\204\\236')\" a1\n+git commit --quiet -m \"$(echo \"This is a very, very long first line for the commit message to see if it is wrapped correctly\" | sed \"s/i/1234/g\" | test-tr 1234 '\\370\\235\\204\\236')\" a1\n \n echo 5 > a1\n git commit --quiet -m \"a\t\t\t\t\t\t\t\t12\t34\t56\t78\" a1\ndiff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh\nindex c955fe4..ba49742 100755\n--- a/t/t5300-pack-object.sh\n+++ b/t/t5300-pack-object.sh\n@@ -15,7 +15,7 @@ test_expect_success \\\n     'rm -f .git/index*\n      for i in a b c\n      do\n-\t     dd if=/dev/zero bs=4k count=1 | perl -pe \"y/\\\\000/$i/\" >$i &&\n+\t     dd if=/dev/zero bs=4k count=1 | test-tr \"\\000\" \"$i\" >$i &&\n \t     git update-index --add $i || return 1\n      done &&\n      cat c >d && echo foo >>d && git update-index --add d &&\ndiff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh\nindex 788b4a5..cda09b5 100755\n--- a/t/t5500-fetch-pack.sh\n+++ b/t/t5500-fetch-pack.sh\n@@ -37,7 +37,7 @@ add () {\n }\n \n count_objects () {\n-\tls .git/objects/??/* 2>>log2.txt | wc -l | tr -d \" \"\n+\tls .git/objects/??/* 2>>log2.txt | wc -l | test-tr -d \" \"\n }\n \n test_expect_object_count () {\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex ecfc999..89f06b2 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -22,8 +22,8 @@ setup_repository () {\n }\n \n tokens_match () {\n-\techo \"$1\" | tr ' ' '\\012' | sort | sed -e '/^$/d' >expect &&\n-\techo \"$2\" | tr ' ' '\\012' | sort | sed -e '/^$/d' >actual &&\n+\techo \"$1\" | test-tr ' ' '\\012' | sort | sed -e '/^$/d' >expect &&\n+\techo \"$2\" | test-tr ' ' '\\012' | sort | sed -e '/^$/d' >actual &&\n \ttest_cmp expect actual\n }\n \ndiff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh\nindex 5daa0be..5dbc6a7 100755\n--- a/t/t6003-rev-list-topo-order.sh\n+++ b/t/t6003-rev-list-topo-order.sh\n@@ -79,7 +79,7 @@ save_tag g4 unique_commit g6 tree -p g3 -p h2\n \n git update-ref HEAD $(tag l5)\n \n-test_output_expect_success 'rev-list has correct number of entries' 'git rev-list HEAD | wc -l | tr -d \\\" \\\"' <<EOF\n+test_output_expect_success 'rev-list has correct number of entries' 'git rev-list HEAD | wc -l | test-tr -d \\\" \\\"' <<EOF\n 19\n EOF\n \ndiff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh\nindex 553131f..5c9bd2b 100755\n--- a/t/t7003-filter-branch.sh\n+++ b/t/t7003-filter-branch.sh\n@@ -4,7 +4,7 @@ test_description='git-filter-branch'\n . ./test-lib.sh\n \n make_commit () {\n-\tlower=$(echo $1 | tr '[A-Z]' '[a-z]')\n+\tlower=$(echo $1 | test-tr 'A-Z' 'a-z')\n \techo $lower > $lower\n \tgit add $lower\n \ttest_tick\ndiff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh\nindex 42b144b..6b4358c 100755\n--- a/t/t9200-git-cvsexportcommit.sh\n+++ b/t/t9200-git-cvsexportcommit.sh\n@@ -35,7 +35,7 @@ check_entries () {\n \tthen\n \t\t>expected\n \telse\n-\t\tprintf '%s\\n' \"$2\" | tr '|' '\\012' >expected\n+\t\tprintf '%s\\n' \"$2\" | test-tr '|' '\\012' >expected\n \tfi\n \ttest_cmp expected actual\n }\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 268b26c..4c7bf9a 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -44,11 +44,16 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME\n export EDITOR VISUAL\n GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}\n \n+# Test the binaries we have just built.  The tests are kept in\n+# t/ subdirectory and are run in trash subdirectory.\n+PATH=$(pwd)/..:$PATH\n+export PATH\n+\n # Protect ourselves from common misconfiguration to export\n # CDPATH into the environment\n unset CDPATH\n \n-case $(echo $GIT_TRACE |tr \"[A-Z]\" \"[a-z]\") in\n+case $(echo $GIT_TRACE |test-tr A-Z a-z) in\n \t1|2|true)\n \t\techo \"* warning: Some tests will not work if GIT_TRACE\" \\\n \t\t\t\"is set as to trace on STDERR ! *\"\n@@ -369,16 +374,13 @@ test_done () {\n \tesac\n }\n \n-# Test the binaries we have just built.  The tests are kept in\n-# t/ subdirectory and are run in trash subdirectory.\n-PATH=$(pwd)/..:$PATH\n GIT_EXEC_PATH=$(pwd)/..\n GIT_TEMPLATE_DIR=$(pwd)/../templates/blt\n unset GIT_CONFIG\n unset GIT_CONFIG_LOCAL\n GIT_CONFIG_NOSYSTEM=1\n GIT_CONFIG_NOGLOBAL=1\n-export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL\n+export GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL\n \n GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git\n export GITPERLLIB\n-- \n1.5.5.rc0.53.g97734\n"},{"id":"72393","messageId":"20080318224436.GA6806@coredump.intra.peff.net","threadId":"12657","inReplyTo":"20080318222302.GA3450@steel.home","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-03-18T22:44:37Z","receivedAt":"2008-03-18T22:44:37Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Mar 18, 2008 at 11:23:02PM +0100, Alex Riesen wrote:\n\n> Jeff King, Wed, Mar 12, 2008 22:31:06 +0100:\n> > -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> > +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> \n> These break in presence of ActiveState Perl on Windows.\n> \n> I suggest replacing such simple construction with a simplified,\n> in-tree, version of tr.\n\n<sigh> It's sad that it must come to that, but your test-tr patches seem\nlike the only sane choice. They seem to work fine on my Solaris box.\n\nNote that there are still a few uses of 'tr' in actual git scripts.\nHowever, they are pretty tame, so I think they should work everywhere.\nOtherwise, test-tr must become \"git tr\". :)\n\n-Peff\n"},{"id":"72378","messageId":"20080318232453.GE3450@steel.home","threadId":"12657","inReplyTo":"20080318224436.GA6806@coredump.intra.peff.net","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-03-18T23:24:53Z","receivedAt":"2008-03-18T23:24:53Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Jeff King, Tue, Mar 18, 2008 23:44:37 +0100:\n> On Tue, Mar 18, 2008 at 11:23:02PM +0100, Alex Riesen wrote:\n> \n> > Jeff King, Wed, Mar 12, 2008 22:31:06 +0100:\n> > > -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > > -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> > > +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> > > +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> > \n> > These break in presence of ActiveState Perl on Windows.\n> > \n> > I suggest replacing such simple construction with a simplified,\n> > in-tree, version of tr.\n> \n> <sigh> It's sad that it must come to that, but your test-tr patches seem\n> like the only sane choice. They seem to work fine on my Solaris box.\n> \n> Note that there are still a few uses of 'tr' in actual git scripts.\n> However, they are pretty tame, so I think they should work everywhere.\n\nYes, I thought about them too and hope for the same (they'll do).\n\n> Otherwise, test-tr must become \"git tr\". :)\n\nWe already use \"git diff\" and \"git apply\" as reliable \"diff\" and\n\"patch\" :)\n"},{"id":"72416","messageId":"7v8x0e2xzq.fsf@gitster.siamese.dyndns.org","threadId":"12657","inReplyTo":"20080318224436.GA6806@coredump.intra.peff.net","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-19T21:40:57Z","receivedAt":"2008-03-19T21:40:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Tue, Mar 18, 2008 at 11:23:02PM +0100, Alex Riesen wrote:\n>\n>> Jeff King, Wed, Mar 12, 2008 22:31:06 +0100:\n>> > -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n>> > -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n>> > +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n>> > +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n>> \n>> These break in presence of ActiveState Perl on Windows.\n>> \n>> I suggest replacing such simple construction with a simplified,\n>> in-tree, version of tr.\n>\n> <sigh> It's sad that it must come to that, but your test-tr patches seem\n> like the only sane choice. They seem to work fine on my Solaris box.\n\nI am very tempted to say that it might make more sense to declare\nActiveState unsupported.  How many times have we suffered from it, and\nnotice it was only from Alex every time, nobody else?  Are there silent\nmajorities involved here?\n"},{"id":"72439","messageId":"20080319225617.GA3139@steel.home","threadId":"12657","inReplyTo":"7v8x0e2xzq.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 03/16] more tr portability test script fixes","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-03-19T22:56:17Z","receivedAt":"2008-03-19T22:56:17Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Junio C Hamano, Wed, Mar 19, 2008 22:40:57 +0100:\n> Jeff King <peff@peff.net> writes:\n> \n> > On Tue, Mar 18, 2008 at 11:23:02PM +0100, Alex Riesen wrote:\n> >\n> >> Jeff King, Wed, Mar 12, 2008 22:31:06 +0100:\n> >> > -    tr '\\000' '\\012' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> >> > -    tr '\\000' '\\012' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> >> > +    perl -pe 'y/\\000/\\012/' <\"$1\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-1\n> >> > +    perl -pe 'y/\\000/\\012/' <\"$2\" | sed -e \"$sanitize_diff_raw_z\" >.tmp-2\n> >> \n> >> These break in presence of ActiveState Perl on Windows.\n> >> \n> >> I suggest replacing such simple construction with a simplified,\n> >> in-tree, version of tr.\n> >\n> > <sigh> It's sad that it must come to that, but your test-tr patches seem\n> > like the only sane choice. They seem to work fine on my Solaris box.\n> \n> I am very tempted to say that it might make more sense to declare\n> ActiveState unsupported.\n\nI am not asking to really support it, it is too offending a thought.\nI am just asking to consider the patch, which removes another\ndependency on local system. Wasn't there issues with tr already?\n\n> How many times have we suffered from it, and notice it was only from\n> Alex every time, nobody else?\n\nWell, I say that every time. I think by know everyone, who seen a\npatch from me, noticed how very specially stupid my kind of setup is.\n\nBTW, who suffered from what?\n\n> Are there silent majorities involved here?\n\nYeah, the windows-people. They are used to silently workaround their\nsystem.\n"}]}