Commit Graph

137 Commits (426d291b6095a51ee249b70a088f99cd67d4bb27)

Author SHA1 Message Date
Patrick Steinhardt 426d291b60 builtin/fsck: move reverse index verification into the packed source
The checks for reverse indexes live in `check_pack_rev_indexes()`, which
is hosted in "builtin/fsck.c". These checks are obviously specific to
the "packed" backend.

Move the logic into `odb_source_packed_fsck()`. As in the preceding
commit, drop the dedicated `ERROR_PACK_REV_INDEX` bit and instead use
the generic `ERROR_OBJECT` bit.

Note that this changes behaviour in two ways:

  - The checks are now skipped when "--connectivity-only" was passed.
    This is because we don't even run `odb_fsck()` at all when that
    flag has been passed by the user, and not verifying data structures
    of the object database matches the documented intent of that flag,
    which is to only check the connectivity of reachable objects.

  - The checks are now skipped for non-local sources when "--no-full"
    was passed. This is, again, in line with the documented intent of
    that flag.

Add a test to cast these semantics into stone.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-11 09:14:44 -07:00
Patrick Steinhardt 6bc7780404 builtin/fsck: move packfile verification into the packed source
Move the packfile verification out of `cmd_fsck()` and into the "packed"
source. While doing so, thread the progress meter and object callback
through the newly introduced `struct odb_fsck_options` so that the
caller's preferences are honoured without exposing those details at the
"builtin/fsck.c" level.

Note that the old code reported failures when verifying packfiles with
the `ERROR_PACK` bit, which gets returned to the caller via the exit
code. This bit is neither exercised in our test suite nor is it
documented anywhere in our codebase. Furthermore, this bit is highly
specific to the object storage backend, which makes it a bad fit for the
new pluggable infrastructure. So instead of retaining these semantics,
we drop them and return the generic `ERROR_OBJECT` bit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-11 09:14:44 -07:00
Patrick Steinhardt a51b77aa1d odb: provide infrastructure for pluggable fsck checks
The on-disk consistency checks in git-fsck(1) are conceptually
backend-specific: while connectivity checks and object-level parsing
checks are generic, verifying the physical integrity of packfiles and
loose objects is meaningful only to backends that use these formats:
Having these checks live in "builtin/fsck.c" violates that layering,
because it forces the command to reach directly into format-specific
internals.

Provide new infrastructure to make these format-specific checks
pluggable and implement stubs for the different source types we already
have. In subsequent commits we'll move functionality over piece by
piece.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-11 09:14:44 -07:00
Junio C Hamano 3db2defe2f Merge branch 'ps/odb-eagerly-load-alternates' into ps/odb-pluggable-fsck
* 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
2026-08-25 18:07:31 -07:00
Junio C Hamano 286f72ca82 Merge branch 'ps/odb-pluggable-pack-generation' into ps/odb-pluggable-fsck
* 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
2026-08-25 18:07:20 -07:00
Junio C Hamano a2ef06b1ef Merge branch 'ps/odb-streams'
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-23 18:01:43 -07:00
Patrick Steinhardt a316d615da odb: introduce interface to generate packfiles
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-21 09:01:54 -07:00
Junio C Hamano 2f6614658f Merge branch 'ps/odb-make-creation-pluggable'
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-20 07:30:52 -07:00
Patrick Steinhardt f978f560dd odb: eagerly initialize alternates
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-17 09:36:10 -07:00
Patrick Steinhardt 9879277091 odb: decouple source path comparisons from `the_repository`
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-17 09:36:10 -07:00
Junio C Hamano d296c52baa Merge branch 'ps/odb-make-creation-pluggable' into 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-12 08:33:36 -07:00
Patrick Steinhardt e927cfeb21 odb: make creation of on-disk structures pluggable
When creating a new "files" object database source we have to create a
couple of directories. These directories are of course specific to this
particular backend, and a different backend may require a setup that is
completely different.

Make the creation of on-disk structures pluggable to accommodate for
this.

Note that there is one exception though: the "objects" directory must
exist in a repository regardless of which backend is in use. If it
doesn't exist then the repository is not treated as a Git repository at
all. Consequently, we create this directory regardless of the backend.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-06 21:24:25 -07:00
Patrick Steinhardt 335fe2545e odb/source: introduce function to map source type to name
Introduce a new function that maps an object source's type to a
human-readable name. Use the function to provide better human-readable
error messages for the downcasting functions.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-06 21:24:25 -07:00
Patrick Steinhardt 8a1ba94eb5 setup: detangle loading of loose object maps
When a repository is configured to use a compatibility hash function
then we load the loose object map when we initialize the repository.
This object map provides the mappings between the canonical object hash
and the compatibility object hash.

Loading the object map happens in `repo_set_compat_hash_algo()`, which
calls `repo_read_loose_object_map()` in case the compatibility object
hash is non-zero. This setup sequence has two major downsides:

  - We assume that the primary object database is the "files" object
    database and unconditionally downcast it. This will cause us to BUG
    in case a different object database type was used together with a
    compat hash algorithm.

  - We require the object database to already have been initialized when
    configuring the object database. This means that we must intermix
    configuration of the repository and initialization of its
    sub-structures in a weird way.

Refactor the logic so that we instead load the loose object map via the
"loose" backend, which fixes both of the above issues.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-06 21:24:25 -07:00
Junio C Hamano 82c48eae1f Merge branch 'ps/odb-pluggable-housekeeping'
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-05 11:10:51 -07:00
Patrick Steinhardt ebdd7e10d6 odb/streaming: unify function names to create new streams
Unify the function names to create new streams from different sources so
that they follow a common schema. While at it, document the ownership of
the file descriptor passed to `odb_stream_from_fd()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05 09:42:50 -07:00
Patrick Steinhardt 93dd24603b odb/streaming: rename `struct read_object_fd_data`
With the preceding refactorings the `struct read_object_fd_data` is now
somewhat misnamed, as it doesn't only contain the data anymore, but also
the stream itself. Rename the structure to `struct fd_stream` to better
match the new structure.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05 09:42:50 -07:00
Patrick Steinhardt e837b812fe odb/streaming: consolidate read and write streams
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-05 09:42:50 -07:00
Patrick Steinhardt a59e4798f0 odb/streaming: rename `struct odb_read_stream`
Rename `struct odb_read_stream` to just `struct odb_stream`. This
prepares for unification of the two different types of streams, as these
provide the same functionality with the preceding refactorings.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05 09:42:50 -07:00
Patrick Steinhardt 8a51f6e8c5 odb/streaming: support streaming arbitrary object types
The object database supports the ability to write object streams into
it. This functionality is used when we encounter a blob that is larger
than "core.bigFileThreshold" so that we don't have to soak large files
into memory.

As we only ever write large files, the infrastructure doesn't support
specifying any other object type than "blob". This limitation is quite
artificial though: there is no reason why we shouldn't support writing
arbitrary large objects with a stream. While it's very unlikely that we
encounter a huge object other than a blob, users are known to be
creative and sometimes like to inflict pain on themselves by creating
commits or trees that are huge.

Extend the infrastructure to support streaming arbitrary object types.
For now we don't use this functionality anywhere, but it brings us a bit
closer to unify `struct odb_read_stream` and `struct odb_write_stream`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05 09:42:50 -07:00
Patrick Steinhardt 7267822542 odb/streaming: drop `is_finished` field
The `is_finished` field is used to track whether a write stream is done
writing all of its data. Tracking this field as part of the stream
itself shouldn't be required though: callers will already know when the
stream is done when the stream's read function returns zero bytes, same
as when reading from a file descriptor.

There is one exception where it gets a bit more complicated: when
consuming data in "builtin/unpack-objects.c" it may happen that we don't
yield any new bytes after reading from the pipe. This is addressed by
looping until we have produced at least a single byte of output.

Drop the field from `struct odb_write_stream`. Again, same as in the
preceding commit, this brings the structure a bit closer to its sibling
`struct odb_read_stream`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-05 09:42:50 -07:00
Patrick Steinhardt b1b008fa2b odb/streaming: track write stream size in the structure
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-08-05 09:42:49 -07:00
Junio C Hamano d407e69787 Merge branch 'ps/odb-move-loose-object-writing'
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-30 10:32:05 -07:00
Junio C Hamano 818eb57007 Merge branch 'rs/tempfile-wo-the-repository'
The tempfile and lockfile APIs have been refactored to stop depending
on the 'the_repository' global variable, and their callers have been
updated to use the repository-aware variants.

* rs/tempfile-wo-the-repository:
  use repo_hold_lock_file_for_update{,_mode,_timeout}() with custom repos
  tempfile: stop using the_repository
  lockfile: add repo_hold_lock_file_for_update{,_timeout}{,_mode}()
  refs/packed: use repo_create_tempfile()
  tempfile: add repo_create_tempfile{,_mode}()
2026-07-30 10:32:02 -07:00
Junio C Hamano 518368999a Merge branch 'ps/odb-for-each-object-filter'
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-22 10:30:54 -07:00
Junio C Hamano 55f961a555 Merge branch 'jt/receive-pack-use-odb-transactions'
'git receive-pack' has been refactored to use ODB transaction
interfaces instead of directly managing 'tmp_objdir' for staging
incoming objects, bringing it closer to being ODB backend agnostic.

* jt/receive-pack-use-odb-transactions:
  builtin/receive-pack: stage incoming objects via ODB transactions
  builtin/receive-pack: drop redundant tmpdir env
  odb/transaction: introduce ODB transaction flags
  odb/transaction: add transaction env interface
  odb/transaction: propagate commit errors
  odb/transaction: propagate begin errors
  object-file: propagate files transaction errors
  object-file: drop check for inflight transactions
  object-file: embed transaction flush logic in commit function
  object-file: rename files transaction fsync function
  object-file: rename files transaction prepare function
2026-07-22 10:30:53 -07:00
Patrick Steinhardt 810f8b2033 object-file: move logic to write loose objects
The logic to write loose objects is split up across "object-file.c" and
"odb/source-loose.c". This split is somewhat weird, but it is the result
of two things:

  - `force_object_loose()` used to reach into internals of how exactly
    we write objects.

  - The logic of writing objects is intertwined with potentially
    starting a transaction.

We have refactored `force_object_loose()` over preceding commits to work
via generic interfaces now, so this reason doesn't exist anymore. But
the second reason still does, as our management of "files" transactions
and their ad-hoc creation is still very messy. This area definitely
requires further work, and that work is indeed ongoing.

That being said, we can already move the writing logic into the "loose"
backend rather easily. All we have to do is to expose two functions that
relate to the transactions.

Expose these two functions and move the writing logic into the "loose"
backend accordingly so that it becomes more self-contained. Note that
this requires us to drop a reference to `the_repository` in favor of
using the source's repository in `start_loose_object_common()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-18 19:03:49 -07:00
Patrick Steinhardt 8d9135dce3 odb: support setting mtime when writing objects
The function `force_object_loose()` is used to loosen packed objects
before repacking. It passes the pack's mtime along so that the newly
written loose object inherits the same timestamp. This matters for
object pruning, which uses the mtime to determine whether an object is
old enough to be pruned.

In a subsequent commit, `force_object_loose()` will be converted to use
the generic `odb_source_write_object()` interface instead of calling
`write_loose_object()` directly. But the generic interface doesn't yet
support setting a specific mtime, which makes it impossible to implement
the logic as of now.

Prepare for the change by introducing a new `mtime` parameter to this
function that we plumb through the stack. If set, the backends are
instructed to set the object's mtime accordingly. If unset, the backends
are expected to use the current time instead.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-18 19:03:48 -07:00
Patrick Steinhardt b688086b8f odb: lift object existence check out of the "loose" backend
Before writing a new loose object we first check whether the object
already exists in any of the sources attached to the object database.
This results in a couple of issues:

  - We have a layering violation, where the source needs to be aware of
    objects stored in any of the other sources.

  - Every backend would have to reimplement this check, which feels
    somewhat pointless.

  - It is not possible to easily write an object into a source in case
    the same object already exists in another source.

Refactor the code and lift up the object existence check from the
"loose" backend into the generic ODB layer. No callers need adjustment
as none of them write via a specific source, but via the ODB layer.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-18 19:03:48 -07:00
Patrick Steinhardt 46a586a719 odb: compute object hash in `odb_write_object_ext()`
Same as in a preceding commit, compute the object hash in
`odb_write_object_ext()` so that we can unify this logic.

Besides unification, this change also allows us to lift the object
existence check out of the "loose" backend into the generic layer, which
will happen in the next commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-18 19:03:48 -07:00
Patrick Steinhardt 215d305f45 odb: compute compat object ID in `odb_write_object_ext()`
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-18 19:03:48 -07:00
Junio C Hamano 9306f4f379 Merge branch 'jt/receive-pack-use-odb-transactions' into HEAD
'git receive-pack' has been refactored to use ODB transaction
interfaces instead of directly managing 'tmp_objdir' for staging
incoming objects, bringing it closer to being ODB backend agnostic.

* jt/receive-pack-use-odb-transactions:
  builtin/receive-pack: stage incoming objects via ODB transactions
  builtin/receive-pack: drop redundant tmpdir env
  odb/transaction: introduce ODB transaction flags
  odb/transaction: add transaction env interface
  odb/transaction: propagate commit errors
  odb/transaction: propagate begin errors
  object-file: propagate files transaction errors
  object-file: drop check for inflight transactions
  object-file: embed transaction flush logic in commit function
  object-file: rename files transaction fsync function
  object-file: rename files transaction prepare function
2026-07-18 19:02:51 -07:00
Junio C Hamano a9d2d2acde Merge branch 'ps/odb-drop-whence'
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-15 13:24:18 -07:00
Patrick Steinhardt 204daf5e5c odb: introduce object filters to `odb_for_each_object()`
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-15 07:19:16 -07:00
Patrick Steinhardt 27bed41ebb odb/source-packed: improve lookup when enumerating objects
When iterating through objects of a packed source that have a specific
prefix we do so via two different methods:

  - When a multi-pack index is available we use that one to efficiently
    loop through all objects.

  - We then loop through all packfiles that aren't covered by a
    multi-pack index.

Regardless of which mechanism we use, we then iterate through all the
objects indexed by the respective data structure. Curiously though,
while we use the indices for enumerating the objects, we completely
ignore it for the actual object lookup. Instead, we call into the
generic `odb_source_read_object_info()` function, which will itself
consult the indices to figure out where the object in question even
lives.

This has two consequences:

  - It's inefficient, as we basically have to figure out the position of
    the object a second time.

  - It's subtly wrong, as it may now happen that a specific object will
    be looked up via a different pack in case it exists multiple times.
    This is unlikely to have any real-world consequences, but it's still
    the wrong thing to do.

Fix the issue by using `packed_object_info()` directly. While at it,
rename the `store` variable to `source`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-15 07:19:15 -07:00
René Scharfe 2e486bfbf7 use repo_hold_lock_file_for_update{,_mode,_timeout}() with custom repos
Apply the config setting core.sharedRepository from the repository at
hand instead of from the_repository.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-14 12:54:25 -07:00
Junio C Hamano 6eb10fffa5 Merge branch 'ps/odb-generalize-prepare'
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-13 08:27:28 -07:00
Patrick Steinhardt 56f3fc9520 odb: make optimizations pluggable
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-13 08:13:17 -07:00
Justin Tobler 48d730a16a odb/transaction: introduce ODB transaction flags
The temporary directory used by git-receive-pack(1) to write objects is
managed slightly differently than how it is done via ODB transactions:

  - The temporary directory is eagerly created upfront, instead of
    waiting for the first object write.

  - The prefix name of the temporary directory is "incoming" instead of
    "bulk-fsync".

In a subsequent commit, git-receive-pack(1) will use ODB transactions
instead of `tmp_objdir` directly. To provide a means to configure the
same transaction behavior, introduce `enum odb_transaction_flags` and
the ODB_TRANSACTION_RECEIVE flag intended as a signal for ODB
transactions using the "files" backend to be set up for
git-receive-pack(1). Transaction call sites are updated accordingly to
provide the required flag parameter.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-10 13:21:53 -07:00
Justin Tobler 28fbc06769 odb/transaction: add transaction env interface
The ODB transaction backend is responsible for creating/managing its own
staging area for writing objects. Other child processes spawned by Git
may need access to uncommitted objects or write new objects in the
staging area though.

Introduce `odb_transaction_env()` which is expected to provide the set
of environment variables needed by a child process to access the
transaction's staging area.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-10 13:21:53 -07:00
Justin Tobler dbb3c87ee4 odb/transaction: propagate commit errors
When `odb_transaction_commit()` is invoked, the return value of the
backend commit callback is silently discarded. A backend has no way
to signal that committing failed, such as when the "files" backend
cannot migrate its temporary object directory into the permanent
ODB.

In a subsequent commit, git-receive-pack(1) starts using ODB transaction
to stage objects and consequently cares about such failures so it can
handle the error appropriately. Change the commit callback signature to
return an int error code and have `odb_transaction_commit()` forward it
accordingly.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-10 13:21:53 -07:00
Justin Tobler 4576d6c522 odb/transaction: propagate begin errors
When `odb_transaction_begin()` is invoked, the function returns the
transaction pointer directly. There is no way for the backend to
signal that it failed to set up its state, such as when creating the
temporary object directory backing the transaction.

In a subsequent commit, git-receive-pack(1) starts using ODB
transactions and needs to be able to report such failures rather
than silently ignore them. Refactor `odb_transaction_begin()` to
return an int error code and write the resulting transaction into an
out parameter. Also introduce `odb_transaction_begin_or_die()` as a
convenience for callsites that do not need to handle errors
explicitly.

Note that `odb_transaction_begin()` now returns an error when the ODB
already has an inflight transaction pending. ODB transaction call sites
that may encounter an inflight transaction are updated to explicitly
handle this case.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-10 13:21:53 -07:00
Justin Tobler 6d017185e3 object-file: propagate files transaction errors
The "files" transaction backend may encounter errors related to managing
the temporary directory used to stage objects, but silently ignores
these errors. Instead return errors encountered in the
`odb_transaction_files_{prepare,begin,commit}()` interfaces to allow
callers to handle them as needed.

Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-10 13:21:53 -07:00
Junio C Hamano 37e3640f25 Merge branch 'ps/odb-drop-whence' into ps/odb-for-each-object-filter
* 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-09 10:12:15 -07:00
Junio C Hamano a4d2e8a074 Merge branch 'ps/connected-generic-promisor-checks'
The connectivity check has been refactored to search for promisor
objects in a generic way using the object database interface,
rather than iterating packfiles directly. This allows connectivity
checks to work properly in repositories that do not use packfiles.

* ps/connected-generic-promisor-checks:
  connected: search promisor objects generically
  connected: split out promisor-based connectivity check
  odb/source-packed: support flags when iterating an object prefix
  odb/source-packed: extract logic to skip certain packs
2026-07-06 15:50:25 -07:00
Junio C Hamano 6786e9ce00 Merge branch 'po/hash-object-size-t'
Support for hashing loose or packed objects larger than 4GB on Windows
and other LLP64 platforms has been improved by converting object header
buffers and data-handling functions from 'unsigned long' to 'size_t'.

* po/hash-object-size-t:
  hash-object: add a >4GB/LLP64 test case using filtered input
  hash-object: add another >4GB/LLP64 test case
  hash-object --stdin: verify that it works with >4GB/LLP64
  hash algorithms: use size_t for section lengths
  object-file.c: use size_t for header lengths
  hash-object: demonstrate a >4GB/LLP64 problem
2026-07-06 15:50:22 -07:00
Junio C Hamano a7f8e84772 Merge branch 'ps/odb-source-packed'
The packed object source has been refactored into a proper struct
odb_source.

* ps/odb-source-packed:
  odb/source-packed: drop pointer to "files" parent source
  midx: refactor interfaces to work on "packed" source
  odb/source-packed: stub out remaining functions
  odb/source-packed: wire up `freshen_object()` callback
  odb/source-packed: wire up `find_abbrev_len()` callback
  odb/source-packed: wire up `count_objects()` callback
  odb/source-packed: wire up `for_each_object()` callback
  odb/source-packed: wire up `read_object_stream()` callback
  odb/source-packed: wire up `read_object_info()` callback
  packfile: use higher-level interface to implement `has_object_pack()`
  odb/source-packed: wire up `reprepare()` callback
  odb/source-packed: wire up `close()` callback
  odb/source-packed: start converting to a proper `struct odb_source`
  odb/source-packed: store pointer to "files" instead of generic source
  packfile: move packed source into "odb/" subsystem
  packfile: split out packfile list logic
  packfile: rename `struct packfile_store` to `odb_source_packed`
2026-07-06 15:50:21 -07:00
Patrick Steinhardt aea037e534 odb: drop `whence` field from object info
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-02 09:52:32 -07:00
Patrick Steinhardt 32a95be604 odb: add `source` field to struct object_info_source
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-02 09:52:32 -07:00
Patrick Steinhardt 11c689b873 packfile: thread odb_source_packed through packed_object_info()
Add an optional `struct odb_source_packed *source` parameter to
`packed_object_info()` and `packed_object_info_with_index_pos()`. This
parameter is unused at this point in time, but it will be used in a
follow-up commit so that we can record the source of a specific object.

Note that callers in "odb/source-packed.c" pass the already-available
source, but all other callers pass `NULL` instead. This is fine though,
as we only care about populating this info when called via the packed
store.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-02 09:52:32 -07:00