From: Junio C Hamano Date: Tue, 18 Oct 2011 04:37:10 +0000 (-0700) Subject: Merge branch 'ph/push-to-delete-nothing' X-Git-Tag: v1.7.8-rc0~62 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/cdc2b2f32cbeab0e2496a59a03a52043f59ebea9?ds=inline;hp=-c Merge branch 'ph/push-to-delete-nothing' * ph/push-to-delete-nothing: receive-pack: don't pass non-existent refs to post-{receive,update} hooks Conflicts: builtin/receive-pack.c --- cdc2b2f32cbeab0e2496a59a03a52043f59ebea9 diff --combined builtin/receive-pack.c index e2d3f94661,b73f18a57b..261b610d24 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@@ -11,7 -11,6 +11,7 @@@ #include "transport.h" #include "string-list.h" #include "sha1-array.h" +#include "connected.h" static const char receive_pack_usage[] = "git receive-pack "; @@@ -26,8 -25,7 +26,8 @@@ static int deny_deletes static int deny_non_fast_forwards; static enum deny_action deny_current_branch = DENY_UNCONFIGURED; static enum deny_action deny_delete_current = DENY_UNCONFIGURED; -static int receive_fsck_objects; +static int receive_fsck_objects = -1; +static int transfer_fsck_objects = -1; static int receive_unpack_limit = -1; static int transfer_unpack_limit = -1; static int unpack_limit = 100; @@@ -81,11 -79,6 +81,11 @@@ static int receive_pack_config(const ch return 0; } + if (strcmp(var, "transfer.fsckobjects") == 0) { + transfer_fsck_objects = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "receive.denycurrentbranch")) { deny_current_branch = parse_deny_action(var, value); return 0; @@@ -154,7 -147,8 +154,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 */ @@@ -212,15 -206,21 +213,15 @@@ static int copy_to_sideband(int in, in return 0; } -static int run_receive_hook(struct command *commands, const char *hook_name) +typedef int (*feed_fn)(void *, const char **, size_t *); +static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state) { - static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4]; - struct command *cmd; struct child_process proc; struct async muxer; const char *argv[2]; - int have_input = 0, code; - - for (cmd = commands; !have_input && cmd; cmd = cmd->next) { - if (!cmd->error_string && !cmd->did_not_exist) - have_input = 1; - } + int code; - if (!have_input || access(hook_name, X_OK) < 0) + if (access(hook_name, X_OK) < 0) return 0; argv[0] = hook_name; @@@ -248,13 -248,15 +249,13 @@@ return code; } - for (cmd = commands; cmd; cmd = cmd->next) { - 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), - cmd->ref_name); - if (write_in_full(proc.in, buf, n) != n) - break; - } + while (1) { + const char *buf; + size_t n; + if (feed(feed_state, &buf, &n)) + break; + if (write_in_full(proc.in, buf, n) != n) + break; } close(proc.in); if (use_sideband) @@@ -262,47 -264,6 +263,51 @@@ return finish_command(&proc); } +struct receive_hook_feed_state { + struct command *cmd; ++ int skip_broken; + struct strbuf buf; +}; + +static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep) +{ + struct receive_hook_feed_state *state = state_; + struct command *cmd = state->cmd; + - while (cmd && cmd->error_string) ++ while (cmd && ++ state->skip_broken && (cmd->error_string || cmd->did_not_exist)) + cmd = cmd->next; + if (!cmd) + return -1; /* EOF */ + strbuf_reset(&state->buf); + strbuf_addf(&state->buf, "%s %s %s\n", + sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1), + cmd->ref_name); + state->cmd = cmd->next; + if (bufp) { + *bufp = state->buf.buf; + *sizep = state->buf.len; + } + return 0; +} + - static int run_receive_hook(struct command *commands, const char *hook_name) ++static int run_receive_hook(struct command *commands, const char *hook_name, ++ int skip_broken) +{ + struct receive_hook_feed_state state; + int status; + + strbuf_init(&state.buf, 0); + state.cmd = commands; ++ state.skip_broken = skip_broken; + if (feed_receive_hook(&state, NULL, NULL)) + return 0; + state.cmd = commands; + status = run_and_feed_hook(hook_name, feed_receive_hook, &state); + strbuf_release(&state.buf); + return status; +} + static int run_update_hook(struct command *cmd) { static const char update_hook[] = "hooks/update"; @@@ -396,7 -357,7 +401,7 @@@ static const char *update(struct comman struct ref_lock *lock; /* only refs/... are allowed */ - if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) { + if (prefixcmp(name, "refs/") || check_refname_format(name + 5, 0)) { rp_error("refusing to create funny ref '%s' remotely", name); return "funny refname"; } @@@ -485,8 -446,13 +490,13 @@@ 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); @@@ -517,7 -483,7 +527,7 @@@ static void run_update_post_hook(struc 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++; } @@@ -528,7 -494,7 +538,7 @@@ 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); @@@ -619,43 -585,6 +629,43 @@@ static void check_aliased_updates(struc string_list_clear(&ref_list, 0); } +static int command_singleton_iterator(void *cb_data, unsigned char sha1[20]) +{ + struct command **cmd_list = cb_data; + struct command *cmd = *cmd_list; + + if (!cmd) + return -1; /* end of list */ + *cmd_list = NULL; /* this returns only one */ + hashcpy(sha1, cmd->new_sha1); + return 0; +} + +static void set_connectivity_errors(struct command *commands) +{ + struct command *cmd; + + for (cmd = commands; cmd; cmd = cmd->next) { + struct command *singleton = cmd; + if (!check_everything_connected(command_singleton_iterator, + 0, &singleton)) + continue; + cmd->error_string = "missing necessary objects"; + } +} + +static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20]) +{ + struct command **cmd_list = cb_data; + struct command *cmd = *cmd_list; + + if (!cmd) + return -1; /* end of list */ + *cmd_list = cmd->next; + hashcpy(sha1, cmd->new_sha1); + return 0; +} + static void execute_commands(struct command *commands, const char *unpacker_error) { struct command *cmd; @@@ -667,12 -596,7 +677,12 @@@ return; } - if (run_receive_hook(commands, pre_receive_hook)) { + cmd = commands; + if (check_everything_connected(iterate_receive_command_list, + 0, &cmd)) + set_connectivity_errors(commands); + - if (run_receive_hook(commands, pre_receive_hook)) { ++ if (run_receive_hook(commands, pre_receive_hook, 0)) { for (cmd = commands; cmd; cmd = cmd->next) cmd->error_string = "pre-receive hook declined"; return; @@@ -756,11 -680,6 +766,11 @@@ static const char *unpack(void struct pack_header hdr; const char *hdr_err; char hdr_arg[38]; + int fsck_objects = (receive_fsck_objects >= 0 + ? receive_fsck_objects + : transfer_fsck_objects >= 0 + ? transfer_fsck_objects + : 0); hdr_err = parse_pack_header(&hdr); if (hdr_err) @@@ -773,7 -692,7 +783,7 @@@ int code, i = 0; const char *unpacker[4]; unpacker[i++] = "unpack-objects"; - if (receive_fsck_objects) + if (fsck_objects) unpacker[i++] = "--strict"; unpacker[i++] = hdr_arg; unpacker[i++] = NULL; @@@ -793,7 -712,7 +803,7 @@@ keeper[i++] = "index-pack"; keeper[i++] = "--stdin"; - if (receive_fsck_objects) + if (fsck_objects) keeper[i++] = "--strict"; keeper[i++] = "--fix-thin"; keeper[i++] = hdr_arg; @@@ -940,7 -859,7 +950,7 @@@ int cmd_receive_pack(int argc, const ch unlink_or_warn(pack_lockfile); if (report_status) report(commands, unpack_status); -- run_receive_hook(commands, post_receive_hook); ++ run_receive_hook(commands, post_receive_hook, 1); run_update_post_hook(commands); if (auto_gc) { const char *argv_gc_auto[] = {