diff options
author | Junio C Hamano <gitster@pobox.com> | 2014-12-02 02:29:54 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-01-09 01:28:43 +0300 |
commit | 0855331941b723b227e93b33955bbe0b45025659 (patch) | |
tree | 70c84e087db0451e9b439c094c809b33fc268535 /builtin/receive-pack.c | |
parent | 21b138d0f64d99b55e901f90d4211e036b881e64 (diff) |
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 'builtin/receive-pack.c')
-rw-r--r-- | builtin/receive-pack.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 11800cda2e..fc8ec9c3fa 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -797,6 +797,20 @@ static const char *push_to_deploy(unsigned char *sha1, return NULL; } +static const char *push_to_checkout_hook = "push-to-checkout"; + +static const char *push_to_checkout(unsigned char *sha1, + struct argv_array *env, + const char *work_tree) +{ + argv_array_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree)); + if (run_hook_le(env->argv, push_to_checkout_hook, + sha1_to_hex(sha1), NULL)) + return "push-to-checkout hook declined"; + else + return NULL; +} + static const char *update_worktree(unsigned char *sha1) { const char *retval; @@ -808,7 +822,10 @@ static const char *update_worktree(unsigned char *sha1) argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(get_git_dir())); - retval = push_to_deploy(sha1, &env, work_tree); + if (!find_hook(push_to_checkout_hook)) + retval = push_to_deploy(sha1, &env, work_tree); + else + retval = push_to_checkout(sha1, &env, work_tree); argv_array_clear(&env); return retval; |