diff options
author | Junio C Hamano <gitster@pobox.com> | 2014-12-01 15:29:54 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-01-08 14:28:43 -0800 |
commit | 0855331941b723b227e93b33955bbe0b45025659 (patch) | |
tree | 70c84e087db0451e9b439c094c809b33fc268535 /t | |
parent | 21b138d0f64d99b55e901f90d4211e036b881e64 (diff) | |
download | git-0855331941b723b227e93b33955bbe0b45025659.tar.gz git-0855331941b723b227e93b33955bbe0b45025659.tar.xz |
receive-pack: support push-to-checkout hook
When receive.denyCurrentBranch is set to updateInstead, a push that
tries to update the branch that is currently checked out is accepted
only when the index and the working tree exactly matches the
currently checked out commit, in which case the index and the
working tree are updated to match the pushed commit. Otherwise the
push is refused.
This hook can be used to customize this "push-to-deploy" logic. The
hook receives the commit with which the tip of the current branch is
going to be updated, and can decide what kind of local changes are
acceptable and how to update the index and the working tree to match
the updated tip of the current branch.
For example, the hook can simply run `git read-tree -u -m HEAD "$1"`
in order to emulate 'git fetch' that is run in the reverse direction
with `git push`, as the two-tree form of `read-tree -u -m` is
essentially the same as `git checkout` that switches branches while
keeping the local changes in the working tree that do not interfere
with the difference between the branches.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 't')
-rwxr-xr-x | t/t5516-fetch-push.sh | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 85c7fecd2..e4436c170 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1434,4 +1434,67 @@ test_expect_success 'receive.denyCurrentBranch = updateInstead' ' ' +test_expect_success 'updateInstead with push-to-checkout hook' ' + rm -fr testrepo && + git init testrepo && + ( + cd testrepo && + git pull .. master && + git reset --hard HEAD^^ && + git tag initial && + git config receive.denyCurrentBranch updateInstead && + write_script .git/hooks/push-to-checkout <<-\EOF + echo >&2 updating from $(git rev-parse HEAD) + echo >&2 updating to "$1" + + git update-index -q --refresh && + git read-tree -u -m HEAD "$1" || { + status=$? + echo >&2 read-tree failed + exit $status + } + EOF + ) && + + # Try pushing into a pristine + git push testrepo master && + ( + cd testrepo && + git diff --quiet && + git diff HEAD --quiet && + test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD) + ) && + + # Try pushing into a repository with conflicting change + ( + cd testrepo && + git reset --hard initial && + echo conflicting >path2 + ) && + test_must_fail git push testrepo master && + ( + cd testrepo && + test $(git rev-parse initial) = $(git rev-parse HEAD) && + test conflicting = "$(cat path2)" && + git diff-index --quiet --cached HEAD + ) && + + # Try pushing into a repository with unrelated change + ( + cd testrepo && + git reset --hard initial && + echo unrelated >path1 && + echo irrelevant >path5 && + git add path5 + ) && + git push testrepo master && + ( + cd testrepo && + test "$(cat path1)" = unrelated && + test "$(cat path5)" = irrelevant && + test "$(git diff --name-only --cached HEAD)" = path5 && + test $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD) + ) +' + test_done |