From bd1855b89760cc0f9a185010a0d92d2e11a73132 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:17 +0100 Subject: odb: rename `FOR_EACH_OBJECT_*` flags Rename the `FOR_EACH_OBJECT_*` flags to have an `ODB_` prefix. This prepares us for a new upcoming `odb_for_each_object()` function and ensures that both the function and its flags have the same prefix. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index e7e4c3348f..64e9e239dc 100644 --- a/object-file.c +++ b/object-file.c @@ -1789,7 +1789,7 @@ int for_each_loose_file_in_source(struct odb_source *source, int for_each_loose_object(struct object_database *odb, each_loose_object_fn cb, void *data, - enum for_each_object_flags flags) + enum odb_for_each_object_flags flags) { struct odb_source *source; @@ -1800,7 +1800,7 @@ int for_each_loose_object(struct object_database *odb, if (r) return r; - if (flags & FOR_EACH_OBJECT_LOCAL_ONLY) + if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) break; } -- cgit v1.3-5-g9baa From 6358da200fffc7f010f079c3f64ed77f10cd751d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:18 +0100 Subject: odb: fix flags parameter to be unsigned The `flags` parameter accepted by various `for_each_object()` functions is a bitfield of multiple flags. Such parameters are typically unsigned in the Git codebase, but we use `enum odb_for_each_object_flags` in some places. Adapt these function signatures to use the correct type. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 3 ++- object-file.h | 3 ++- packfile.c | 4 ++-- packfile.h | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 64e9e239dc..8fa461dd59 100644 --- a/object-file.c +++ b/object-file.c @@ -414,7 +414,8 @@ static int parse_loose_header(const char *hdr, struct object_info *oi) int odb_source_loose_read_object_info(struct odb_source *source, const struct object_id *oid, - struct object_info *oi, int flags) + struct object_info *oi, + unsigned flags) { int ret; int fd; diff --git a/object-file.h b/object-file.h index 42bb50e10c..2acf19fb91 100644 --- a/object-file.h +++ b/object-file.h @@ -47,7 +47,8 @@ void odb_source_loose_reprepare(struct odb_source *source); int odb_source_loose_read_object_info(struct odb_source *source, const struct object_id *oid, - struct object_info *oi, int flags); + struct object_info *oi, + unsigned flags); int odb_source_loose_read_object_stream(struct odb_read_stream **out, struct odb_source *source, diff --git a/packfile.c b/packfile.c index b65f0b43f1..79fe64a25b 100644 --- a/packfile.c +++ b/packfile.c @@ -2259,7 +2259,7 @@ 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 odb_for_each_object_flags flags) + unsigned flags) { uint32_t i; int r = 0; @@ -2302,7 +2302,7 @@ int for_each_object_in_pack(struct packed_git *p, } int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, - void *data, enum odb_for_each_object_flags flags) + void *data, unsigned flags) { struct odb_source *source; int r = 0; diff --git a/packfile.h b/packfile.h index 15551258bd..447c44c4a7 100644 --- a/packfile.h +++ b/packfile.h @@ -339,9 +339,9 @@ typedef int each_packed_object_fn(const struct object_id *oid, void *data); int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn, void *data, - enum odb_for_each_object_flags flags); + unsigned flags); int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, - void *data, enum odb_for_each_object_flags flags); + void *data, unsigned flags); /* A hook to report invalid files in pack directory */ #define PACKDIR_FILE_PACK 1 -- cgit v1.3-5-g9baa From 6ecab3cdf67012592734ed9493db634d39326d43 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:19 +0100 Subject: object-file: extract function to read object info from path Extract a new function that allows us to read object info for a specific loose object via a user-supplied path. This function will be used in a subsequent commit. Note that this also allows us to drop `stat_loose_object()`, which is a simple wrapper around `odb_loose_path()` plus lstat(3p). Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 8fa461dd59..a651129426 100644 --- a/object-file.c +++ b/object-file.c @@ -165,30 +165,13 @@ int stream_object_signature(struct repository *r, const struct object_id *oid) } /* - * Find "oid" as a loose object in given source. - * Returns 0 on success, negative on failure. + * Find "oid" as a loose object in given source, open the object and return its + * file descriptor. Returns the file descriptor on success, negative on failure. * * The "path" out-parameter will give the path of the object we found (if any). * Note that it may point to static storage and is only valid until another * call to stat_loose_object(). */ -static int stat_loose_object(struct odb_source_loose *loose, - const struct object_id *oid, - struct stat *st, const char **path) -{ - static struct strbuf buf = STRBUF_INIT; - - *path = odb_loose_path(loose->source, &buf, oid); - if (!lstat(*path, st)) - return 0; - - return -1; -} - -/* - * Like stat_loose_object(), but actually open the object and return the - * descriptor. See the caveats on the "path" parameter above. - */ static int open_loose_object(struct odb_source_loose *loose, const struct object_id *oid, const char **path) { @@ -412,7 +395,8 @@ static int parse_loose_header(const char *hdr, struct object_info *oi) return 0; } -int odb_source_loose_read_object_info(struct odb_source *source, +static int read_object_info_from_path(struct odb_source *source, + const char *path, const struct object_id *oid, struct object_info *oi, unsigned flags) @@ -420,7 +404,6 @@ int odb_source_loose_read_object_info(struct odb_source *source, int ret; int fd; unsigned long mapsize; - const char *path; void *map = NULL; git_zstream stream, *stream_to_end = NULL; char hdr[MAX_HEADER_LEN]; @@ -443,7 +426,7 @@ int odb_source_loose_read_object_info(struct odb_source *source, goto out; } - if (stat_loose_object(source->loose, oid, &st, &path) < 0) { + if (lstat(path, &st) < 0) { ret = -1; goto out; } @@ -455,7 +438,7 @@ int odb_source_loose_read_object_info(struct odb_source *source, goto out; } - fd = open_loose_object(source->loose, oid, &path); + fd = git_open(path); if (fd < 0) { if (errno != ENOENT) error_errno(_("unable to open loose object %s"), oid_to_hex(oid)); @@ -534,6 +517,16 @@ out: return ret; } +int odb_source_loose_read_object_info(struct odb_source *source, + const struct object_id *oid, + struct object_info *oi, + unsigned flags) +{ + static struct strbuf buf = STRBUF_INIT; + odb_loose_path(source, &buf, oid); + return read_object_info_from_path(source, buf.buf, oid, oi, flags); +} + static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c, const void *buf, unsigned long len, struct object_id *oid, -- cgit v1.3-5-g9baa From cde615b6f05228cd7cf125de6bf5757381f65381 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:20 +0100 Subject: object-file: introduce function to iterate through objects We have multiple divergent interfaces to iterate through objects of a specific backend: - `for_each_loose_object()` yields all loose objects. - `for_each_packed_object()` (somewhat obviously) yields all packed objects. These functions have different function signatures, which makes it hard to create a common abstraction layer that covers both of these. Introduce a new function `odb_source_loose_for_each_object()` to plug this gap. This function doesn't take any data specific to loose objects, but instead it accepts a `struct object_info` that will be populated the exact same as if `odb_source_loose_read_object()` was called. The benefit of this new interface is that we can continue to pass backend-specific data, as `struct object_info` contains a union for these exact use cases. This will allow us to unify how we iterate through objects across both loose and packed objects in a subsequent commit. The `for_each_loose_object()` function continues to exist for now, but it will be removed at the end of this patch series. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ object-file.h | 11 +++++++++++ odb.h | 12 ++++++++++++ 3 files changed, 71 insertions(+) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index a651129426..ef2c7618c1 100644 --- a/object-file.c +++ b/object-file.c @@ -1801,6 +1801,54 @@ int for_each_loose_object(struct object_database *odb, return 0; } +struct for_each_object_wrapper_data { + struct odb_source *source; + const struct object_info *request; + odb_for_each_object_cb cb; + void *cb_data; +}; + +static int for_each_object_wrapper_cb(const struct object_id *oid, + const char *path, + void *cb_data) +{ + struct for_each_object_wrapper_data *data = cb_data; + + if (data->request) { + struct object_info oi = *data->request; + + if (read_object_info_from_path(data->source, path, oid, &oi, 0) < 0) + return -1; + + return data->cb(oid, &oi, data->cb_data); + } else { + return data->cb(oid, NULL, data->cb_data); + } +} + +int odb_source_loose_for_each_object(struct odb_source *source, + const struct object_info *request, + odb_for_each_object_cb cb, + void *cb_data, + unsigned flags) +{ + struct for_each_object_wrapper_data data = { + .source = source, + .request = request, + .cb = cb, + .cb_data = cb_data, + }; + + /* There are no loose promisor objects, so we can return immediately. */ + if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) + return 0; + if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local) + return 0; + + return for_each_loose_file_in_source(source, for_each_object_wrapper_cb, + NULL, NULL, &data); +} + static int append_loose_object(const struct object_id *oid, const char *path UNUSED, void *data) diff --git a/object-file.h b/object-file.h index 2acf19fb91..5b9641cd89 100644 --- a/object-file.h +++ b/object-file.h @@ -137,6 +137,17 @@ int for_each_loose_object(struct object_database *odb, each_loose_object_fn, void *, enum odb_for_each_object_flags flags); +/* + * Iterate through all loose objects in the given object database source and + * invoke the callback function for each of them. If given, the object info + * will be populated with the object's data as if you had called + * `odb_source_loose_read_object_info()` on the object. + */ +int odb_source_loose_for_each_object(struct odb_source *source, + const struct object_info *request, + odb_for_each_object_cb cb, + void *cb_data, + unsigned flags); /** * format_object_header() is a thin wrapper around s xsnprintf() that diff --git a/odb.h b/odb.h index 74503addf1..f97f249580 100644 --- a/odb.h +++ b/odb.h @@ -463,6 +463,18 @@ enum odb_for_each_object_flags { ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS = (1<<4), }; +/* + * A callback function that can be used to iterate through objects. If given, + * the optional `oi` parameter will be populated the same as if you would call + * `odb_read_object_info()`. + * + * Returning a non-zero error code will cause iteration to abort. The error + * code will be propagated. + */ +typedef int (*odb_for_each_object_cb)(const struct object_id *oid, + struct object_info *oi, + void *cb_data); + enum { /* * By default, `odb_write_object()` does not actually write anything -- cgit v1.3-5-g9baa From 7b7cbaef2781cf755bc900e871964ae62ad532c5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:27 +0100 Subject: odb: introduce mtime fields for object info requests There are some use cases where we need to figure out the mtime for objects. Most importantly, this is the case when we want to prune unreachable objects. But getting at that data requires users to manually derive the info either via the loose object's mtime, the packfiles' mtime or via the ".mtimes" file. Introduce a new `struct object_info::mtimep` pointer that allows callers to request an object's mtime. This new field will be used in a subsequent commit. Note that the concept of "mtime" is ambiguous: given an object, it may be stored multiple times in the object database, and each of these instances may have a different mtime. Disambiguating these mtimes is nothing that can happen on the generic ODB layer: the caller may search for the oldest object, the newest object, or even the relation of object mtimes depending on the specific source they are located in. As such, it is the responsibility of the caller to disambiguate mtimes. A consequence of this is that it's most likely incorrect to look up the mtime via `odb_read_object_info()`, as this interface does not give us enough information to disambiguate the mtime. Document this accordingly and tell users to use `odb_for_each_object()` instead. Even with this gotcha though it's sensible to have this request as part of the object info, as the mtime is a property of the object storage format. If we for example had a "black-box" storage backend, we'd still need to be able to query it for the mtime info in a generic way. We could introduce a safety mechanism that for example calls `BUG()` in case we look up the mtime outside of `odb_for_each_object()`. But that feels somewhat heavy-handed. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 29 +++++++++++++++++++++++++---- odb.c | 2 ++ odb.h | 13 +++++++++++++ packfile.c | 41 ++++++++++++++++++++++++++++++++++------- 4 files changed, 74 insertions(+), 11 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index ef2c7618c1..5537ab2c37 100644 --- a/object-file.c +++ b/object-file.c @@ -409,6 +409,7 @@ static int read_object_info_from_path(struct odb_source *source, char hdr[MAX_HEADER_LEN]; unsigned long size_scratch; enum object_type type_scratch; + struct stat st; /* * If we don't care about type or size, then we don't @@ -421,7 +422,7 @@ static int read_object_info_from_path(struct odb_source *source, if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) { struct stat st; - if ((!oi || !oi->disk_sizep) && (flags & OBJECT_INFO_QUICK)) { + if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) { ret = quick_has_loose(source->loose, oid) ? 0 : -1; goto out; } @@ -431,8 +432,12 @@ static int read_object_info_from_path(struct odb_source *source, goto out; } - if (oi && oi->disk_sizep) - *oi->disk_sizep = st.st_size; + if (oi) { + if (oi->disk_sizep) + *oi->disk_sizep = st.st_size; + if (oi->mtimep) + *oi->mtimep = st.st_mtime; + } ret = 0; goto out; @@ -446,7 +451,21 @@ static int read_object_info_from_path(struct odb_source *source, goto out; } - map = map_fd(fd, path, &mapsize); + if (fstat(fd, &st)) { + close(fd); + ret = -1; + goto out; + } + + mapsize = xsize_t(st.st_size); + if (!mapsize) { + close(fd); + ret = error(_("object file %s is empty"), path); + goto out; + } + + map = xmmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); if (!map) { ret = -1; goto out; @@ -454,6 +473,8 @@ static int read_object_info_from_path(struct odb_source *source, if (oi->disk_sizep) *oi->disk_sizep = mapsize; + if (oi->mtimep) + *oi->mtimep = st.st_mtime; stream_to_end = &stream; diff --git a/odb.c b/odb.c index 13a415c2c3..9d9a3fad62 100644 --- a/odb.c +++ b/odb.c @@ -702,6 +702,8 @@ static int do_oid_object_info_extended(struct object_database *odb, oidclr(oi->delta_base_oid, odb->repo->hash_algo); if (oi->contentp) *oi->contentp = xmemdupz(co->buf, co->size); + if (oi->mtimep) + *oi->mtimep = 0; oi->whence = OI_CACHED; } return 0; diff --git a/odb.h b/odb.h index b5d28bc188..8ad0fcc02f 100644 --- a/odb.h +++ b/odb.h @@ -318,6 +318,19 @@ struct object_info { struct object_id *delta_base_oid; void **contentp; + /* + * The time the given looked-up object has been last modified. + * + * Note: the mtime may be ambiguous in case the object exists multiple + * times in the object database. It is thus _not_ recommended to use + * this field outside of contexts where you would read every instance + * of the object, like for example with `odb_for_each_object()`. As it + * is impossible to say at the ODB level what the intent of the caller + * is (e.g. whether to find the oldest or newest object), it is the + * responsibility of the caller to disambiguate the mtimes. + */ + time_t *mtimep; + /* Response */ enum { OI_CACHED, diff --git a/packfile.c b/packfile.c index c54deabd64..845633139f 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)); + + if (maybe_index_pos) + index_pos = *maybe_index_pos; + else + index_pos = pack_pos_to_index(p, pack_pos); - *oi->disk_sizep = pack_pos_to_offset(p, pos + 1) - obj_offset; + *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, @@ -2378,7 +2404,8 @@ static int packfile_store_for_each_object_wrapper(const struct object_id *oid, off_t offset = nth_packed_object_offset(pack, index_pos); struct object_info oi = *data->request; - if (packed_object_info(pack, offset, &oi) < 0) { + if (packed_object_info_with_index_pos(pack, offset, + &index_pos, &oi) < 0) { mark_bad_packed_object(pack, oid); return -1; } -- cgit v1.3-5-g9baa From 3565faf28c2059c6260d53ac71a303b1c04b0a7b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Jan 2026 10:51:30 +0100 Subject: odb: drop unused `for_each_{loose,packed}_object()` functions We have converted all callers of `for_each_loose_object()` and `for_each_packed_object()` to use their new replacement functions instead. We can thus remove them now. Do so and inline `packfile_store_for_each_object_internal()` now that it only has a single callsite again. This makes it a bit easier to follow the callback indirection that is happening there. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- object-file.c | 20 ------------ object-file.h | 11 ------- packfile.c | 99 +++++++++++++++++++++-------------------------------------- packfile.h | 2 -- 4 files changed, 35 insertions(+), 97 deletions(-) (limited to 'object-file.c') diff --git a/object-file.c b/object-file.c index 5537ab2c37..6785821c8c 100644 --- a/object-file.c +++ b/object-file.c @@ -1802,26 +1802,6 @@ int for_each_loose_file_in_source(struct odb_source *source, return r; } -int for_each_loose_object(struct object_database *odb, - each_loose_object_fn cb, void *data, - enum odb_for_each_object_flags flags) -{ - struct odb_source *source; - - odb_prepare_alternates(odb); - for (source = odb->sources; source; source = source->next) { - int r = for_each_loose_file_in_source(source, cb, NULL, - NULL, data); - if (r) - return r; - - if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) - break; - } - - return 0; -} - struct for_each_object_wrapper_data { struct odb_source *source; const struct object_info *request; diff --git a/object-file.h b/object-file.h index b5eac0349e..d9979baea8 100644 --- a/object-file.h +++ b/object-file.h @@ -126,17 +126,6 @@ int for_each_loose_file_in_source(struct odb_source *source, each_loose_subdir_fn subdir_cb, void *data); -/* - * Iterate over all accessible loose objects without respect to - * reachability. By default, this includes both local and alternate objects. - * The order in which objects are visited is unspecified. - * - * Any flags specific to packs are ignored. - */ -int for_each_loose_object(struct object_database *odb, - each_loose_object_fn, void *, - enum odb_for_each_object_flags flags); - /* * Iterate through all loose objects in the given object database source and * invoke the callback function for each of them. If an object info request is diff --git a/packfile.c b/packfile.c index 845633139f..57fbf51876 100644 --- a/packfile.c +++ b/packfile.c @@ -2327,65 +2327,6 @@ int for_each_object_in_pack(struct packed_git *p, return r; } -static int packfile_store_for_each_object_internal(struct packfile_store *store, - each_packed_object_fn cb, - void *data, - unsigned flags, - int *pack_errors) -{ - struct packfile_list_entry *e; - int ret = 0; - - store->skip_mru_updates = true; - - for (e = packfile_store_get_packs(store); e; e = e->next) { - struct packed_git *p = e->pack; - - 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; - } - - ret = for_each_object_in_pack(p, cb, data, flags); - if (ret) - break; - } - - store->skip_mru_updates = false; - - return ret; -} - -int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, - void *data, unsigned flags) -{ - struct odb_source *source; - int pack_errors = 0; - int ret = 0; - - odb_prepare_alternates(repo->objects); - - for (source = repo->objects->sources; source; source = source->next) { - ret = packfile_store_for_each_object_internal(source->packfiles, cb, data, - flags, &pack_errors); - if (ret) - break; - } - - return ret ? ret : pack_errors; -} - struct packfile_store_for_each_object_wrapper_data { struct packfile_store *store; const struct object_info *request; @@ -2428,14 +2369,44 @@ int packfile_store_for_each_object(struct packfile_store *store, .cb = cb, .cb_data = cb_data, }; + struct packfile_list_entry *e; int pack_errors = 0, ret; - ret = packfile_store_for_each_object_internal(store, packfile_store_for_each_object_wrapper, - &data, flags, &pack_errors); - if (ret) - return ret; + store->skip_mru_updates = true; + + for (e = packfile_store_get_packs(store); e; e = e->next) { + struct packed_git *p = e->pack; + + 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; + } + + ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper, + &data, flags); + if (ret) + goto out; + } + + ret = 0; - return pack_errors ? -1 : 0; +out: + store->skip_mru_updates = false; + + if (!ret && pack_errors) + ret = -1; + return ret; } struct add_promisor_object_data { diff --git a/packfile.h b/packfile.h index b7964f0289..1a1b720764 100644 --- a/packfile.h +++ b/packfile.h @@ -340,8 +340,6 @@ typedef int each_packed_object_fn(const struct object_id *oid, int for_each_object_in_pack(struct packed_git *p, each_packed_object_fn, void *data, unsigned flags); -int for_each_packed_object(struct repository *repo, each_packed_object_fn cb, - void *data, unsigned flags); /* * Iterate through all packed objects in the given packfile store and invoke -- cgit v1.3-5-g9baa