aboutsummaryrefslogtreecommitdiff
path: root/packfile.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-02-23 13:48:00 -0800
committerJunio C Hamano <gitster@pobox.com>2026-02-23 13:48:00 -0800
commit703c97519dfac64291f79b1772e25c65d233e97e (patch)
treeeaa54faaa2f776393ba94dd35ef37cded5649f62 /packfile.c
parent7c02d39fc2ed2702223c7674f73150d9a7e61ba4 (diff)
parent3565faf28c2059c6260d53ac71a303b1c04b0a7b (diff)
downloadgit-703c97519dfac64291f79b1772e25c65d233e97e.tar.xz
Merge branch 'ps/odb-for-each-object' into ps/odb-sources
* ps/odb-for-each-object: odb: drop unused `for_each_{loose,packed}_object()` functions reachable: convert to use `odb_for_each_object()` builtin/pack-objects: use `packfile_store_for_each_object()` odb: introduce mtime fields for object info requests treewide: drop uses of `for_each_{loose,packed}_object()` treewide: enumerate promisor objects via `odb_for_each_object()` builtin/fsck: refactor to use `odb_for_each_object()` odb: introduce `odb_for_each_object()` packfile: introduce function to iterate through objects packfile: extract function to iterate through objects of a store object-file: introduce function to iterate through objects object-file: extract function to read object info from path odb: fix flags parameter to be unsigned odb: rename `FOR_EACH_OBJECT_*` flags
Diffstat (limited to 'packfile.c')
-rw-r--r--packfile.c184
1 files changed, 126 insertions, 58 deletions
diff --git a/packfile.c b/packfile.c
index 402c3b5dc7..57fbf51876 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1578,13 +1578,14 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
hashmap_add(&delta_base_cache, &ent->ent);
}
-int packed_object_info(struct packed_git *p,
- off_t obj_offset, struct object_info *oi)
+static int packed_object_info_with_index_pos(struct packed_git *p, off_t obj_offset,
+ uint32_t *maybe_index_pos, struct object_info *oi)
{
struct pack_window *w_curs = NULL;
unsigned long size;
off_t curpos = obj_offset;
enum object_type type = OBJ_NONE;
+ uint32_t pack_pos;
int ret;
/*
@@ -1619,16 +1620,35 @@ int packed_object_info(struct packed_git *p,
}
}
- if (oi->disk_sizep) {
- uint32_t pos;
- if (offset_to_pack_pos(p, obj_offset, &pos) < 0) {
+ if (oi->disk_sizep || (oi->mtimep && p->is_cruft)) {
+ if (offset_to_pack_pos(p, obj_offset, &pack_pos) < 0) {
error("could not find object at offset %"PRIuMAX" "
"in pack %s", (uintmax_t)obj_offset, p->pack_name);
ret = -1;
goto out;
}
+ }
+
+ if (oi->disk_sizep)
+ *oi->disk_sizep = pack_pos_to_offset(p, pack_pos + 1) - obj_offset;
+
+ if (oi->mtimep) {
+ if (p->is_cruft) {
+ uint32_t index_pos;
+
+ if (load_pack_mtimes(p) < 0)
+ die(_("could not load .mtimes for cruft pack '%s'"),
+ pack_basename(p));
- *oi->disk_sizep = pack_pos_to_offset(p, pos + 1) - obj_offset;
+ if (maybe_index_pos)
+ index_pos = *maybe_index_pos;
+ else
+ index_pos = pack_pos_to_index(p, pack_pos);
+
+ *oi->mtimep = nth_packed_mtime(p, index_pos);
+ } else {
+ *oi->mtimep = p->mtime;
+ }
}
if (oi->typep) {
@@ -1681,6 +1701,12 @@ out:
return ret;
}
+int packed_object_info(struct packed_git *p, off_t obj_offset,
+ struct object_info *oi)
+{
+ return packed_object_info_with_index_pos(p, obj_offset, NULL, oi);
+}
+
static void *unpack_compressed_entry(struct packed_git *p,
struct pack_window **w_curs,
off_t curpos,
@@ -2259,12 +2285,12 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid,
int for_each_object_in_pack(struct packed_git *p,
each_packed_object_fn cb, void *data,
- enum for_each_object_flags flags)
+ unsigned flags)
{
uint32_t i;
int r = 0;
- if (flags & FOR_EACH_OBJECT_PACK_ORDER) {
+ if (flags & ODB_FOR_EACH_OBJECT_PACK_ORDER) {
if (load_pack_revindex(p->repo, p))
return -1;
}
@@ -2285,7 +2311,7 @@ int for_each_object_in_pack(struct packed_git *p,
* - in pack-order, it is pack position, which we must
* convert to an index position in order to get the oid.
*/
- if (flags & FOR_EACH_OBJECT_PACK_ORDER)
+ if (flags & ODB_FOR_EACH_OBJECT_PACK_ORDER)
index_pos = pack_pos_to_index(p, i);
else
index_pos = i;
@@ -2301,75 +2327,114 @@ int for_each_object_in_pack(struct packed_git *p,
return r;
}
-int for_each_packed_object(struct repository *repo, each_packed_object_fn cb,
- void *data, enum for_each_object_flags flags)
+struct packfile_store_for_each_object_wrapper_data {
+ struct packfile_store *store;
+ const struct object_info *request;
+ odb_for_each_object_cb cb;
+ void *cb_data;
+};
+
+static int packfile_store_for_each_object_wrapper(const struct object_id *oid,
+ struct packed_git *pack,
+ uint32_t index_pos,
+ void *cb_data)
{
- struct odb_source *source;
- int r = 0;
- int pack_errors = 0;
+ struct packfile_store_for_each_object_wrapper_data *data = cb_data;
- odb_prepare_alternates(repo->objects);
+ if (data->request) {
+ off_t offset = nth_packed_object_offset(pack, index_pos);
+ struct object_info oi = *data->request;
- for (source = repo->objects->sources; source; source = source->next) {
- struct packfile_list_entry *e;
+ if (packed_object_info_with_index_pos(pack, offset,
+ &index_pos, &oi) < 0) {
+ mark_bad_packed_object(pack, oid);
+ return -1;
+ }
- source->packfiles->skip_mru_updates = true;
+ return data->cb(oid, &oi, data->cb_data);
+ } else {
+ return data->cb(oid, NULL, data->cb_data);
+ }
+}
- for (e = packfile_store_get_packs(source->packfiles); e; e = e->next) {
- struct packed_git *p = e->pack;
+int packfile_store_for_each_object(struct packfile_store *store,
+ const struct object_info *request,
+ odb_for_each_object_cb cb,
+ void *cb_data,
+ unsigned flags)
+{
+ struct packfile_store_for_each_object_wrapper_data data = {
+ .store = store,
+ .request = request,
+ .cb = cb,
+ .cb_data = cb_data,
+ };
+ struct packfile_list_entry *e;
+ int pack_errors = 0, ret;
- if ((flags & FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
- continue;
- if ((flags & FOR_EACH_OBJECT_PROMISOR_ONLY) &&
- !p->pack_promisor)
- continue;
- if ((flags & FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
- p->pack_keep_in_core)
- continue;
- if ((flags & FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
- p->pack_keep)
- continue;
- if (open_pack_index(p)) {
- pack_errors = 1;
- continue;
- }
+ store->skip_mru_updates = true;
- r = for_each_object_in_pack(p, cb, data, flags);
- if (r)
- break;
- }
+ for (e = packfile_store_get_packs(store); e; e = e->next) {
+ struct packed_git *p = e->pack;
- source->packfiles->skip_mru_updates = false;
+ if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
+ continue;
+ if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
+ !p->pack_promisor)
+ continue;
+ if ((flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
+ p->pack_keep_in_core)
+ continue;
+ if ((flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
+ p->pack_keep)
+ continue;
+ if (open_pack_index(p)) {
+ pack_errors = 1;
+ continue;
+ }
- if (r)
- break;
+ ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper,
+ &data, flags);
+ if (ret)
+ goto out;
}
- return r ? r : pack_errors;
+ ret = 0;
+
+out:
+ store->skip_mru_updates = false;
+
+ if (!ret && pack_errors)
+ ret = -1;
+ return ret;
}
+struct add_promisor_object_data {
+ struct repository *repo;
+ struct oidset *set;
+};
+
static int add_promisor_object(const struct object_id *oid,
- struct packed_git *pack,
- uint32_t pos UNUSED,
- void *set_)
+ struct object_info *oi UNUSED,
+ void *cb_data)
{
- struct oidset *set = set_;
+ struct add_promisor_object_data *data = cb_data;
struct object *obj;
int we_parsed_object;
- obj = lookup_object(pack->repo, oid);
+ obj = lookup_object(data->repo, oid);
if (obj && obj->parsed) {
we_parsed_object = 0;
} else {
we_parsed_object = 1;
- obj = parse_object_with_flags(pack->repo, oid,
+ obj = parse_object_with_flags(data->repo, oid,
PARSE_OBJECT_SKIP_HASH_CHECK);
}
if (!obj)
return 1;
- oidset_insert(set, oid);
+ oidset_insert(data->set, oid);
/*
* If this is a tree, commit, or tag, the objects it refers
@@ -2387,19 +2452,19 @@ static int add_promisor_object(const struct object_id *oid,
*/
return 0;
while (tree_entry_gently(&desc, &entry))
- oidset_insert(set, &entry.oid);
+ oidset_insert(data->set, &entry.oid);
if (we_parsed_object)
free_tree_buffer(tree);
} else if (obj->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *) obj;
struct commit_list *parents = commit->parents;
- oidset_insert(set, get_commit_tree_oid(commit));
+ oidset_insert(data->set, get_commit_tree_oid(commit));
for (; parents; parents = parents->next)
- oidset_insert(set, &parents->item->object.oid);
+ oidset_insert(data->set, &parents->item->object.oid);
} else if (obj->type == OBJ_TAG) {
struct tag *tag = (struct tag *) obj;
- oidset_insert(set, get_tagged_oid(tag));
+ oidset_insert(data->set, get_tagged_oid(tag));
}
return 0;
}
@@ -2411,10 +2476,13 @@ int is_promisor_object(struct repository *r, const struct object_id *oid)
if (!promisor_objects_prepared) {
if (repo_has_promisor_remote(r)) {
- for_each_packed_object(r, add_promisor_object,
- &promisor_objects,
- FOR_EACH_OBJECT_PROMISOR_ONLY |
- FOR_EACH_OBJECT_PACK_ORDER);
+ struct add_promisor_object_data data = {
+ .repo = r,
+ .set = &promisor_objects,
+ };
+
+ odb_for_each_object(r->objects, NULL, add_promisor_object, &data,
+ ODB_FOR_EACH_OBJECT_PROMISOR_ONLY | ODB_FOR_EACH_OBJECT_PACK_ORDER);
}
promisor_objects_prepared = 1;
}