aboutsummaryrefslogtreecommitdiff
path: root/builtin/receive-pack.c
diff options
context:
space:
mode:
authorPang Yan Han <pangyanhan@gmail.com>2011-09-28 23:39:35 +0800
committerJunio C Hamano <gitster@pobox.com>2011-09-30 12:18:46 -0700
commit160b81ed819d870b7d098bf61b51c4bc959507f3 (patch)
treedd264c6422bb15d7c227a2a7bce0012bbcf42a3c /builtin/receive-pack.c
parent85e9c7e1d42849c5c3084a9da748608468310c0e (diff)
downloadgit-160b81ed819d870b7d098bf61b51c4bc959507f3.tar.gz
git-160b81ed819d870b7d098bf61b51c4bc959507f3.tar.xz
receive-pack: don't pass non-existent refs to post-{receive,update} hooks
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.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ae164da4d..b73f18a57 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);