diff options
author | Pang Yan Han <pangyanhan@gmail.com> | 2011-09-28 23:39:35 +0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-09-30 12:18:46 -0700 |
commit | 160b81ed819d870b7d098bf61b51c4bc959507f3 (patch) | |
tree | dd264c6422bb15d7c227a2a7bce0012bbcf42a3c /builtin/receive-pack.c | |
parent | 85e9c7e1d42849c5c3084a9da748608468310c0e (diff) | |
download | git-160b81ed819d870b7d098bf61b51c4bc959507f3.tar.gz |
receive-pack: don't pass non-existent refs to post-{receive,update} hooksph/push-to-delete-nothing
When a push specifies deletion of non-existent refs, the post post-receive and
post-update hooks receive them as input/arguments.
For instance, for the following push, where refs/heads/nonexistent is a ref
which does not exist on the remote side:
git push origin :refs/heads/nonexistent
the post-receive hook receives from standard input:
<null-sha1> SP <null-sha1> SP refs/heads/nonexistent
and the post-update hook receives as arguments:
refs/heads/nonexistent
which does not make sense since it is a no-op.
Teach receive-pack not to pass non-existent refs to the post-receive and
post-update hooks. If the push only attempts to delete non-existent refs,
these hooks are not even called.
The update and pre-receive hooks are still notified about attempted
deletion of non-existent refs to give them a chance to inspect the
situation and act on it.
[jc: mild fix-ups to avoid introducing an extra list; also added fixes to
some tests]
Signed-off-by: Pang Yan Han <pangyanhan@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r-- | builtin/receive-pack.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index ae164da4d5..b73f18a57b 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -147,7 +147,8 @@ static void write_head_info(void) struct command { struct command *next; const char *error_string; - unsigned int skip_update; + unsigned int skip_update:1, + did_not_exist:1; unsigned char old_sha1[20]; unsigned char new_sha1[20]; char ref_name[FLEX_ARRAY]; /* more */ @@ -215,7 +216,7 @@ static int run_receive_hook(struct command *commands, const char *hook_name) int have_input = 0, code; for (cmd = commands; !have_input && cmd; cmd = cmd->next) { - if (!cmd->error_string) + if (!cmd->error_string && !cmd->did_not_exist) have_input = 1; } @@ -248,7 +249,7 @@ static int run_receive_hook(struct command *commands, const char *hook_name) } for (cmd = commands; cmd; cmd = cmd->next) { - if (!cmd->error_string) { + if (!cmd->error_string && !cmd->did_not_exist) { size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n", sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1), @@ -445,8 +446,13 @@ static const char *update(struct command *cmd) if (is_null_sha1(new_sha1)) { if (!parse_object(old_sha1)) { - rp_warning("Allowing deletion of corrupt ref."); old_sha1 = NULL; + if (ref_exists(name)) { + rp_warning("Allowing deletion of corrupt ref."); + } else { + rp_warning("Deleting a non-existent ref."); + cmd->did_not_exist = 1; + } } if (delete_ref(namespaced_name, old_sha1, 0)) { rp_error("failed to delete %s", name); @@ -477,7 +483,7 @@ static void run_update_post_hook(struct command *commands) struct child_process proc; for (argc = 0, cmd = commands; cmd; cmd = cmd->next) { - if (cmd->error_string) + if (cmd->error_string || cmd->did_not_exist) continue; argc++; } @@ -488,7 +494,7 @@ static void run_update_post_hook(struct command *commands) for (argc = 1, cmd = commands; cmd; cmd = cmd->next) { char *p; - if (cmd->error_string) + if (cmd->error_string || cmd->did_not_exist) continue; p = xmalloc(strlen(cmd->ref_name) + 1); strcpy(p, cmd->ref_name); |