Commit Graph

76571 Commits (f7ca9bbea6de24ff375bfba38c536b0a89474900)

Author SHA1 Message Date
Elijah Newren f7ca9bbea6 sequencer: switch non-recursive merges over to ort
The do_recursive_merge() function, which is somewhat misleadingly named
since its purpose in life is to do a *non*-recursive merge, had code to
allow either using the recursive or ort backends.  The default has been
ort for a very long time, let's just remove the code path for allowing
the recursive backend to be selected.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-08 13:59:12 -07:00
Elijah Newren 2e806d8464 merge-ort: enable diff-algorithms other than histogram
The ort merge strategy has always used the histogram diff algorithm.
The recursive merge strategy, in contrast, defaults to the myers
diff algorithm, while allowing it to be changed.

Change the ort merge strategy to allow different diff algorithms, by
removing the hard coded value in merge_start() and instead just making
it a default in init_merge_options().  Technically, this also changes
the default diff algorithm for the recursive backend too, but we're
going to remove the final callers of the recursive backend in the next
two commits.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-08 13:59:12 -07:00
Elijah Newren 77c029493a builtin/merge-recursive: switch to using merge_ort_generic()
Switch from merge-recursive to merge-ort.  Adjust the following
testcases due to the switch:

* t6430: most of the test differences here were due to improved D/F
  conflict handling explained in more detail in ef52778708 (merge
  tests: expect improved directory/file conflict handling in ort,
  2020-10-26).  These changes weren't made to this test back in that
  commit simply because I had been looking at `git merge` rather than
  `git merge-recursive`.  The final test in this testsuite, though, was
  expunged because it was looking for specific output, and the calls to
  output_commit_title() were discarded from merge_ort_internal() in its
  adaptation from merge_recursive_internal(); see 8119214f4e
  (merge-ort: implement merge_incore_recursive(), 2020-12-16).

* t6434: This test is built entirely around rename/delete conflicts,
  which had a suboptimal handling under merge-recursive.  As explained
  in more detail in commits 1f3c9ba707 ("t6425: be more flexible with
  rename/delete conflict messages", 2020-08-10) and 727c75b23f ("t6404,
  t6423: expect improved rename/delete handling in ort backend",
  2020-10-26), rename/delete conflicts should each have two entries in
  the index rather than just one.  Adjust the expectations for all the
  tests in this testcase to see the two entries per rename/delete
  conflict.

* t6424: merge-recursive had a special check-if-toplevel-trees-match
  check that it ran at the beginning on both the merge-base and the
  other side being merged in.  In such a case, it exited early and
  printed an "Already up to date." message.  merge-ort got rid of
  this, and instead checks the merge base tree matching the other
  side throughout the tree instead of just at the toplevel, allowing
  it to avoid recursing into various subtrees.  As part of that, it
  got rid of the specialty toplevel message.  That message hasn't
  been missed for years from `git merge`, so I don't think it is
  necessary to keep it just for `git merge-recursive`, especially
  since the latter is rarely used.  (git itself only references it
  in the testsuite, whereas it used to power one of the three
  rebase backends that existed once upon a time.)

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-08 13:59:11 -07:00
Elijah Newren b5dff2bd61 checkout: replace merge_trees() with merge_ort_nonrecursive()
Replace the use of merge_trees() from merge-recursive.[ch] with the
merge-ort equivalent.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-04-08 13:59:11 -07:00
Junio C Hamano 5b97a56fa0 The second batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-29 16:39:11 +09:00
Junio C Hamano 30eadc9d59 Merge branch 'hj/doc-rev-list-ancestry-fix'
Doc update.

* hj/doc-rev-list-ancestry-fix:
  doc: add missing commit C to the graph for --ancestry-path=H D..M
2025-03-29 16:39:11 +09:00
Junio C Hamano 81d8747cea Merge branch 'es/meson-building-docs-requires-perl'
Build update.

* es/meson-building-docs-requires-perl:
  meson: fix perl detection when docs are enabled, but perl bindings aren't
2025-03-29 16:39:11 +09:00
Junio C Hamano ff926a6d1b Merge branch 'en/random-cleanups'
Miscellaneous code clean-ups.

* en/random-cleanups:
  merge-ort: remove extraneous word in comment
  merge-ort: fix accidental strset<->strintmap
  t7615: be more explicit about diff algorithm used
  t6423: fix a comment that accidentally reversed two commits
  stash: remove merge-recursive.h include
2025-03-29 16:39:10 +09:00
Junio C Hamano 6767149eca Merge branch 'rs/xdiff-context-length-fix'
The xdiff code on 32-bit platform misbehaved when an insanely large
context size is given, which has been corrected.

* rs/xdiff-context-length-fix:
  xdiff: avoid arithmetic overflow in xdl_get_hunk()
2025-03-29 16:39:10 +09:00
Junio C Hamano f76fe4ab06 Merge branch 'jk/use-wunreachable-code-for-devs'
Enable -Wunreachable-code for developer builds.

* jk/use-wunreachable-code-for-devs:
  config.mak.dev: enable -Wunreachable-code
  git-compat-util: add NOT_CONSTANT macro and use it in atfork_prepare()
  run-command: use errno to check for sigfillset() error
2025-03-29 16:39:10 +09:00
Junio C Hamano b9b404fa1c Merge branch 'en/diff-rename-follow-fix'
A corner-case bug in "git log --follow -B" has been fixed.

* en/diff-rename-follow-fix:
  diffcore-rename: fix BUG when break detection and --follow used together
2025-03-29 16:39:09 +09:00
Junio C Hamano 27fe152e88 Merge branch 'tb/multi-cruft-pack-refresh-fix'
Certain "cruft" objects would have never been refreshed when there
are multiple cruft packs in the repository, which has been
corrected.

* tb/multi-cruft-pack-refresh-fix:
  builtin/pack-objects.c: freshen objects from existing cruft packs
2025-03-29 16:39:09 +09:00
Junio C Hamano f3db666cca Merge branch 'am/dir-dedup-decl-of-repository'
Code cleanup.

* am/dir-dedup-decl-of-repository:
  dir.h: remove duplicate forward declaration of struct repository
2025-03-29 16:39:09 +09:00
Junio C Hamano 64aef9217f Merge branch 'ps/meson-with-breaking-changes'
Update meson based build procedure for breaking changes support.

* ps/meson-with-breaking-changes:
  meson: don't install git-pack-redundant(1) docs with breaking changes
  meson: don't compile git-pack-redundant(1) with breaking changes
  meson: define WITH_BREAKING_CHANGES when enabling breaking changes
2025-03-29 16:39:08 +09:00
Junio C Hamano 650b2e2fdb Merge branch 'jk/fetch-ref-prefix-cleanup'
In protocol v2 where the refs advertisement is constrained, we try
to tell the server side not to limit the advertisement when there
is no specific need to, which has been the source of confusion and
recent bugs.  Revamp the logic to simplify.

* jk/fetch-ref-prefix-cleanup:
  fetch: use ref prefix list to skip ls-refs
  fetch: avoid ls-refs only to ask for HEAD symref update
  fetch: stop protecting additions to ref-prefix list
  fetch: ask server to advertise HEAD for config-less fetch
  refspec_ref_prefixes(): clean up refspec_item logic
  t5516: beef up exact-oid ref prefixes test
  t5516: drop NEEDSWORK about v2 reachability behavior
  t5516: prefer "oid" to "sha1" in some test titles
  t5702: fix typo in test name
2025-03-29 16:39:08 +09:00
Junio C Hamano ef0d6b7151 Merge branch 'ab/decorate-code-cleanup'
Code clean-up.

* ab/decorate-code-cleanup:
  decorate: fix sign comparison warnings
2025-03-29 16:39:08 +09:00
Junio C Hamano eb7923be1f Merge branch 'en/merge-ort-prepare-to-remove-recursive'
First step of deprecating and removing merge-recursive.

* en/merge-ort-prepare-to-remove-recursive:
  am: switch from merge_recursive_generic() to merge_ort_generic()
  merge-ort: fix merge.directoryRenames=false
  t3650: document bug when directory renames are turned off
  merge-ort: support having merge verbosity be set to 0
  merge-ort: allow rename detection to be disabled
  merge-ort: add new merge_ort_generic() function
2025-03-29 16:39:07 +09:00
Junio C Hamano 8d6413a1be Merge branch 'ps/refname-avail-check-optim'
The code paths to check whether a refname X is available (by seeing
if another ref X/Y exists, etc.) have been optimized.

* ps/refname-avail-check-optim:
  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()`
2025-03-29 16:39:07 +09:00
Junio C Hamano 01d17c0530 Merge branch 'cc/signed-fast-export-import'
"git fast-export | git fast-import" learns to deal with commit and
tag objects with embedded signatures a bit better.

* cc/signed-fast-export-import:
  fast-export, fast-import: add support for signed-commits
  fast-export: do not modify memory from get_commit_buffer
  git-fast-export.adoc: clarify why 'verbatim' may not be a good idea
  fast-export: rename --signed-tags='warn' to 'warn-verbatim'
  fast-export: fix missing whitespace after switch
  git-fast-import.adoc: add missing LF in the BNF
2025-03-29 16:39:07 +09:00
Junio C Hamano 66b90d9bad Start 2.50 cycle (batch #1)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-26 16:26:11 +09:00
Junio C Hamano 87a8e533e3 Merge branch 'ja/doc-block-delimiter-markup-fix'
Doc markup updates.

* ja/doc-block-delimiter-markup-fix:
  doc: add a blank line around block delimiters
2025-03-26 16:26:11 +09:00
Junio C Hamano 52241c96c7 Merge branch 'en/merge-process-renames-crash-fix'
The merge-recursive and merge-ort machinery crashed in corner cases
when certain renames are involved.

* en/merge-process-renames-crash-fix:
  merge-ort: fix slightly overzealous assertion for rename-to-self
  t6423: add a testcase causing a failed assertion in process_renames
2025-03-26 16:26:11 +09:00
Junio C Hamano 1a764cdbdc Merge branch 'ua/some-builtins-wo-the-repository'
A handful of built-in command implementations have been rewritten
to use the repository instance supplied by git.c:run_builtin(), its
caller.

* ua/some-builtins-wo-the-repository:
  builtin/checkout-index: stop using `the_repository`
  builtin/for-each-ref: stop using `the_repository`
  builtin/ls-files: stop using `the_repository`
  builtin/pack-refs: stop using `the_repository`
  builtin/send-pack: stop using `the_repository`
  builtin/verify-commit: stop using `the_repository`
  builtin/verify-tag: stop using `the_repository`
  config: teach repo_config to allow `repo` to be NULL
2025-03-26 16:26:10 +09:00
Junio C Hamano def5e32bc5 Merge branch 'tb/refs-exclude-fixes'
The refname exclusion logic in the packed-ref backend has been
broken for some time, which confused upload-pack to advertise
different set of refs.  This has been corrected.

* tb/refs-exclude-fixes:
  refs.c: stop matching non-directory prefixes in exclude patterns
  refs.c: remove empty '--exclude' patterns
2025-03-26 16:26:10 +09:00
Junio C Hamano de35b7b3ff Merge branch 'sj/ref-consistency-checks-more'
"git fsck" becomes more careful when checking the refs.

* sj/ref-consistency-checks-more:
  builtin/fsck: add `git refs verify` child process
  packed-backend: check whether the "packed-refs" is sorted
  packed-backend: add "packed-refs" entry consistency check
  packed-backend: check whether the refname contains NUL characters
  packed-backend: add "packed-refs" header consistency check
  packed-backend: check if header starts with "# pack-refs with: "
  packed-backend: check whether the "packed-refs" is regular file
  builtin/refs: get worktrees without reading head information
  t0602: use subshell to ensure working directory unchanged
2025-03-26 16:26:10 +09:00
Junio C Hamano f50df872a4 Merge branch 'jt/diff-pairs'
A post-processing filter for "diff --raw" output has been
introduced.

* jt/diff-pairs:
  builtin/diff-pairs: allow explicit diff queue flush
  builtin: introduce diff-pairs command
  diff: add option to skip resolving diff statuses
  diff: return diff_filepair from diff queue helpers
2025-03-26 16:26:09 +09:00
Elijah Newren 947e219fb6 am: switch from merge_recursive_generic() to merge_ort_generic()
Switch from merge-recursive to merge-ort.  Adjust the following
testcases due to the switch:

* t4151: This test left an untracked file in the way of the merge.
  merge-recursive could only sometimes tell when untracked files were
  in the way, and by the time it discovers others, it has already made
  too many changes to back out of the merge.  So, instead of writing the
  results to e.g. 'file1' it would instead write them to
  'file1~branch1'.  This is confusing for users, because they might not
  notice 'file1~branch1' and accidentally add and commit 'file1'.
  In contrast, merge-ort correctly notices the file in the way before
  making any changes and aborts.  Since this test didn't care about the
  file in the way, just remove it before calling git-am.

* t4255: Usage of merge-ort allows us to change two known failures into
  successes.

* t6427: As noted a few commits ago, the choice of conflict label for
  diff3 markers for the ancestor commit was previously handled by
  merge-recursive.c rather than by callers.  Since that has now changed,
  `git am` needs to specify that label.  Although the previous conflict
  label ("constructed merge base") was already fairly somewhat slanted
  towards `git am`, let's use wording more along the lines of the
  related command-line flag from `git apply` and function involved to
  tie it more closely to `git am`.

Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:49:08 -07:00
Elijah Newren a16e8efe5c merge-ort: fix merge.directoryRenames=false
There are two issues here.

First, when merge.directoryRenames is set to false, there are a few code
paths that should be turned off.  I missed one; collect_renames() was
still doing some directory rename detection logic unconditionally.  It
ended up not having much effect because
get_provisional_directory_renames() was skipped earlier and not setting
up renames->dir_renames, but the code should still be skipped.

Second, the larger issue is that sometimes we get a cached_pair rename
from a previous commit being replayed mapping A->B, but in a subsequent
commit but collect_merge_info() doesn't even recurse into the
directory containing B because there are no source pairings for that
rename that are relevant; we can merge that commit fine without knowing
the rename.  But since the cached renames are added to the normal
renames, when we go to process it and find that B is not part of
opt->priv->paths, we hit the assertion error
  process_renames: Assertion `newinfo && ~newinfo->merged.clean` failed.
I think we could fix this at the beginning of detect_regular_renames() by
pruning from cached_pairs any entry whose destination isn't in
opt->priv->paths, but it's suboptimal in that we'd kind of like the
cached_pair to be restored afterwards so that it can help the subsequent
commit, but more importantly since it sits at the intersection of
the caching renames optimization and the relevant renames optimization,
and the trivial directory resolution optimization, and I don't currently
have Documentation/technical/remembering-renames.txt fully paged in, I'm
not sure if that's a full solution or a bandaid for the current
testcase.  However, since the remembering renames optimization was the
weakest of the set, and the optimization is far less important when
directory rename detection is off (as that implies far fewer potential
renames), let's just use a bigger hammer to ensure this special case is
fixed: turn off the rename caching.  We do the same thing already when
we encounter rename/rename(1to1) cases (as per `git grep -3
disabling.the.optimization`, though it uses a slightly different
triggering mechanism since it's trying to affect the next time that
merge_check_renames_reusable() is called), and I think it makes sense
to do the same here.

Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:49:04 -07:00
Johannes Schindelin a9185cc89b t3650: document bug when directory renames are turned off
There is a bug in the way renames are cached that rears its head when
`merge.directoryRenames` is set to false; it results in the following
message:

    merge-ort.c:3002: process_renames: Assertion `newinfo && !newinfo->merged.clean' failed.
    Aborted

It is quite a curious bug: the same test case will succeed, without any
assertion, if instead run with `merge.directoryRenames=true`.

Further, the assertion does not manifest while replaying the first
commit, it manifests while replaying the _second_ commit of the commit
range. But it does _not_ manifest when the second commit is replayed
individually.

This would indicate that there is an incomplete rename cache left-over
from the first replayed commit which is being reused for the second
commit, and if directory rename detection is enabled, the missing paths
are somehow regenerated.

Incidentally, the same bug can by triggered by modifying t6429 to switch
from merge.directoryRenames=true to merge.directoryRenames=false.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
[en: tweaked the commit message slightly, including adjusting the
 line number of the assertion to the latest version, and the much
 later discovery that a simple t6429 tweak would also display the
 issue.]
Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:48:57 -07:00
Elijah Newren 3965976edb merge-ort: support having merge verbosity be set to 0
Various callers such as am & checkout set the merge verbosity to 0 to
avoid having conflict messages printed.  While this could be achieved by
avoiding the wrappers from merge-ort-wrappers and instead passing 0 for
display_update_msgs to merge_switch_to_result(), for simplicity of
converting callers simply allow them to also achieve this with the
merge-ort-wrappers by setting verbosity to 0.

Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:48:51 -07:00
Elijah Newren a707d4f941 merge-ort: allow rename detection to be disabled
When merge-ort was written, I did not at first allow rename detection to
be disabled, because I suspected that most folks disabling rename
detection were doing so solely for performance reasons.  Since I put a
lot of working into providing dramatic speedups for rename detection
performance as used by the merge machinery, I wanted to know if there
were still real world repositories where rename detection was
problematic from a performance perspective.  We have had years now to
collect such information, and while we never received one, waiting
longer with the option disabled seems unlikely to help surface such
issues at this point.  Also, there has been at least one request to
allow rename detection to be disabled for behavioral rather than
performance reasons (see the thread including
https://lore.kernel.org/git/CABPp-BG-Nx6SCxxkGXn_Fwd2wseifMFND8eddvWxiZVZk0zRaA@mail.gmail.com/
), so let's start heeding the config and command line settings.

Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:48:47 -07:00
Elijah Newren 4e5d9de96c merge-ort: add new merge_ort_generic() function
merge-recursive.[ch] have three entry points:
  * merge_trees()
  * merge_recursive()
  * merge_recursive_generic()
merge-ort*.[ch] only has equivalents for the first two.  Add an
equivalent for the final entry point, so we can switch callers to
use it and remove merge-recursive.[ch].

While porting it over, finally fix the issue with the label for the
ancestor (used when merge.conflictStyle=diff3 as a conflict label).
merge-recursive.c has traditionally not allowed callers to set that
label, but I have found that problematic for years.

(Side note: This function was initially part of the merge-ort rewrite,
but reviewers questioned the ancestor label funnyness which I was
never really happy with anyway.  It resulted in me jettisoning it and
hoping at the time that I would eventually be able to force the existing
callers to use some other API.  That worked with `git stash`, as per
874cf2a604 (stash: apply stash using 'merge_ort_nonrecursive()',
2022-05-10), but this API is the most reasonable one for `git am` and
`git merge-recursive`, if we can just allow them some freedom over the
ancestor label.)

The merge_recursive_generic() function did not know whether it was being
invoked by `git stash`, `git merge-recursive`, or `git am`, and the
choice of meaningful ancestor label, when there is a unique ancestor,
varies for these different callers:

  * git am: ancestor is a constructed "fake ancestor" that user knows
            nothing about and has no access to.  (And is different than
            the normal thing we mean by a "virtual merge base" which is
            the merging of merge bases.)
  * git merge-recursive: ancestor might be a tree, but at least it
                         was one specified by the user (if they invoked
                         merge-recursive directly)
  * git stash: ancestor was the commit serving as the stash base

Thus, using a label like "constructed merge base" (as
merge_recursive_generic() does) presupposes that `git am` is the only
caller; it is incorrect for other callers.  This label has thrown me off
more than once.  Allow the caller to override when there is a unique
merge base.

Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:48:30 -07:00
Han Jiang 5af21c9acb doc: add missing commit C to the graph for --ancestry-path=H D..M
The graph for `--ancestry-path=H D..M` should contain commit C.

Signed-off-by: Han Jiang <jhcarl0814@gmail.com>
Acked-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-18 09:05:42 -07:00
Jeff King 16f5d967e2 config.mak.dev: enable -Wunreachable-code
Having the compiler point out unreachable code can help avoid bugs, like
the one discussed in:

  https://lore.kernel.org/git/20250307195057.GA3675279@coredump.intra.peff.net/

In that case it was found by Coverity, but finding it earlier saves
everybody time and effort.

We can use -Wunreachable-code to get some help from the compiler here.
Interestingly, this is a noop in gcc. It was a real warning up until gcc
4.x, when it was removed for being too flaky, but they left the
command-line option to avoid breaking users. See:

  https://stackoverflow.com/questions/17249934/why-does-gcc-not-warn-for-unreachable-code

However, clang does implement this option, and it finds the case
mentioned above (and no other cases within the code base). And since we
run clang in several of our CI jobs, that's enough to get an early
warning of breakage.

We could enable it only for clang, but since gcc is happy to ignore it,
it's simpler to just turn it on for all developer builds.

Signed-off-by: Jeff King <peff@peff.net>
[jc: squashed meson.build change sent by Patrick]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 17:31:28 -07:00
Junio C Hamano 82e79c6364 git-compat-util: add NOT_CONSTANT macro and use it in atfork_prepare()
Our hope is that the number of code paths that falsely trigger
warnings with the -Wunreachable-code compilation option are small,
and they can be worked around case-by-case basis, like we just did
in the previous commit.  If we need such a workaround a bit more
often, however, we may benefit from a more generic and descriptive
facility that helps document the cases we need such workarounds.

    Side note: if we need the workaround all over the place, it
    simply means -Wunreachable-code is not a good tool for us to
    save engineering effort to catch mistakes.  We are still
    exploring if it helps us, so let's assume that it is not the
    case.

Introduce NOT_CONSTANT() macro, with which, the developer can tell
the compiler:

    Do not optimize this expression out, because, despite whatever
    you are told by the system headers, this expression should *not*
    be treated as a constant.

and use it as a replacement for the workaround we used that was
somewhat specific to the sigfillset case.  If the compiler already
knows that the call to sigfillset() cannot fail on a particular
platform it is compiling for and declares that the if() condition
would not hold, it is plausible that the next version of the
compiler may learn that sigfillset() that never fails would not
touch errno and decide that in this sequence:

	errno = 0;
	sigfillset(&all)
	if (errno)
		die_errno("sigfillset");

the if() statement will never trigger.  Marking that the value
returned by sigfillset() cannot be a constant would document our
intention better and would not break with such a new version of
compiler that is even more "clever".  With the marco, the above
sequence can be rewritten:

	if (NOT_CONSTANT(sigfillset(&all)))
		die_errno("sigfillset");

which looks almost like other innocuous annotations we have,
e.g. UNUSED.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 17:30:49 -07:00
Jeff King 7e1bec1edd run-command: use errno to check for sigfillset() error
Since enabling -Wunreachable-code, builds with clang on macOS now fail,
complaining that the die_errno() call in:

  if (sigfillset(&all))
	die_errno("sigfillset");

is unreachable. On that platform the manpage documents that sigfillset()
always returns success, and presumably the implementation is a macro or
inline function that does so in a way that is transparent to the
compiler.

But we should continue to check on other platforms, since POSIX says it
may return an error.

We could solve this with a compile-time knob to split the two cases
(assuming success on macOS and checking for the error elsewhere). But we
can also work around it more directly by relying on errno to check the
outcome (since POSIX dictates that errno will be set on error). And that
works around the compiler's cleverness, since it doesn't know the
semantics of errno (though I suppose if sigfillset() is simple enough,
it could perhaps realize that no writes to errno are possible; however
this does seem to work in practice).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 16:54:41 -07:00
Elijah Newren a18c18b470 merge-ort: remove extraneous word in comment
"is was" -> "was"

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:39:04 -07:00
Elijah Newren 5692a46b09 merge-ort: fix accidental strset<->strintmap
Both strset_for_each_entry and strintmap_for_each_entry are macros that
evaluate to the same thing, so they are technically interchangeable.
However, the intent is that we use the one matching the variable type we
are passing.  Unfortunately, I somehow mistakenly got one of these wrong
in 7bee6c1004 (merge-ort: avoid recursing into directories when we
don't need to, 2021-07-16) -- possibly related to the fact that
relevant_sources was initially a strset and later refactored into a
strintmap.  Correct which macro we use.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:39:03 -07:00
Elijah Newren a373f93370 t7615: be more explicit about diff algorithm used
t7615 is entirely about testing the differences about different
diff algorithms, but it doesn't specify any diff algorithm when it
is testing myers.  Given that we have discussed potentially switching
defaults (https://lore.kernel.org/git/xmqqed873vgn.fsf@gitster.g/), it
makes sense in tests that are about different diff algorithms to be
explicitly about which one is intended to be used in each test.  Add
that specificity.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:39:03 -07:00
Elijah Newren 9c69ad275e t6423: fix a comment that accidentally reversed two commits
The comment describing testcase 13b of t6423 somehow mixed up commits
A and B in one paragraph.  Fix the references.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:39:03 -07:00
Elijah Newren e40eefba02 stash: remove merge-recursive.h include
stash was modified to use merge_ort_nonrecursive() instead of
merge_recursive_generic() back in commit 874cf2a604 (stash: apply
stash using 'merge_ort_nonrecursive()', 2022-05-10).  That makes the
inclusion of merge-recursive.h unnecessary.  In preparation for the
removal of merge-recursive.h, remove the unnecessary include.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:39:03 -07:00
Eli Schwartz 7c8cd9c158 meson: fix perl detection when docs are enabled, but perl bindings aren't
The `perl` variable in meson.build is assigned to a program lookup,
which may have the value "not-found object" if configuring with
`-Dperl=disabled`.

There is already a list of other cases where we do need a perl command,
even when not building perl bindings. Building documentation should be
one of those cases, but was missing from the list. Add it.

Fixes:

```
$ meson setup builddir/ -Ddocs=man -Dperl=disabled -Dtests=false
[...]
Documentation/meson.build:308:22: ERROR: Tried to use not-found external program in "command"
```

Bug: https://bugs.gentoo.org/949247
Signed-off-by: Eli Schwartz <eschwartz@gentoo.org>
Acked-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-17 15:25:42 -07:00
Elijah Newren 554051d691 diffcore-rename: fix BUG when break detection and --follow used together
Prior to commit 9db2ac5616 (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>
2025-03-14 18:43:28 -07:00
René Scharfe d39e28e68c 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>
2025-03-14 16:19:40 -07:00
Junio C Hamano 683c54c999 Git 2.49
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-03-14 09:19:41 -07:00
Taylor Blau 08f612ba70 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>
2025-03-13 11:48:04 -07:00
Junio C Hamano c9d3534de3 l10n-2.49.0-rnd1
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE37vMEzKDqYvVxs51k24VDd1FMtUFAmfS5hkACgkQk24VDd1F
 MtWFFA//YocbgRwqWIIBvRX1GC+8qRxoAGEsANWFThJoIy9Lr1EOPuzaxDI9t8As
 1sSSUJk7HFQJ5Sh9pohf5Ej5iZbZVRdxjyRS9tdmf87wpkInMfntYHg1yw78XkoO
 6g2n/lXCdDvezYNE0nWyUE8wJwNax9NFo+7DRLVrnpS09d/KwDKc4IXW1ikHZbb1
 KCjUcVk1w8YZpSKsE9s2i61A7k5LGW8uH5dW0S6vwhBCyZbPGFuD3vYnr9g119de
 KkjRf5VIItcUpKeRdAvaj4FvXO7101xqmsUOCkKZVSh6iw7HHwDHii8L3VOANWul
 ROH6nc/YZGYDHCmwSg2WWLPzv7IwuAqbgD5LN3j18p+ur2JfTVcTGYHHQfxUlWq1
 5VLatGp8Bte3rIJyCJRu+1r3dm4PLOGU6dlH3J7pNDqB0lgwgV55Mu+FC3+rDIyg
 osKQTYiMXGFAIqRT9ZN641wy5hx8mgJtOu7POIGCr5gdEZQsoYu1aNtfIOKjTBoI
 TSd8GQRN6NhC6KqYHjTcFSllm1EdrSjdaqzyWIj52uCuYEvi74pd8x6LR+h7fUKN
 dNctoxED99wv7mrhjoG4nwb8+LL90rHPzWMGT1xBY7B5sRzeStoSXfMzvMEL0LAV
 iDO3uj19ShyQlsXWGsNtfYe52oeU6HQtkyhpiMYcqRRRCbn6AN0=
 =uSnf
 -----END PGP SIGNATURE-----

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
2025-03-13 10:20:33 -07:00
Jiang Xin ab7cb7e263 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
2025-03-13 21:57:56 +08:00
Yi-Jyun Pan 7bc205bec2
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>
2025-03-13 21:53:11 +08:00
Jiang Xin c64eec3400 Merge branch 'l10n-de-2.49' of github.com:ralfth/git
* 'l10n-de-2.49' of github.com:ralfth/git:
  l10n: update German translation
2025-03-13 14:15:38 +08:00