summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/receive-pack.c16
-rw-r--r--sha1-array.c16
-rw-r--r--sha1-array.h6
3 files changed, 35 insertions, 3 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 6bb1281666..e1a687ad07 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -10,6 +10,7 @@
#include "remote.h"
#include "transport.h"
#include "string-list.h"
+#include "sha1-array.h"
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
@@ -731,14 +732,23 @@ static int delete_only(struct command *commands)
return 1;
}
-static void add_one_alternate_ref(const struct ref *ref, void *unused)
+static void add_one_alternate_sha1(const unsigned char sha1[20], void *unused)
{
- add_extra_ref(".have", ref->old_sha1, 0);
+ add_extra_ref(".have", sha1, 0);
+}
+
+static void collect_one_alternate_ref(const struct ref *ref, void *data)
+{
+ struct sha1_array *sa = data;
+ sha1_array_append(sa, ref->old_sha1);
}
static void add_alternate_refs(void)
{
- for_each_alternate_ref(add_one_alternate_ref, NULL);
+ struct sha1_array sa = SHA1_ARRAY_INIT;
+ for_each_alternate_ref(collect_one_alternate_ref, &sa);
+ sha1_array_for_each_unique(&sa, add_one_alternate_sha1, NULL);
+ sha1_array_clear(&sa);
}
int cmd_receive_pack(int argc, const char **argv, const char *prefix)
diff --git a/sha1-array.c b/sha1-array.c
index 5b75a5a35d..b2f47f98fb 100644
--- a/sha1-array.c
+++ b/sha1-array.c
@@ -41,3 +41,19 @@ void sha1_array_clear(struct sha1_array *array)
array->alloc = 0;
array->sorted = 0;
}
+
+void sha1_array_for_each_unique(struct sha1_array *array,
+ for_each_sha1_fn fn,
+ void *data)
+{
+ int i;
+
+ if (!array->sorted)
+ sha1_array_sort(array);
+
+ for (i = 0; i < array->nr; i++) {
+ if (i > 0 && !hashcmp(array->sha1[i], array->sha1[i-1]))
+ continue;
+ fn(array->sha1[i], data);
+ }
+}
diff --git a/sha1-array.h b/sha1-array.h
index 15d3b6b984..4499b5dad4 100644
--- a/sha1-array.h
+++ b/sha1-array.h
@@ -15,4 +15,10 @@ void sha1_array_sort(struct sha1_array *array);
int sha1_array_lookup(struct sha1_array *array, const unsigned char *sha1);
void sha1_array_clear(struct sha1_array *array);
+typedef void (*for_each_sha1_fn)(const unsigned char sha1[20],
+ void *data);
+void sha1_array_for_each_unique(struct sha1_array *array,
+ for_each_sha1_fn fn,
+ void *data);
+
#endif /* SHA1_ARRAY_H */