Merge branch 'jk/test-seq-format'

A test helper "test_seq" function learned the "-f <fmt>" option,
which allowed us to simplify a lot of test scripts.

* jk/test-seq-format:
  test-lib: teach test_seq the -f option
  t7422: replace confusing printf with echo
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index bf10d25..f0d50d7 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -281,7 +281,7 @@
 test_expect_success 'filtering large input to small output should use little memory' '
 	test_config filter.devnull.clean "cat >/dev/null" &&
 	test_config filter.devnull.required true &&
-	for i in $(test_seq 1 30); do printf "%1048576d" 1 || return 1; done >30MB &&
+	test_seq -f "%1048576d" 1 30 >30MB &&
 	echo "30MB filter=devnull" >.gitattributes &&
 	GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
 '
@@ -299,7 +299,7 @@
 test_expect_success EXPENSIVE 'filter large file' '
 	test_config filter.largefile.smudge cat &&
 	test_config filter.largefile.clean cat &&
-	for i in $(test_seq 1 2048); do printf "%1048576d" 1 || return 1; done >2GB &&
+	test_seq -f "%1048576d" 1 2048 >2GB &&
 	echo "2GB filter=largefile" >.gitattributes &&
 	git add 2GB 2>err &&
 	test_must_be_empty err &&
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 1be534a..3ea5d51 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -477,11 +477,7 @@
 		test_commit --no-tag initial &&
 
 		head=$(git rev-parse HEAD) &&
-		for i in $(test_seq 100)
-		do
-			printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" ||
-			return 1
-		done >expect &&
+		test_seq -f "$head commit\trefs/heads/branch-%d" 100 >expect &&
 		printf "%s commit\trefs/heads/main\n" "$head" >>expect &&
 
 		for i in $(test_seq 100)
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
index d0d7e80..7df2ad5 100755
--- a/t/t0612-reftable-jgit-compatibility.sh
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -112,14 +112,11 @@
 		cd repo &&
 
 		test_commit A &&
-		awk "
-		    BEGIN {
-			print \"start\";
-			for (i = 0; i < 10000; i++)
-			    printf \"create refs/heads/branch-%d HEAD\n\", i;
-			print \"commit\";
-		    }
-		" >input &&
+		{
+			echo start &&
+			test_seq -f "create refs/heads/branch-%d HEAD" 10000 &&
+			echo commit
+		} >input &&
 		git update-ref --stdin <input &&
 
 		test_same_refs &&
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index 6447920..d77e601 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -66,11 +66,7 @@
 	(
 		cd repo &&
 		test_commit initial &&
-		for i in $(test_seq 200)
-		do
-			printf "update refs/heads/branch-%d HEAD\n" "$i" ||
-			return 1
-		done >input &&
+		test_seq -f "update refs/heads/branch-%d HEAD" 200 >input &&
 		git update-ref --stdin <input &&
 		git pack-refs &&
 
@@ -180,11 +176,7 @@
 	(
 		cd repo &&
 		test_commit initial &&
-		for i in $(test_seq 10)
-		do
-			printf "update refs/heads/branch-%d HEAD\n" "$i" ||
-			return 1
-		done >input &&
+		test_seq -f "update refs/heads/branch-%d HEAD" 10 >input &&
 		git update-ref --stdin <input &&
 		git -c reftable.restartInterval=1 pack-refs &&
 
@@ -224,11 +216,7 @@
 	(
 		cd repo &&
 		test_commit initial &&
-		for i in $(test_seq 5)
-		do
-			printf "update refs/heads/branch-%d HEAD\n" "$i" ||
-			return 1
-		done >input &&
+		test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
 		git update-ref --stdin <input &&
 		git -c reftable.blockSize=100 pack-refs &&
 
@@ -263,11 +251,7 @@
 	(
 		cd repo &&
 		test_commit initial &&
-		for i in $(test_seq 5)
-		do
-			printf "update refs/heads/branch-%d HEAD\n" "$i" ||
-			return 1
-		done >input &&
+		test_seq -f "update refs/heads/branch-%d HEAD" 5 >input &&
 		git update-ref --stdin <input &&
 		git -c reftable.blockSize=100 -c reftable.indexObjects=false pack-refs &&
 
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index d29d23c..e373d91 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -1380,10 +1380,7 @@
 
 test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' '
 (
-	for i in $(test_seq 33)
-	do
-		echo "create refs/heads/$i HEAD" || exit 1
-	done >large_input &&
+	test_seq -f "create refs/heads/%d HEAD" 33 >large_input &&
 	run_with_limited_open_files git update-ref --stdin <large_input &&
 	git rev-parse --verify -q refs/heads/33
 )
@@ -1391,10 +1388,7 @@
 
 test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches does not burst open file limit' '
 (
-	for i in $(test_seq 33)
-	do
-		echo "delete refs/heads/$i HEAD" || exit 1
-	done >large_input &&
+	test_seq -f "delete refs/heads/%d HEAD" 33 >large_input &&
 	run_with_limited_open_files git update-ref --stdin <large_input &&
 	test_must_fail git rev-parse --verify -q refs/heads/33
 )
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 5174995..027dedd 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -176,10 +176,7 @@
 	blob=$(echo $s | git hash-object -w --stdin) &&
 
 	# create tree containing 65500 entries of that blob
-	for i in $(test_seq 1 65500)
-	do
-		echo "100644 blob $blob	$i" || return 1
-	done >tree &&
+	test_seq -f "100644 blob $blob\t%d" 1 65500 >tree &&
 	tree=$(git mktree <tree) &&
 
 	# zip it, creating an archive a bit bigger than 4GB
diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh
index 9cbe7ca..f14c0fb 100755
--- a/t/t6422-merge-rename-corner-cases.sh
+++ b/t/t6422-merge-rename-corner-cases.sh
@@ -1146,10 +1146,7 @@
 			cd simple_${sideL}_${sideR} &&
 
 			# Create some related files now
-			for i in $(test_seq 1 10)
-			do
-				echo Random base content line $i
-			done >file_v1 &&
+			test_seq -f "Random base content line %d" 1 10 >file_v1 &&
 			cp file_v1 file_v2 &&
 			echo modification >>file_v2 &&
 
@@ -1293,10 +1290,7 @@
 		cd nested_conflicts_from_rename_rename &&
 
 		# Create some related files now
-		for i in $(test_seq 1 10)
-		do
-			echo Random base content line $i
-		done >file_v1 &&
+		test_seq -f "Random base content line %d" 1 10 >file_v1 &&
 
 		cp file_v1 file_v2 &&
 		cp file_v1 file_v3 &&
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh
index 023a5cb..aea1ddf 100755
--- a/t/t7422-submodule-output.sh
+++ b/t/t7422-submodule-output.sh
@@ -180,17 +180,14 @@
 		COMMIT=$(git rev-parse HEAD) &&
 		for i in $(test_seq 2000)
 		do
-			printf "[submodule \"sm-$i\"]\npath = recursive-submodule-path-$i\n" "$i" ||
+			echo "[submodule \"sm-$i\"]" &&
+			echo "path = recursive-submodule-path-$i" ||
 			return 1
 		done >gitmodules &&
 		BLOB=$(git hash-object -w --stdin <gitmodules) &&
 
 		printf "100644 blob $BLOB\t.gitmodules\n" >tree &&
-		for i in $(test_seq 2000)
-		do
-			printf "160000 commit $COMMIT\trecursive-submodule-path-%d\n" "$i" ||
-			return 1
-		done >>tree &&
+		test_seq -f "160000 commit $COMMIT\trecursive-submodule-path-%d" 2000 >>tree &&
 		TREE=$(git mktree <tree) &&
 
 		COMMIT=$(git commit-tree "$TREE") &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index bee4a2c..6230746 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1451,9 +1451,21 @@
 #     test_seq 1 5 -- outputs 1 2 3 4 5 one line at a time
 #
 # or with one argument (end), in which case it starts counting
-# from 1.
+# from 1. In addition to the start/end arguments, you can pass an optional
+# printf format. For example:
+#
+#     test_seq -f "line %d" 1 5
+#
+# would print 5 lines, "line 1" through "line 5".
 
 test_seq () {
+	local fmt="%d"
+	case "$1" in
+	-f)
+		fmt="$2"
+		shift 2
+		;;
+	esac
 	case $# in
 	1)	set 1 "$@" ;;
 	2)	;;
@@ -1462,7 +1474,7 @@
 	test_seq_counter__=$1
 	while test "$test_seq_counter__" -le "$2"
 	do
-		echo "$test_seq_counter__"
+		printf "$fmt\n" "$test_seq_counter__"
 		test_seq_counter__=$(( $test_seq_counter__ + 1 ))
 	done
 }