git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add test-tr: poor-man tr
@ 2008-06-11 18:25 Alex Riesen, Alex Riesen
  2008-06-11 18:26 ` [PATCH] Use test-tr in the tests Alex Riesen
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Alex Riesen, Alex Riesen @ 2008-06-11 18:25 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

It offers a limited set of POSIX tr, in particular: no character class
support and no [n*m] operators. Only 8bit. C-escapes supported, and
character ranges. Deletion and squeezing should work, but -s does not
match the GNU tr from coreutils (which, in turn, does not match POSIX).

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---

Rebased on top of current master. I still think it makes the test
suite more portable.

 Makefile  |    2 +-
 test-tr.c |  206 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 1 deletions(-)
 create mode 100644 test-tr.c

diff --git a/Makefile b/Makefile
index 1937507..5f208d6 100644
--- a/Makefile
+++ b/Makefile
@@ -1229,7 +1229,7 @@ endif
 
 ### Testing rules
 
-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_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
 
 all:: $(TEST_PROGRAMS)
 
diff --git a/test-tr.c b/test-tr.c
new file mode 100644
index 0000000..82af602
--- /dev/null
+++ b/test-tr.c
@@ -0,0 +1,206 @@
+/*
+vim: sw=8
+*/
+#include "cache.h"
+
+static int squeeze, delete;
+
+static unsigned char *unquote(const char *s, unsigned *len)
+{
+	unsigned char *result = malloc(strlen(s)), *r = result;
+
+	while (*s) {
+		switch (*s) {
+		case '\\':
+			++s;
+#define ISOCT(c) (((c) >= '0' && (c) <= '7'))
+			if (ISOCT(*s)) {
+				unsigned int c;
+				char oct[4] = {0,0,0,0};
+				oct[0] = *s++;
+				c = (oct[0] - '0');
+				if (ISOCT(*s)) {
+					oct[1] = *s++;
+					c = (c << 3) |(oct[1] - '0');
+					if (ISOCT(*s)) {
+						oct[2] = *s++;
+						c = (c << 3) |(oct[2] - '0');
+					}
+				}
+				if (c > 255) {
+					fprintf(stderr, "invalid octal character specification: \\%s\n", oct);
+					exit(1);
+				}
+				*r++ = c & 0xff;
+			} else {
+				switch (*s) {
+				case '\0':
+					*r++ = '\\';
+					break;
+				case '\\':
+					*r++ = *s++;
+					break;
+				case 'a':
+					*r++ = '\a';
+					++s;
+					break;
+				case 'b':
+					*r++ = '\b';
+					++s;
+					break;
+				case 'f':
+					*r++ = '\f';
+					++s;
+					break;
+				case 'n':
+					*r++ = '\n';
+					++s;
+					break;
+				case 'r':
+					*r++ = '\r';
+					++s;
+					break;
+				case 't':
+					*r++ = '\t';
+					++s;
+					break;
+				case 'v':
+					*r++ = '\v';
+					++s;
+					break;
+				default:
+					*r++ = '\\';
+					*r++ = *s++;
+					break;
+				}
+			}
+			break;
+		default:
+			*r++ = *s++;
+		}
+	}
+
+	*len = r - result;
+	*r = '\0';
+	return result;
+}
+
+#define MAX_PATTERN 256
+static void put_op(unsigned char *conv, unsigned char ch, unsigned *len)
+{
+	unsigned i = (*len)++;
+	if (*len > MAX_PATTERN) {
+		fprintf(stderr, "pattern too long\n");
+		exit(1);
+	}
+	conv[i] = ch;
+}
+
+static void parse(const unsigned char *rule, unsigned rule_len,
+		  unsigned char *set, unsigned *set_len)
+{
+	const unsigned char *p = rule;
+	while (p < rule + rule_len) {
+		if ('-' == *p && p > rule && p[1]) {
+			unsigned c;
+			if (p[-1] > p[1]) {
+				fprintf(stderr, "%c%c%c: range is reversed\n",
+					p[-1], *p, p[1]);
+				exit(1);
+			}
+			c = p[-1] + 1u;
+			for (; c <= p[1]; ++c)
+				put_op(set, c, set_len);
+			++p;
+			++p;
+			continue;
+		}
+		put_op(set, *p, set_len);
+		++p;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned set1_len = 0, set2_len = 0;
+	unsigned char set1[MAX_PATTERN];
+	unsigned char set2[MAX_PATTERN];
+
+	ssize_t n;
+	unsigned char last = 0, have_last = 0;
+	unsigned char buf[BUFSIZ];
+
+	char *rule1 = NULL, *rule2 = NULL;
+	unsigned char *urule1, *urule2;
+	unsigned urule1_len, urule2_len;
+	int opt;
+
+	for (opt = 1; opt < argc; ++opt) {
+		if (!strcmp("-s", argv[opt]))
+			squeeze = 1;
+		else if (!strcmp("-d", argv[opt]))
+			delete = 1;
+		else if (!rule1) {
+			rule1 = argv[opt];
+		} else if (!rule2)
+			rule2 = argv[opt];
+	}
+	if (!rule1) {
+	    fprintf(stderr, "no source set given\n"
+		    "test-tr [-s] [-d] set1 [set2]\n"
+		    "\"set\" supports only \\NNN, \\a-\\v and CHAR1-CHAR2 rules\n");
+	    exit(1);
+	}
+	if (delete && rule2) {
+		fprintf(stderr, "extra operand %s when deleting\n", rule2);
+		exit(1);
+	}
+	urule1 = unquote(rule1, &urule1_len);
+	urule2 = NULL;
+	urule2_len = 0;
+	if ((!rule2 || !*rule2) && !delete && !squeeze) {
+		fprintf(stderr, "set2 must be non-empty\n");
+		exit(1);
+	}
+
+	parse(urule1, urule1_len, set1, &set1_len);
+
+	if (rule2) {
+		unsigned i;
+		urule2 = unquote(rule2, &urule2_len);
+		parse(urule2, urule2_len, set2, &set2_len);
+		i = set2[set2_len - 1];
+		while (set2_len < set1_len)
+			put_op(set2, i, &set2_len);
+	}
+
+	while ((n = read(STDIN_FILENO, buf, sizeof(buf)))) {
+		if (n < 0) {
+			int err = errno;
+			if (EINTR == err || EAGAIN == err)
+				continue;
+			fprintf(stderr, "%s: %s\n", argv[0], strerror(err));
+			exit(1);
+		}
+		if (set1_len) {
+			unsigned i, o = 0;
+			for (i = 0; i < (unsigned)n; ++i) {
+				unsigned char *p, ch = buf[i];
+				p = memchr(set1, ch, set1_len);
+				if (p) {
+					if (delete)
+						continue;
+					if (set2_len)
+						ch = set2[p - set1];
+				}
+				if (!(squeeze && have_last && ch == last))
+					buf[o++] = ch;
+				have_last = 1;
+				last = ch;
+			}
+			n = o;
+		}
+		write(STDOUT_FILENO, buf, n);
+	}
+	return 0;
+}
-- 
1.5.6.rc2.57.gc9624

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

* [PATCH] Use test-tr in the tests
  2008-06-11 18:25 [PATCH] Add test-tr: poor-man tr Alex Riesen, Alex Riesen
@ 2008-06-11 18:26 ` Alex Riesen
  2008-06-11 21:34 ` [PATCH] Add test-tr: poor-man tr Alex Riesen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Alex Riesen @ 2008-06-11 18:26 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
 t/annotate-tests.sh            |    4 ++--
 t/diff-lib.sh                  |    4 ++--
 t/t0000-basic.sh               |    2 +-
 t/t0020-crlf.sh                |   10 +++++-----
 t/t0021-conversion.sh          |    2 +-
 t/t1300-repo-config.sh         |    4 ++--
 t/t3300-funny-names.sh         |    6 +++---
 t/t3402-rebase-merge.sh        |    4 ++--
 t/t4004-diff-rename-symlink.sh |    2 +-
 t/t4015-diff-whitespace.sh     |    6 +++---
 t/t4019-diff-wserror.sh        |    2 +-
 t/t4020-diff-external.sh       |    2 +-
 t/t4022-diff-rewrite.sh        |    2 +-
 t/t4101-apply-nonl.sh          |    4 ++--
 t/t4103-apply-binary.sh        |    4 ++--
 t/t4116-apply-reverse.sh       |    4 ++--
 t/t4118-apply-empty-context.sh |    4 ++--
 t/t4200-rerere.sh              |    2 +-
 t/t4201-shortlog.sh            |    4 ++--
 t/t5300-pack-object.sh         |    2 +-
 t/t5500-fetch-pack.sh          |    2 +-
 t/t5505-remote.sh              |    4 ++--
 t/t6003-rev-list-topo-order.sh |    2 +-
 t/t6033-merge-crlf.sh          |    4 ++--
 t/t7003-filter-branch.sh       |    2 +-
 t/t9200-git-cvsexportcommit.sh |    2 +-
 t/t9401-git-cvsserver-crlf.sh  |    4 ++--
 t/test-lib.sh                  |   12 +++++++-----
 28 files changed, 54 insertions(+), 52 deletions(-)

diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index cacb273..8e10323 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -104,7 +104,7 @@ test_expect_success \
 
 test_expect_success \
     'an incomplete line added' \
-    'echo "incomplete" | tr -d "\\012" >>file &&
+    'echo "incomplete" | test-tr -d "\\012" >>file &&
     GIT_AUTHOR_NAME="C" git commit -a -m "Incomplete"'
 
 test_expect_success \
@@ -115,7 +115,7 @@ test_expect_success \
     'some edit' \
     'mv file file.orig &&
     sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" < file.orig > file &&
-    echo "incomplete" | tr -d "\\012" >>file &&
+    echo "incomplete" | test-tr -d "\\012" >>file &&
     GIT_AUTHOR_NAME="D" git commit -a -m "edit"'
 
 test_expect_success \
diff --git a/t/diff-lib.sh b/t/diff-lib.sh
index 4bddeb5..f840340 100644
--- a/t/diff-lib.sh
+++ b/t/diff-lib.sh
@@ -21,8 +21,8 @@ compare_diff_raw_z () {
     # Also we do not check SHA1 hash generation in this test, which
     # is a job for t0000-basic.sh
 
-    perl -pe 'y/\000/\012/' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1
-    perl -pe 'y/\000/\012/' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2
+    test-tr '\000' '\012' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1
+    test-tr '\000' '\012' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2
     test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
 }
 
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 690f80a..ad81546 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -324,7 +324,7 @@ test_expect_success 'very long name in the index handled sanely' '
 	(
 		git ls-files -s path4 |
 		sed -e "s/	.*/	/" |
-		tr -d "\012"
+		test-tr -d "\012"
 		echo "$a"
 	) | git update-index --index-info &&
 	len=$(git ls-files "a*" | wc -c) &&
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 2bfeac9..7427d59 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -5,20 +5,20 @@ test_description='CRLF conversion'
 . ./test-lib.sh
 
 q_to_nul () {
-	perl -pe 'y/Q/\000/'
+	test-tr Q '\000'
 }
 
 q_to_cr () {
-	tr Q '\015'
+	test-tr Q '\015'
 }
 
 append_cr () {
-	sed -e 's/$/Q/' | tr Q '\015'
+	sed -e 's/$/Q/' | test-tr Q '\015'
 }
 
 remove_cr () {
-	tr '\015' Q <"$1" | grep Q >/dev/null &&
-	tr '\015' Q <"$1" | sed -ne 's/Q$//p'
+	test-tr '\015' Q <"$1" | grep Q >/dev/null &&
+	test-tr '\015' Q <"$1" | sed -ne 's/Q$//p'
 }
 
 test_expect_success setup '
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 8fc39d7..d146db4 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -5,7 +5,7 @@ test_description='blob conversion via gitattributes'
 . ./test-lib.sh
 
 cat <<\EOF >rot13.sh
-tr \
+test-tr \
   'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
   'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
 EOF
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index afe7e66..57ba088 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -715,12 +715,12 @@ Qsection.sub=section.val4
 Qsection.sub=section.val5Q
 EOF
 
-git config --null --list | perl -pe 'y/\000/Q/' > result
+git config --null --list | test-tr '\000' Q > result
 echo >>result
 
 test_expect_success '--null --list' 'cmp result expect'
 
-git config --null --get-regexp 'val[0-9]' | perl -pe 'y/\000/Q/' > result
+git config --null --get-regexp 'val[0-9]' | test-tr '\000' Q > result
 echo >>result
 
 test_expect_success '--null --get-regexp' 'cmp result expect'
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index 0574ef1..6ec6c24 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -54,7 +54,7 @@ echo 'just space
 no-funny
 tabs	," (dq) and spaces' >expected
 test_expect_success 'git ls-files -z with-funny' \
-	'git ls-files -z | perl -pe y/\\000/\\012/ >current &&
+	'git ls-files -z | test-tr "\000" "\012" >current &&
 	test_cmp expected current'
 
 t1=`git write-tree`
@@ -83,11 +83,11 @@ test_expect_success 'git diff-tree with-funny' \
 echo 'A
 tabs	," (dq) and spaces' >expected
 test_expect_success 'git diff-index -z with-funny' \
-	'git diff-index -z --name-status $t0 | perl -pe y/\\000/\\012/ >current &&
+	'git diff-index -z --name-status $t0 | test-tr "\000" "\012" >current &&
 	test_cmp expected current'
 
 test_expect_success 'git diff-tree -z with-funny' \
-	'git diff-tree -z --name-status $t0 $t1 | perl -pe y/\\000/\\012/ >current &&
+	'git diff-tree -z --name-status $t0 $t1 | test-tr "\000" "\012" >current &&
 	test_cmp expected current'
 
 cat > expected <<\EOF
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index 7b7d072..704f9a3 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -30,11 +30,11 @@ test_expect_success setup '
 	git update-index --force-remove original &&
 	git commit -a -m"side renames and edits." &&
 
-	tr "[a-z]" "[A-Z]" <original >newfile &&
+	test-tr a-z A-Z <original >newfile &&
 	git add newfile &&
 	git commit -a -m"side edits further." &&
 
-	tr "[a-m]" "[A-M]" <original >newfile &&
+	test-tr a-m A-M <original >newfile &&
 	rm -f original &&
 	git commit -a -m"side edits once again." &&
 
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 3d25be7..b49efa4 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -14,7 +14,7 @@ by an edit for them.
 
 test_expect_success \
     'prepare reference tree' \
-    'echo xyzzy | tr -d '\\\\'012 >yomin &&
+    'echo xyzzy | test-tr -d "\012" >yomin &&
      ln -s xyzzy frotz &&
     git update-index --add frotz yomin &&
     tree=$(git write-tree) &&
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index ca0302f..8841626 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -51,7 +51,7 @@ test_expect_success "Ray's example with -w" 'test_cmp expect out'
 git diff -b > out
 test_expect_success "Ray's example with -b" 'test_cmp expect out'
 
-tr 'Q' '\015' << EOF > x
+test-tr 'Q' '\015' << EOF > x
 whitespace at beginning
 whitespace change
 whitespace in the middle
@@ -71,7 +71,7 @@ unchanged line
 CR at end
 EOF
 
-tr 'Q' '\015' << EOF > expect
+test-tr 'Q' '\015' << EOF > expect
 diff --git a/x b/x
 index d99af23..8b32fb5 100644
 --- a/x
@@ -99,7 +99,7 @@ EOF
 git diff -w > out
 test_expect_success 'another test, with -w' 'test_cmp expect out'
 
-tr 'Q' '\015' << EOF > expect
+test-tr 'Q' '\015' << EOF > expect
 diff --git a/x b/x
 index d99af23..8b32fb5 100644
 --- a/x
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index 0d9cbb6..4967026 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -12,7 +12,7 @@ test_expect_success setup '
 	echo "         Eight SP indent" >>F &&
 	echo " 	HT and SP indent" >>F &&
 	echo "With trailing SP " >>F &&
-	echo "Carriage ReturnQ" | tr Q "\015" >>F &&
+	echo "Carriage ReturnQ" | test-tr Q "\015" >>F &&
 	echo "No problem" >>F
 
 '
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 637b4e1..3ae3165 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -99,7 +99,7 @@ test_expect_success 'no diff with -diff' '
 	git diff | grep Binary
 '
 
-echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
+echo NULZbetweenZwords | test-tr 'Z' '\000' > file
 
 test_expect_success 'force diff with "diff"' '
 	echo >.gitattributes "file diff" &&
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index bf996fc..01d221b 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -8,7 +8,7 @@ test_expect_success setup '
 
 	cat ../../COPYING >test &&
 	git add test &&
-	tr \
+	test-tr \
 	  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
 	  "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
 	  <../../COPYING >test
diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh
index da8abcf..53277e6 100755
--- a/t/t4101-apply-nonl.sh
+++ b/t/t4101-apply-nonl.sh
@@ -12,8 +12,8 @@ test_description='git apply should handle files with incomplete lines.
 
 (echo a; echo b) >frotz.0
 (echo a; echo b; echo c) >frotz.1
-(echo a; echo b | tr -d '\012') >frotz.2
-(echo a; echo c; echo b | tr -d '\012') >frotz.3
+(echo a; echo b | test-tr -d '\012') >frotz.2
+(echo a; echo c; echo b | test-tr -d '\012') >frotz.3
 
 for i in 0 1 2 3
 do
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index 1b58233..f7542a0 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -24,10 +24,10 @@ git update-index --add --remove file1 file2 file4
 git-commit -m 'Initial Version' 2>/dev/null
 
 git-checkout -b binary
-perl -pe 'y/x/\000/' <file1 >file3
+test-tr x '\000' <file1 >file3
 cat file3 >file4
 git add file2
-perl -pe 'y/\000/v/' <file3 >file1
+test-tr '\000' v <file3 >file1
 rm -f file2
 git update-index --add --remove file1 file2 file3 file4
 git-commit -m 'Second Version'
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index 1459a90..31608df 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -12,14 +12,14 @@ test_description='git apply in reverse
 test_expect_success setup '
 
 	for i in a b c d e f g h i j k l m n; do echo $i; done >file1 &&
-	perl -pe "y/ijk/\\000\\001\\002/" <file1 >file2 &&
+	test-tr "ijk" "\000\001\002" <file1 >file2 &&
 
 	git add file1 file2 &&
 	git commit -m initial &&
 	git tag initial &&
 
 	for i in a b c g h i J K L m o n p q; do echo $i; done >file1 &&
-	perl -pe "y/mon/\\000\\001\\002/" <file1 >file2 &&
+	test-tr "mon" "\000\001\002" <file1 >file2 &&
 
 	git commit -a -m second &&
 	git tag second &&
diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh
index f92e259..89e5d14 100755
--- a/t/t4118-apply-empty-context.sh
+++ b/t/t4118-apply-empty-context.sh
@@ -18,13 +18,13 @@ test_expect_success setup '
 	cat file1 >file1.orig &&
 	{
 		cat file1 &&
-		echo Q | tr -d "\\012"
+		echo Q | test-tr -d "\012"
 	} >file2 &&
 	cat file2 >file2.orig
 	git add file1 file2 &&
 	sed -e "/^B/d" <file1.orig >file1 &&
 	sed -e "/^[BQ]/d" <file2.orig >file2 &&
-	echo Q | tr -d "\\012" >>file2 &&
+	echo Q | test-tr -d "\012" >>file2 &&
 	cat file1 >file1.mods &&
 	cat file2 >file2.mods &&
 	git diff |
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 85d7e3e..23b10f2 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -129,7 +129,7 @@ test_expect_success 'rerere kicked in' "! grep ======= a1"
 test_expect_success 'rerere prefers first change' 'test_cmp a1 expect'
 
 rm $rr/postimage
-echo "$sha1	a1" | perl -pe 'y/\012/\000/' > .git/rr-cache/MERGE_RR
+echo "$sha1	a1" | test-tr '\012' '\000' > .git/rr-cache/MERGE_RR
 
 test_expect_success 'rerere clear' 'git rerere clear'
 
diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh
index 405b971..1a4b88d 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -19,12 +19,12 @@ git commit --quiet -m "This is a very, very long first line for the commit messa
 
 # test if the wrapping is still valid when replacing all i's by treble clefs.
 echo 3 > a1
-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
+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
 
 # now fsck up the utf8
 git config i18n.commitencoding non-utf-8
 echo 4 > a1
-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
+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
 
 echo 5 > a1
 git commit --quiet -m "a								12	34	56	78" a1
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 983a393..ebb85a5 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -15,7 +15,7 @@ test_expect_success \
     'rm -f .git/index*
      for i in a b c
      do
-	     dd if=/dev/zero bs=4k count=1 | perl -pe "y/\\000/$i/" >$i &&
+	     dd if=/dev/zero bs=4k count=1 | test-tr "\000" "$i" >$i &&
 	     git update-index --add $i || return 1
      done &&
      cat c >d && echo foo >>d && git update-index --add d &&
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 140e874..784600e 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -37,7 +37,7 @@ add () {
 }
 
 count_objects () {
-	ls .git/objects/??/* 2>>log2.txt | wc -l | tr -d " "
+	ls .git/objects/??/* 2>>log2.txt | wc -l | test-tr -d " "
 }
 
 test_expect_object_count () {
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 0d7ed1f..4c08c81 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -22,8 +22,8 @@ setup_repository () {
 }
 
 tokens_match () {
-	echo "$1" | tr ' ' '\012' | sort | sed -e '/^$/d' >expect &&
-	echo "$2" | tr ' ' '\012' | sort | sed -e '/^$/d' >actual &&
+	echo "$1" | test-tr ' ' '\012' | sort | sed -e '/^$/d' >expect &&
+	echo "$2" | test-tr ' ' '\012' | sort | sed -e '/^$/d' >actual &&
 	test_cmp expect actual
 }
 
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index 5daa0be..5dbc6a7 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -79,7 +79,7 @@ save_tag g4 unique_commit g6 tree -p g3 -p h2
 
 git update-ref HEAD $(tag l5)
 
-test_output_expect_success 'rev-list has correct number of entries' 'git rev-list HEAD | wc -l | tr -d \" \"' <<EOF
+test_output_expect_success 'rev-list has correct number of entries' 'git rev-list HEAD | wc -l | test-tr -d \" \"' <<EOF
 19
 EOF
 
diff --git a/t/t6033-merge-crlf.sh b/t/t6033-merge-crlf.sh
index 75d9602..fed088a 100755
--- a/t/t6033-merge-crlf.sh
+++ b/t/t6033-merge-crlf.sh
@@ -1,11 +1,11 @@
 #!/bin/sh
 
 append_cr () {
-	sed -e 's/$/Q/' | tr Q '\015'
+	sed -e 's/$/Q/' | test-tr Q '\015'
 }
 
 remove_cr () {
-	tr '\015' Q | sed -e 's/Q$//'
+	test-tr '\015' Q | sed -e 's/Q$//'
 }
 
 test_description='merge conflict in crlf repo
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index e26f726..9928863 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -4,7 +4,7 @@ test_description='git-filter-branch'
 . ./test-lib.sh
 
 make_commit () {
-	lower=$(echo $1 | tr '[A-Z]' '[a-z]')
+	lower=$(echo $1 | test-tr 'A-Z' 'a-z')
 	echo $lower > $lower
 	git add $lower
 	test_tick
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index b1dc32d..f84a99c 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -35,7 +35,7 @@ check_entries () {
 	then
 		>expected
 	else
-		printf '%s\n' "$2" | tr '|' '\012' >expected
+		printf '%s\n' "$2" | test-tr '|' '\012' >expected
 	fi
 	test_cmp expected actual
 }
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
index e27a1c5..f5b4d94 100755
--- a/t/t9401-git-cvsserver-crlf.sh
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -12,11 +12,11 @@ repository using cvs CLI client via git-cvsserver server'
 . ./test-lib.sh
 
 q_to_nul () {
-    perl -pe 'y/Q/\000/'
+    test-tr Q '\000'
 }
 
 q_to_cr () {
-    tr Q '\015'
+    test-tr Q '\015'
 }
 
 marked_as () {
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 7a8bd27..c3eb7df 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -44,11 +44,16 @@ export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
 export EDITOR VISUAL
 GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
 
+# Test the binaries we have just built.  The tests are kept in
+# t/ subdirectory and are run in trash subdirectory.
+PATH=$(pwd)/..:$PATH
+export PATH
+
 # Protect ourselves from common misconfiguration to export
 # CDPATH into the environment
 unset CDPATH
 
-case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
+case $(echo $GIT_TRACE |test-tr A-Z a-z) in
 	1|2|true)
 		echo "* warning: Some tests will not work if GIT_TRACE" \
 			"is set as to trace on STDERR ! *"
@@ -385,16 +390,13 @@ test_done () {
 	esac
 }
 
-# Test the binaries we have just built.  The tests are kept in
-# t/ subdirectory and are run in trash subdirectory.
-PATH=$(pwd)/..:$PATH
 GIT_EXEC_PATH=$(pwd)/..
 GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
 unset GIT_CONFIG
 unset GIT_CONFIG_LOCAL
 GIT_CONFIG_NOSYSTEM=1
 GIT_CONFIG_NOGLOBAL=1
-export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
+export GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
 
 GITPERLLIB=$(pwd)/../perl/blib/lib:$(pwd)/../perl/blib/arch/auto/Git
 export GITPERLLIB
-- 
1.5.6.rc2.57.gc9624

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-11 18:25 [PATCH] Add test-tr: poor-man tr Alex Riesen, Alex Riesen
  2008-06-11 18:26 ` [PATCH] Use test-tr in the tests Alex Riesen
@ 2008-06-11 21:34 ` Alex Riesen
  2008-06-11 22:54 ` Jeff King
  2008-06-12  6:32 ` Alf Clement
  3 siblings, 0 replies; 14+ messages in thread
From: Alex Riesen @ 2008-06-11 21:34 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano

Alex Riesen, Wed, Jun 11, 2008 20:25:01 +0200:
> --- /dev/null
> +++ b/test-tr.c
> @@ -0,0 +1,206 @@
> +/*
> +vim: sw=8
> +*/

Sorry about that...

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-11 18:25 [PATCH] Add test-tr: poor-man tr Alex Riesen, Alex Riesen
  2008-06-11 18:26 ` [PATCH] Use test-tr in the tests Alex Riesen
  2008-06-11 21:34 ` [PATCH] Add test-tr: poor-man tr Alex Riesen
@ 2008-06-11 22:54 ` Jeff King
  2008-06-12  6:01   ` Alex Riesen
  2008-06-12  6:32 ` Alf Clement
  3 siblings, 1 reply; 14+ messages in thread
From: Jeff King @ 2008-06-11 22:54 UTC (permalink / raw)
  To: Alex Riesen, Alex Riesen; +Cc: git, Junio C Hamano

On Wed, Jun 11, 2008 at 08:25:01PM +0200, Alex Riesen wrote:

> It offers a limited set of POSIX tr, in particular: no character class
> support and no [n*m] operators. Only 8bit. C-escapes supported, and
> character ranges. Deletion and squeezing should work, but -s does not
> match the GNU tr from coreutils (which, in turn, does not match POSIX).
> 
> Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
> ---
> 
> Rebased on top of current master. I still think it makes the test
> suite more portable.

Having wrestled with Solaris tr, I can understand where you are coming
from. However, does this _actually_ increase the portability of the test
suite? That is, are there failing tests that this fixes, and if so, for
which platforms (getting a successful run of the test suite on Solaris
is still on my long-term todo, but I thought I had fixed all of the tr
issues)?

Or is your rationale "this will prevent people from screwing up the test
scripts accidentally in the future"?

I am not opposed to the latter, but I think it makes sense to state it
clearly in the commit message.

-Peff

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-11 22:54 ` Jeff King
@ 2008-06-12  6:01   ` Alex Riesen
  2008-06-12  6:23     ` Jeff King
  0 siblings, 1 reply; 14+ messages in thread
From: Alex Riesen @ 2008-06-12  6:01 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano

Jeff King, Thu, Jun 12, 2008 00:54:48 +0200:
> On Wed, Jun 11, 2008 at 08:25:01PM +0200, Alex Riesen wrote:
> 
> > It offers a limited set of POSIX tr, in particular: no character class
> > support and no [n*m] operators. Only 8bit. C-escapes supported, and
> > character ranges. Deletion and squeezing should work, but -s does not
> > match the GNU tr from coreutils (which, in turn, does not match POSIX).
> > 
> > Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
> > ---
> > 
> > Rebased on top of current master. I still think it makes the test
> > suite more portable.
> 
> Having wrestled with Solaris tr, I can understand where you are coming
> from. However, does this _actually_ increase the portability of the test
> suite? That is, are there failing tests that this fixes, and if so, for
> which platforms (getting a successful run of the test suite on Solaris
> is still on my long-term todo, but I thought I had fixed all of the tr
> issues)?

Frankly, it started because I wanted to minimize use of Perl on
Windows (because I can't get around ActiveState Perl at work, and it
breaks almost everything it touches). Accidentally, it is also faster
there (maybe just because it's smaller).

But, as was already noted, tr does not behave the same for all
platforms (there were even differences in output, BSD or Solaris put
out a stray LF?).

> Or is your rationale "this will prevent people from screwing up the test
> scripts accidentally in the future"?

We just can't have that. Nothing can prevent people from screwing up
anything in any given point of time :)

In any case, I wont push this change too hard. I must admit, that
there is no real good reason besides one "screwed" company using
obsoleted tools in a weird way. And it is a maintenance effort (and
people will forget to use test-tr instead of perl and tr).
And maybe someday my employment situation improves and I wont push it
at all :)

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-12  6:01   ` Alex Riesen
@ 2008-06-12  6:23     ` Jeff King
  2008-06-12  6:28       ` Jeff King
  2008-06-12 20:32       ` Alex Riesen
  0 siblings, 2 replies; 14+ messages in thread
From: Jeff King @ 2008-06-12  6:23 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano

On Thu, Jun 12, 2008 at 08:01:52AM +0200, Alex Riesen wrote:

> Frankly, it started because I wanted to minimize use of Perl on
> Windows (because I can't get around ActiveState Perl at work, and it
> breaks almost everything it touches). Accidentally, it is also faster
> there (maybe just because it's smaller).

Ah, right. Well, I am not opposed to getting rid of perl in the test
scripts (there is core functionality provided by perl, so one can easily
run git on a system with no perl at all).

However, even with your patch, there is still some perl left, so I am
not sure that it has really bought us very much.

> But, as was already noted, tr does not behave the same for all
> platforms (there were even differences in output, BSD or Solaris put
> out a stray LF?).

I think those were all resolved by using perl, and your patch replaces
them with test-tr.

> > Or is your rationale "this will prevent people from screwing up the test
> > scripts accidentally in the future"?
> We just can't have that. Nothing can prevent people from screwing up
> anything in any given point of time :)

Heh. At least we can yell at them after the fact for not using the
available tool. :)

> In any case, I wont push this change too hard. I must admit, that
> there is no real good reason besides one "screwed" company using
> obsoleted tools in a weird way. And it is a maintenance effort (and
> people will forget to use test-tr instead of perl and tr).

There is maintenance effort either way; people need to know not to do
unportable things with tr (and other tools), and the solution to that is
to run the test scripts on each platform (something we are starting to
do).

So I am not opposed to test-tr, I just wanted you to explain it better
in the commit log. ;)

-Peff

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-12  6:23     ` Jeff King
@ 2008-06-12  6:28       ` Jeff King
  2008-06-12 20:32       ` Alex Riesen
  1 sibling, 0 replies; 14+ messages in thread
From: Jeff King @ 2008-06-12  6:28 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano

On Thu, Jun 12, 2008 at 02:23:09AM -0400, Jeff King wrote:

> Ah, right. Well, I am not opposed to getting rid of perl in the test
> scripts (there is core functionality provided by perl, so one can easily
> run git on a system with no perl at all).

Er, sorry. This should read: "there is _no_ core functionality provide
by perl".

-Peff

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-11 18:25 [PATCH] Add test-tr: poor-man tr Alex Riesen, Alex Riesen
                   ` (2 preceding siblings ...)
  2008-06-11 22:54 ` Jeff King
@ 2008-06-12  6:32 ` Alf Clement
  2008-06-12  7:25   ` Johannes Schindelin
  3 siblings, 1 reply; 14+ messages in thread
From: Alf Clement @ 2008-06-12  6:32 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano

Hi Alex,

> +static unsigned char *unquote(const char *s, unsigned *len)
> +{
> +       unsigned char *result = malloc(strlen(s)), *r = result;

are you sure that the buffer is big enough?? Nomally you do a
malloc(strlen(s)+1).

CU,
Alf

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-12  6:32 ` Alf Clement
@ 2008-06-12  7:25   ` Johannes Schindelin
  2008-06-12 20:20     ` Alex Riesen, Alex Riesen
  0 siblings, 1 reply; 14+ messages in thread
From: Johannes Schindelin @ 2008-06-12  7:25 UTC (permalink / raw)
  To: Alf Clement; +Cc: Alex Riesen, git, Junio C Hamano

Hi,

On Thu, 12 Jun 2008, Alf Clement wrote:

> > +static unsigned char *unquote(const char *s, unsigned *len) +{
> > +       unsigned char *result = malloc(strlen(s)), *r = result;
> 
> are you sure that the buffer is big enough?? Nomally you do a
> malloc(strlen(s)+1).

AFAIU a "tr" really only ever replaces single characters by single 
characters.  So, not even looking at the code -- just like you -- I would 
expect it to get the exact number of bytes read, and to write the same 
number of bytes.

I certainly would not expect it to do something string based, introducing 
a silly expectation of NUL-terminations (which tr(1) does not expect 
either).

Ciao,
Dscho

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

* [PATCH] Add test-tr: poor-man tr
  2008-06-12  7:25   ` Johannes Schindelin
@ 2008-06-12 20:20     ` Alex Riesen, Alex Riesen
  0 siblings, 0 replies; 14+ messages in thread
From: Alex Riesen, Alex Riesen @ 2008-06-12 20:20 UTC (permalink / raw)
  To: git; +Cc: Alf Clement, Johannes Schindelin, Junio C Hamano, Jeff King

It offers a limited set of POSIX tr, in particular: no character class
support and no [n*m] operators. Only 8bit. C-escapes supported, and
character ranges. Deletion and squeezing should work, but -s does not
match the GNU tr from coreutils (which, in turn, does not match POSIX).

Even if the program does not offers the full tr features, what's left
is guaranteed to work the same on every platform where you manage to
compile it (unless the platform does something really nasty at low
level). Originally written to overcome brokenness of ActiveState Perl
on Windows, it should also improve (assuming it will be used instead
of local "tr" and "perl -pe y///") portability of the test suite on
other platforms.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
Johannes Schindelin, Thu, Jun 12, 2008 09:25:09 +0200:
> On Thu, 12 Jun 2008, Alf Clement wrote:
> 
> > > +static unsigned char *unquote(const char *s, unsigned *len) +{
> > > +       unsigned char *result = malloc(strlen(s)), *r = result;
> > 
> > are you sure that the buffer is big enough?? Nomally you do a
> > malloc(strlen(s)+1).
> 
> AFAIU a "tr" really only ever replaces single characters by single 
> characters.  So, not even looking at the code -- just like you -- I would 
> expect it to get the exact number of bytes read, and to write the same 
> number of bytes.
> 
> I certainly would not expect it to do something string based, introducing 
> a silly expectation of NUL-terminations (which tr(1) does not expect 
> either).

In any case, Alf is right. The unquote is called unconditionally with
its arguments, even if there is nothing to unquote. In which case the
size of result is off by one. Corrected test-tr.c (also with a
sensible header) below.

 Makefile  |    2 +-
 test-tr.c |  212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 213 insertions(+), 1 deletions(-)
 create mode 100644 test-tr.c

diff --git a/Makefile b/Makefile
index 1937507..5f208d6 100644
--- a/Makefile
+++ b/Makefile
@@ -1229,7 +1229,7 @@ endif
 
 ### Testing rules
 
-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_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
 
 all:: $(TEST_PROGRAMS)
 
diff --git a/test-tr.c b/test-tr.c
new file mode 100644
index 0000000..2248535
--- /dev/null
+++ b/test-tr.c
@@ -0,0 +1,212 @@
+/*
+ * test-tr  A simplified tr(1) implementation for testing purposes
+ *
+ * It offers a limited set of POSIX tr, in particular: no character
+ * class support and no [n*m] operators. Only 8bit. C-escapes
+ * supported, and character ranges. Deletion and squeezing should
+ * work, but -s does not match the GNU tr from coreutils (which, in
+ * turn, does not match POSIX).
+ */
+#include "cache.h"
+
+static int squeeze, delete;
+
+static unsigned char *unquote(const char *s, unsigned *len)
+{
+	unsigned char *result = malloc(strlen(s) + 1), *r = result;
+
+	while (*s) {
+		switch (*s) {
+		case '\\':
+			++s;
+#define ISOCT(c) (((c) >= '0' && (c) <= '7'))
+			if (ISOCT(*s)) {
+				unsigned int c;
+				char oct[4] = {0,0,0,0};
+				oct[0] = *s++;
+				c = (oct[0] - '0');
+				if (ISOCT(*s)) {
+					oct[1] = *s++;
+					c = (c << 3) |(oct[1] - '0');
+					if (ISOCT(*s)) {
+						oct[2] = *s++;
+						c = (c << 3) |(oct[2] - '0');
+					}
+				}
+				if (c > 255) {
+					fprintf(stderr, "invalid octal character specification: \\%s\n", oct);
+					exit(1);
+				}
+				*r++ = c & 0xff;
+			} else {
+				switch (*s) {
+				case '\0':
+					*r++ = '\\';
+					break;
+				case '\\':
+					*r++ = *s++;
+					break;
+				case 'a':
+					*r++ = '\a';
+					++s;
+					break;
+				case 'b':
+					*r++ = '\b';
+					++s;
+					break;
+				case 'f':
+					*r++ = '\f';
+					++s;
+					break;
+				case 'n':
+					*r++ = '\n';
+					++s;
+					break;
+				case 'r':
+					*r++ = '\r';
+					++s;
+					break;
+				case 't':
+					*r++ = '\t';
+					++s;
+					break;
+				case 'v':
+					*r++ = '\v';
+					++s;
+					break;
+				default:
+					*r++ = '\\';
+					*r++ = *s++;
+					break;
+				}
+			}
+			break;
+		default:
+			*r++ = *s++;
+		}
+	}
+
+	*len = r - result;
+	*r = '\0';
+	return result;
+}
+
+#define MAX_PATTERN 256
+static void put_op(unsigned char *conv, unsigned char ch, unsigned *len)
+{
+	unsigned i = (*len)++;
+	if (*len > MAX_PATTERN) {
+		fprintf(stderr, "pattern too long\n");
+		exit(1);
+	}
+	conv[i] = ch;
+}
+
+static void parse(const unsigned char *rule, unsigned rule_len,
+		  unsigned char *set, unsigned *set_len)
+{
+	const unsigned char *p = rule;
+	while (p < rule + rule_len) {
+		if ('-' == *p && p > rule && p[1]) {
+			unsigned c;
+			if (p[-1] > p[1]) {
+				fprintf(stderr, "%c%c%c: range is reversed\n",
+					p[-1], *p, p[1]);
+				exit(1);
+			}
+			c = p[-1] + 1u;
+			for (; c <= p[1]; ++c)
+				put_op(set, c, set_len);
+			++p;
+			++p;
+			continue;
+		}
+		put_op(set, *p, set_len);
+		++p;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned set1_len = 0, set2_len = 0;
+	unsigned char set1[MAX_PATTERN];
+	unsigned char set2[MAX_PATTERN];
+
+	ssize_t n;
+	unsigned char last = 0, have_last = 0;
+	unsigned char buf[BUFSIZ];
+
+	char *rule1 = NULL, *rule2 = NULL;
+	unsigned char *urule1, *urule2;
+	unsigned urule1_len, urule2_len;
+	int opt;
+
+	for (opt = 1; opt < argc; ++opt) {
+		if (!strcmp("-s", argv[opt]))
+			squeeze = 1;
+		else if (!strcmp("-d", argv[opt]))
+			delete = 1;
+		else if (!rule1) {
+			rule1 = argv[opt];
+		} else if (!rule2)
+			rule2 = argv[opt];
+	}
+	if (!rule1) {
+	    fprintf(stderr, "no source set given\n"
+		    "test-tr [-s] [-d] set1 [set2]\n"
+		    "\"set\" supports only \\NNN, \\a-\\v and CHAR1-CHAR2 rules\n");
+	    exit(1);
+	}
+	if (delete && rule2) {
+		fprintf(stderr, "extra operand %s when deleting\n", rule2);
+		exit(1);
+	}
+	urule1 = unquote(rule1, &urule1_len);
+	urule2 = NULL;
+	urule2_len = 0;
+	if ((!rule2 || !*rule2) && !delete && !squeeze) {
+		fprintf(stderr, "set2 must be non-empty\n");
+		exit(1);
+	}
+
+	parse(urule1, urule1_len, set1, &set1_len);
+
+	if (rule2) {
+		unsigned i;
+		urule2 = unquote(rule2, &urule2_len);
+		parse(urule2, urule2_len, set2, &set2_len);
+		i = set2[set2_len - 1];
+		while (set2_len < set1_len)
+			put_op(set2, i, &set2_len);
+	}
+
+	while ((n = read(STDIN_FILENO, buf, sizeof(buf)))) {
+		if (n < 0) {
+			int err = errno;
+			if (EINTR == err || EAGAIN == err)
+				continue;
+			fprintf(stderr, "%s: %s\n", argv[0], strerror(err));
+			exit(1);
+		}
+		if (set1_len) {
+			unsigned i, o = 0;
+			for (i = 0; i < (unsigned)n; ++i) {
+				unsigned char *p, ch = buf[i];
+				p = memchr(set1, ch, set1_len);
+				if (p) {
+					if (delete)
+						continue;
+					if (set2_len)
+						ch = set2[p - set1];
+				}
+				if (!(squeeze && have_last && ch == last))
+					buf[o++] = ch;
+				have_last = 1;
+				last = ch;
+			}
+			n = o;
+		}
+		write(STDOUT_FILENO, buf, n);
+	}
+	return 0;
+}
-- 
1.5.6.rc2.43.g77bfa

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-12  6:23     ` Jeff King
  2008-06-12  6:28       ` Jeff King
@ 2008-06-12 20:32       ` Alex Riesen
  2008-06-13  6:02         ` Jeff King
  1 sibling, 1 reply; 14+ messages in thread
From: Alex Riesen @ 2008-06-12 20:32 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano

Jeff King, Thu, Jun 12, 2008 08:23:09 +0200:
> On Thu, Jun 12, 2008 at 08:01:52AM +0200, Alex Riesen wrote:
> 
> > Frankly, it started because I wanted to minimize use of Perl on
> > Windows (because I can't get around ActiveState Perl at work, and it
> > breaks almost everything it touches). Accidentally, it is also faster
> > there (maybe just because it's smaller).
> 
> Ah, right. Well, I am not opposed to getting rid of perl in the test
> scripts (there is core functionality provided by perl, so one can easily
> run git on a system with no perl at all).

"git add --interactive" and "git send-mail". The first has a very good
replacement (git gui). The other, even if not that "core", is a very
popular tool. (And I can't use it at work at all: noone to understand
word "patch" there. And even then, noone would care about change
review anyway).

> However, even with your patch, there is still some perl left, so I am
> not sure that it has really bought us very much.

I was forced to carefully check every instance and am positive that
the others are ok with regard to ActiveState Perl and Windows quirks :)
(IOW, I run the testsuite every day and it aint broke yet)

> > But, as was already noted, tr does not behave the same for all
> > platforms (there were even differences in output, BSD or Solaris put
> > out a stray LF?).
> 
> I think those were all resolved by using perl, and your patch replaces
> them with test-tr.

That was the problem. ActiveState Perl always replaces LF in the
output with CRLF, which caused mismatches with template files in some
tests (even the generated templates had LF line endings, cygwins tools
follow that convention). At first, I tried to get by putting
"binmode(STDOUT)" into every test, but this became boring with a time.
Besides, the lines get very long and ugly (and make conflict resolving
harder).

> > In any case, I wont push this change too hard. I must admit, that
> > there is no real good reason besides one "screwed" company using
> > obsoleted tools in a weird way. And it is a maintenance effort (and
> > people will forget to use test-tr instead of perl and tr).
> 
> There is maintenance effort either way; people need to know not to do
> unportable things with tr (and other tools), and the solution to that is
> to run the test scripts on each platform (something we are starting to
> do).

With test-tr they still have to do all that, but also support its
existence. So I'm not sure.

> So I am not opposed to test-tr, I just wanted you to explain it better
> in the commit log. ;)

I already tried.

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-12 20:32       ` Alex Riesen
@ 2008-06-13  6:02         ` Jeff King
  2008-06-13 17:26           ` Alex Riesen
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff King @ 2008-06-13  6:02 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano

On Thu, Jun 12, 2008 at 10:32:45PM +0200, Alex Riesen wrote:

> That was the problem. ActiveState Perl always replaces LF in the
> output with CRLF, which caused mismatches with template files in some
> tests (even the generated templates had LF line endings, cygwins tools
> follow that convention). At first, I tried to get by putting
> "binmode(STDOUT)" into every test, but this became boring with a time.
> Besides, the lines get very long and ugly (and make conflict resolving
> harder).

Does ActiveState respect the PERLIO environment variable? I haven't
played with it much, but my understanding is that setting
PERLIO=:unix:perlio should give you sane behavior (the default on
Windows should be PERLIO=:unix:crlf).

> > So I am not opposed to test-tr, I just wanted you to explain it better
> > in the commit log. ;)
> 
> I already tried.

I think this thread and the improved commit message have helped.

-Peff

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-13  6:02         ` Jeff King
@ 2008-06-13 17:26           ` Alex Riesen
  2008-06-13 18:00             ` Jeff King
  0 siblings, 1 reply; 14+ messages in thread
From: Alex Riesen @ 2008-06-13 17:26 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano

Jeff King, Fri, Jun 13, 2008 08:02:15 +0200:
> On Thu, Jun 12, 2008 at 10:32:45PM +0200, Alex Riesen wrote:
> 
> > That was the problem. ActiveState Perl always replaces LF in the
> > output with CRLF, which caused mismatches with template files in some
> > tests (even the generated templates had LF line endings, cygwins tools
> > follow that convention). At first, I tried to get by putting
> > "binmode(STDOUT)" into every test, but this became boring with a time.
> > Besides, the lines get very long and ugly (and make conflict resolving
> > harder).
> 
> Does ActiveState respect the PERLIO environment variable? I haven't
> played with it much, but my understanding is that setting
> PERLIO=:unix:perlio should give you sane behavior (the default on
> Windows should be PERLIO=:unix:crlf).

I didn't know about it (and managed to miss it when I looked to
workaround the problem. I even looked into the manpage documenting
environment variables!)

Yes, it works. It has side effects (the scripts of some build
processes will be affected), but that's already something...

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

* Re: [PATCH] Add test-tr: poor-man tr
  2008-06-13 17:26           ` Alex Riesen
@ 2008-06-13 18:00             ` Jeff King
  0 siblings, 0 replies; 14+ messages in thread
From: Jeff King @ 2008-06-13 18:00 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano

On Fri, Jun 13, 2008 at 07:26:34PM +0200, Alex Riesen wrote:

> > Does ActiveState respect the PERLIO environment variable? I haven't
> > played with it much, but my understanding is that setting
> > PERLIO=:unix:perlio should give you sane behavior (the default on
> > Windows should be PERLIO=:unix:crlf).
> 
> I didn't know about it (and managed to miss it when I looked to
> workaround the problem. I even looked into the manpage documenting
> environment variables!)
> 
> Yes, it works. It has side effects (the scripts of some build
> processes will be affected), but that's already something...

I was thinking that we could set it inside test-lib.sh to get consistent
behavior. It should just be a no-op on sane systems.

-Peff

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

end of thread, other threads:[~2008-06-13 18:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-11 18:25 [PATCH] Add test-tr: poor-man tr Alex Riesen, Alex Riesen
2008-06-11 18:26 ` [PATCH] Use test-tr in the tests Alex Riesen
2008-06-11 21:34 ` [PATCH] Add test-tr: poor-man tr Alex Riesen
2008-06-11 22:54 ` Jeff King
2008-06-12  6:01   ` Alex Riesen
2008-06-12  6:23     ` Jeff King
2008-06-12  6:28       ` Jeff King
2008-06-12 20:32       ` Alex Riesen
2008-06-13  6:02         ` Jeff King
2008-06-13 17:26           ` Alex Riesen
2008-06-13 18:00             ` Jeff King
2008-06-12  6:32 ` Alf Clement
2008-06-12  7:25   ` Johannes Schindelin
2008-06-12 20:20     ` Alex Riesen, Alex Riesen

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