Commit Graph

616 Commits (2c47028e632339f133c368bb9716cc1386fffe4d)

Author SHA1 Message Date
Junio C Hamano 412eb590dd Merge branch 'cc/lazy-fetch-trusted-bit' into seen
A new 'uploadpack.lazyFetchTrusted' configuration variable has been
introduced to allow 'upload-pack' to lazily fetch missing objects from
configured promisor remotes when serving trusted repositories.

* cc/lazy-fetch-trusted-bit:
  builtin/upload-pack: set GIT_NO_LAZY_FETCH to 0 on trusted repo
  promisor-remote: prevent infinite recursion when lazy fetching
  upload-pack: read uploadpack.lazyFetchTrusted
  setup: extract path_allowlist_apply()
  promisor-remote: factor out lazy_fetch_objects()
2026-09-17 12:54:39 -07:00
Junio C Hamano fdb8395264 Merge branch 'ps/ref-storage-format' into jch
The terminology regarding reference storage formats has been unified
across command-line options, environment variables, configuration
variables, and source code, standardizing on the phrase "ref storage
format" (e.g., `--ref-storage-format`, `'GIT_REF_STORAGE_FORMAT'`).
Additionally, the `--ref-storage-format` option has been updated to
accept payloads in the form `<format>://<payload>`.

* ps/ref-storage-format:
  setup: allow "--ref-storage-format=" to specify a payload
  setup: rename "init.defaultRefFormat" to "init.defaultRefStorageFormat"
  t: rename GIT_TEST_DEFAULT_REF_FORMAT
  setup: rename ref storage format environment variables
  setup: refactor how we configure the ref storage format
  refs: expose function to parse reference URIs
  help: rename "default-ref-format" to "default-ref-storage-format"
  builtin/rev-parse: rename "--show-ref-format" to "--show-ref-storage-format"
  builtin/submodule: rename "--ref-format=" to "--ref-storage-format="
  builtin/refs: rename "--ref-format=" to "--ref-storage-format="
  builtin/clone: rename "--ref-format=" to "--ref-storage-format="
  builtin/init: rename "--ref-format=" to "--ref-storage-format="
  parse-options: allow for hidden aliases
2026-09-17 12:54:15 -07:00
Junio C Hamano 1847b18a9b Merge branch 'ps/odb-alternates-at-creation' into jch
The setup of alternates has been deferred to object database
creation time during clone, which drops the unused ad-hoc alternate
writing API, simplifying the object database backend interface.

* ps/odb-alternates-at-creation:
  odb/source: remove the ability to write alternates
  builtin/clone: write alternates via `odb_create_on_disk()`
  odb/source: support writing alternates when creating the database
  builtin/clone: move setup of alternates for non-shared local clones
  builtin/clone: move setup of alternates for shared local clones
  builtin/clone: refactor handling of "--reference{,-if-able}"
  builtin/clone: move around `setup_reference()`
  builtin/clone: defer setup of the object database
  setup: split up concerns of `init_db()`
2026-09-17 12:54:13 -07:00
Patrick Steinhardt a9c1a15deb builtin/clone: write alternates via `odb_create_on_disk()`
When creating a repository with alternates we first initialize the
object database and then write alternates to it in a separate step. This
is unfortunate due to a couple of reasons:

  - It requires us to have a `write_alternates()` callback, which is
    unfortunate as we never even write alternates to an object database
    after it has been created.

  - We're about to make alternates an implementation detail of the
    object database's backend in a future patch series, so having this
    callback is suboptimal there.

  - The backend has more flexibility with how exactly alternates are
    configured when it itself is in full control over their setup at the
    time where it creates the object database itself.

We have thus introduced the ability to write alternates right at
creation time in the preceding commits, and we have unified setup of
alternates into a single location. All that's left to do for us now is
to wire up alternates as an option for the database creation.

Do so.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-10 13:07:03 -07:00
Patrick Steinhardt d13e56771d odb/source: support writing alternates when creating the database
Add the ability to write alternates when creating the object database.
This change allows us to remove the `write_alternates()` callback in a
subsequent patch.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-10 13:07:03 -07:00
Patrick Steinhardt 20e38cba39 setup: split up concerns of `init_db()`
The function `init_db()` is responsible for creating the on-disk
directory structure required for a Git repository. It is used by both
git-init(1) and git-clone(1), and because their expected behaviour is
different we support a couple of flags:

  - The `QUIET` flag controls whether the command is quiet or not. For
    git-init(1) this is user-controllable, whereas for git-clone(1)
    we're always quiet.

  - The `EXIST_OK` flag controls whether a preexisting repository is
    okay or not. For git-init(1) it is, for git-clone(1) it's not.

  - The `SKIP_REFDB` flag controls whether the reference database should
    already be created or not. For git-init(1) we do, but for
    git-clone(1) we don't because it does not yet know about the default
    branch and about the remote object hash.

Furthermore, we're about to add another divergence in behaviour, where
we have to also skip creation of the object database in git-clone(1).
This is becoming quite cumbersome though.

Instead of introducing another flag, start to split up concerns of the
function so that we never create the reference or object database. This
becomes the responsibility of the caller, which is thus free to defer
their creation to a later point in time. This lets us get rid of most of
the divergent behaviour:

  - We don't need the `SKIP_REFDB` and a potential `SKIP_ODB` flags
    anymore.

  - We don't need the `QUIET` flag anymore, as nothing prints output
    except for the final status message that tells the user that the
    repository has been (re)initialized. But as this message is specific
    to git-init(1), we can easily move it there.

The only piece of information we still have to convey is whether or not
reinitialization of a preexisting repository is okay. This is handled by
a new `reinit_ok` pointer that, if non-`NULL`, indicates that it is okay
to reinitialize the repository. Furthermore, the pointer will be written
to to indicate whether the repository was reinitialized or not, which we
need in git-init(1) to print the correct initialization message.

With these refactorings, `init_db()` is named quite misleadingly though,
as we don't create any of the reference or object databases anymore.
Rename it to `create_repository()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-10 13:07:02 -07:00
Patrick Steinhardt dd907a4172 setup: allow "--ref-storage-format=" to specify a payload
Reference storage backends can be configured with a payload via the
"extensions.refStorage" config key and the "GIT_REF_STORAGE_FORMAT"
environment variable, both of which accept a URI in the format
"<format>://<payload>". The payload may contain backend-specific
information, for example an alternate refs directory or which database
references should be stored in.

The `--ref-storage-format=` option of git-init(1) and git-clone(1) does
not know about payloads though: its value is parsed as a plain format
name, so backends that require a payload cannot be conveniently set up
at initialization time via the command line.

Teach the option to accept the same URI syntax. Also, document the
optional payloads for both the "files" and "reftable" backends.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-09 11:04:31 -07:00
Patrick Steinhardt 53d995c53f setup: rename "init.defaultRefFormat" to "init.defaultRefStorageFormat"
With the same reasoning as for git-init(1), rename the
"init.defaultRefFormat" config option to "init.defaultRefStorageFormat"
and keep the old name as an alias.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-09 11:04:31 -07:00
Patrick Steinhardt 768ec52864 setup: rename ref storage format environment variables
With the same reasoning as for git-init(1), rename the environment
variables GIT_REFERENCE_BACKEND and GIT_DEFAULT_REF_FORMAT to
GIT_REF_STORAGE_FORMAT and GIT_DEFAULT_REF_STORAGE_FORMAT, respectively.
The old names are kept as an alias to retain compatibility.

While at it, fix indentation for `GIT_REF_STORAGE_FORMAT` docs to use
tabs instead of spaces.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-09 11:04:31 -07:00
Patrick Steinhardt 78c0b35650 setup: refactor how we configure the ref storage format
When (re)initializing a repository we need to figure out the ref storage
format that the repository ought to use. This logic is surprisingly
complex, as we have grown a lot of different mechanisms over time to
configure the format. Unfortunately, as a result of this organic growth,
the logic that configures the storage format has grown very complex.

The biggest culprit here is that we're mixing the logic that determines
the desired storage format with the logic that validates whether the end
result is sane. This leads to some repetitive code, and makes it very
easy to forget validation for some of the branches.

In fact, the way we handle GIT_REFERENCE_BACKEND shows exactly one such
edge case where we don't properly validate. When initializing a
repository with one storage format and then reinitializing it with the
environment variable set to a different format then we'd corrupt the
repository because we silently change the format:

    $ git init repo
    $ git -C repo commit --allow-empty -m message
    $ GIT_REFERENCE_BACKEND=reftable git -C repo init
    fatal: could not open '.../refs/heads' for writing: Is a directory
    $ git -C repo log
    fatal: your current branch appears to be broken

Refactor the code so that we clearly distinguish between these two
different concerns. This lets us clearly spell out the precedence order
and makes the whole logic significantly easier to extend going forward.

Note that the new logic intentionally changes the precedence order so
that "GIT_REFERENCE_BACKEND" is now overridden by the
"--ref-storage-format=" command line option. This matches our usual
precedence order, where explicit command line arguments override
environment variables.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-09 11:04:31 -07:00
Patrick Steinhardt 0af0e959c8 refs: expose function to parse reference URIs
In the next commit we're about to add more sites that want to parse a
reference backends URI into a format and payload. Expose a new function
`ref_storage_format_by_uri()` that enables this.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-09 11:04:31 -07:00
Christian Couder e63bb82850 setup: extract path_allowlist_apply()
In a following commit we are going to check whether a repository is
part of an allowlist specified in a config variable.

To prepare for that let's extract existing code from
safe_directory_cb() into a new path_allowlist_apply() helper that will
help with such checks.

While at it let's make the helper's code simpler and more generic, by
passing it a `bool (*allow_path)(const char *path, void *cbdata)`
function that decides if a path is acceptable by the caller.

To further simplify how to reuse that new helper, and avoid duplicating
the config-value handling in a future commit, let's also introduce a
path_allowlist_config_apply() helper.

For clarity, let's change the `int is_safe` to `bool safe` in
`struct safe_directory_data`.

Signed-off-by: Christian Couder <christian.couder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-09-08 10:02:56 -07:00
Junio C Hamano d595003219 Merge branch 'yn/worktree-repair-relative'
The git worktree repair command failed to rewrite the .git file of
a working tree from a relative path to an absolute path when the
command was run in the working tree itself. The
read_gitfile_gently() function was modified to also return whether
the path originally recorded in the file was absolute, and this new
capability is used to correctly detect such mismatches.

* yn/worktree-repair-relative:
  worktree repair: detect relative path in .git file correctly
2026-09-07 09:32:06 -07:00
Junio C Hamano 8b92a9cf4f Merge branch 'ps/odb-eagerly-load-alternates'
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
2026-08-31 08:24:59 -07:00
Yoichi NAKAYAMA 53d330c360 worktree repair: detect relative path in .git file correctly
Given a state in which the cross-references between the worktree and
the repository (specifically worktree/id/gitdir in the main repository
and the .git file in the worktree) are recorded using absolute paths,
setting 'worktree.useRelativePaths=true' and running 'git worktree
repair' within the main worktree converts them to relative paths.

Conversely, given a state in which the cross-references are recorded
using relative paths, one would expect that setting
'worktree.useRelativePaths=false' and running 'git worktree repair'
would convert them to absolute paths. However, they remain as relative
paths.

This is because we incorrectly use read_gitfile_gently(), which always
returns an absolute path. To fix this, introduce read_gitfile_raw(),
which reads the path from the .git file without resolving it to an
absolute path.

Because read_gitfile_raw() does not validate the path with
is_git_directory(), repair_gitfile() performs this validation to
preserve the existing behavior.

Signed-off-by: Yoichi NAKAYAMA <yoichi.nakayama@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-28 10:22:04 -07:00
Junio C Hamano 3caf98a8bf Merge branch 'ch/chdir-notify-drop-name'
The unused name parameter in 'struct chdir_notify_entry' has been
removed from chdir_notify_register(), chdir_notify_unregister(), and
related callback signatures across several subsystems, simplifying the
API now that trace output no longer uses it.

* ch/chdir-notify-drop-name:
  chdir-notify.h: Removed unused param 'name'
2026-08-25 10:53:33 -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 1c46ce6dda setup: create ref and object databases after config is written
When creating a new repository we create both the reference and object
databases after we have finalized the repository. This ensures that
those subsystems find a fully-configured repository at the time where
they are asked to create their own on-disk data structures.

There is one exception though: while we have already fully configured
the repository at this point, we haven't yet written both
"core.sharedRepository" and "receive.denyNonFastforwards". The latter
configuration doesn't really matter to us, but the first one does as the
"files" object database source reads it.

This doesn't cause any problems right now, but it will in a subsequent
patch where we will start to read "core.ignoreCase" when creating the
object database. Move the initialization of both of these data
structures towards the end of `init_db()`. The only thing that now comes
after is status reporting, but that's it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-17 09:36:09 -07:00
Colin Hinton f17d211c97 chdir-notify.h: Removed unused param 'name'
The `name` parameter in `chdir_notify_entry` was only ever used by
chdir_notify_reparent() to produce trace output. That function was
removed in 5bf546755c (chdir-notify: drop unused
`chdir_notify_reparent()`, 2026-06-25), which left `name` with no
remaining consumers.

Prior to that removal, most callers had already stopped passing a
meaningful name, switching to NULL in 1f43ff2c7e (refs: unregister
reference stores from "chdir_notify", 2026-06-25) and 0de2467e6c
(odb/source-packed: start converting to a proper `struct odb_source`,
2026-06-17).

Since no caller has populated `name` with real data for some time,
and its last consumer is gone, drop it from chdir_notify_register(),
chdir_notify_unregister(), and the callback signature to simplify
the API.

Signed-off-by: Colin Hinton <colinlewishinton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-14 15:08:35 -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 c1d233bd30 setup: defer object database creation
In a subsequent commit we'll make the creation of the on-disk data
structures of an object database pluggable. This will lead to an
in-between state where we have already configured the repository's
object database, but it's not usable yet until we eventually call
`create_object_directory()`.

Lift the call to `odb_new()` out of `apply_repository_format()` so that
callers have more wiggle room with when exactly they call it, and adapt
them accordingly. The only exception is `init_db()`, where we now defer
creating the object database until we call `create_object_database()`.

With this change, initializing and creating the object database on disk
is now neatly encapsulated in a single function, which will make it
easier for a subsequent commit to move creation of the on-disk data
structures into the `struct odb_source` backends.

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 30bc6f0e8c setup: handle ODB-related environment variables in `odb_new()`
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-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 bb8bc6995e Merge branch 'ps/copy-wo-the-repository'
The copy_file() and copy_file_with_time() functions have been
refactored to take a repository parameter, allowing the removal of the
implicit dependency on the global 'the_repository' variable in
'copy.c'.

* ps/copy-wo-the-repository:
  copy: drop dependency on `the_repository`
2026-07-27 09:09:00 -07:00
Junio C Hamano 0c20b08631 Merge branch 'ps/refs-wo-the-repository'
The ref subsystem and the worktree API have been refactored to pass a
repository pointer down the call chain, allowing them to drop
references to the global 'the_repository' variable.  As part of this,
the handling of the 'core.packedRefsTimeout' configuration has been
moved into the per-repository ref store structure.

* ps/refs-wo-the-repository:
  refs: remove remaining uses of `the_repository`
  worktree: pass repository to public functions
  worktree: pass repository to file-local functions
  worktree: refactor code to use available repositories
  refs/files: drop `USE_THE_REPOSITORY_VARIABLE`
  refs/packed: de-globalize handling of "core.packedRefsTimeout"
2026-07-27 09:08:59 -07:00
Junio C Hamano 2688b28699 Merge branch 'ps/setup-split-discovery-and-setup'
The repository discovery and repository configuration phases, which
were previously intertwined in 'setup.c', have been split.  Repository
discovery has been updated to populate a 'struct repo_discovery'
without modifying the repository state, which is then taken by
repository configuration to initialize the repository, paving the way
for clean unification of repository configuration.

* ps/setup-split-discovery-and-setup:
  setup: mark `set_git_work_tree()` as file-local
  setup: pass worktree to `init_db()`
  setup: drop redundant configuration of `startup_info->have_repository`
  setup: make repository discovery self-contained
  setup: propagate prefix via repository discovery
  setup: drop static `cwd` variable
  setup: move prefix into repository
  setup: embed repository format in discovery
  setup: introduce explicit repository discovery
  setup: split up concerns of `setup_git_env_internal()`
  setup: unify setup of shallow file
  setup: mark bogus worktree in `apply_repository_format()`
  setup: rename `check_repository_format_gently()`
2026-07-19 10:42:15 -07:00
Patrick Steinhardt 0717b3595d copy: drop dependency on `the_repository`
When copying a file we need to potentially adapt permissions of the new
file based on whether or not "core.shared" is enabled. Parsing this
configuration makes us implicitly depend on `the_repository`.

Refactor the code to instead require the caller to pass in a repository
so that we can remove `USE_THE_REPOSITORY_VARIABLE`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-16 14:10:08 -07:00
Patrick Steinhardt e2533e0915 worktree: pass repository to public functions
Refactor remaining public functions that still depend on
`the_repository` to instead receive a repository as parameter. This
allows us to get rid of `USE_THE_REPOSITORY_VARIABLE`.

Adapt callers accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-16 07:40:22 -07:00
Patrick Steinhardt 4df38c632f setup: mark `set_git_work_tree()` as file-local
In the preceding commit we have removed the last callers of
`set_git_work_tree()` that is located outside of "setup.c". Remove its
declaration and mark the function as file-local.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:41 -07:00
Patrick Steinhardt 293b7850a7 setup: pass worktree to `init_db()`
In the preceding commits we have refactored how we discover and set up
repositories so that we cannot end up with partially-configured repos.
Instead, we apply the gitdir, worktree and repository format in a single
location, only.

Initializing a new repository has the same antipattern though: while
most of the information for the new repository is passed via parameters,
the work tree is instead propagated by configuring the repository's work
tree.

Refactor the code so that we also pass the work tree as an explicit
parameter. Like this, configuration fo the repository happens in a
single spot, too, just as with repository discovery.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:41 -07:00
Patrick Steinhardt eba53f5f5f setup: drop redundant configuration of `startup_info->have_repository`
In `init_db()` we set `startup_info->have_repository` twice: once before
reading and applying the repository format and once after. This is
redundant though, as configuring the repository format does not rely on
this variable at all.

Remove the first such site. While at it, fix up formatting a bit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:41 -07:00
Patrick Steinhardt 2513a4d6f3 setup: make repository discovery self-contained
In the preceding commits we have introduced a separate repository
discovery phase and refactored the logic so that we have two clear
phases:

  1. Repository discovery, which doesn't modify the repository itself at
     all.

  2. Repository configuration, which takes the information we have
     discovered to set up the repository.

Extract the first phase into a new function `repo_discover()` to further
stress these two different phases.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:41 -07:00
Patrick Steinhardt 0bf8e14643 setup: propagate prefix via repository discovery
In the preceding commits we have started to propagate all information
required for the configuration of the repository via a new `struct
repo_discovery`. The only exception is the repository's prefix, which we
still return via the return parameter.

This is conceptually fine, but somewhat inconsistent. Refactor this to
instead propagate the prefix via the repository discovery, too.

While at it, drop a static variable in `repo_discover_bare_gitdir()`.
We apply its value to the repository discovery anyway, so we don't have
to keep it around afterwards anymore.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:41 -07:00
Patrick Steinhardt 28f38f35a0 setup: drop static `cwd` variable
The current working directory is stored as part of a static strbuf
variable. This variable had to have a lifetime longer than its
containing function because the value we return typically points into
that buffer.

In the preceding commit we have moved the prefix into the repository
though. Consequently, we can now return the repository's prefix instead
of the local one and thus properly manage the lifecycle of this local
variable.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt b964ad1f01 setup: move prefix into repository
The repository prefix is currently stored in the startup info. This
feels somewhat awkward though, as it is inherently a property of a given
repository.

Move the prefix into the repository accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt abe894164f setup: embed repository format in discovery
All functions related to repository discovery receive both a `struct
repository_discovery` and `struct repository_format` as input, and the
expectation is that both will be populated. Refactor this so that the
repository format is part of the discovery result.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt d66975fa06 setup: introduce explicit repository discovery
When setting up the global repository we intermix repository discovery
and repository configuration: we repeatedly call `set_git_work_tree()`
and `apply_and_export_relative_gitdir()` until we're happy with the
result. The result of this is then a partially-configured repository
that we use for further setup.

This process is quite hard to follow, as it's never quite clear which
parts of the repository have been configured already and which haven't.
Furthermore, it means that the repository configuration is distributed
across many different places instead of having it neatly contained in a
single location. Ultimately, this is the reason that we cannot use a
central function like `repo_init()`.

Refactor the logic so that we stop partially-configuring a repository
and instead populate a new `struct repo_discovery`. This allow us to
essentially split repository setup into two phases:

  - The first phase only figures out parameters required to configure
    the repository.

  - The second phase then takes these parameters and applies them to the
    repository.

Like this, we'll never end up with a partially-configured repository and
can eventually extend `repo_init()` to handle the full initialization
for us.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt cf1687a41c setup: split up concerns of `setup_git_env_internal()`
The function `setup_git_env_internal()` does two completely unrelated
things:

  - It configures the repository's gitdir and propagates environment
    variables into it.

  - It configures a couple of global parameters via environment
    variables.

The function is called when we initialize the repository's path, but
it's also called via `chdir_notify_register()` whenever we change the
current working directory. While we indeed have to reconfigure the
gitdir in case it's a relative path, it doesn't make sense to reapply
the global environment variables.

Split up concerns of this function along the above delineation. Handling
of the global environment variables is moved into `init_git()`, as they
can be considered part of our setup procedure.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt d43b9acb05 setup: unify setup of shallow file
It is possible to configure an arbitrary "shallow" file via two
mechanisms, and the respective logic to handle these is split across two
locations:

  - Via the "GIT_SHALLOW_FILE" environment variable, which is handled in
    `setup_git_env_internal()`.

  - Via the global "--shallow-file=" command line option, which is
    handled in `handle_options()`.

We can rather easily unify this logic by not configuring the shallow
file in `handle_options()`, but instead overwriting the environment
variable. The environment variable itself is then handled inside of
`apply_repository_format()`, which is responsible for configuring a
discovered Git directory.

This new logic is similar in nature to how we handle the other global
options already, all of which end up setting an environment variable.
So for one this gives us more consistency. But more importantly, this
change means that `the_repository` will not contain any relevant state
anymore before we hit `apply_repository_format()` once we're at the end
of this patch series. Consequently, it will become possible for us to
completely discard `the_repository` and populate it anew.

Note that on first sight, this change looks like it might change the
precedence order. Before this change, we used to configure the shallow
file in the arguments handler first, and then it looks like we override
it via the environment variable. What's important to note though is the
last parameter to `set_alternate_shallow_file()`, which tells us whether
we want to overwrite a preexisting value, and when applying the value
from the environment we tell it not to overwrite preexisting values. So
in effect, the command line has precedence over the environment. After
this change, we now overwrite preexisting environment variables when we
see the argument, and consequently we keep the precedence order in tact.

With this change though we don't need the final parameter anymore that
tells `set_alternate_shallow_file()` whether or not to overwrite. We
only have a single callsite for this function now, and that function is
itself only ever called exactly once. Remove that parameter.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt c6799958b1 setup: mark bogus worktree in `apply_repository_format()`
When a repository is configured to have both "core.worktree" and
"core.bare" we emit a warning and mark the worktree configuration as
bogus so that the next call to `setup_work_tree()` will cause us to die.
This allows us to still use the misconfigured repository, at least as
long as we don't try to use its worktree.

This condition is handled in `setup_explicit_git_dir()`. In a subsequent
commit we'll refactor this function so that it doesn't receive a repo as
input anymore though, and consequently we cannot set the "bogus" bit
anymore.

Move the logic into `apply_repository_format()` instead to prepare for
this. While at it, fix up formatting a bit.

Note that this change requires us to also explicitly unset the value of
"core.worktree" in case we have the "GIT_WORK_TREE" environment variable
set. This is because the environment variable overrides the repository's
configuration, and we don't want to warn or die in case the work tree
has been configured explicitly regardless of whether or not "core.bare"
is set.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Patrick Steinhardt 9ca3ea9881 setup: rename `check_repository_format_gently()`
The function `check_repository_format_gently()` receives a format as
input. An unknowing reader may thus suspect that this function actually
checks the passed-in format for consistency. While the function indeed
checks the repository format, it actually serves two purposes:

  - It reads the repository's format and populates the passed-in format
    with that information.

  - It then indeed checks whether the format is consistent.

Rename the function to `read_and_verify_repository_format()` to clarify
its functionality. While at it, reorder the parameters so that the
format comes first to better match other functions that pass around the
format.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-07-07 10:49:40 -07:00
Junio C Hamano 3442a0fb79 Merge branch 'ps/refs-onbranch-fixes'
Reference backend configuration has been updated to load lazily to
avoid recursive calls during repository initialization when 'onbranch'
configuration conditions are evaluated. This has also fixed a memory
leak and allowed the unused `chdir_notify_reparent()` machinery to be
dropped.

* ps/refs-onbranch-fixes:
  refs: protect against chicken-and-egg recursion
  refs/reftable: lazy-load configuration to fix chicken-and-egg
  reftable: split up write options
  refs/files: lazy-load configuration to fix chicken-and-egg
  refs: move parsing of "core.logAllRefUpdates" back into ref stores
  repository: free main reference database
  chdir-notify: drop unused `chdir_notify_reparent()`
  refs: unregister reference stores from "chdir_notify"
  setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
  setup: stop applying repository format twice
  setup: inline `check_and_apply_repository_format()`
2026-07-06 15:50:24 -07:00
Junio C Hamano ed5d4f6e89 Merge branch 'jk/setup-gitfile-diag-fix'
A regression in the error diagnosis code for invalid .git files has
been fixed, avoiding a potential NULL-pointer crash when reporting
that a .git file does not point to a valid repository.

* jk/setup-gitfile-diag-fix:
  read_gitfile(): simplify NOT_A_REPO error message
2026-07-06 15:50:20 -07:00
Junio C Hamano 4f71cef8dd Merge branch 'ps/setup-drop-global-state' into ps/setup-split-discovery-and-setup
* ps/setup-drop-global-state:
  treewide: drop USE_THE_REPOSITORY_VARIABLE
  environment: stop using `the_repository` in `is_bare_repository()`
  environment: split up concerns of `is_bare_repository_cfg`
  builtin/init: stop modifying `is_bare_repository_cfg`
  setup: remove global `git_work_tree_cfg` variable
  builtin/init: simplify logic to configure worktree
  builtin/init: stop modifying global `git_work_tree_cfg` variable
2026-06-30 11:28:10 -07:00
Patrick Steinhardt a9e4ce0aec refs: move parsing of "core.logAllRefUpdates" back into ref stores
In cc42c88945 (refs: extract out reflog config to generic layer,
2026-05-04) we have refactored how we parse "core.logAllRefUpdates" so
that it happens in the generic layer. Unfortunately, this has worsened a
preexisting issue where we may recurse when creating the reference store
because of a chicken-and-egg problem between parsing the configuration
and evaluating "onbranch" conditions.

Prepare for a fix by essentially reverting that change so that we handle
this setting in the respective backends again. The backends are already
parsing other configuration anyway, so by moving the logic back in there
we can ensure that all backend configuration is parsed the same way.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-26 08:27:19 -07:00
Patrick Steinhardt 7d9ffe68f2 setup: don't apply "GIT_REFERENCE_BACKEND" without a repository
When discovering a repository we eventually also apply the
"GIT_REFERENCE_BACKEND" environment variable to the repository. There's
two problems with that:

  - We do this unconditionally, which is rather pointless: we really
    only have to configure the repository when we have found one.

  - We have already applied the repository format at that point in time,
    so we need to manually reapply it.

Move the logic around so that we only apply the environment variable
when a repository was discovered. This also allows us to drop the
explcit call to `repo_set_ref_storage_format()` because we now adjust
the format before we apply it via `apply_repository_format()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-26 08:27:19 -07:00
Patrick Steinhardt 93c4361c41 setup: stop applying repository format twice
When discovering the repository in "setup.c" we apply the final
repository format multiple times:

  - Once via `repository_format_configure()`, where we apply the hash
    algorithm and ref storage format to both `struct repository_format`
    and `struct repository`.

  - And once via `apply_repository_format()`, where we apply these two
    settings from `struct repository_format` to `struct repository`.

With the current flow both of these are in fact necessary. But this is
only because we call `repository_format_configure()` after we have
called `apply_repository_format()`. Consequently, if we only changed the
repository format in `repository_format_configure()` it would never
propagate to the repository.

Refactor the code so that we first configure the repository format
before applying it to the repository so that we can stop setting the
hash and reference storage format multiple times.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-26 08:27:19 -07:00
Patrick Steinhardt 35b6b8256c setup: inline `check_and_apply_repository_format()`
We have two callsites of `check_and_apply_repository_format()`. In a
subsequent commit we'll want to adapt one of those callsites to change
the order in which we read and apply the repository format, at which
point the helper function will not really be a good fit for us anymore.

Inline the function to both of the callsites.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-26 08:27:19 -07:00
Junio C Hamano f19edf4d01 Merge branch 'ps/setup-centralize-odb-creation' into ps/refs-onbranch-fixes
* ps/setup-centralize-odb-creation:
  setup: construct object database in `apply_repository_format()`
  repository: stop reading loose object map twice on repo init
  setup: stop initializing object database without repository
  setup: stop creating the object database in `setup_git_env()`
  repository: stop initializing the object database in `repo_set_gitdir()`
  setup: deduplicate logic to apply repository format
  setup: drop `setup_git_env()`
  t0001: plug test gaps for git-init(1) with GIT_OBJECT_DIRECTORY
2026-06-26 08:26:01 -07:00