mirror of
https://github.com/git/git
synced 2024-11-05 18:59:29 +00:00
0856f13aba
Hooks executed by Subversion are spawned with an empty environment. By default, not even variables like PATH will be propagated to them. In order to ensure that we're still able to find required executables, we thus write the current PATH variable into the hook script itself and then re-export it in t9164. This happens too late in the script though, as we already tried to execute the basename(1) utility before exporting the PATH variable. This tends to work on most platforms as the fallback value of PATH for Bash (see `getconf PATH`) is likely to contain this binary. But on more exotic platforms like NixOS this is not the case, and thus the test fails. While we could work around this issue by simply setting PATH earlier, it feels fragile to inject a user-controlled value into the script and have the shell interpret it. Instead, we can refactor the hook setup to write a `hooks-env` file that configures PATH for us. Like this, Subversion will know to set up the environment as expected for all hooks. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
224 lines
6.3 KiB
Bash
Executable file
224 lines
6.3 KiB
Bash
Executable file
#!/bin/sh
|
|
#
|
|
# Copyright (c) 2012 Robert Luberda
|
|
#
|
|
|
|
test_description='concurrent git svn dcommit'
|
|
|
|
. ./lib-git-svn.sh
|
|
|
|
|
|
|
|
test_expect_success 'setup svn repository' '
|
|
svn_cmd checkout "$svnrepo" work.svn &&
|
|
(
|
|
cd work.svn &&
|
|
echo >file && echo > auto_updated_file &&
|
|
svn_cmd add file auto_updated_file &&
|
|
svn_cmd commit -m "initial commit"
|
|
) &&
|
|
svn_cmd checkout "$svnrepo" work-auto-commits.svn
|
|
'
|
|
N=0
|
|
next_N()
|
|
{
|
|
N=$(( $N + 1 ))
|
|
}
|
|
|
|
# Setup SVN repository hooks to emulate SVN failures or concurrent commits
|
|
# The function adds
|
|
# either pre-commit hook, which causes SVN commit given in second argument
|
|
# to fail
|
|
# or post-commit hook, which creates a new commit (a new line added to
|
|
# auto_updated_file) after given SVN commit
|
|
# The first argument contains a type of the hook
|
|
# The second argument contains a number (not SVN revision) of commit
|
|
# the hook should be applied for (each time the hook is run, the given
|
|
# number is decreased by one until it gets 0, in which case the hook
|
|
# will execute its real action)
|
|
setup_hook()
|
|
{
|
|
hook_type="$1" # "pre-commit" or "post-commit"
|
|
skip_revs="$2"
|
|
[ "$hook_type" = "pre-commit" ] ||
|
|
[ "$hook_type" = "post-commit" ] ||
|
|
{ echo "ERROR: invalid argument ($hook_type)" \
|
|
"passed to setup_hook" >&2 ; return 1; }
|
|
echo "cnt=$skip_revs" > "$hook_type-counter"
|
|
rm -f "$rawsvnrepo/hooks/"*-commit # drop previous hooks
|
|
|
|
# Subversion hooks run with an empty environment by default. We thus
|
|
# need to propagate PATH so that we can find executables.
|
|
cat >"$rawsvnrepo/conf/hooks-env" <<-EOF
|
|
[default]
|
|
PATH = ${PATH}
|
|
EOF
|
|
|
|
hook="$rawsvnrepo/hooks/$hook_type"
|
|
cat > "$hook" <<- 'EOF1'
|
|
#!/bin/sh
|
|
set -e
|
|
cd "$1/.." # "$1" is repository location
|
|
exec >> svn-hook.log 2>&1
|
|
hook="$(basename "$0")"
|
|
echo "*** Executing $hook $@"
|
|
set -x
|
|
. ./$hook-counter
|
|
cnt="$(($cnt - 1))"
|
|
echo "cnt=$cnt" > ./$hook-counter
|
|
[ "$cnt" = "0" ] || exit 0
|
|
EOF1
|
|
if [ "$hook_type" = "pre-commit" ]; then
|
|
echo "echo 'commit disallowed' >&2; exit 1" >>"$hook"
|
|
else
|
|
echo "svnconf=\"$svnconf\"" >>"$hook"
|
|
cat >>"$hook" <<- 'EOF2'
|
|
cd work-auto-commits.svn
|
|
svn up --config-dir "$svnconf"
|
|
echo "$$" >> auto_updated_file
|
|
svn commit --config-dir "$svnconf" \
|
|
-m "auto-committing concurrent change"
|
|
exit 0
|
|
EOF2
|
|
fi
|
|
chmod 755 "$hook"
|
|
}
|
|
|
|
check_contents()
|
|
{
|
|
gitdir="$1"
|
|
(cd ../work.svn && svn_cmd up) &&
|
|
test_cmp file ../work.svn/file &&
|
|
test_cmp auto_updated_file ../work.svn/auto_updated_file
|
|
}
|
|
|
|
test_expect_success 'check if post-commit hook creates a concurrent commit' '
|
|
setup_hook post-commit 1 &&
|
|
(
|
|
cd work.svn &&
|
|
cp auto_updated_file au_file_saved &&
|
|
echo 1 >> file &&
|
|
svn_cmd commit -m "changing file" &&
|
|
svn_cmd up &&
|
|
! test_cmp auto_updated_file au_file_saved
|
|
)
|
|
'
|
|
|
|
test_expect_success 'check if pre-commit hook fails' '
|
|
setup_hook pre-commit 2 &&
|
|
(
|
|
cd work.svn &&
|
|
echo 2 >> file &&
|
|
svn_cmd commit -m "changing file once again" &&
|
|
echo 3 >> file &&
|
|
! svn_cmd commit -m "this commit should fail" &&
|
|
svn_cmd revert file
|
|
)
|
|
'
|
|
|
|
test_expect_success 'dcommit error handling' '
|
|
setup_hook pre-commit 2 &&
|
|
next_N && git svn clone "$svnrepo" work$N.git &&
|
|
(
|
|
cd work$N.git &&
|
|
echo 1 >> file && git commit -am "commit change $N.1" &&
|
|
echo 2 >> file && git commit -am "commit change $N.2" &&
|
|
echo 3 >> file && git commit -am "commit change $N.3" &&
|
|
# should fail to dcommit 2nd and 3rd change
|
|
# but still should leave the repository in reasonable state
|
|
test_must_fail git svn dcommit &&
|
|
git update-index --refresh &&
|
|
git show HEAD~2 | grep -q git-svn-id &&
|
|
! git show HEAD~1 | grep -q git-svn-id &&
|
|
! git show HEAD | grep -q git-svn-id
|
|
)
|
|
'
|
|
|
|
test_expect_success 'dcommit concurrent change in non-changed file' '
|
|
setup_hook post-commit 2 &&
|
|
next_N && git svn clone "$svnrepo" work$N.git &&
|
|
(
|
|
cd work$N.git &&
|
|
echo 1 >> file && git commit -am "commit change $N.1" &&
|
|
echo 2 >> file && git commit -am "commit change $N.2" &&
|
|
echo 3 >> file && git commit -am "commit change $N.3" &&
|
|
# should rebase and leave the repository in reasonable state
|
|
git svn dcommit &&
|
|
git update-index --refresh &&
|
|
check_contents &&
|
|
git show HEAD~3 | grep -q git-svn-id &&
|
|
git show HEAD~2 | grep -q git-svn-id &&
|
|
git show HEAD~1 | grep -q auto-committing &&
|
|
git show HEAD | grep -q git-svn-id
|
|
)
|
|
'
|
|
|
|
# An utility function used in the following test
|
|
delete_first_line()
|
|
{
|
|
file="$1" &&
|
|
sed 1d < "$file" > "${file}.tmp" &&
|
|
rm "$file" &&
|
|
mv "${file}.tmp" "$file"
|
|
}
|
|
|
|
test_expect_success 'dcommit concurrent non-conflicting change' '
|
|
setup_hook post-commit 2 &&
|
|
next_N && git svn clone "$svnrepo" work$N.git &&
|
|
(
|
|
cd work$N.git &&
|
|
cat file >> auto_updated_file &&
|
|
git commit -am "commit change $N.1" &&
|
|
delete_first_line auto_updated_file &&
|
|
git commit -am "commit change $N.2" &&
|
|
delete_first_line auto_updated_file &&
|
|
git commit -am "commit change $N.3" &&
|
|
# should rebase and leave the repository in reasonable state
|
|
git svn dcommit &&
|
|
git update-index --refresh &&
|
|
check_contents &&
|
|
git show HEAD~3 | grep -q git-svn-id &&
|
|
git show HEAD~2 | grep -q git-svn-id &&
|
|
git show HEAD~1 | grep -q auto-committing &&
|
|
git show HEAD | grep -q git-svn-id
|
|
)
|
|
'
|
|
|
|
test_expect_success 'dcommit --no-rebase concurrent non-conflicting change' '
|
|
setup_hook post-commit 2 &&
|
|
next_N && git svn clone "$svnrepo" work$N.git &&
|
|
(
|
|
cd work$N.git &&
|
|
cat file >> auto_updated_file &&
|
|
git commit -am "commit change $N.1" &&
|
|
delete_first_line auto_updated_file &&
|
|
git commit -am "commit change $N.2" &&
|
|
delete_first_line auto_updated_file &&
|
|
git commit -am "commit change $N.3" &&
|
|
# should fail as rebase is needed
|
|
test_must_fail git svn dcommit --no-rebase &&
|
|
# but should leave HEAD unchanged
|
|
git update-index --refresh &&
|
|
! git show HEAD~2 | grep -q git-svn-id &&
|
|
! git show HEAD~1 | grep -q git-svn-id &&
|
|
! git show HEAD | grep -q git-svn-id
|
|
)
|
|
'
|
|
|
|
test_expect_success 'dcommit fails on concurrent conflicting change' '
|
|
setup_hook post-commit 1 &&
|
|
next_N && git svn clone "$svnrepo" work$N.git &&
|
|
(
|
|
cd work$N.git &&
|
|
echo a >> file &&
|
|
git commit -am "commit change $N.1" &&
|
|
echo b >> auto_updated_file &&
|
|
git commit -am "commit change $N.2" &&
|
|
echo c >> auto_updated_file &&
|
|
git commit -am "commit change $N.3" &&
|
|
test_must_fail git svn dcommit && # rebase should fail
|
|
test_must_fail git update-index --refresh
|
|
)
|
|
'
|
|
|
|
test_done
|