sha1_file: add for_each iterators for loose and packed objects
authorJeff King <peff@peff.net>
Wed, 15 Oct 2014 22:41:21 +0000 (18:41 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Oct 2014 17:10:41 +0000 (10:10 -0700)
We typically iterate over the reachable objects in a
repository by starting at the tips and walking the graph.
There's no easy way to iterate over all of the objects,
including unreachable ones. Let's provide a way of doing so.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
sha1_file.c
diff --git a/cache.h b/cache.h
index bdfbbcf7904bf7604b73b4a29b7e7162980c20aa..51ee856acccb90b0652072fcf721b7b99b069f1c 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1272,6 +1272,17 @@ int for_each_loose_file_in_objdir(const char *path,
                                  each_loose_subdir_fn subdir_cb,
                                  void *data);
 
                                  each_loose_subdir_fn subdir_cb,
                                  void *data);
 
+/*
+ * Iterate over loose and packed objects in both the local
+ * repository and any alternates repositories.
+ */
+typedef int each_packed_object_fn(const unsigned char *sha1,
+                                 struct packed_git *pack,
+                                 uint32_t pos,
+                                 void *data);
+extern int for_each_loose_object(each_loose_object_fn, void *);
+extern int for_each_packed_object(each_packed_object_fn, void *);
+
 struct object_info {
        /* Request */
        enum object_type *typep;
 struct object_info {
        /* Request */
        enum object_type *typep;
index fa08475c91d0312bd88c679d88340ab1aaab8928..55c65b7ef69a288c99051506485d1bd97d09d479 100644 (file)
@@ -3348,3 +3348,65 @@ int for_each_loose_file_in_objdir(const char *path,
        strbuf_release(&buf);
        return r;
 }
        strbuf_release(&buf);
        return r;
 }
+
+struct loose_alt_odb_data {
+       each_loose_object_fn *cb;
+       void *data;
+};
+
+static int loose_from_alt_odb(struct alternate_object_database *alt,
+                             void *vdata)
+{
+       struct loose_alt_odb_data *data = vdata;
+       return for_each_loose_file_in_objdir(alt->base,
+                                            data->cb, NULL, NULL,
+                                            data->data);
+}
+
+int for_each_loose_object(each_loose_object_fn cb, void *data)
+{
+       struct loose_alt_odb_data alt;
+       int r;
+
+       r = for_each_loose_file_in_objdir(get_object_directory(),
+                                         cb, NULL, NULL, data);
+       if (r)
+               return r;
+
+       alt.cb = cb;
+       alt.data = data;
+       return foreach_alt_odb(loose_from_alt_odb, &alt);
+}
+
+static int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data)
+{
+       uint32_t i;
+       int r = 0;
+
+       for (i = 0; i < p->num_objects; i++) {
+               const unsigned char *sha1 = nth_packed_object_sha1(p, i);
+
+               if (!sha1)
+                       return error("unable to get sha1 of object %u in %s",
+                                    i, p->pack_name);
+
+               r = cb(sha1, p, i, data);
+               if (r)
+                       break;
+       }
+       return r;
+}
+
+int for_each_packed_object(each_packed_object_fn cb, void *data)
+{
+       struct packed_git *p;
+       int r = 0;
+
+       prepare_packed_git();
+       for (p = packed_git; p; p = p->next) {
+               r = for_each_object_in_pack(p, cb, data);
+               if (r)
+                       break;
+       }
+       return r;
+}