builtin/cat-file: filter objects via object database

When batching all objects, git-cat-file(1) reaches into the internals of
the object database and manually manages bitmaps to apply object
filters. This creates coupling between the command and the internals of
the respective backend.

Refactor git-cat-file(1) to use the new object filter option when
batching all objects. This significantly simplifies the logic and
ensures that we don't have to reach into internals of the "files" source
anymore.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Patrick Steinhardt 2026-07-15 08:22:39 +02:00 committed by Junio C Hamano
parent 204daf5e5c
commit bfa86e6a3a
1 changed files with 7 additions and 69 deletions

View File

@ -20,7 +20,6 @@
#include "userdiff.h"
#include "oid-array.h"
#include "packfile.h"
#include "pack-bitmap.h"
#include "object-file.h"
#include "object-name.h"
#include "odb.h"
@ -844,28 +843,6 @@ static int batch_one_object_oi(const struct object_id *oid,
return payload->callback(oid, NULL, 0, payload->payload);
}

static int batch_one_object_packed(const struct object_id *oid,
struct packed_git *pack,
uint32_t pos,
void *_payload)
{
struct for_each_object_payload *payload = _payload;
return payload->callback(oid, pack, nth_packed_object_offset(pack, pos),
payload->payload);
}

static int batch_one_object_bitmapped(const struct object_id *oid,
enum object_type type UNUSED,
int flags UNUSED,
uint32_t hash UNUSED,
struct packed_git *pack,
off_t offset,
void *_payload)
{
struct for_each_object_payload *payload = _payload;
return payload->callback(oid, pack, offset, payload->payload);
}

static void batch_each_object(struct batch_options *opt,
for_each_object_fn callback,
unsigned flags,
@ -875,56 +852,17 @@ static void batch_each_object(struct batch_options *opt,
.callback = callback,
.payload = _payload,
};
struct odb_source_info source_info;
struct object_info oi = {
.source_infop = &source_info,
};
struct odb_for_each_object_options opts = {
.flags = flags,
.filter = &opt->objects_filter,
};
struct bitmap_index *bitmap = NULL;
struct odb_source *source;

/*
* TODO: we still need to tap into implementation details of the object
* database sources. Ideally, we should extend `odb_for_each_object()`
* to handle object filters itself so that we can move the filtering
* logic into the individual sources.
*/
odb_prepare_alternates(the_repository->objects);
for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
int ret = odb_source_for_each_object(&files->loose->base, NULL, batch_one_object_oi,
&payload, &opts);
if (ret)
break;
}

if (opt->objects_filter.choice != LOFC_DISABLED &&
(bitmap = prepare_bitmap_git(the_repository)) &&
!for_each_bitmapped_object(bitmap, &opt->objects_filter,
batch_one_object_bitmapped, &payload)) {
struct packed_git *pack;

repo_for_each_pack(the_repository, pack) {
if (bitmap_index_contains_pack(bitmap, pack) ||
open_pack_index(pack))
continue;
for_each_object_in_pack(pack, batch_one_object_packed,
&payload, flags);
}
} else {
struct odb_source_info source_info;
struct object_info oi = {
.source_infop = &source_info,
};

for (source = the_repository->objects->sources; source; source = source->next) {
struct odb_source_files *files = odb_source_files_downcast(source);
int ret = odb_source_for_each_object(&files->packed->base, &oi,
batch_one_object_oi, &payload, &opts);
if (ret)
break;
}
}

free_bitmap_index(bitmap);
odb_for_each_object_ext(the_repository->objects, &oi,
batch_one_object_oi, &payload, &opts);
}

static int batch_objects(struct batch_options *opt)