]> git.ipfire.org Git - thirdparty/git.git/log
thirdparty/git.git
5 months agodiffcore-rename: fix BUG when break detection and --follow used together
Elijah Newren [Sat, 15 Mar 2025 01:08:13 +0000 (01:08 +0000)] 
diffcore-rename: fix BUG when break detection and --follow used together

Prior to commit 9db2ac56168e (diffcore-rename: accelerate rename_dst
setup, 2020-12-11), the function add_rename_dst() resulted in quadratic
runtime since each call inserted the new entry into the array in sorted
order.  The reason for the sorted order requirement was so that
locate_rename_dst(), used when break detection is turned on, could find
the appropriate entry in logarithmic time via bisection on string
comparisons.  (It's better to be quadratic in moving pointers than
quadratic in string comparisons, so this made some sense.)  However,
since break detection always sticks the broken pairs adjacent to each
other, that commit decided to simply append entries to rename_dst, and
record the mapping of (filename) -> (index within rename_dst) via a
strintmap.  Doing this relied on the fact that when adding the source of
a broken pair via register_rename_src(), that the next item we'd process
was the other half of the same broken pair and would be added to
rename_dst via add_rename_dst().  This assumption was fine under break
detection alone, but the combination of break detection and
single_follow violated that assumption because of this code:

else if (options->single_follow &&
 strcmp(options->single_follow, p->two->path))
continue; /* not interested */

which would end up skipping calling add_rename_dst() below that point.
Since I knew I was assuming that the dst pair of a break would always be
added right after the src pair of a break, I added a new BUG() directive
as part of that commit later on at time of use that would check my
assumptions held.  That BUG() didn't trip for nearly 4 years...which
sadly meant I had long since forgotten the related details.  Anyway...

When the dst half of a broken pair is skipped like this, it means that
not only could my recorded index be invalid (just past the end of the
array), it could also point to some unrelated dst that just happened to
be the next one added to the array.  So, to fix this, we need to add a
little more safety around the checks for the recorded break_idx.

It turns out that making a testcase to trigger this is quite the
challenge.  I actually added two testscases:
  * One testcase which uses --follow incorrectly (it uses its single
    pathspec to specifying something other than a single filename), and
    which triggers the same bug reported-by Olaf.  This triggers a
    special case within locate_rename_dst() where idx evaluates to 0
    and rename_dst is NULL, meaning that our return value of
    &rename_dst[idx] happens to evaluate to NULL as well.  This
    addressing of an index into a NULL array hints at deeper problems,
    which are raised in the next testcase...
  * A second testcase which when run under valgrind shows that the code
    actually depends upon unintialized memory, in particular the entry
    just after the end of the rename_dst array.

In short, when the two rare options -B and --follow are used together,
fix the accidental find of the wrong dst entry (which would often be
uninitialized memory just past the end of the array, but also could
have just been a dst for an unrelated path if no dst was recorded for
the expected path).  Do so by adding a little more care around checking
the recorded indices in break_idx.

Reported-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoxdiff: avoid arithmetic overflow in xdl_get_hunk()
René Scharfe [Fri, 14 Mar 2025 22:00:42 +0000 (23:00 +0100)] 
xdiff: avoid arithmetic overflow in xdl_get_hunk()

xdl_get_hunk() calculates the maximum number of common lines between two
changes that would fit into the same hunk for the given context options.
It involves doubling and addition and thus can overflow if the terms are
huge.

The type of ctxlen and interhunkctxlen in xdemitconf_t is long, while
the type of the corresponding context and interhunkcontext in struct
diff_options is int.  On many platforms longs are bigger that ints,
which prevents the overflow.  On Windows they have the same range and
the overflow manifests as hunks that are split erroneously and lines
being repeated between them.

Fix the overflow by checking and not going beyond LONG_MAX.  This allows
specifying a huge context line count and getting all lines of a changed
files in a single hunk, as expected.

Reported-by: Jason Cho <jason11choca@proton.me>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoGit 2.49 v2.49.0
Junio C Hamano [Fri, 14 Mar 2025 16:19:41 +0000 (09:19 -0700)] 
Git 2.49

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/pack-objects.c: freshen objects from existing cruft packs
Taylor Blau [Thu, 13 Mar 2025 18:09:47 +0000 (14:09 -0400)] 
builtin/pack-objects.c: freshen objects from existing cruft packs

Once an object is written into a cruft pack, we can only freshen it by
writing a new loose or packed copy of that object with a more recent
mtime.

Prior to 61568efa95 (builtin/pack-objects.c: support `--max-pack-size`
with `--cruft`, 2023-08-28), we typically had at most one cruft pack in
a repository at any given time. So freshening unreachable objects was
straightforward when already rewriting the cruft pack (and its *.mtimes
file).

But 61568efa95 changes things: 'pack-objects' now supports writing
multiple cruft packs when invoked with `--cruft` and the
`--max-pack-size` flag. Cruft packs are rewritten until they reach some
size threshold, at which point they are considered "frozen", and will
only be modified in a pruning GC, or if the threshold itself is
adjusted.

Prior to this patch, however, this process breaks down when we attempt
to freshen an object packed in an earlier cruft pack, and that cruft
pack is larger than the threshold and thus will survive the repack.

When this is the case, it is impossible to freshen objects in cruft
pack(s) when those cruft packs are larger than the threshold. This is
because we would avoid writing them in the new cruft pack entirely, for
a couple of reasons.

 1. When enumerating packed objects via 'add_objects_in_unpacked_packs()'
    we pass the SKIP_IN_CORE_KEPT_PACKS, which is used to avoid looping
    over the packs we're going to retain (which are marked as kept
    in-core by 'read_cruft_objects()').

    This means that we will avoid enumerating additional packed copies
    of objects found in any cruft packs which are larger than the given
    size threshold. Thus there is no opportunity to call
    'create_object_entry()' whatsoever.

 2. We likewise will discard the loose copy (if one exists) of any
    unreachable object packed in a cruft pack that is larger than the
    threshold. Here our call path is 'add_unreachable_loose_objects()',
    which uses the 'add_loose_object()' callback.

    That function will eventually land us in 'want_object_in_pack()'
    (via 'add_cruft_object_entry()'), and we'll discard the object as it
    appears in one of the packs which we marked as kept in-core.

This means in effect that it is impossible to freshen an unreachable
object once it appears in a cruft pack larger than the given threshold.

Instead, we should pack an additional copy of an unreachable object we
want to freshen even if it appears in a cruft pack, provided that the
cruft copy has an mtime which is before the mtime of the copy we are
trying to pack/freshen. This is sub-optimal in the sense that it
requires keeping an additional copy of unreachable objects upon
freshening, but we don't have a better alternative without the ability
to make in-place modifications to existing *.mtimes files.

In order to implement this, we have to adjust the behavior of
'want_found_object()'. When 'pack-objects' is told that we're *not*
going to retain any cruft packs (i.e. the set of packs marked as kept
in-core does not contain a cruft pack), the behavior is unchanged.

But when there *is* at least one cruft pack that we're holding onto, it
is no longer sufficient to reject a copy of an object found in that
cruft pack for that reason alone. In this case, we only want to reject a
candidate object when copies of that object either:

 - exists in a non-cruft pack that we are retaining, regardless of that
   pack's mtime, or

 - exists in a cruft pack with an mtime at least as recent as the copy
   we are debating whether or not to pack, in which case freshening
   would be redundant.

To do this, keep track of whether or not we have any cruft packs in our
in-core kept list with a new 'ignore_packed_keep_in_core_has_cruft'
flag. When we end up in this new special case, we replace a call to
'has_object_kept_pack()' to 'want_cruft_object_mtime()', and only reject
objects when we have a copy in an existing cruft pack with at least as
recent an mtime as our candidate (in which case "freshening" would be
redundant).

Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoMerge tag 'l10n-2.49.0-rnd1' of https://github.com/git-l10n/git-po
Junio C Hamano [Thu, 13 Mar 2025 17:20:33 +0000 (10:20 -0700)] 
Merge tag 'l10n-2.49.0-rnd1' of https://github.com/git-l10n/git-po

l10n-2.49.0-rnd1

* tag 'l10n-2.49.0-rnd1' of https://github.com/git-l10n/git-po:
  l10n: zh_TW: Git 2.49.0 round 1
  l10n: update German translation
  l10n: po-id for 2.49
  l10n: zh_CN: updated translation for 2.49
  l10n: uk: add 2.49 translation
  l10n: tr: Update Turkish translations for 2.49.0
  l10n: ko: fix minor typo in Korean translation
  l10n: it: fix spelling of "sorgente" (Italian for "source")
  l10n: sv.po: Fix Swedish typos
  l10n: sv.po: Update Swedish translation
  l10n: fr: 2.49 round 2
  l10n: bg.po: Updated Bulgarian translation (5836t)
  l10n: Updated translation for vi-2.49

5 months agoMerge branch 'l10n/zh-TW/2025-03-09' of github.com:l10n-tw/git-po
Jiang Xin [Thu, 13 Mar 2025 13:57:56 +0000 (21:57 +0800)] 
Merge branch 'l10n/zh-TW/2025-03-09' of github.com:l10n-tw/git-po

* 'l10n/zh-TW/2025-03-09' of github.com:l10n-tw/git-po:
  l10n: zh_TW: Git 2.49.0 round 1

5 months agol10n: zh_TW: Git 2.49.0 round 1
Yi-Jyun Pan [Sun, 9 Mar 2025 02:54:02 +0000 (10:54 +0800)] 
l10n: zh_TW: Git 2.49.0 round 1

Co-authored-by: Lumynous <lumynou5.tw@gmail.com>
Signed-off-by: Yi-Jyun Pan <pan93412@gmail.com>
5 months agoMerge branch 'l10n-de-2.49' of github.com:ralfth/git
Jiang Xin [Thu, 13 Mar 2025 06:15:38 +0000 (14:15 +0800)] 
Merge branch 'l10n-de-2.49' of github.com:ralfth/git

* 'l10n-de-2.49' of github.com:ralfth/git:
  l10n: update German translation

5 months agol10n: update German translation
Ralf Thielow [Thu, 13 Mar 2025 06:03:42 +0000 (07:03 +0100)] 
l10n: update German translation

Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>
5 months agol10n: po-id for 2.49
Bagas Sanjaya [Tue, 4 Mar 2025 08:26:27 +0000 (15:26 +0700)] 
l10n: po-id for 2.49

Update following components:

  * builtin/clone.c
  * builtin/commit.c
  * builtin/fetch.c
  * builtin/index-pack.c
  * builtin/pack-objects.c
  * builtin/refs.c
  * builtin/repack.c
  * builtin/unpack-objects.c
  * command-list.h
  * diff.c
  * object-file.c
  * parse-options.c
  * promisor-remote.c
  * refspec.c
  * remote.c

Translate following new components:

  * path-walk.c
  * builtin/backfill.c
  * t/helper/test-path-walk.c

Signed-off-by: Bagas Sanjaya <bagasdotme@gmail.com>
5 months agoA bit more updates after -rc2
Junio C Hamano [Wed, 12 Mar 2025 19:06:30 +0000 (12:06 -0700)] 
A bit more updates after -rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoMerge branch 'pb/doc-follow-remote-head'
Junio C Hamano [Wed, 12 Mar 2025 19:06:58 +0000 (12:06 -0700)] 
Merge branch 'pb/doc-follow-remote-head'

Doc updates.

* pb/doc-follow-remote-head:
  config/remote.txt: improve wording for 'remote.<name>.followRemoteHEAD'
  config/remote.txt: reunite 'severOption' description paragraphs

5 months agoMerge branch 'tc/zlib-ng-fix'
Junio C Hamano [Wed, 12 Mar 2025 19:06:58 +0000 (12:06 -0700)] 
Merge branch 'tc/zlib-ng-fix'

"git version --build-options" stopped showing zlib version by
mistake due to recent refactoring, which has been corrected.

* tc/zlib-ng-fix:
  help: print zlib-ng version number
  help: include git-zlib.h to print zlib version

5 months agoMerge branch 'ma/clone-doc-markup-fix'
Junio C Hamano [Wed, 12 Mar 2025 19:06:57 +0000 (12:06 -0700)] 
Merge branch 'ma/clone-doc-markup-fix'

Doc markup fix.

* ma/clone-doc-markup-fix:
  git-clone doc: fix indentation

5 months agoMerge branch 'ps/refname-avail-check-optim' into kn/non-transactional-batch-updates
Junio C Hamano [Wed, 12 Mar 2025 18:55:05 +0000 (11:55 -0700)] 
Merge branch 'ps/refname-avail-check-optim' into kn/non-transactional-batch-updates

* ps/refname-avail-check-optim: (43 commits)
  refs: reuse iterators when determining refname availability
  refs/iterator: implement seeking for files iterators
  refs/iterator: implement seeking for packed-ref iterators
  refs/iterator: implement seeking for ref-cache iterators
  refs/iterator: implement seeking for reftable iterators
  refs/iterator: implement seeking for merged iterators
  refs/iterator: provide infrastructure to re-seek iterators
  refs/iterator: separate lifecycle from iteration
  refs: stop re-verifying common prefixes for availability
  refs/files: batch refname availability checks for initial transactions
  refs/files: batch refname availability checks for normal transactions
  refs/reftable: batch refname availability checks
  refs: introduce function to batch refname availability checks
  builtin/update-ref: skip ambiguity checks when parsing object IDs
  object-name: allow skipping ambiguity checks in `get_oid()` family
  object-name: introduce `repo_get_oid_with_flags()`
  Git 2.49-rc0
  The fourteenth batch
  mailmap: fix check-mailmap with full mailmap line
  The thirteenth batch
  ...

5 months agorefs: reuse iterators when determining refname availability
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:22 +0000 (16:56 +0100)] 
refs: reuse iterators when determining refname availability

When verifying whether refnames are available we have to verify whether
any reference exists that is nested under the current reference. E.g.
given a reference "refs/heads/foo", we must make sure that there is no
other reference "refs/heads/foo/*".

This check is performed using a ref iterator with the prefix set to the
nested reference namespace. Until now it used to not be possible to
reseek iterators, so we always had to reallocate the iterator for every
single reference we're about to check. This keeps us from reusing state
that the iterator may have and that may make it work more efficiently.

Refactor the logic to reseek iterators. This leads to a sizeable speedup
with the "reftable" backend:

    Benchmark 1: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):      39.8 ms ±   0.9 ms    [User: 29.7 ms, System: 9.8 ms]
      Range (min … max):    38.4 ms …  42.0 ms    62 runs

    Benchmark 2: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):      31.9 ms ±   1.1 ms    [User: 27.0 ms, System: 4.5 ms]
      Range (min … max):    29.8 ms …  34.3 ms    74 runs

    Summary
      update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.25 ± 0.05 times faster than update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)

The "files" backend doesn't really show a huge impact:

    Benchmark 1: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     392.3 ms ±   7.1 ms    [User: 59.7 ms, System: 328.8 ms]
      Range (min … max):   384.6 ms … 404.5 ms    10 runs

    Benchmark 2: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):     387.7 ms ±   7.4 ms    [User: 54.6 ms, System: 329.6 ms]
      Range (min … max):   377.0 ms … 397.7 ms    10 runs

    Summary
      update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.01 ± 0.03 times faster than update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)

This is mostly because it is way slower to begin with because it has to
create a separate file for each new reference, so the milliseconds we
shave off by reseeking the iterator doesn't really translate into a
significant relative improvement.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: implement seeking for files iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:21 +0000 (16:56 +0100)] 
refs/iterator: implement seeking for files iterators

Implement seeking for "files" iterators. As we simply use a ref-cache
iterator under the hood the implementation is straight-forward. Note
that we do not implement seeking on reflog iterators, same as with the
"reftable" backend.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: implement seeking for packed-ref iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:20 +0000 (16:56 +0100)] 
refs/iterator: implement seeking for packed-ref iterators

Implement seeking of `packed-ref` iterators. The implementation is again
straight forward, except that we cannot continue to use the prefix
iterator as we would otherwise not be able to reseek the iterator
anymore in case one first asks for an empty and then for a non-empty
prefix. Instead, we open-code the logic to in `advance()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: implement seeking for ref-cache iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:19 +0000 (16:56 +0100)] 
refs/iterator: implement seeking for ref-cache iterators

Implement seeking of ref-cache iterators. This is done by splitting most
of the logic to seek iterators out of `cache_ref_iterator_begin()` and
putting it into `cache_ref_iterator_seek()` so that we can reuse the
logic.

Note that we cannot use the optimization anymore where we return an
empty ref iterator when there aren't any references, as otherwise it
wouldn't be possible to reseek the iterator to a different prefix that
may exist. This shouldn't be much of a performance concern though as we
now start to bail out early in case `advance()` sees that there are no
more directories to be searched.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: implement seeking for reftable iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:18 +0000 (16:56 +0100)] 
refs/iterator: implement seeking for reftable iterators

Implement seeking of reftable iterators. As the low-level reftable
iterators already support seeking this change is straight-forward. Two
notes though:

  - We do not support seeking on reflog iterators. It is unclear what
    seeking would even look like in this context, as you typically would
    want to seek to a specific entry in the reflog for a specific ref.
    There is currently no use case for this, but if one arises in the
    future, we can still implement seeking at that later point.

  - We start to check whether `reftable_stack_init_ref_iterator()` is
    successful.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: implement seeking for merged iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:17 +0000 (16:56 +0100)] 
refs/iterator: implement seeking for merged iterators

Implement seeking on merged iterators. The implementation is rather
straight forward, with the only exception that we must not deallocate
the underlying iterators once they have been exhausted.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: provide infrastructure to re-seek iterators
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:16 +0000 (16:56 +0100)] 
refs/iterator: provide infrastructure to re-seek iterators

Reftable iterators need to be scrapped after they have either been
exhausted or aren't useful to the caller anymore, and it is explicitly
not possible to reuse them for iterations. But enabling for reuse of
iterators may allow us to tune them by reusing internal state of an
iterator. The reftable iterators for example can already be reused
internally, but we're not able to expose this to any users outside of
the reftable backend.

Introduce a new `.seek` function in the ref iterator vtable that allows
callers to seek an iterator multiple times. It is expected to be
functionally the same as calling `refs_ref_iterator_begin()` with a
different (or the same) prefix.

Note that it is not possible to adjust parameters other than the seeked
prefix for now, so exclude patterns, trimmed prefixes and flags will
remain unchanged. We do not have a usecase for changing these parameters
right now, but if we ever find one we can adapt accordingly.

Implement the callback for trivial cases. The other iterators will be
implemented in subsequent commits.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/iterator: separate lifecycle from iteration
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:15 +0000 (16:56 +0100)] 
refs/iterator: separate lifecycle from iteration

The ref and reflog iterators have their lifecycle attached to iteration:
once the iterator reaches its end, it is automatically released and the
caller doesn't have to care about that anymore. When the iterator should
be released before it has been exhausted, callers must explicitly abort
the iterator via `ref_iterator_abort()`.

This lifecycle is somewhat unusual in the Git codebase and creates two
problems:

  - Callsites need to be very careful about when exactly they call
    `ref_iterator_abort()`, as calling the function is only valid when
    the iterator itself still is. This leads to somewhat awkward calling
    patterns in some situations.

  - It is impossible to reuse iterators and re-seek them to a different
    prefix. This feature isn't supported by any iterator implementation
    except for the reftable iterators anyway, but if it was implemented
    it would allow us to optimize cases where we need to search for
    specific references repeatedly by reusing internal state.

Detangle the lifecycle from iteration so that we don't deallocate the
iterator anymore once it is exhausted. Instead, callers are now expected
to always call a newly introduce `ref_iterator_free()` function that
deallocates the iterator and its internal state.

Note that the `dir_iterator` is somewhat special because it does not
implement the `ref_iterator` interface, but is only used to implement
other iterators. Consequently, we have to provide `dir_iterator_free()`
instead of `dir_iterator_release()` as the allocated structure itself is
managed by the `dir_iterator` interfaces, as well, and not freed by
`ref_iterator_free()` like in all the other cases.

While at it, drop the return value of `ref_iterator_abort()`, which
wasn't really required by any of the iterator implementations anyway.
Furthermore, stop calling `base_ref_iterator_free()` in any of the
backends, but instead call it in `ref_iterator_free()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs: stop re-verifying common prefixes for availability
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:14 +0000 (16:56 +0100)] 
refs: stop re-verifying common prefixes for availability

One of the checks done by `refs_verify_refnames_available()` is whether
any of the prefixes of a reference already exists. For example, given a
reference "refs/heads/main", we'd check whether "refs/heads" or "refs"
already exist, and if so we'd abort the transaction.

When updating multiple references at once, this check is performed for
each of the references individually. Consequently, because references
tend to have common prefixes like "refs/heads/" or refs/tags/", we
evaluate the availability of these prefixes repeatedly. Naturally this
is a waste of compute, as the availability of those prefixes should in
general not change in the middle of a transaction. And if it would,
backends would notice at a later point in time.

Optimize this pattern by storing prefixes in a `strset` so that we can
trivially track those prefixes that we have already checked. This leads
to a significant speedup with the "reftable" backend when creating many
references that all share a common prefix:

    Benchmark 1: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):      63.1 ms ±   1.8 ms    [User: 41.0 ms, System: 21.6 ms]
      Range (min … max):    60.6 ms …  69.5 ms    38 runs

    Benchmark 2: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):      40.0 ms ±   1.3 ms    [User: 29.3 ms, System: 10.3 ms]
      Range (min … max):    38.1 ms …  47.3 ms    61 runs

    Summary
      update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.58 ± 0.07 times faster than update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)

For the "files" backend we see an improvement, but a much smaller one:

    Benchmark 1: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     395.8 ms ±   5.3 ms    [User: 63.6 ms, System: 330.5 ms]
      Range (min … max):   387.0 ms … 404.6 ms    10 runs

    Benchmark 2: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):     386.0 ms ±   4.0 ms    [User: 51.5 ms, System: 332.8 ms]
      Range (min … max):   380.8 ms … 392.6 ms    10 runs

    Summary
      update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.03 ± 0.02 times faster than update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)

This change also leads to a modest improvement when writing references
with "initial" semantics, for example when migrating references. The
following benchmarks are migrating 1m references from the "reftable" to
the "files" backend:

    Benchmark 1: migrate reftable:files (refcount = 1000000, revision = HEAD~)
      Time (mean ± σ):     836.6 ms ±   5.6 ms    [User: 645.2 ms, System: 185.2 ms]
      Range (min … max):   829.6 ms … 845.9 ms    10 runs

    Benchmark 2: migrate reftable:files (refcount = 1000000, revision = HEAD)
      Time (mean ± σ):     759.8 ms ±   5.1 ms    [User: 574.9 ms, System: 178.9 ms]
      Range (min … max):   753.1 ms … 768.8 ms    10 runs

    Summary
      migrate reftable:files (refcount = 1000000, revision = HEAD) ran
        1.10 ± 0.01 times faster than migrate reftable:files (refcount = 1000000, revision = HEAD~)

And vice versa:

    Benchmark 1: migrate files:reftable (refcount = 1000000, revision = HEAD~)
      Time (mean ± σ):     870.7 ms ±   5.7 ms    [User: 735.2 ms, System: 127.4 ms]
      Range (min … max):   861.6 ms … 883.2 ms    10 runs

    Benchmark 2: migrate files:reftable (refcount = 1000000, revision = HEAD)
      Time (mean ± σ):     799.1 ms ±   8.5 ms    [User: 661.1 ms, System: 130.2 ms]
      Range (min … max):   787.5 ms … 812.6 ms    10 runs

    Summary
      migrate files:reftable (refcount = 1000000, revision = HEAD) ran
        1.09 ± 0.01 times faster than migrate files:reftable (refcount = 1000000, revision = HEAD~)

The impact here is significantly smaller given that we don't perform any
reference reads with "initial" semantics, so the speedup only comes from
us doing less string list lookups.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/files: batch refname availability checks for initial transactions
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:13 +0000 (16:56 +0100)] 
refs/files: batch refname availability checks for initial transactions

The "files" backend explicitly carves out special logic for its initial
transaction so that it can avoid writing out every single reference as
a loose reference. While the assumption is that there shouldn't be any
preexisting references, we still have to verify that none of the newly
written references will conflict with any other new reference in the
same transaction.

Refactor the initial transaction to use batched refname availability
checks. This does not yet have an effect on performance as we still call
`refs_verify_refname_available()` in a loop. But this will change in
subsequent commits and then impact performance when cloning a repository
with many references or when migrating references to the "files" format.

This will improve performance when cloning a repository with many
references or when migrating references from any format to the "files"
format once the availability checks have learned to optimize checks for
many references in a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/files: batch refname availability checks for normal transactions
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:12 +0000 (16:56 +0100)] 
refs/files: batch refname availability checks for normal transactions

Same as the "reftable" backend that we have adapted in the preceding
commit to use batched refname availability checks we can also do so for
the "files" backend. Things are a bit more intricate here though, as we
call `refs_verify_refname_available()` in a set of different contexts:

  1. `lock_raw_ref()` when it hits either EEXISTS or EISDIR when creating
     a new reference, mostly to create a nice, user-readable error
     message. This is nothing we have to care about too much, as we only
     hit this code path at most once when we hit a conflict.

  2. `lock_raw_ref()` when it _could_ create the lockfile to check
     whether it is conflicting with any packed refs. In the general case,
     this code path will be hit once for every (successful) reference
     update.

  3. `lock_ref_oid_basic()`, but it is only executed when copying or
     renaming references or when expiring reflogs. It will thus not be
     called in contexts where we have many references queued up.

  4. `refs_refname_ref_available()`, but again only when copying or
     renaming references. It is thus not interesting due to the same
     reason as the previous case.

  5. `files_transaction_finish_initial()`, which is only executed when
     creating a new repository or migrating references.

So out of these, only (2) and (5) are viable candidates to use the
batched checks.

Adapt `lock_raw_ref()` accordingly by queueing up reference names that
need to be checked for availability and then checking them after we have
processed all updates. This check is done before we (optionally) lock
the `packed-refs` file, which is somewhat flawed because it means that
the `packed-refs` could still change after the availability check and
thus create an undetected conflict. But unconditionally locking the file
would change semantics that users are likely to rely on, so we keep the
current locking sequence intact, even if it's suboptmial.

The refactoring of `files_transaction_finish_initial()` will be done in
the next commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs/reftable: batch refname availability checks
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:11 +0000 (16:56 +0100)] 
refs/reftable: batch refname availability checks

Refactor the "reftable" backend to batch the availability check for
refnames. This does not yet have an effect on performance as
`refs_verify_refnames_available()` effectively still performs the
availability check for each refname individually. But this will be
optimized in subsequent commits, where we learn to optimize some parts
of the logic when checking multiple refnames for availability.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefs: introduce function to batch refname availability checks
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:10 +0000 (16:56 +0100)] 
refs: introduce function to batch refname availability checks

The `refs_verify_refname_available()` functions checks whether a
reference update can be committed or whether it would conflict with
either a prefix or suffix thereof. This function needs to be called once
per reference that one wants to check, which requires us to redo a
couple of checks every time the function is called.

Introduce a new function `refs_verify_refnames_available()` that does
the same, but for a list of references. For now, the new function uses
the exact same implementation, except that we loop through all refnames
provided by the caller. This will be tuned in subsequent commits.

The existing `refs_verify_refname_available()` function is reimplemented
on top of the new function. As such, the diff is best viewed with the
`--ignore-space-change option`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/update-ref: skip ambiguity checks when parsing object IDs
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:09 +0000 (16:56 +0100)] 
builtin/update-ref: skip ambiguity checks when parsing object IDs

Most of the commands in git-update-ref(1) accept an old and/or new
object ID to update a specific reference to. These object IDs get parsed
via `repo_get_oid()`, which not only handles plain object IDs, but also
those that have a suffix like "~" or "^2". More surprisingly though, it
even knows to resolve arbitrary revisions, despite the fact that its
manpage does not mention this fact even once.

One consequence of this is that we also check for ambiguous references:
when parsing a full object ID where the DWIM mechanism would also cause
us to resolve it as a branch, we'd end up printing a warning. While this
check makes sense to have in general, it is arguably less useful in the
context of git-update-ref(1). This is due to multiple reasons:

  - The manpage is explicitly structured around object IDs. So if we see
    a fully blown object ID, the intent should be quite clear in
    general.

  - The command is part of our plumbing layer and not a tool that users
    would generally use in interactive workflows. As such, the warning
    will likely not be visible to anybody in the first place.

  - Users can and should use the fully-qualified refname in case there
    is any potential for ambiguity. And given that this command is part
    of our plumbing layer, one should always try to be as defensive as
    possible and use fully-qualified refnames.

Furthermore, this check can be quite expensive when updating lots of
references via `--stdin`, because we try to read multiple references per
object ID that we parse according to the DWIM rules. This effect can be
seen both with the "files" and "reftable" backend.

The issue is not unique to git-update-ref(1), but was also an issue in
git-cat-file(1), where it was addressed by disabling the ambiguity check
in 25fba78d36b (cat-file: disable object/refname ambiguity check for
batch mode, 2013-07-12).

Disable the warning in git-update-ref(1), which provides a significant
speedup with both backends. The user-visible outcome is unchanged even
when ambiguity exists, except that we don't show the warning anymore.

The following benchmark creates 10000 new references with a 100000
preexisting refs with the "files" backend:

    Benchmark 1: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     467.3 ms ±   5.1 ms    [User: 100.0 ms, System: 365.1 ms]
      Range (min … max):   461.9 ms … 479.3 ms    10 runs

    Benchmark 2: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):     394.1 ms ±   5.8 ms    [User: 63.3 ms, System: 327.6 ms]
      Range (min … max):   384.9 ms … 405.7 ms    10 runs

    Summary
      update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.19 ± 0.02 times faster than update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)

And with the "reftable" backend:

    Benchmark 1: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     146.9 ms ±   2.2 ms    [User: 90.4 ms, System: 56.0 ms]
      Range (min … max):   142.7 ms … 150.8 ms    19 runs

    Benchmark 2: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):      63.2 ms ±   1.1 ms    [User: 41.0 ms, System: 21.8 ms]
      Range (min … max):    61.1 ms …  66.6 ms    41 runs

    Summary
      update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD) ran
        2.32 ± 0.05 times faster than update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)

Note that the absolute improvement with both backends is roughly in the
same ballpark, but the relative improvement for the "reftable" backend
is more significant because writing the new table to disk is faster in
the first place.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoobject-name: allow skipping ambiguity checks in `get_oid()` family
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:08 +0000 (16:56 +0100)] 
object-name: allow skipping ambiguity checks in `get_oid()` family

When reading an object ID via `get_oid_basic()` or any of its related
functions we perform a check whether the object ID is ambiguous, which
can be the case when a reference with the same name exists. While the
check is generally helpful, there are cases where it only adds to the
runtime overhead without providing much of a benefit.

Add a new flag that allows us to disable the check. The flag will be
used in a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoobject-name: introduce `repo_get_oid_with_flags()`
Patrick Steinhardt [Wed, 12 Mar 2025 15:56:07 +0000 (16:56 +0100)] 
object-name: introduce `repo_get_oid_with_flags()`

Introduce a new function `repo_get_oid_with_flags()`. This function
behaves the same as `repo_get_oid()`, except that it takes an extra
`flags` parameter that it ends up passing to `get_oid_with_context()`.

This function will be used in a subsequent commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoci: perform build and smoke tests for Meson docs
Patrick Steinhardt [Wed, 12 Mar 2025 14:28:54 +0000 (15:28 +0100)] 
ci: perform build and smoke tests for Meson docs

Our "documentation" CI job performs a couple of tests against our
documentation. Part of these tests is to check whether documentation
builds at all and whether it spits out the expected set of files. We
don't yet have such a test for Meson, which means that we wouldn't
notice at all if building the documentation were to break. As a result,
breakages as fixed by 87eccc3a81d (meson: fix building technical and
howto docs, 2025-03-02) are easy to go unnoticed.

Address this test gap by starting to build both manpages and HTML sites
as part of the CI job.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agomeson: don't install git-pack-redundant(1) docs with breaking changes
Patrick Steinhardt [Wed, 12 Mar 2025 13:17:34 +0000 (14:17 +0100)] 
meson: don't install git-pack-redundant(1) docs with breaking changes

When breaking changes are enabled we continue to install documentation
of the git-pack-redundant(1) command even though it is completely
disabled and thus inaccessible. Improve this by only installing the
documentation in case breaking changes aren't enabled.

Based-on-patch-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agomeson: don't compile git-pack-redundant(1) with breaking changes
Patrick Steinhardt [Wed, 12 Mar 2025 13:17:33 +0000 (14:17 +0100)] 
meson: don't compile git-pack-redundant(1) with breaking changes

We continue to compile the git-pack-redundant(1) builtin with Meson when
breaking changes are enabled even though we ultimately don't expose this
command at all. This is mostly harmless, but given that the intent of
the build option is to be as close as possible to the state where the
breaking change has been fully implemented this isn't optimal either.

Improve the situation by not compiling the builtin when breaking changes
are enabled.

Based-on-patch-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agomeson: define WITH_BREAKING_CHANGES when enabling breaking changes
Patrick Steinhardt [Wed, 12 Mar 2025 13:17:32 +0000 (14:17 +0100)] 
meson: define WITH_BREAKING_CHANGES when enabling breaking changes

While Meson already supports the `-Dbreaking_changes=true` option, it
only wires up the build option that propagates into the tests. The build
option is only used for our tests to enable the `WITH_BREAKING_CHANGES`
prerequisite though, and does not influence the code that is actually
being built.

The omission went unnoticed because we only have tests right now that
get disabled when breaking changes are enabled, but not the other way
round. In other words, we don't have any tests that verify that breaking
changes behave as expected.

Fix the build issue by setting the `WITH_BREAKING_CHANGES` preprocessor
macro when breaking changes are enabled. Note that the `libgit_c_args`
array is defined after the current spot where we handle the option, so
to not have multiple sites where we handle it we instead move it after
the array has been defined.

Based-on-patch-by: Phillip Wood <phillip.wood123@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoname-rev: remove "--stdin" support
Junio C Hamano [Tue, 11 Mar 2025 21:25:05 +0000 (14:25 -0700)] 
name-rev: remove "--stdin" support

As part of Git 3.0, remove the hidden synonym for "--annotate-stdin"
for real.  As this does not change the fact that it used to be
called "--stdin" in older version of Git, keep that passage in the
documentation for "--annotate-stdin".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot6120: further modernize
Junio C Hamano [Tue, 11 Mar 2025 21:25:04 +0000 (14:25 -0700)] 
t6120: further modernize

There is absolutely no reason why a pattern given to grep to find
'warning: --stdin is deprecated' must be quoted within a pair of
single quotes, or the pattern to look for the literal string as ERE.

Quote the test body with a pair of single quotes like everybody
else, and quote the needle string in a pair of double quotes.  Also
use test_grep instead of "grep -E".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot6120: avoid hiding "git" exit status
Junio C Hamano [Tue, 11 Mar 2025 21:25:03 +0000 (14:25 -0700)] 
t6120: avoid hiding "git" exit status

A handful of tests invoke "git" on the upstream side of a pipe,
hiding its exit status.  Correct them.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot: introduce WITH_BREAKING_CHANGES prerequisite
Junio C Hamano [Tue, 11 Mar 2025 21:25:02 +0000 (14:25 -0700)] 
t: introduce WITH_BREAKING_CHANGES prerequisite

Earlier c5bc9a7f (Makefile: wire up build option for deprecated
features, 2025-01-22) made an unfortunate decision to introduce the
WITHOUT_BREAKING_CHANGES prerequisite to perform tests that ensure
the historical behaviour that may be different from what we will
have in the future.  It would inevitably invite double-negation when
we need to add tests to ensure the behaviour we want to have in the
future.

Introduce WITH_BREAKING_CHANGES prerequisite and replace the
existing uses of WITHOUT_BREAKING_CHANGES prerequisite.  To catch
any future topics that add more uses of WITHOUT_BREAKING_CHANGES,
mark it as a removed prerequisite.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoMerge branch 'tl/zh_CN_2.49.0_rnd' of github.com:dyrone/git
Jiang Xin [Wed, 12 Mar 2025 11:36:40 +0000 (19:36 +0800)] 
Merge branch 'tl/zh_CN_2.49.0_rnd' of github.com:dyrone/git

* 'tl/zh_CN_2.49.0_rnd' of github.com:dyrone/git:
  l10n: zh_CN: updated translation for 2.49

5 months agol10n: zh_CN: updated translation for 2.49
Teng Long [Sun, 9 Mar 2025 12:32:13 +0000 (20:32 +0800)] 
l10n: zh_CN: updated translation for 2.49

Helped-by: 依云 <lilydjwg@gmail.com>
Helped-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
Signed-off-by: Teng Long <dyroneteng@gmail.com>
5 months agoMerge branch '2.49-uk-update' of github.com:arkid15r
Jiang Xin [Wed, 12 Mar 2025 03:10:40 +0000 (11:10 +0800)] 
Merge branch '2.49-uk-update' of github.com:arkid15r

* '2.49-uk-update' of github.com:arkid15r/git-ukrainian-l10n:
  l10n: uk: add 2.49 translation

5 months agol10n: uk: add 2.49 translation
Arkadii Yakovets [Wed, 12 Mar 2025 02:39:45 +0000 (19:39 -0700)] 
l10n: uk: add 2.49 translation

Co-authored-by: Kate Golovanova <kate@kgthreads.com>
Co-authored-by: Mikhail T. <Mikhail.Teterin@BNY.com>
Co-authored-by: Tamara Lazerka <lazerkatamara@gmail.com>
Signed-off-by: Arkadii Yakovets <ark@cho.red>
Signed-off-by: Kate Golovanova <kate@kgthreads.com>
Signed-off-by: Mikhail T. <Mikhail.Teterin@BNY.com>
Signed-off-by: Tamara Lazerka <lazerkatamara@gmail.com>
5 months agodir.h: remove duplicate forward declaration of struct repository
Abhijeetsingh Meena [Tue, 11 Mar 2025 14:59:35 +0000 (14:59 +0000)] 
dir.h: remove duplicate forward declaration of struct repository

The `struct repository;` forward declaration appears twice in `dir.h`:
once at line 10 and again at line 46. This duplication is unnecessary
and likely unintentional.

Removing the second declaration has no impact on compilation, as verified
by a clean build.

Signed-off-by: Abhijeetsingh Meena <abhijeet040403@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot: extend test_lazy_prereq
Junio C Hamano [Tue, 11 Mar 2025 21:25:01 +0000 (14:25 -0700)] 
t: extend test_lazy_prereq

Allow test_lazy_prereq script to signal a programming error by
exiting with status 125 (like how bisect scripts do).  This is used
to signal a deprecated-and-then-removed prerequisite that should
never be used in tests anymore.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot: document test_lazy_prereq
Junio C Hamano [Tue, 11 Mar 2025 21:25:00 +0000 (14:25 -0700)] 
t: document test_lazy_prereq

The t/README file talked about test_set_prereq but lacked
explanation on test_lazy_prereq, which is a more modern way to
define prerequisites.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agol10n: tr: Update Turkish translations for 2.49.0
Emir SARI [Thu, 27 Feb 2025 10:22:50 +0000 (13:22 +0300)] 
l10n: tr: Update Turkish translations for 2.49.0

Signed-off-by: Emir SARI <emir_sari@icloud.com>
5 months agoMerge branch 'vi-2.49' of github.com:Nekosha/git-po
Jiang Xin [Mon, 10 Mar 2025 23:35:07 +0000 (07:35 +0800)] 
Merge branch 'vi-2.49' of github.com:Nekosha/git-po

* 'vi-2.49' of github.com:Nekosha/git-po:
  l10n: Updated translation for vi-2.49

5 months agoMerge branch 'master' of github.com:alshopov/git-po
Jiang Xin [Mon, 10 Mar 2025 23:33:18 +0000 (07:33 +0800)] 
Merge branch 'master' of github.com:alshopov/git-po

* 'master' of github.com:alshopov/git-po:
  l10n: bg.po: Updated Bulgarian translation (5836t)

5 months agoMerge branch 'fr_v2.49' of github.com:jnavila/git
Jiang Xin [Mon, 10 Mar 2025 23:23:32 +0000 (07:23 +0800)] 
Merge branch 'fr_v2.49' of github.com:jnavila/git

* 'fr_v2.49' of github.com:jnavila/git:
  l10n: fr: 2.49 round 2

5 months agoMerge branch 'master' of github.com:nafmo/git-l10n-sv
Jiang Xin [Mon, 10 Mar 2025 23:22:07 +0000 (07:22 +0800)] 
Merge branch 'master' of github.com:nafmo/git-l10n-sv

* 'master' of github.com:nafmo/git-l10n-sv:
  l10n: sv.po: Fix Swedish typos
  l10n: sv.po: Update Swedish translation

5 months agol10n: ko: fix minor typo in Korean translation
seoyeon-kwon [Thu, 23 Jan 2025 06:06:37 +0000 (15:06 +0900)] 
l10n: ko: fix minor typo in Korean translation

Signed-off-by: seoyeon-kwon <seoyeon.kwon@navercorp.com>
5 months agol10n: it: fix spelling of "sorgente" (Italian for "source")
Ruggero Turra [Sat, 22 Feb 2025 22:18:23 +0000 (23:18 +0100)] 
l10n: it: fix spelling of "sorgente" (Italian for "source")

Signed-off-by: Ruggero Turra <ruggero.turra@cern.ch>
5 months agofast-export, fast-import: add support for signed-commits
Luke Shumaker [Mon, 10 Mar 2025 15:57:46 +0000 (16:57 +0100)] 
fast-export, fast-import: add support for signed-commits

fast-export has a --signed-tags= option that controls how to handle tag
signatures.  However, there is no equivalent for commit signatures; it
just silently strips the signature out of the commit (analogously to
--signed-tags=strip).

While signatures are generally problematic for fast-export/fast-import
(because hashes are likely to change), if they're going to support tag
signatures, there's no reason to not also support commit signatures.

So, implement a --signed-commits= option that mirrors the --signed-tags=
option.

On the fast-export side, try to be as much like signed-tags as possible,
in both implementation and in user-interface.  This will change the
default behavior to '--signed-commits=abort' from what is now
'--signed-commits=strip'.  In order to provide an escape hatch for users
of third-party tools that call fast-export and do not yet know of the
--signed-commits= option, add an environment variable
'FAST_EXPORT_SIGNED_COMMITS_NOABORT=1' that changes the default to
'--signed-commits=warn-strip'.

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofast-export: do not modify memory from get_commit_buffer
Luke Shumaker [Mon, 10 Mar 2025 15:57:45 +0000 (16:57 +0100)] 
fast-export: do not modify memory from get_commit_buffer

fast-export's helper function find_encoding() takes a `const char *`, but
modifies that memory despite the `const`.  Ultimately, this memory came
from get_commit_buffer(), and you're not supposed to modify the memory
that you get from get_commit_buffer().

So, get rid of find_encoding() in favor of commit.h:find_commit_header(),
which gives back a string length, rather than mutating the memory to
insert a '\0' terminator.

Because find_commit_header() detects the "\n\n" string that separates the
headers and the commit message, move the call to be above the
`message = strstr(..., "\n\n")` call.  This helps readability, and allows
for the value of `encoding` to be used for a better value of "..." so that
the same memory doesn't need to be checked twice.  Introduce a
`commit_buffer_cursor` variable to avoid writing an awkward
`encoding ? encoding + encoding_len : committer_end` expression.

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agogit-fast-export.adoc: clarify why 'verbatim' may not be a good idea
Luke Shumaker [Mon, 10 Mar 2025 15:57:44 +0000 (16:57 +0100)] 
git-fast-export.adoc: clarify why 'verbatim' may not be a good idea

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofast-export: rename --signed-tags='warn' to 'warn-verbatim'
Luke Shumaker [Mon, 10 Mar 2025 15:57:43 +0000 (16:57 +0100)] 
fast-export: rename --signed-tags='warn' to 'warn-verbatim'

The --signed-tags= option takes one of five arguments specifying how to
handle signed tags during export.  Among these arguments, 'strip' is to
'warn-strip' as 'verbatim' is to 'warn' (the unmentioned argument is
'abort', which stops the fast-export process entirely).  That is,
signatures are either stripped or copied verbatim while exporting, with
or without a warning.

Match the pattern and rename 'warn' to 'warn-verbatim' to make it clear
that it instructs fast-export to copy signatures verbatim.

To maintain backwards compatibility, 'warn' is still recognized as
deprecated synonym of 'warn-verbatim'.

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofast-export: fix missing whitespace after switch
Christian Couder [Mon, 10 Mar 2025 15:57:42 +0000 (16:57 +0100)] 
fast-export: fix missing whitespace after switch

"Documentation/CodingGuidelines" says that there should be whitespaces
around operators like 'if', 'switch', 'for', etc.

Let's fix this in "builtin/fast-export.c".

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agogit-fast-import.adoc: add missing LF in the BNF
Luke Shumaker [Mon, 10 Mar 2025 15:57:41 +0000 (16:57 +0100)] 
git-fast-import.adoc: add missing LF in the BNF

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agodecorate: fix sign comparison warnings
Arnav Bhate [Mon, 10 Mar 2025 18:08:53 +0000 (23:38 +0530)] 
decorate: fix sign comparison warnings

There are multiple instances where ints have been initialized with
values of unsigned ints, and where negative values don't mean anything.
When such ints are compared with unsigned ints, it causes sign comparison
warnings.

Also, some of these are used just as stand-ins for their initial
values, never being modified, thus obscuring the specific conditions
under which certain operations happen.

Replace int with unsigned int for 2 variables, and replace the
intermediate variables with their initial values for 2 other variables.

Signed-off-by: Arnav Bhate <bhatearnav@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agohash: stop depending on `the_repository` in `null_oid()`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:31 +0000 (08:13 +0100)] 
hash: stop depending on `the_repository` in `null_oid()`

The `null_oid()` function returns the object ID that only consists of
zeroes. Naturally, this ID also depends on the hash algorithm used, as
the number of zeroes is different between SHA1 and SHA256. Consequently,
the function returns the hash-algorithm-specific null object ID.

This is currently done by depending on `the_hash_algo`, which implicitly
makes us depend on `the_repository`. Refactor the function to instead
pass in the hash algorithm for which we want to retrieve the null object
ID. Adapt callsites accordingly by passing in `the_repository`, thus
bubbling up the dependency on that global variable by one layer.

There are a couple of trivial exceptions for subsystems that already got
rid of `the_repository`. These subsystems instead use the repository
that is available via the calling context:

  - "builtin/grep.c"
  - "grep.c"
  - "refs/debug.c"

There are also two non-trivial exceptions:

  - "diff-no-index.c": Here we know that we may not have a repository
    initialized at all, so we cannot rely on `the_repository`. Instead,
    we adapt `diff_no_index()` to get a `struct git_hash_algo` as
    parameter. The only caller is located in "builtin/diff.c", where we
    know to call `repo_set_hash_algo()` in case we're running outside of
    a Git repository. Consequently, it is fine to continue passing
    `the_repository->hash_algo` even in this case.

  - "builtin/ls-files.c": There is an in-flight patch series that drops
    `USE_THE_REPOSITORY_VARIABLE` in this file, which causes a semantic
    conflict because we use `null_oid()` in `show_submodule()`. The
    value is passed to `repo_submodule_init()`, which may use the object
    ID to resolve a tree-ish in the superproject from which we want to
    read the submodule config. As such, the object ID should refer to an
    object in the superproject, and consequently we need to use its hash
    algorithm.

    This means that we could in theory just not bother about this edge
    case at all and just use `the_repository` in "diff-no-index.c". But
    doing so would feel misdesigned.

Remove the `USE_THE_REPOSITORY_VARIABLE` preprocessor define in
"hash.c".

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agohash: fix "-Wsign-compare" warnings
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:30 +0000 (08:13 +0100)] 
hash: fix "-Wsign-compare" warnings

There are a couple of trivial "-Wsign-compare" warnings in "hash.c". Fix
them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoobject-file: split out logic regarding hash algorithms
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:29 +0000 (08:13 +0100)] 
object-file: split out logic regarding hash algorithms

While we have a "hash.h" header, the actual implementation of the
subsystem is hosted by "object-file.c". This makes it harder than
necessary to find the actual implementation of the hash subsystem and
intermingles the different concerns with one another.

Split out the implementation of hash algorithms into a new, separate
"hash.c" file.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agodelta-islands: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:28 +0000 (08:13 +0100)] 
delta-islands: stop depending on `the_repository`

There are multiple sites in "delta-islands.c" where we use the
global `the_repository` variable, either explicitly or implicitly by
using `the_hash_algo`.

Refactor the code to stop using `the_repository`. In most cases this is
trivial because we already had a repository available in the calling
context, with the only exception being `propagate_island_marks()`. Adapt
it so that the repository gets passed in via a parameter.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoobject-file-convert: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:27 +0000 (08:13 +0100)] 
object-file-convert: stop depending on `the_repository`

There are multiple sites in "object-file-convert.c" where we use the
global `the_repository` variable, either explicitly or implicitly by
using `the_hash_algo`. All of these callsites are transitively called
from `convert_object_file()`, which indeed has no repo as input.

Refactor the function so that it receives a repository as a parameter
and pass it through to all internal functions to get rid of the
dependency. Remove the `USE_THE_REPOSITORY_VARIABLE` define.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agopack-bitmap-write: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:26 +0000 (08:13 +0100)] 
pack-bitmap-write: stop depending on `the_repository`

There are multiple sites in "pack-bitmap-write.c" where we use the
global `the_repository` variable, either explicitly or implicitly by
using `the_hash_algo`.

Refactor the code so that the `struct bitmap_writer` stores the
repository it is getting initialized with. Like this, we can adapt
callsites that use `the_repository` to instead use the repository
provided by the writer.

Remove the `USE_THE_REPOSITORY_VARIABLE` define.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agopack-revindex: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:25 +0000 (08:13 +0100)] 
pack-revindex: stop depending on `the_repository`

There are multiple sites in "pack-revindex.c" where we use the global
`the_repository` variable, either explicitly or implicitly by using
`the_hash_algo`. In all of those cases we already have a repository
available in the calling context though.

Refactor the code to instead use the caller-provided repository and
remove the `USE_THE_REPOSITORY_VARIABLE` define.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agopack-check: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:24 +0000 (08:13 +0100)] 
pack-check: stop depending on `the_repository`

There are multiple sites in "pack-check.c" where we use the global
`the_repository` variable, either explicitly or implicitly by using
`the_hash_algo`. In all of those cases we already have a repository
available in the calling context though.

Refactor the code to instead use the caller-provided repository and
remove the `USE_THE_REPOSITORY_VARIABLE` define.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoenvironment: move access to "core.bigFileThreshold" into repo settings
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:23 +0000 (08:13 +0100)] 
environment: move access to "core.bigFileThreshold" into repo settings

The "core.bigFileThreshold" setting is stored in a global variable and
populated via `git_default_core_config()`. This may cause issues in
the case where one is handling multiple different repositories in a
single process with different values for that config key, as we may or
may not see the correct value in that case. Furthermore, global state
blocks our path towards libification.

Refactor the code so that we instead store the value in `struct
repo_settings`, where the value is computed as-needed and cached.

Note that this change requires us to adapt one test in t1050 that
verifies that we die when parsing an invalid "core.bigFileThreshold"
value. The exercised Git command doesn't use the value at all, and thus
it won't hit the new code path that parses the value. This is addressed
by using git-hash-object(1) instead, which does read the value.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agopack-write: stop depending on `the_repository` and `the_hash_algo`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:22 +0000 (08:13 +0100)] 
pack-write: stop depending on `the_repository` and `the_hash_algo`

There are a couple of functions in "pack-write.c" that implicitly depend
on `the_repository` or `the_hash_algo`. Remove this dependency by
injecting the repository via a parameter and adapt callers accordingly.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoobject: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:21 +0000 (08:13 +0100)] 
object: stop depending on `the_repository`

There are a couple of functions exposed by "object.c" that implicitly
depend on `the_repository`. Remove this dependency by injecting the
repository via a parameter. Adapt callers accordingly by simply using
`the_repository`, except in cases where the subsystem is already free of
the repository. In that case, we instead pass the repository provided by
the caller's context.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agocsum-file: stop depending on `the_repository`
Patrick Steinhardt [Mon, 10 Mar 2025 07:13:20 +0000 (08:13 +0100)] 
csum-file: stop depending on `the_repository`

There are multiple sites in "csum-file.c" where we use the global
`the_repository` variable, either explicitly or implicitly by using
`the_hash_algo`.

Refactor the code to stop using `the_repository` by adapting functions
to receive required data as parameters. Adapt callsites accordingly by
either using `the_repository->hash_algo`, or by using a context-provided
hash algorithm in case the subsystem already got rid of its dependency
on `the_repository`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofetch: use ref prefix list to skip ls-refs
Jeff King [Sun, 9 Mar 2025 03:21:59 +0000 (22:21 -0500)] 
fetch: use ref prefix list to skip ls-refs

In git-fetch we have an optimization to avoid issuing an ls-refs command
to the server if we don't care about the value of any refs (e.g.,
because we are fetching exact object ids), saving a round-trip to the
server. This comes from e70a3030e7 (fetch: do not list refs if fetching
only hashes, 2018-09-27).

It uses an explicit flag "must_list_refs" to decide when we need to do
so. That was needed back then, because the list of ref-prefixes was not
always complete. If it was empty, it did not necessarily mean that we
were not interested in any refs). But that is no longer the case; an
empty list of prefixes means that we truly do not care about any refs.

And so rather than an explicit flag, we can just check whether we are
interested in any ref prefixes. This simplifies the code slightly, as
there is now a single source of truth for the decision.

It also fixes a bug in / optimizes a very unlikely case, which is:

  git fetch $remote ^foo $oid

I.e., a negative refspec combined with an exact oid fetch. This is
somewhat nonsense, in that there are no positive refspecs mentioning
refs to countermand with the negative one. But we should be able to do
this without issuing an ls-refs command (excluding "foo" from the empty
set will obviously still be the empty set).

However, the current code does not do so. The negative refspec is not
counted as a noop in un-setting the must_list_refs flag (hardly the
fault of e70a3030e7, as negative refspecs did not appear until much
later). But by using the prefix list as a source of truth, this
naturally just works; the negative refspec does not add a prefix to ask
about, and hence does not trigger the ls-refs call.

This is esoteric enough that I didn't bother adding a test. The real
value here is in the code simplification.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofetch: avoid ls-refs only to ask for HEAD symref update
Jeff King [Sun, 9 Mar 2025 03:20:16 +0000 (22:20 -0500)] 
fetch: avoid ls-refs only to ask for HEAD symref update

When we fetch from a configured remote, we may try to update the local
refs/remotes/<origin>/HEAD, and so we ask the server to advertise its
HEAD to us.

But if we aren't otherwise asking about any refs at all, then we know
this HEAD update can never happen! To consider a new value for HEAD,
the set_head() function uses guess_remote_head(). And even if it sees an
explicit symref value for HEAD, it will only report that as a match if
we also saw that remote ref advertised, and it mapped to a local
tracking ref via get_fetch_map().

In other words, a fetch like this:

  git fetch origin $exact_oid:refs/heads/foo

can never update HEAD, because we will never have fetched (nor even see
the advertisement for) the ref that HEAD points to.

Currently the command above will still call ls-refs to ask about the
HEAD, even though it is pointless. This patch teaches it to skip the
ls-refs call entirely in this case, which avoids a round-trip to the
server.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofetch: stop protecting additions to ref-prefix list
Jeff King [Sun, 9 Mar 2025 03:10:39 +0000 (22:10 -0500)] 
fetch: stop protecting additions to ref-prefix list

When using the ref-prefix feature of protocol v2, a client which sends
no prefixes at all will get the full advertisement. And so the code in
git-fetch was historically loose about setting up that list based on our
refspecs. There were cases where we needed to know about some refs, so
we just didn't add anything to the ref-prefix list.

And hence further code, like that for tag-following and updating
origin/HEAD, had to be careful about adding to an empty list. E.g., see
the bug fixed by bd52d9a058 (fetch: fix following tags when fetching
specific OID, 2025-03-07).

But the previous commit removed the last such case, and now we know an
empty ref-prefix list (at least inside git-fetch's do_fetch() function)
means that we really don't need to see any refs. So we can drop those
extra conditionals.

This simplifies the code a little. But it also means that some cases can
now use ref prefixes when they would not otherwise. As the test shows,
fetching an exact oid into a local ref can now avoid enumerating all of
the refs. The refspec itself doesn't need to know about any remote refs,
and the tag auto-following can just ask about refs/tags/.

The same is true for asking about HEAD to update the local origin/HEAD.
I didn't add a test for that yet, though, as we can optimize it even
further.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofetch: ask server to advertise HEAD for config-less fetch
Jeff King [Sun, 9 Mar 2025 03:08:47 +0000 (22:08 -0500)] 
fetch: ask server to advertise HEAD for config-less fetch

If we're not given any refspecs (either on the command line or via
config) and we have no branch merge config, then we fetch the remote
HEAD into our local FETCH_HEAD. In that case we do not send any
ref-prefix option to the server at all, and we see the full
advertisement.

But this is sub-optimal. We only care about HEAD, so we can just ask
for that, and ignore all of the other refs.

The new test demonstrates a case where we see fewer refs (in this case
only one less, but in theory we could be ignoring millions of them).

This also removes the only case where we care about seeing some refs
from the other side, but don't add anything to the ref_prefixes list.
Cleaning this up means one less maintenance burden. Before this patch,
any code which wanted to add to the list had to make sure the list was
not empty, since an empty list meant "ask for everything". Now it really
means "we are not interested in any refs".

This should let us optimize a few more cases in subsequent patches.

Note that we'll add "HEAD" to the list of prefixes, and later code for
updating "refs/remotes/<remote>/HEAD" may likewise do so. In theory this
could cause duplicates in the list, but in practice these can't both
trigger. We hit our new case only if there are no refspecs, and the
"<remote>/HEAD" feature is enabled only when we are fetching from a
remote with configured refspecs. We could be defensive with a flag, but
it didn't seem worth it to me (the absolute worse case is a useless
redundant ref-prefix line sent to the server).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agorefspec_ref_prefixes(): clean up refspec_item logic
Jeff King [Sun, 9 Mar 2025 03:07:06 +0000 (22:07 -0500)] 
refspec_ref_prefixes(): clean up refspec_item logic

The point of refspec_ref_prefixes() is to look over the set of refspecs
and set up an appropriate list of "ref-prefix" strings to send to the
server.

The logic for handling individual refspec_items has some confusing bits.
The final part of our if/else cascade checks this:

  else if (item->src && !item->exact_sha1)
prefix = item->src;

But we know that "item->exact_sha1" can never be true, because earlier
we did:

  if (item->exact_sha1 || item->negative)
continue;

This is due to 6c301adb0a (fetch: do not pass ref-prefixes for fetch by
exact SHA1, 2018-05-31), which added the continue. So it is tempting to
remove the extra exact_sha1 at the end of the cascade, leaving the one
at the top of the loop.

But I don't think that's quite right. The full cascade is:

  if (rs->fetch == REFSPEC_FETCH)
prefix = item->src;
  else if (item->dst)
prefix = item->dst;
  else if (item->src && !item->exact_sha1)
prefix = item->src;

which all comes from 6373cb598e (refspec: consolidate ref-prefix
generation logic, 2018-05-16). That first "if" is supposed to handle
fetches, where we care about the source name, since that is coming from
the server. And the rest should be for pushes, where we care about the
destination, since that's the name the server will use. And we get that
either explicitly from "dst" (for something like "foo:bar") or
implicitly from the source (a refspec like "foo" is treated as
"foo:foo").

But how should exact_sha1 interact with those? For a fetch, exact_sha1
always means we do not care about sending a name to the server (there is
no server refname at all). But pushing an exact sha1 should still care
about the destination on the server! It is only if we have to fall back
to the implicit source that we need to care if it is a real ref (though
arguably such a push does not even make sense; where would the server
store it?).

So I think that 6c301adb0a "broke" the push case by always skipping
exact_sha1 items, even though a push should only care about the
destination.

Of course this is all completely academic. We have still not implemented
a v2 push protocol, so even though we do call this function for pushes,
we'd never actually send these ref-prefix lines.

However, given the effort I spent to figure out what was going on here,
and the overlapping exact_sha1 checks, I'd like to rewrite this to
preemptively fix the bug, and hopefully make it less confusing.

This splits the "if" at the top-level into fetch vs push, and then each
handles exact_sha1 appropriately itself. The check for negative refspecs
remains outside of either (there is no protocol support for them, so we
never send them to the server, but rather use them only to reduce the
advertisement we receive).

The resulting behavior should be identical for fetches, but hopefully
sets us up better for a potential future v2 push.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot5516: beef up exact-oid ref prefixes test
Jeff King [Sun, 9 Mar 2025 03:02:47 +0000 (22:02 -0500)] 
t5516: beef up exact-oid ref prefixes test

Commit 6c301adb0a (fetch: do not pass ref-prefixes for fetch by exact
SHA1, 2018-05-31) added a test that fetching an exact oid with the v2
protocol works. Originally it failed without the code change from that
commit, because fetch failed with "no matching remote head".

That changed in 0177565148 (transport: do not list refs if possible,
2018-09-27), which made fetch more forgiving of this case.

But that now meant the test passes even without its fix! So let's also
have it check the packet listing to make sure we did not ask for the
bogus prefix (ultimately this is less important than whether the command
fails, since it's just an optimization, but we should make sure not to
regress it).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot5516: drop NEEDSWORK about v2 reachability behavior
Jeff King [Sun, 9 Mar 2025 03:02:03 +0000 (22:02 -0500)] 
t5516: drop NEEDSWORK about v2 reachability behavior

When this test was added in 6c301adb0a (fetch: do not pass ref-prefixes
for fetch by exact SHA1, 2018-05-31), there was still some uncertainty
about the v2 protocol's looser behavior with serving objects that are
not directly pointed at by a ref.

At this point that behavior is well established, and I do not think we
would ever change v2 to match the v0 behavior (and if we did,
remembering to update this test is the least of our concerns).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot5516: prefer "oid" to "sha1" in some test titles
Jeff King [Sun, 9 Mar 2025 03:01:40 +0000 (22:01 -0500)] 
t5516: prefer "oid" to "sha1" in some test titles

These old tests refer to object ids as "sha1". These days we prefer
the more algorithm-agnostic "oid".

There are a few more tests that mention sha1 in the title and also use
it in variables throughout the test. I've left them for now, as changing
them is more involved (and they're linked to the allowTipSHA1InWant
config, which as a v0-only thing actually is always sha1).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agot5702: fix typo in test name
Jeff King [Sun, 9 Mar 2025 03:01:23 +0000 (22:01 -0500)] 
t5702: fix typo in test name

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agodoc: add a blank line around block delimiters
Jean-Noël Avila [Sun, 9 Mar 2025 19:45:11 +0000 (19:45 +0000)] 
doc: add a blank line around block delimiters

The documentation is using the historical mode for titles, which is a
setext-style (i.e., two-line) section title.

The issue with this mode is that starting block delimiters (e.g.,
`----`) can be confused with a section title when they are exactly the
same length as the preceding line. In the original documentation, this
is taken care of for English by the writer, but it is not the case for
translations where these delimiters are hidden. A translator can
generate a line that is exactly the same length as the following block
delimiter, which leads to this line being considered as a title.

To safeguard against this issue, add a blank line before and after
block delimiters where block is at root level, else add a "+" line
before block delimiters to link it to the preceding paragraph.

Signed-off-by: Jean-Noël Avila <jn.avila@free.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agogit-clone doc: fix indentation
Martin Ågren [Mon, 10 Mar 2025 11:07:56 +0000 (12:07 +0100)] 
git-clone doc: fix indentation

Commit bc26f7690a (clone: make it possible to specify --tags,
2025-02-06) added a new paragraph in the middle of this list item. By
adding an empty line rather than using a list continuation, we broke the
list continuation, with the new paragraph ending up funnily indented.

Restore the chain of list continuations.

Signed-off-by: Martin Ågren <martin.agren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agol10n: sv.po: Fix Swedish typos
Tuomas Ahola [Sat, 8 Mar 2025 20:45:10 +0000 (22:45 +0200)] 
l10n: sv.po: Fix Swedish typos

Signed-off-by: Tuomas Ahola <taahol@utu.fi>
5 months agol10n: sv.po: Update Swedish translation
Peter Krefting [Mon, 10 Mar 2025 16:48:34 +0000 (17:48 +0100)] 
l10n: sv.po: Update Swedish translation

- Update for 2.49.0.
- Fix numerous typos found by spelling checker.
- Fix more straight quotes.
- Harmonize translation of "blob" (to "blob", not "blobb").
- Harmonize translation of "reflog" (to "referenslogg").

Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
5 months agoGit 2.49-rc2 v2.49.0-rc2
Junio C Hamano [Mon, 10 Mar 2025 15:47:08 +0000 (08:47 -0700)] 
Git 2.49-rc2

Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoMerge branch 'tb/fetch-follow-tags-fix'
Junio C Hamano [Mon, 10 Mar 2025 15:45:58 +0000 (08:45 -0700)] 
Merge branch 'tb/fetch-follow-tags-fix'

* tb/fetch-follow-tags-fix:
  fetch: fix following tags when fetching specific OID

5 months agobuiltin/checkout-index: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:07 +0000 (05:05 +0530)] 
builtin/checkout-index: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/checkout-index.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_checkout_index()` function with `repo`
set to NULL and then early in the function, `show_usage_with_options_if_asked()`
call will give the options help and exit.

Pass an instance of "struct index_state" available in the calling
context to both `checkout_all()` and `checkout_file()` to remove their
dependency on the global `the_repository` variable.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/for-each-ref: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:06 +0000 (05:05 +0530)] 
builtin/for-each-ref: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/for-each-ref.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_for_each_ref()` function with `repo`
set to NULL and then early in the function, `parse_options()` call will
give the options help and exit.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/ls-files: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:05 +0000 (05:05 +0530)] 
builtin/ls-files: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/ls-files.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_ls_files()` function with `repo` set
to NULL and then early in the function, `show_usage_with_options_if_asked()`
call will give the options help and exit.

Pass the repository available in the calling context to both
`expand_objectsize()` and `show_ru_info()` to remove their
dependency on the global `the_repository` variable.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/pack-refs: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:04 +0000 (05:05 +0530)] 
builtin/pack-refs: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/pack-refs.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_pack_refs()` function with `repo` set
to NULL and then early in the function, `parse_options()` call will give
the options help and exit.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/send-pack: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:03 +0000 (05:05 +0530)] 
builtin/send-pack: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/send-pack.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_send_pack()` function with `repo` set
to NULL and then early in the function, `parse_options()` call will give
the options help and exit.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/verify-commit: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:02 +0000 (05:05 +0530)] 
builtin/verify-commit: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/verify-commit.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_verify_commit()` function with `repo`
set to NULL and then early in the function, `parse_options()` call will
give the options help and exit.

Pass the repository available in the calling context to `verify_commit()`
to remove it's dependency on the global `the_repository` variable.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agobuiltin/verify-tag: stop using `the_repository`
Usman Akinyemi [Fri, 7 Mar 2025 23:35:01 +0000 (05:05 +0530)] 
builtin/verify-tag: stop using `the_repository`

Remove the_repository global variable in favor of the repository
argument that gets passed in "builtin/verify-tag.c".

When `-h` is passed to the command outside a Git repository, the
`run_builtin()` will call the `cmd_verify_tag()` function with `repo` set
to NULL and then early in the function, `parse_options()` call will give
the options help and exit.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoconfig: teach repo_config to allow `repo` to be NULL
Usman Akinyemi [Fri, 7 Mar 2025 23:35:00 +0000 (05:05 +0530)] 
config: teach repo_config to allow `repo` to be NULL

The `repo` value can be NULL if a builtin command is run outside
any repository. The current implementation of `repo_config()` will
fail if `repo` is NULL.

If the `repo` is NULL the `repo_config()` can ignore the repository
configuration but it should read the other configuration sources like
the system-side configuration instead of failing.

Teach the `repo_config()` to allow `repo` to be NULL by calling the
`read_very_early_config()` which read config but only enumerate system
and global settings.

This will be useful in the following commits.

Suggested-by: Junio C Hamano <gitster@pobox.com>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agofetch: fix following tags when fetching specific OID
Taylor Blau [Fri, 7 Mar 2025 23:27:03 +0000 (18:27 -0500)] 
fetch: fix following tags when fetching specific OID

In 3f763ddf28 (fetch: set remote/HEAD if it does not exist, 2024-11-22),
unconditionally adds "HEAD" to the list of ref prefixes we send to the
server.

This breaks a core assumption that the list of prefixes we send to the
server is complete. We must either send all prefixes we care about, or
none at all (in the latter case the server then advertises everything).

The tag following code is careful to only add "refs/tags/" to the list
of prefixes if there are already entries in the prefix list. But because
the new code from 3f763ddf28 runs after the tag code, and because it
unconditionally adds to the prefix list, we may end up with a prefix
list that _should_ have "refs/tags/" in it, but doesn't.

When that is the case, the server does not advertise any tags, and our
auto-following breaks because we never learned about any tags in the
first place.

Fix this by only adding "HEAD" to the ref prefixes when we know that we
are already limiting the advertisement. In either case we'll learn about
HEAD (either through the limited advertisement, or implicitly through a
full advertisement).

Reported-by: Igor Todorovski <itodorov@ca.ibm.com>
Co-authored-by: Jeff King <peff@peff.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agohelp: print zlib-ng version number
Toon Claes [Fri, 7 Mar 2025 14:18:08 +0000 (15:18 +0100)] 
help: print zlib-ng version number

When building against zlib-ng, the header file `zlib.h` is not included,
but `zlib-ng.h` is included instead. It's `zlib.h` that defines
`ZLIB_VERSION` and that macro is used to print out zlib version in
`git-version(1)` with `--build-options`. But when it's not defined, no
version is printed.

`zlib-ng.h` defines another macro: `ZLIBNG_VERSION`. Use that macro to
print the zlib-ng version in `git version --build-options` when it's
set. Otherwise fallback to `ZLIB_VERSION`.

Signed-off-by: Toon Claes <toon@iotcl.com>
Helped-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agohelp: include git-zlib.h to print zlib version
Toon Claes [Fri, 7 Mar 2025 14:18:07 +0000 (15:18 +0100)] 
help: include git-zlib.h to print zlib version

In 41f1a8435a (git-compat-util: move include of "compat/zlib.h" into
"git-zlib.h", 2025-01-28) some code was refactored to enable easier
linking against zlib-ng.

This removed `zlib.h` being indirectly included in `help.c`. As this
file uses `ZLIB_VERSION` to print the version number of zlib when
running git-version(1) with `--build-options`, this resulted in a
regression.

Include `git-zlib.h` directly into `help.c` to print zlib version
information. This brings back the zlib version in the output of
`git version --build-options`.

Signed-off-by: Toon Claes <toon@iotcl.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
5 months agoMerge branch 'js/win-2.49-build-fixes'
Junio C Hamano [Thu, 6 Mar 2025 22:06:31 +0000 (14:06 -0800)] 
Merge branch 'js/win-2.49-build-fixes'

Hotfix to help building Git-for-Windows.

* js/win-2.49-build-fixes:
  cmake: generalize the handling of the `CLAR_TEST_OBJS` list
  meson: fix sorting
  ident: stop assuming that `gw_gecos` is writable

5 months agoMerge branch 'pw/repo-layout-doc-update'
Junio C Hamano [Thu, 6 Mar 2025 22:06:31 +0000 (14:06 -0800)] 
Merge branch 'pw/repo-layout-doc-update'

Some future breaking changes would remove certain parts of the
default repository, which were still described even when the
documents were built for the future with WITH_BREAKING_CHANGES.

* pw/repo-layout-doc-update:
  docs: fix repository-layout when building with breaking changes