t5702: use test_commit_bulk
[gitweb.git] / t / test-lib-functions.sh
index 681c41ba329a90db8c668fde4640025872f1e622..6083cf483a13583a02271b923240188abaa6643b 100644 (file)
@@ -233,6 +233,129 @@ test_merge () {
        git tag "$1"
 }
 
+# Efficiently create <nr> commits, each with a unique number (from 1 to <nr>
+# by default) in the commit message.
+#
+# Usage: test_commit_bulk [options] <nr>
+#   -C <dir>:
+#      Run all git commands in directory <dir>
+#   --ref=<n>:
+#      ref on which to create commits (default: HEAD)
+#   --start=<n>:
+#      number commit messages from <n> (default: 1)
+#   --message=<msg>:
+#      use <msg> as the commit mesasge (default: "commit %s")
+#   --filename=<fn>:
+#      modify <fn> in each commit (default: %s.t)
+#   --contents=<string>:
+#      place <string> in each file (default: "content %s")
+#   --id=<string>:
+#      shorthand to use <string> 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 <<EOF"
+               printf "$message\n" $n
+               echo "EOF"
+               if test -n "$add_from"
+               then
+                       echo "from $ref^0"
+                       add_from=
+               fi
+               printf "M 644 inline $filename\n" $n
+               echo "data <<EOF"
+               printf "$contents\n" $n
+               echo "EOF"
+               echo
+               n=$((n + 1))
+               total=$((total - 1))
+       done >"$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.
@@ -309,6 +432,26 @@ test_unset_prereq () {
 }
 
 test_set_prereq () {
+       if test -n "$GIT_TEST_FAIL_PREREQS"
+       then
+               case "$1" in
+               # The "!" case is handled below with
+               # test_unset_prereq()
+               !*)
+                       ;;
+               # (Temporary?) whitelist of things we can't easily
+               # pretend not to support
+               SYMLINKS)
+                       ;;
+               # Inspecting whether GIT_TEST_FAIL_PREREQS is on
+               # should be unaffected.
+               FAIL_PREREQS)
+                       ;;
+               *)
+                       return
+               esac
+       fi
+
        case "$1" in
        !*)
                test_unset_prereq "${1#!}"
@@ -943,6 +1086,34 @@ test_when_finished () {
                } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
 }
 
+# This function can be used to schedule some commands to be run
+# unconditionally at the end of the test script, e.g. to stop a daemon:
+#
+#      test_expect_success 'test git daemon' '
+#              git daemon &
+#              daemon_pid=$! &&
+#              test_atexit 'kill $daemon_pid' &&
+#              hello world
+#      '
+#
+# The commands will be executed before the trash directory is removed,
+# i.e. the atexit commands will still be able to access any pidfiles or
+# socket files.
+#
+# Note that these commands will be run even when a test script run
+# with '--immediate' fails.  Be careful with your atexit commands to
+# minimize any changes to the failed state.
+
+test_atexit () {
+       # We cannot detect when we are in a subshell in general, but by
+       # doing so on Bash is better than nothing (the test will
+       # silently pass on other shells).
+       test "${BASH_SUBSHELL-0}" = 0 ||
+       error "bug in test script: test_atexit does nothing in a subshell"
+       test_atexit_cleanup="{ $*
+               } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_atexit_cleanup"
+}
+
 # Most tests can use the created repository, but some may need to create more.
 # Usage: test_create_repo <directory>
 test_create_repo () {
@@ -1211,6 +1382,12 @@ depacketize () {
        '
 }
 
+# Converts base-16 data into base-8. The output is given as a sequence of
+# escaped octals, suitable for consumption by 'printf'.
+hex2oct () {
+       perl -ne 'printf "\\%03o", hex for /../g'
+}
+
 # Set the hash algorithm in use to $1.  Only useful when testing the testsuite.
 test_set_hash () {
        test_hash_algo="$1"