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.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 1dbb8a0692..83492af05f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -21,6 +21,7 @@
#include "sigchain.h"
#include "fsck.h"
#include "tmp-objdir.h"
+#include "oidset.h"
static const char * const receive_pack_usage[] = {
N_("git receive-pack <git-dir>"),
@@ -250,8 +251,9 @@ static void show_ref(const char *path, const unsigned char *sha1)
}
static int show_ref_cb(const char *path_full, const struct object_id *oid,
- int flag, void *unused)
+ int flag, void *data)
{
+ struct oidset *seen = data;
const char *path = strip_namespace(path_full);
if (ref_is_hidden(path, path_full))
@@ -260,37 +262,38 @@ static int show_ref_cb(const char *path_full, const struct object_id *oid,
/*
* Advertise refs outside our current namespace as ".have"
* refs, so that the client can use them to minimize data
- * transfer but will otherwise ignore them. This happens to
- * cover ".have" that are thrown in by add_one_alternate_ref()
- * to mark histories that are complete in our alternates as
- * well.
+ * transfer but will otherwise ignore them.
*/
- if (!path)
+ if (!path) {
+ if (oidset_insert(seen, oid))
+ return 0;
path = ".have";
+ } else {
+ oidset_insert(seen, oid);
+ }
show_ref(path, oid->hash);
return 0;
}
-static int show_one_alternate_sha1(const unsigned char sha1[20], void *unused)
+static void show_one_alternate_ref(const char *refname,
+ const struct object_id *oid,
+ void *data)
{
- show_ref(".have", sha1);
- return 0;
-}
+ struct oidset *seen = data;
-static void collect_one_alternate_ref(const struct ref *ref, void *data)
-{
- struct sha1_array *sa = data;
- sha1_array_append(sa, ref->old_oid.hash);
+ if (oidset_insert(seen, oid))
+ return;
+
+ show_ref(".have", oid->hash);
}
static void write_head_info(void)
{
- struct sha1_array sa = SHA1_ARRAY_INIT;
+ static struct oidset seen = OIDSET_INIT;
- for_each_alternate_ref(collect_one_alternate_ref, &sa);
- sha1_array_for_each_unique(&sa, show_one_alternate_sha1, NULL);
- sha1_array_clear(&sa);
- for_each_ref(show_ref_cb, NULL);
+ for_each_ref(show_ref_cb, &seen);
+ for_each_alternate_ref(show_one_alternate_ref, &seen);
+ oidset_clear(&seen);
if (!sent_capabilities)
show_ref("capabilities^{}", null_sha1);
@@ -1414,7 +1417,7 @@ static void execute_commands(struct command *commands,
{
struct check_connected_options opt = CHECK_CONNECTED_INIT;
struct command *cmd;
- unsigned char sha1[20];
+ struct object_id oid;
struct iterate_data data;
struct async muxer;
int err_fd = 0;
@@ -1471,7 +1474,7 @@ static void execute_commands(struct command *commands,
check_aliased_updates(commands);
free(head_name_to_free);
- head_name = head_name_to_free = resolve_refdup("HEAD", 0, sha1, NULL);
+ head_name = head_name_to_free = resolve_refdup("HEAD", 0, oid.hash, NULL);
if (use_atomic)
execute_commands_atomic(commands, si);
@@ -1664,8 +1667,11 @@ static const char *unpack(int err_fd, struct shallow_info *si)
}
tmp_objdir = tmp_objdir_create();
- if (!tmp_objdir)
+ if (!tmp_objdir) {
+ if (err_fd > 0)
+ close(err_fd);
return "unable to create temporary object directory";
+ }
child.env = tmp_objdir_env(tmp_objdir);
/*