summaryrefslogtreecommitdiff
path: root/odb.h
AgeCommit message (Collapse)AuthorFilesLines
11 daysMerge branch 'ty/repository-fetch-if-missing'Junio C Hamano1-8/+0
The global variable 'fetch_if_missing' has been moved to a member in 'struct repository', continuing the libification process and allowing per-repository control (such as for submodules). * ty/repository-fetch-if-missing: repository: move fetch_if_missing into struct repository
13 daysMerge branch 'ps/odb-pluggable-pack-generation'Junio C Hamano1-0/+152
The mechanism to generate a packfile corresponding to the result of a fetch/push has been made pluggable through a set of object database callback functions, removing hardcoded references to 'pack-objects' and enabling alternative ODBs to serve packfiles themselves. * ps/odb-pluggable-pack-generation: bundle: generate packfiles via the object database bundle: get (mostly) rid of `the_repository` builtin/bundle: refactor option handling for progress meter send-pack: generate packfiles via the object database upload-pack: generate packfiles via the object database odb: introduce interface to generate packfiles
13 daysMerge branch 'jt/receive-pack-pluggable-writes'Junio C Hamano1-2/+4
The 'git receive-pack' command has been updated to use a new ODB transaction interface for writing incoming packfiles, making it more backend-agnostic. * jt/receive-pack-pluggable-writes: odb/transaction: add transaction interface to write packfiles odb: return temporary ODB source when set builtin/receive-pack: explicitly pass packfile fd builtin/receive-pack: report unpack errors via strbuf builtin/receive-pack: lift global state out of unpack() builtin/receive-pack: read unpack limit config lazily builtin/receive-pack: pass shallow file explicitly odb/transaction: add transaction finalize interface builtin/receive-pack: properly clean up keep files
13 daysMerge branch 'ps/odb-eagerly-load-alternates'Junio C Hamano1-12/+10
The object database layer has been simplified by eagerly loading alternate object directories upon initialization, instead of deferring it to the first object lookup. This eliminates the need for scattered lazy-loading calls throughout the codebase and paves the way for integrating alternates with the pluggable backends. * ps/odb-eagerly-load-alternates: odb: drop `alternates_db` field odb: drop `loaded_alternates` field odb: eagerly initialize alternates odb: decouple source path comparisons from `the_repository` setup: create ref and object databases after config is written
13 daysMerge branch 'ps/odb-generic-corrupt-objects'Junio C Hamano1-4/+13
The object database (odb) API has been refactored to distinguish between missing objects and corrupt ones by returning more descriptive error statuses. Both the packed and loose backends now faithfully propagate error details using a generic strbuf error mechanism, removing backend-specific leakage from central lookup paths. * ps/odb-generic-corrupt-objects: odb: handle `OBJECT_INFO_DIE_IF_CORRUPT` generically odb/source: allow `read_object_info()` to bubble up error messages odb/source: let callers discern missing and corrupt objects odb/source: introduce error status when reading objects odb/source-packed: flag known-bad objects as corrupt and not missing
2026-08-23Merge branch 'ps/odb-streams'Junio C Hamano1-2/+2
The 'struct odb_read_stream' and 'struct odb_write_stream' structures have been consolidated into a single unified 'struct odb_stream' structure, simplifying object database streaming APIs and enabling streaming of arbitrary object types. * ps/odb-streams: odb/streaming: unify function names to create new streams odb/streaming: rename `struct input_zstream_data` odb/streaming: rename `struct read_object_fd_data` odb/streaming: consolidate read and write streams odb/streaming: rename `struct odb_read_stream` odb/streaming: support streaming arbitrary object types odb/streaming: drop `is_finished` field odb/streaming: track write stream size in the structure
2026-08-23Merge branch 'ps/cat-file-remote-object-info-type'Junio C Hamano1-3/+0
The 'remote-object-info' command for 'git cat-file --batch-command' has been extended to support the '%(objecttype)' placeholder. * ps/cat-file-remote-object-info-type: cat-file: unify default format serve: advertise type capability fetch-object-info: parse type from server response protocol-caps: add type support to object-info transport: drop remote object-info fields from transport struct fetch-object-info: die() on the remaining error path fetch-object-info: use dedicated struct for the results fetch-object-info: pass arguments directly instead of a struct fetch-object-info: detect malformed server responses t5701: use test_file_size() to get the size of a file
2026-08-21odb: introduce interface to generate packfilesPatrick Steinhardt1-0/+152
Packfiles have two primary use cases: - They are used to store objects at rest in a Git repository. - They are used on the transport layer to transfer objects between two repositories. The first class is closely tied to a given object database backend, and as such this use is highly specific to how such a backend decides to store its data. This shows in git-pack-objects(1), which is used by git-repack(1) et al to optimize the object database, which supports lots of options that are closely coupled with how data is stored. But the second class is quite a lot more generic: we don't care about specifics of how the object database stores its objects, but to generate the packfiles we only care about the object graph itself. Still, this use case is also coupled with git-pack-objects(1). Unfortunately, because git-pack-objects(1) covers both classes, the result is that it is very hard to port the whole command to properly support pluggable object databases. There are simply way too many options that an alternative implementation will have a very hard time to support in the first place. And despite being hard to implement, it's also quite unnecessary to implement those backend-specific options. Optimizing the object database has already been made pluggable, and an alternative implementation is unlikely to care about cruft packs, unpacked objects, keep packs and the like. But we still need to make at least _parts_ of the packfile generation pluggable so that backends can generate packfiles for the transport layer itself. Introduce a new interface that lets backends generate a new packfile and implement that interface for the "files" backend. The options supported by the callback are exactly the set of options that are required for the transport layer, but nothing more. This means that git-pack-objects(1) itself cannot be ported over to this new interface, but as explained above that's a hard feat to pull off due to the backend-specific features. Ideally though, we should expose the ability to generate arbitrary packfiles using this interface. The intent of this is to eventually introduce a git-objects(1) subcommand (similar to git-refs(1)) that exposes generic interfaces for accessing everything related to the object database. In that case, we are able to expose only those options that are generic. Subsequent commits will convert git-upload-pack(1), git-send-pack(1) and git-bundle(1) to use this interface. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-20odb: return temporary ODB source when setJustin Tobler1-2/+4
When invoked, `odb_set_temporary_primary_source()` installs a temporary object directory as the new primary ODB source. A caller that wants to operate on the ODB source of the open transaction must assume that it is the first entry in the ODB source list which is a bit awkward and fragile. Instead, return the newly installed source directly and report the previous primary source via a new `prev_source` out parameter. Propagate the installed source through `tmp_objdir_replace_primary_odb()` and start storing it in the "files" ODB transaction so a subsequent commit can easily access it without relying on the ODB source list ordering. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-20Merge branch 'ps/odb-make-creation-pluggable'Junio C Hamano1-2/+15
The creation of the on-disk data structures for the object database has been made pluggable, allowing future backends to customize their setup. As part of this, the initialization of the object database has been deferred, and the loading of the loose-object map has been detangled from repository initialization. * ps/odb-make-creation-pluggable: odb: make creation of on-disk structures pluggable odb/source: introduce function to map source type to name setup: defer object database creation setup: handle ODB-related environment variables in `odb_new()` setup: detangle loading of loose object maps loose: load loose object map for the correct source
2026-08-19odb/source: let callers discern missing and corrupt objectsPatrick Steinhardt1-0/+2
As explained in the preceding commits, reading objects can either fail because the object truly does not exist or because it exists, but its data is corrupt. Some callers do care about this distinction, but there is no way to tell these two cases apart right now. Introduce a new `ODB_READ_NOT_FOUND` value that ought to be returned by the backends in case the object truly does not exist and adapt backends to use it. Note that we don't yet return this error from `odb_read_object_info()` itself. This will be fixed in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-19odb/source: introduce error status when reading objectsPatrick Steinhardt1-4/+11
The `read_object_info()` callback of `struct odb_source` is documented to return a negative error code in case reading the object has failed, and zero otherwise. This is overly broad though, as there are two very different kinds of failures: - The object may not exist in the source at all. - The object exists, but reading it has failed, for example because its on-disk state is corrupt. This distinction matters to callers: when an object is corrupt in one source we may still find a good copy of it in another source, so we may still be able to proceed with a given operation. The "packed" source already distinguishes these cases by returning a positive value for missing objects and a negative value in case reading the object has failed. But it is the only such source that distinguishes those cases, and the returned value is translated into a negative error code by the "files" backend anyway. Introduce a new error status that is specific to reading objects and adapt the infrastructure to return it. For now, we only discern successful reads from generic failures, which mostly matches the status quo. In subsequent commits though we're about to add an error that explicitly tells the caller that an object does not exist. Note that we keep the "packed" backend as-is with its positive return code for missing objects. This will be fixed in the next commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17odb: drop `alternates_db` fieldPatrick Steinhardt1-7/+0
The `struct object_database::alternates_db` field tracks the value of the "GIT_ALTERNATE_OBJECT_DIRECTORIES" environment variable and is used in `odb_prepare_alternates()`. It's not necessary to store it as a separate field anymore though, as we stopped lazy-loading alternates. Consequently, we can simply pass it to `odb_prepare_alternates()` via `odb_new()` now. Do so and remove the field. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17odb: drop `loaded_alternates` fieldPatrick Steinhardt1-2/+0
The `struct object_database::loaded_alternates` field tells us whether or not alternates have been loaded already. This field was useful before the preceding commit as we were indeed lazy-loading alternates. But now that we started to eagerly load them we can assume them to be loaded after `odb_new()`, and hence the field does not serve any purpose anymore. Remove it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17odb: eagerly initialize alternatesPatrick Steinhardt1-6/+0
When creating the object database we initialize the main object database source, but we don't yet initialize its alternates. Instead, we have many calls to `odb_prepare_alternates()` cluttered around the code base whenever we are about to iterate through the sources. This lazy loading doesn't really add much value: the moment where we read any object we _have_ to load the alternates anyway. So given that most of our commands would access the object database this optimization is not really buying us much in the first place. Quite on the contrary, it makes the code harder to understand and is a potential source of bugs in case any callsite forgot to prepare alternates before we iterate through the sources. Historically though there was a reason why we deferred lazy-loading: it may happen that the repository has "core.ignoreCase" configured, and we use that to deduplicate the list of alternates in case we had the same alternate configured multiple times, but with different casing. We used to initialize the object database before we had fully configured the owning repository though, and consequently we couldn't access that configuration yet. This has changed in the preceding commit though where we started to parse "core.ignoreCase" manually. Eagerly prepare alternates both when creating the object database and when flushing its caches. Drop the now-unneeded calls to prepare the alternates that are scattered across the code base. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17odb: decouple source path comparisons from `the_repository`Patrick Steinhardt1-1/+14
When registering alternates we deduplicate object database sources by their path so that the same source won't be added twice. Ever since cf2dc1c238 (speed up alt_odb_usable() with many alternates, 2021-07-07) this duplicate check is backed by a map keyed by the source's path, using `fspathhash()` and `fspatheq()` as hash and equality functions, respectively. These functions are problematic in this context for two reasons: - They implicitly depend on `the_repository` instead of the repository that owns the object database. - They derive case-sensitivity from `repo_ignore_case()`, which returns a default value in case the repository's configuration has not been parsed yet. Object database sources may be registered before that is the case, so the answer may flip depending on when a source gets registered. Fix this by making the comparison self-contained in the object database. Instead of using `fspathhash()` and `fspatheq()` we resolve "core.ignoreCase" manually and then use the correct comparison function based on the result. This requires us to migrate to a `struct hashmap`, as the khash interface does not give us the ability to pass an arbitrary payload to these functions, and hence we'd have to use global state to decide which of those to use. Note that we can unconditionally use `strihash()` to compute entry hashes regardless of case sensitivity: a hash function only needs to guarantee that equal keys have equal hashes, and a case-insensitive hash satisfies this requirement for both case-sensitive and case-insensitive equality. Overall it's quite debatable whether all of this complexity really is worth it, out of two reasons: - We could linearly search through all sources to find duplicates. But the mentioned commit cares about cases with thousands of alternates, and a linear search would of course regress performance quite a bit. This doesn't really feel like a reasonable case to care about, but I don't feel comfortable regressing it anyway. - It's dubious whether we should handle "core.ignoreCase" in the first place. The downside would be that we might add the same alternate multiple times with different casing. But this is an edge case, and it's not even fully fixed because we don't resolve symlinks or mountpoints, either. So for now, keep this infrastructure in-place while removing the global dependency on `the_repository`. We may want to revisit this in the future though. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-15repository: move fetch_if_missing into struct repositoryTian Yuchen1-8/+0
The global variable 'fetch_if_missing' controls whether a missing object check should prompt a lazy fetch from a promisor remote. In order to continue the libification effort, move it into 'struct repository' and initialize it to 1 by default to keep the previous behavior. builtin/fetch-pack.c, builtin/fsck.c, and builtin/rev-list.c are entered via commands marked RUN_SETUP in git.c:commands[]. Their 'repo' parameter is only NULL when '-h' is given outside of a repository, in which case either show_usage_if_asked() or parse_options()'s own '-h' handling exits the process before returning. We can therefore drop their UNUSED markers and assign to 'repo' directly. builtin/index-pack.c is entered via RUN_SETUP_GENTLY, so its 'repo' pointer can be NULL any time it is run outside of a repository, not only with '-h'. We keep a NULL check there and fall back to 'the_repository'. builtin/pack-objects.c needs two adjustments to make 'repo' reach every 'fetch_if_missing' call site: 'read_stdin_packs()' now takes a 'struct repository *'; 'option_parse_missing_action()', which is registered as an OPT_CALLBACK, receives a 'repo' through the option's 'value' field now. Additionally, update the partial clone documentation to reflect that this is now a per-repository flag. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Ayush Chandekar <ayu.chandekar@gmail.com> Mentored-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Tian Yuchen <cat@malon.dev> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12Merge branch 'ps/odb-make-creation-pluggable' into ↵Junio C Hamano1-2/+15
ps/odb-eagerly-load-alternates * ps/odb-make-creation-pluggable: odb: make creation of on-disk structures pluggable odb/source: introduce function to map source type to name setup: defer object database creation setup: handle ODB-related environment variables in `odb_new()` setup: detangle loading of loose object maps loose: load loose object map for the correct source
2026-08-07fetch-object-info: use dedicated struct for the resultsPablo Sabater1-3/+0
fetch_object_info() collects information about N objects, but it stores the results in an array of object_info. That struct holds the extended parameters of read_object_info() (The optional outputs the caller wants filled). Its pointers tell that function where to write the answers for a single object. object_info is not meant to be the final storage, and since fetch_object_info() does not call read_object_info(), there is no reason to use it. Using it means allocating one scalar per object per attribute just to have those pointers somewhere to point at. Add struct fetch_object_info_results. The caller sets the wants_* flags to say what it is interested in, and fetch_object_info() allocates one array per attribute. A set wants_* flag means "asked for", while a non-NULL array means "available". The caller releases the arrays with free_fetch_object_info_results(). The object_info_options string list is no longer needed. Filtering against the server's advertisement now sets local ask_* flags, and send_object_info_request() turns those into the v2 protocol option strings. remote_atom_map[] existed only to map those strings back into atom names, so drop it and build remote_allowed_atoms from the result arrays. Currently for wants_* and ask_* there is only the 'size' variant but a subsequent commit will add '*_type'. free_object_info_contents() loses its only caller and is dropped. Dropping the allow-list check makes the final else reachable from the wire, so die() instead of BUG(): an unknown attribute is the server's error, not ours. Helped-by: Jeff King <peff@peff.net> Helped-by: Junio C Hamano <gitster@pobox.com> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Mentored-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-06setup: handle ODB-related environment variables in `odb_new()`Patrick Steinhardt1-2/+15
When initializing a repository's object database we have to respect the GIT_OBJECT_DIRECTORY and GIT_ALTERNATE_OBJECT_DIRECTORIES environment variables, which can be set by the user to override the default location of where we write objects to and read objects from. This is handled in `apply_repository_format()`, which is fine. But in a subsequent commit we'll have to defer constructing the object database to a later point in some cases, and that will require a second site where we call `odb_new()`. And of course, that second site would have to handle those environment variables, as well. It would be somewhat awkward to duplicate the logic though. But there's a better alternative: instead of handling this logic in "setup.c", we can easily handle environment variables in `odb_new()` itself. This ensures that object database creation is neatly self-contained, and we don't have to duplicate any of the logic. Another benefit is that in a future patch series we plan to move handling of alternates into the backends themselves [1], and that will require us to also handle those environment variables in the "files" backend itself. So moving the logic into the ODB level already gets us one step closer to that goal. Refactor the logic accordingly. [1]: https://lore.kernel.org/git/amLgMqkqxR8mKIbT@pks.im/ Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05Merge branch 'ps/odb-pluggable-housekeeping'Junio C Hamano1-0/+45
Object database housekeeping in 'git gc' and 'git maintenance' has been refactored to be pluggable. The files-backend-specific logic, including incremental and geometric repacking as well as object pruning, has been moved out of the command implementation and into the files object database source, enabling future alternative object database backends to implement their own housekeeping services. * ps/odb-pluggable-housekeeping: odb: make optimizations pluggable builtin/gc: fix signedness issues in ODB-related functionality builtin/gc: refactor ODB optimizations to operate on "files" source builtin/gc: introduce `odb_optimize_required()` builtin/gc: move geometric repacking into `odb_optimize()` builtin/gc: introduce object database optimization options builtin/gc: inline config values specific to the "files" backend builtin/gc: make repack arguments self-contained builtin/gc: extract object database optimizations into separate function builtin/gc: move worktree and rerere tasks before object optimizations odb: run "pre-auto-gc" hook for all maintenance tasks t7900: simplify how we check for maintenance tasks
2026-08-05odb/streaming: consolidate read and write streamsPatrick Steinhardt1-2/+2
The `struct odb_read_stream` and `struct odb_write_stream` both provide the same functionality: they allow a caller to read object data from an arbitrary source. Historically, the only difference was that the read stream was used to read data out of the object database, whereas the write stream was used to write data into the object database, but the interfaces were mostly the same. Over the preceding commits we have refactored the write stream to have almost exactly the same interface as the read stream. With these refactorings we can now easily merge those two streams into a single interface that's used for both use cases. While most of the changes are mechanical, there are two sites that need special mention: - "builtin/unpack-objects.c" creates a write stream from compressed object data. - "odb/streaming.c" creates a write stream from a file descriptor. Adapting these sites to yield the new stream type requires a couple more changes. Most importantly, instead of embedding the pointer to the data in `struct odb_write_stream`, we now allocate a structure that wraps the new `struct odb_stream` base. Other than that though, the changes are rather straight forward. Some of the structures and functions are now somewhat misnamed. These will be fixed in subsequent commits. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05odb/streaming: track write stream size in the structurePatrick Steinhardt1-1/+1
When passing around a `struct odb_write_stream` we typically also have to pass the number of bytes that the stream will yield. This is required because the object header itself contains that size, and consequently we cannot write the header without that information. Move this information into the stream itself so that it becomes self- describing. In addition to that, this also brings the `struct odb_write_stream` a bit closer to the `struct odb_read_stream` so that we can eventually merge both stream types. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-30Merge branch 'ps/odb-move-loose-object-writing'Junio C Hamano1-4/+6
The logic to write loose objects has been refactored and moved from 'object-file.c' to the loose backend source file 'odb/source-loose.c', making the loose backend more self-contained. This is achieved by first refactoring force_object_loose() to use generic ODB write interfaces instead of loose-backend internals. * ps/odb-move-loose-object-writing: object-file: move logic to write loose objects object-file: move `force_object_loose()` object-file: force objects loose via generic interface object-file: fix memory leak in `force_object_loose()` odb: support setting mtime when writing objects odb: lift object existence check out of the "loose" backend odb: compute object hash in `odb_write_object_ext()` t/u-odb-inmemory: implement wrapper for writing objects odb: compute compat object ID in `odb_write_object_ext()`
2026-07-30Merge branch 'ps/cat-file-remote-object-info'Junio C Hamano1-0/+9
The 'remote-object-info' command has been added to 'git cat-file --batch-command', allowing clients to request object metadata (currently size) from a remote server via protocol v2 without downloading the entire object. Format placeholders are dynamically filtered on the client based on server-advertised capabilities, returning empty strings for inapplicable or unsupported fields. * ps/cat-file-remote-object-info: cat-file: make remote-object-info allow-list adapt to the server cat-file: add remote-object-info to batch-command transport: add client support for object-info serve: advertise object-info feature protocol-caps: check object existence regardless of the attributes requested fetch-pack: move fetch initialization connect: make write_fetch_command_and_capabilities() more generic fetch-pack: move write_fetch_command_and_capabilities() to connect.c fetch-pack: use unsigned int for hash_algo variable fetch-pack: drop the static advertise_sid variable t1006: extract helper functions into new 'lib-cat-file.sh' cat-file: declare loop counter inside for() transport-helper: fix memory leak of helper on disconnect
2026-07-25Merge branch 'ps/cat-file-remote-object-info' into ↵Junio C Hamano1-0/+9
ps/cat-file-remote-object-info-type * ps/cat-file-remote-object-info: cat-file: make remote-object-info allow-list adapt to the server cat-file: add remote-object-info to batch-command transport: add client support for object-info serve: advertise object-info feature protocol-caps: check object existence regardless of the attributes requested fetch-pack: move fetch initialization connect: make write_fetch_command_and_capabilities() more generic fetch-pack: move write_fetch_command_and_capabilities() to connect.c fetch-pack: use unsigned int for hash_algo variable fetch-pack: drop the static advertise_sid variable t1006: extract helper functions into new 'lib-cat-file.sh' cat-file: declare loop counter inside for() transport-helper: fix memory leak of helper on disconnect
2026-07-24cat-file: add remote-object-info to batch-commandEric Ju1-0/+3
Since the info command in cat-file --batch-command prints object info for a given object, it is natural to add another command in cat-file --batch-command to print object info for a given object from a remote. Add remote-object-info command to cat-file --batch-command. While info takes object ids one at a time, this creates overhead when making requests to a server. So remote-object-info instead can take multiple object ids at once. The cat-file --batch-command command is generally implemented in the following manner: - Receive and parse input from user - Call respective function attached to command - Get object info, print object info In --buffer mode, this changes to: - Receive and parse input from user - Store respective function attached to command in a queue - After flush, loop through commands in queue - Call respective function attached to command - Get object info, print object info Notice how the getting and printing of object info is accomplished one at a time. As described above, this creates a problem for making requests to a server. Therefore, remote-object-info is implemented in the following manner: - Receive and parse input from user If command is remote-object-info: - Get object info from remote - Loop through and print each object info Else: - Call respective function attached to command - Parse input, get object info, print object info And finally for --buffer mode remote-object-info: - Receive and parse input from user - Store respective function attached to command in a queue - After flush, loop through commands in queue: If command is remote-object-info: - Get object info from remote - Loop through and print each object info Else: - Call respective function attached to command - Get object info, print object info To summarize, remote-object-info gets object info from the remote and then loops through the object info passed in, printing the info. In order for remote-object-info to avoid remote communication overhead in the non-buffer mode, the objects are passed in as such: remote-object-info <remote> <oid> <oid> ... <oid> rather than remote-object-info <remote> <oid> remote-object-info <remote> <oid> ... remote-object-info <remote> <oid> Placeholders in the format are validated against an allow-list of the atoms the remote path supports: "objectname" and "objectsize". Unsupported atoms expand to an empty string, honoring how for-each-ref handles known but inapplicable atoms. Without this, atoms like %(objecttype) would mark data->info.typep and because the server only sends size, type_name() would later crash. As extra safety, even outside of the remote path, initialize expand_data's type to OBJ_BAD and handle type_name() returning NULL. Helped-by: Jonathan Tan <jonathantanmy@google.com> Helped-by: Christian Couder <chriscool@tuxfamily.org> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Mentored-by: Chandra Pratap <chandrapratap3519@gmail.com> Signed-off-by: Calvin Wan <calvinwan@google.com> Signed-off-by: Eric Ju <eric.peijian@gmail.com> [pablo: added the atom allow-list validation] Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-24transport: add client support for object-infoCalvin Wan1-0/+6
Sometimes, it is beneficial to retrieve information about an object without downloading it entirely. The server-side logic for this functionality was implemented in commit "a2ba162cda (object-info: support for retrieving object info, 2021-04-20)." And the wire format is documented at https://git-scm.com/docs/protocol-v2#_object_info. Introduce client-side support for the object-info capability. Add its own function for object-info separate from existing fetch infrastructure. Currently, the client supports requesting a list of OIDs with the size attribute from a v2 server. If the server does not advertise this feature (i.e., transfer.advertiseobjectinfo is set to false), the client returns an error and exits. Note that: 1. The entire request is written into req_buf before being sent to the remote. This approach follows the pattern used in the send_fetch_request() logic within 'fetch-pack.c'. Streaming the request is not addressed in this patch. 2. A new field 'unrecognized' has been added to object_info. This new field is set at fetch_object_info() when the object is unrecognized by the server. Helped-by: Jonathan Tan <jonathantanmy@google.com> Helped-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Calvin Wan <calvinwan@google.com> Signed-off-by: Eric Ju <eric.peijian@gmail.com> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-22Merge branch 'ps/odb-for-each-object-filter'Junio C Hamano1-0/+12
The object database enumeration interface odb_for_each_object() has been taught to accept object filters, allowing the underlying backends to optimize the traversal by using reachability bitmaps when available. 'git cat-file --batch-all-objects' has been updated to use this generic interface, simplifying its code and avoiding direct access to ODB backend internals. * ps/odb-for-each-object-filter: builtin/cat-file: filter objects via object database odb: introduce object filters to `odb_for_each_object()` pack-bitmap: introduce function to open bitmap for a single source pack-bitmap: drop `_1` suffix from functions that open bitmaps pack-bitmap: iterate object sources when opening bitmaps pack-bitmap: allow aborting iteration of bitmapped objects pack-objects: drop unused return value from add_object_entry() pack-bitmap: mark object filter as `const` odb/source-packed: improve lookup when enumerating objects
2026-07-18odb: compute compat object ID in `odb_write_object_ext()`Patrick Steinhardt1-4/+6
Repositories can have a compatibility hash configured, which means that such a repository is expected to maintain a mapping between canonical and compatibility object hashes. Maintaining this mapping is the responsibility of the object database sources, where we either store them as part of the loose objects map or in packfile indices v3 (once we gain support for this feature). But besides storing these compatibility hashes, the sources are also responsible for generating the compatibility hash in the first place. This is somewhat unnecessary though, as the compatibility hash should be computed the same no matter which source is being used. The consequence is that we need to duplicate this functionality across the different backends, which does not make a lot of sense. Refactor the code so that we instead compute the compatibility hash in `odb_write_object_ext()` and then pass the computed value to the sources. No callers need adjustment as there are none that write objects via the source interfaces directly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15Merge branch 'ps/odb-drop-whence'Junio C Hamano1-24/+56
The 'whence' field in 'struct object_info' has been removed. The backend-specific object information retrieval has been refactored into an opt-in 'struct object_info_source' structure. * ps/odb-drop-whence: odb: document object info fields odb: drop `whence` field from object info treewide: convert users of `whence` to the new source field odb: add `source` field to struct object_info_source odb: make backend-specific fields optional packfile: thread odb_source_packed through packed_object_info()
2026-07-15odb: introduce object filters to `odb_for_each_object()`Patrick Steinhardt1-0/+12
The function `for_each_bitmapped_object()` can be used to iterate through all objects covered by a bitmap. The benefit of this function is that it allows the caller to efficiently handle some object filters. For example, this can be used to filter out objects of a specific type with some simple bitmap operations. But callers are currently required to manually wire up the use of bitmaps though, and to do so they have to reach into internals of a given object database source. Introduce a new `struct odb_for_each_object_options::filter` field so that the interface becomes generic. When set, then a backend may optionally use the filter to skip some objects that it would have otherwise yielded. Note that the respective backends are free to ignore this field if they cannot meaningfully optimize for a given filter, and consequently callers need to verify whether they actually want the returned objects. While annoying, we cannot easily lift this restriction anyway as the object filter infrastructure supports some filters that cannot be answered by the object database alone. An alternative might be to limit the filters to only those that _can_ be answered by backends. But ultimately, the filters that can be answered efficiently by the "packed" backend are completely disjunct from those that can be answered by the "loose" backend, and consequently the set of filters supported by all backends would be empty. Furthermore, it would require us to make assumptions about capabilities of future backends, which may be able to efficiently handle more filters than current ones. So in the end, this alternative would only limit us artificially. Implement the logic for the "packed" source. Note that we use the new function `prepare_bitmap_git_for_source()` to open the bitmap: as the backend operates on a single object source, we must only use bitmaps that belong to that specific source. Otherwise we might yield objects that are not part of the source at all, and with multiple sources we would enumerate the same bitmap once per source. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-13Merge branch 'ps/odb-generalize-prepare'Junio C Hamano1-2/+14
The 'reprepare()' callback for object database sources has been generalized into a 'prepare()' callback with an optional flush cache flag, and a new 'odb_prepare()' wrapper has been introduced to allow pre-opening object database sources. * ps/odb-generalize-prepare: odb: introduce `odb_prepare()` odb/source: generalize `reprepare()` callback
2026-07-13odb: make optimizations pluggablePatrick Steinhardt1-0/+45
Move `odb_optimize()` and `odb_optimize_required()` from "builtin/gc.c" into the "files" source and wire them up via newly introduced vtable pointers for the object database sources. This makes the logic pluggable and thus allows other backends to have their own, custom implementation. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-02odb: document object info fieldsPatrick Steinhardt1-1/+17
Some of the fields in `struct object_info` are undocumented. Add these missing comments. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-02odb: drop `whence` field from object infoPatrick Steinhardt1-7/+0
In the preceding commits we have migrated all callers to derive their information of how a specific object is stored to use the new object info source instead, and hence the field is now unused. Drop it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-02odb: add `source` field to struct object_info_sourcePatrick Steinhardt1-4/+7
The previous commit introduced `struct object_info_source` as an opt-in container for backend-specific information, but for now we only moved preexisting data into this structure. Most importantly, the caller has no way yet to learn about which source an object was actually looked up from. Instead, callers have to rely on the `whence` enum to distinguish the object type, but cannot use that enum to tell the object source. Add a `struct odb_source *source` field to the structure and populate it from each backend's lookup path. The `whence` enum is still set and used by callers; it will be removed in a subsequent commit now that `sourcep->source` can identify the backend on its own. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-02odb: make backend-specific fields optionalPatrick Steinhardt1-20/+40
The `struct object_info` carries two pieces of information about how an object was looked up: - The `whence` enum identifying the backend. - The backend-tagged union `u` exposing backend-specific details (currently only the packed-source case, which records the owning pack, offset and packed object type). The union is populated unconditionally, even though most callers don't care about provenance at all. Split the backend-specific union out into a new public type, `struct object_info_source`, and make the object info structure carry it via just another opt-in request pointer. As with all the other requestable information, callers that need source info allocate a `struct object_info_source` on the stack and point `sourcep` at it; callers that don't care about it simply leave the field as a `NULL` pointer. Adapt callers accordingly. Note that the `whence` enum is strictly-speaking also backend-specific information, so it would be another good candidate to be moved into the `struct object_info_source`. For now though it is left alone, as it will be replaced by a `struct odb_source` pointer in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-22odb: introduce `odb_prepare()`Patrick Steinhardt1-2/+6
Introduce `odb_prepare()` as a simple wrapper to prepare alternates and then prepare each individual source. Adapt git-grep(1) to use it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-22odb/source: generalize `reprepare()` callbackPatrick Steinhardt1-0/+8
The `reprepare()` callback function can be used to flush caches of a given object source and then prepare it anew. This is for example used when a concurrent process may have written new objects. Ultimately, this can be seen as doing two separate steps: 1. We drop any caches. 2. We prepare the source. We have one callsite in git-grep(1) though that really only want to do (2). This is done by reaching into the "files" backend directly and then calling `odb_source_packed_prepare()`, which of course may not work with alternate backends. We could in theory just call `reprepare()` here, and that would likely not have any significant downside. But this would certainly feel like a code smell. Instead, generalize the `reprepare()` callback to `prepare()` with a flag that optionally instructs the backend to also flush the caches, which allows us to drop the external `odb_source_packed_prepare()` declaration. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-21Merge branch 'js/objects-larger-than-4gb-on-windows-more'Junio C Hamano1-5/+5
* js/objects-larger-than-4gb-on-windows-more: odb: use size_t for object_info.sizep and the size APIs packfile,delta: drop the `cast_size_t_to_ulong()` wrappers pack-objects: use size_t for in-core object sizes packfile: widen unpack_entry()'s size out-parameter to size_t pack-objects(check_pack_inflate()): use size_t instead of unsigned long patch-delta: use size_t for sizes compat/msvc: use _chsize_s for ftruncate
2026-06-16Merge branch 'wy/docs-typofixes'Junio C Hamano1-1/+1
Various typos, grammatical errors, and duplicated words in both documentation and code comments have been corrected. * wy/docs-typofixes: docs: fix typos and grammar
2026-06-15odb: use size_t for object_info.sizep and the size APIsJohannes Schindelin1-5/+5
When `js/objects-larger-than-4gb-on-windows` widened the streaming, index-pack and unpack-objects code paths, in the interest of keeping the patches somewhat reasonably-sized, it left the public ODB API still typed in `unsigned long`. In particular `struct object_info::sizep` and the four wrappers built on top of it (`odb_read_object`, `odb_read_object_peeled`, `odb_read_object_info`, `odb_pretend_object`) still return the unpacked size through `unsigned long *`, so on Windows `cat-file -s` and the `git add` / `git status` paths for a >4 GiB blob silently cap at 4 GiB. Widen the field and the four wrappers. The previous commits already widened the `unpack_entry()` cascade and pack-objects' in-core size accessors, so most of the cascade arrives here with no further work: the temporary shims in `packed_object_info_with_index_pos()` and in `unpack_entry()`'s delta-base recovery path go away, the two `SET_SIZE(entry, cast_size_t_to_ulong(canonical_size))` calls in `check_object()` and the matching one in `drop_reused_delta()` collapse to plain `SET_SIZE`, and `oe_get_size_slow()`'s tail `cast_size_t_to_ulong()` is gone too. What remains narrow are the boundaries this series does not intend to touch: the diff, blame, textconv and fast-import machinery. Even so, this patch is unfortunately quite large. Assisted-by: Opus 4.7 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-30docs: fix typos and grammarWeijie Yuan1-1/+1
Fix several spelling mistakes, subject-verb agreement issues, and duplicated words. Signed-off-by: Weijie Yuan <wy@wyuan.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-15odb: generic in-memory sourcePatrick Steinhardt1-1/+1
Make the in-memory source generic. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-15odb: introduce "in-memory" sourcePatrick Steinhardt1-2/+2
Next to our typical object database sources, each object database also has an implicit source of "cached" objects. These cached objects only exist in memory and some use cases: - They contain evergreen objects that we expect to always exist, like for example the empty tree. - They can be used to store temporary objects that we don't want to persist to disk, which is used by git-blame(1) to create a fake worktree commit. Overall, their use is somewhat restricted though. For example, we don't provide the ability to use it as a temporary object database source that allows the user to write objects, but discard them after Git exists. So while these cached objects behave almost like a source, they aren't used as one. This is about to change over the following commits, where we will turn cached objects into a new "in-memory" source. This will allow us to use it exactly the same as any other source by providing the same common interface as the "files" source. For now, the in-memory source only hosts the cached objects and doesn't provide any logic yet. This will change with subsequent commits, where we move respective functionality into the source. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-15Merge branch 'jt/odb-transaction-write' into ps/odb-in-memoryJunio C Hamano1-36/+1
* jt/odb-transaction-write: odb/transaction: make `write_object_stream()` pluggable object-file: generalize packfile writes to use odb_write_stream object-file: avoid fd seekback by checking object size upfront object-file: remove flags from transaction packfile writes odb: update `struct odb_write_stream` read() callback odb/transaction: use pluggable `begin_transaction()` odb: split `struct odb_transaction` into separate header
2026-05-15odb: update `struct odb_write_stream` read() callbackJustin Tobler1-5/+1
The `read()` callback used by `struct odb_write_stream` currently returns a pointer to an internal buffer along with the number of bytes read. This makes buffer ownership unclear and provides no way to report errors. Update the interface to instead require the caller to provide a buffer, and have the callback return the number of bytes written to it or a negative value on error. While at it, also move the `struct odb_write_stream` definition to "odb/streaming.h". Call sites are updated accordingly. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-05-15odb: split `struct odb_transaction` into separate headerJustin Tobler1-31/+0
The current ODB transaction interface is colocated with other ODB interfaces in "odb.{c,h}". Subsequent commits will expand `struct odb_transaction` to support write operations on the transaction directly. To keep things organized and prevent "odb.{c,h}" from becoming more unwieldy, split out `struct odb_transaction` into a separate header. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-31odb: drop unneeded headers and forward declsPatrick Steinhardt1-9/+3
There's a couple of unneeded forward declarations and headers in "odb.h". Drop these. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>