summaryrefslogtreecommitdiff
path: root/builtin/receive-pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r--builtin/receive-pack.c61
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)