diff --git a/cache.h b/cache.h index f438540f9b..6d14702df2 100644 --- a/cache.h +++ b/cache.h @@ -1633,6 +1633,11 @@ enum for_each_object_flags { /* Only iterate over packs obtained from the promisor remote. */ FOR_EACH_OBJECT_PROMISOR_ONLY = (1<<1), + + /* + * Visit objects within a pack in packfile order rather than .idx order + */ + FOR_EACH_OBJECT_PACK_ORDER = (1<<2), }; /* diff --git a/commit-graph.c b/commit-graph.c index b0a55ad128..69a0d1c203 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -730,7 +730,7 @@ void write_commit_graph(const char *obj_dir, die("error adding pack %s", packname.buf); if (open_pack_index(p)) die("error opening index for %s", packname.buf); - for_each_object_in_pack(p, add_packed_commits, &oids); + for_each_object_in_pack(p, add_packed_commits, &oids, 0); close_pack(p); } strbuf_release(&packname); diff --git a/packfile.c b/packfile.c index 9da8f6d728..ebcb5742ec 100644 --- a/packfile.c +++ b/packfile.c @@ -1885,19 +1885,30 @@ int has_pack_index(const unsigned char *sha1) return 1; } -int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data) +int for_each_object_in_pack(struct packed_git *p, + each_packed_object_fn cb, void *data, + enum for_each_object_flags flags) { uint32_t i; int r = 0; + if (flags & FOR_EACH_OBJECT_PACK_ORDER) + load_pack_revindex(p); + for (i = 0; i < p->num_objects; i++) { + uint32_t pos; struct object_id oid; - if (!nth_packed_object_oid(&oid, p, i)) - return error("unable to get sha1 of object %u in %s", - i, p->pack_name); + if (flags & FOR_EACH_OBJECT_PACK_ORDER) + pos = p->revindex[i].nr; + else + pos = i; - r = cb(&oid, p, i, data); + if (!nth_packed_object_oid(&oid, p, pos)) + return error("unable to get sha1 of object %u in %s", + pos, p->pack_name); + + r = cb(&oid, p, pos, data); if (r) break; } @@ -1922,7 +1933,7 @@ int for_each_packed_object(each_packed_object_fn cb, void *data, pack_errors = 1; continue; } - r = for_each_object_in_pack(p, cb, data); + r = for_each_object_in_pack(p, cb, data, flags); if (r) break; } diff --git a/packfile.h b/packfile.h index c86a8c2716..99411bdd85 100644 --- a/packfile.h +++ b/packfile.h @@ -153,8 +153,8 @@ extern int has_pack_index(const unsigned char *sha1); * By default, this includes both local and alternate packs. * * Note that some objects may appear twice if they are found in multiple packs. - * Each pack is visited in an unspecified order. Objects within a pack are - * visited in pack-idx order (i.e., sorted by oid). + * Each pack is visited in an unspecified order. By default, objects within a + * pack are visited in pack-idx order (i.e., sorted by oid). * * The list of flags can be found in cache.h. */ @@ -162,7 +162,9 @@ typedef int each_packed_object_fn(const struct object_id *oid, struct packed_git *pack, uint32_t pos, void *data); -int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn, void *data); +int for_each_object_in_pack(struct packed_git *p, + each_packed_object_fn, void *data, + enum for_each_object_flags flags); int for_each_packed_object(each_packed_object_fn, void *, enum for_each_object_flags flags);