diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh index 93516ef67c..37151a3adc 100755 --- a/t/t3311-notes-merge-fanout.sh +++ b/t/t3311-notes-merge-fanout.sh @@ -114,12 +114,12 @@ cp expect_log_x expect_log_y test_expect_success 'Add a few hundred commits w/notes to trigger fanout (x -> y)' ' git update-ref refs/notes/y refs/notes/x && git config core.notesRef refs/notes/y && - i=5 && - while test $i -lt $num + test_commit_bulk --start=6 --id=commit $((num - 5)) && + i=0 && + while test $i -lt $((num - 5)) do - i=$(($i + 1)) && - test_commit "commit$i" >/dev/null && - git notes add -m "notes for commit$i" || return 1 + git notes add -m "notes for commit$i" HEAD~$i || return 1 + i=$((i + 1)) done && test "$(git rev-parse refs/notes/y)" != "$(git rev-parse refs/notes/x)" && # Expected number of commits and notes diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index a26c8ba9a2..6640329ebf 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -21,15 +21,9 @@ has_any () { } test_expect_success 'setup repo with moderate-sized history' ' - for i in $(test_seq 1 10) - do - test_commit $i - done && + test_commit_bulk --id=file 100 && git checkout -b other HEAD~5 && - for i in $(test_seq 1 10) - do - test_commit side-$i - done && + test_commit_bulk --id=side 10 && git checkout master && bitmaptip=$(git rev-parse master) && blob=$(echo tagged-blob | git hash-object -w --stdin) && @@ -106,10 +100,7 @@ test_expect_success 'clone from bitmapped repository' ' ' test_expect_success 'setup further non-bitmapped commits' ' - for i in $(test_seq 1 10) - do - test_commit further-$i - done + test_commit_bulk --id=further 10 ' rev_list_tests 'partial bitmap' diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 5b33f625dd..011b81d4fc 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -499,10 +499,7 @@ test_expect_success 'upload-pack respects client shallows' ' # Add extra commits to the client so that the whole fetch takes more # than 1 request (due to negotiation) - for i in $(test_seq 1 32) - do - test_commit -C client c$i - done && + test_commit_bulk -C client --id=c 32 && git -C server checkout -b newbranch base && test_commit -C server client_wants && @@ -711,10 +708,7 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' # Create many commits to extend the negotiation phase across multiple # requests, so that the server does not send "ready" in the first # request. - for i in $(test_seq 1 32) - do - test_commit -C http_child c$i - done && + test_commit_bulk -C http_child --id=c 32 && # After the acknowledgments section, pretend that a DELIM # (0001) was sent instead of a FLUSH (0000). diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 0951d1bbdc..de4b6106ef 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -176,7 +176,7 @@ test_expect_success 'setup repos for change-while-negotiating test' ' git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" && cd "$LOCAL_PRISTINE" && git checkout -b side && - for i in $(test_seq 1 33); do test_commit s$i; done && + test_commit_bulk --id=s 33 && # Add novel commits to upstream git checkout master && @@ -287,7 +287,7 @@ test_expect_success 'setup repos for fetching with ref-in-want tests' ' git clone "file://$REPO" "$LOCAL_PRISTINE" && cd "$LOCAL_PRISTINE" && git checkout -b side && - for i in $(test_seq 1 33); do test_commit s$i; done && + test_commit_bulk --id=s 33 && # Add novel commits to upstream git checkout master && diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 93f23cfa82..8a72b4c43a 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -66,12 +66,7 @@ test_expect_success setup ' git commit -a -m "Right #5" && git checkout -b long && - i=0 && - while test $i -lt 30 - do - test_commit $i one && - i=$(($i+1)) - done && + test_commit_bulk --start=0 --message=%s --filename=one 30 && git show-branch && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 27b81276fc..d4f199391f 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -233,6 +233,129 @@ test_merge () { git tag "$1" } +# Efficiently create commits, each with a unique number (from 1 to +# by default) in the commit message. +# +# Usage: test_commit_bulk [options] +# -C : +# Run all git commands in directory +# --ref=: +# ref on which to create commits (default: HEAD) +# --start=: +# number commit messages from (default: 1) +# --message=: +# use as the commit mesasge (default: "commit %s") +# --filename=: +# modify in each commit (default: %s.t) +# --contents=: +# place in each file (default: "content %s") +# --id=: +# shorthand to use and %s in message, filename, and contents +# +# The message, filename, and contents strings are evaluated by printf, with the +# first "%s" replaced by the current commit number. So you can do: +# +# test_commit_bulk --filename=file --contents="modification %s" +# +# to have every commit touch the same file, but with unique content. +# +test_commit_bulk () { + tmpfile=.bulk-commit.input + indir=. + ref=HEAD + n=1 + message='commit %s' + filename='%s.t' + contents='content %s' + while test $# -gt 0 + do + case "$1" in + -C) + indir=$2 + shift + ;; + --ref=*) + ref=${1#--*=} + ;; + --start=*) + n=${1#--*=} + ;; + --message=*) + message=${1#--*=} + ;; + --filename=*) + filename=${1#--*=} + ;; + --contents=*) + contents=${1#--*=} + ;; + --id=*) + message="${1#--*=} %s" + filename="${1#--*=}-%s.t" + contents="${1#--*=} %s" + ;; + -*) + BUG "invalid test_commit_bulk option: $1" + ;; + *) + break + ;; + esac + shift + done + total=$1 + + add_from= + if git -C "$indir" rev-parse --verify "$ref" + then + add_from=t + fi + + while test "$total" -gt 0 + do + test_tick && + echo "commit $ref" + printf 'author %s <%s> %s\n' \ + "$GIT_AUTHOR_NAME" \ + "$GIT_AUTHOR_EMAIL" \ + "$GIT_AUTHOR_DATE" + printf 'committer %s <%s> %s\n' \ + "$GIT_COMMITTER_NAME" \ + "$GIT_COMMITTER_EMAIL" \ + "$GIT_COMMITTER_DATE" + echo "data <"$tmpfile" + + git -C "$indir" \ + -c fastimport.unpacklimit=0 \ + fast-import <"$tmpfile" || return 1 + + # This will be left in place on failure, which may aid debugging. + rm -f "$tmpfile" + + # If we updated HEAD, then be nice and update the index and working + # tree, too. + if test "$ref" = "HEAD" + then + git -C "$indir" checkout -f HEAD || return 1 + fi + +} + # This function helps systems where core.filemode=false is set. # Use it instead of plain 'chmod +x' to set or unset the executable bit # of a file in the working directory and add it to the index.