Message ID | e3be6705d103ccbc165d0fd3b9b7c818d14001e9.1740516033.git.git@grubix.eu (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [BUG/WIP] unit-tests: use clean test environment | expand |
On Tue, Feb 25, 2025 at 09:48:47PM +0100, Michael J Gruber wrote: > So far, unit-tests are run in the user's environment, in particular with > the user's git config which can influence test runs. > > Set up the same clean test environment which we use for the other tests. > --- > Hi there, > > I finally got around to checking whether the last test in t-trailer fails > for me: one of the trailers is present in my git config, messing up the > test assumption. The reasons is a systematic problem in the way we run > unit-tests. > > The attached patch is more POC than WIP - it makes t-trailer work again > for me, at least. > > unittest-lib.sh is a trimmed down version of test-lib.sh, and I'm sure > it can be trimmed down even more, maybe to the extent of being included > in run-test.sh. > > Also, I'm not sute the Makefile change catches all invocations of > unit-tests. (It certainly does not cover direct invocations, of course.) This to me is the biggest issue with the chosen approach. It would be great if we could find a way to sanitize the environment in the unit test executable directly instead of forcing users to run the unit tests via the provided script. I suspect that most environment variables shouldn't matter (for now), so overall the duplication may be acceptable: - We need to unset a couple of variables, but we can probably reuse logic `git rev-parse --local-env-vars`. - We need to ask Git to not read the configuration, which we can do by setting a couple of envvars. This should be manageable. But other than that I don't think we rely on any other infrastructure exposed via environment variables, to the best of my knowledge. So it shouldn't be that much logic, which may make it an option to implement this in "t/unit-tests/unit-test.c" directly. We still have a couple of other unit tests that have a different entry point than the clar-based tests. But Seyi has been converting most of them already, and I wouldn't worry about the remaining ones. So only doing it for the clar-based tests should be good enough for our case as we can assume that the other tests will go away sooner rather than later. Thanks! Patrick
Patrick Steinhardt <ps@pks.im> writes: > This to me is the biggest issue with the chosen approach. It would be > great if we could find a way to sanitize the environment in the unit > test executable directly instead of forcing users to run the unit tests > via the provided script. True. What the end-to-end tests do is to have a central place (in test-lib.sh if I recall correctly) to ensure a sane environment and have everybody run that before their own code. In theory we should be able to do the same in C (otherwise we wouldn't rewriting things done in scripts to the language ;-)). > I suspect that most environment variables shouldn't matter (for now), so > overall the duplication may be acceptable: > > - We need to unset a couple of variables, but we can probably reuse > logic `git rev-parse --local-env-vars`. > > - We need to ask Git to not read the configuration, which we can do by > setting a couple of envvars. This should be manageable. "Provide a controlled environment where Git pretends this is the $HOME and that is the $AUTHOR_NAME and so on" is much more preferrable than "Tell it not to read", no? Thanks.
On Fri, Feb 28, 2025 at 06:15:42AM -0800, Junio C Hamano wrote: > Patrick Steinhardt <ps@pks.im> writes: > > I suspect that most environment variables shouldn't matter (for now), so > > overall the duplication may be acceptable: > > > > - We need to unset a couple of variables, but we can probably reuse > > logic `git rev-parse --local-env-vars`. > > > > - We need to ask Git to not read the configuration, which we can do by > > setting a couple of envvars. This should be manageable. > > "Provide a controlled environment where Git pretends this is the > $HOME and that is the $AUTHOR_NAME and so on" is much more > preferrable than "Tell it not to read", no? Maybe. I guess for unit tests it's a lot less clear cut as most of the tests won't depend on such a controlled environment. So sanitizing the environment would be a good enough first step for me, and if we see demand for making specific information available to lots of tests we could still start to expose those at a later point. Of course, if the author already wants to do both steps right now I won't complain :) Patrick
Am Mo., 3. März 2025 um 11:33 Uhr schrieb Patrick Steinhardt <ps@pks.im>: > > On Fri, Feb 28, 2025 at 06:15:42AM -0800, Junio C Hamano wrote: > > Patrick Steinhardt <ps@pks.im> writes: > > > I suspect that most environment variables shouldn't matter (for now), so > > > overall the duplication may be acceptable: > > > > > > - We need to unset a couple of variables, but we can probably reuse > > > logic `git rev-parse --local-env-vars`. > > > > > > - We need to ask Git to not read the configuration, which we can do by > > > setting a couple of envvars. This should be manageable. > > > > "Provide a controlled environment where Git pretends this is the > > $HOME and that is the $AUTHOR_NAME and so on" is much more > > preferrable than "Tell it not to read", no? > > Maybe. I guess for unit tests it's a lot less clear cut as most of the > tests won't depend on such a controlled environment. So sanitizing the > environment would be a good enough first step for me, and if we see > demand for making specific information available to lots of tests we > could still start to expose those at a later point. Since I haven't been following the list I don't know what the plan is regarding the different test sets/framework. But, unless they are meant to be completely separate or rewritten right away, I would say that both shell tests and C tests (whatever framework) should run in the same environment, and this should be a controlled environment in terms of git and other config files (which means set up a separate HOME) and the most relevant env vars (test-lib.sh tries to do that, too). > Of course, if the author already wants to do both steps right now I > won't complain :) Nah, I had a hard time just reading the failing unit-test and figuring out how to deal with it - GIT_TEST_OPTIONS=`-i -v` does nothing for unit-tests, and I yet have to find documentation on them. I do understand why you want a solution in C, not a shell wrapper. (Though you have one right now ...) I'd rather leave this to those "in the know", or "in the want" ;-) Michael
Patrick Steinhardt <ps@pks.im> writes: > Maybe. I guess for unit tests it's a lot less clear cut as most of the > tests won't depend on such a controlled environment. So sanitizing the > environment would be a good enough first step for me, and if we see > demand for making specific information available to lots of tests we > could still start to expose those at a later point. Fair enough. To put it another way, if you write a test and if it gets affected by externalities, perhaps you are testing a function that is at too high a level that is not a suitable target for unit tested? I am thinking about the recent "make repo-config callable with repo==NULL outside a repository" topic, for example, and I suspect repo_config() is in a layer that is at a bit too high for suitable unit test target. Thanks.
On Mon, Mar 03, 2025 at 06:07:29AM -0800, Junio C Hamano wrote: > Patrick Steinhardt <ps@pks.im> writes: > > > Maybe. I guess for unit tests it's a lot less clear cut as most of the > > tests won't depend on such a controlled environment. So sanitizing the > > environment would be a good enough first step for me, and if we see > > demand for making specific information available to lots of tests we > > could still start to expose those at a later point. > > Fair enough. > > To put it another way, if you write a test and if it gets affected > by externalities, perhaps you are testing a function that is at too > high a level that is not a suitable target for unit tested? I think one problem with this approach is that breakage is likely going to depend on the user's environment. So something that works just fine for you, the test author, may introduce a hidden dependency that breaks for somebody else much later. Some examples, assuming we just suppress reading Git config: - Without an explicit ident, we fall back to constructing one from system info. So if a unit test ever creates a commit, it will work fine for most people, but not for somebody with a blank GECOS field in /etc/passwd. (We do look at that field for reflogs, which current unit tests already do, but we are more forgiving there since we don't pass IDENT_STRICT). - Other programs we call (e.g., imagine gpg or ssh for commit signing or verification) may read their own config based on $HOME, $XDG_CONFIG_HOME, etc. I don't know if Patrick was including that in "sanitizing the environment" or not. -Peff
On Tue, Mar 04, 2025 at 02:30:10AM -0500, Jeff King wrote: > On Mon, Mar 03, 2025 at 06:07:29AM -0800, Junio C Hamano wrote: > > > Patrick Steinhardt <ps@pks.im> writes: > > > > > Maybe. I guess for unit tests it's a lot less clear cut as most of the > > > tests won't depend on such a controlled environment. So sanitizing the > > > environment would be a good enough first step for me, and if we see > > > demand for making specific information available to lots of tests we > > > could still start to expose those at a later point. > > > > Fair enough. > > > > To put it another way, if you write a test and if it gets affected > > by externalities, perhaps you are testing a function that is at too > > high a level that is not a suitable target for unit tested? > > I think one problem with this approach is that breakage is likely going > to depend on the user's environment. So something that works just fine > for you, the test author, may introduce a hidden dependency that breaks > for somebody else much later. > > Some examples, assuming we just suppress reading Git config: > > - Without an explicit ident, we fall back to constructing one from > system info. So if a unit test ever creates a commit, it will work > fine for most people, but not for somebody with a blank GECOS field > in /etc/passwd. (We do look at that field for reflogs, which current > unit tests already do, but we are more forgiving there since we > don't pass IDENT_STRICT). > > - Other programs we call (e.g., imagine gpg or ssh for commit signing > or verification) may read their own config based on $HOME, > $XDG_CONFIG_HOME, etc. I don't know if Patrick was including that in > "sanitizing the environment" or not. Oh, yes. I didn't mean to say we shouldn't sanitize at all, I rather meant to say we should sanitize to values that simply cause us to do a no-op in the relevant parts. That means we'd: - Unset a bunch of environment variables where we know that they impact Git. - Set config-related environment variables to read configuration from "/dev/null". This is in contrast to the more involved fix here, which would be to populate a temporary home directory with gitconfig files and whatnot. Patrick
On Tue, Mar 04, 2025 at 08:39:50AM +0100, Patrick Steinhardt wrote: > > Some examples, assuming we just suppress reading Git config: > > > > - Without an explicit ident, we fall back to constructing one from > > system info. So if a unit test ever creates a commit, it will work > > fine for most people, but not for somebody with a blank GECOS field > > in /etc/passwd. (We do look at that field for reflogs, which current > > unit tests already do, but we are more forgiving there since we > > don't pass IDENT_STRICT). > > > > - Other programs we call (e.g., imagine gpg or ssh for commit signing > > or verification) may read their own config based on $HOME, > > $XDG_CONFIG_HOME, etc. I don't know if Patrick was including that in > > "sanitizing the environment" or not. > > Oh, yes. I didn't mean to say we shouldn't sanitize at all, I rather > meant to say we should sanitize to values that simply cause us to do a > no-op in the relevant parts. That means we'd: > > - Unset a bunch of environment variables where we know that they > impact Git. > > - Set config-related environment variables to read configuration > from "/dev/null". > > This is in contrast to the more involved fix here, which would be to > populate a temporary home directory with gitconfig files and whatnot. OK. I still think you'd want to set GIT_COMMITTER_NAME (to avoid gecos dependencies). And I'm assuming your "a bunch of environment variables where we know that they impact Git" includes $HOME, since we are inheriting dependencies from sub-programs. It doesn't necessarily have to point somewhere useful, though I wouldn't be surprised if some programs complain if they can't write to it. -Peff
Jeff King <peff@peff.net> writes: >> Oh, yes. I didn't mean to say we shouldn't sanitize at all, I rather >> meant to say we should sanitize to values that simply cause us to do a >> no-op in the relevant parts. That means we'd: >> >> - Unset a bunch of environment variables where we know that they >> impact Git. >> >> - Set config-related environment variables to read configuration >> from "/dev/null". >> >> This is in contrast to the more involved fix here, which would be to >> populate a temporary home directory with gitconfig files and whatnot. > > OK. I still think you'd want to set GIT_COMMITTER_NAME (to avoid gecos > dependencies). > > And I'm assuming your "a bunch of environment variables where we know > that they impact Git" includes $HOME, since we are inheriting > dependencies from sub-programs. It doesn't necessarily have to point > somewhere useful, though I wouldn't be surprised if some programs > complain if they can't write to it. I guess eventually we will come full circle and need to sanitize pretty much the same set of environments as t/test-lib.sh does?
diff --git a/t/Makefile b/t/Makefile index 2994eb5fa9..1222b22440 100644 --- a/t/Makefile +++ b/t/Makefile @@ -74,7 +74,7 @@ prove: pre-clean check-chainlint $(TEST_LINT) $(MAKE) clean-except-prove-cache $(T): - @echo "*** $@ ***"; '$(TEST_SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) + @echo "*** $@ ***"; '$(TEST_SHELL_PATH_SQ)' ./run-test.sh $@ $(GIT_TEST_OPTS) $(UNIT_TESTS): @echo "*** $@ ***"; $@ diff --git a/t/run-test.sh b/t/run-test.sh index 63328ac630..216c039641 100755 --- a/t/run-test.sh +++ b/t/run-test.sh @@ -13,6 +13,7 @@ case "$1" in exec "${TEST_SHELL_PATH}" "$@" ${TEST_OPTIONS} ;; *) + . ./unittest-lib.sh exec "$@" ;; esac diff --git a/t/unittest-lib.sh b/t/unittest-lib.sh new file mode 100644 index 0000000000..d53757f18b --- /dev/null +++ b/t/unittest-lib.sh @@ -0,0 +1,385 @@ +# Test framework for git. See t/README for usage. +# +# Copyright (c) 2005 Junio C Hamano +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see https://www.gnu.org/licenses/ . + +# Test the binaries we have just built. The tests are kept in +# t/ subdirectory and are run in 'trash directory' subdirectory. +if test -z "$TEST_DIRECTORY" +then + # ensure that TEST_DIRECTORY is an absolute path so that it + # is valid even if the current working directory is changed + TEST_DIRECTORY=$(pwd) +else + # The TEST_DIRECTORY will always be the path to the "t" + # directory in the git.git checkout. This is overridden by + # e.g. t/lib-subtest.sh, but only because its $(pwd) is + # different. Those tests still set "$TEST_DIRECTORY" to the + # same path. + # + # See use of "$GIT_BUILD_DIR" and "$TEST_DIRECTORY" below for + # hard assumptions about "$GIT_BUILD_DIR/t" existing and being + # the "$TEST_DIRECTORY", and e.g. "$TEST_DIRECTORY/helper" + # needing to exist. + TEST_DIRECTORY=$(cd "$TEST_DIRECTORY" && pwd) || exit 1 +fi +GIT_BUILD_DIR="${GIT_BUILD_DIR:-${TEST_DIRECTORY%/t}}" +if test "$TEST_DIRECTORY" = "$GIT_BUILD_DIR" +then + echo "PANIC: Running in a $TEST_DIRECTORY that doesn't end in '/t'?" >&2 + exit 1 +fi +if test -f "$GIT_BUILD_DIR/GIT-BUILD-DIR" +then + GIT_BUILD_DIR="$(cat "$GIT_BUILD_DIR/GIT-BUILD-DIR")" || exit 1 + # On Windows, we must convert Windows paths lest they contain a colon + case "$(uname -s)" in + *MINGW*) + GIT_BUILD_DIR="$(cygpath -au "$GIT_BUILD_DIR")" + ;; + esac +fi + + +if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +then + echo >&2 'error: GIT-BUILD-OPTIONS missing (has Git been built?).' + exit 1 +fi +. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +export PERL_PATH SHELL_PATH + +if test -z "$TEST_OUTPUT_DIRECTORY" +then + # Similarly, override this to store the test-results subdir + # elsewhere + TEST_OUTPUT_DIRECTORY=$TEST_DIRECTORY +fi + +# Explicitly set the default branch name for testing, to avoid the +# transitory "git init" warning under --verbose. +: ${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME:=master} +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +################################################################ +# It appears that people try to run tests without building... +"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null +if test $? != 1 +then + if test -n "$GIT_TEST_INSTALLED" + then + echo >&2 "error: there is no working Git at '$GIT_TEST_INSTALLED'" + else + echo >&2 'error: you do not seem to have built git yet.' + fi + exit 1 +fi + +TRASH_DIRECTORY="trash directory.unit-tests" +test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY" +case "$TRASH_DIRECTORY" in +/*) ;; # absolute path is good + *) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$TRASH_DIRECTORY" ;; +esac + +# Since bash 5.0, checkwinsize is enabled by default which does +# update the COLUMNS variable every time a non-builtin command +# completes, even for non-interactive shells. +# Disable that since we are aiming for repeatability. +test -n "$BASH_VERSION" && shopt -u checkwinsize 2>/dev/null + +# For repeatability, reset the environment to known value. +# TERM is sanitized below, after saving color control sequences. +LANG=C +LC_ALL=C +PAGER=cat +TZ=UTC +COLUMNS=80 +export LANG LC_ALL PAGER TZ COLUMNS +EDITOR=: + +# A call to "unset" with no arguments causes at least Solaris 10 +# /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets +# deriving from the command substitution clustered with the other +# ones. +unset VISUAL EMAIL LANGUAGE $("$PERL_PATH" -e ' + my @env = keys %ENV; + my $ok = join("|", qw( + TRACE + DEBUG + TEST + .*_TEST + PROVE + VALGRIND + UNZIP + PERF_ + CURL_VERBOSE + TRACE_CURL + BUILD_DIR + )); + my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); + print join("\n", @vars); +') +unset XDG_CACHE_HOME +unset XDG_CONFIG_HOME +unset GITPERLLIB +unset GIT_TRACE2_PARENT_NAME +unset GIT_TRACE2_PARENT_SID +TEST_AUTHOR_LOCALNAME=author +TEST_AUTHOR_DOMAIN=example.com +GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN} +GIT_AUTHOR_NAME='A U Thor' +GIT_AUTHOR_DATE='1112354055 +0200' +TEST_COMMITTER_LOCALNAME=committer +TEST_COMMITTER_DOMAIN=example.com +GIT_COMMITTER_EMAIL=${TEST_COMMITTER_LOCALNAME}@${TEST_COMMITTER_DOMAIN} +GIT_COMMITTER_NAME='C O Mitter' +GIT_COMMITTER_DATE='1112354055 +0200' +GIT_MERGE_VERBOSITY=5 +GIT_MERGE_AUTOEDIT=no +export GIT_MERGE_VERBOSITY GIT_MERGE_AUTOEDIT +export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME +export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME +export GIT_COMMITTER_DATE GIT_AUTHOR_DATE +export EDITOR + +GIT_DEFAULT_HASH="${GIT_TEST_DEFAULT_HASH:-sha1}" +export GIT_DEFAULT_HASH +GIT_DEFAULT_REF_FORMAT="${GIT_TEST_DEFAULT_REF_FORMAT:-files}" +export GIT_DEFAULT_REF_FORMAT +GIT_TEST_MERGE_ALGORITHM="${GIT_TEST_MERGE_ALGORITHM:-ort}" +export GIT_TEST_MERGE_ALGORITHM + +# Use specific version of the index file format +if test -n "${GIT_TEST_INDEX_VERSION:+isset}" +then + GIT_INDEX_VERSION="$GIT_TEST_INDEX_VERSION" + export GIT_INDEX_VERSION +fi + +if test -n "$GIT_TEST_PERL_FATAL_WARNINGS" +then + GIT_PERL_FATAL_WARNINGS=1 + export GIT_PERL_FATAL_WARNINGS +fi + +# Protect ourselves from common misconfiguration to export +# CDPATH into the environment +unset CDPATH + +unset GREP_OPTIONS +unset UNZIP + +case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in +1|2|true) + GIT_TRACE=4 + ;; +esac + +# Line feed +LF=' +' + +# Single quote +SQ=\' + +# UTF-8 ZERO WIDTH NON-JOINER, which HFS+ ignores +# when case-folding filenames +u200c=$(printf '\342\200\214') + +export _x05 _x35 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX + +test "x$TERM" != "xdumb" && ( + test -t 1 && + tput bold >/dev/null 2>&1 && + tput setaf 1 >/dev/null 2>&1 && + tput sgr0 >/dev/null 2>&1 + ) && + color=t + +if test -n "$color" +then + # Save the color control sequences now rather than run tput + # each time say_color() is called. This is done for two + # reasons: + # * TERM will be changed to dumb + # * HOME will be changed to a temporary directory and tput + # might need to read ~/.terminfo from the original HOME + # directory to get the control sequences + # Note: This approach assumes the control sequences don't end + # in a newline for any terminal of interest (command + # substitutions strip trailing newlines). Given that most + # (all?) terminals in common use are related to ECMA-48, this + # shouldn't be a problem. + say_color_error=$(tput bold; tput setaf 1) # bold red + say_color_skip=$(tput setaf 4) # blue + say_color_warn=$(tput setaf 3) # brown/yellow + say_color_pass=$(tput setaf 2) # green + say_color_info=$(tput setaf 6) # cyan + say_color_reset=$(tput sgr0) + say_color_="" # no formatting for normal text + say_color () { + test -z "$1" && test -n "$quiet" && return + eval "say_color_color=\$say_color_$1" + shift + printf "%s\\n" "$say_color_color$*$say_color_reset" + } +else + say_color() { + test -z "$1" && test -n "$quiet" && return + shift + printf "%s\n" "$*" + } +fi + +USER_TERM="$TERM" +TERM=dumb +export TERM USER_TERM + +_error_exit () { + GIT_EXIT_OK=t + exit 1 +} + +error () { + say_color error "error: $*" + _error_exit +} + +BUG () { + error >&7 "bug in the test script: $*" +} + +BAIL_OUT () { + test $# -ne 1 && BUG "1 param" + + # Do not change "Bail out! " string. It's part of TAP syntax: + # https://testanything.org/tap-specification.html + local bail_out="Bail out! " + local message="$1" + + say_color >&5 error $bail_out "$message" + _error_exit +} + +say () { + say_color info "$*" +} + +die () { + code=$? + if test -n "$GIT_EXIT_OK" + then + exit $code + else + echo >&52"FATAL: Unexpected exit with code $code" + exit 1 + fi +} + +GIT_EXIT_OK= +trap 'die' EXIT +# Disable '-x' tracing, because with some shells, notably dash, it +# prevents running the cleanup commands when a test script run with +# '--verbose-log -x' is interrupted. +trap '{ code=$?; set +x; } 2>/dev/null; exit $code' INT TERM HUP + +if test -n "$GIT_TEST_INSTALLED" +then + GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) || + error "Cannot run git from $GIT_TEST_INSTALLED." + PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR/t/helper:$PATH + GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH} +else # normal case, use ../bin-wrappers only unless $with_dashes: + if test -n "$no_bin_wrappers" + then + with_dashes=t + else + git_bin_dir="$GIT_BUILD_DIR/bin-wrappers" + if ! test -x "$git_bin_dir/git" + then + if test -z "$with_dashes" + then + say "$git_bin_dir/git is not executable; using GIT_EXEC_PATH" + fi + with_dashes=t + fi + PATH="$git_bin_dir:$PATH" + fi + GIT_EXEC_PATH=$GIT_BUILD_DIR + if test -n "$with_dashes" + then + PATH="$GIT_BUILD_DIR:$GIT_BUILD_DIR/t/helper:$PATH" + fi +fi +GIT_TEMPLATE_DIR="$GIT_TEST_TEMPLATE_DIR" +GIT_CONFIG_NOSYSTEM=1 +GIT_ATTR_NOSYSTEM=1 +GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/.." +export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_ATTR_NOSYSTEM GIT_CEILING_DIRECTORIES + +GITPERLLIB="$GIT_TEST_GITPERLLIB" +export GITPERLLIB +test -d "$GIT_TEMPLATE_DIR" || { + BAIL_OUT "You haven't built things yet, have you?" +} + +if ! test -x "$GIT_BUILD_DIR"/t/helper/test-tool$X +then + BAIL_OUT 'You need to build test-tool; Run "make t/helper/test-tool" in the source (toplevel) directory' +fi + +# Last-minute variable setup +USER_HOME="$HOME" +HOME="$TRASH_DIRECTORY" +GNUPGHOME="$HOME/gnupg-home-not-used" +export HOME GNUPGHOME USER_HOME + +# "rm -rf" existing trash directory, even if a previous run left it +# with bad permissions. +remove_trash_directory () { + dir="$1" + if ! rm -rf "$dir" 2>/dev/null + then + chmod -R u+rwx "$dir" + rm -rf "$dir" + fi + ! test -d "$dir" +} + +# Test repository +remove_trash_directory "$TRASH_DIRECTORY" || { + BAIL_OUT 'cannot prepare test area' +} + +remove_trash=t +if test -z "$TEST_NO_CREATE_REPO" +then + git init \ + ${TEST_CREATE_REPO_NO_TEMPLATE:+--template=} \ + "$TRASH_DIRECTORY" || + error "cannot run git init" +else + mkdir -p "$TRASH_DIRECTORY" +fi + + +# Ensure that no test accidentally triggers a Git command +# that runs the actual maintenance scheduler, affecting a user's +# system permanently. +# Tests that verify the scheduler integration must set this locally +# to avoid errors. +GIT_TEST_MAINT_SCHEDULER="none:exit 1" +export GIT_TEST_MAINT_SCHEDULER