* Re: [PATCH v5 1/3] pager: include stdint.h because uintmax_t is used
From: Junio C Hamano @ 2024-02-27 23:25 UTC (permalink / raw)
To: Kyle Lippincott; +Cc: Calvin Wan, git, Jonathan Tan, phillip.wood123
In-Reply-To: <CAO_smVgmaXvyZZ7zp6RCFD_6kpL2pHKC9gMDeg+yXBb9R4rR5w@mail.gmail.com>
Kyle Lippincott <spectral@google.com> writes:
> of <git-compat-util.h> that enforces that we're using C99. Therefore,
> I'm assuming that any compiler that claims to be C99 and passes that
> check at the top of <git-compat-util.h> will support inttypes.h,
> stdint.h, stdbool.h, and other files defined by the C99 standard to
> include types that we need in our .h files are able to be included
> without reservation.
We at the git project is much more conservative than trusting the
compilers and take their "claim" to support a standard at the face
value, though ;-). As our CodingGuidelines say, we honor real world
constraints more than what's written on paper as "standard", and
would ...
> To flip it around: any compiler/platform that's
> missing inttypes.h, or is missing stdint.h, or raises errors if both
> are included, or requires other headers to be included before them
> _isn't a C99 compiler_, and _isn't supported_.
... refrain from taking such a position as much as possible.
> I think the only viable solution to this is to not use these types
> that depend on #defines in the interface available to non-git
> projects.
OK. Now we have that behind us, can we start outlining what kind of
things _are_ exported out in the library to the outside world? The
only example of the C source file that is a client of the library we
have is t/helper/test-stdlib.c but it includes
<abspath.h>
<hex-ll.h>
<parse.h>
<strbuf.h>
<string-list.h>
after including <git-compat-util.h>. Are the services offered by
these five header files the initial set of the library, minimally
viable demonstration? Has somebody already analyzed and enumerated
what kind of system definitions we need to support the interface
these five header files offer?
Once we know that, perhaps the next task would be to create a
<git-absolute-minimum-portability-requirement.h> header by taking a
subset of <git-compat-util.h>, and have test-stdlib.c include that
instead of <git-compat-util.h>. <git-compat-util.h> will of course
include that header to replace the parts it lost to the new header.
It does *not* make it a requirement for client programs to include
the <git-absolute-minimum-portability-requirement.h>, though. They
can include the system headers in the way they like, as long as they
do not let them define symbols in ways contradicting to what our
headers expect. <git-absolute-minimum-portability-requirement.h> is
merely a way for us to tell those who write these client programs
what the system symbols we rely on are.
So, that's one (or two? first to analyse and enumerate, second to
split a new header file out of compat-util) actionable task, I
guess.
^ permalink raw reply
* Re: [PATCH 08/12] reftable/merged: avoid duplicate pqueue emptiness check
From: James Liu @ 2024-02-27 23:53 UTC (permalink / raw)
To: Patrick Steinhardt, git
In-Reply-To: <68bd6871132bac3ff8d67e908dd31647feab6bc3.1707895758.git.ps@pks.im>
On Wed Feb 14, 2024 at 6:46 PM AEDT, Patrick Steinhardt wrote:
> Now if this check was there to accellerate the common case it might have
s/accellerate/accelerate
^ permalink raw reply
* Re: [PATCH 09/12] reftable/record: reuse refname when decoding
From: James Liu @ 2024-02-28 0:06 UTC (permalink / raw)
To: Patrick Steinhardt, git
In-Reply-To: <3ba697036c1db3837f46775823a7bd55602b4bac.1707895758.git.ps@pks.im>
On Wed Feb 14, 2024 at 6:46 PM AEDT, Patrick Steinhardt wrote:
> This refactoring is safe to do because all functions that assigning to
> the refname will first call `release_reftable_record()`, which will zero
> out the complete record after releasing memory.
s/release_reftable_record/reftable_ref_record_release
> Furthermore, with this change we now perform a mostly constant number of
> allocations when iterating.
That's awesome!
> + SWAP(refname, r->refname);
> + SWAP(refname_cap, r->refname_cap);
> reftable_ref_record_release(r);
> + SWAP(refname, r->refname);
> + SWAP(refname_cap, r->refname_cap);
What do you think about reversing the order of the `SWAP` arguments in
the last two invocations? If my understanding is correct that we're
preserving the `refname` and `refname_cap` fields so we can set them back
into a freshly initialised `r`, reversing the args might make that intent
a bit clearer.
Also, since we're unconditionally `memcpy`ing the key into `r->refname`
below, can we avoid the `SWAP(refname, r->refname)` call altogether?
> - assert(hash_size > 0);
> -
> - r->refname = reftable_malloc(key.len + 1);
> + REFTABLE_ALLOC_GROW(r->refname, key.len + 1, r->refname_cap);
> memcpy(r->refname, key.buf, key.len);
> r->refname[key.len] = 0;
^ permalink raw reply
* Re: [PATCH 10/12] reftable/record: reuse refname when copying
From: James Liu @ 2024-02-28 0:08 UTC (permalink / raw)
To: Patrick Steinhardt, git
In-Reply-To: <d7311598c0f81ad3fa41560b54b0974d41485a23.1707895758.git.ps@pks.im>
On Wed Feb 14, 2024 at 6:46 PM AEDT, Patrick Steinhardt wrote:
> + SWAP(refname, ref->refname);
> + SWAP(refname_cap, ref->refname_cap);
> reftable_ref_record_release(ref);
> + SWAP(refname, ref->refname);
> + SWAP(refname_cap, ref->refname_cap);
Likewise here, what are your thoughts about reversing the SWAP arguments for
the last two invocations?
^ permalink raw reply
* Re: [PATCH v6 13/16] commit-graph: new Bloom filter version that fixes murmur3
From: Jiang Xin @ 2024-02-28 0:11 UTC (permalink / raw)
To: Taylor Blau
Cc: git, Jeff King, Junio C Hamano, Jonathan Tan, SZEDER Gábor
In-Reply-To: <d2f11c082d3bf10d9127c330a7d59b7e47ac4f21.1706741516.git.me@ttaylorr.com>
On Thu, Feb 1, 2024 at 9:50 AM Taylor Blau <me@ttaylorr.com> wrote:
>
> diff --git a/Documentation/config/commitgraph.txt b/Documentation/config/commitgraph.txt
> index e68cdededa..7f8c9d6638 100644
> --- a/Documentation/config/commitgraph.txt
> +++ b/Documentation/config/commitgraph.txt
> @@ -15,7 +15,7 @@ commitGraph.readChangedPaths::
>
> commitGraph.changedPathsVersion::
The word commitGraph is in camelCase here.
> diff --git a/commit-graph.c b/commit-graph.c
> index 6c3fbae142..6f9cab181e 100644
> --- a/commit-graph.c
> +++ b/commit-graph.c
> @@ -2501,6 +2499,13 @@ int write_commit_graph(struct object_directory *odb,
> }
> if (!commit_graph_compatible(r))
> return 0;
> + if (r->settings.commit_graph_changed_paths_version < -1
> + || r->settings.commit_graph_changed_paths_version > 2) {
> + warning(_("attempting to write a commit-graph, but "
> + "'commitgraph.changedPathsVersion' (%d) is not supported"),
To fix mismatched config variable, s/commitgraph/commitGraph/
See: https://github.com/git-l10n/pot-changes/blob/pot/seen/2024-02-27.diff#L32
--
Jiang Xin
^ permalink raw reply
* Re: [PATCH 11/12] reftable/record: decode keys in place
From: James Liu @ 2024-02-28 0:13 UTC (permalink / raw)
To: Patrick Steinhardt, git
In-Reply-To: <f0663c1d62d13d01afb1fa6c3760a38741bdfc8e.1707895758.git.ps@pks.im>
On Wed Feb 14, 2024 at 6:46 PM AEDT, Patrick Steinhardt wrote:
> - strbuf_reset(key);
> - strbuf_add(key, last_key.buf, prefix_len);
> - strbuf_add(key, in.buf, suffix_len);
> + strbuf_setlen(last_key, prefix_len);
> + strbuf_add(last_key, in.buf, suffix_len);
> string_view_consume(&in, suffix_len);
>
> return start_len - in.len;
Since we're using `strbuf`, there's no need to worry about extra bytes
for the null terminator here right?
^ permalink raw reply
* Re: [PATCH] git-difftool--helper: honor `--trust-exit-code` with `--dir-diff`
From: David Aguilar @ 2024-02-28 1:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Patrick Steinhardt, git, Jean-Rémy Falleri
In-Reply-To: <xmqqttm8i8hb.fsf@gitster.g>
On Fri, Feb 16, 2024 at 10:12 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Patrick Steinhardt <ps@pks.im> writes:
>
> > The `--trust-exit-code` option for git-diff-tool(1) was introduced via
> > 2b52123fcf (difftool: add support for --trust-exit-code, 2014-10-26).
> > When set, it makes us return the exit code of the invoked diff tool when
> > diffing multiple files. This patch didn't change the code path where
> > `--dir-diff` was passed because we already returned the exit code of the
> > diff tool unconditionally in that case.
> >
> > This was changed a month later via c41d3fedd8 (difftool--helper: add
> > explicit exit statement, 2014-11-20), where an explicit `exit 0` was
> > added to the end of git-difftool--helper.sh. While the stated intent of
> > that commit was merely a cleanup, it had the consequence that we now
> > to ignore the exit code of the diff tool when `--dir-diff` was set. This
> > change in behaviour is thus very likely an unintended side effect of
> > this patch.
> >
> > Now there are two ways to fix this:
> >
> > - We can either restore the original behaviour, which unconditionally
> > returned the exit code of the diffing tool when `--dir-diff` is
> > passed.
> >
> > - Or we can make the `--dir-diff` case respect the `--trust-exit-code`
> > flag.
> >
> > The fact that we have been ignoring exit codes for 7 years by now makes
> > me rather lean towards the latter option. Furthermore, respecting the
> > flag in one case but not the other would needlessly make the user
> > interface more complex.
> >
> > Fix the bug so that we also honor `--trust-exit-code` for dir diffs and
> > adjust the documentation accordingly.
> >
> > Reported-by: Jean-Rémy Falleri <jr.falleri@gmail.com>
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
>
> Sounds sensible.
>
> The last time David was on list seems to be in April 2023; just in
> case let's CC him for an Ack (or something else).
Thanks! I'm still lurking around.
I've been meaning to make some Git-adjacent announcements and
contributions soon..
Until then:
Acked-by: David Aguilar <davvid@gmail.com>
--
David
^ permalink raw reply
* Re: [PATCH] git-difftool--helper: honor `--trust-exit-code` with `--dir-diff`
From: Junio C Hamano @ 2024-02-28 2:15 UTC (permalink / raw)
To: David Aguilar; +Cc: Patrick Steinhardt, git, Jean-Rémy Falleri
In-Reply-To: <CAJDDKr5+3jszG=psh=kUGDjNCeTDGPSS-qDuN=JAq-3ua=bNDg@mail.gmail.com>
David Aguilar <davvid@gmail.com> writes:
>> The last time David was on list seems to be in April 2023; just in
>> case let's CC him for an Ack (or something else).
>
> Thanks! I'm still lurking around.
> I've been meaning to make some Git-adjacent announcements and
> contributions soon..
>
> Until then:
>
> Acked-by: David Aguilar <davvid@gmail.com>
Thanks.
It always is nice to hear from old-timer project participants.
^ permalink raw reply
* Re: [PATCH] branch: adjust documentation
From: Dragan Simic @ 2024-02-28 2:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Rubén Justo
In-Reply-To: <b6d22f5a66de49efc623eceddbdc6faf@manjaro.org>
Hello Junio,
On 2024-02-20 21:34, Dragan Simic wrote:
> On 2024-02-20 21:25, Rubén Justo wrote:
>> Adjust the placeholders we use in Documentation/git-branch.txt to what
>> we say in CodingGuideLines:
>>
>> If a placeholder has multiple words, they are separated by dashes:
>> <new-branch-name>
>> --template=<template-directory>
>>
>> Best viewed with --word-diff.
>>
>> Signed-off-by: Rubén Justo <rjusto@gmail.com>
>
> Looking good to me!
Just checking, do you see the changes that Ruben proposed in this patch
fit for our starting point in the git-branch documentation rewrite?
> Reviewed-by: Dragan Simic <dsimic@manjaro.org>
>
>> ---
>>
>> Documentation/git-branch.txt | 54
>> +++++++++++++++++-------------------
>> 1 file changed, 25 insertions(+), 29 deletions(-)
>>
>> diff --git a/Documentation/git-branch.txt
>> b/Documentation/git-branch.txt
>> index 0b08442932..489507e25f 100644
>> --- a/Documentation/git-branch.txt
>> +++ b/Documentation/git-branch.txt
>> @@ -17,13 +17,13 @@ SYNOPSIS
>> [(-r | --remotes) | (-a | --all)]
>> [--list] [<pattern>...]
>> 'git branch' [--track[=(direct|inherit)] | --no-track] [-f]
>> - [--recurse-submodules] <branchname> [<start-point>]
>> -'git branch' (--set-upstream-to=<upstream> | -u <upstream>)
>> [<branchname>]
>> -'git branch' --unset-upstream [<branchname>]
>> -'git branch' (-m | -M) [<oldbranch>] <newbranch>
>> -'git branch' (-c | -C) [<oldbranch>] <newbranch>
>> -'git branch' (-d | -D) [-r] <branchname>...
>> -'git branch' --edit-description [<branchname>]
>> + [--recurse-submodules] <new-branch> [<start-point>]
>> +'git branch' (--set-upstream-to=<upstream> | -u <upstream>)
>> [<branch>]
>> +'git branch' --unset-upstream [<branch>]
>> +'git branch' (-m | -M) [<branch>] <new-branch>
>> +'git branch' (-c | -C) [<branch>] <new-branch>
>> +'git branch' (-d | -D) [-r] <branch>...
>> +'git branch' --edit-description [<branch>]
>>
>> DESCRIPTION
>> -----------
>> @@ -53,7 +53,7 @@ branches not merged into the named commit will be
>> listed. If the <commit>
>> argument is missing it defaults to `HEAD` (i.e. the tip of the
>> current
>> branch).
>>
>> -The command's second form creates a new branch head named
>> <branchname>
>> +The command's second form creates a new branch head named
>> <new-branch>
>> which points to the current `HEAD`, or <start-point> if given. As a
>> special case, for <start-point>, you may use `"A...B"` as a shortcut
>> for
>> the merge base of `A` and `B` if there is exactly one merge base. You
>> @@ -61,7 +61,7 @@ can leave out at most one of `A` and `B`, in which
>> case it defaults to
>> `HEAD`.
>>
>> Note that this will create the new branch, but it will not switch the
>> -working tree to it; use "git switch <newbranch>" to switch to the
>> +working tree to it; use "git switch <new-branch>" to switch to the
>> new branch.
>>
>> When a local branch is started off a remote-tracking branch, Git sets
>> up the
>> @@ -72,17 +72,17 @@ the remote-tracking branch. This behavior may be
>> changed via the global
>> overridden by using the `--track` and `--no-track` options, and
>> changed later using `git branch --set-upstream-to`.
>>
>> -With a `-m` or `-M` option, <oldbranch> will be renamed to
>> <newbranch>.
>> -If <oldbranch> had a corresponding reflog, it is renamed to match
>> -<newbranch>, and a reflog entry is created to remember the branch
>> -renaming. If <newbranch> exists, -M must be used to force the rename
>> +With a `-m` or `-M` option, <branch> will be renamed to <new-branch>.
>> +If <branch> had a corresponding reflog, it is renamed to match
>> +<new-branch>, and a reflog entry is created to remember the branch
>> +renaming. If <new-branch> exists, -M must be used to force the rename
>> to happen.
>>
>> The `-c` and `-C` options have the exact same semantics as `-m` and
>> `-M`, except instead of the branch being renamed, it will be copied
>> to a
>> new name, along with its config and reflog.
>>
>> -With a `-d` or `-D` option, `<branchname>` will be deleted. You may
>> +With a `-d` or `-D` option, `<branch>` will be deleted. You may
>> specify more than one branch for deletion. If the branch currently
>> has a reflog then the reflog will also be deleted.
>>
>> @@ -107,7 +107,7 @@ OPTIONS
>> --create-reflog::
>> Create the branch's reflog. This activates recording of
>> all changes made to the branch ref, enabling use of date
>> - based sha1 expressions such as "<branchname>@\{yesterday}".
>> + based sha1 expressions such as "<branch>@\{yesterday}".
>> Note that in non-bare repositories, reflogs are usually
>> enabled by default by the `core.logAllRefUpdates` config option.
>> The negated form `--no-create-reflog` only overrides an earlier
>> @@ -116,7 +116,7 @@ OPTIONS
>>
>> -f::
>> --force::
>> - Reset <branchname> to <start-point>, even if <branchname> exists
>> + Reset <new-branch> to <start-point>, even if <new-branch> exists
>> already. Without `-f`, 'git branch' refuses to change an existing
>> branch.
>> In combination with `-d` (or `--delete`), allow deleting the
>> branch irrespective of its merged status, or whether it even
>> @@ -124,8 +124,8 @@ OPTIONS
>> `-m` (or `--move`), allow renaming the branch even if the new
>> branch name already exists, the same applies for `-c` (or `--copy`).
>> +
>> -Note that 'git branch -f <branchname> [<start-point>]', even with
>> '-f',
>> -refuses to change an existing branch `<branchname>` that is checked
>> out
>> +Note that 'git branch -f <new-branch> [<start-point>]', even with
>> '-f',
>> +refuses to change an existing branch `<new-branch>` that is checked
>> out
>> in another worktree linked to the same repository.
>>
>> -m::
>> @@ -255,7 +255,7 @@ how the `branch.<name>.remote` and
>> `branch.<name>.merge` options are used.
>> linkgit:git-config[1]. Currently, only branch creation is
>> supported.
>> +
>> -When used in branch creation, a new branch <branchname> will be
>> created
>> +When used in branch creation, a new branch <new-branch> will be
>> created
>> in the superproject and all of the submodules in the superproject's
>> <start-point>. In submodules, the branch will point to the submodule
>> commit in the superproject's <start-point> but the branch's tracking
>> @@ -270,12 +270,12 @@ superproject's "origin/main", but tracks the
>> submodule's "origin/main".
>>
>> -u <upstream>::
>> --set-upstream-to=<upstream>::
>> - Set up <branchname>'s tracking information so <upstream> is
>> - considered <branchname>'s upstream branch. If no <branchname>
>> + Set up <branch>'s tracking information so <upstream> is
>> + considered <branch>'s upstream branch. If no <branch>
>> is specified, then it defaults to the current branch.
>>
>> --unset-upstream::
>> - Remove the upstream information for <branchname>. If no branch
>> + Remove the upstream information for <branch>. If no branch
>> is specified it defaults to the current branch.
>>
>> --edit-description::
>> @@ -300,8 +300,8 @@ superproject's "origin/main", but tracks the
>> submodule's "origin/main".
>> Only list branches whose tips are not reachable from the
>> specified commit (HEAD if not specified). Implies `--list`.
>>
>> -<branchname>::
>> - The name of the branch to create or delete.
>> +<new-branch>::
>> + The name of the branch to create.
>> The new branch name must pass all checks defined by
>> linkgit:git-check-ref-format[1]. Some of these checks
>> may restrict the characters allowed in a branch name.
>> @@ -311,14 +311,10 @@ superproject's "origin/main", but tracks the
>> submodule's "origin/main".
>> given as a branch name, a commit-id, or a tag. If this
>> option is omitted, the current HEAD will be used instead.
>>
>> -<oldbranch>::
>> +<branch>::
>> The name of an existing branch. If this option is omitted,
>> the name of the current branch will be used instead.
>>
>> -<newbranch>::
>> - The new name for an existing branch. The same restrictions as for
>> - <branchname> apply.
>> -
>> --sort=<key>::
>> Sort based on the key given. Prefix `-` to sort in descending
>> order of the value. You may use the --sort=<key> option
^ permalink raw reply
* What's cooking in git.git (Feb 2024, #09; Tue, 27)
From: Junio C Hamano @ 2024-02-28 5:44 UTC (permalink / raw)
To: git
Here are the topics that have been cooking in my tree. Commits
prefixed with '+' are in 'next' (being in 'next' is a sign that a
topic is stable enough to be used and are candidate to be in a
future release). Commits prefixed with '-' are only in 'seen', and
aren't considered "accepted" at all and may be annotated with an URL
to a message that raises issues but they are no means exhaustive. A
topic without enough support may be discarded after a long period of
no activity (of course they can be resubmit when new interests
arise).
Copies of the source code to Git live in many repositories, and the
following is a list of the ones I push into or their mirrors. Some
repositories have only a subset of branches.
With maint, master, next, seen, todo:
git://git.kernel.org/pub/scm/git/git.git/
git://repo.or.cz/alt-git.git/
https://kernel.googlesource.com/pub/scm/git/git/
https://github.com/git/git/
https://gitlab.com/git-vcs/git/
With all the integration branches and topics broken out:
https://github.com/gitster/git/
Even though the preformatted documentation in HTML and man format
are not sources, they are published in these repositories for
convenience (replace "htmldocs" with "manpages" for the manual
pages):
git://git.kernel.org/pub/scm/git/git-htmldocs.git/
https://github.com/gitster/git-htmldocs.git/
Release tarballs are available at:
https://www.kernel.org/pub/software/scm/git/
--------------------------------------------------
[Graduated to 'master']
* ba/credential-test-clean-fix (2024-02-15) 1 commit
(merged to 'next' on 2024-02-19 at 290708b10a)
+ t/lib-credential: clean additional credential
(this branch is used by jk/t0303-clean.)
Test clean-up.
source: <pull.1664.git.1707959036807.gitgitgadget@gmail.com>
* bb/completion-no-grep-into-awk (2024-02-16) 1 commit
(merged to 'next' on 2024-02-19 at 8373f95424)
+ completion: use awk for filtering the config entries
Some parts of command line completion script (in contrib/) have
been micro-optimized.
source: <20240216171046.927552-1-dev+git@drbeat.li>
* cp/apply-core-filemode (2023-12-26) 3 commits
(merged to 'next' on 2024-02-07 at 089a3fbb86)
+ apply: code simplification
+ apply: correctly reverse patch's pre- and post-image mode bits
+ apply: ignore working tree filemode when !core.filemode
"git apply" on a filesystem without filemode support have learned
to take a hint from what is in the index for the path, even when
not working with the "--index" or "--cached" option, when checking
the executable bit match what is required by the preimage in the
patch.
cf. <xmqqzfwb53a9.fsf@gitster.g>
source: <20231226233218.472054-1-gitster@pobox.com>
* gt/at-is-synonym-for-head-in-add-patch (2024-02-13) 2 commits
(merged to 'next' on 2024-02-14 at cd901555d6)
+ add -p tests: remove PERL prerequisites
+ add-patch: classify '@' as a synonym for 'HEAD'
Teach "git checkout -p" and friends that "@" is a synonym for
"HEAD".
source: <20240211202035.7196-2-shyamthakkar001@gmail.com>
* jb/doc-interactive-singlekey-do-not-need-perl (2024-02-19) 1 commit
(merged to 'next' on 2024-02-19 at 9eda75497d)
+ doc: remove outdated information about interactive.singleKey
Doc clean-up.
source: <20240218030327.40453-1-julio.bacel@gmail.com>
* jc/am-whitespace-doc (2024-02-14) 1 commit
(merged to 'next' on 2024-02-19 at 492f0f9174)
+ doc: add shortcut to "am --whitespace=<action>"
"git am --help" now tells readers what actions are available in
"git am --whitespace=<action>", in addition to saying that the
option is passed through to the underlying "git apply".
source: <xmqqplwyvqby.fsf@gitster.g>
* jc/t9210-lazy-fix (2024-02-08) 1 commit
(merged to 'next' on 2024-02-13 at fb61ca2fba)
+ t9210: do not rely on lazy fetching to fail
(this branch is used by cc/rev-list-allow-missing-tips.)
Adjust use of "rev-list --missing" in an existing tests so that it
does not depend on a buggy failure mode.
source: <xmqq7cjemttr.fsf@gitster.g>
* jk/t0303-clean (2024-02-19) 2 commits
(merged to 'next' on 2024-02-19 at f57b65215f)
+ t0303: check that helper_test_clean removes all credentials
+ Merge branch 'ba/credential-test-clean-fix' into jk/t0303-clean
(this branch uses ba/credential-test-clean-fix.)
Test clean-up.
source: <20240217045814.GA539459@coredump.intra.peff.net>
* kh/column-reject-negative-padding (2024-02-13) 2 commits
(merged to 'next' on 2024-02-14 at c30c08e495)
+ column: guard against negative padding
+ column: disallow negative padding
"git column" has been taught to reject negative padding value, as
it would lead to nonsense behaviour including division by zero.
source: <cover.1707839454.git.code@khaugsbakk.name>
* km/mergetool-vimdiff-layout-fallback (2024-02-19) 1 commit
(merged to 'next' on 2024-02-19 at bf7f086f05)
+ mergetools: vimdiff: use correct tool's name when reading mergetool config
Variants of vimdiff learned to honor mergetool.<variant>.layout settings.
source: <20240217162718.21272-1-kipras@kipras.org>
* mh/libsecret-empty-password-fix (2024-02-19) 1 commit
(merged to 'next' on 2024-02-19 at b2e17695ca)
+ libsecret: retrieve empty password
Credential helper based on libsecret (in contrib/) has been updated
to handle an empty password correctly.
source: <pull.1676.v2.git.git.1708375258296.gitgitgadget@gmail.com>
* ps/ref-tests-update-even-more (2024-02-15) 7 commits
(merged to 'next' on 2024-02-15 at 064b2b4089)
+ t7003: ensure filter-branch prunes reflogs with the reftable backend
+ t2011: exercise D/F conflicts with HEAD with the reftable backend
+ t1405: remove unneeded cleanup step
+ t1404: make D/F conflict tests compatible with reftable backend
+ t1400: exercise reflog with gaps with reftable backend
+ t0410: convert tests to use DEFAULT_REPO_FORMAT prereq
+ t: move tests exercising the "files" backend
More tests that are marked as "ref-files only" have been updated to
improve test coverage of reftable backend.
source: <cover.1707985173.git.ps@pks.im>
* ps/reftable-backend (2024-02-07) 3 commits
(merged to 'next' on 2024-02-08 at ba1c4c52bb)
+ refs/reftable: fix leak when copying reflog fails
(merged to 'next' on 2024-02-07 at 1115200acb)
+ ci: add jobs to test with the reftable backend
+ refs: introduce reftable backend
(this branch is used by kn/for-all-refs and ps/reflog-list.)
Integrate the reftable code into the refs framework as a backend.
source: <cover.1707288261.git.ps@pks.im>
* ps/reftable-iteration-perf (2024-02-12) 7 commits
(merged to 'next' on 2024-02-12 at 6abaf58383)
+ reftable/reader: add comments to `table_iter_next()`
+ reftable/record: don't try to reallocate ref record name
+ reftable/block: swap buffers instead of copying
+ reftable/pq: allocation-less comparison of entry keys
+ reftable/merged: skip comparison for records of the same subiter
+ reftable/merged: allocation-less dropping of shadowed records
+ reftable/record: introduce function to compare records by key
(this branch is used by ps/reftable-iteration-perf-part2.)
The code to iterate over refs with the reftable backend has seen
some optimization.
source: <cover.1707726654.git.ps@pks.im>
* rj/tag-column-fix (2024-02-14) 1 commit
(merged to 'next' on 2024-02-19 at 9aa52b4ffb)
+ tag: error when git-column fails
"git tag --column" failed to check the exit status of its "git
column" invocation, which has been corrected.
source: <59df085d-0de8-45b1-9b8b-c69e91e56a1f@gmail.com>
* rs/use-xstrncmpz (2024-02-12) 1 commit
(merged to 'next' on 2024-02-12 at 37e5f0fc14)
+ use xstrncmpz()
Code clean-up.
source: <954b75d0-1504-4f57-b34e-e770a4b7b3ea@web.de>
--------------------------------------------------
[New Topics]
* cw/git-std-lib (2024-02-22) 3 commits
- test-stdlib: show that git-std-lib is independent
- git-std-lib: introduce Git Standard Library
- pager: include stdint.h because uintmax_t is used
Split libgit.a out to a separate git-std-lib tor easier reuse.
Needs review.
source: <cover.1696021277.git.jonathantanmy@google.com>
* js/merge-base-with-missing-commit (2024-02-27) 11 commits
- repo_get_merge_bases_many_dirty(): pass on errors from `merge_bases_many()`
- repo_get_merge_bases_many(): pass on errors from `merge_bases_many()`
- get_octopus_merge_bases(): pass on errors from `merge_bases_many()`
- repo_get_merge_bases(): pass on errors from `merge_bases_many()`
- get_merge_bases_many_0(): pass on errors from `merge_bases_many()`
- merge_bases_many(): pass on errors from `paint_down_to_common()`
- commit-reach: start reporting errors in `paint_down_to_common()`
- Prepare `paint_down_to_common()` for handling shallow commits
- Start reporting missing commits in `repo_in_merge_bases_many()`
- Prepare `repo_in_merge_bases_many()` to optionally expect missing commits
- paint_down_to_common: plug two memory leaks
Make sure failure return from merge_bases_many() is properly caught.
Needs review.
source: <pull.1657.v3.git.1709040497.gitgitgadget@gmail.com>
* tb/multi-pack-verbatim-reuse (2024-02-23) 1 commit
(merged to 'next' on 2024-02-23 at 8ee07f1da4)
+ Documentation/config/pack.txt: fix broken AsciiDoc mark-up
Docfix.
Will merge to 'master'.
source: <72bb58e5f3b8a5a622394c5ff40426156e122580.1708720255.git.me@ttaylorr.com>
* eg/add-uflags (2024-02-24) 1 commit
- add: use unsigned type for collection of bits
Code clean-up practice.
cf. <CAP8UFD3qR8E0gvUQtzzkLPWv4Db45kFS4pEqHKQr5siciVJ-zQ@mail.gmail.com>
source: <20240224112638.72257-2-giganteeugenio2@gmail.com>
* jc/doc-compat-util (2024-02-27) 1 commit
(merged to 'next' on 2024-02-27 at a838805d8c)
+ doc: clarify the wording on <git-compat-util.h> requirement
Clarify wording in the CodingGuidelines that requires <git-compat-util.h>
to be the first header file.
Will merge to 'master'.
source: <xmqqle76kdpr.fsf_-_@gitster.g>
* jc/no-include-of-compat-util-from-headers (2024-02-24) 1 commit
(merged to 'next' on 2024-02-26 at 85857c09d9)
+ compat: drop inclusion of <git-compat-util.h>
Header file clean-up.
Will merge to 'master'.
source: <xmqqwmqtli18.fsf@gitster.g>
* jk/reflog-special-cases-fix (2024-02-26) 3 commits
(merged to 'next' on 2024-02-27 at e9fbe29d06)
+ read_ref_at(): special-case ref@{0} for an empty reflog
+ get_oid_basic(): special-case ref@{n} for oldest reflog entry
+ Revert "refs: allow @{n} to work with n-sized reflog"
The logic to access reflog entries by date and number had ugly
corner cases at the boundaries, which have been cleaned up.
Will merge to 'master'.
source: <20240226100010.GA1214708@coredump.intra.peff.net>
* jk/textconv-cache-outside-repo-fix (2024-02-26) 1 commit
(merged to 'next' on 2024-02-26 at d4a81531ef)
+ userdiff: skip textconv caching when not in a repository
The code incorrectly attempted to use textconv cache when asked,
even when we are not running in a repository, which has been
corrected.
Will merge to 'master'.
source: <20240226102729.GB2685773@coredump.intra.peff.net>
* js/remove-cruft-files (2024-02-26) 1 commit
(merged to 'next' on 2024-02-26 at c6491c1c5d)
+ neue: remove a bogus empty file
Remove an empty file that shouldn't have been added in the first
place.
Will merge to 'master'.
source: <pull.1674.git.1708958183225.gitgitgadget@gmail.com>
* jt/commit-redundant-scissors-fix (2024-02-27) 2 commits
- commit: unify logic to avoid multiple scissors lines when merging
- commit: avoid redundant scissor line with --cleanup=scissors -v
"git commit -v --cleanup=scissors" used to add the scissors line
twice in the log message buffer, which has been corrected.
Comments?
source: <Zd2eLxPelxvP8FDk@localhost>
* pb/ort-make-submodule-conflict-message-an-advice (2024-02-26) 1 commit
(merged to 'next' on 2024-02-27 at abe2ab5ed7)
+ merge-ort: turn submodule conflict suggestions into an advice
When a merge conflicted at a submodule, merge-ort backend used to
unconditionally give a lengthy message to suggest how to resolve
it. Now the message can be squelched as an advice message.
Will merge to 'master'.
source: <pull.1661.v2.git.git.1708954048301.gitgitgadget@gmail.com>
* rj/complete-worktree-paths-fix (2024-02-27) 1 commit
- completion: fix __git_complete_worktree_paths
The logic to complete the command line arguments to "git worktree"
subcommand (in contrib/) has been updated to correctly honor things
like "git -C dir" etc.
Comments?
source: <b8f09e20-d0d3-4e0b-afe2-31affeb61052@gmail.com>
* rs/fetch-simplify-with-starts-with (2024-02-26) 1 commit
(merged to 'next' on 2024-02-27 at 84bba0a921)
+ fetch: convert strncmp() with strlen() to starts_with()
Code simplification.
Will merge to 'master'.
source: <cb94b938-03f9-4dd3-84c1-f5244ca81be3@web.de>
* rs/name-rev-with-mempool (2024-02-26) 2 commits
(merged to 'next' on 2024-02-27 at b10b58ad64)
+ name-rev: use mem_pool_strfmt()
+ mem-pool: add mem_pool_strfmt()
Many small allocations "git name-rev" makes have been updated to
allocate from a mem-pool.
Will merge to 'master'.
source: <20240225113947.89357-1-l.s.r@web.de>
* rs/submodule-prefix-simplify (2024-02-26) 1 commit
(merged to 'next' on 2024-02-27 at c6051f9f6b)
+ submodule: use strvec_pushf() for --submodule-prefix
Code simplification.
Will merge to 'master'.
source: <8cd983fb-32b9-41c6-a9e7-a485b190488c@web.de>
* rs/t-ctype-simplify (2024-02-26) 3 commits
- t-ctype: do one test per class and char
- t-ctype: avoid duplicating class names
- t-ctype: allow NUL anywhere in the specification string
Code simplification to one unit-test program.
Comments?
source: <20240225112722.89221-1-l.s.r@web.de>
* sg/upload-pack-error-message-fix (2024-02-26) 1 commit
(merged to 'next' on 2024-02-27 at 7cd7a4c4d8)
+ upload-pack: don't send null character in abort message to the client
An error message from "git upload-pack", which responds to "git
fetch" requests, had a trialing NUL in it, which has been
corrected.
Will merge to 'master'.
source: <20240225183452.1939334-1-szeder.dev@gmail.com>
* ak/rebase-autosquash (2024-02-27) 1 commit
(merged to 'next' on 2024-02-27 at 1a37c5ed5e)
+ rebase: fix typo in autosquash documentation
Typofix.
Will merge to 'master'.
source: <pull.1676.git.1709015578890.gitgitgadget@gmail.com>
* ps/reftable-repo-init-fix (2024-02-27) 2 commits
- refs/reftable: don't fail empty transactions in repo without HEAD
- Merge branch 'ps/remote-helper-repo-initialization-fix' into ps/reftable-repo-init-fix
(this branch uses ps/remote-helper-repo-initialization-fix.)
Clear the fallout from a fix for 2.44 regression.
Will merge to 'next'?
source: <95be968e10bd02c64448786e690bbefe5c082577.1709041721.git.ps@pks.im>
* ps/remote-helper-repo-initialization-fix (2024-02-27) 1 commit
- builtin/clone: allow remote helpers to detect repo
(this branch is used by ps/reftable-repo-init-fix.)
A custom remote helper no longer cannot access the newly created
repository during "git clone", which is a regression in Git 2.44.
This has been corrected.
Will merge to 'next'?
source: <9d888adf92e9a8af7c18847219f97d3e595e3e36.1709041721.git.ps@pks.im>
* pw/rebase-i-ignore-cherry-pick-help-environment (2024-02-27) 1 commit
- rebase -i: stop setting GIT_CHERRY_PICK_HELP
Code simplification by getting rid of code that sets an environment
variable that is no longer used.
Comments?
source: <pull.1678.git.1709042783847.gitgitgadget@gmail.com>
--------------------------------------------------
[Cooking]
* ps/difftool-dir-diff-exit-code (2024-02-20) 1 commit
(merged to 'next' on 2024-02-21 at a7bbef5a5f)
+ git-difftool--helper: honor `--trust-exit-code` with `--dir-diff`
"git difftool --dir-diff" learned to honor the "--trust-exit-code"
option; it used to always exit with 0 and signalled success.
Will merge to 'master'.
source: <0fac668f8fc021af9f9c4df5134da59816307ccc.1708423309.git.ps@pks.im>
* ds/doc-send-email-capitalization (2024-02-20) 1 commit
(merged to 'next' on 2024-02-21 at c4aac4b993)
+ documentation: send-email: use camel case consistently
Doc update.
Will merge to 'master'.
source: <88f1fe08c3047e14090957093ee8d98b0f60cb6c.1708467601.git.dsimic@manjaro.org>
* ja/docfixes (2024-02-20) 3 commits
(merged to 'next' on 2024-02-21 at 6d778ca672)
+ doc: end sentences with full-stop
+ doc: close unclosed angle-bracket of a placeholder in git-clone doc
+ doc: git-rev-parse: enforce command-line description syntax
Doc update.
Will merge to 'master'.
source: <pull.1670.git.1708468374.gitgitgadget@gmail.com>
* hs/rebase-not-in-progress (2024-02-21) 1 commit
(merged to 'next' on 2024-02-23 at ce53f5243f)
+ rebase: make warning less passive aggressive
Error message update.
Will merge to 'master'.
source: <pull.1669.v2.git.1708537097448.gitgitgadget@gmail.com>
* jw/remote-doc-typofix (2024-02-21) 1 commit
(merged to 'next' on 2024-02-23 at fe95873cfa)
+ git-remote.txt: fix typo
Docfix.
Will merge to 'master'.
source: <20240221083554.5255-1-jwilk@jwilk.net>
* ja/doc-placeholders-markup-rules (2024-02-21) 1 commit
(merged to 'next' on 2024-02-23 at b6761ceeac)
+ doc: clarify the format of placeholders
The way placeholders are to be marked-up in documentation have been
specified; use "_<placeholder>_" to typeset the word inside a pair
of <angle-brakets> emphasized.
Will merge to 'master'.
source: <pull.1671.git.1708550340094.gitgitgadget@gmail.com>
* jc/doc-add-placeholder-fix (2024-02-21) 1 commit
(merged to 'next' on 2024-02-23 at 6950ff216b)
+ doc: apply the new placeholder rules to git-add documentation
Practice the new mark-up rule for <placeholders> with "git add"
documentation page.
Will merge to 'master'.
source: <xmqqbk89molz.fsf@gitster.g>
* as/option-names-in-messages (2024-02-16) 5 commits
- revision.c: trivial fix to message
- builtin/clone.c: trivial fix of message
- builtin/remote.c: trivial fix of error message
- transport-helper.c: trivial fix of error message
- rebase: trivial fix of error message
Error message updates.
Expecting a reroll.
source: <20240216101647.28837-1-ash@kambanaria.org>
* ps/reflog-list (2024-02-21) 9 commits
(merged to 'next' on 2024-02-23 at 7413632239)
+ builtin/reflog: introduce subcommand to list reflogs
+ refs: stop resolving ref corresponding to reflogs
+ refs: drop unused params from the reflog iterator callback
+ refs: always treat iterators as ordered
+ refs/files: sort merged worktree and common reflogs
+ refs/files: sort reflogs returned by the reflog iterator
+ dir-iterator: support iteration in sorted order
+ dir-iterator: pass name to `prepare_next_entry_data()` directly
+ Merge branch 'ps/reftable-backend' into ps/reflog-list
"git reflog" learned a "list" subcommand that enumerates known reflogs.
Will merge to 'master'.
source: <cover.1708518982.git.ps@pks.im>
* jh/fsmonitor-icase-corner-case-fix (2024-02-26) 14 commits
- fsmonitor: support case-insensitive events
- fsmonitor: refactor bit invalidation in refresh callback
- fsmonitor: trace the new invalidated cache-entry count
- fsmonitor: return invalided cache-entry count on non-directory event
- fsmonitor: remove custom loop from non-directory path handler
- fsmonitor: return invalidated cache-entry count on directory event
- fsmonitor: move untracked-cache invalidation into helper functions
- fsmonitor: refactor untracked-cache invalidation
- dir: create untracked_cache_invalidate_trimmed_path()
- fsmonitor: refactor refresh callback for non-directory events
- fsmonitor: clarify handling of directory events in callback helper
- fsmonitor: refactor refresh callback on directory events
- t7527: add case-insensitve test for FSMonitor
- name-hash: add index_dir_find()
FSMonitor client code was confused when FSEvents were given in a
different case on a case-insensitive filesystem, which has been
corrected.
Comments?
source: <pull.1662.v3.git.1708983565.gitgitgadget@gmail.com>
* ps/reftable-iteration-perf-part2 (2024-02-14) 13 commits
- reftable: allow inlining of a few functions
- reftable/record: decode keys in place
- reftable/record: reuse refname when copying
- reftable/record: reuse refname when decoding
- reftable/merged: avoid duplicate pqueue emptiness check
- reftable/merged: circumvent pqueue with single subiter
- reftable/merged: handle subiter cleanup on close only
- reftable/merged: remove unnecessary null check for subiters
- reftable/merged: make subiters own their records
- reftable/merged: advance subiter on subsequent iteration
- reftable/merged: make `merged_iter` structure private
- reftable/pq: use `size_t` to track iterator index
- Merge branch 'ps/reftable-iteration-perf' into ps/reftable-iteration-perf-part2
The code to iterate over refs with the reftable backend has seen
some optimization.
Needs review.
source: <cover.1707895758.git.ps@pks.im>
* cp/t9146-use-test-path-helpers (2024-02-14) 1 commit
(merged to 'next' on 2024-02-21 at 0b8356ef33)
+ t9146: replace test -d/-e/-f with appropriate test_path_is_* function
Test script clean-up.
Will merge to 'master'.
source: <pull.1661.v3.git.1707933048210.gitgitgadget@gmail.com>
* js/cmake-with-test-tool (2024-02-23) 2 commits
- cmake: let `test-tool` run the unit tests, too
- Merge branch 'js/unit-test-suite-runner' into js/cmake-with-test-tool
(this branch uses js/unit-test-suite-runner.)
"test-tool" is now built in CMake build to also run the unit tests.
May want to roll it into the base topic.
source: <pull.1666.git.1708038924522.gitgitgadget@gmail.com>
* kn/for-all-refs (2024-02-23) 6 commits
(merged to 'next' on 2024-02-27 at aef2406cca)
+ for-each-ref: add new option to include root refs
+ ref-filter: rename 'FILTER_REFS_ALL' to 'FILTER_REFS_REGULAR'
+ refs: introduce `refs_for_each_include_root_refs()`
+ refs: extract out `loose_fill_ref_dir_regular_file()`
+ refs: introduce `is_pseudoref()` and `is_headref()`
+ Merge branch 'ps/reftable-backend' into kn/for-all-refs
"git for-each-ref" filters its output with prefixes given from the
command line, but it did not honor an empty string to mean "pass
everything", which has been corrected.
Will merge to 'master'.
source: <20240223100112.44127-1-karthik.188@gmail.com>
* jc/no-lazy-fetch (2024-02-27) 3 commits
- git: extend --no-lazy-fetch to work across subprocesses
- git: document GIT_NO_REPLACE_OBJECTS environment variable
(merged to 'next' on 2024-02-13 at 7c7136e547)
+ git: --no-lazy-fetch option
"git --no-lazy-fetch cmd" allows to run "cmd" while disabling lazy
fetching of objects from the promisor remote, which may be handy
for debugging.
Will merge to 'next'?
source: <xmqq1q8xx38i.fsf@gitster.g>
source: <xmqq1q9cl3xv.fsf@gitster.g>
source: <xmqq1q9mmtpw.fsf@gitster.g>
* js/unit-test-suite-runner (2024-02-23) 8 commits
- ci: use test-tool as unit test runner on Windows
- t/Makefile: run unit tests alongside shell tests
- unit tests: add rule for running with test-tool
- test-tool run-command testsuite: support unit tests
- test-tool run-command testsuite: remove hardcoded filter
- test-tool run-command testsuite: get shell from env
- t0080: turn t-basic unit test into a helper
- Merge branch 'jk/unit-tests-buildfix' into js/unit-test-suite-runner
(this branch is used by js/cmake-with-test-tool.)
The "test-tool" has been taught to run testsuite tests in parallel,
bypassing the need to use the "prove" tool.
Needs review.
source: <cover.1708728717.git.steadmon@google.com>
* cc/rev-list-allow-missing-tips (2024-02-14) 4 commits
(merged to 'next' on 2024-02-21 at 9b63eec23f)
+ rev-list: allow missing tips with --missing=[print|allow*]
+ t6022: fix 'test' style and 'even though' typo
+ oidset: refactor oidset_insert_from_set()
+ revision: clarify a 'return NULL' in get_reference()
"git rev-list --missing=print" has learned to optionally take
"--allow-missing-tips", which allows the objects at the starting
points to be missing.
Will merge to 'master'.
source: <20240214142513.4002639-1-christian.couder@gmail.com>
* js/merge-tree-3-trees (2024-02-23) 7 commits
- fill_tree_descriptor(): mark error message for translation
- cache-tree: avoid an unnecessary check
- Always check `parse_tree*()`'s return value
- t4301: verify that merge-tree fails on missing blob objects
- merge-ort: do check `parse_tree()`'s return value
- merge-tree: fail with a non-zero exit code on missing tree objects
(merged to 'next' on 2024-01-30 at 0c77b04e59)
+ merge-tree: accept 3 trees as arguments
"git merge-tree" has learned that the three trees involved in the
3-way merge only need to be trees, not necessarily commits.
Will merge to 'next'?
source: <pull.1647.git.1706277694231.gitgitgadget@gmail.com>
source: <pull.1651.v4.git.1708677266.gitgitgadget@gmail.com>
* rj/complete-reflog (2024-01-26) 4 commits
- completion: reflog show <log-options>
- completion: reflog with implicit "show"
- completion: introduce __git_find_subcommand
- completion: introduce __gitcomp_subcommand
The command line completion script (in contrib/) learned to
complete "git reflog" better.
Expecting a reroll.
cf. <dd106d87-3363-426a-90a2-16e1f2d04661@gmail.com>
source: <98daf977-dbad-4d3b-a293-6a769895088f@gmail.com>
* ml/log-merge-with-cherry-pick-and-other-pseudo-heads (2024-02-27) 2 commits
- revision: implement `git log --merge` also for rebase/cherry-pick/revert
- revision: ensure MERGE_HEAD is a ref in prepare_show_merge
"git log --merge" learned to pay attention to CHERRY_PICK_HEAD and
other kinds of *_HEAD pseudorefs.
Will merge to 'next'?
source: <20240225-ml-log-merge-with-cherry-pick-and-other-pseudo-heads-v5-0-af1ef2d9e44d@gmail.com>
* bk/complete-dirname-for-am-and-format-patch (2024-01-12) 1 commit
- completion: dir-type optargs for am, format-patch
Command line completion support (in contrib/) has been
updated for a few commands to complete directory names where a
directory name is expected.
Expecting a reroll.
cf. <40c3a824-a961-490b-94d4-4eb23c8f713d@gmail.com>
source: <d37781c3-6af2-409b-95a8-660a9b92d20b@smtp-relay.sendinblue.com>
* bk/complete-send-email (2024-01-12) 1 commit
- completion: don't complete revs when --no-format-patch
Command line completion support (in contrib/) has been taught to
avoid offering revision names as candidates to "git send-email" when
the command is used to send pre-generated files.
Expecting a reroll.
cf. <CAC4O8c88Z3ZqxH2VVaNPpEGB3moL5dJcg3cOWuLWwQ_hLrJMtA@mail.gmail.com>
source: <a718b5ee-afb0-44bd-a299-3208fac43506@smtp-relay.sendinblue.com>
* la/trailer-api (2024-02-16) 9 commits
(merged to 'next' on 2024-02-21 at 631e28bbbc)
+ format_trailers_from_commit(): indirectly call trailer_info_get()
+ format_trailer_info(): move "fast path" to caller
+ format_trailers(): use strbuf instead of FILE
+ trailer_info_get(): reorder parameters
+ trailer: start preparing for formatting unification
+ trailer: move interpret_trailers() to interpret-trailers.c
+ trailer: prepare to expose functions as part of API
+ shortlog: add test for de-duplicating folded trailers
+ trailer: free trailer_info _after_ all related usage
Code clean-up.
Will merge to 'master'.
source: <pull.1632.v5.git.1708124950.gitgitgadget@gmail.com>
* tb/path-filter-fix (2024-01-31) 16 commits
- bloom: introduce `deinit_bloom_filters()`
- commit-graph: reuse existing Bloom filters where possible
- object.h: fix mis-aligned flag bits table
- commit-graph: new Bloom filter version that fixes murmur3
- commit-graph: unconditionally load Bloom filters
- bloom: prepare to discard incompatible Bloom filters
- bloom: annotate filters with hash version
- repo-settings: introduce commitgraph.changedPathsVersion
- t4216: test changed path filters with high bit paths
- t/helper/test-read-graph: implement `bloom-filters` mode
- bloom.h: make `load_bloom_filter_from_graph()` public
- t/helper/test-read-graph.c: extract `dump_graph_info()`
- gitformat-commit-graph: describe version 2 of BDAT
- commit-graph: ensure Bloom filters are read with consistent settings
- revision.c: consult Bloom filters for root commits
- t/t4216-log-bloom.sh: harden `test_bloom_filters_not_used()`
The Bloom filter used for path limited history traversal was broken
on systems whose "char" is unsigned; update the implementation and
bump the format version to 2.
Waiting for a final ack?
cf. <ZcFjkfbsBfk7JQIH@nand.local>
source: <cover.1706741516.git.me@ttaylorr.com>
* eb/hash-transition (2023-10-02) 30 commits
- t1016-compatObjectFormat: add tests to verify the conversion between objects
- t1006: test oid compatibility with cat-file
- t1006: rename sha1 to oid
- test-lib: compute the compatibility hash so tests may use it
- builtin/ls-tree: let the oid determine the output algorithm
- object-file: handle compat objects in check_object_signature
- tree-walk: init_tree_desc take an oid to get the hash algorithm
- builtin/cat-file: let the oid determine the output algorithm
- rev-parse: add an --output-object-format parameter
- repository: implement extensions.compatObjectFormat
- object-file: update object_info_extended to reencode objects
- object-file-convert: convert commits that embed signed tags
- object-file-convert: convert commit objects when writing
- object-file-convert: don't leak when converting tag objects
- object-file-convert: convert tag objects when writing
- object-file-convert: add a function to convert trees between algorithms
- object: factor out parse_mode out of fast-import and tree-walk into in object.h
- cache: add a function to read an OID of a specific algorithm
- tag: sign both hashes
- commit: export add_header_signature to support handling signatures on tags
- commit: convert mergetag before computing the signature of a commit
- commit: write commits for both hashes
- object-file: add a compat_oid_in parameter to write_object_file_flags
- object-file: update the loose object map when writing loose objects
- loose: compatibilty short name support
- loose: add a mapping between SHA-1 and SHA-256 for loose objects
- repository: add a compatibility hash algorithm
- object-names: support input of oids in any supported hash
- oid-array: teach oid-array to handle multiple kinds of oids
- object-file-convert: stubs for converting from one object format to another
Teach a repository to work with both SHA-1 and SHA-256 hash algorithms.
Will merge to and cook in 'next'?
cf. <xmqqv86z5359.fsf@gitster.g>
source: <878r8l929e.fsf@gmail.froward.int.ebiederm.org>
* jc/rerere-cleanup (2023-08-25) 4 commits
- rerere: modernize use of empty strbuf
- rerere: try_merge() should use LL_MERGE_ERROR when it means an error
- rerere: fix comment on handle_file() helper
- rerere: simplify check_one_conflict() helper function
Code clean-up.
Not ready to be reviewed yet.
source: <20230824205456.1231371-1-gitster@pobox.com>
--------------------------------------------------
[Discarded]
* mh/credential-oauth-refresh-token-with-osxkeychain (2024-02-14) 1 commit
. credential/osxkeychain: store new attributes
OAuth refresh tokens and password expiry timestamps are now stored
in the osxkeychain backend , just the way libsecret and wincred
backends of the credential subsystem do.
Retracted.
cf. <CAGJzqsknN_RmYeT0xcn4cTLcJhsxSOUC6ppRVepxMDf3day5Fw@mail.gmail.com>
source: <pull.1663.git.1707860618119.gitgitgadget@gmail.com>
^ permalink raw reply
* Allow setting diff.worddiff=color via gitconfig
From: Olliver Schinagl @ 2024-02-28 8:54 UTC (permalink / raw)
To: git
Currently, the only way to set `word-diff=color` is through alias. It
would be much nicer of course if we could do
[diff]
worddiff=color
in git-config of course.
Thank you,
Olliver
^ permalink raw reply
* [PATCH] revision: fix --missing=[print|allow*] for annotated tags
From: Christian Couder @ 2024-02-28 9:10 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Patrick Steinhardt, John Cai, Linus Arver,
Eric Sunshine, Christian Couder, Christian Couder
In-Reply-To: <20240214142513.4002639-1-christian.couder@gmail.com>
In 9830926c7d (rev-list: add commit object support in `--missing`
option, 2023-10-27) we fixed the `--missing` option in `git rev-list`
so that it works with missing commits, not just blobs/trees.
Unfortunately, such a command was still failing with a "fatal: bad
object <oid>" if it was passed a missing commit, blob or tree as an
argument (before the rev walking even begins). This was fixed in a
recent commit.
That fix still doesn't work when an argument passed to the command is
an annotated tag pointing to a missing commit though. In that case
`git rev-list --missing=...` still errors out with a "fatal: bad
object <oid>" error where <oid> is the object ID of the missing
commit.
Let's fix this issue, and also, while at it, let's add tests not just
for annotated tags but also for regular tags and branches.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
This is a follow up to cc/rev-list-allow-missing-tips which is in
'next' and scheduled to be merged to 'master'. So it depends on that
branch.
revision.c | 8 +++++++-
t/t6022-rev-list-missing.sh | 24 ++++++++++++++++++------
2 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/revision.c b/revision.c
index 0c7266b1eb..8f0d638af1 100644
--- a/revision.c
+++ b/revision.c
@@ -419,15 +419,21 @@ static struct commit *handle_commit(struct rev_info *revs,
*/
while (object->type == OBJ_TAG) {
struct tag *tag = (struct tag *) object;
+ struct object_id *oid;
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
- object = parse_object(revs->repo, get_tagged_oid(tag));
+ oid = get_tagged_oid(tag);
+ object = parse_object(revs->repo, oid);
if (!object) {
if (revs->ignore_missing_links || (flags & UNINTERESTING))
return NULL;
if (revs->exclude_promisor_objects &&
is_promisor_object(&tag->tagged->oid))
return NULL;
+ if (revs->do_not_die_on_missing_objects && oid) {
+ oidset_insert(&revs->missing_commits, oid);
+ return NULL;
+ }
die("bad object %s", oid_to_hex(&tag->tagged->oid));
}
object->flags |= flags;
diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh
index 78387eebb3..127180e1c9 100755
--- a/t/t6022-rev-list-missing.sh
+++ b/t/t6022-rev-list-missing.sh
@@ -10,7 +10,10 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'create repository and alternate directory' '
test_commit 1 &&
test_commit 2 &&
- test_commit 3
+ test_commit 3 &&
+ git tag -m "tag message" annot_tag HEAD~1 &&
+ git tag regul_tag HEAD~1 &&
+ git branch a_branch HEAD~1
'
# We manually corrupt the repository, which means that the commit-graph may
@@ -78,7 +81,7 @@ do
done
done
-for missing_tip in "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t"
+for missing_tip in "annot_tag" "regul_tag" "a_branch" "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t"
do
# We want to check that things work when both
# - all the tips passed are missing (case existing_tip = ""), and
@@ -88,9 +91,6 @@ do
for action in "allow-any" "print"
do
test_expect_success "--missing=$action with tip '$missing_tip' missing and tip '$existing_tip'" '
- oid="$(git rev-parse $missing_tip)" &&
- path=".git/objects/$(test_oid_to_path $oid)" &&
-
# Before the object is made missing, we use rev-list to
# get the expected oids.
if test "$existing_tip" = "HEAD"
@@ -109,11 +109,23 @@ do
echo $(git rev-parse HEAD:2.t) >>expect.raw
fi &&
+ missing_oid="$(git rev-parse $missing_tip)" &&
+
+ if test "$missing_tip" = "annot_tag"
+ then
+ oid="$(git rev-parse $missing_tip^{commit})" &&
+ echo "$missing_oid" >>expect.raw
+ else
+ oid="$missing_oid"
+ fi &&
+
+ path=".git/objects/$(test_oid_to_path $oid)" &&
+
mv "$path" "$path.hidden" &&
test_when_finished "mv $path.hidden $path" &&
git rev-list --missing=$action --objects --no-object-names \
- $oid $existing_tip >actual.raw &&
+ $missing_oid $existing_tip >actual.raw &&
# When the action is to print, we should also add the missing
# oid to the expect list.
--
2.44.0.297.g8ee07f1da4
^ permalink raw reply related
* [PATCH v4 00/11] The merge-base logic vs missing commit objects
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git; +Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin
In-Reply-To: <pull.1657.v3.git.1709040497.gitgitgadget@gmail.com>
This patch series is in the same spirit as what I proposed in
https://lore.kernel.org/git/pull.1651.git.1707212981.gitgitgadget@gmail.com/,
where I tackled missing tree objects. This here patch series tackles missing
commit objects instead: Git's merge-base logic handles these missing commit
objects as if there had not been any commit object at all, i.e. if two
commits' merge base commit is missing, they will be treated as if they had
no common commit history at all, which is a bug. Those commit objects should
not be missing, of course, i.e. this is only a problem in corrupt
repositories.
This patch series is a bit more tricky than the "missing tree objects" one,
though: The function signature of quite a few functions need to be changed
to allow callers to discern between "missing commit object" vs "no
merge-base found".
And of course it gets even more tricky because in shallow and partial clones
we expect commit objects to be missing, and that must not be treated like an
error but the existing logic is actually desirable in those scenarios.
I am deeply sorry both about the length of this patch series as well as
having to lean so heavily on reviews on the Git mailing list.
Changes since v3:
* Reworded some hard-to-understand paragraphs in the commit message of
"Prepare paint_down_to_common() for handling shallow commits" (4/11).
* Changed an inconsistent paint_down_to_common() < 0 to simply test whether
the return value is non-zero.
* Changed all commit messages to have proper <area>: prefixes.
Changes since v2:
* Moved a hunk from 3/11 to 2/11 that lets the repo_in_merge_bases_many()
function return an error if non-existing commits have been passed to it,
unless the ignore_missing_commits parameter is non-zero.
* The end result is tree-same.
Changes since v1:
* Addressed a lot of memory leaks.
* Reordered patch 2 and 3 to render the commit message's comment about
unchanged behavior true.
* Fixed the incorrectly converted condition in the merge_submodule()
function.
* The last patch ("paint_down_to_common(): special-case shallow/partial
clones") was dropped because it is not actually necessary, and the
explanation for that was added to the commit message of "Prepare
paint_down_to_common() for handling shallow commits".
* An inconsistently-named variable i was renamed to be consistent with the
other variables called ret.
Johannes Schindelin (11):
commit-reach(paint_down_to_common): plug two memory leaks
commit-reach(repo_in_merge_bases_many): optionally expect missing
commits
commit-reach(repo_in_merge_bases_many): report missing commits
commit-reach(paint_down_to_common): prepare for handling shallow
commits
commit-reach(paint_down_to_common): start reporting errors
commit-reach(merge_bases_many): pass on "missing commits" errors
commit-reach(get_merge_bases_many_0): pass on "missing commits" errors
commit-reach(repo_get_merge_bases): pass on "missing commits" errors
commit-reach(get_octopus_merge_bases): pass on "missing commits"
errors
commit-reach(repo_get_merge_bases_many): pass on "missing commits"
errors
commit-reach(repo_get_merge_bases_many_dirty): pass on errors
bisect.c | 7 +-
builtin/branch.c | 12 +-
builtin/fast-import.c | 6 +-
builtin/fetch.c | 2 +
builtin/log.c | 30 +++--
builtin/merge-base.c | 23 +++-
builtin/merge-tree.c | 5 +-
builtin/merge.c | 26 ++--
builtin/pull.c | 9 +-
builtin/rebase.c | 8 +-
builtin/receive-pack.c | 6 +-
builtin/rev-parse.c | 5 +-
commit-reach.c | 209 ++++++++++++++++++++-----------
commit-reach.h | 26 ++--
commit.c | 7 +-
diff-lib.c | 5 +-
http-push.c | 5 +-
log-tree.c | 5 +-
merge-ort.c | 87 +++++++++++--
merge-recursive.c | 58 +++++++--
notes-merge.c | 3 +-
object-name.c | 7 +-
remote.c | 2 +-
revision.c | 12 +-
sequencer.c | 8 +-
shallow.c | 21 ++--
submodule.c | 7 +-
t/helper/test-reach.c | 11 +-
t/t4301-merge-tree-write-tree.sh | 12 ++
29 files changed, 441 insertions(+), 183 deletions(-)
base-commit: 564d0252ca632e0264ed670534a51d18a689ef5d
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1657%2Fdscho%2Fmerge-base-and-missing-objects-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1657/dscho/merge-base-and-missing-objects-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/1657
Range-diff vs v3:
1: 6e4e409cd43 ! 1: 647fa2ed5c5 paint_down_to_common: plug two memory leaks
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- paint_down_to_common: plug two memory leaks
+ commit-reach(paint_down_to_common): plug two memory leaks
When a commit is missing, we return early (currently pretending that no
merge basis could be found in that case). At that stage, it is possible
2: f68d77c6123 ! 2: 48e69bf7229 Prepare `repo_in_merge_bases_many()` to optionally expect missing commits
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- Prepare `repo_in_merge_bases_many()` to optionally expect missing commits
+ commit-reach(repo_in_merge_bases_many): optionally expect missing commits
Currently this function treats unrelated commit histories the same way
as commit histories with missing commit objects.
3: 0aaa224b5db ! 3: 1938b317a49 Start reporting missing commits in `repo_in_merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- Start reporting missing commits in `repo_in_merge_bases_many()`
+ commit-reach(repo_in_merge_bases_many): report missing commits
Some functions in Git's source code follow the convention that returning
a negative value indicates a fatal error, e.g. repository corruption.
4: 84e7fbc07e0 ! 4: 837aa5a89c6 Prepare `paint_down_to_common()` for handling shallow commits
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- Prepare `paint_down_to_common()` for handling shallow commits
+ commit-reach(paint_down_to_common): prepare for handling shallow commits
When `git fetch --update-shallow` needs to test for commit ancestry, it
can naturally run into a missing object (e.g. if it is a parent of a
- shallow commit). To accommodate, the merge base logic will need to be
- able to handle this situation gracefully.
+ shallow commit). For the purpose of `--update-shallow`, this needs to be
+ treated as if the child commit did not even have that parent, i.e. the
+ commit history needs to be clamped.
- Currently, that logic pretends that a missing parent commit is
- equivalent to a missing parent commit, and for the purpose of
- `--update-shallow` that is exactly what we need it to do.
+ For all other scenarios, clamping the commit history is actually a bug,
+ as it would hide repository corruption (for an analysis regarding
+ shallow and partial clones, see the analysis further down).
- Therefore, let's introduce a flag to indicate when that is precisely the
- logic we want.
+ Add a flag to optionally ask the function to ignore missing commits, as
+ `--update-shallow` needs it to, while detecting missing objects as a
+ repository corruption error by default.
- We need a flag, and cannot rely on `is_repository_shallow()` to indicate
- that situation, because that function would return 0: There may not
- actually be a `shallow` file, as demonstrated e.g. by t5537.10 ("add new
- shallow root with receive.updateshallow on") and t5538.4 ("add new
- shallow root with receive.updateshallow on").
+ This flag is needed, and cannot replaced by `is_repository_shallow()` to
+ indicate that situation, because that function would return 0 in the
+ `--update-shallow` scenario: There is not actually a `shallow` file in
+ that scenario, as demonstrated e.g. by t5537.10 ("add new shallow root
+ with receive.updateshallow on") and t5538.4 ("add new shallow root with
+ receive.updateshallow on").
Note: shallow commits' parents are set to `NULL` internally already,
therefore there is no need to special-case shallow repositories here, as
5: 85332b58c37 ! 5: b978b5d233a commit-reach: start reporting errors in `paint_down_to_common()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- commit-reach: start reporting errors in `paint_down_to_common()`
+ commit-reach(paint_down_to_common): start reporting errors
If a commit cannot be parsed, it is currently ignored when looking for
merge bases. That's undesirable as the operation can pretend success in
@@ commit-reach.c: static struct commit_list *merge_bases_many(struct repository *r
}
- list = paint_down_to_common(r, one, n, twos, 0, 0);
-+ if (paint_down_to_common(r, one, n, twos, 0, 0, &list) < 0) {
++ if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
+ free_commit_list(list);
+ return NULL;
+ }
6: 2ae6a54dd59 ! 6: 0f1ce130ce6 merge_bases_many(): pass on errors from `paint_down_to_common()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- merge_bases_many(): pass on errors from `paint_down_to_common()`
+ commit-reach(merge_bases_many): pass on "missing commits" errors
The `paint_down_to_common()` function was just taught to indicate
parsing errors, and now the `merge_bases_many()` function is aware of
@@ commit-reach.c: static int paint_down_to_common(struct repository *r,
+ oid_to_hex(&twos[i]->object.oid));
}
- if (paint_down_to_common(r, one, n, twos, 0, 0, &list) < 0) {
+ if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
free_commit_list(list);
- return NULL;
+ return -1;
7: 4321795102d ! 7: 133b69b6a62 get_merge_bases_many_0(): pass on errors from `merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- get_merge_bases_many_0(): pass on errors from `merge_bases_many()`
+ commit-reach(get_merge_bases_many_0): pass on "missing commits" errors
The `merge_bases_many()` function was just taught to indicate
parsing errors, and now the `get_merge_bases_many_0()` function is aware
8: 35545c4b777 ! 8: bd52f258cd9 repo_get_merge_bases(): pass on errors from `merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- repo_get_merge_bases(): pass on errors from `merge_bases_many()`
+ commit-reach(repo_get_merge_bases): pass on "missing commits" errors
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases()` function (which is also
9: a963058d2ba ! 9: b7ef90a57f0 get_octopus_merge_bases(): pass on errors from `merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- get_octopus_merge_bases(): pass on errors from `merge_bases_many()`
+ commit-reach(get_octopus_merge_bases): pass on "missing commits" errors
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases()` function (which is also
10: c3bed9c8500 ! 10: 32587b3caa7 repo_get_merge_bases_many(): pass on errors from `merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- repo_get_merge_bases_many(): pass on errors from `merge_bases_many()`
+ commit-reach(repo_get_merge_bases_many): pass on "missing commits" errors
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases_many()` function is aware of
11: bdbf47ae505 ! 11: 05de9f24444 repo_get_merge_bases_many_dirty(): pass on errors from `merge_bases_many()`
@@ Metadata
Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
## Commit message ##
- repo_get_merge_bases_many_dirty(): pass on errors from `merge_bases_many()`
+ commit-reach(repo_get_merge_bases_many_dirty): pass on errors
+
+ (Actually, this commit is only about passing on "missing commits"
+ errors, but adding that to the commit's title would have made it too
+ long.)
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases_many_dirty()` function is
--
gitgitgadget
^ permalink raw reply
* [PATCH v4 01/11] commit-reach(paint_down_to_common): plug two memory leaks
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
When a commit is missing, we return early (currently pretending that no
merge basis could be found in that case). At that stage, it is possible
that a merge base could have been found already, and added to the
`result`, which is now leaked.
The priority queue has a similar issue: There might still be a commit in
that queue.
Let's release both, to address the potential memory leaks.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/commit-reach.c b/commit-reach.c
index a868a575ea1..7ea916f9ebd 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -105,8 +105,11 @@ static struct commit_list *paint_down_to_common(struct repository *r,
parents = parents->next;
if ((p->object.flags & flags) == flags)
continue;
- if (repo_parse_commit(r, p))
+ if (repo_parse_commit(r, p)) {
+ clear_prio_queue(&queue);
+ free_commit_list(result);
return NULL;
+ }
p->object.flags |= flags;
prio_queue_put(&queue, p);
}
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 02/11] commit-reach(repo_in_merge_bases_many): optionally expect missing commits
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Currently this function treats unrelated commit histories the same way
as commit histories with missing commit objects.
Typically, missing commit objects constitute a corrupt repository,
though, and should be reported as such. The next commits will make it
so, but there is one exception: In `git fetch --update-shallow` we
_expect_ commit objects to be missing, and we do want to treat the
now-incomplete commit histories as unrelated.
To allow for that, let's introduce an additional parameter that is
passed to `repo_in_merge_bases_many()` to trigger this behavior, and use
it in the two callers in `shallow.c`.
This commit changes behavior slightly: unless called from the
`shallow.c` functions that set the `ignore_missing_commits` bit, any
non-existing tip commit that is passed to `repo_in_merge_bases_many()`
will now result in an error.
Note: When encountering missing commits while traversing the commit
history in search for merge bases, with this commit there won't be a
change in behavior just yet, their children will still be interpreted as
root commits. This bug will get fixed by follow-up commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 9 +++++----
commit-reach.h | 3 ++-
remote.c | 2 +-
shallow.c | 5 +++--
t/helper/test-reach.c | 2 +-
5 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/commit-reach.c b/commit-reach.c
index 7ea916f9ebd..5c1b5256598 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -467,7 +467,7 @@ int repo_is_descendant_of(struct repository *r,
other = with_commit->item;
with_commit = with_commit->next;
- if (repo_in_merge_bases_many(r, other, 1, &commit))
+ if (repo_in_merge_bases_many(r, other, 1, &commit, 0))
return 1;
}
return 0;
@@ -478,17 +478,18 @@ int repo_is_descendant_of(struct repository *r,
* Is "commit" an ancestor of one of the "references"?
*/
int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
- int nr_reference, struct commit **reference)
+ int nr_reference, struct commit **reference,
+ int ignore_missing_commits)
{
struct commit_list *bases;
int ret = 0, i;
timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO;
if (repo_parse_commit(r, commit))
- return ret;
+ return ignore_missing_commits ? 0 : -1;
for (i = 0; i < nr_reference; i++) {
if (repo_parse_commit(r, reference[i]))
- return ret;
+ return ignore_missing_commits ? 0 : -1;
generation = commit_graph_generation(reference[i]);
if (generation > max_generation)
diff --git a/commit-reach.h b/commit-reach.h
index 35c4da49481..68f81549a44 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -30,7 +30,8 @@ int repo_in_merge_bases(struct repository *r,
struct commit *reference);
int repo_in_merge_bases_many(struct repository *r,
struct commit *commit,
- int nr_reference, struct commit **reference);
+ int nr_reference, struct commit **reference,
+ int ignore_missing_commits);
/*
* Takes a list of commits and returns a new list where those
diff --git a/remote.c b/remote.c
index abb24822beb..763c80f4a7d 100644
--- a/remote.c
+++ b/remote.c
@@ -2675,7 +2675,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
if (MERGE_BASES_BATCH_SIZE < size)
size = MERGE_BASES_BATCH_SIZE;
- if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk)))
+ if ((ret = repo_in_merge_bases_many(the_repository, commit, size, chunk, 0)))
break;
}
diff --git a/shallow.c b/shallow.c
index ac728cdd778..dfcc1f86a7f 100644
--- a/shallow.c
+++ b/shallow.c
@@ -797,7 +797,7 @@ static void post_assign_shallow(struct shallow_info *info,
for (j = 0; j < bitmap_nr; j++)
if (bitmap[0][j] &&
/* Step 7, reachability test at commit level */
- !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits)) {
+ !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1)) {
update_refstatus(ref_status, info->ref->nr, *bitmap);
dst++;
break;
@@ -828,7 +828,8 @@ int delayed_reachability_test(struct shallow_info *si, int c)
si->reachable[c] = repo_in_merge_bases_many(the_repository,
commit,
si->nr_commits,
- si->commits);
+ si->commits,
+ 1);
si->need_reachability_test[c] = 0;
}
return si->reachable[c];
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 3e173399a00..aa816e168ea 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -113,7 +113,7 @@ int cmd__reach(int ac, const char **av)
repo_in_merge_bases(the_repository, A, B));
else if (!strcmp(av[1], "in_merge_bases_many"))
printf("%s(A,X):%d\n", av[1],
- repo_in_merge_bases_many(the_repository, A, X_nr, X_array));
+ repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0));
else if (!strcmp(av[1], "is_descendant_of"))
printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
else if (!strcmp(av[1], "get_merge_bases_many")) {
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 03/11] commit-reach(repo_in_merge_bases_many): report missing commits
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Some functions in Git's source code follow the convention that returning
a negative value indicates a fatal error, e.g. repository corruption.
Let's use this convention in `repo_in_merge_bases()` to report when one
of the specified commits is missing (i.e. when `repo_parse_commit()`
reports an error).
Also adjust the callers of `repo_in_merge_bases()` to handle such
negative return values.
Note: As of this patch, errors are returned only if any of the specified
merge heads is missing. Over the course of the next patches, missing
commits will also be reported by the `paint_down_to_common()` function,
which is called by `repo_in_merge_bases_many()`, and those errors will
be properly propagated back to the caller at that stage.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/branch.c | 12 +++++--
builtin/fast-import.c | 6 +++-
builtin/fetch.c | 2 ++
builtin/log.c | 7 ++--
builtin/merge-base.c | 6 +++-
builtin/pull.c | 4 +++
builtin/receive-pack.c | 6 +++-
commit-reach.c | 8 +++--
http-push.c | 5 ++-
merge-ort.c | 81 ++++++++++++++++++++++++++++++++++++------
merge-recursive.c | 54 +++++++++++++++++++++++-----
shallow.c | 18 ++++++----
12 files changed, 173 insertions(+), 36 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index e7ee9bd0f15..7f9e79237f3 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -161,6 +161,8 @@ static int branch_merged(int kind, const char *name,
merged = reference_rev ? repo_in_merge_bases(the_repository, rev,
reference_rev) : 0;
+ if (merged < 0)
+ exit(128);
/*
* After the safety valve is fully redefined to "check with
@@ -169,9 +171,13 @@ static int branch_merged(int kind, const char *name,
* any of the following code, but during the transition period,
* a gentle reminder is in order.
*/
- if ((head_rev != reference_rev) &&
- (head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0) != merged) {
- if (merged)
+ if (head_rev != reference_rev) {
+ int expect = head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0;
+ if (expect < 0)
+ exit(128);
+ if (expect == merged)
+ ; /* okay */
+ else if (merged)
warning(_("deleting branch '%s' that has been merged to\n"
" '%s', but not yet merged to HEAD"),
name, reference_name);
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 444f41cf8ca..14c2efa88fc 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -1625,6 +1625,7 @@ static int update_branch(struct branch *b)
oidclr(&old_oid);
if (!force_update && !is_null_oid(&old_oid)) {
struct commit *old_cmit, *new_cmit;
+ int ret;
old_cmit = lookup_commit_reference_gently(the_repository,
&old_oid, 0);
@@ -1633,7 +1634,10 @@ static int update_branch(struct branch *b)
if (!old_cmit || !new_cmit)
return error("Branch %s is missing commits.", b->name);
- if (!repo_in_merge_bases(the_repository, old_cmit, new_cmit)) {
+ ret = repo_in_merge_bases(the_repository, old_cmit, new_cmit);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
warning("Not updating %s"
" (new tip %s does not contain %s)",
b->name, oid_to_hex(&b->oid),
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fd134ba74d9..0584a1f8b64 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -978,6 +978,8 @@ static int update_local_ref(struct ref *ref,
uint64_t t_before = getnanotime();
fast_forward = repo_in_merge_bases(the_repository, current,
updated);
+ if (fast_forward < 0)
+ exit(128);
forced_updates_ms += (getnanotime() - t_before) / 1000000;
} else {
fast_forward = 1;
diff --git a/builtin/log.c b/builtin/log.c
index ba775d7b5cf..1705da71aca 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1623,7 +1623,7 @@ static struct commit *get_base_commit(const char *base_commit,
{
struct commit *base = NULL;
struct commit **rev;
- int i = 0, rev_nr = 0, auto_select, die_on_failure;
+ int i = 0, rev_nr = 0, auto_select, die_on_failure, ret;
switch (auto_base) {
case AUTO_BASE_NEVER:
@@ -1723,7 +1723,10 @@ static struct commit *get_base_commit(const char *base_commit,
rev_nr = DIV_ROUND_UP(rev_nr, 2);
}
- if (!repo_in_merge_bases(the_repository, base, rev[0])) {
+ ret = repo_in_merge_bases(the_repository, base, rev[0]);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
if (die_on_failure) {
die(_("base commit should be the ancestor of revision list"));
} else {
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index e68b7fe45d7..0308fd73289 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -103,12 +103,16 @@ static int handle_octopus(int count, const char **args, int show_all)
static int handle_is_ancestor(int argc, const char **argv)
{
struct commit *one, *two;
+ int ret;
if (argc != 2)
die("--is-ancestor takes exactly two commits");
one = get_commit_reference(argv[0]);
two = get_commit_reference(argv[1]);
- if (repo_in_merge_bases(the_repository, one, two))
+ ret = repo_in_merge_bases(the_repository, one, two);
+ if (ret < 0)
+ exit(128);
+ if (ret)
return 0;
else
return 1;
diff --git a/builtin/pull.c b/builtin/pull.c
index be2b2c9ebc9..e6f2942c0c5 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -931,6 +931,8 @@ static int get_can_ff(struct object_id *orig_head,
merge_head = lookup_commit_reference(the_repository, orig_merge_head);
ret = repo_is_descendant_of(the_repository, merge_head, list);
free_commit_list(list);
+ if (ret < 0)
+ exit(128);
return ret;
}
@@ -955,6 +957,8 @@ static int already_up_to_date(struct object_id *orig_head,
commit_list_insert(theirs, &list);
ok = repo_is_descendant_of(the_repository, ours, list);
free_commit_list(list);
+ if (ok < 0)
+ exit(128);
if (!ok)
return 0;
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 8c4f0cb90a9..956fea6293e 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1546,6 +1546,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
starts_with(name, "refs/heads/")) {
struct object *old_object, *new_object;
struct commit *old_commit, *new_commit;
+ int ret2;
old_object = parse_object(the_repository, old_oid);
new_object = parse_object(the_repository, new_oid);
@@ -1559,7 +1560,10 @@ static const char *update(struct command *cmd, struct shallow_info *si)
}
old_commit = (struct commit *)old_object;
new_commit = (struct commit *)new_object;
- if (!repo_in_merge_bases(the_repository, old_commit, new_commit)) {
+ ret2 = repo_in_merge_bases(the_repository, old_commit, new_commit);
+ if (ret2 < 0)
+ exit(128);
+ if (!ret2) {
rp_error("denying non-fast-forward %s"
" (you should pull first)", name);
ret = "non-fast-forward";
diff --git a/commit-reach.c b/commit-reach.c
index 5c1b5256598..5ff71d72d51 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -464,11 +464,13 @@ int repo_is_descendant_of(struct repository *r,
} else {
while (with_commit) {
struct commit *other;
+ int ret;
other = with_commit->item;
with_commit = with_commit->next;
- if (repo_in_merge_bases_many(r, other, 1, &commit, 0))
- return 1;
+ ret = repo_in_merge_bases_many(r, other, 1, &commit, 0);
+ if (ret)
+ return ret;
}
return 0;
}
@@ -598,6 +600,8 @@ int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
commit_list_insert(old_commit, &old_commit_list);
ret = repo_is_descendant_of(the_repository,
new_commit, old_commit_list);
+ if (ret < 0)
+ exit(128);
free_commit_list(old_commit_list);
return ret;
}
diff --git a/http-push.c b/http-push.c
index a704f490fdb..24c16a4f5ff 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1576,8 +1576,11 @@ static int verify_merge_base(struct object_id *head_oid, struct ref *remote)
struct commit *head = lookup_commit_or_die(head_oid, "HEAD");
struct commit *branch = lookup_commit_or_die(&remote->old_oid,
remote->name);
+ int ret = repo_in_merge_bases(the_repository, branch, head);
- return repo_in_merge_bases(the_repository, branch, head);
+ if (ret < 0)
+ exit(128);
+ return ret;
}
static int delete_remote_branch(const char *pattern, int force)
diff --git a/merge-ort.c b/merge-ort.c
index 6491070d965..9f3af46333a 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -544,6 +544,7 @@ enum conflict_and_info_types {
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
CONFLICT_SUBMODULE_NULL_MERGE_BASE,
+ CONFLICT_SUBMODULE_CORRUPT,
/* Keep this entry _last_ in the list */
NB_CONFLICT_TYPES,
@@ -596,7 +597,9 @@ static const char *type_short_descriptions[] = {
[CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] =
"CONFLICT (submodule may have rewinds)",
[CONFLICT_SUBMODULE_NULL_MERGE_BASE] =
- "CONFLICT (submodule lacks merge base)"
+ "CONFLICT (submodule lacks merge base)",
+ [CONFLICT_SUBMODULE_CORRUPT] =
+ "CONFLICT (submodule corrupt)"
};
struct logical_conflict_info {
@@ -1710,7 +1713,14 @@ static int find_first_merges(struct repository *repo,
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
- if (repo_in_merge_bases(repo, b, commit))
+ int ret = repo_in_merge_bases(repo, b, commit);
+
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0)
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
@@ -1725,9 +1735,17 @@ static int find_first_merges(struct repository *repo,
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
- if (i != j && repo_in_merge_bases(repo, m2, m1)) {
- contains_another = 1;
- break;
+ if (i != j) {
+ int ret = repo_in_merge_bases(repo, m2, m1);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0) {
+ contains_another = 1;
+ break;
+ }
}
}
@@ -1749,7 +1767,7 @@ static int merge_submodule(struct merge_options *opt,
{
struct repository subrepo;
struct strbuf sb = STRBUF_INIT;
- int ret = 0;
+ int ret = 0, ret2;
struct commit *commit_o, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
@@ -1796,8 +1814,26 @@ static int merge_submodule(struct merge_options *opt,
}
/* check whether both changes are forward */
- if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
- !repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_a);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ goto cleanup;
+ }
+ if (ret2 > 0)
+ ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_b);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ goto cleanup;
+ }
+ if (!ret2) {
path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0,
path, NULL, NULL, NULL,
_("Failed to merge submodule %s "
@@ -1807,7 +1843,16 @@ static int merge_submodule(struct merge_options *opt,
}
/* Case #1: a is contained in b or vice versa */
- if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ goto cleanup;
+ }
+ if (ret2 > 0) {
oidcpy(result, b);
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
path, NULL, NULL, NULL,
@@ -1816,7 +1861,16 @@ static int merge_submodule(struct merge_options *opt,
ret = 1;
goto cleanup;
}
- if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a);
+ if (ret2 < 0) {
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ goto cleanup;
+ }
+ if (ret2 > 0) {
oidcpy(result, a);
path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
path, NULL, NULL, NULL,
@@ -1841,6 +1895,13 @@ static int merge_submodule(struct merge_options *opt,
parent_count = find_first_merges(&subrepo, path, commit_a, commit_b,
&merges);
switch (parent_count) {
+ case -1:
+ path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s "
+ "(repository corrupt)"),
+ path);
+ break;
case 0:
path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0,
path, NULL, NULL, NULL,
diff --git a/merge-recursive.c b/merge-recursive.c
index e3beb0801b1..0d931cc14ad 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1144,7 +1144,13 @@ static int find_first_merges(struct repository *repo,
die("revision walk setup failed");
while ((commit = get_revision(&revs)) != NULL) {
struct object *o = &(commit->object);
- if (repo_in_merge_bases(repo, b, commit))
+ int ret = repo_in_merge_bases(repo, b, commit);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret)
add_object_array(o, NULL, &merges);
}
reset_revision_walk();
@@ -1159,9 +1165,17 @@ static int find_first_merges(struct repository *repo,
contains_another = 0;
for (j = 0; j < merges.nr; j++) {
struct commit *m2 = (struct commit *) merges.objects[j].item;
- if (i != j && repo_in_merge_bases(repo, m2, m1)) {
- contains_another = 1;
- break;
+ if (i != j) {
+ int ret = repo_in_merge_bases(repo, m2, m1);
+ if (ret < 0) {
+ object_array_clear(&merges);
+ release_revisions(&revs);
+ return ret;
+ }
+ if (ret > 0) {
+ contains_another = 1;
+ break;
+ }
}
}
@@ -1197,7 +1211,7 @@ static int merge_submodule(struct merge_options *opt,
const struct object_id *b)
{
struct repository subrepo;
- int ret = 0;
+ int ret = 0, ret2;
struct commit *commit_base, *commit_a, *commit_b;
int parent_count;
struct object_array merges;
@@ -1234,14 +1248,29 @@ static int merge_submodule(struct merge_options *opt,
}
/* check whether both changes are forward */
- if (!repo_in_merge_bases(&subrepo, commit_base, commit_a) ||
- !repo_in_merge_bases(&subrepo, commit_base, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_a);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ goto cleanup;
+ }
+ if (ret2 > 0)
+ ret2 = repo_in_merge_bases(&subrepo, commit_base, commit_b);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ goto cleanup;
+ }
+ if (!ret2) {
output(opt, 1, _("Failed to merge submodule %s (commits don't follow merge-base)"), path);
goto cleanup;
}
/* Case #1: a is contained in b or vice versa */
- if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ goto cleanup;
+ }
+ if (ret2) {
oidcpy(result, b);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
@@ -1254,7 +1283,12 @@ static int merge_submodule(struct merge_options *opt,
ret = 1;
goto cleanup;
}
- if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
+ ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a);
+ if (ret2 < 0) {
+ output(opt, 1, _("Failed to merge submodule %s (repository corrupt)"), path);
+ goto cleanup;
+ }
+ if (ret2) {
oidcpy(result, a);
if (show(opt, 3)) {
output(opt, 3, _("Fast-forwarding submodule %s to the following commit:"), path);
@@ -1402,6 +1436,8 @@ static int merge_mode_and_contents(struct merge_options *opt,
&o->oid,
&a->oid,
&b->oid);
+ if (result->clean < 0)
+ return -1;
} else if (S_ISLNK(a->mode)) {
switch (opt->recursive_variant) {
case MERGE_VARIANT_NORMAL:
diff --git a/shallow.c b/shallow.c
index dfcc1f86a7f..f71496f35c3 100644
--- a/shallow.c
+++ b/shallow.c
@@ -795,12 +795,16 @@ static void post_assign_shallow(struct shallow_info *info,
if (!*bitmap)
continue;
for (j = 0; j < bitmap_nr; j++)
- if (bitmap[0][j] &&
- /* Step 7, reachability test at commit level */
- !repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1)) {
- update_refstatus(ref_status, info->ref->nr, *bitmap);
- dst++;
- break;
+ if (bitmap[0][j]) {
+ /* Step 7, reachability test at commit level */
+ int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1);
+ if (ret < 0)
+ exit(128);
+ if (!ret) {
+ update_refstatus(ref_status, info->ref->nr, *bitmap);
+ dst++;
+ break;
+ }
}
}
info->nr_ours = dst;
@@ -830,6 +834,8 @@ int delayed_reachability_test(struct shallow_info *si, int c)
si->nr_commits,
si->commits,
1);
+ if (si->reachable[c] < 0)
+ exit(128);
si->need_reachability_test[c] = 0;
}
return si->reachable[c];
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 04/11] commit-reach(paint_down_to_common): prepare for handling shallow commits
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
When `git fetch --update-shallow` needs to test for commit ancestry, it
can naturally run into a missing object (e.g. if it is a parent of a
shallow commit). For the purpose of `--update-shallow`, this needs to be
treated as if the child commit did not even have that parent, i.e. the
commit history needs to be clamped.
For all other scenarios, clamping the commit history is actually a bug,
as it would hide repository corruption (for an analysis regarding
shallow and partial clones, see the analysis further down).
Add a flag to optionally ask the function to ignore missing commits, as
`--update-shallow` needs it to, while detecting missing objects as a
repository corruption error by default.
This flag is needed, and cannot replaced by `is_repository_shallow()` to
indicate that situation, because that function would return 0 in the
`--update-shallow` scenario: There is not actually a `shallow` file in
that scenario, as demonstrated e.g. by t5537.10 ("add new shallow root
with receive.updateshallow on") and t5538.4 ("add new shallow root with
receive.updateshallow on").
Note: shallow commits' parents are set to `NULL` internally already,
therefore there is no need to special-case shallow repositories here, as
the merge-base logic will not try to access parent commits of shallow
commits.
Likewise, partial clones aren't an issue either: If a commit is missing
during the revision walk in the merge-base logic, it is fetched via
`promisor_remote_get_direct()`. And not only the single missing commit
object: Due to the way the "promised" objects are fetched (in
`fetch_objects()` in `promisor-remote.c`, using `fetch
--filter=blob:none`), there is no actual way to fetch a single commit
object, as the remote side will pass that commit OID to `pack-objects
--revs [...]` which in turn passes it to `rev-list` which interprets
this as a commit _range_ instead of a single object. Therefore, in
partial clones (unless they are shallow in addition), all commits
reachable from a commit that is in the local object database are also
present in that local database.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/commit-reach.c b/commit-reach.c
index 5ff71d72d51..7112b10eeea 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -53,7 +53,8 @@ static int queue_has_nonstale(struct prio_queue *queue)
static struct commit_list *paint_down_to_common(struct repository *r,
struct commit *one, int n,
struct commit **twos,
- timestamp_t min_generation)
+ timestamp_t min_generation,
+ int ignore_missing_commits)
{
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
struct commit_list *result = NULL;
@@ -108,6 +109,13 @@ static struct commit_list *paint_down_to_common(struct repository *r,
if (repo_parse_commit(r, p)) {
clear_prio_queue(&queue);
free_commit_list(result);
+ /*
+ * At this stage, we know that the commit is
+ * missing: `repo_parse_commit()` uses
+ * `OBJECT_INFO_DIE_IF_CORRUPT` and therefore
+ * corrupt commits would already have been
+ * dispatched with a `die()`.
+ */
return NULL;
}
p->object.flags |= flags;
@@ -143,7 +151,7 @@ static struct commit_list *merge_bases_many(struct repository *r,
return NULL;
}
- list = paint_down_to_common(r, one, n, twos, 0);
+ list = paint_down_to_common(r, one, n, twos, 0, 0);
while (list) {
struct commit *commit = pop_commit(&list);
@@ -214,7 +222,7 @@ static int remove_redundant_no_gen(struct repository *r,
min_generation = curr_generation;
}
common = paint_down_to_common(r, array[i], filled,
- work, min_generation);
+ work, min_generation, 0);
if (array[i]->object.flags & PARENT2)
redundant[i] = 1;
for (j = 0; j < filled; j++)
@@ -504,7 +512,7 @@ int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
bases = paint_down_to_common(r, commit,
nr_reference, reference,
- generation);
+ generation, ignore_missing_commits);
if (commit->object.flags & PARENT2)
ret = 1;
clear_commit_marks(commit, all_flags);
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 05/11] commit-reach(paint_down_to_common): start reporting errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
If a commit cannot be parsed, it is currently ignored when looking for
merge bases. That's undesirable as the operation can pretend success in
a corrupt repository, even though the command should fail with an error
message.
Let's start at the bottom of the stack by teaching the
`paint_down_to_common()` function to return an `int`: if negative, it
indicates fatal error, if 0 success.
This requires a couple of callers to be adjusted accordingly.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 66 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 45 insertions(+), 21 deletions(-)
diff --git a/commit-reach.c b/commit-reach.c
index 7112b10eeea..9ad5f9db4f7 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -50,14 +50,14 @@ static int queue_has_nonstale(struct prio_queue *queue)
}
/* all input commits in one and twos[] must have been parsed! */
-static struct commit_list *paint_down_to_common(struct repository *r,
- struct commit *one, int n,
- struct commit **twos,
- timestamp_t min_generation,
- int ignore_missing_commits)
+static int paint_down_to_common(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ timestamp_t min_generation,
+ int ignore_missing_commits,
+ struct commit_list **result)
{
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
- struct commit_list *result = NULL;
int i;
timestamp_t last_gen = GENERATION_NUMBER_INFINITY;
@@ -66,8 +66,8 @@ static struct commit_list *paint_down_to_common(struct repository *r,
one->object.flags |= PARENT1;
if (!n) {
- commit_list_append(one, &result);
- return result;
+ commit_list_append(one, result);
+ return 0;
}
prio_queue_put(&queue, one);
@@ -95,7 +95,7 @@ static struct commit_list *paint_down_to_common(struct repository *r,
if (flags == (PARENT1 | PARENT2)) {
if (!(commit->object.flags & RESULT)) {
commit->object.flags |= RESULT;
- commit_list_insert_by_date(commit, &result);
+ commit_list_insert_by_date(commit, result);
}
/* Mark parents of a found merge stale */
flags |= STALE;
@@ -108,7 +108,8 @@ static struct commit_list *paint_down_to_common(struct repository *r,
continue;
if (repo_parse_commit(r, p)) {
clear_prio_queue(&queue);
- free_commit_list(result);
+ free_commit_list(*result);
+ *result = NULL;
/*
* At this stage, we know that the commit is
* missing: `repo_parse_commit()` uses
@@ -116,7 +117,10 @@ static struct commit_list *paint_down_to_common(struct repository *r,
* corrupt commits would already have been
* dispatched with a `die()`.
*/
- return NULL;
+ if (ignore_missing_commits)
+ return 0;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&p->object.oid));
}
p->object.flags |= flags;
prio_queue_put(&queue, p);
@@ -124,7 +128,7 @@ static struct commit_list *paint_down_to_common(struct repository *r,
}
clear_prio_queue(&queue);
- return result;
+ return 0;
}
static struct commit_list *merge_bases_many(struct repository *r,
@@ -151,7 +155,10 @@ static struct commit_list *merge_bases_many(struct repository *r,
return NULL;
}
- list = paint_down_to_common(r, one, n, twos, 0, 0);
+ if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
+ free_commit_list(list);
+ return NULL;
+ }
while (list) {
struct commit *commit = pop_commit(&list);
@@ -205,7 +212,7 @@ static int remove_redundant_no_gen(struct repository *r,
for (i = 0; i < cnt; i++)
repo_parse_commit(r, array[i]);
for (i = 0; i < cnt; i++) {
- struct commit_list *common;
+ struct commit_list *common = NULL;
timestamp_t min_generation = commit_graph_generation(array[i]);
if (redundant[i])
@@ -221,8 +228,16 @@ static int remove_redundant_no_gen(struct repository *r,
if (curr_generation < min_generation)
min_generation = curr_generation;
}
- common = paint_down_to_common(r, array[i], filled,
- work, min_generation, 0);
+ if (paint_down_to_common(r, array[i], filled,
+ work, min_generation, 0, &common)) {
+ clear_commit_marks(array[i], all_flags);
+ clear_commit_marks_many(filled, work, all_flags);
+ free_commit_list(common);
+ free(work);
+ free(redundant);
+ free(filled_index);
+ return -1;
+ }
if (array[i]->object.flags & PARENT2)
redundant[i] = 1;
for (j = 0; j < filled; j++)
@@ -422,6 +437,10 @@ static struct commit_list *get_merge_bases_many_0(struct repository *r,
clear_commit_marks_many(n, twos, all_flags);
cnt = remove_redundant(r, rslt, cnt);
+ if (cnt < 0) {
+ free(rslt);
+ return NULL;
+ }
result = NULL;
for (i = 0; i < cnt; i++)
commit_list_insert_by_date(rslt[i], &result);
@@ -491,7 +510,7 @@ int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
int nr_reference, struct commit **reference,
int ignore_missing_commits)
{
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
int ret = 0, i;
timestamp_t generation, max_generation = GENERATION_NUMBER_ZERO;
@@ -510,10 +529,11 @@ int repo_in_merge_bases_many(struct repository *r, struct commit *commit,
if (generation > max_generation)
return ret;
- bases = paint_down_to_common(r, commit,
- nr_reference, reference,
- generation, ignore_missing_commits);
- if (commit->object.flags & PARENT2)
+ if (paint_down_to_common(r, commit,
+ nr_reference, reference,
+ generation, ignore_missing_commits, &bases))
+ ret = -1;
+ else if (commit->object.flags & PARENT2)
ret = 1;
clear_commit_marks(commit, all_flags);
clear_commit_marks_many(nr_reference, reference, all_flags);
@@ -566,6 +586,10 @@ struct commit_list *reduce_heads(struct commit_list *heads)
}
}
num_head = remove_redundant(the_repository, array, num_head);
+ if (num_head < 0) {
+ free(array);
+ return NULL;
+ }
for (i = 0; i < num_head; i++)
tail = &commit_list_insert(array[i], tail)->next;
free(array);
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 06/11] commit-reach(merge_bases_many): pass on "missing commits" errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `paint_down_to_common()` function was just taught to indicate
parsing errors, and now the `merge_bases_many()` function is aware of
that, too.
One tricky aspect is that `merge_bases_many()` parses commits of its
own, but wants to gracefully handle the scenario where NULL is passed as
a merge head, returning the empty list of merge bases. The way this was
handled involved calling `repo_parse_commit(NULL)` and relying on it to
return an error. This has to be done differently now so that we can
handle missing commits correctly by producing a fatal error.
Next step: adjust the caller of `merge_bases_many()`:
`get_merge_bases_many_0()`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/commit-reach.c b/commit-reach.c
index 9ad5f9db4f7..ddfec5289dd 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -131,41 +131,49 @@ static int paint_down_to_common(struct repository *r,
return 0;
}
-static struct commit_list *merge_bases_many(struct repository *r,
- struct commit *one, int n,
- struct commit **twos)
+static int merge_bases_many(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result)
{
struct commit_list *list = NULL;
- struct commit_list *result = NULL;
int i;
for (i = 0; i < n; i++) {
- if (one == twos[i])
+ if (one == twos[i]) {
/*
* We do not mark this even with RESULT so we do not
* have to clean it up.
*/
- return commit_list_insert(one, &result);
+ *result = commit_list_insert(one, result);
+ return 0;
+ }
}
+ if (!one)
+ return 0;
if (repo_parse_commit(r, one))
- return NULL;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&one->object.oid));
for (i = 0; i < n; i++) {
+ if (!twos[i])
+ return 0;
if (repo_parse_commit(r, twos[i]))
- return NULL;
+ return error(_("could not parse commit %s"),
+ oid_to_hex(&twos[i]->object.oid));
}
if (paint_down_to_common(r, one, n, twos, 0, 0, &list)) {
free_commit_list(list);
- return NULL;
+ return -1;
}
while (list) {
struct commit *commit = pop_commit(&list);
if (!(commit->object.flags & STALE))
- commit_list_insert_by_date(commit, &result);
+ commit_list_insert_by_date(commit, result);
}
- return result;
+ return 0;
}
struct commit_list *get_octopus_merge_bases(struct commit_list *in)
@@ -410,10 +418,11 @@ static struct commit_list *get_merge_bases_many_0(struct repository *r,
{
struct commit_list *list;
struct commit **rslt;
- struct commit_list *result;
+ struct commit_list *result = NULL;
int cnt, i;
- result = merge_bases_many(r, one, n, twos);
+ if (merge_bases_many(r, one, n, twos, &result) < 0)
+ return NULL;
for (i = 0; i < n; i++) {
if (one == twos[i])
return result;
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 07/11] commit-reach(get_merge_bases_many_0): pass on "missing commits" errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `merge_bases_many()` function was just taught to indicate
parsing errors, and now the `get_merge_bases_many_0()` function is aware
of that, too.
Next step: adjust the callers of `get_merge_bases_many_0()`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit-reach.c | 57 +++++++++++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/commit-reach.c b/commit-reach.c
index ddfec5289dd..c0123eb7207 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -410,37 +410,38 @@ static int remove_redundant(struct repository *r, struct commit **array, int cnt
return remove_redundant_no_gen(r, array, cnt);
}
-static struct commit_list *get_merge_bases_many_0(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos,
- int cleanup)
+static int get_merge_bases_many_0(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ int cleanup,
+ struct commit_list **result)
{
struct commit_list *list;
struct commit **rslt;
- struct commit_list *result = NULL;
int cnt, i;
- if (merge_bases_many(r, one, n, twos, &result) < 0)
- return NULL;
+ if (merge_bases_many(r, one, n, twos, result) < 0)
+ return -1;
for (i = 0; i < n; i++) {
if (one == twos[i])
- return result;
+ return 0;
}
- if (!result || !result->next) {
+ if (!*result || !(*result)->next) {
if (cleanup) {
clear_commit_marks(one, all_flags);
clear_commit_marks_many(n, twos, all_flags);
}
- return result;
+ return 0;
}
/* There are more than one */
- cnt = commit_list_count(result);
+ cnt = commit_list_count(*result);
CALLOC_ARRAY(rslt, cnt);
- for (list = result, i = 0; list; list = list->next)
+ for (list = *result, i = 0; list; list = list->next)
rslt[i++] = list->item;
- free_commit_list(result);
+ free_commit_list(*result);
+ *result = NULL;
clear_commit_marks(one, all_flags);
clear_commit_marks_many(n, twos, all_flags);
@@ -448,13 +449,12 @@ static struct commit_list *get_merge_bases_many_0(struct repository *r,
cnt = remove_redundant(r, rslt, cnt);
if (cnt < 0) {
free(rslt);
- return NULL;
+ return -1;
}
- result = NULL;
for (i = 0; i < cnt; i++)
- commit_list_insert_by_date(rslt[i], &result);
+ commit_list_insert_by_date(rslt[i], result);
free(rslt);
- return result;
+ return 0;
}
struct commit_list *repo_get_merge_bases_many(struct repository *r,
@@ -462,7 +462,12 @@ struct commit_list *repo_get_merge_bases_many(struct repository *r,
int n,
struct commit **twos)
{
- return get_merge_bases_many_0(r, one, n, twos, 1);
+ struct commit_list *result = NULL;
+ if (get_merge_bases_many_0(r, one, n, twos, 1, &result) < 0) {
+ free_commit_list(result);
+ return NULL;
+ }
+ return result;
}
struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
@@ -470,14 +475,24 @@ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
int n,
struct commit **twos)
{
- return get_merge_bases_many_0(r, one, n, twos, 0);
+ struct commit_list *result = NULL;
+ if (get_merge_bases_many_0(r, one, n, twos, 0, &result) < 0) {
+ free_commit_list(result);
+ return NULL;
+ }
+ return result;
}
struct commit_list *repo_get_merge_bases(struct repository *r,
struct commit *one,
struct commit *two)
{
- return get_merge_bases_many_0(r, one, 1, &two, 1);
+ struct commit_list *result = NULL;
+ if (get_merge_bases_many_0(r, one, 1, &two, 1, &result) < 0) {
+ free_commit_list(result);
+ return NULL;
+ }
+ return result;
}
/*
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 08/11] commit-reach(repo_get_merge_bases): pass on "missing commits" errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases()` function (which is also
surfaced via the `repo_get_merge_bases()` macro) is aware of that, too.
Naturally, there are a lot of callers that need to be adjusted now, too.
Next step: adjust the callers of `get_octopus_merge_bases()`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/log.c | 10 +++++-----
builtin/merge-tree.c | 5 +++--
builtin/merge.c | 20 ++++++++++++--------
builtin/rebase.c | 8 +++++---
builtin/rev-parse.c | 5 +++--
commit-reach.c | 23 +++++++++++------------
commit-reach.h | 7 ++++---
diff-lib.c | 5 +++--
log-tree.c | 5 +++--
merge-ort.c | 6 +++++-
merge-recursive.c | 4 +++-
notes-merge.c | 3 ++-
object-name.c | 7 +++++--
revision.c | 12 ++++++++----
sequencer.c | 8 ++++++--
submodule.c | 7 ++++++-
t/t4301-merge-tree-write-tree.sh | 12 ++++++++++++
17 files changed, 96 insertions(+), 51 deletions(-)
diff --git a/builtin/log.c b/builtin/log.c
index 1705da71aca..befafd6ae04 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1702,11 +1702,11 @@ static struct commit *get_base_commit(const char *base_commit,
*/
while (rev_nr > 1) {
for (i = 0; i < rev_nr / 2; i++) {
- struct commit_list *merge_base;
- merge_base = repo_get_merge_bases(the_repository,
- rev[2 * i],
- rev[2 * i + 1]);
- if (!merge_base || merge_base->next) {
+ struct commit_list *merge_base = NULL;
+ if (repo_get_merge_bases(the_repository,
+ rev[2 * i],
+ rev[2 * i + 1], &merge_base) < 0 ||
+ !merge_base || merge_base->next) {
if (die_on_failure) {
die(_("failed to find exact merge base"));
} else {
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index a35e0452d66..76200250629 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -463,8 +463,9 @@ static int real_merge(struct merge_tree_options *o,
* Get the merge bases, in reverse order; see comment above
* merge_incore_recursive in merge-ort.h
*/
- merge_bases = repo_get_merge_bases(the_repository, parent1,
- parent2);
+ if (repo_get_merge_bases(the_repository, parent1,
+ parent2, &merge_bases) < 0)
+ exit(128);
if (!merge_bases && !o->allow_unrelated_histories)
die(_("refusing to merge unrelated histories"));
merge_bases = reverse_commit_list(merge_bases);
diff --git a/builtin/merge.c b/builtin/merge.c
index d748d46e135..ac9d58adc29 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1517,10 +1517,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!remoteheads)
; /* already up-to-date */
- else if (!remoteheads->next)
- common = repo_get_merge_bases(the_repository, head_commit,
- remoteheads->item);
- else {
+ else if (!remoteheads->next) {
+ if (repo_get_merge_bases(the_repository, head_commit,
+ remoteheads->item, &common) < 0) {
+ ret = 2;
+ goto done;
+ }
+ } else {
struct commit_list *list = remoteheads;
commit_list_insert(head_commit, &list);
common = get_octopus_merge_bases(list);
@@ -1631,7 +1634,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct commit_list *j;
for (j = remoteheads; j; j = j->next) {
- struct commit_list *common_one;
+ struct commit_list *common_one = NULL;
struct commit *common_item;
/*
@@ -1639,9 +1642,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* merge_bases again, otherwise "git merge HEAD^
* HEAD^^" would be missed.
*/
- common_one = repo_get_merge_bases(the_repository,
- head_commit,
- j->item);
+ if (repo_get_merge_bases(the_repository, head_commit,
+ j->item, &common_one) < 0)
+ exit(128);
+
common_item = common_one->item;
free_commit_list(common_one);
if (!oideq(&common_item->object.oid, &j->item->object.oid)) {
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 043c65dccd9..06a55fc7325 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -879,7 +879,8 @@ static int can_fast_forward(struct commit *onto, struct commit *upstream,
if (!upstream)
goto done;
- merge_bases = repo_get_merge_bases(the_repository, upstream, head);
+ if (repo_get_merge_bases(the_repository, upstream, head, &merge_bases) < 0)
+ exit(128);
if (!merge_bases || merge_bases->next)
goto done;
@@ -898,8 +899,9 @@ static void fill_branch_base(struct rebase_options *options,
{
struct commit_list *merge_bases = NULL;
- merge_bases = repo_get_merge_bases(the_repository, options->onto,
- options->orig_head);
+ if (repo_get_merge_bases(the_repository, options->onto,
+ options->orig_head, &merge_bases) < 0)
+ exit(128);
if (!merge_bases || merge_bases->next)
oidcpy(branch_base, null_oid());
else
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index fde8861ca4e..c97d0f6144c 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -297,7 +297,7 @@ static int try_difference(const char *arg)
show_rev(NORMAL, &end_oid, end);
show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
if (symmetric) {
- struct commit_list *exclude;
+ struct commit_list *exclude = NULL;
struct commit *a, *b;
a = lookup_commit_reference(the_repository, &start_oid);
b = lookup_commit_reference(the_repository, &end_oid);
@@ -305,7 +305,8 @@ static int try_difference(const char *arg)
*dotdot = '.';
return 0;
}
- exclude = repo_get_merge_bases(the_repository, a, b);
+ if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0)
+ exit(128);
while (exclude) {
struct commit *commit = pop_commit(&exclude);
show_rev(REVERSED, &commit->object.oid, NULL);
diff --git a/commit-reach.c b/commit-reach.c
index c0123eb7207..b2e90687f7c 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -189,9 +189,12 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
struct commit_list *new_commits = NULL, *end = NULL;
for (j = ret; j; j = j->next) {
- struct commit_list *bases;
- bases = repo_get_merge_bases(the_repository, i->item,
- j->item);
+ struct commit_list *bases = NULL;
+ if (repo_get_merge_bases(the_repository, i->item,
+ j->item, &bases) < 0) {
+ free_commit_list(bases);
+ return NULL;
+ }
if (!new_commits)
new_commits = bases;
else
@@ -483,16 +486,12 @@ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
return result;
}
-struct commit_list *repo_get_merge_bases(struct repository *r,
- struct commit *one,
- struct commit *two)
+int repo_get_merge_bases(struct repository *r,
+ struct commit *one,
+ struct commit *two,
+ struct commit_list **result)
{
- struct commit_list *result = NULL;
- if (get_merge_bases_many_0(r, one, 1, &two, 1, &result) < 0) {
- free_commit_list(result);
- return NULL;
- }
- return result;
+ return get_merge_bases_many_0(r, one, 1, &two, 1, result);
}
/*
diff --git a/commit-reach.h b/commit-reach.h
index 68f81549a44..2c6fcdd34f6 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -9,9 +9,10 @@ struct ref_filter;
struct object_id;
struct object_array;
-struct commit_list *repo_get_merge_bases(struct repository *r,
- struct commit *rev1,
- struct commit *rev2);
+int repo_get_merge_bases(struct repository *r,
+ struct commit *rev1,
+ struct commit *rev2,
+ struct commit_list **result);
struct commit_list *repo_get_merge_bases_many(struct repository *r,
struct commit *one, int n,
struct commit **twos);
diff --git a/diff-lib.c b/diff-lib.c
index 0e9ec4f68af..498224ccce2 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -565,7 +565,7 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
{
int i;
struct commit *mb_child[2] = {0};
- struct commit_list *merge_bases;
+ struct commit_list *merge_bases = NULL;
for (i = 0; i < revs->pending.nr; i++) {
struct object *obj = revs->pending.objects[i].item;
@@ -592,7 +592,8 @@ void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
mb_child[1] = lookup_commit_reference(the_repository, &oid);
}
- merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]);
+ if (repo_get_merge_bases(the_repository, mb_child[0], mb_child[1], &merge_bases) < 0)
+ exit(128);
if (!merge_bases)
die(_("no merge base found"));
if (merge_bases->next)
diff --git a/log-tree.c b/log-tree.c
index 504da6b519e..4f337766a39 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -1010,7 +1010,7 @@ static int do_remerge_diff(struct rev_info *opt,
struct object_id *oid)
{
struct merge_options o;
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
struct merge_result res = {0};
struct pretty_print_context ctx = {0};
struct commit *parent1 = parents->item;
@@ -1035,7 +1035,8 @@ static int do_remerge_diff(struct rev_info *opt,
/* Parse the relevant commits and get the merge bases */
parse_commit_or_die(parent1);
parse_commit_or_die(parent2);
- bases = repo_get_merge_bases(the_repository, parent1, parent2);
+ if (repo_get_merge_bases(the_repository, parent1, parent2, &bases) < 0)
+ exit(128);
/* Re-merge the parents */
merge_incore_recursive(&o, bases, parent1, parent2, &res);
diff --git a/merge-ort.c b/merge-ort.c
index 9f3af46333a..90d8495ca1f 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -5066,7 +5066,11 @@ static void merge_ort_internal(struct merge_options *opt,
struct strbuf merge_base_abbrev = STRBUF_INIT;
if (!merge_bases) {
- merge_bases = repo_get_merge_bases(the_repository, h1, h2);
+ if (repo_get_merge_bases(the_repository, h1, h2,
+ &merge_bases) < 0) {
+ result->clean = -1;
+ return;
+ }
/* See merge-ort.h:merge_incore_recursive() declaration NOTE */
merge_bases = reverse_commit_list(merge_bases);
}
diff --git a/merge-recursive.c b/merge-recursive.c
index 0d931cc14ad..d609373d960 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -3638,7 +3638,9 @@ static int merge_recursive_internal(struct merge_options *opt,
}
if (!merge_bases) {
- merge_bases = repo_get_merge_bases(the_repository, h1, h2);
+ if (repo_get_merge_bases(the_repository, h1, h2,
+ &merge_bases) < 0)
+ return -1;
merge_bases = reverse_commit_list(merge_bases);
}
diff --git a/notes-merge.c b/notes-merge.c
index 8799b522a55..51282934ae6 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -607,7 +607,8 @@ int notes_merge(struct notes_merge_options *o,
assert(local && remote);
/* Find merge bases */
- bases = repo_get_merge_bases(the_repository, local, remote);
+ if (repo_get_merge_bases(the_repository, local, remote, &bases) < 0)
+ exit(128);
if (!bases) {
base_oid = null_oid();
base_tree_oid = the_hash_algo->empty_tree;
diff --git a/object-name.c b/object-name.c
index 0bfa29dbbfe..63bec6d9a2b 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1481,7 +1481,7 @@ int repo_get_oid_mb(struct repository *r,
struct object_id *oid)
{
struct commit *one, *two;
- struct commit_list *mbs;
+ struct commit_list *mbs = NULL;
struct object_id oid_tmp;
const char *dots;
int st;
@@ -1509,7 +1509,10 @@ int repo_get_oid_mb(struct repository *r,
two = lookup_commit_reference_gently(r, &oid_tmp, 0);
if (!two)
return -1;
- mbs = repo_get_merge_bases(r, one, two);
+ if (repo_get_merge_bases(r, one, two, &mbs) < 0) {
+ free_commit_list(mbs);
+ return -1;
+ }
if (!mbs || mbs->next)
st = -1;
else {
diff --git a/revision.c b/revision.c
index 00d5c29bfce..eb0d550842f 100644
--- a/revision.c
+++ b/revision.c
@@ -1965,7 +1965,7 @@ static void add_pending_commit_list(struct rev_info *revs,
static void prepare_show_merge(struct rev_info *revs)
{
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
struct commit *head, *other;
struct object_id oid;
const char **prune = NULL;
@@ -1980,7 +1980,8 @@ static void prepare_show_merge(struct rev_info *revs)
other = lookup_commit_or_die(&oid, "MERGE_HEAD");
add_pending_object(revs, &head->object, "HEAD");
add_pending_object(revs, &other->object, "MERGE_HEAD");
- bases = repo_get_merge_bases(the_repository, head, other);
+ if (repo_get_merge_bases(the_repository, head, other, &bases) < 0)
+ exit(128);
add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
free_commit_list(bases);
@@ -2068,14 +2069,17 @@ static int handle_dotdot_1(const char *arg, char *dotdot,
} else {
/* A...B -- find merge bases between the two */
struct commit *a, *b;
- struct commit_list *exclude;
+ struct commit_list *exclude = NULL;
a = lookup_commit_reference(revs->repo, &a_obj->oid);
b = lookup_commit_reference(revs->repo, &b_obj->oid);
if (!a || !b)
return dotdot_missing(arg, dotdot, revs, symmetric);
- exclude = repo_get_merge_bases(the_repository, a, b);
+ if (repo_get_merge_bases(the_repository, a, b, &exclude) < 0) {
+ free_commit_list(exclude);
+ return -1;
+ }
add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE,
flags_exclude);
add_pending_commit_list(revs, exclude, flags_exclude);
diff --git a/sequencer.c b/sequencer.c
index d584cac8ed9..4417f2f1956 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -3913,7 +3913,7 @@ static int do_merge(struct repository *r,
int run_commit_flags = 0;
struct strbuf ref_name = STRBUF_INIT;
struct commit *head_commit, *merge_commit, *i;
- struct commit_list *bases, *j;
+ struct commit_list *bases = NULL, *j;
struct commit_list *to_merge = NULL, **tail = &to_merge;
const char *strategy = !opts->xopts.nr &&
(!opts->strategy ||
@@ -4139,7 +4139,11 @@ static int do_merge(struct repository *r,
}
merge_commit = to_merge->item;
- bases = repo_get_merge_bases(r, head_commit, merge_commit);
+ if (repo_get_merge_bases(r, head_commit, merge_commit, &bases) < 0) {
+ ret = -1;
+ goto leave_merge;
+ }
+
if (bases && oideq(&merge_commit->object.oid,
&bases->item->object.oid)) {
ret = 0;
diff --git a/submodule.c b/submodule.c
index e603a19a876..04931a5474b 100644
--- a/submodule.c
+++ b/submodule.c
@@ -595,7 +595,12 @@ static void show_submodule_header(struct diff_options *o,
(!is_null_oid(two) && !*right))
message = "(commits not present)";
- *merge_bases = repo_get_merge_bases(sub, *left, *right);
+ *merge_bases = NULL;
+ if (repo_get_merge_bases(sub, *left, *right, merge_bases) < 0) {
+ message = "(corrupt repository)";
+ goto output_header;
+ }
+
if (*merge_bases) {
if ((*merge_bases)->item == *left)
fast_forward = 1;
diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
index b2c8a43fce3..5d1e7aca4c8 100755
--- a/t/t4301-merge-tree-write-tree.sh
+++ b/t/t4301-merge-tree-write-tree.sh
@@ -945,4 +945,16 @@ test_expect_success 'check the input format when --stdin is passed' '
test_cmp expect actual
'
+test_expect_success 'error out on missing commits as well' '
+ git init --bare missing-commit.git &&
+ git rev-list --objects side1 side3 >list-including-initial &&
+ grep -v ^$(git rev-parse side1^) <list-including-initial >list &&
+ git pack-objects missing-commit.git/objects/pack/missing-initial <list &&
+ side1=$(git rev-parse side1) &&
+ side3=$(git rev-parse side3) &&
+ test_must_fail git --git-dir=missing-commit.git \
+ merge-tree --allow-unrelated-histories $side1 $side3 >actual &&
+ test_must_be_empty actual
+'
+
test_done
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 09/11] commit-reach(get_octopus_merge_bases): pass on "missing commits" errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases()` function (which is also
surfaced via the `get_merge_bases()` macro) is aware of that, too.
Naturally, the callers need to be adjusted now, too.
Next step: adjust `repo_get_merge_bases_many()`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/merge-base.c | 8 ++++++--
builtin/merge.c | 6 +++++-
builtin/pull.c | 5 +++--
commit-reach.c | 20 +++++++++++---------
commit-reach.h | 2 +-
5 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 0308fd73289..2edffc5487e 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -77,13 +77,17 @@ static int handle_independent(int count, const char **args)
static int handle_octopus(int count, const char **args, int show_all)
{
struct commit_list *revs = NULL;
- struct commit_list *result, *rev;
+ struct commit_list *result = NULL, *rev;
int i;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
- result = get_octopus_merge_bases(revs);
+ if (get_octopus_merge_bases(revs, &result) < 0) {
+ free_commit_list(revs);
+ free_commit_list(result);
+ return 128;
+ }
free_commit_list(revs);
reduce_heads_replace(&result);
diff --git a/builtin/merge.c b/builtin/merge.c
index ac9d58adc29..94c5b693972 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1526,7 +1526,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
} else {
struct commit_list *list = remoteheads;
commit_list_insert(head_commit, &list);
- common = get_octopus_merge_bases(list);
+ if (get_octopus_merge_bases(list, &common) < 0) {
+ free(list);
+ ret = 2;
+ goto done;
+ }
free(list);
}
diff --git a/builtin/pull.c b/builtin/pull.c
index e6f2942c0c5..0c5a55f2f4d 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -820,7 +820,7 @@ static int get_octopus_merge_base(struct object_id *merge_base,
const struct object_id *merge_head,
const struct object_id *fork_point)
{
- struct commit_list *revs = NULL, *result;
+ struct commit_list *revs = NULL, *result = NULL;
commit_list_insert(lookup_commit_reference(the_repository, curr_head),
&revs);
@@ -830,7 +830,8 @@ static int get_octopus_merge_base(struct object_id *merge_base,
commit_list_insert(lookup_commit_reference(the_repository, fork_point),
&revs);
- result = get_octopus_merge_bases(revs);
+ if (get_octopus_merge_bases(revs, &result) < 0)
+ exit(128);
free_commit_list(revs);
reduce_heads_replace(&result);
diff --git a/commit-reach.c b/commit-reach.c
index b2e90687f7c..288d3d896a2 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -176,24 +176,26 @@ static int merge_bases_many(struct repository *r,
return 0;
}
-struct commit_list *get_octopus_merge_bases(struct commit_list *in)
+int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result)
{
- struct commit_list *i, *j, *k, *ret = NULL;
+ struct commit_list *i, *j, *k;
if (!in)
- return ret;
+ return 0;
- commit_list_insert(in->item, &ret);
+ commit_list_insert(in->item, result);
for (i = in->next; i; i = i->next) {
struct commit_list *new_commits = NULL, *end = NULL;
- for (j = ret; j; j = j->next) {
+ for (j = *result; j; j = j->next) {
struct commit_list *bases = NULL;
if (repo_get_merge_bases(the_repository, i->item,
j->item, &bases) < 0) {
free_commit_list(bases);
- return NULL;
+ free_commit_list(*result);
+ *result = NULL;
+ return -1;
}
if (!new_commits)
new_commits = bases;
@@ -202,10 +204,10 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
for (k = bases; k; k = k->next)
end = k;
}
- free_commit_list(ret);
- ret = new_commits;
+ free_commit_list(*result);
+ *result = new_commits;
}
- return ret;
+ return 0;
}
static int remove_redundant_no_gen(struct repository *r,
diff --git a/commit-reach.h b/commit-reach.h
index 2c6fcdd34f6..4690b6ecd0c 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -21,7 +21,7 @@ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
struct commit *one, int n,
struct commit **twos);
-struct commit_list *get_octopus_merge_bases(struct commit_list *in);
+int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result);
int repo_is_descendant_of(struct repository *r,
struct commit *commit,
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 10/11] commit-reach(repo_get_merge_bases_many): pass on "missing commits" errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases_many()` function is aware of
that, too.
Naturally, there are a lot of callers that need to be adjusted now, too.
Next stop: `repo_get_merge_bases_dirty()`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
bisect.c | 7 ++++---
builtin/log.c | 13 +++++++------
commit-reach.c | 16 ++++++----------
commit-reach.h | 7 ++++---
commit.c | 7 ++++---
t/helper/test-reach.c | 9 ++++++---
6 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/bisect.c b/bisect.c
index 1be8e0a2711..2018466d69f 100644
--- a/bisect.c
+++ b/bisect.c
@@ -851,10 +851,11 @@ static void handle_skipped_merge_base(const struct object_id *mb)
static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)
{
enum bisect_error res = BISECT_OK;
- struct commit_list *result;
+ struct commit_list *result = NULL;
- result = repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1,
- rev + 1);
+ if (repo_get_merge_bases_many(the_repository, rev[0], rev_nr - 1,
+ rev + 1, &result) < 0)
+ exit(128);
for (; result; result = result->next) {
const struct object_id *mb = &result->item->object.oid;
diff --git a/builtin/log.c b/builtin/log.c
index befafd6ae04..c75790a7cec 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1656,7 +1656,7 @@ static struct commit *get_base_commit(const char *base_commit,
struct branch *curr_branch = branch_get(NULL);
const char *upstream = branch_get_upstream(curr_branch, NULL);
if (upstream) {
- struct commit_list *base_list;
+ struct commit_list *base_list = NULL;
struct commit *commit;
struct object_id oid;
@@ -1667,11 +1667,12 @@ static struct commit *get_base_commit(const char *base_commit,
return NULL;
}
commit = lookup_commit_or_die(&oid, "upstream base");
- base_list = repo_get_merge_bases_many(the_repository,
- commit, total,
- list);
- /* There should be one and only one merge base. */
- if (!base_list || base_list->next) {
+ if (repo_get_merge_bases_many(the_repository,
+ commit, total,
+ list,
+ &base_list) < 0 ||
+ /* There should be one and only one merge base. */
+ !base_list || base_list->next) {
if (die_on_failure) {
die(_("could not find exact merge base"));
} else {
diff --git a/commit-reach.c b/commit-reach.c
index 288d3d896a2..0aeaef25343 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -462,17 +462,13 @@ static int get_merge_bases_many_0(struct repository *r,
return 0;
}
-struct commit_list *repo_get_merge_bases_many(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos)
+int repo_get_merge_bases_many(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ struct commit_list **result)
{
- struct commit_list *result = NULL;
- if (get_merge_bases_many_0(r, one, n, twos, 1, &result) < 0) {
- free_commit_list(result);
- return NULL;
- }
- return result;
+ return get_merge_bases_many_0(r, one, n, twos, 1, result);
}
struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
diff --git a/commit-reach.h b/commit-reach.h
index 4690b6ecd0c..458043f4d58 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -13,9 +13,10 @@ int repo_get_merge_bases(struct repository *r,
struct commit *rev1,
struct commit *rev2,
struct commit_list **result);
-struct commit_list *repo_get_merge_bases_many(struct repository *r,
- struct commit *one, int n,
- struct commit **twos);
+int repo_get_merge_bases_many(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result);
/* To be used only when object flags after this call no longer matter */
struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
struct commit *one, int n,
diff --git a/commit.c b/commit.c
index 8405d7c3fce..00add5d81c6 100644
--- a/commit.c
+++ b/commit.c
@@ -1054,7 +1054,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
{
struct object_id oid;
struct rev_collect revs;
- struct commit_list *bases;
+ struct commit_list *bases = NULL;
int i;
struct commit *ret = NULL;
char *full_refname;
@@ -1079,8 +1079,9 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
for (i = 0; i < revs.nr; i++)
revs.commit[i]->object.flags &= ~TMP_MARK;
- bases = repo_get_merge_bases_many(the_repository, commit, revs.nr,
- revs.commit);
+ if (repo_get_merge_bases_many(the_repository, commit, revs.nr,
+ revs.commit, &bases) < 0)
+ exit(128);
/*
* There should be one and only one merge base, when we found
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index aa816e168ea..84ee9da8681 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -117,9 +117,12 @@ int cmd__reach(int ac, const char **av)
else if (!strcmp(av[1], "is_descendant_of"))
printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
else if (!strcmp(av[1], "get_merge_bases_many")) {
- struct commit_list *list = repo_get_merge_bases_many(the_repository,
- A, X_nr,
- X_array);
+ struct commit_list *list = NULL;
+ if (repo_get_merge_bases_many(the_repository,
+ A, X_nr,
+ X_array,
+ &list) < 0)
+ exit(128);
printf("%s(A,X):\n", av[1]);
print_sorted_commit_ids(list);
} else if (!strcmp(av[1], "reduce_heads")) {
--
gitgitgadget
^ permalink raw reply related
* [PATCH v4 11/11] commit-reach(repo_get_merge_bases_many_dirty): pass on errors
From: Johannes Schindelin via GitGitGadget @ 2024-02-28 9:44 UTC (permalink / raw)
To: git
Cc: Patrick Steinhardt, Dirk Gouders, Johannes Schindelin,
Johannes Schindelin
In-Reply-To: <pull.1657.v4.git.1709113457.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
(Actually, this commit is only about passing on "missing commits"
errors, but adding that to the commit's title would have made it too
long.)
The `merge_bases_many()` function was just taught to indicate parsing
errors, and now the `repo_get_merge_bases_many_dirty()` function is
aware of that, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/merge-base.c | 9 ++++++---
commit-reach.c | 16 ++++++----------
commit-reach.h | 7 ++++---
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 2edffc5487e..a8a1ca53968 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -13,10 +13,13 @@
static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
{
- struct commit_list *result, *r;
+ struct commit_list *result = NULL, *r;
- result = repo_get_merge_bases_many_dirty(the_repository, rev[0],
- rev_nr - 1, rev + 1);
+ if (repo_get_merge_bases_many_dirty(the_repository, rev[0],
+ rev_nr - 1, rev + 1, &result) < 0) {
+ free_commit_list(result);
+ return -1;
+ }
if (!result)
return 1;
diff --git a/commit-reach.c b/commit-reach.c
index 0aeaef25343..202776b29e9 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -471,17 +471,13 @@ int repo_get_merge_bases_many(struct repository *r,
return get_merge_bases_many_0(r, one, n, twos, 1, result);
}
-struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
- struct commit *one,
- int n,
- struct commit **twos)
+int repo_get_merge_bases_many_dirty(struct repository *r,
+ struct commit *one,
+ int n,
+ struct commit **twos,
+ struct commit_list **result)
{
- struct commit_list *result = NULL;
- if (get_merge_bases_many_0(r, one, n, twos, 0, &result) < 0) {
- free_commit_list(result);
- return NULL;
- }
- return result;
+ return get_merge_bases_many_0(r, one, n, twos, 0, result);
}
int repo_get_merge_bases(struct repository *r,
diff --git a/commit-reach.h b/commit-reach.h
index 458043f4d58..bf63cc468fd 100644
--- a/commit-reach.h
+++ b/commit-reach.h
@@ -18,9 +18,10 @@ int repo_get_merge_bases_many(struct repository *r,
struct commit **twos,
struct commit_list **result);
/* To be used only when object flags after this call no longer matter */
-struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
- struct commit *one, int n,
- struct commit **twos);
+int repo_get_merge_bases_many_dirty(struct repository *r,
+ struct commit *one, int n,
+ struct commit **twos,
+ struct commit_list **result);
int get_octopus_merge_bases(struct commit_list *in, struct commit_list **result);
--
gitgitgadget
^ permalink raw reply related
* git-config doc: variables sorting bug
From: Bruno Haible @ 2024-02-28 10:12 UTC (permalink / raw)
To: git
Hi,
In https://git-scm.com/docs/git-config the variables (advice.* ...
worktree.guessRemote) are apparently meant to be in alphabetical order.
However,
filter.<driver>.clean
filter.<driver>.smudge
come after format.*. They should come before format.*, since 'i' < 'o'.
Bruno
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox