diff options
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r-- | builtin/receive-pack.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index f7cd180252..e6b3879a5b 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -20,6 +20,7 @@ #include "gpg-interface.h" #include "sigchain.h" #include "fsck.h" +#include "tmp-objdir.h" static const char * const receive_pack_usage[] = { N_("git receive-pack <git-dir>"), @@ -86,6 +87,8 @@ static enum { } use_keepalive; static int keepalive_in_sec = 5; +static struct tmp_objdir *tmp_objdir; + static enum deny_action parse_deny_action(const char *var, const char *value) { if (value) { @@ -224,7 +227,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb) static void show_ref(const char *path, const unsigned char *sha1) { if (sent_capabilities) { - packet_write(1, "%s %s\n", sha1_to_hex(sha1), path); + packet_write_fmt(1, "%s %s\n", sha1_to_hex(sha1), path); } else { struct strbuf cap = STRBUF_INIT; @@ -239,7 +242,7 @@ static void show_ref(const char *path, const unsigned char *sha1) if (advertise_push_options) strbuf_addstr(&cap, " push-options"); strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized()); - packet_write(1, "%s %s%c%s\n", + packet_write_fmt(1, "%s %s%c%s\n", sha1_to_hex(sha1), path, 0, cap.buf); strbuf_release(&cap); sent_capabilities = 1; @@ -664,6 +667,9 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, } else argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT"); + if (tmp_objdir) + argv_array_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir)); + if (use_sideband) { memset(&muxer, 0, sizeof(muxer)); muxer.proc = copy_to_sideband; @@ -763,6 +769,7 @@ static int run_update_hook(struct command *cmd) proc.stdout_to_stderr = 1; proc.err = use_sideband ? -1 : 0; proc.argv = argv; + proc.env = tmp_objdir_env(tmp_objdir); code = start_command(&proc); if (code) @@ -834,6 +841,7 @@ static int update_shallow_ref(struct command *cmd, struct shallow_info *si) !delayed_reachability_test(si, i)) sha1_array_append(&extra, si->shallow->sha1[i]); + opt.env = tmp_objdir_env(tmp_objdir); setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra); if (check_connected(command_singleton_iterator, cmd, &opt)) { rollback_lock_file(&shallow_lock); @@ -1155,10 +1163,6 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) struct string_list_item *item; struct command *dst_cmd; unsigned char sha1[GIT_SHA1_RAWSZ]; - char cmd_oldh[GIT_SHA1_HEXSZ + 1], - cmd_newh[GIT_SHA1_HEXSZ + 1], - dst_oldh[GIT_SHA1_HEXSZ + 1], - dst_newh[GIT_SHA1_HEXSZ + 1]; int flag; strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name); @@ -1189,14 +1193,14 @@ static void check_aliased_update(struct command *cmd, struct string_list *list) dst_cmd->skip_update = 1; - find_unique_abbrev_r(cmd_oldh, cmd->old_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(cmd_newh, cmd->new_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(dst_oldh, dst_cmd->old_sha1, DEFAULT_ABBREV); - find_unique_abbrev_r(dst_newh, dst_cmd->new_sha1, DEFAULT_ABBREV); rp_error("refusing inconsistent update between symref '%s' (%s..%s) and" " its target '%s' (%s..%s)", - cmd->ref_name, cmd_oldh, cmd_newh, - dst_cmd->ref_name, dst_oldh, dst_newh); + cmd->ref_name, + find_unique_abbrev(cmd->old_sha1, DEFAULT_ABBREV), + find_unique_abbrev(cmd->new_sha1, DEFAULT_ABBREV), + dst_cmd->ref_name, + find_unique_abbrev(dst_cmd->old_sha1, DEFAULT_ABBREV), + find_unique_abbrev(dst_cmd->new_sha1, DEFAULT_ABBREV)); cmd->error_string = dst_cmd->error_string = "inconsistent aliased update"; @@ -1241,12 +1245,17 @@ static void set_connectivity_errors(struct command *commands, for (cmd = commands; cmd; cmd = cmd->next) { struct command *singleton = cmd; + struct check_connected_options opt = CHECK_CONNECTED_INIT; + if (shallow_update && si->shallow_ref[cmd->index]) /* to be checked in update_shallow_ref() */ continue; + + opt.env = tmp_objdir_env(tmp_objdir); if (!check_connected(command_singleton_iterator, &singleton, - NULL)) + &opt)) continue; + cmd->error_string = "missing necessary objects"; } } @@ -1429,6 +1438,7 @@ static void execute_commands(struct command *commands, data.si = si; opt.err_fd = err_fd; opt.progress = err_fd && !quiet; + opt.env = tmp_objdir_env(tmp_objdir); if (check_connected(iterate_receive_command_list, &data, &opt)) set_connectivity_errors(commands, si); @@ -1445,6 +1455,19 @@ static void execute_commands(struct command *commands, return; } + /* + * Now we'll start writing out refs, which means the objects need + * to be in their final positions so that other processes can see them. + */ + if (tmp_objdir_migrate(tmp_objdir) < 0) { + for (cmd = commands; cmd; cmd = cmd->next) { + if (!cmd->error_string) + cmd->error_string = "unable to migrate objects to permanent storage"; + } + return; + } + tmp_objdir = NULL; + check_aliased_updates(commands); free(head_name_to_free); @@ -1640,6 +1663,18 @@ static const char *unpack(int err_fd, struct shallow_info *si) argv_array_push(&child.args, alt_shallow_file); } + tmp_objdir = tmp_objdir_create(); + if (!tmp_objdir) + return "unable to create temporary object directory"; + child.env = tmp_objdir_env(tmp_objdir); + + /* + * Normally we just pass the tmp_objdir environment to the child + * processes that do the heavy lifting, but we may need to see these + * objects ourselves to set up shallow information. + */ + tmp_objdir_add_as_alternate(tmp_objdir); + if (ntohl(hdr.hdr_entries) < unpack_limit) { argv_array_pushl(&child.args, "unpack-objects", hdr_arg, NULL); if (quiet) |