Commit Graph

82030 Commits (fcc8c931b536614faddcdc20c43bfb5dc72cd8ef)

Author SHA1 Message Date
Junio C Hamano fcc8c931b5 Merge branch 'js/coverity-unchecked-returns-fix'
A handful of code paths have been corrected to check return values
from functions like curl_easy_duphandle(), deflateInit(), lseek(),
dup(), and strbuf_getline_lf(), resolving several Coverity warnings
about unchecked returns.

* js/coverity-unchecked-returns-fix:
  bisect: handle dup() failure when redirecting stdout
  bisect: check get_terms return at all call sites
  bisect: check strbuf_getline_lf return when reading terms
  transport-helper: warn when export-marks file cannot be finalized
  transport-helper: check dup() return in get_exporter
  compat/pread: check initial lseek for errors
  last-modified: handle repo_parse_commit() failures
  reftable tests: check reftable_table_init_ref_iterator() return
  reftable/block: check deflateInit() return value
  reftable: handle block-writer initialization errors
  config: propagate launch_editor() failure in show_editor()
  http: die on curl_easy_duphandle failure in get_active_slot
2026-08-24 13:17:50 -07:00
Junio C Hamano 593c42fe07 The 17th batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-23 18:01:47 -07:00
Junio C Hamano 679a72c6b8 Merge branch 'kk/merge-base-exhaustion'
The merge-base computation has been optimized by stopping the walk
early when one side's exclusive commits in the queue are exhausted,
yielding significant speedups for queries with one-sided histories.

* kk/merge-base-exhaustion:
  commit-reach: remove commit-date ordering fallback
  commit-reach: move min_generation check into paint_queue_get()
  commit-reach: terminate merge-base walk when one paint side is exhausted
  commit-reach: introduce struct paint_state with per-side counters
  t6600: add clock-skew topologies and step counts for edge cases
  commit-reach: add trace2 instrumentation to paint_down_to_common()
  t6099: add side-exhaustion regression test
  t6600: add test cases for side-exhaustion edge cases
  test-lib-functions: improve diagnostic output for trace2 data assertions
  Documentation/technical: add paint-down-to-common doc
2026-08-23 18:01:46 -07:00
Junio C Hamano e8e7bf97fe Merge branch 'js/sequencer-release-odb-before-commit'
The sequencer has been updated to release the object database before
spawning 'git commit'.  This prevents open file handles from
blocking auto-maintenance tasks, such as repacking, on systems like
Windows where open files cannot be easily unlinked.

* js/sequencer-release-odb-before-commit:
  sequencer: release the ODB before spawning git commit
2026-08-23 18:01:45 -07:00
Junio C Hamano 6aab7b26a6 Merge branch 'hn/send-email-missing-subject-error'
The error message given by 'git send-email' when a message file is
missing a 'Subject:' header has been clarified, and the error string
is now terminated with a newline so that Perl avoids appending its
internal source location data.

* hn/send-email-missing-subject-error:
  send-email: clarify missing subject error
2026-08-23 18:01:44 -07:00
Junio C Hamano a2ef06b1ef Merge branch 'ps/odb-streams'
The 'struct odb_read_stream' and 'struct odb_write_stream'
structures have been consolidated into a single unified 'struct
odb_stream' structure, simplifying object database streaming APIs
and enabling streaming of arbitrary object types.

* ps/odb-streams:
  odb/streaming: unify function names to create new streams
  odb/streaming: rename `struct input_zstream_data`
  odb/streaming: rename `struct read_object_fd_data`
  odb/streaming: consolidate read and write streams
  odb/streaming: rename `struct odb_read_stream`
  odb/streaming: support streaming arbitrary object types
  odb/streaming: drop `is_finished` field
  odb/streaming: track write stream size in the structure
2026-08-23 18:01:43 -07:00
Junio C Hamano 10d3ea2469 Merge branch 'cc/fast-import-usage'
The usage string of 'git fast-import' has been updated to use the
parse_options() API for displaying help, and its SYNOPSIS in the
documentation has been standardized to match.

* cc/fast-import-usage:
  fast-import: remove useless from_stream argument
  fast-import: use parse_options() for command line options
  fast-import: use callbacks to parse some options
  fast-import: use struct option for usage string
  fast-import: move command state globals into 'struct fast_import_state'
  fast-import: introduce 'struct fast_import_state'
  fast-import: factor out option_*() functions
  fast-import: use int for some bool flags
  fast-import: localize 'i' into the 'for' loops using it
  api-parse-options.adoc: document hidden and OPT_*_F option macros
  api-parse-options.adoc: document per-option flags
  parse-options: introduce OPT_HIDDEN_GROUP
2026-08-23 18:01:42 -07:00
Junio C Hamano 4b27b7c707 Merge branch 'ps/cat-file-remote-object-info-type'
The 'remote-object-info' command for 'git cat-file --batch-command'
has been extended to support the '%(objecttype)' placeholder.

* ps/cat-file-remote-object-info-type:
  cat-file: unify default format
  serve: advertise type capability
  fetch-object-info: parse type from server response
  protocol-caps: add type support to object-info
  transport: drop remote object-info fields from transport struct
  fetch-object-info: die() on the remaining error path
  fetch-object-info: use dedicated struct for the results
  fetch-object-info: pass arguments directly instead of a struct
  fetch-object-info: detect malformed server responses
  t5701: use test_file_size() to get the size of a file
2026-08-23 18:01:42 -07:00
Junio C Hamano 1a3e64c6c4 The 16th batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-20 07:30:52 -07:00
Junio C Hamano 3f664917c2 Merge branch 'kh/doc-trailers'
Documentation for 'git interpret-trailers' has been updated to explain
the format of trailer keys (alphanumeric characters and hyphens),
replace outdated terminology, define key terms upfront, and document
how comment lines in the input are treated.

* kh/doc-trailers:
  doc: interpret-trailers: document comment line treatment
  doc: interpret-trailers: rewrite new-trailers paragraphs
  doc: interpret-trailers: commit to “trailer block” term
  doc: interpret-trailers: join new-trailers again
  doc: interpret-trailers: add key format example
  doc: interpret-trailers: explain key format
  doc: interpret-trailers: explain the format after the intro
  doc: interpret-trailers: not just for commit messages
  doc: interpret-trailers: use “metadata” in Name as well
  doc: interpret-trailers: replace “lines” with “metadata”
  doc: interpret-trailers: stop fixating on RFC 822
2026-08-20 07:30:52 -07:00
Junio C Hamano 2f6614658f Merge branch 'ps/odb-make-creation-pluggable'
The creation of the on-disk data structures for the object database
has been made pluggable, allowing future backends to customize their
setup.  As part of this, the initialization of the object database
has been deferred, and the loading of the loose-object map has been
detangled from repository initialization.

* ps/odb-make-creation-pluggable:
  odb: make creation of on-disk structures pluggable
  odb/source: introduce function to map source type to name
  setup: defer object database creation
  setup: handle ODB-related environment variables in `odb_new()`
  setup: detangle loading of loose object maps
  loose: load loose object map for the correct source
2026-08-20 07:30:52 -07:00
Junio C Hamano 006933a32c Merge branch 'hn/branch-delete-merged'
The 'git branch' command has been taught the '--delete-merged' option
to remove local branches that are already merged into their tracked
remote-tracking branches.

* hn/branch-delete-merged:
  branch: add --dry-run for --delete-merged
  branch: add branch.<name>.deleteMerged opt-out
  branch: add --delete-merged <pattern>
  branch: prepare delete_branches for a bulk caller
  branch: let delete_branches skip unmerged branches on bulk refusal
  branch: convert delete_branches() to a flags argument
  branch: add --forked filter for --list mode
2026-08-20 07:30:51 -07:00
Junio C Hamano dea0ea3582 The 15th batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-18 09:31:36 -07:00
Junio C Hamano e23356ae1a Merge branch 'hn/bisect-reset-when-found'
The 'git bisect' command has been taught a
'--reset-when-found[=<where>]' option that tells the command to
automatically run 'git bisect reset' to jump back to the original
state or to the found culprit.

* hn/bisect-reset-when-found:
  bisect: add --reset-when-found to leave when done
  bisect: let bisect_reset() optionally check out quietly
2026-08-18 09:31:36 -07:00
Junio C Hamano 3beb8bb742 Merge branch 'ps/writev'
A compatibility wrapper for writev(3p) has been reintroduced,
including fixes for CMake build and 'MAX_IO_SIZE' limits on NonStop.
Calls to write(3p) in send_sideband() and cat_blob() have been
refactored to use writev(3p) wrappers to reduce syscall overhead.

* ps/writev:
  fast-import: use writev(3p) to send cat-blob responses
  sideband: use writev(3p) to send pktlines
  wrapper: properly handle MAX_IO_SIZE in writev(3p)
  wrapper: introduce writev(3p) wrappers
  compat/posix: introduce writev(3p) wrapper
2026-08-18 09:31:36 -07:00
Junio C Hamano 1428b15baf Merge branch 'kh/doc-refs-migrate-limitations'
The known limitations of the ref format migration in 'git refs' have
been moved to be displayed as a warning admonition directly under the
description of the 'migrate' subcommand, improving visibility.  A
reference to 'git-maintenance' has also been corrected to use the
'linkgit' macro.

* kh/doc-refs-migrate-limitations:
  doc: refs: linkgit to git-maintenance(1)
  doc: refs: put ref migration warning under the command
2026-08-18 09:31:36 -07:00
Junio C Hamano 18e66859d8 The 14th batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-15 09:20:27 -07:00
Junio C Hamano 230296d560 Merge branch 'jc/add-resolved'
'git add' has been taught a new '--resolved' option to stage
conflict-resolved paths, while leaving unrelated local changes
unstaged.  It scans the unmerged paths for leftover conflict
markers and aborts if any are found.

* jc/add-resolved:
  add: introduce '--resolved' option
  read-cache: add remove_file_from_index_with_flags()
  merge-ll: consolidate conflict marker scanning logic
  read-cache: reindent
2026-08-15 09:20:27 -07:00
Junio C Hamano 90d7103396 Merge branch 'kl/t7528-ssh-agent-for-csh-users'
The 'ssh-agent' tests in 't7528' have been fixed to work when the
user's login shell is csh-like, by explicitly passing '-s' to
'ssh-agent' to force Bourne shell syntax.

* kl/t7528-ssh-agent-for-csh-users:
  t7528: fix failure under csh
2026-08-15 09:20:27 -07:00
Junio C Hamano 8b34c1f352 Merge branch 'tn/packfile-uri-concurrency'
Concurrent downloads of packfiles via packfile URIs and dumb HTTP are
safer by avoiding concurrent appends to the staging file.  Opening in
read-write mode with separate file offsets prevents corruption and
preserves resumability.  'fetch-pack' now tolerates pre-existing
'.keep' files.

* tn/packfile-uri-concurrency:
  fetch-pack: accept "pack" output for packfile URIs
  http: permit unlinking partial packs on Windows
  http: avoid concurrent appends to partial packs
  http: accept HTTP 416 for complete partial packs
  http: avoid closing index-pack input twice
  http-fetch: correct --index-pack-arg documentation
2026-08-15 09:20:27 -07:00
Junio C Hamano f2f3a37b68 Merge branch 'jm/t0213-skip-emulated-ancestry-tests'
The 'TRACE2_ANCESTRY' prerequisite in the 't0213' test script has been
refined to avoid failures under user-mode emulation by verifying that
the ancestry collector reports the expected process names rather than
the emulator binary name.

* jm/t0213-skip-emulated-ancestry-tests:
  t0213: skip ancestry tests under user-mode emulation
2026-08-15 09:20:26 -07:00
Elijah Newren 745601a9a9 mailmap: map Elijah Newren's current and previous work addresses
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 13:16:46 -07:00
Johannes Schindelin 65cda10d5b sequencer: release the ODB before spawning git commit
As of 4557f1add2 (rebase--helper: add a builtin helper for interactive
rebases, 2017-02-09), continuing an interactive rebase uses the builtin
sequencer, which spawns `git commit`.

The child may trigger auto-maintenance, which may need to replace files
for which the sequencer still holds resources. See
https://github.com/git-for-windows/git/issues/6315: on Windows, this
produces unlink retry prompts that cannot succeed while the sequencer
waits for the child.

Resources such as file handles or memory mappings must be released
before spawning a command that may run auto-maintenance, as established
by 28d04e1ec1 (run-command: offer to close the object store before
running, 2021-09-09): release the ODB file handles and memory mappings,
so that auto-gc can repack (potentially deleting existing packfiles in
the process); If the sequencer needs to access the ODB afterwards, it
will gracefully (re-)open the ODB.

Release the sequencer's ODB before spawning `git commit`. The regression
test uses the legacy-delete trick introduced by 69ed0e35a7 (mingw:
optionally use legacy (non-POSIX) delete semantics, 2026-05-07) to
trigger the failure on modern Windows.

Assisted-by: GPT-5.6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:07:03 -07:00
Johannes Schindelin 5f87f65af6 bisect: handle dup() failure when redirecting stdout
To capture the output of each verdict command, bisect_run()
temporarily redirects stdout to a temporary file via the classic
dup(1) / dup2() pair, restoring it afterwards. The return value of
dup(1) is not checked, however. When it fails, the saved descriptor
is -1, which is then passed to close() (the issue Coverity flags),
and the matching dup2() that is meant to restore stdout also fails,
leaving the process with stdout still pointing at the temporary file
for the remainder of the run.

Treat a failed dup(1) or dup2(..., 1) as a fatal error for this bisect
step: close the temporary file descriptor, report the error via
error_errno(), and break out of the loop so the existing cleanup path
handles the rest, just as on other failure paths in this function.

Reported by Coverity as CID 1508242 ("Improper use of negative
value").

Assisted-by: Opus 4.7
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin 211ba0c0c8 bisect: check get_terms return at all call sites
Six callers of get_terms() silently discard its return value. When
get_terms fails (missing or truncated BISECT_TERMS file), the term
strings remain NULL or empty, causing confusing downstream
behavior: commands like "bisect next" or "bisect run" proceed with
empty term strings, producing nonsensical ref names (refs/bisect/
with no suffix) and misleading error messages.

Let's not discard the return value, but handle an error with the same
message `bisect_terms()` already uses when reading the terms failed.

Pointed out by Coverity.

There is one slight complication here: One caller _needs_ the return
value to indicate an error when the `BISECT_TERMS` file is absent, all
the other call sites are totally okay with a "missing" `BISECT_TERMS`
file. To address that, extend the function signature of `get_terms()` to
indicate which behavior the caller wants.

Assisted-by: Claude Opus 4.6
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin 2f93092642 bisect: check strbuf_getline_lf return when reading terms
get_terms() in builtin/bisect.c and read_bisect_terms() in
bisect.c both read the BISECT_TERMS file but do not check the
strbuf_getline_lf() return values. If the file is truncated
(e.g., a partial write from a crash or disk-full condition),
strbuf_getline_lf returns EOF and the strbuf remains empty.
strbuf_detach then returns an empty string, and the term names
silently become "" instead of the expected "bad"/"good" or
custom terms.

In get_terms(), check for EOF and return -1 on truncation,
matching the existing -1 return for a missing file.

In read_bisect_terms(), die with a descriptive message when a
line cannot be read, consistent with the die_errno for a
non-ENOENT open failure in the same function. Unlike get_terms(),
read_bisect_terms() returns void and uses die() for all error
paths, so the die is the appropriate error handling here.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin 78ef560657 transport-helper: warn when export-marks file cannot be finalized
When push_refs_with_export() finalizes a successful push, it writes
the fast-export marks file to a .tmp sibling and rename()s it into
place. The return value of rename() is currently ignored. If the
rename fails (permission denied, full disk, or an antivirus product
locking the destination on Windows), the .tmp file is left behind
and the existing export_marks file remains stale; the next
fast-export operation that resumes from it then silently operates on
inconsistent bookkeeping.

The push itself succeeded by that point, so promoting this to a
fatal error would be inappropriate. Emit warning_errno() naming both
paths so the user can recover manually, and keep returning 0.

Flagged by Coverity as CID 1427723 ("Unchecked return value").

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin af62506595 transport-helper: check dup() return in get_exporter
get_exporter() duplicates helper->in via dup() and stores the
result in fastexport->out. If dup() fails (fd exhaustion), it
returns -1. The child_process machinery interprets out = -1 as
"create a pipe for stdout", which would silently change the
fast-export process's output wiring: instead of sending data
back through the helper's input fd, it would write to a new pipe
that nobody reads from.

Check the return value and report the error before proceeding.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin 02b9662a6e compat/pread: check initial lseek for errors
git_pread() saves the current file offset via lseek(fd, 0,
SEEK_CUR) and later restores it. If the initial lseek fails
(e.g., the fd is a pipe or otherwise non-seekable),
current_offset is -1. This negative value is later passed to
lseek(fd, -1, SEEK_SET) at line 16, which sets the file position
to an unintended location (or fails with EINVAL on some
platforms).

Check the initial lseek return value and return -1 immediately
if it fails, consistent with the error handling for the other
lseek calls in the same function.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin ec428c6646 last-modified: handle repo_parse_commit() failures
last_modified_run() and process_parent() call repo_parse_commit()
without checking the return value at three sites. When a commit
object is corrupt or unavailable (e.g., a shallow clone boundary
or a missing object in a partial clone), the parse fails and the
commit's internal fields (parents, tree, date) are not populated.

The consequences depend on which call site fails:

At line 417 (the main walk loop), c->parents stays NULL after a
failed parse. The parent-walking loop at line 440 simply does not
execute, silently treating the unparsable commit as a root commit.
This produces incorrect "last modified" results: paths changed in
ancestors beyond the corrupt commit are attributed to the wrong
commit or not reported at all.

At line 423 (the --not exclusion walk), n->parents stays NULL,
causing the exclusion walk to stop prematurely. Commits that
should be excluded from the output may be incorrectly included.

At line 293 (process_parent), the parent's tree and parents are
unavailable, so diff operations against it produce wrong results
and the parent's own ancestors are never enqueued for walking.

Skip unparsable commits by checking the return value and
continuing to the next iteration (or returning early in
process_parent). This matches the defensive pattern used in other
revision walkers such as limit_list() and get_revision_internal().

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:50 -07:00
Johannes Schindelin e3ddc2e529 reftable tests: check reftable_table_init_ref_iterator() return
test_reftable_table__seek_once() and test_reftable_table__reseek()
both call reftable_table_init_ref_iterator() without checking its
return value. This function returns an int error code (0 on
success, negative on failure). Every other reftable function call
in these same tests checks the return via cl_assert_equal_i() or
cl_assert(), making this omission inconsistent.

If the iterator initialization ever fails (e.g., due to a memory
allocation failure in the reftable internals), the test would
proceed to seek and read with an uninitialized iterator, producing
misleading test results or crashes rather than a clear assertion
failure.

Check the return value via cl_assert_equal_i(ret, 0), consistent
with the surrounding code.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:49 -07:00
Johannes Schindelin f8121b7479 reftable/block: check deflateInit() return value
block_writer_init() allocates a z_stream and calls deflateInit()
to prepare it for compressing log records. The return value of
deflateInit() is silently discarded. If zlib initialization fails
(e.g., Z_MEM_ERROR when the system is under memory pressure), the
z_stream is left in an undefined state.

Subsequent deflate() calls in block_writer_finish() then operate
on this uninitialized stream. Current zlib/zlib-ng versions handle
such a stream gracefully, by returning `Z_STREAM_ERROR`, so in
practice it would likely not result in catastrophic error.

The function already uses REFTABLE_ZLIB_ERROR for deflate() failures
later in the code path, so returning the same error code for
deflateInit() failure is consistent.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:49 -07:00
Johannes Schindelin 47568fee94 reftable: handle block-writer initialization errors
2d5dbb37b2 (reftable/block: handle allocation failures, 2024-10-02)
taught `writer_reinit_block_writer()` to report initialization failures
and updated its callers, but `reftable_writer_new()` continued to ignore
the return value.

Consequently, the constructor could report success after block-writer
initialization had failed. Propagate the error and release the
constructor's allocations instead of returning an unusable writer.

Pointed out by GPT-5.6 Sol and Claude Opus 4.8.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:49 -07:00
Johannes Schindelin 633ac346ee config: propagate launch_editor() failure in show_editor()
show_editor() calls launch_editor() to open the user's editor on
the configuration file, but discards the return value and
unconditionally returns 0 (success). When the editor fails to
launch (e.g., $EDITOR is not found, or the editor exits with a
nonzero status), the caller receives no indication that anything
went wrong.

This affects "git config edit" and "git config --edit": the
command silently succeeds even when the editor could not be
started. In contrast, other editor-launching paths in git (such
as "git commit" and "git rebase --edit-todo") properly propagate
editor failures and exit with an error.

Check the return value and propagate the failure by returning -1.
The two callers (cmd_config_edit at line 1315 and the legacy
cmd_config at line 1478) both propagate this return to
handle_builtin, which translates negative returns into an error
exit.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:49 -07:00
Johannes Schindelin 93aab89509 http: die on curl_easy_duphandle failure in get_active_slot
get_active_slot() duplicates the default curl handle via
curl_easy_duphandle() to create a per-slot session handle. The
return value is stored directly in slot->curl without checking
for NULL. curl_easy_duphandle() can return NULL when memory
allocation fails internally, and the libcurl documentation
explicitly states this possibility.

When this happens, slot->curl is NULL and the very next operation
(curl_easy_setopt on line 1632 for CURLOPT_COOKIEFILE) passes
NULL as the curl handle, which is undefined behavior in libcurl
and typically crashes.

Every HTTP operation in git goes through get_active_slot(), so
this affects all remote-https, remote-http, and HTTP-based
operations (clone, fetch, push over HTTP, bundle-uri downloads).

Add a NULL check and die() with a clear message. There is no
reasonable recovery from a failed handle duplication: the process
is out of memory and cannot perform any HTTP operation.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-12 09:05:49 -07:00
Junio C Hamano 11c6700f10 The 13th batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 10:07:00 -07:00
Junio C Hamano 97895a898d Merge branch 'ns/merge-base-is-ancestor-tests'
Tests for 'git merge-base --is-ancestor' have been added to cover
exit codes (0 for success, 1 for non-ancestor, 128 for errors) and
to ensure it cannot be combined with '--all'.

* ns/merge-base-is-ancestor-tests:
  merge-base: add tests for --is-ancestor
2026-08-11 10:07:00 -07:00
Junio C Hamano 4753128b86 Merge branch 'lo/mv-missing-dest-dir-check'
'git mv' has been updated to check for a missing destination
leading directory during the checking phase, allowing 'git mv -n'
to report the failure.  The error message when the rename(2)
syscall fails has also been improved to name both the source and
the destination.

* lo/mv-missing-dest-dir-check:
  mv: reject a destination whose leading path is missing or a symlink
  mv: name both source and destination when rename fails
2026-08-11 10:07:00 -07:00
Junio C Hamano 461ed7e1b3 Merge branch 'kh/doc-replay-config'
Documentation for 'git replay' has been updated to refer to its
configuration variables.

* kh/doc-replay-config:
  doc: replay: move “default” to the right-hand side
  doc: replay: use a nested description list
  doc: replay: improve config description
  doc: link to config for git-replay(1)
2026-08-11 10:07:00 -07:00
Junio C Hamano 3307faf4c1 Merge branch 'sk/test-commit-body-helper'
A new test helper commit_body() has been introduced to print the
message body of a commit, and various tests have been updated to use
it instead of spelling out the command pipeline manually and losing
the exit status of the 'git cat-file' command on the upstream of the
pipe.

* sk/test-commit-body-helper:
  t: use commit_body to extract commit message bodies
  test-lib-functions: add commit_body helper
2026-08-11 10:06:59 -07:00
Junio C Hamano bf6bc2ae42 Merge branch 'ja/doc-synopsis-style-yet-more'
Synopsis and options in the documentation for 'git format-patch',
'git imap-send', 'git send-email', and 'git request-pull' have been
updated to the modern style.

* ja/doc-synopsis-style-yet-more:
  doc: convert git-request-pull synopsis and options to new style
  doc: convert git-send-email synopsis and options to new style
  doc: convert git-format-patch synopsis and options to new style
  doc: convert git-imap-send synopsis and options to new style
2026-08-11 10:06:59 -07:00
Kristofer Karlsson 56c9056e30 commit-reach: remove commit-date ordering fallback
Remove the fallback that switched paint_down_to_common() from
generation ordering to commit-date ordering when the commit-graph
lacks corrected commit dates (v1 graph with topo levels only).

The fallback was added in 091f4cf3 (commit: don't use generation
numbers if not needed, 2018-08-30) to avoid a performance
regression on the Linux kernel repo where v1 topo levels caused
"git merge-base v4.8 v4.9" to walk 636k commits instead of 167k.
A side branch with a low topo level stayed in the queue behind a
long chain, preventing early STALE propagation.

Side-exhaustion (added in the previous commits) solves this
differently by terminating the walk as soon as one paint side
empties from the queue, preventing the deep walk regardless of
queue ordering. Benchmarks of "git merge-base --all v4.8 v4.9"
on the Linux kernel repo show that side-exhaustion reduces the
step count far below what the date-ordering fallback achieved:

                         steps      time
  no graph, baseline:   167,413    3.25 s
  v1 graph, baseline:   167,413    0.25 s
  v2 graph, baseline:   167,441    0.29 s
  v1 graph, this series:  5,725    0.02 s
  v2 graph, this series:  3,887    0.01 s

With generation ordering always active, the existing min_generation
check in paint_queue_get() can safely terminate once the walk
crosses below the caller's generation floor. The date ordering
fallback broke this invariant: a commit could have a finite topo
level while the queue was date-ordered, causing the early exit to
fire before all merge bases were found.

With the fallback removed, gen_ordered is always true and can be
dropped. The topo_ceiling field (introduced earlier) already
handles V1_MAX saturation, so the early exit gates need no further
changes.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson 4e08160c2b commit-reach: move min_generation check into paint_queue_get()
Consolidate the min_generation termination condition into
paint_queue_get(), alongside the existing stale-entry and
side-exhaustion checks.

Move last_gen into struct paint_state so that
commit_graph_generation() is called exactly once per dequeued commit
and the result is shared across all termination checks and the
monotonicity BUG assertion.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson 02d7ba092d commit-reach: terminate merge-base walk when one paint side is exhausted
Add an early termination check to paint_down_to_common() using the
per-side counters introduced earlier. Once the walk enters the
ordered region, terminate early when one side's exclusive count
drops to zero -- no new merge-base can form without both paint
sides meeting.

The check also waits for pending_merge_bases to reach zero, ensuring
all merge-base candidates have been dequeued and recorded before
exiting.

The optimization is gated by gen_ordered (which excludes v1
commit-graphs that use the date-ordering fallback) and by a
generation check against topo_ceiling. topo_ceiling is
GENERATION_NUMBER_INFINITY for v2 graphs and
GENERATION_NUMBER_V1_MAX for v1 graphs, so that saturated commits
are treated as unordered. Together these ensure the check only
fires in the ordered region where topological ordering holds.

The same topo_ceiling boundary is applied to the existing
single-result early exit so that all generation-dependent gates
express the same saturation-aware boundary consistently.

Step counts measured with trace2 on git.git with commit-graph:

  merge-base --all v2.0.0 v2.55.0-rc1:
    before: 72264 steps    after: 44589 steps

  merge-base --all v2.55.0-rc1 v2.55.0-rc1~5:
    before:   110 steps    after:     7 steps

Helped-by: Derrick Stolee <stolee@gmail.com>
Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson a3e5bad734 commit-reach: introduce struct paint_state with per-side counters
Add a paint_state struct for use by paint_down_to_common() that
wraps a prio_queue with per-side commit counters. Each non-stale
queued commit occupies exactly one counter bucket based on its
paint flags: PARENT1-only, PARENT2-only, or both sides (a pending
merge-base candidate).

The counters are maintained by paint_count_update() which adjusts
the appropriate bucket by a signed delta. An exhaustive switch on
the paint+stale bits documents all valid flag combinations in one
place.

Convert paint_down_to_common() to use paint_state. The loop now
drains the queue via paint_queue_get() which returns NULL when all
counters reach zero, replacing the old pointer-based termination
(max_nonstale). This is equivalent behavior -- both conditions
detect that no non-stale entries remain.

paint_queue_get() uses a "pop first" form: it dequeues a commit,
then checks the counters. This means the loop exits one iteration
earlier than the old code in some topologies (the popped stale
commit is never processed), so a few step counts drop by one.

The existing nonstale_queue is left in place for ahead_behind(),
though nonstale_queue_put_dedup() and nonstale_queue_get_dedup()
become unused and are removed.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson bad379346d t6600: add clock-skew topologies and step counts for edge cases
Add topologies and tests exercising paint_down_to_common() under
clock skew, where commit-date ordering (v1 commit-graph without
corrected commit dates) violates the topological invariant that
children are dequeued before parents:

 - se-*: side-exhaustion fires too early when one paint side fully
   drains from the queue while a low-date ancestor on the other
   side is still queued

 - se2-*: side-exhaustion returns a too-deep merge base because
   the correct (closer) base never receives both paint sides

Also add step counts to the edge-case tests from the previous
commit, a mixed finite/INFINITY generation topology exercising
the transition from INFINITY-generation commits to graph-backed
commits, and step counts for the grid-based merge-base test.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson 6300d71cd6 commit-reach: add trace2 instrumentation to paint_down_to_common()
Add a step counter and trace2_data_intmax() call so that the number
of commits visited during the paint walk is observable via
GIT_TRACE2_EVENT. This provides a way to measure the impact of
future optimizations without relying on wall-clock benchmarks alone.

Some step counts already vary across commit-graph modes (e.g.
in_merge_bases_many:self) because the pre-existing min_generation
optimization short-circuits the walk when generation data is
available.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson 259a45f1f8 t6099: add side-exhaustion regression test
Add t6099 to test the case where multiple merge-base candidates exist
and one is an ancestor of another. This exercises the side-exhaustion
optimization in paint_down_to_common together with the
remove_redundant safety net in get_merge_bases_many_0.

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Elijah Newren d3180b1534 t6600: add test cases for side-exhaustion edge cases
Add test cases to t6600-test-reach.sh that exercise edge cases in the
side-exhaustion optimization for paint_down_to_common():

 - in_merge_bases_many:self: commit is both A and one of the X inputs
 - get_merge_bases_many:duplicate-twos: duplicate entries in X list
 - get_merge_bases_many:pending-stale: STALE transition on an
   already-painted commit (ps-* diamond topology)
 - get_merge_bases_many:infinity-both-sides: both tips outside the
   commit-graph with non-monotonic dates (pi-* topology)

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:32 -07:00
Kristofer Karlsson fe4877bc17 test-lib-functions: improve diagnostic output for trace2 data assertions
test_trace2_data is a bare grep that silently exits on failure.
Add a more informative variant that verifies the event appears
exactly once and reports what went wrong: key not found, multiple
entries, or value mismatch. Diagnostics go to FD 4 like test_grep.

Before (value mismatch):

  $ test_trace2_data status count/changed 999 <trace2.txt
  $ echo $?
  1
  (no output)

After:

  $ test_trace2_data_singular status count/changed 999 <trace2.txt
  error: trace2 data 'status/count/changed'
    expected: 999
    actual:   0

Signed-off-by: Kristofer Karlsson <krka@spotify.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-08-11 07:34:31 -07:00