sha1_file: add for_each iterators for loose and packed objects

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>

Jeff King committed Oct 15, 2014 at 18:41 UTC 660c889e46d185dc98ba78963528826728b0a55d
2 files changed +73
cache.h
+11
@@ -1272,6 +1272,17 @@ int for_each_loose_file_in_objdir(const char *path,
1272 each_loose_subdir_fn subdir_cb,
1273 void *data);
1274
1275 +/*
1276 + * Iterate over loose and packed objects in both the local
1277 + * repository and any alternates repositories.
1278 + */
1279 +typedef int each_packed_object_fn(const unsigned char *sha1,
1280 + struct packed_git *pack,
1281 + uint32_t pos,
1282 + void *data);
1283 +extern int for_each_loose_object(each_loose_object_fn, void *);
1284 +extern int for_each_packed_object(each_packed_object_fn, void *);
1285 +
1286 struct object_info {
1287 /* Request */
1288 enum object_type *typep;
sha1_file.c
+62
@@ -3348,3 +3348,65 @@ int for_each_loose_file_in_objdir(const char *path,
3348 strbuf_release(&buf);
3349 return r;
3350 }
3351 +
3352 +struct loose_alt_odb_data {
3353 + each_loose_object_fn *cb;
3354 + void *data;
3355 +};
3356 +
3357 +static int loose_from_alt_odb(struct alternate_object_database *alt,
3358 + void *vdata)
3359 +{
3360 + struct loose_alt_odb_data *data = vdata;
3361 + return for_each_loose_file_in_objdir(alt->base,
3362 + data->cb, NULL, NULL,
3363 + data->data);
3364 +}
3365 +
3366 +int for_each_loose_object(each_loose_object_fn cb, void *data)
3367 +{
3368 + struct loose_alt_odb_data alt;
3369 + int r;
3370 +
3371 + r = for_each_loose_file_in_objdir(get_object_directory(),
3372 + cb, NULL, NULL, data);
3373 + if (r)
3374 + return r;
3375 +
3376 + alt.cb = cb;
3377 + alt.data = data;
3378 + return foreach_alt_odb(loose_from_alt_odb, &alt);
3379 +}
3380 +
3381 +static int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn cb, void *data)
3382 +{
3383 + uint32_t i;
3384 + int r = 0;
3385 +
3386 + for (i = 0; i < p->num_objects; i++) {
3387 + const unsigned char *sha1 = nth_packed_object_sha1(p, i);
3388 +
3389 + if (!sha1)
3390 + return error("unable to get sha1 of object %u in %s",
3391 + i, p->pack_name);
3392 +
3393 + r = cb(sha1, p, i, data);
3394 + if (r)
3395 + break;
3396 + }
3397 + return r;
3398 +}
3399 +
3400 +int for_each_packed_object(each_packed_object_fn cb, void *data)
3401 +{
3402 + struct packed_git *p;
3403 + int r = 0;
3404 +
3405 + prepare_packed_git();
3406 + for (p = packed_git; p; p = p->next) {
3407 + r = for_each_object_in_pack(p, cb, data);
3408 + if (r)
3409 + break;
3410 + }
3411 + return r;
3412 +}