git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: [PATCH v3 1/3] Documentation: alias: rework notes into points
  @ 2024-05-23 15:14  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-05-23 15:14 UTC (permalink / raw)
  To: Ian Wienand; +Cc: git

Ian Wienand <iwienand@redhat.com> writes:

> There are a number of caveats when using aliases.  Rather than
> stuffing them all together in a paragraph, let's separate them out
> into individual points to make it clearer what's going on.

Nicely explained.

> diff --git a/Documentation/config/alias.txt b/Documentation/config/alias.txt
> index 01df96fab3..40851ef429 100644
> --- a/Documentation/config/alias.txt
> +++ b/Documentation/config/alias.txt
> @@ -21,8 +21,9 @@ If the alias expansion is prefixed with an exclamation point,
>  it will be treated as a shell command.  For example, defining
>  `alias.new = !gitk --all --not ORIG_HEAD`, the invocation
>  `git new` is equivalent to running the shell command
> +`gitk --all --not ORIG_HEAD`.  Note:
> ++
> +* Shell commands will be executed from the top-level directory of a
> +  repository, which may not necessarily be the current directory.
> +* `GIT_PREFIX` is set as returned by running `git rev-parse --show-prefix`
> +  from the original current directory. See linkgit:git-rev-parse[1].

Looking for '[NOTE]' in the Documentation/ files finds sections
marked up like this (this one is from Documentation/git-blame.txt):

    ...
    parser (which should be quite natural for most scripting languages).
    +
    [NOTE]
    For people who do parsing: to make it more robust, just ignore any
    lines between the first and last one ("<sha1>" and "filename" lines)
    ...

and its rendition looks like this:

https://git.github.io/htmldocs/git-blame.html#:~:text=most%20scripting%20languages).-,Note,-For%20people%20who

I am undecided if it gives a better presentation, especially when we
are giving bulletted list, so let's take the patch as-is and leave
it to interested folks to explore the use of [NOTE] _after_ this set
of patches lands as #leftoverbit follow-up topic.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v4 1/3] doc: clean up usage documentation for --no-* opts
  2024-05-03 17:30  6%     ` Junio C Hamano
@ 2024-05-06  1:39  0%       ` James Liu
  0 siblings, 0 replies; 200+ results
From: James Liu @ 2024-05-06  1:39 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Sat May 4, 2024 at 3:30 AM AEST, Junio C Hamano wrote:
> James Liu <james@jamesliu.io> writes:
>
> > We'll be adding another option to the --no-* class of options soon.
> >
> > Clean up the existing options by grouping them together in the OPTIONS
> > section, and adding missing ones to the SYNOPSIS.
>
> Nice.  
>
> > diff --git a/Documentation/git.txt b/Documentation/git.txt
> > index 7a1b112a3e..7fa75350b2 100644
> > --- a/Documentation/git.txt
> > +++ b/Documentation/git.txt
> > @@ -11,9 +11,9 @@ SYNOPSIS
> >  [verse]
> >  'git' [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
> >      [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
> > -    [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
> > -    [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
> > -    [--config-env=<name>=<envvar>] <command> [<args>]
> > +    [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--no-lazy-fetch]
> > +    [--no-optional-locks] [--bare] [--git-dir=<path>] [--work-tree=<path>]
> > +    [--namespace=<name>] [--config-env=<name>=<envvar>] <command> [<args>]
>
> Looks sensible.
>
> There still are a few options (like noglob-pathspecs) missing, but
> cleaning them up from this part of the documentation is totally
> outside the scope of this topic (#leftoverbits -- we either make
> this exhaustive, or make it clear that this is not exhaustive).
>
> Thanks.

I did notice noglob-pathspecs, but I wasn't sure if it came under the
same purview as the `--no-*` options (where a dash exists after "no").

Cheers,
James

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v4 1/3] doc: clean up usage documentation for --no-* opts
  @ 2024-05-03 17:30  6%     ` Junio C Hamano
  2024-05-06  1:39  0%       ` James Liu
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-05-03 17:30 UTC (permalink / raw)
  To: James Liu; +Cc: git

James Liu <james@jamesliu.io> writes:

> We'll be adding another option to the --no-* class of options soon.
>
> Clean up the existing options by grouping them together in the OPTIONS
> section, and adding missing ones to the SYNOPSIS.

Nice.  

> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index 7a1b112a3e..7fa75350b2 100644
> --- a/Documentation/git.txt
> +++ b/Documentation/git.txt
> @@ -11,9 +11,9 @@ SYNOPSIS
>  [verse]
>  'git' [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
>      [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
> -    [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
> -    [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
> -    [--config-env=<name>=<envvar>] <command> [<args>]
> +    [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--no-lazy-fetch]
> +    [--no-optional-locks] [--bare] [--git-dir=<path>] [--work-tree=<path>]
> +    [--namespace=<name>] [--config-env=<name>=<envvar>] <command> [<args>]

Looks sensible.

There still are a few options (like noglob-pathspecs) missing, but
cleaning them up from this part of the documentation is totally
outside the scope of this topic (#leftoverbits -- we either make
this exhaustive, or make it clear that this is not exhaustive).

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v5 4/7] refs: add support for transactional symref updates
  2024-05-02  7:47  6%           ` Patrick Steinhardt
  2024-05-02 11:10  0%             ` Karthik Nayak
@ 2024-05-02 16:51  0%             ` Junio C Hamano
  1 sibling, 0 replies; 200+ results
From: Junio C Hamano @ 2024-05-02 16:51 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Karthik Nayak, christian.couder, git

Patrick Steinhardt <ps@pks.im> writes:

> I wouldn't say we can't do that. We already do log when symrefs become
> dangling when updating references via HEAD by logging a zero OID as new
> OID. That is, if we have "HEAD -> refs/heads/foo" and you delete the
> latter, then we create a new reflog message for "HEAD" with zero OID as
> new OID.
>
> I would claim that the current behaviour where we don't create a reflog
> entry when updating a ref to become dangling is a mere bug. I think it's
> fair to declare this a #leftoverbit and handle it in a follow-up patch
> series. But it would be nice to say so in an in-code comment.

I like that.  Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 4/7] refs: add support for transactional symref updates
  2024-05-02  7:47  6%           ` Patrick Steinhardt
@ 2024-05-02 11:10  0%             ` Karthik Nayak
  2024-05-02 16:51  0%             ` Junio C Hamano
  1 sibling, 0 replies; 200+ results
From: Karthik Nayak @ 2024-05-02 11:10 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Junio C Hamano, christian.couder, git

[-- Attachment #1: Type: text/plain, Size: 3298 bytes --]

Patrick Steinhardt <ps@pks.im> writes:

> On Thu, May 02, 2024 at 05:50:47AM +0000, Karthik Nayak wrote:
>> Junio C Hamano <gitster@pobox.com> writes:
>> > Karthik Nayak <karthik.188@gmail.com> writes:
>> >> From: Karthik Nayak <karthik.188@gmail.com>
>> >> We do not add reflog for dangling symref updates, because currently
>> >> 'git-symbolic-ref' doesn't add reflog for dangling symref updates and it
>> >> would be best to keep this behavior consistent as we would move it to
>> >> start using transaction based updates in the following commit.
>> >
>> > If we are not changing the behaviour, does it deserve a four-line
>> > paragraph?  It is not like we describe every no changes (i.e. "we
>> > could break the behaviour by introducing this and that bugs, but we
>> > did not" is not something we usually say in proposed log messages).
>> >
>> > At most, if you want to highlight that behaviour, I would expect a
>> > brief mention like:
>> >
>> >     Note that a dangling symref update does not record a new reflog
>> >     entry, which is unchanged before and after this commit.
>> >
>> > As a reflog entry records name of the object that is pointed by the
>> > ref (either directly or indirectly) before and after an operation,
>> > an operation that involve a dangling reflog that does not point at
>> > any object cannot be expressed in a reflog, no?  It is way too late
>> > to change this, but it would have been interesting if the design of
>> > reflog had a room to log the change of symbolic ref target as well
>> > as object names.  It would have allowed us to say "HEAD at time T
>> > pointed at refs/heads/main (which did not exist)", "HEAD at time T+1
>> > directly pointed at commit X (detached)", "HEAD at time T+2 pointed
>> > at refs/heads/next", etc. and allowed us to much more cleanly
>> > support "previous branch".
>> >
>>
>> While I agree that four lines may seem excessive, I think it is indeed
>> an important point to note. Mostly because this shows that when doing
>> dangling symref updates, there is no record of this update. The best
>> situation would be like you mentioned, to record the symref target
>> changes. But even with the current design, it would have been nice to at
>> least acknowledge that there was some update done to the symref. By
>> having zero-oid for the new and old value in the reflog. But seems like
>> we can't do that either.
>
> I wouldn't say we can't do that. We already do log when symrefs become
> dangling when updating references via HEAD by logging a zero OID as new
> OID. That is, if we have "HEAD -> refs/heads/foo" and you delete the
> latter, then we create a new reflog message for "HEAD" with zero OID as
> new OID.
>
> I would claim that the current behaviour where we don't create a reflog
> entry when updating a ref to become dangling is a mere bug. I think it's
> fair to declare this a #leftoverbit and handle it in a follow-up patch
> series. But it would be nice to say so in an in-code comment.
>

I think _can't_ wasn't the best terminology. My previous series actually
added a reflog, but I noticed a bunch of tests were failing and I think
it made sense to keep the existing behaviour.

But addressing it as a bug would definitely be a good way to go and fix
this, I'll add a comment in the code for now.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 4/7] refs: add support for transactional symref updates
  @ 2024-05-02  7:47  6%           ` Patrick Steinhardt
  2024-05-02 11:10  0%             ` Karthik Nayak
  2024-05-02 16:51  0%             ` Junio C Hamano
  0 siblings, 2 replies; 200+ results
From: Patrick Steinhardt @ 2024-05-02  7:47 UTC (permalink / raw)
  To: Karthik Nayak; +Cc: Junio C Hamano, christian.couder, git

[-- Attachment #1: Type: text/plain, Size: 2947 bytes --]

On Thu, May 02, 2024 at 05:50:47AM +0000, Karthik Nayak wrote:
> Junio C Hamano <gitster@pobox.com> writes:
> > Karthik Nayak <karthik.188@gmail.com> writes:
> >> From: Karthik Nayak <karthik.188@gmail.com>
> >> We do not add reflog for dangling symref updates, because currently
> >> 'git-symbolic-ref' doesn't add reflog for dangling symref updates and it
> >> would be best to keep this behavior consistent as we would move it to
> >> start using transaction based updates in the following commit.
> >
> > If we are not changing the behaviour, does it deserve a four-line
> > paragraph?  It is not like we describe every no changes (i.e. "we
> > could break the behaviour by introducing this and that bugs, but we
> > did not" is not something we usually say in proposed log messages).
> >
> > At most, if you want to highlight that behaviour, I would expect a
> > brief mention like:
> >
> >     Note that a dangling symref update does not record a new reflog
> >     entry, which is unchanged before and after this commit.
> >
> > As a reflog entry records name of the object that is pointed by the
> > ref (either directly or indirectly) before and after an operation,
> > an operation that involve a dangling reflog that does not point at
> > any object cannot be expressed in a reflog, no?  It is way too late
> > to change this, but it would have been interesting if the design of
> > reflog had a room to log the change of symbolic ref target as well
> > as object names.  It would have allowed us to say "HEAD at time T
> > pointed at refs/heads/main (which did not exist)", "HEAD at time T+1
> > directly pointed at commit X (detached)", "HEAD at time T+2 pointed
> > at refs/heads/next", etc. and allowed us to much more cleanly
> > support "previous branch".
> >
> 
> While I agree that four lines may seem excessive, I think it is indeed
> an important point to note. Mostly because this shows that when doing
> dangling symref updates, there is no record of this update. The best
> situation would be like you mentioned, to record the symref target
> changes. But even with the current design, it would have been nice to at
> least acknowledge that there was some update done to the symref. By
> having zero-oid for the new and old value in the reflog. But seems like
> we can't do that either.

I wouldn't say we can't do that. We already do log when symrefs become
dangling when updating references via HEAD by logging a zero OID as new
OID. That is, if we have "HEAD -> refs/heads/foo" and you delete the
latter, then we create a new reflog message for "HEAD" with zero OID as
new OID.

I would claim that the current behaviour where we don't create a reflog
entry when updating a ref to become dangling is a mere bug. I think it's
fair to declare this a #leftoverbit and handle it in a follow-up patch
series. But it would be nice to say so in an in-code comment.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3/3] color: add support for 12-bit RGB colors
  2024-04-30 17:31  6%     ` Junio C Hamano
@ 2024-04-30 18:41  0%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-04-30 18:41 UTC (permalink / raw)
  To: Jeff King; +Cc: Beat Bolli, git, Beat Bolli

Junio C Hamano <gitster@pobox.com> writes:

>>> @@ -146,7 +146,10 @@ test_expect_success 'non-hex character in RGB color' '
>>>  	invalid_color "#12x456" &&
>>>  	invalid_color "#123x56" &&
>>>  	invalid_color "#1234x6" &&
>>> -	invalid_color "#12345x"
>>> +	invalid_color "#12345x" &&
>>> +	invalid_color "#x23" &&
>>> +	invalid_color "#1x3" &&
>>> +	invalid_color "#12x"
>>>  '
>>
>> This made me wonder what we'd do with "#1", "#12", "#1234", etc. Looking
>> at the code change, I think we'd continue to reject them. I wonder if it
>> is worth covering here.
>
> Worth covering in this test, yes, but I am perfectly OK with leaving
> it outside the series as a #leftoverbit clean-up.

Ah, I take it back.  The preimage was added by [2/3] so it is fair
to say that that step would be the right place to do that from the
get-go.


^ permalink raw reply	[relevance 0%]

* Re: [PATCH 3/3] color: add support for 12-bit RGB colors
  @ 2024-04-30 17:31  6%     ` Junio C Hamano
  2024-04-30 18:41  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-04-30 17:31 UTC (permalink / raw)
  To: Jeff King; +Cc: Beat Bolli, git, Beat Bolli

Jeff King <peff@peff.net> writes:

> On Mon, Apr 29, 2024 at 06:48:49PM +0200, Beat Bolli wrote:
>
>> -test_expect_success '24-bit colors' '
>> -	color "#ff00ff black" "[38;2;255;0;255;40m"
>> +test_expect_success 'RGB colors' '
>> +	color "#ff00ff #0f0" "[38;2;255;0;255;48;2;0;255;0m"
>>  '
>
> Heh, I would still think of it as a shorthand for 24-bit color, but I
> guess you could argue it is now 12-bit color. :)
>
> (Only observing, I think the new name is fine).
>
>>  test_expect_success '"default" foreground' '
>> @@ -146,7 +146,10 @@ test_expect_success 'non-hex character in RGB color' '
>>  	invalid_color "#12x456" &&
>>  	invalid_color "#123x56" &&
>>  	invalid_color "#1234x6" &&
>> -	invalid_color "#12345x"
>> +	invalid_color "#12345x" &&
>> +	invalid_color "#x23" &&
>> +	invalid_color "#1x3" &&
>> +	invalid_color "#12x"
>>  '
>
> This made me wonder what we'd do with "#1", "#12", "#1234", etc. Looking
> at the code change, I think we'd continue to reject them. I wonder if it
> is worth covering here.

Worth covering in this test, yes, but I am perfectly OK with leaving
it outside the series as a #leftoverbit clean-up.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update`
  2024-04-29  7:02  0%         ` Patrick Steinhardt
@ 2024-04-29  7:55  0%           ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2024-04-29  7:55 UTC (permalink / raw)
  To: Patrick Steinhardt
  Cc: Junio C Hamano, Phillip Wood, Karthik Nayak, christian.couder, git

On Mon, Apr 29, 2024 at 09:02:56AM +0200, Patrick Steinhardt wrote:

> > IMHO these should _all_ be forbidden, because we only want to allow the
> > more limited pseudoref names everywhere (and never mischievous ones like
> > "config" or whatever). And once we are doing that, then show-ref has no
> > need to check the format. It can just call read_ref() and it either gets
> > an answer or doesn't.
> > 
> > I don't know if that is a #leftoverbit though. It perhaps more
> > complicated than that.
> 
> Yeah, this is something that I've repeatedly stumbled over myself. If I
> remember correctly, the plan was to clean up and consolidate all these
> different functions we have for checking ref names such that they become
> easier to use and hopefully lead to more consistent behaviour.

I think the code changes here aren't too bad (modulo some
head-scratching I had to do around per-worktree refs). I'll post a
series in a moment (split off from here since we're far off topic from
the original thread).

> In any case, I very much agree that git-update-ref(1) should refuse to
> write refs with names that are known-bad. There should probably be an
> escape hatch though that at least allows you to _delete_ those, or
> otherwise there is no way to remove such a ref in the reftable repo.
> Well, except for meddling with the binary format, but I doubt that
> anybody would really want to do that.

Yeah, ironically deleting is the one thing you cannot do with them even
right now. ;) That is because the supposedly-looser refname_is_safe() is
actually tighter.

It would be tough to loosen it safely, since you don't want to allow
deleting arbitrary files in .git. Or worse, escaping .git via clever
paths, symlinks, etc. So I think at most you'd want some kind of "trust
me, for this command don't bother with ref format checks" flag.

Or alternatively, refname_is_safe() should become a per-backend thing.
And then reftables can say "everything is safe", because the ref names
are never used as paths (I think, anyway; I didn't follow all of the
discussion around per-worktree refs, pseudorefs, etc).

-Peff

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update`
  2024-04-26 21:15  5%       ` Jeff King
@ 2024-04-29  7:02  0%         ` Patrick Steinhardt
  2024-04-29  7:55  0%           ` Jeff King
  0 siblings, 1 reply; 200+ results
From: Patrick Steinhardt @ 2024-04-29  7:02 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Phillip Wood, Karthik Nayak, christian.couder, git

[-- Attachment #1: Type: text/plain, Size: 3305 bytes --]

On Fri, Apr 26, 2024 at 05:15:29PM -0400, Jeff King wrote:
> On Fri, Apr 26, 2024 at 12:31:36PM -0700, Junio C Hamano wrote:
> 
> > This is an unrelated #leftoverbits tangent, but while trying to find
> > out the reason why "[_add]" in the title looked irritating to me, I
> > noticed that builtin/show-ref.c includes <refs/refs-internal.h>.  I
> > do not know what it uses from the "internal" implementation detail,
> > but the API may have to be cleaned up so that a random "client"
> > caller do not have to do so.
> 
> There are two issues. One is the use of refs_read_raw_ref(), added by
> Patrick's 9080a7f178 (builtin/show-ref: add new mode to check for
> reference existence, 2023-10-31). And it argues there why the regular
> API is unsufficient (mostly because it does not protect errno).
> 
> But the more interesting one is a call to refname_is_safe(), added
> recently by Phillip's 1dbe401563 (show-ref --verify: accept pseudorefs,
> 2024-02-07). Looking at that commit, the intent was to allow pseudo-refs
> by loosening the conditional that checked "HEAD" to allow "FOO_BAR" but
> not "foobar" outside of "refs/". We enforce the all-caps pseudoref
> syntax in is_refname_safe().
> 
> The proper API there is I think check_ref_format() with ALLOW_ONELEVEL.
> But you shouldn't need to do that, because the refs code should be
> checking the names itself (using check_ref_format() usually, but falling
> back to refname_is_safe() if the ALLOW_BAD_NAME flag is passed).
> 
> And I think there _is_ a bug there. The idea of those two functions is
> that check_ref_format() would allow a subset of what refname_is_safe()
> does. We'd fall back to the latter when deleting, but not otherwise
> allow creation or updates.
> 
> However, it looks like check_ref_format() doesn't enforce the pseudo-ref
> syntax. It will happily resolve this:
> 
>   git rev-parse HEAD >.git/foo
>   git rev-parse foo
> 
> and even update it:
> 
>   git update-ref foo HEAD
> 
> though curiously we will refuse to delete it:
> 
>   $ git update-ref -d foo
>   error: refusing to update ref with bad name 'foo'
> 
> since that sets the ALLOW_BAD_NAME flag!
> 
> IMHO these should _all_ be forbidden, because we only want to allow the
> more limited pseudoref names everywhere (and never mischievous ones like
> "config" or whatever). And once we are doing that, then show-ref has no
> need to check the format. It can just call read_ref() and it either gets
> an answer or doesn't.
> 
> I don't know if that is a #leftoverbit though. It perhaps more
> complicated than that.

Yeah, this is something that I've repeatedly stumbled over myself. If I
remember correctly, the plan was to clean up and consolidate all these
different functions we have for checking ref names such that they become
easier to use and hopefully lead to more consistent behaviour.

In any case, I very much agree that git-update-ref(1) should refuse to
write refs with names that are known-bad. There should probably be an
escape hatch though that at least allows you to _delete_ those, or
otherwise there is no way to remove such a ref in the reftable repo.
Well, except for meddling with the binary format, but I doubt that
anybody would really want to do that.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v4 2/7] files-backend: extract out `create_symref_lock`
  2024-04-26 21:39  5%     ` Junio C Hamano
@ 2024-04-28 19:57  0%       ` Karthik Nayak
  0 siblings, 0 replies; 200+ results
From: Karthik Nayak @ 2024-04-28 19:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: christian.couder, git, ps

[-- Attachment #1: Type: text/plain, Size: 6127 bytes --]

Junio C Hamano <gitster@pobox.com> writes:

> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> From: Karthik Nayak <karthik.188@gmail.com>
>>
>> The function `create_symref_locked` creates a symref by creating a
>> '<symref>.lock' file and then committing the symref lock, which creates
>> the final symref.
>>
>> Split this into two individual functions `create_and_commit_symref` and
>> `create_symref_locked`. This way we can create the symref lock and
>> commit it at different times. This will be used to provide symref
>> support in `git-update-ref(1)`.
>
> It is a confusing way to describe what this patch did, though.  If
> you truly splitted create_symref_locked() into two, you would have
> functions A and B, and existing callers of create_symref_locked()
> would be changed to call A() and then B().  I do not think such a
> split would make sense in this case, but the above description gives
> an impression that it was what you did.
>
> In reality, an early part of create_symref_locked() was made into a
> separate helper function that can be called from callers other than
> create_symref_locked(), and because the helper got a name too
> similar to the original, you had to rename create_symref_locked() to
> create_and_commit_symref().  The existing callers of it are not
> affected, modulo the name change.
>
> Perhaps
>
>     Split the early half of create_symref_locked() into a new helper
>     funciton create_symref_lock().  Because the name of the new
>     function is too similar to the original, rename the original to
>     create_and_commit_symref() to avoid confusion.
>
>     The new helper will be used to ...
>
> or something?
>

Thanks. I agree with what you're saying. I would also s/Split/Extract
perhaps because it drives the point better.

>> -static int create_symref_locked(struct files_ref_store *refs,
>> -				struct ref_lock *lock, const char *refname,
>> -				const char *target, const char *logmsg)
>> +static int create_symref_lock(struct files_ref_store *refs,
>> +			      struct ref_lock *lock, const char *refname,
>> +			      const char *target)
>>  {
>> +	if (!fdopen_lock_file(&lock->lk, "w"))
>> +		return error("unable to fdopen %s: %s",
>> +			     get_lock_file_path(&lock->lk), strerror(errno));
>> +
>> +	/* no error check; commit_ref will check ferror */
>> +	fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target);
>
> This was a bit puzzling (see below).
>
>> +	return 0;
>> +}
>> +
>> +static int create_and_commit_symref(struct files_ref_store *refs,
>> +				    struct ref_lock *lock, const char *refname,
>> +				    const char *target, const char *logmsg)
>> +{
>> +	int ret;
>> +
>>  	if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
>>  		update_symref_reflog(refs, lock, refname, target, logmsg);
>>  		return 0;
>>  	}
>
>     Offtopic: we might want to start planning to deprecate creation
>     of "symlink refs".  Linus originally used a symlink for
>     .git/HEAD, but 9f0bb90d (core.prefersymlinkrefs: use symlinks
>     for .git/HEAD, 2006-05-02) made it default not to use of
>     symbolic links.  As long as we preserve the ability to work on a
>     repository whose HEAD still uses a symbolic link, I'd hope
>     nothing would break (#leftoverbits).
>
> Let me rearrange this hunk to show the original first:
>
>> -	if (!fdopen_lock_file(&lock->lk, "w"))
>> -		return error("unable to fdopen %s: %s",
>> -			     get_lock_file_path(&lock->lk), strerror(errno));
>> -	update_symref_reflog(refs, lock, refname, target, logmsg);
>> -	/* no error check; commit_ref will check ferror */
>> -	fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target);
>> -	if (commit_ref(lock) < 0)
>> -		return error("unable to write symref for %s: %s", refname,
>> -			     strerror(errno));
>
> The original in create_symref_locked() created a lockfile, called
> update_symref_reflog(), and called commit_ref() to commit the thing.
>
> The "no error check" comment is about detecting an error while
> writing into the lock file.  It came from 370e5ad6 (create_symref:
> use existing ref-lock code, 2015-12-29).  Because the fprintf() call
> was immediately followed by commit_ref(), and the code assumed that
> commit_ref() will check ferror(), we do not bother checking if the
> fprintf() call fails to write the contents correctly.
>
>> +	ret = create_symref_lock(refs, lock, refname, target);
>> +	if (!ret) {
>> +		update_symref_reflog(refs, lock, refname, target, logmsg);
>>
>> +		if (commit_ref(lock) < 0)
>> +			return error("unable to write symref for %s: %s", refname,
>> +				     strerror(errno));
>> +	}
>
> The new code lets create_symref_lock() to create a lockfile, and
> does the rest here.  commit_ref() does call commit_lock_file(),
> which eventually passes the control to close_tempfile() and a
> write error can be detected there.
>
> But the point of this patch is that the creation of the locked
> symref file PLUS writing its new contents (which is done by
> create_symref_lock()) can be done way ahead of the remainder that
> eventually does commit_ref().  So it smells a bit[*] dubious that we
> still leave the error from fprintf() ignored in the "early half" in
> the rearranged code.
>
> 	Side note: it is a "bit", as it is unlikely that we will do
> 	something to clear the ferror() from the (FILE *) in the
> 	meantime.
>

You're right. I would say that perhaps it is a bit more than a 'bit
dubious' since `commit_ref()` being called after, is no longer a
guarantee. I'll go ahead and add error handling here.

>> @@ -1960,7 +1973,8 @@ static int files_create_symref(struct ref_store *ref_store,
>>  		return -1;
>>  	}
>>
>> -	ret = create_symref_locked(refs, lock, refname, target, logmsg);
>> +	ret = create_and_commit_symref(refs, lock, refname, target, logmsg);
>> +
>>  	unlock_ref(lock);
>>  	return ret;
>>  }
>
> This hunk shows the "original function was renamed; there is no
> other changes visible to the caller" nature of this rearrangement.
>
> The extra blank line is probably a nice touch.

Thanks. I'm sure it's not the best idea to introduce whitespace, but this
felt more readable here.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 690 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v4 2/7] files-backend: extract out `create_symref_lock`
  @ 2024-04-26 21:39  5%     ` Junio C Hamano
  2024-04-28 19:57  0%       ` Karthik Nayak
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-04-26 21:39 UTC (permalink / raw)
  To: Karthik Nayak; +Cc: christian.couder, git, ps

Karthik Nayak <karthik.188@gmail.com> writes:

> From: Karthik Nayak <karthik.188@gmail.com>
>
> The function `create_symref_locked` creates a symref by creating a
> '<symref>.lock' file and then committing the symref lock, which creates
> the final symref.
>
> Split this into two individual functions `create_and_commit_symref` and
> `create_symref_locked`. This way we can create the symref lock and
> commit it at different times. This will be used to provide symref
> support in `git-update-ref(1)`.

It is a confusing way to describe what this patch did, though.  If
you truly splitted create_symref_locked() into two, you would have
functions A and B, and existing callers of create_symref_locked()
would be changed to call A() and then B().  I do not think such a
split would make sense in this case, but the above description gives
an impression that it was what you did.

In reality, an early part of create_symref_locked() was made into a
separate helper function that can be called from callers other than
create_symref_locked(), and because the helper got a name too
similar to the original, you had to rename create_symref_locked() to
create_and_commit_symref().  The existing callers of it are not
affected, modulo the name change.

Perhaps

    Split the early half of create_symref_locked() into a new helper
    funciton create_symref_lock().  Because the name of the new
    function is too similar to the original, rename the original to
    create_and_commit_symref() to avoid confusion.

    The new helper will be used to ...

or something?

> -static int create_symref_locked(struct files_ref_store *refs,
> -				struct ref_lock *lock, const char *refname,
> -				const char *target, const char *logmsg)
> +static int create_symref_lock(struct files_ref_store *refs,
> +			      struct ref_lock *lock, const char *refname,
> +			      const char *target)
>  {
> +	if (!fdopen_lock_file(&lock->lk, "w"))
> +		return error("unable to fdopen %s: %s",
> +			     get_lock_file_path(&lock->lk), strerror(errno));
> +
> +	/* no error check; commit_ref will check ferror */
> +	fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target);

This was a bit puzzling (see below).

> +	return 0;
> +}
> +
> +static int create_and_commit_symref(struct files_ref_store *refs,
> +				    struct ref_lock *lock, const char *refname,
> +				    const char *target, const char *logmsg)
> +{
> +	int ret;
> +
>  	if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
>  		update_symref_reflog(refs, lock, refname, target, logmsg);
>  		return 0;
>  	}

    Offtopic: we might want to start planning to deprecate creation
    of "symlink refs".  Linus originally used a symlink for
    .git/HEAD, but 9f0bb90d (core.prefersymlinkrefs: use symlinks
    for .git/HEAD, 2006-05-02) made it default not to use of
    symbolic links.  As long as we preserve the ability to work on a
    repository whose HEAD still uses a symbolic link, I'd hope
    nothing would break (#leftoverbits).

Let me rearrange this hunk to show the original first:

> -	if (!fdopen_lock_file(&lock->lk, "w"))
> -		return error("unable to fdopen %s: %s",
> -			     get_lock_file_path(&lock->lk), strerror(errno));
> -	update_symref_reflog(refs, lock, refname, target, logmsg);
> -	/* no error check; commit_ref will check ferror */
> -	fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target);
> -	if (commit_ref(lock) < 0)
> -		return error("unable to write symref for %s: %s", refname,
> -			     strerror(errno));

The original in create_symref_locked() created a lockfile, called
update_symref_reflog(), and called commit_ref() to commit the thing.

The "no error check" comment is about detecting an error while
writing into the lock file.  It came from 370e5ad6 (create_symref:
use existing ref-lock code, 2015-12-29).  Because the fprintf() call
was immediately followed by commit_ref(), and the code assumed that
commit_ref() will check ferror(), we do not bother checking if the
fprintf() call fails to write the contents correctly.

> +	ret = create_symref_lock(refs, lock, refname, target);
> +	if (!ret) {
> +		update_symref_reflog(refs, lock, refname, target, logmsg);
>  
> +		if (commit_ref(lock) < 0)
> +			return error("unable to write symref for %s: %s", refname,
> +				     strerror(errno));
> +	}

The new code lets create_symref_lock() to create a lockfile, and
does the rest here.  commit_ref() does call commit_lock_file(),
which eventually passes the control to close_tempfile() and a
write error can be detected there.

But the point of this patch is that the creation of the locked
symref file PLUS writing its new contents (which is done by
create_symref_lock()) can be done way ahead of the remainder that
eventually does commit_ref().  So it smells a bit[*] dubious that we
still leave the error from fprintf() ignored in the "early half" in
the rearranged code.

	Side note: it is a "bit", as it is unlikely that we will do
	something to clear the ferror() from the (FILE *) in the
	meantime.

> @@ -1960,7 +1973,8 @@ static int files_create_symref(struct ref_store *ref_store,
>  		return -1;
>  	}
>  
> -	ret = create_symref_locked(refs, lock, refname, target, logmsg);
> +	ret = create_and_commit_symref(refs, lock, refname, target, logmsg);
> +
>  	unlock_ref(lock);
>  	return ret;
>  }

This hunk shows the "original function was renamed; there is no
other changes visible to the caller" nature of this rearrangement.

The extra blank line is probably a nice touch.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update`
  2024-04-26 19:31  6%     ` Junio C Hamano
@ 2024-04-26 21:15  5%       ` Jeff King
  2024-04-29  7:02  0%         ` Patrick Steinhardt
  0 siblings, 1 reply; 200+ results
From: Jeff King @ 2024-04-26 21:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Phillip Wood, Karthik Nayak, christian.couder, git, ps

On Fri, Apr 26, 2024 at 12:31:36PM -0700, Junio C Hamano wrote:

> This is an unrelated #leftoverbits tangent, but while trying to find
> out the reason why "[_add]" in the title looked irritating to me, I
> noticed that builtin/show-ref.c includes <refs/refs-internal.h>.  I
> do not know what it uses from the "internal" implementation detail,
> but the API may have to be cleaned up so that a random "client"
> caller do not have to do so.

There are two issues. One is the use of refs_read_raw_ref(), added by
Patrick's 9080a7f178 (builtin/show-ref: add new mode to check for
reference existence, 2023-10-31). And it argues there why the regular
API is unsufficient (mostly because it does not protect errno).

But the more interesting one is a call to refname_is_safe(), added
recently by Phillip's 1dbe401563 (show-ref --verify: accept pseudorefs,
2024-02-07). Looking at that commit, the intent was to allow pseudo-refs
by loosening the conditional that checked "HEAD" to allow "FOO_BAR" but
not "foobar" outside of "refs/". We enforce the all-caps pseudoref
syntax in is_refname_safe().

The proper API there is I think check_ref_format() with ALLOW_ONELEVEL.
But you shouldn't need to do that, because the refs code should be
checking the names itself (using check_ref_format() usually, but falling
back to refname_is_safe() if the ALLOW_BAD_NAME flag is passed).

And I think there _is_ a bug there. The idea of those two functions is
that check_ref_format() would allow a subset of what refname_is_safe()
does. We'd fall back to the latter when deleting, but not otherwise
allow creation or updates.

However, it looks like check_ref_format() doesn't enforce the pseudo-ref
syntax. It will happily resolve this:

  git rev-parse HEAD >.git/foo
  git rev-parse foo

and even update it:

  git update-ref foo HEAD

though curiously we will refuse to delete it:

  $ git update-ref -d foo
  error: refusing to update ref with bad name 'foo'

since that sets the ALLOW_BAD_NAME flag!

IMHO these should _all_ be forbidden, because we only want to allow the
more limited pseudoref names everywhere (and never mischievous ones like
"config" or whatever). And once we are doing that, then show-ref has no
need to check the format. It can just call read_ref() and it either gets
an answer or doesn't.

I don't know if that is a #leftoverbit though. It perhaps more
complicated than that.

-Peff

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update`
  @ 2024-04-26 19:31  6%     ` Junio C Hamano
  2024-04-26 21:15  5%       ` Jeff King
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-04-26 19:31 UTC (permalink / raw)
  To: Karthik Nayak; +Cc: christian.couder, git, ps

Karthik Nayak <karthik.188@gmail.com> writes:

> From: Karthik Nayak <karthik.188@gmail.com>
> Subject: Re: [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update`
>
> The `ref_transaction[_add]_update` functions obtain ref information and
> flags to create a `ref_update` and add it to the transaction at hand.

Just a very minor irritation, but ref_transaction_add_update() is a
function used internally in the ref subsystem and is exported only
because its visibility needs to cross file boundaries between refs.c
and refs/*backend.c files.

It would be better to only mention ref_transaction_update() in the
title, and talk about the need to make matching adjustment to
ref_transaction_add_update(), which is an internal function, in the
body of the log message.

This is an unrelated #leftoverbits tangent, but while trying to find
out the reason why "[_add]" in the title looked irritating to me, I
noticed that builtin/show-ref.c includes <refs/refs-internal.h>.  I
do not know what it uses from the "internal" implementation detail,
but the API may have to be cleaned up so that a random "client"
caller do not have to do so.

The patch itself looked good.  Thanks.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH 2/2] maintenance: running maintenance should not stop on errors
  @ 2024-04-17 15:41  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-04-17 15:41 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> In https://github.com/microsoft/git/issues/623, it was reported that
> maintenance stops on a missing repository, omitting the remaining
> repositories that were scheduled for maintenance.
>
> This is undesirable, as it should be a best effort type of operation.
>
> It should still fail due to the missing repository, of course, but not
> leave the non-missing repositories in unmaintained shapes.
>
> Let's use `for-each-repo`'s shiny new `--keep-going` option that we just
> introduced for that very purpose.
>
> This change will be picked up when running `git maintenance start`,
> which is run implicitly by `scalar reconfigure`.
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  builtin/gc.c           | 7 ++++---
>  t/t7900-maintenance.sh | 6 +++---
>  2 files changed, 7 insertions(+), 6 deletions(-)

Other than the N_("") thing Eric noticed, I didn't find anything
glaringly wrong in these two patches.  Nicely done.

We may want to fold overly long lines we see in the patch, but I'd
prefer to see it done as a post-cleanup task (#leftoverbits), as the
lines in the preimage of the patch are already overly long.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] imap-send: increase command size limit
  @ 2024-04-16 16:08  6%   ` René Scharfe
  0 siblings, 0 replies; 200+ results
From: René Scharfe @ 2024-04-16 16:08 UTC (permalink / raw)
  To: Jeff King; +Cc: Git List

Am 15.04.24 um 20:55 schrieb Jeff King:
> On Sun, Apr 14, 2024 at 06:47:52PM +0200, René Scharfe wrote:
>
>> While 1KB is plenty for user names, passwords and mailbox names,
>> there's no point in limiting our commands like that.  Call xstrvfmt()
>> instead of open-coding it and use strbuf to format the command to
>> send, as we need its length.  Fail hard if it exceeds INT_MAX, because
>> socket_write() can't take more than that.
>
> Hmm. I applaud your attention to detail, but this INT_MAX thing is ugly. ;)

It is.  I thought about using cast_size_t_to_int() instead, but decided
to preserve the original error message.

> Shouldn't socket_write() just use size_t / ssize_t?

Probably size_t.

> In particular, this made me wonder what we would do for larger items.
> Like, say, the actual message to be uploaded. And indeed, we use a
> strbuf to read in the messages and pass the whole buffer for each to
> socket_write(). So we'd possibly quietly truncate such a message.

Hmm, perhaps we should at least sprinkle in some more overflow checks?

> Fixing it is a little more complicated than switching to size_t, because
> the underlying SSL_write() uses an int. So we'd probably need some
> looping, similar to xwrite().

Or SSL_write_ex(), which takes and returns size_t.  It was added in
OpenSSL 1.1.1, which reached its end of life half a year ago.

https://www.openssl.org/docs/man1.1.1/man3/SSL_write.html
https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/

> In practice I doubt this is ever an issue. 2GB emails are not likely to
> be usable in general.

Tough.  Who likes to get multi-GB patches in their inbox?  Heard of
people exchanging CD images by email decades ago, though, so I
wouldn't rule this out totally.  Perhaps that's the last puzzle piece
to convert game studios to perform email reviews of asset-heavy
binary diffs? ;-)

> And I kind of doubt that this is a reasonable
> vector for attacks, since the inputs to imap-send would generally come
> from the user themselves (and certainly truncating the attack message is
> probably not that interesting, though I imagine one could convince
> write_in_full() to do an out-of-bounds read as a size_t becomes a
> negative int which becomes a large size_t again).

Right.  If you can get a user to upload more than 2GB of hostile data to
their mail server then you don't need to bother crafting an integer
overflow exploit.

Still, checking for overflow instead of truncating silently seems like a
good idea even for half-dead low-impact code.  #leftoverbits

René

^ permalink raw reply	[relevance 6%]

* Re: [RFC] bisect: Introduce skip-when to automatically skip commits
  2024-04-08 16:49  5%                 ` Junio C Hamano
@ 2024-04-10 10:39  0%                   ` Olliver Schinagl
  0 siblings, 0 replies; 200+ results
From: Olliver Schinagl @ 2024-04-10 10:39 UTC (permalink / raw)
  To: Junio C Hamano, phillip.wood123
  Cc: phillip.wood, git, Christian Couder, Stefan Haller

On 08-04-2024 18:49, Junio C Hamano wrote:
> phillip.wood123@gmail.com writes:
>
>>>> get_terms() wants to read the first line into `term_bad` and the
>>>> second line into `term_good` so it makes sense that it uses two
>>>> calls to `strbuf_getline()` to do that. It does not want to read
>>>> the whole file into a single buffer as we do here.
>>> Right, but I why not use strbuf_getline()?
>> Because you want the whole file, not just one line as the script name
>> could potentially contain a newline
> It is technically true, but it somehow sounds like an implausible
> scenario to me.  The real reason why read_file() is preferrable is
> because you do not have to write, and we do not want to see you write,
> the whole "open (and handle error), read, chomp, and return" sequence.
>
> I would even suspect that get_terms() is a poorly written
> anti-pattern.  If I were adding that function to the system today, I
> wouldn't be surprised if I did read_file() the whole thing and
> worked in-core to split two items out.

So I've peaked at it, and think something like:

+int bisect_read_terms(const char **read_bad, const char **read_good)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       if (!strbuf_read_file(&sb, git_path_bisect_terms(), 0)) {
+               *read_bad = "bad";
+               *read_good = "good";
+               return -1;
+       }
+
+       terms = strbuf_split(&sb);
+       *term_bad = strbuf_detach(terms[0], NULL);
+       *term_good = strbuf_detach(terms[1], NULL);
+
+       strbuf_release(&sb);
+
+       return 0;
+}

would do the trick. This function could then be called from 
builtin/bisect.c as well to have a single interface. Right now, there's 
two ways to do the same thing, just because the arguments to the 
function are different, and the body is slightly different, but the same.

Shall I send a MR with this?

>
>> If I understand correctly we're encouraging the user to run "git
>> bisect skip" from the post checkout script. Doesn't that mean we'll
>> end up with a set of processes that look like
>>
>> 	- git bisect start
>> 	  - post checkout script
>>              - git bisect skip
>>                - post checkout script
>>                  - git bisect skip
>>                    ...
>>
>> as the "git bisect start" is waiting for the post checkout script to
>> finish running, but that script is waiting for "git bisect skip" to
>> finish running and so on. Each of those processes takes up system
>> resources, similar to how a recursive function can exhaust the
>> available stack space by calling itself over and over again.
> True.  What such a post-checkout script can do is to only mark the
> HEAD as "untestable", just like a run script given to "bisect run"
> signals that fact by returnint 125.  And at that point, I doubt it
> makes sense to add such a post-checkout script for the purpose of
> allowing "bisect skip".
>
> Having said that, a post-checkout script and pre-resume script may
> have a huge value in helping those whose tests cannot be automated
> (in other words, they cannot do "git bisect run") when they need to
> tweak the working tree during bisection.  We all have seen, during a
> bisection session that spans a segment of history that has another
> bug that affects our test *but* is orthogonal to the bug we are
> chasing, that we "cherry-pick --no-commit" the fix for that other
> problem inside "git bisect run" script.  It might look something
> like
>
>      #!/bin/sh
>      if git merge-base --is-ancestor $the_other_bug HEAD
>      then
> 	# we need the fix
> 	git cherry-pick --no-commit $fix_for_the_other_bug ||
> 	exit 125
>      fi
>
>      make test
>      status=$?
>      git reset --hard ;# undo the cherry-pick
>      exit $status
>
> But to those whose test is not a good match to "git bisect run", if
> we had a mechanism to tweak the checked out working tree after the
> "bisect next" (which is an internal mechanism that "bisect good",
> "bisect bad", and "bisect skip" share to give you the next HEAD and
> the working tree to test) checks out the working tree before it
> gives the control back to you, we could split the above script into
> two parts and throw the "conditionally cherry-pick the fix" part
> into that mechanism.  We'd need to have a companion script to "redo
> the damage" (the "reset --hard" in the above illustration) if this
> were to work seamlessly.  That obviously is totally orthogonal to
> what we are discussing in this thread, but may make a good #leftoverbits
> material (but not for novices).

While completly orthonogal, I agree; it would be nice to have and 
'abuse' for the bisect-skip usecase. So if we ignore the fact that it 
can be abused for this (which I don't think is a bad thing, it just 
risks the recursive issue Phillip mentioned.


As I'm not familiar with the deeps of bisect, I just use it as a dumb 
simple user, e.g. start; good, bad; I'm not sure the usecase you are 
describing is completly clear to me.

Are you saying 'git bisect run` is great, but not useful in all 
situations, and so in some cases, we want what you just said? Or would 
this also be part of git bisect run?

I've drafted the post-checkout and pre-resume here: 
https://gitlab.com/olliver/git/-/commit/6b5415377600551c0d94a359fd4b8ca7a3678dcf 
where I'm not clear on what the best points are for for the pre/post 
points. I've put the 'pre' bit in the bisect_state function, as that was 
being triggered by many suboptions, but might not be correct based on 
your answer to the above 
(https://gitlab.com/olliver/git/-/commit/6b5415377600551c0d94a359fd4b8ca7a3678dcf#46324e17f99db64a67eb9a5983ffc3a680914ee3_1001_1028). 
The post-checkout part, I've put in bisect_next 
(https://gitlab.com/olliver/git/-/commit/43993fca32f174f1005c7a445887c0ba5c4036b5#46324e17f99db64a67eb9a5983ffc3a680914ee3_672_717) 
which seems to match what you described.


Olliver


^ permalink raw reply	[relevance 0%]

* Re: [RFC] bisect: Introduce skip-when to automatically skip commits
  @ 2024-04-08 16:49  5%                 ` Junio C Hamano
  2024-04-10 10:39  0%                   ` Olliver Schinagl
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-04-08 16:49 UTC (permalink / raw)
  To: phillip.wood123
  Cc: Olliver Schinagl, phillip.wood, git, Christian Couder, Stefan Haller

phillip.wood123@gmail.com writes:

>>> get_terms() wants to read the first line into `term_bad` and the
>>> second line into `term_good` so it makes sense that it uses two
>>> calls to `strbuf_getline()` to do that. It does not want to read
>>> the whole file into a single buffer as we do here.
>> Right, but I why not use strbuf_getline()?
>
> Because you want the whole file, not just one line as the script name
> could potentially contain a newline

It is technically true, but it somehow sounds like an implausible
scenario to me.  The real reason why read_file() is preferrable is
because you do not have to write, and we do not want to see you write,
the whole "open (and handle error), read, chomp, and return" sequence.

I would even suspect that get_terms() is a poorly written
anti-pattern.  If I were adding that function to the system today, I
wouldn't be surprised if I did read_file() the whole thing and
worked in-core to split two items out.

> If I understand correctly we're encouraging the user to run "git
> bisect skip" from the post checkout script. Doesn't that mean we'll
> end up with a set of processes that look like
>
> 	- git bisect start
> 	  - post checkout script
>             - git bisect skip
>               - post checkout script
>                 - git bisect skip
>                   ...
>
> as the "git bisect start" is waiting for the post checkout script to
> finish running, but that script is waiting for "git bisect skip" to
> finish running and so on. Each of those processes takes up system
> resources, similar to how a recursive function can exhaust the
> available stack space by calling itself over and over again.

True.  What such a post-checkout script can do is to only mark the
HEAD as "untestable", just like a run script given to "bisect run"
signals that fact by returnint 125.  And at that point, I doubt it
makes sense to add such a post-checkout script for the purpose of
allowing "bisect skip".

Having said that, a post-checkout script and pre-resume script may
have a huge value in helping those whose tests cannot be automated
(in other words, they cannot do "git bisect run") when they need to
tweak the working tree during bisection.  We all have seen, during a
bisection session that spans a segment of history that has another
bug that affects our test *but* is orthogonal to the bug we are
chasing, that we "cherry-pick --no-commit" the fix for that other
problem inside "git bisect run" script.  It might look something
like

    #!/bin/sh
    if git merge-base --is-ancestor $the_other_bug HEAD
    then
	# we need the fix
	git cherry-pick --no-commit $fix_for_the_other_bug ||
	exit 125
    fi

    make test
    status=$?
    git reset --hard ;# undo the cherry-pick
    exit $status

But to those whose test is not a good match to "git bisect run", if
we had a mechanism to tweak the checked out working tree after the
"bisect next" (which is an internal mechanism that "bisect good",
"bisect bad", and "bisect skip" share to give you the next HEAD and
the working tree to test) checks out the working tree before it
gives the control back to you, we could split the above script into
two parts and throw the "conditionally cherry-pick the fix" part
into that mechanism.  We'd need to have a companion script to "redo
the damage" (the "reset --hard" in the above illustration) if this
were to work seamlessly.  That obviously is totally orthogonal to
what we are discussing in this thread, but may make a good #leftoverbits
material (but not for novices).

^ permalink raw reply	[relevance 5%]

* Re: [PATCH] CodingGuidelines: quote assigned value with "local" and "export"
  @ 2024-04-05 16:21  6%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-04-05 16:21 UTC (permalink / raw)
  To: git; +Cc: Patrick Steinhardt, Eric Sunshine, René Scharfe

Somebody may want to inspect the output from

    $ git grep -E -i -e '^	*(local|export) [a-z0-9_]*=\$'

and fix those that can be used with dash.  I made a cursory scan and
removed obviously safe ones whose RHS will never have $IFS whitespaces,
and the following are remainders.  #leftoverbits

t/t0610-reftable-basics.sh:	local actual=$(ls -l "$file") &&
t/test-lib-functions.sh:	local file=${2:-"$1.t"} &&
t/test-lib-functions.sh:	local basename=${1#??}
t/test-lib-functions.sh:	local var=$1 port
t/test-lib-functions.sh:	local expr=$(printf '"%s",' "$@")
t/test-lib-functions.sh:	local inc=${2:-0} &&
t/test-lib-functions.sh:	local inc=${2:-0} &&
t/test-lib-functions.sh:	local ret=$?

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] sequencer: honor signoff opt in run_git_commit
  2024-04-04 16:22  5% ` Junio C Hamano
@ 2024-04-04 19:21  0%   ` Phillip Wood
  0 siblings, 0 replies; 200+ results
From: Phillip Wood @ 2024-04-04 19:21 UTC (permalink / raw)
  To: Junio C Hamano, David Bimmler via GitGitGadget; +Cc: git, David Bimmler

On 04/04/2024 17:22, Junio C Hamano wrote:
> "David Bimmler via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 
>> From: David Bimmler <david.bimmler@isovalent.com>
>>
>> When rebasing interactively, --signoff would not take effect for commits
>> which conflict. That is, commits applying cleanly would be signed off,
>> but commits requiring intervention would miss the sign off trailer.
> 
> Good finding.

Yes, thanks for posting this patch.

>> The reason is that run_git_commit did not check for the signoff replay
>> opt, and hence even though the option was picked up and passed
>> correctly, the actual committing dropped the ball.
> 
> We record and read back the initial "--signoff" given from the
> command line (and options.signoff from the "options sheet" when not
> REPLAY_INTERACTIVE_REBASE) in opts->signoff, but that piece of
> information is used only to decide if we call append_signoff().
> When do_commit(), after try_to_commit() punts, calls "git commit",
> the invocation lacks "--signoff" on the command line.
> 
>      Side note: the "let's avoid spawning 'git commit' and duplicate
>      it in-process" codepath in try_to_commit() does not seem to pay
>      attention to opts->signoff at all, and it does not do the
>      append_signoff() to add the trailer.  Is this something this
>      patch needs to fix as well, or am I misreading the control flow
>      (e.g., perhaps opts->signoff is set we somehow refrain from
>      doing the "let's do it in-process" logic)?

I think it is more complicated than that. We do not use the "--signoff" 
option of "git commit" because we do not want to append the 
"Signed-off-by:" trailer when processing "fixup" and "squash" commands. 
The trailer is appended to the commit message by the sequencer in 
do_pick_commits(). The problem is that when we commit a conflict 
resolution we end up using the original commit message rather than the 
file containing the commit message that we would have used if we had not 
stopped for conflicts. I've got some patches which need their commit 
messages cleaning up at 
https://github.com/phillipwood/git/commits/wip/fix-rebase-signoff-with-conflicts/ 
which use the correct file when committing conflict resolutions. I'll 
try and clean them up next week.

Best Wishes

Phillip

> If we forgot to tell "git commit" that we want the result
> signed-off, of course it would not add the trailer.  Perhaps
> 
>      -correctly, the actual committing dropped the ball"
>      +correctly to run_git_commit(), it failed to pass it to
>      +underlying 'git commit'
> 
> is less misleading.
> 
>> The patch adds a test specifically for this case, as well as amending a
>> squash test which codified the broken behaviour.
> 
> "The patch adds" -> "Add"
> 
> I love this kind of test update that corrects a mistaken expectation
> after a careful analysis of how the commands should behave.
> 
> Very good job.  Nicely done.
> 
>> diff --git a/sequencer.c b/sequencer.c
>> index fa838f264f5..16595e26a17 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -1121,6 +1121,8 @@ static int run_git_commit(const char *defmsg,
>>   		strvec_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>>   	else
>>   		strvec_push(&cmd.args, "--no-gpg-sign");
>> +	if (opts->signoff)
>> +		strvec_push(&cmd.args, "--signoff");
>>   	if (defmsg)
>>   		strvec_pushl(&cmd.args, "-F", defmsg, NULL);
>>   	else if (!(flags & EDIT_MSG))
> 
> This is straight-forward and obviously correct.
> 
>> diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
>> index e1b1e947647..fcecdf41978 100755
>> --- a/t/t3428-rebase-signoff.sh
>> +++ b/t/t3428-rebase-signoff.sh
>> @@ -27,6 +27,13 @@ first
>>   Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/")
>>   EOF
>>   
>> +# Expected signed off message after resolving the conflict
>> +cat >expected-signed-after-conflict <<EOF
>> +update file on side
>> +
>> +Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/")
>> +EOF
>> +
> 
> The t3428 script uses ancient style to prepare these expectations
> outside the test_expect_success blocks, and following the pattern
> is fine (until we clean-up the style of the whole script).  Cleaning
> it up is better done as a separate series, and when the dust settles
> after this fix lands.  #leftoverbits
> 
>>   # Expected commit message after rebase without --signoff (or with --no-signoff)
>>   cat >expected-unsigned <<EOF
>>   first
>> @@ -82,4 +89,30 @@ test_expect_success 'rebase -m --signoff fails' '
>>   	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
>>   	test_cmp expected-signed actual
>>   '
>> +
>> +test_expect_success 'rebase -i signs commits even if a conflict occurs' '
>> +	git branch -M main &&
>> +
>> +	git branch side &&
>> +	echo "b" >file &&
>> +	git add file &&
>> +	git commit -m"update file" &&
> 
> Have a SP between "-m" and its value, imitating existing tests.
> 
>> +	test_tick &&
> 
> Why?  Does the rest of the test depend on commits to have different
> timestamps?
> 
> If you want to use test_tick, the pattern to follow is to call it
> _before_ creating a commit, not after.  Up to this point in the
> original script nobody calls it (or test_commit that by default
> calls it), so "test_tick && git_commit" would be OK.
> 
> But if there is no dependency on exact sequence of timestamps,
> letting the commit share the same initial timestamp (hardcoded in
> test-lib.sh for better reproducibility) is more preferable, as use
> of test_tick sends a wrong message that the test results may be
> affected by the exact timestamps.
> 
>> +	test_must_fail git rebase -i --signoff main &&
>> +
>> +	echo "merged" >file &&
>> +	git add file &&
>> +	git rebase --continue &&
>> +
>> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
>> +	test_cmp expected-signed-after-conflict actual
> 
> Running any git command on the left hand side of a pipe is frowned
> upon, as it will hide exit status from it when it fails.
> 
> In this case, the primary thing we care about is that we have added
> the sign off that did not exist in the original, so I wonder
> 
> 	git cat-file commit HEAD >actual &&
> 	test_grep "Signed-off-by: " actual
> 
> would be sufficient?
> 
>> +'
>> +
>>   test_done
>> diff --git a/t/t3437/expected-squash-message b/t/t3437/expected-squash-message
>> index ab2434f90ed..d74af0bcf6b 100644
>> --- a/t/t3437/expected-squash-message
>> +++ b/t/t3437/expected-squash-message
>> @@ -48,4 +48,6 @@ edited 1
>>   edited 2
>>   
>>   edited 3
>> +
>> +Signed-off-by: Rebase Committer <rebase.committer@example.com>
>>   squashed
> 
> This defines the expected outcome from
> 
>      git rebase -ik --signoff A
> 
> in t3437-rebase-fixup-options.sh; I am not sure if the location the
> sign-off is inserted is sensible, though.
> 
> Thanks.
> 

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] sequencer: honor signoff opt in run_git_commit
  @ 2024-04-04 16:22  5% ` Junio C Hamano
  2024-04-04 19:21  0%   ` Phillip Wood
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-04-04 16:22 UTC (permalink / raw)
  To: David Bimmler via GitGitGadget; +Cc: git, David Bimmler

"David Bimmler via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: David Bimmler <david.bimmler@isovalent.com>
>
> When rebasing interactively, --signoff would not take effect for commits
> which conflict. That is, commits applying cleanly would be signed off,
> but commits requiring intervention would miss the sign off trailer.

Good finding.

> The reason is that run_git_commit did not check for the signoff replay
> opt, and hence even though the option was picked up and passed
> correctly, the actual committing dropped the ball.

We record and read back the initial "--signoff" given from the
command line (and options.signoff from the "options sheet" when not
REPLAY_INTERACTIVE_REBASE) in opts->signoff, but that piece of
information is used only to decide if we call append_signoff().
When do_commit(), after try_to_commit() punts, calls "git commit",
the invocation lacks "--signoff" on the command line.

    Side note: the "let's avoid spawning 'git commit' and duplicate
    it in-process" codepath in try_to_commit() does not seem to pay
    attention to opts->signoff at all, and it does not do the
    append_signoff() to add the trailer.  Is this something this
    patch needs to fix as well, or am I misreading the control flow
    (e.g., perhaps opts->signoff is set we somehow refrain from
    doing the "let's do it in-process" logic)?

If we forgot to tell "git commit" that we want the result
signed-off, of course it would not add the trailer.  Perhaps

    -correctly, the actual committing dropped the ball" 
    +correctly to run_git_commit(), it failed to pass it to
    +underlying 'git commit'

is less misleading.

> The patch adds a test specifically for this case, as well as amending a
> squash test which codified the broken behaviour.

"The patch adds" -> "Add"

I love this kind of test update that corrects a mistaken expectation
after a careful analysis of how the commands should behave.

Very good job.  Nicely done.

> diff --git a/sequencer.c b/sequencer.c
> index fa838f264f5..16595e26a17 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -1121,6 +1121,8 @@ static int run_git_commit(const char *defmsg,
>  		strvec_pushf(&cmd.args, "-S%s", opts->gpg_sign);
>  	else
>  		strvec_push(&cmd.args, "--no-gpg-sign");
> +	if (opts->signoff)
> +		strvec_push(&cmd.args, "--signoff");
>  	if (defmsg)
>  		strvec_pushl(&cmd.args, "-F", defmsg, NULL);
>  	else if (!(flags & EDIT_MSG))

This is straight-forward and obviously correct.

> diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
> index e1b1e947647..fcecdf41978 100755
> --- a/t/t3428-rebase-signoff.sh
> +++ b/t/t3428-rebase-signoff.sh
> @@ -27,6 +27,13 @@ first
>  Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/")
>  EOF
>  
> +# Expected signed off message after resolving the conflict
> +cat >expected-signed-after-conflict <<EOF
> +update file on side
> +
> +Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/")
> +EOF
> +

The t3428 script uses ancient style to prepare these expectations
outside the test_expect_success blocks, and following the pattern
is fine (until we clean-up the style of the whole script).  Cleaning
it up is better done as a separate series, and when the dust settles
after this fix lands.  #leftoverbits 

>  # Expected commit message after rebase without --signoff (or with --no-signoff)
>  cat >expected-unsigned <<EOF
>  first
> @@ -82,4 +89,30 @@ test_expect_success 'rebase -m --signoff fails' '
>  	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
>  	test_cmp expected-signed actual
>  '
> +
> +test_expect_success 'rebase -i signs commits even if a conflict occurs' '
> +	git branch -M main &&
> +
> +	git branch side &&
> +	echo "b" >file &&
> +	git add file &&
> +	git commit -m"update file" &&

Have a SP between "-m" and its value, imitating existing tests.

> +	test_tick &&

Why?  Does the rest of the test depend on commits to have different
timestamps?

If you want to use test_tick, the pattern to follow is to call it
_before_ creating a commit, not after.  Up to this point in the
original script nobody calls it (or test_commit that by default
calls it), so "test_tick && git_commit" would be OK.

But if there is no dependency on exact sequence of timestamps,
letting the commit share the same initial timestamp (hardcoded in
test-lib.sh for better reproducibility) is more preferable, as use
of test_tick sends a wrong message that the test results may be
affected by the exact timestamps.

> +	test_must_fail git rebase -i --signoff main &&
> +
> +	echo "merged" >file &&
> +	git add file &&
> +	git rebase --continue &&
> +
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	test_cmp expected-signed-after-conflict actual

Running any git command on the left hand side of a pipe is frowned
upon, as it will hide exit status from it when it fails.

In this case, the primary thing we care about is that we have added
the sign off that did not exist in the original, so I wonder

	git cat-file commit HEAD >actual &&
	test_grep "Signed-off-by: " actual

would be sufficient?

> +'
> +
>  test_done
> diff --git a/t/t3437/expected-squash-message b/t/t3437/expected-squash-message
> index ab2434f90ed..d74af0bcf6b 100644
> --- a/t/t3437/expected-squash-message
> +++ b/t/t3437/expected-squash-message
> @@ -48,4 +48,6 @@ edited 1
>  edited 2
>  
>  edited 3
> +
> +Signed-off-by: Rebase Committer <rebase.committer@example.com>
>  squashed

This defines the expected outcome from

    git rebase -ik --signoff A

in t3437-rebase-fixup-options.sh; I am not sure if the location the
sign-off is inserted is sensible, though.

Thanks.

^ permalink raw reply	[relevance 5%]

* Re: [GSoC] Microproject help
  2024-03-25 21:23  0%   ` Junio C Hamano
@ 2024-03-25 21:37  0%     ` Eric Sunshine
  0 siblings, 0 replies; 200+ results
From: Eric Sunshine @ 2024-03-25 21:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: vk, git

On Mon, Mar 25, 2024 at 5:23 PM Junio C Hamano <gitster@pobox.com> wrote:
> Eric Sunshine <sunshine@sunshineco.com> writes:
> > On Mon, Mar 25, 2024 at 11:40 AM vk <g@vkabc.me> wrote:
> >> If there is any low hanging fruits that you can suggest to me for the
> >> microproject, that will be great. I will also be searching throughout
> >> the mailing list to see if there are any potential microproject to work
> >> on.
> >
> > Searching the mailing list for "#leftoverbits"[1] can be a good way to
> > discover little tasks which may be suitable for a GSoC microproject.
>
> True, but with a caveat that they may range from "low hanging fruit"
> to "too hard, let's punt".  After seeing the anonymous questioners'
> question, I did go to that query page (actually I qualified the
> query further to list only the ones I gave the mark) and decided not
> to suggest it because I found that many recent ones are harder than
> "trivial changes suitable for a practice material to go through the
> review cycles" X-<.

Since the purpose of a GSoC microproject is to familiarize the
candidate with the project's mailing-list workflow and to give the
GSoC mentors a feel for how the candidate interacts, perhaps the
easiest suggestion would be the old fallback of having the candidate
look for a single test script which still uses `test -f` or `test -e`
or such, and converting that to use one of the test_path_foo()
functions from t/test-lib-functions.sh.

^ permalink raw reply	[relevance 0%]

* Re: [GSoC] Microproject help
  2024-03-25 20:51  6% ` Eric Sunshine
@ 2024-03-25 21:23  0%   ` Junio C Hamano
  2024-03-25 21:37  0%     ` Eric Sunshine
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-03-25 21:23 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: vk, git

Eric Sunshine <sunshine@sunshineco.com> writes:

> On Mon, Mar 25, 2024 at 11:40 AM vk <g@vkabc.me> wrote:
>> For the microproject, I have looked into the lists for 2024 and it seems
>> that all the projects have been taken except for `Replace a
>> run_command*() call by direct calls to C functions`. However, it seems
>> that the issue has been solved. The command I ran to search throughout
>> the repo is `git grep 'run_command*('` and the search result returns
>> run_command functions which I assume are essential.
>>
>> If there is any low hanging fruits that you can suggest to me for the
>> microproject, that will be great. I will also be searching throughout
>> the mailing list to see if there are any potential microproject to work
>> on.
>
> Searching the mailing list for "#leftoverbits"[1] can be a good way to
> discover little tasks which may be suitable for a GSoC microproject.
>
> [1]: https://lore.kernel.org/git/?q=%23leftoverbits

True, but with a caveat that they may range from "low hanging fruit"
to "too hard, let's punt".  After seeing the anonymous questioners'
question, I did go to that query page (actually I qualified the
query further to list only the ones I gave the mark) and decided not
to suggest it because I found that many recent ones are harder than
"trivial changes suitable for a practice material to go through the
review cycles" X-<.

Thanks.


^ permalink raw reply	[relevance 0%]

* Re: [GSoC] Microproject help
  @ 2024-03-25 20:51  6% ` Eric Sunshine
  2024-03-25 21:23  0%   ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Eric Sunshine @ 2024-03-25 20:51 UTC (permalink / raw)
  To: vk; +Cc: git

On Mon, Mar 25, 2024 at 11:40 AM vk <g@vkabc.me> wrote:
> For the microproject, I have looked into the lists for 2024 and it seems
> that all the projects have been taken except for `Replace a
> run_command*() call by direct calls to C functions`. However, it seems
> that the issue has been solved. The command I ran to search throughout
> the repo is `git grep 'run_command*('` and the search result returns
> run_command functions which I assume are essential.
>
> If there is any low hanging fruits that you can suggest to me for the
> microproject, that will be great. I will also be searching throughout
> the mailing list to see if there are any potential microproject to work
> on.

Searching the mailing list for "#leftoverbits"[1] can be a good way to
discover little tasks which may be suitable for a GSoC microproject.

[1]: https://lore.kernel.org/git/?q=%23leftoverbits

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] pretty: find pretty formats case-insensitively
  @ 2024-03-25 18:12  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-25 18:12 UTC (permalink / raw)
  To: Jeff King; +Cc: Brian Lyles, git

Jeff King <peff@peff.net> writes:

> The mention of "recursive" in the function we call made me what wonder
> if we'd need more normalization. And I think we do. Try this
> modification to your test:
>
> diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
> index 321e305979..be549b1d4b 100755
> --- a/t/t4205-log-pretty-formats.sh
> +++ b/t/t4205-log-pretty-formats.sh
> @@ -61,8 +61,9 @@ test_expect_success 'alias user-defined format' '
>  
>  test_expect_success 'alias user-defined format is matched case-insensitively' '
>  	git log --pretty="format:%h" >expected &&
> -	git config pretty.testalias "format:%h" &&
> -	git log --pretty=testAlias >actual &&
> +	git config pretty.testone "format:%h" &&
> +	git config pretty.testtwo testOne &&
> +	git log --pretty=testTwo >actual &&
>  	test_cmp expected actual
>  '

Very good thinking.  I totally missed the short-cut to another
short-cut while reading the patch.

>> +test_expect_success 'alias user-defined format is matched case-insensitively' '
>> +	git log --pretty="format:%h" >expected &&
>> +	git config pretty.testalias "format:%h" &&
>> +	git log --pretty=testAlias >actual &&
>> +	test_cmp expected actual
>> +'
>
> Modern style would be to use "test_config" here (or just "git -c"), but
> I see the surrounding tests are too old to do so. So I'd be OK with
> matching them (but cleaning up all of the surrounding ones would be
> nice, too).

Yup.  I do not mind seeing it done either way, as a preliminary
clean-up before the main fix, just a fix with more modern style
while leaving the clean-up as #leftoverbits to be done after the
dust settles.

> PS The matching rules in find_commit_format_recursive() seem weird
>    to me. We do a prefix match, and then return the entry whose name is
>    the shortest? And break ties based on which came first? So:
>
>      git -c pretty.abcd=format:one \
>          -c pretty.abc=format:two \
>          -c pretty.abd=format:three \
> 	 log -1 --format=ab
>
>    quietly chooses "two". I guess the "shortest wins" is meant to allow
>    "foo" to be chosen over "foobar" if you specify the whole name. But
>    the fact that we don't flag an ambiguity between "abc" and "abd"
>    seems strange.
>    That is all orthogonal to your patch, of course, but just a
>    head-scratcher I noticed while looking at the code.

I think it is not just strange but outright wrong.  I agree that it
is orthogonal to this fix.

Thanks, both.




^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 0/5] Fixes for Documentation/MyFirstObjectWalk.txt
  2024-03-25 17:50  6%   ` Junio C Hamano
@ 2024-03-25 18:01  0%     ` Kyle Lippincott
  0 siblings, 0 replies; 200+ results
From: Kyle Lippincott @ 2024-03-25 18:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Dirk Gouders, git, Emily Shaffer

On Mon, Mar 25, 2024 at 10:50 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Dirk Gouders <dirk@gouders.net> writes:
>
> > The 3rd iteration for this series.
> >
> > I tried to credit Kyle's suggestions for 4 and 5 with Helped-by tags and
> > hope it was adequate to do so.  Actually, at least #4 was a lot more
> > than a Helped-by, I would say...
>
> It seemed adequate, at least to me, but I'll leave the final say up
> to Kyle.
>
> I left a few comments but overall the series is looking much nicer.
> Thanks for working on it (and thanks for reviewing and helping,
> Kyle).
>
> This is an unrelated tangent, but I wonder if we can come up with a
> way to find breakages coming from API updates to these "tutorial"
> documents.  The original "user-manual" also shares the same issue,
> and the issue may be deeper there as it also needs to catch up with
> end-user facing UI updates.  In any case, we somehow ended up with
> two more "tutorial"-ish documents (MyFirstContribution.txt is the
> other one) that somebody needs to keep an eye on.
>
> Ideally if we can have automated tests, it would be nice.  Perhaps
> sprinkling some special instruction in comments that is hidden from
> AsciiDoc mark-up to help our custom program to assemble the bits
> into the state of the tutorial program that the readers should be
> arriving at at different points in the tutorial document, and make
> sure they compile, link, and test well?

On another project, I've had a (separate) test file that just does
what the tutorial says to do, and there's an automatic notice for
"you're touching tutorial-test.sh, make sure you make any required
changes to tutorial.txt as well". I don't know if we have that second
part available to us here, though.

> Or "follow one of our three
> tutorial documents to the letter to see if they need adjusting, and
> come up with a set of patches to adjust them" can be listed as one
> of the microproject ideas?  I'll leave a #leftoverbits mark here, but
> what I want to see discussed (and eventually implemented) is not the
> clean-up itself (which can go stale over time) but the strategy to
> keep the "tutorial" material up-to-date.
>
> THanks.
>

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v3 0/5] Fixes for Documentation/MyFirstObjectWalk.txt
  @ 2024-03-25 17:50  6%   ` Junio C Hamano
  2024-03-25 18:01  0%     ` Kyle Lippincott
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-03-25 17:50 UTC (permalink / raw)
  To: Dirk Gouders; +Cc: git, Emily Shaffer, Kyle Lippincott

Dirk Gouders <dirk@gouders.net> writes:

> The 3rd iteration for this series.
>
> I tried to credit Kyle's suggestions for 4 and 5 with Helped-by tags and
> hope it was adequate to do so.  Actually, at least #4 was a lot more
> than a Helped-by, I would say...

It seemed adequate, at least to me, but I'll leave the final say up
to Kyle.

I left a few comments but overall the series is looking much nicer.
Thanks for working on it (and thanks for reviewing and helping,
Kyle).

This is an unrelated tangent, but I wonder if we can come up with a
way to find breakages coming from API updates to these "tutorial"
documents.  The original "user-manual" also shares the same issue,
and the issue may be deeper there as it also needs to catch up with
end-user facing UI updates.  In any case, we somehow ended up with
two more "tutorial"-ish documents (MyFirstContribution.txt is the
other one) that somebody needs to keep an eye on.

Ideally if we can have automated tests, it would be nice.  Perhaps
sprinkling some special instruction in comments that is hidden from
AsciiDoc mark-up to help our custom program to assemble the bits
into the state of the tutorial program that the readers should be
arriving at at different points in the tutorial document, and make
sure they compile, link, and test well?  Or "follow one of our three
tutorial documents to the letter to see if they need adjusting, and
come up with a set of patches to adjust them" can be listed as one
of the microproject ideas?  I'll leave a #leftoverbits mark here, but
what I want to see discussed (and eventually implemented) is not the
clean-up itself (which can go stale over time) but the strategy to
keep the "tutorial" material up-to-date.

THanks.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH] contrib: drop hg-to-git script
  @ 2024-03-23 18:49  6%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-23 18:49 UTC (permalink / raw)
  To: Jeff King; +Cc: Johannes Schindelin, Matthew Rollings, Stelian Pop, git

Jeff King <peff@peff.net> writes:

> Anyway, the important takeaway to me is that searches are not likely to
> end up at contrib/hg-to-git, with people wondering where it went. They
> will point directly to the alternatives.

And what is most attractive is that the list of alternatives they
will see in there searches will be updated as new and better ones
appear, unlike contrib/hg-to-git/README that we would need to
conciously maintain, which we are unlikely to do.

We might want to see if there are other contrib/ ones with only
tombstone READMEs and remove them as a part of spring (in the
northern hemisphere) cleaning, #leftoverbits, citing what we
discussed in this thread as the rationale.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] editorconfig: add Makefiles to "text files"
  @ 2024-03-23 17:36  5%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-23 17:36 UTC (permalink / raw)
  To: Max Gautier; +Cc: git, Hans Jerry Illikainen

Max Gautier <mg@max.gautier.name> writes:

>>  * Among the files we ship (i.e. "git ls-tree -r HEAD") and edit
>>    with editors that honor .editorconfig settings, are there any
>>    file that we do not want tab indentation other than *.py?
>
> $ git ls-tree -r HEAD | cut -f 2 | \
> ...
>       2 png
> ...

As I expected ;-) We do not have all that many kinds.  Some like
image files are not even meant to be edited as text and the usual
"editor"s people use to edit them are probably unaware of what we
write in the .editorconfig file.

> Not sure which one among those don't want the same tab-indent settings
> though.

That is the other important question.  What I was hoping to hear was
that other than Python there are not be any kind that are edited by
editorconfig-aware editors.  But that unfortunately is not what we
are hearing.

>>  * Does .editorconfig file allow possibly conflicting setting, with
>>    a reliable conflict resolution rules?
>
> Yeah it does: https://spec.editorconfig.org/#id8
> TL;DR:
> - from top to bottom, last matching section wins
> - if multiple .editorconfig are found (up until one with the root key or
>   in /) closest to the file wins.
>> 
>> What I am trying to get at is if it is possible to make something
>> along this line to work:
>> 
>>     [*]
>> 	charset = utf-8
>> 	insert_final_newline = true
>> 	indent_style = tab
>> 	tab_width = 8
>>     [*.py]
>> 	indent_style = space
>> 	indet_size = 4
>> 
>> I am assuming, without knowing, that the conflict resolution rule
>> may be "for the same setting, the last match wins" so by default we
>> always use "indent_style = tab", but if we are talking about a Python
>> script, it is overruled with "indent_style = space".
>
> So it looks like it's possible, if we also add judiciously .editorconfig
> in subdirectory where we have other files which don't want the same
> settings, probably:

That is much less than ideal---I was hoping that we can do this
with just one file.  My reading of that spec is that in the same
file it would be the last one wins, so something line what I gave
you above should work more-or-less as-is?

Also I am not sure if there is any reason why ...

> - po/
> - t/
> - contrib/
> - .github/
> - ...
>
> Not sure if that's easier than adding stuff to the to the root config
> though.

... t/*.sh should use rules different from those that apply to
check-builtins.sh at the root level, or contrib/mw-to-git/*.perl
should use Perl rules different from those that apply to
perl/Git.pm.  So I think "we need per-directory customization" is a
red herring.

The real potential downside of the approach to use a single default
fallback set of rules with "match everything" is that types that we
did not tweak the editor rules for are suddenly and uniformly
subjected to a rule that may not match the contents.  We currently
do not do anything to .yml or .md so we do not force them to be in
any consistent layout---even if all contributors use editorconfig
aware editor to edit them, they will produce inconsistent result.
If we enforce "everybody indent with tab unless explicitly set
differently like we do for .py", these contributors consistently use
tab indent on .yml or .md, which may not be a suitable convention
for the material.  My quick look says that .github/**/*.yml wants
two-space indentation, and .md are fine with any indentation so
enforcing tab indent consistently may be better than not enforcing
any indent at all.

So, my gut feeling is that forcing "everybody uses tab indent by
default, and file types with specific needs should opt out just like
we do for Python" may initially give us a bit of friction (e.g., We
may find .github/**/*.yml would want different rules, so we would
add "[*.yml]" section just like we have "[*.py]" section), but would
make the rule coverage more complete and more clear.  We would give
a .yml file some rule to follow, which may initially be wrong but we
can fix with explicit rule.

So I dunno.  If the Makefile snippet were the last type of files we
would ever add to .editorconfig, I think the patch under discussion
is a good progress, but if we share the vision of "more complete and
clear rule coverage", it is going in the opposite direction.

Let me take your patch as-is, but leave it #leftoverbits to at least
see the feasibility of switching to "everything falls under the
default set of rules, and specific needs are dealt with exceptions"
model.

Thanks.


^ permalink raw reply	[relevance 5%]

* [PATCH 0/2] git-compat-util: move convert_slashes from compat/mingw.h and rename it
@ 2024-03-18 12:47  6% Mohit Marathe via GitGitGadget
  0 siblings, 0 replies; 200+ results
From: Mohit Marathe via GitGitGadget @ 2024-03-18 12:47 UTC (permalink / raw)
  To: git; +Cc: Mohit Marathe

Hi all,

This series aims to complete a #leftoverbits: https://lore.kernel.org/
git/xmqqzfw43xad.fsf@gitster.g/ by moving convert_slashes() to
git-compat-util.h and renaming it to change_path_separators().

I appreciate your review and feedback on this patch series.

Best regards, Mohit Marathe

Mohit Marathe (2):
  git-compat-util: migrate `convert_slashes()` from compat/mingw.h
  test-lib: replace repeated code logic with an existing helper

 abspath.c               | 4 ++--
 compat/mingw.c          | 4 ++--
 compat/mingw.h          | 6 ------
 git-compat-util.h       | 7 +++++++
 path.c                  | 2 +-
 t/unit-tests/test-lib.c | 9 +++------
 6 files changed, 15 insertions(+), 17 deletions(-)


base-commit: 2953d95d402b6bff1a59c4712f4d46f1b9ea137f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1699%2Fmohit-marathe%2Fconvert-slashes-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1699/mohit-marathe/convert-slashes-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1699
-- 
gitgitgadget

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 09/22] t/t4*: avoid redundant uses of cat
  2024-03-16  1:34  6%     ` Taylor Blau
@ 2024-03-16  6:04  0%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-16  6:04 UTC (permalink / raw)
  To: Taylor Blau; +Cc: Beat Bolli, git, Beat Bolli

Taylor Blau <me@ttaylorr.com> writes:

> This and the two similar transformations below it look good to me. This
> obviously isn't the fault of your patch (nor should it necessarily be
> its aim to fix), but I wonder if it would be worthwhile to extract the
>
>     tr "\0" "\n" <out | head -n 3 | grep 3.bar | cut -f 2 -d " "
>
> pattern into a helper function, since it's used in a few places in this
> test script.

I somehow thought that the theme of the topic is to reduce the depth
of the pipeline.  "head -n 3" piped into "grep" sounds something a
single sed script can do, e.g.

	tr '\000' '\012' <out |	sed -n -e '1,3s/3.bar/&/p'

> That's just a suggestion, and shouldn't hold up this patch/series. Maybe
> just some #leftoverbits :-).

Ditto.  The whole thing can be turned into a Perl scriptlet, which
may be even easier to read (the cost to spin up one Perl interpreter
might be greater than constructing 4 process pipeline on certain
systems, though).

Thanks.

P.S. It is nice to hear from you Taylor.  It's been a while.


^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 09/22] t/t4*: avoid redundant uses of cat
  @ 2024-03-16  1:34  6%     ` Taylor Blau
  2024-03-16  6:04  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Taylor Blau @ 2024-03-16  1:34 UTC (permalink / raw)
  To: Beat Bolli; +Cc: git, Junio C Hamano, Beat Bolli

On Fri, Mar 15, 2024 at 08:46:06PM +0100, Beat Bolli wrote:
> diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
> index 12ac43687366..578641467753 100755
> --- a/t/t4301-merge-tree-write-tree.sh
> +++ b/t/t4301-merge-tree-write-tree.sh
> @@ -313,7 +313,7 @@ test_expect_success 'rename/add handling' '
>  		# First, check that the bar that appears at stage 3 does not
>  		# correspond to an individual blob anywhere in history
>  		#
> -		hash=$(cat out | tr "\0" "\n" | head -n 3 | grep 3.bar | cut -f 2 -d " ") &&
> +		hash=$(tr "\0" "\n" <out | head -n 3 | grep 3.bar | cut -f 2 -d " ") &&
>  		git rev-list --objects --all >all_blobs &&
>  		! grep $hash all_blobs &&

This and the two similar transformations below it look good to me. This
obviously isn't the fault of your patch (nor should it necessarily be
its aim to fix), but I wonder if it would be worthwhile to extract the

    tr "\0" "\n" <out | head -n 3 | grep 3.bar | cut -f 2 -d " "

pattern into a helper function, since it's used in a few places in this
test script.

That's just a suggestion, and shouldn't hold up this patch/series. Maybe
just some #leftoverbits :-).

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 11/15] find multi-byte comment chars in unterminated buffers
  @ 2024-03-14 19:37  6%       ` René Scharfe
  0 siblings, 0 replies; 200+ results
From: René Scharfe @ 2024-03-14 19:37 UTC (permalink / raw)
  To: Jeff King
  Cc: git, Junio C Hamano, Dragan Simic, Kristoffer Haugsbakk, Manlio Perillo

Am 12.03.24 um 09:05 schrieb Jeff King:
> On Thu, Mar 07, 2024 at 08:42:22PM +0100, René Scharfe wrote:
>
>>> @@ -2562,7 +2562,7 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
>>>  	/* left-trim */
>>>  	bol += strspn(bol, " \t");
>>>
>>> -	if (bol == eol || *bol == '\r' || *bol == comment_line_char) {
>>> +	if (bol == eol || *bol == '\r' || starts_with_mem(bol, eol - bol, comment_line_str)) {
>>
>> If the strspn() call is safe (which it is, as the caller expects the
>> string to be NUL-terminated) then you could use starts_with() here and
>> avoid the length calculation.  But that would also match
>> comment_line_str values that contain LF, which the _mem version does not
>> and that's better.
>
> I try not to read too much into the use of string functions on what
> otherwise appears to be an unterminated buffer. While in Git it is quite
> often terminated at allocation time (coming from a strbuf, etc) I feel
> like I've fixed a number of out-of-bounds reads simply due to sloppy
> practices. And even if something is correct today, it is easy for it to
> change, since the assumption is made far away from allocation.
>
> So I dunno. Like you said, fewer computations is fewer opportunity to
> mess things up. I don't like the idea of introducing a new hand-grenade
> that might blow up later, but maybe if it's right next to a strspn()
> call that's already a problem, it's not materially making anything
> worse.

Yeah, and my logic was flawed: If the caller somehow guarantees that a
space or tab occurs before eol then the strspn() call is safe.  Its
presence doesn't guarantee NUL termination.  parse_insn_line() would
not be safe to use without that prerequisite, but that's a different
matter..

>>> @@ -882,7 +882,7 @@ static size_t find_trailer_block_start(const char *buf, size_t len)
>>>
>>>  	/* The first paragraph is the title and cannot be trailers */
>>>  	for (s = buf; s < buf + len; s = next_line(s)) {
>>> -		if (s[0] == comment_line_char)
>>> +		if (starts_with_mem(s, buf + len - s, comment_line_str))
>>>  			continue;
>>>  		if (is_blank_line(s))
>>
>> Another case where starts_with() would be safe to use, as
>> is_blank_line() expects (and gets) a NUL-terminated string, but it would
>> allow matching comment_line_str values that contain LF.
>
> Hmm. Yes, it is a NUL-terminated string always, but the caller has told
> us not to look past end_of_log_message(). I suspect that if there is no
> newline in comment_line_str() it's probably impossible to go past "len"
> (just because the end of the log surely ends with either a NUL or a
> newline). But it feels iffy to me. I dunno.

Same flawed thinking on my part: As long as we're guaranteed a blank
line in the buffer we won't walk past its end.  That doesn't mean we can
assume a NUL is present.  But that's fragile.  The code should use
memchr() instead of strchrnul().

That's not the problem you set out to solve in your series, though, and
you avoid making it worse by respecting the length limit in the code
you change.  #leftoverbits

Keeping track of the remaining length increases code size and adds
opportunities for mistakes.  Not sure how to avoid it, however.  Using
eol instead of len at least avoids subtractions.

tl;dr: Good patch (in v2).

René

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 1/5] xdiff-interface: refactor parsing of merge.conflictstyle
  @ 2024-03-14 17:19  6%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-14 17:19 UTC (permalink / raw)
  To: Phillip Wood via GitGitGadget; +Cc: git, Elijah Newren, Phillip Wood

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Factor out the code that parses of conflict style name so it can be
> reused in a later commit that wants to parse the name given on the
> command line.
>
> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> ---
>  xdiff-interface.c | 29 ++++++++++++++++++-----------
>  xdiff-interface.h |  1 +
>  2 files changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/xdiff-interface.c b/xdiff-interface.c
> index 3162f517434..16ed8ac4928 100644
> --- a/xdiff-interface.c
> +++ b/xdiff-interface.c
> @@ -305,6 +305,22 @@ int xdiff_compare_lines(const char *l1, long s1,
>  	return xdl_recmatch(l1, s1, l2, s2, flags);
>  }
>  
> +int parse_conflict_style_name(const char *value)
> +{
> +	if (!strcmp(value, "diff3"))
> +		return XDL_MERGE_DIFF3;
> +	else if (!strcmp(value, "zdiff3"))
> +		return XDL_MERGE_ZEALOUS_DIFF3;
> +	else if (!strcmp(value, "merge"))
> +		return 0;
> +	/*
> +	 * Please update _git_checkout() in git-completion.bash when
> +	 * you add new merge config
> +	 */
> +	else
> +		return -1;
> +}

As these symbols are now more public, it is tempting to leave a
#leftoverbits mark to remind us to clean them up by adding
XDL_MERGE_MERGE (instead of 0) and XDL_MERGE_UNKNOWN (instead of -1)
after the dust settles.  That would have made reading later patches
in the series a little less puzzling.

But within the scope of this series, the above is perfect, faithful
refactoring of the original.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 1/3] config.txt: describe whitespace characters further and more accurately
  2024-03-14  1:18  5%   ` Junio C Hamano
@ 2024-03-14  6:20  0%     ` Dragan Simic
  0 siblings, 0 replies; 200+ results
From: Dragan Simic @ 2024-03-14  6:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, rsbecker, github

On 2024-03-14 02:18, Junio C Hamano wrote:
> Dragan Simic <dsimic@manjaro.org> writes:
>> -The syntax is fairly flexible and permissive; whitespaces are mostly
>> -ignored.  The '#' and ';' characters begin comments to the end of 
>> line,
>> -blank lines are ignored.
>> +The syntax is fairly flexible and permissive.  Whitespace characters,
>> +which in this context are the space character (SP) and the horizontal
>> +tabulation (HT), are mostly ignored.  The '#' and ';' characters 
>> begin
>> +comments to the end of line.  Blank lines are ignored.
> 
> OK, except for "whitespace characters"---do we need to say
> "whitespace characters", after we already listed HT and SP are the
> ones, instead of just "whitespaces"?

I also spent some time thinking about that.  To me, the plural form, 
i.e.
"whitespaces", simply doesn't sound very good, because "whitespace" 
feels
to me more like a mass noun, and I really haven't seen it used in plural
form in other projects.

>>  A line that defines a value can be continued to the next line by
>> +ending it with a `\`; the backslash and the end-of-line are stripped.
>> +Leading whitespace characters after 'name =', the remainder of the
>>  line after the first comment character '#' or ';', and trailing
>> +whitespace characters of the line are discarded unless they are 
>> enclosed
>> +in double quotes.  This discarding of the trailing whitespace 
>> characters
>> +also applies after the remainder of the line after the comment 
>> character
>> +is discarded.
> 
> "also" makes it sound as if we do it twice, once to remove trailing
> whitespaces after the remainder of the line after '#", and then trim
> the trailing whitespaces after we removed the comment.

Good point, I also felt it the same way, but went with such wording 
simply
because I thought it should be more understandable to the users, despite
being technically a bit incorrect.

> I wonder if we can make it clearer by following the step-by-step
> nature of the earlier part of the paragraph through.  We already say
> the folded line processing is done first, so break things down in
> conceptual phases/steps, perhaps like
> 
>  * The backslash at the end-of-line is removed, together with the
>    end-of-line, to form a single long line.
> 
>  * Anything that come after the first unquoted comment character,
>    either '#' or ';', are discarded.
> 
>  * The leading and trailing whitespaces around the value part
>    (i.e. what follows 'name =') are discarded.
> 
>  * Remaining unquoted whitespaces inside the value part are munged.

Hmm, I'm not really sure that such a description would be more clear
to the users, despite being technically more correct.  I'll think a bit
more about it.

>> +Any number of internal whitespace characters found within
>> +the value are converted to the same number of space (SP) characters.
> 
> The last one sounds like a bug to me, by the way.
> 
> At least the very original 17712991 (Add ".git/config" file parser,
> 2005-10-10) squashed a run of whitespace characters into a single
> SP, which makes sense as a "clean-up".
> 
> But ebdaae37 (config: Keep inner whitespace verbatim, 2009-07-30),
> while claiming to "Keep" inner whitespaces, broke it by replacing
> any isspace() bytes that are not SP with SP, contradicting its
> stated purpose.

Thank you for the investigation.  The ebdaae37 commit certainly
introduced a bug to the value parsing, which presumably has remained
undected because the included test passes.

The way I see it, fixing the bug may actually be a breaking change,
because some user configurations may actually rely on the current
(mis)behavior.  This makes me somewhat afraid that fixing this bug,
which I already thought about, may actually do more harm than good.
However, fixing this bug seems to be only right thing to do, which
I'll explain further below.

> As the latest change by the author of that change is from more than
> 10 years ago, I do not expect that he is still interested in this
> part of the codebase, but thanks to a very clearly written log
> message, we can read what the motivation behind that change was, and
> seeing that what the code does contradicts with the stated
> motivation we can safely declare that this is an ancient bug.

Agreed, the evidence is clear.

> Fixing that bug can of course be left outside the series.  For those
> who are looking for microproject ideas who discovered this message
> by searching for the #leftoverbits keyword, one possible fix would
> be to revert ebdaae37, make sure a value with any whitespace in it
> gets quoted, and document clearly that an unquoted run of
> whitespaces is squashed into a single SP.  Another way that is
> milder is to finish what ebdaae37 wanted to do and retain the
> whitespaces "verbatim".

I already though about fixing the bug so the value parser actually does
what git-config(1) currently says, but as I already noted above, I'm
afraid a bit that fixing this bug may actually do more harm than good.

Though, further investigation shows that setting a configuration value,
by invoking git-config(1), converts value-internal tabs into "\t" escape
sequences, which the value-parsing logic doesn't "squash" into spaces.
That's why the test included in the ebdaae37 commit passes.  On the 
other
hand, value-internal literal tab characters, found in a configuration
file, do get "squashed" by the value-parsing logic, so I'd say that the
only right thing to do is to fix this bug by making the value-internal
whitespace characters preserved verbatim.

I'd be happy to include the bugfix into this series, if my 
above-mentioned
fears prove to be unnecessary.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 1/3] config.txt: describe whitespace characters further and more accurately
  @ 2024-03-14  1:18  5%   ` Junio C Hamano
  2024-03-14  6:20  0%     ` Dragan Simic
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-03-14  1:18 UTC (permalink / raw)
  To: Dragan Simic; +Cc: git, rsbecker, github

Dragan Simic <dsimic@manjaro.org> writes:

> Make it more clear what the whitespace characters are in the context of git
> configuration, improve the description of the trailing whitespace handling,
> and correct the description of the value-internal whitespace handling.
>
> Signed-off-by: Dragan Simic <dsimic@manjaro.org>
> ---
>  Documentation/config.txt | 19 +++++++++++--------
>  1 file changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 782c2bab906c..4480bb44203b 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -22,9 +22,10 @@ multivalued.
>  Syntax
>  ~~~~~~
>  
> -The syntax is fairly flexible and permissive; whitespaces are mostly
> -ignored.  The '#' and ';' characters begin comments to the end of line,
> -blank lines are ignored.
> +The syntax is fairly flexible and permissive.  Whitespace characters,
> +which in this context are the space character (SP) and the horizontal
> +tabulation (HT), are mostly ignored.  The '#' and ';' characters begin
> +comments to the end of line.  Blank lines are ignored.

OK, except for "whitespace characters"---do we need to say
"whitespace characters", after we already listed HT and SP are the
ones, instead of just "whitespaces"?

> @@ -64,12 +65,14 @@ The variable names are case-insensitive, allow only alphanumeric characters
>  and `-`, and must start with an alphabetic character.
>  
>  A line that defines a value can be continued to the next line by
> +ending it with a `\`; the backslash and the end-of-line are stripped.
> +Leading whitespace characters after 'name =', the remainder of the
>  line after the first comment character '#' or ';', and trailing
> +whitespace characters of the line are discarded unless they are enclosed
> +in double quotes.  This discarding of the trailing whitespace characters
> +also applies after the remainder of the line after the comment character
> +is discarded.

"also" makes it sound as if we do it twice, once to remove trailing
whitespaces after the remainder of the line after '#", and then trim
the trailing whitespaces after we removed the comment.

I wonder if we can make it clearer by following the step-by-step
nature of the earlier part of the paragraph through.  We already say
the folded line processing is done first, so break things down in
conceptual phases/steps, perhaps like

 * The backslash at the end-of-line is removed, together with the
   end-of-line, to form a single long line.

 * Anything that come after the first unquoted comment character,
   either '#' or ';', are discarded.

 * The leading and trailing whitespaces around the value part
   (i.e. what follows 'name =') are discarded.

 * Remaining unquoted whitespaces inside the value part are munged.

> +Any number of internal whitespace characters found within
> +the value are converted to the same number of space (SP) characters.

The last one sounds like a bug to me, by the way.

At least the very original 17712991 (Add ".git/config" file parser,
2005-10-10) squashed a run of whitespace characters into a single
SP, which makes sense as a "clean-up".

But ebdaae37 (config: Keep inner whitespace verbatim, 2009-07-30),
while claiming to "Keep" inner whitespaces, broke it by replacing
any isspace() bytes that are not SP with SP, contradicting its
stated purpose.

As the latest change by the author of that change is from more than
10 years ago, I do not expect that he is still interested in this
part of the codebase, but thanks to a very clearly written log
message, we can read what the motivation behind that change was, and
seeing that what the code does contradicts with the stated
motivation we can safely declare that this is an ancient bug.

Fixing that bug can of course be left outside the series.  For those
who are looking for microproject ideas who discovered this message
by searching for the #leftoverbits keyword, one possible fix would
be to revert ebdaae37, make sure a value with any whitespace in it
gets quoted, and document clearly that an unquoted run of
whitespaces is squashed into a single SP.  Another way that is
milder is to finish what ebdaae37 wanted to do and retain the
whitespaces "verbatim".

Thanks.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH] bugreport.c: fix a crash in `git bugreport` with `--no-suffix` option
  @ 2024-03-13 15:59  7% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-13 15:59 UTC (permalink / raw)
  To: barroit via GitGitGadget; +Cc: git, barroit, Emily Shaffer, Taylor Blau

"barroit via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Jiamu Sun <barroit@linux.com>
>
> executing `git bugreport --no-suffix` led to a segmentation fault
> due to strbuf_addftime() being called with a NULL option_suffix
> variable. This occurs because negating the "--[no-]suffix" option
> causes the parser to set option_suffix to NULL, which is not
> handled prior to calling strbuf_addftime().
>
> Signed-off-by: Jiamu Sun <barroit@linux.com>
> ---

"git blame" points at 238b439d (bugreport: add tool to generate
debugging info, 2020-04-16) that is the very beginning of this tool,
and the bug survived 4f6460df (builtin/bugreport.c: use thread-safe
localtime_r(), 2020-11-30).  Apparently neither commit considered
"--suffix=<string>" would invite users to say "--no-suffix" (authors
of them CC'ed for their input).

Perhaps we should update the documentation a bit while at it?  Here
is what I can find in its documentation.

    SYNOPSIS
    --------
    [verse]
    'git bugreport' [(-o | --output-directory) <path>] [(-s | --suffix) <format>]
                    [--diagnose[=<mode>]]

    -s <format>::
    --suffix <format>::
            Specify an alternate suffix for the bugreport name, to create a file
            named 'git-bugreport-<formatted-suffix>'. This should take the form of a
            strftime(3) format string; the current local time will be used.

The above does not say that it is possible to ask the code not to
use suffix at all with "--no-suffix".  If we want it to happen and
behave sensibly (which I think the code with your patch does, from
my cursory read), we probably should document it.  At least two
developers, considered to be expert Git developers and consider
themselves to be expert Git users, did not even anticipate that
"--no-suffix" will hit their code.

Another approach (with devil's advocate hat on) is obviously to use
the PARSE_OPT_NONEG bit so that people won't do what hurts them ;-),
but the fix is so trivial that it may be better to formally accept
"--no-suffix" in this case.

An aside #leftoverbits is to find OPTION_STRING that is used without
NONEG bit and make sure negating them with the "--no-" prefix will
not trigger a similar issue.  All uses of OPT_STRING() that use a
variable that is initialized to a non-NULL string are suspect.  Of
course, this is #leftoverbits and must be kept outside the topic to
fix this bug (i.e. this patch).

>     bugreport.c: fix a crash in git bugreport with --no-suffix option
>     
>     executing git bugreport --no-suffix led to a segmentation fault due to
>     strbuf_addftime() being called with a NULL option_suffix variable. This
>     occurs because negating the "--[no-]suffix" option causes the parser to
>     set option_suffix to NULL, which is not handled prior to calling
>     strbuf_addftime().
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1693%2Fbarroit%2Ffix-bugreport-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1693/barroit/fix-bugreport-v1
> Pull-Request: https://github.com/gitgitgadget/git/pull/1693
>
>  builtin/bugreport.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/builtin/bugreport.c b/builtin/bugreport.c
> index 3106e56a130..32281815b77 100644
> --- a/builtin/bugreport.c
> +++ b/builtin/bugreport.c
> @@ -138,8 +138,11 @@ int cmd_bugreport(int argc, const char **argv, const char *prefix)
>  	strbuf_complete(&report_path, '/');
>  	output_path_len = report_path.len;
>  
> -	strbuf_addstr(&report_path, "git-bugreport-");
> -	strbuf_addftime(&report_path, option_suffix, localtime_r(&now, &tm), 0, 0);
> +	strbuf_addstr(&report_path, "git-bugreport");
> +	if (option_suffix) {
> +		strbuf_addch(&report_path, '-');
> +		strbuf_addftime(&report_path, option_suffix, localtime_r(&now, &tm), 0, 0);
> +	}
>  	strbuf_addstr(&report_path, ".txt");
>  
>  	switch (safe_create_leading_directories(report_path.buf)) {
>
> base-commit: 945115026aa63df4ab849ab14a04da31623abece

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] git: --no-lazy-fetch option
  @ 2024-03-09  1:57  6%         ` Linus Arver
  0 siblings, 0 replies; 200+ results
From: Linus Arver @ 2024-03-09  1:57 UTC (permalink / raw)
  To: Jeff King, Junio C Hamano; +Cc: git, Christian Couder

Jeff King <peff@peff.net> writes:

> On Fri, Feb 16, 2024 at 09:22:20AM -0800, Junio C Hamano wrote:
>
> [...]
>> Add documentation and note that for this variable, unlike many
>> boolean-looking environment variables, only the presence matters,
>> not what value it is set to.
>
> Yuck. IMHO depending on GIT_NO_REPLACE_OBJECTS=0 is somewhat crazy, and
> we could consider the current behavior a bug. It's probably not _that_
> big a deal either way (because I would not expect anybody to set it that
> way in the first place). But I wonder if being consistent across
> variables trumps retaining weird historical compatibility for such a
> far-fetched case. I dunno. I guess this is https://xkcd.com/1172/. :)

I totally agree with your take on this. Would such cleanup patches
(e.g., changing the behavior of GIT_NO_REPLACE_OBJECTS=0 to be "false"
instead of "true") be acceptable as #leftoverbits?

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 01/22] doc: avoid redundant use of cat
  @ 2024-03-05 22:24  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-03-05 22:24 UTC (permalink / raw)
  To: Beat Bolli; +Cc: git, Beat Bolli

"Beat Bolli" <bb@drbeat.li> writes:

> The update-hook-example.txt script uses this anti-pattern twice. Call grep
> with the input file name directy. While at it, merge the two consecutive
> grep calls.

OK.  

While at it, we could also place $allowed_users_file inside a pair
of double quotes, as the "test -f" before the part we are touching
is prepared to have $IFS whitespace in it (perhaps inside $GIT_DIR),
but I am OK to leave it as a #leftoverbit outside this topic.



> Signed-off-by: Beat Bolli <dev+git@drbeat.li>
> ---
>  Documentation/howto/update-hook-example.txt | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.txt
> index 151ee84cebce..4e727deedd21 100644
> --- a/Documentation/howto/update-hook-example.txt
> +++ b/Documentation/howto/update-hook-example.txt
> @@ -100,7 +100,7 @@ info "The user is: '$username'"
>  
>  if test -f "$allowed_users_file"
>  then
> -  rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
> +  rc=$(grep -Ev '^(#|$)' $allowed_users_file |
>      while read heads user_patterns
>      do
>        # does this rule apply to us?
> @@ -138,7 +138,7 @@ info "'$groups'"
>  
>  if test -f "$allowed_groups_file"
>  then
> -  rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
> +  rc=$(grep -Ev '^(#|$)' $allowed_groups_file |
>      while read heads group_patterns
>      do
>        # does this rule apply to us?

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] revision: fix --missing=[print|allow*] for annotated tags
  @ 2024-02-28 17:46  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-28 17:46 UTC (permalink / raw)
  To: Christian Couder
  Cc: git, Patrick Steinhardt, John Cai, Linus Arver, Eric Sunshine,
	Christian Couder

Christian Couder <christian.couder@gmail.com> writes:

> 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);

This is locally a no-op but we need it because we will use oid
later, OK.

>  		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;
> +			}

And we recover from the "oh, that is not an object" by doing the
usual "add to missing-objects list".  OK.

At this point we do not know the type of the tagged object (the tag
itself may hint what the tagged object is, though).  We might want
to rename .missing_commits to .missing_objects later after the dust
settles.  revision.c:get_reference() already adds anything that is
pointed at by a ref to this oidset already, so it is not a new
problem with this patch, though.

> 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" &&

Hmph, this might be OK for now, but recently I saw Dscho used a nice
trick to prepare a packfile that excludes certain objects in a
separate directory and use that directory as GIT_OBJECT_DIRECTORY to
simulate a situation where some objects are missing without touching
this level of implementation details.  We may want to clean things
up.

Perhaps somebody will write a shell helper function that creates
such an object directory that contains all objects in the current
repository, except for ones that are specified.  And then we add it
to t/test-lib-functions.sh, so that it can be used to update various
tests (#leftoverbits).

>  				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.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] git: extend --no-lazy-fetch to work across subprocesses
  2024-02-27  6:04  7%           ` Junio C Hamano
@ 2024-02-27  7:49  6%             ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2024-02-27  7:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Christian Couder

On Mon, Feb 26, 2024 at 10:04:54PM -0800, Junio C Hamano wrote:

> ----- >8 --------- >8 --------- >8 --------- >8 -----
> Subject: [PATCH v2 3/3] git: extend --no-lazy-fetch to work across subprocesses
> [...]

This looks pretty reasonable to me, and the lines you drew for
#leftoverbits all seemed liked good spots.

The only thing I noticed in the patch was this (which I think is not
even new in this round):

> diff --git a/environment.c b/environment.c
> index 9e37bf58c0..afad78a3f8 100644
> --- a/environment.c
> +++ b/environment.c
> @@ -136,6 +136,7 @@ const char * const local_repo_env[] = {
>  	GRAFT_ENVIRONMENT,
>  	INDEX_ENVIRONMENT,
>  	NO_REPLACE_OBJECTS_ENVIRONMENT,
> +	NO_LAZY_FETCH_ENVIRONMENT,
>  	GIT_REPLACE_REF_BASE_ENVIRONMENT,
>  	GIT_PREFIX_ENVIRONMENT,
>  	GIT_SHALLOW_FILE_ENVIRONMENT,

This will clear the environment variable when we move between
repositories. I can see an argument for it, and certainly that's how
GIT_NO_REPLACE_OBJECTS works.

But I can also see an argument that this is not a property of the
_repository_, but of the request. For example, if I run "git
--no-lazy-fetch log" and we cross into a submodule to do a diff, should
that submodule also avoid lazy-fetching? I'd think so, but I think your
patch would restore the defaults when we "enter" the submodule repo.

There's some prior art there, I think, in how GIT_CEILING_DIRECTORIES
works, or even something like "git --literal-pathspecs", neither of
which appear in local_repo_env.

-Peff

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] git: extend --no-lazy-fetch to work across subprocesses
  @ 2024-02-27  6:04  7%           ` Junio C Hamano
  2024-02-27  7:49  6%             ` Jeff King
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-02-27  6:04 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Christian Couder

Jeff King <peff@peff.net> writes:

>> diff --git a/Documentation/git.txt b/Documentation/git.txt
>> index 2f1cb3ef4e..be2829003d 100644
>> --- a/Documentation/git.txt
>> +++ b/Documentation/git.txt
>> @@ -183,6 +183,8 @@ If you just want to run git as if it was started in `<path>` then use
>>  	Do not fetch missing objects from the promisor remote on
>>  	demand.  Useful together with `git cat-file -e <object>` to
>>  	see if the object is locally available.
>> +	This is equivalent to setting the `GIT_NO_LAZY_FETCH`
>> +	environment variable to `1`.
>
> As with the other patch, I'd suggest adding an entry to the list of
> environment variables later in the manpage.

Thanks, done.

We'll have to make a separate patch to add GIT_NO_REPLACE_OBJECTS to
the list, by the way (#leftoverbits), which I used as a model to
find what needs to be updated.

>> --- a/environment.h
>> +++ b/environment.h
>> @@ -35,6 +35,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);
>>  #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
>>  #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
>>  #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
>> +#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
>>  #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
>>  #define GITATTRIBUTES_FILE ".gitattributes"
>>  #define INFOATTRIBUTES_FILE "info/attributes"
>
> A small nit, but maybe worth keeping the two replace-related variables
> next to each other, rather than sticking the new one in the middle?

OK.

>> diff --git a/git.c b/git.c
>> index 28e8bf7497..d11d4dc77b 100644
>> --- a/git.c
>> +++ b/git.c
>> @@ -189,6 +189,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
>>  				*envchanged = 1;
>>  		} else if (!strcmp(cmd, "--no-lazy-fetch")) {
>>  			fetch_if_missing = 0;
>> +			setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
>> +			if (envchanged)
>> +				*envchanged = 1;
>>  		} else if (!strcmp(cmd, "--no-replace-objects")) {
>>  			disable_replace_refs();
>>  			setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
>
> I _suspect_ this makes the fetch_if_missing call redundant, since we
> should be parsing these before doing any repo setup that would trigger
> the code that reads the environment variable.

True.  Again, we'd need to clean-up the NO_REPLACE_OBJECTS codepath
as well---the disable_replace_refs() call should also be redundant,
which I mimicked to add the no-lazy-fetch codepath (#leftoverbits).

> This should probably also be xsetenv(), though as you can see in the
> context we are not very consistent about using it. :) But certainly if
> we failed to set it I would prefer to see an error rather than
> accidentally lazy-fetching.

I'd probably leave it outside the scope of this series; as nobody
uses xsetenv() in git.c currently, it would be a clean-up topic on
its own (#leftoverbits).

>> diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
>> index 5b7bee888d..59629cea1f 100755
>> --- a/t/t0410-partial-clone.sh
>> +++ b/t/t0410-partial-clone.sh
>> @@ -665,6 +665,15 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
>>  	git -C partial.git rev-list --objects --missing=print HEAD >out &&
>>  	grep "[?]$FILE_HASH" out &&
>>  
>> +	# The no-lazy-fetch mechanism prevents Git from fetching
>> +	test_must_fail env GIT_NO_LAZY_FETCH=1 \
>> +		git -C partial.git cat-file -e "$FILE_HASH" &&
>> +	test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
>> +
>> +	# Sanity check that the file is still missing
>> +	git -C partial.git rev-list --objects --missing=print HEAD >out &&
>> +	grep "[?]$FILE_HASH" out &&
>
> OK, we exercise it by setting the variable directly. A more interesting
> one might be:
>
>   git -c alias.foo='!git cat-file' --no-lazy-fetch ...
>
> which should fail without the patch.

True, again.  I'll test all three variants (i.e. environment,
command line option to "git", forced subprocess turning command line
option to "git" into environment).

Thanks.



----- >8 --------- >8 --------- >8 --------- >8 -----
Subject: [PATCH v2 3/3] git: extend --no-lazy-fetch to work across subprocesses

Modeling after how the `--no-replace-objects` option is made usable
across subprocess spawning (e.g., cURL based remote helpers are
spawned as a separate process while running "git fetch"), allow the
`--no-lazy-fetch` option to be passed across process boundaries.

Do not model how the value of GIT_NO_REPLACE_OBJECTS environment
variable is ignored, though.  Just use the usual git_env_bool() to
allow "export GIT_NO_LAZY_FETCH=0" and "unset GIT_NO_LAZY_FETCH"
to be equivalents.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Range-diff:
1:  00e202b679 ! 1:  e0764f2e21 git: extend --no-lazy-fetch to work across subprocesses
    @@ Documentation/git.txt: If you just want to run git as if it was started in `<pat
      
      --literal-pathspecs::
      	Treat pathspecs literally (i.e. no globbing, no pathspec magic).
    +@@ Documentation/git.txt: for full details.
    + 	Setting this Boolean environment variable to true will cause Git to treat all
    + 	pathspecs as case-insensitive.
    + 
    ++`GIT_NO_LAZY_FETCH`::
    ++	Setting this Boolean environment variable to true tells Git
    ++	not to lazily fetch missing objects from the promisor remote
    ++	on demand.
    ++
    + `GIT_REFLOG_ACTION`::
    + 	When a ref is updated, reflog entries are created to keep
    + 	track of the reason why the ref was updated (which is
     
      ## environment.c ##
     @@ environment.c: const char * const local_repo_env[] = {
    @@ environment.c: void setup_git_env(const char *git_dir)
     
      ## environment.h ##
     @@ environment.h: const char *getenv_safe(struct strvec *argv, const char *name);
    - #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
      #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
      #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
    -+#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
      #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
    ++#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
      #define GITATTRIBUTES_FILE ".gitattributes"
      #define INFOATTRIBUTES_FILE "info/attributes"
    + #define ATTRIBUTE_MACRO_PREFIX "[attr]"
     
      ## git.c ##
     @@ git.c: static int handle_options(const char ***argv, int *argc, int *envchanged)
    @@ t/t0410-partial-clone.sh: test_expect_success 'lazy-fetch when accessing object
     +	# The no-lazy-fetch mechanism prevents Git from fetching
     +	test_must_fail env GIT_NO_LAZY_FETCH=1 \
     +		git -C partial.git cat-file -e "$FILE_HASH" &&
    ++
    ++	# The same with command line option to "git"
     +	test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
     +
    ++	# The same, forcing a subprocess via an alias
    ++	test_must_fail git --no-lazy-fetch -C partial.git \
    ++		-c alias.foo="!git cat-file" foo -e "$FILE_HASH" &&
    ++
     +	# Sanity check that the file is still missing
     +	git -C partial.git rev-list --objects --missing=print HEAD >out &&
     +	grep "[?]$FILE_HASH" out &&

 Documentation/git.txt    |  7 +++++++
 environment.c            |  4 ++++
 environment.h            |  1 +
 git.c                    |  3 +++
 t/t0410-partial-clone.sh | 15 +++++++++++++++
 5 files changed, 30 insertions(+)

diff --git a/Documentation/git.txt b/Documentation/git.txt
index 2f1cb3ef4e..6fbaa9dd2b 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -183,6 +183,8 @@ If you just want to run git as if it was started in `<path>` then use
 	Do not fetch missing objects from the promisor remote on
 	demand.  Useful together with `git cat-file -e <object>` to
 	see if the object is locally available.
+	This is equivalent to setting the `GIT_NO_LAZY_FETCH`
+	environment variable to `1`.
 
 --literal-pathspecs::
 	Treat pathspecs literally (i.e. no globbing, no pathspec magic).
@@ -896,6 +898,11 @@ for full details.
 	Setting this Boolean environment variable to true will cause Git to treat all
 	pathspecs as case-insensitive.
 
+`GIT_NO_LAZY_FETCH`::
+	Setting this Boolean environment variable to true tells Git
+	not to lazily fetch missing objects from the promisor remote
+	on demand.
+
 `GIT_REFLOG_ACTION`::
 	When a ref is updated, reflog entries are created to keep
 	track of the reason why the ref was updated (which is
diff --git a/environment.c b/environment.c
index 9e37bf58c0..afad78a3f8 100644
--- a/environment.c
+++ b/environment.c
@@ -136,6 +136,7 @@ const char * const local_repo_env[] = {
 	GRAFT_ENVIRONMENT,
 	INDEX_ENVIRONMENT,
 	NO_REPLACE_OBJECTS_ENVIRONMENT,
+	NO_LAZY_FETCH_ENVIRONMENT,
 	GIT_REPLACE_REF_BASE_ENVIRONMENT,
 	GIT_PREFIX_ENVIRONMENT,
 	GIT_SHALLOW_FILE_ENVIRONMENT,
@@ -207,6 +208,9 @@ void setup_git_env(const char *git_dir)
 	shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
 	if (shallow_file)
 		set_alternate_shallow_file(the_repository, shallow_file, 0);
+
+	if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0))
+		fetch_if_missing = 0;
 }
 
 int is_bare_repository(void)
diff --git a/environment.h b/environment.h
index e5351c9dd9..5cec19cecc 100644
--- a/environment.h
+++ b/environment.h
@@ -36,6 +36,7 @@ const char *getenv_safe(struct strvec *argv, const char *name);
 #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
 #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
 #define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
+#define NO_LAZY_FETCH_ENVIRONMENT "GIT_NO_LAZY_FETCH"
 #define GITATTRIBUTES_FILE ".gitattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
diff --git a/git.c b/git.c
index 28e8bf7497..d11d4dc77b 100644
--- a/git.c
+++ b/git.c
@@ -189,6 +189,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--no-lazy-fetch")) {
 			fetch_if_missing = 0;
+			setenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 1);
+			if (envchanged)
+				*envchanged = 1;
 		} else if (!strcmp(cmd, "--no-replace-objects")) {
 			disable_replace_refs();
 			setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 5b7bee888d..c282851af7 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -665,6 +665,21 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
 	git -C partial.git rev-list --objects --missing=print HEAD >out &&
 	grep "[?]$FILE_HASH" out &&
 
+	# The no-lazy-fetch mechanism prevents Git from fetching
+	test_must_fail env GIT_NO_LAZY_FETCH=1 \
+		git -C partial.git cat-file -e "$FILE_HASH" &&
+
+	# The same with command line option to "git"
+	test_must_fail git --no-lazy-fetch -C partial.git cat-file -e "$FILE_HASH" &&
+
+	# The same, forcing a subprocess via an alias
+	test_must_fail git --no-lazy-fetch -C partial.git \
+		-c alias.foo="!git cat-file" foo -e "$FILE_HASH" &&
+
+	# Sanity check that the file is still missing
+	git -C partial.git rev-list --objects --missing=print HEAD >out &&
+	grep "[?]$FILE_HASH" out &&
+
 	git -C full cat-file -s "$FILE_HASH" >expect &&
 	test-tool partial-clone object-info partial.git "$FILE_HASH" >actual &&
 	test_cmp expect actual &&
-- 
2.44.0-35-ga2082dbdd3


^ permalink raw reply related	[relevance 7%]

* Re: [PATCH v3 4/5] Always check `parse_tree*()`'s return value
  @ 2024-02-22 17:58  5%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-22 17:58 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget
  Cc: git, Patrick Steinhardt, Eric Sunshine, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> @@ -707,7 +707,8 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
>  	init_checkout_metadata(&opts.meta, info->refname,
>  			       info->commit ? &info->commit->object.oid : null_oid(),
>  			       NULL);
> -	parse_tree(tree);
> +	if (parse_tree(tree) < 0)
> +		return 128;

The other error returned from this function is when unpack_trees()
fails well before the writeout phase and the value we return is also
128, so the caller is prepared to act on it.  OK.

> @@ -786,9 +787,15 @@ static int merge_working_tree(const struct checkout_opts *opts,
>  		if (new_branch_info->commit)
>  			BUG("'switch --orphan' should never accept a commit as starting point");
>  		new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
> -	} else
> +		if (!new_tree)
> +			BUG("unable to read empty tree");

parse_tree() of the_hash_algo->empty_tree should result in a tree
object without having to even consult the object store, so BUG(),
not die(), is very much appropriate here.  OK.

> +	} else {
>  		new_tree = repo_get_commit_tree(the_repository,
>  						new_branch_info->commit);
> +		if (!new_tree)
> +			return error(_("unable to read tree %s"),
> +				     oid_to_hex(&new_branch_info->commit->object.oid));

We can help translators by enclosing %s inside a pair of parentheses.

    $ git grep -h 'msgid .*unable to read tree' po | sort | uniq -c
     18 msgid "unable to read tree (%s)"

FYI, the message with "(%s)" is shared by four places; there is one
instance of the message without parentheses added very recently that
forced .po files to have both entries.  We probably should unify them
to use the one with more existing users.

> @@ -823,7 +830,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
>  				oid_to_hex(old_commit_oid));
>  
>  		init_tree_desc(&trees[0], tree->buffer, tree->size);
> -		parse_tree(new_tree);
> +		if (parse_tree(new_tree) < 0)
> +			exit(128);

There is another exit() in the same else clause this code is in, and
upon failing to unpack_trees(), that call exits with 128.  This
parse_tree() is about preparing the input for that call, so it makes
sense to exit with the same code.  Excellent.

> diff --git a/builtin/clone.c b/builtin/clone.c
> index c6357af9498..4410b55be98 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -736,7 +736,8 @@ static int checkout(int submodule_progress, int filter_submodules)
>  	tree = parse_tree_indirect(&oid);
>  	if (!tree)
>  		die(_("unable to parse commit %s"), oid_to_hex(&oid));
> -	parse_tree(tree);
> +	if (parse_tree(tree) < 0)
> +		exit(128);
>  	init_tree_desc(&t, tree->buffer, tree->size);
>  	if (unpack_trees(1, &t, &opts) < 0)
>  		die(_("unable to checkout working tree"));

Exactly the same reasoning applies, as die() exits with 128.

We may want to "#define EXIT_DIE 128" and use it in appropriate
places to make such a reasoning/review easier (possibly an entry for
#leftoverbits)?

> diff --git a/builtin/commit.c b/builtin/commit.c
> index 781af2e206c..0723f06de7a 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -339,7 +339,8 @@ static void create_base_index(const struct commit *current_head)
>  	tree = parse_tree_indirect(&current_head->object.oid);
>  	if (!tree)
>  		die(_("failed to unpack HEAD tree object"));
> -	parse_tree(tree);
> +	if (parse_tree(tree) < 0)
> +		exit(128);
>  	init_tree_desc(&t, tree->buffer, tree->size);
>  	if (unpack_trees(1, &t, &opts))
>  		exit(128); /* We've already reported the error, finish dying */

Ditto.

> diff --git a/builtin/read-tree.c b/builtin/read-tree.c
> index 8196ca9dd85..5923ed36893 100644
> --- a/builtin/read-tree.c
> +++ b/builtin/read-tree.c
> @@ -263,7 +263,8 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
>  	cache_tree_free(&the_index.cache_tree);
>  	for (i = 0; i < nr_trees; i++) {
>  		struct tree *tree = trees[i];
> -		parse_tree(tree);
> +		if (parse_tree(tree) < 0)
> +			return 128;
>  		init_tree_desc(t+i, tree->buffer, tree->size);
>  	}
>  	if (unpack_trees(nr_trees, t, &opts))

Ditto.  After the post-context we also return 128.

> diff --git a/builtin/reset.c b/builtin/reset.c
> index 4b018d20e3b..f030f57f4e9 100644
> --- a/builtin/reset.c
> +++ b/builtin/reset.c
> @@ -119,6 +119,10 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t
>  
>  	if (reset_type == MIXED || reset_type == HARD) {
>  		tree = parse_tree_indirect(oid);
> +		if (!tree) {
> +			error(_("unable to read tree %s"), oid_to_hex(oid));
> +			goto out;
> +		}
>  		prime_cache_tree(the_repository, the_repository->index, tree);
>  	}

Good.

> diff --git a/cache-tree.c b/cache-tree.c
> index 641427ed410..c6508b64a5c 100644
> --- a/cache-tree.c
> +++ b/cache-tree.c
> @@ -779,8 +779,8 @@ static void prime_cache_tree_rec(struct repository *r,
>  			struct cache_tree_sub *sub;
>  			struct tree *subtree = lookup_tree(r, &entry.oid);
>  
> -			if (!subtree->object.parsed)
> -				parse_tree(subtree);
> +			if (!subtree->object.parsed && parse_tree(subtree) < 0)
> +				exit(128);
>  			sub = cache_tree_sub(it, entry.path);
>  			sub->cache_tree = cache_tree();

The cache_tree() used to be just an optimization mechanism, but
there is no other way than fully populating it to write a tree
object out of the index, so dying here is the only sensible thing to
do upon unparseable subtree.  Otherwise we would end up silently
writing a bogus result.  Good.

> diff --git a/merge-recursive.c b/merge-recursive.c
> index e3beb0801b1..10d41bfd487 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -410,7 +410,8 @@ static inline int merge_detect_rename(struct merge_options *opt)
>  
>  static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
>  {
> -	parse_tree(tree);
> +	if (parse_tree(tree) < 0)
> +		exit(128);
>  	init_tree_desc(desc, tree->buffer, tree->size);
>  }

OK.

> diff --git a/merge.c b/merge.c
> index b60925459c2..14a7325859d 100644
> --- a/merge.c
> +++ b/merge.c
> @@ -80,7 +80,10 @@ int checkout_fast_forward(struct repository *r,
>  		return -1;
>  	}
>  	for (i = 0; i < nr_trees; i++) {
> -		parse_tree(trees[i]);
> +		if (parse_tree(trees[i]) < 0) {
> +			rollback_lock_file(&lock_file);
> +			return -1;
> +		}
>  		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
>  	}

This handles the error in the same way as the other case earlier
where any of the tree-ish failed to load.  OK.

> diff --git a/reset.c b/reset.c
> index 48da0adf851..a93fdbc12e3 100644
> --- a/reset.c
> +++ b/reset.c
> @@ -158,6 +158,11 @@ int reset_head(struct repository *r, const struct reset_head_opts *opts)
>  	}
>  
>  	tree = parse_tree_indirect(oid);
> +	if (!tree) {
> +		ret = error(_("unable to read tree %s"), oid_to_hex(oid));
> +		goto leave_reset_head;
> +	}

OK, but the _("unable to read tree (%s)") comment applies here, too.

> diff --git a/sequencer.c b/sequencer.c
> index d584cac8ed9..407473bab28 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -715,6 +715,8 @@ static int do_recursive_merge(struct repository *r,
>  	o.show_rename_progress = 1;
>  
>  	head_tree = parse_tree_indirect(head);
> +	if (!head_tree)
> +		return error(_("unable to read tree %s"), oid_to_hex(head));
>  	next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);
>  	base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r);

Ditto.

> @@ -3887,6 +3889,8 @@ static int do_reset(struct repository *r,
>  	}
>  
>  	tree = parse_tree_indirect(&oid);
> +	if (!tree)
> +		return error(_("unable to read tree %s"), oid_to_hex(&oid));

Ditto.

>  	prime_cache_tree(r, r->index, tree);
>  
>  	if (write_locked_index(r->index, &lock, COMMIT_LOCK) < 0)

Looking good, modulo the additional translator burden.

Thanks.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v3 1/5] merge-tree: fail with a non-zero exit code on missing tree objects
  @ 2024-02-22 17:13  6%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-22 17:13 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget
  Cc: git, Patrick Steinhardt, Eric Sunshine, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> -	parse_tree(merge_base);
> -	parse_tree(side1);
> -	parse_tree(side2);
> +	if (parse_tree(merge_base) < 0 ||
> +	    parse_tree(side1) < 0 ||
> +	    parse_tree(side2) < 0)
> +		return -1;

Obviously good.

> diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
> index 7d0fa74da74..908c9b540c8 100755
> --- a/t/t4301-merge-tree-write-tree.sh
> +++ b/t/t4301-merge-tree-write-tree.sh
> @@ -951,4 +951,15 @@ test_expect_success '--merge-base with tree OIDs' '
>  	test_cmp with-commits with-trees
>  '
>  
> +test_expect_success 'error out on missing tree objects' '
> +	git init --bare missing-tree.git &&
> +	git rev-list side3 >list &&
> +	git rev-parse side3^: >>list &&
> +	git pack-objects missing-tree.git/objects/pack/side3-tree-is-missing <list &&
> +	side3=$(git rev-parse side3) &&
> +	test_must_fail git --git-dir=missing-tree.git merge-tree $side3^ $side3 >actual 2>err &&
> +	test_grep "Could not read $(git rev-parse $side3:)" err &&
> +	test_must_be_empty actual
> +'

I very much like the way this test emulates an operation in a
repository that lack certaion objects so cleanly, and wish we
had used this pattern instead of poking at loose object files
in hundreds of existing tests (#leftoverbits obviously).

It also justifies why a silent "return -1" in the patch is
sufficient ;-)

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] git-remote.txt: fix typo
  @ 2024-02-21 18:18  6% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-21 18:18 UTC (permalink / raw)
  To: Jakub Wilk; +Cc: git, Abhradeep Chakraborty

Jakub Wilk <jwilk@jwilk.net> writes:

> Signed-off-by: Jakub Wilk <jwilk@jwilk.net>
> ---
>  Documentation/git-remote.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
> index 1dec314834..932a5c3ea4 100644
> --- a/Documentation/git-remote.txt
> +++ b/Documentation/git-remote.txt
> @@ -35,7 +35,7 @@ OPTIONS
>  -v::
>  --verbose::
>  	Be a little more verbose and show remote url after name.
> -	For promisor remotes, also show which filter (`blob:none` etc.)
> +	For promisor remotes, also show which filters (`blob:none` etc.)
>  	are configured.
>  	NOTE: This must be placed between `remote` and subcommand.

When you give more than one filters to "git clone", they are used to
create a single "combined" filter, so strictly speaking, "also show
which filter is configured" is a grammatically valid that might be
more technically correct.  E.g. the user may see

    $ git clone --filter=blob:none --filter=tree:2 $there sample-repo
    $ git -C sample-repo remote -v show
    origin ... (fetch) [combine:blob:none+tree:2]
    origin ... (push)

in the output.  It may not be a bad idea to update the code to show
the filter information in a way that is more clear that we are
seeing a list of filters (perhaps showing the above as "[blob:none
tree:2]" might be a good starting point, as a totally separate topic
(#leftoverbits).

After taking your patch as-is, that is.  In user's mind, they
consider they gave two filters, and making a single combined filter
is something Git did without being asked for its own convenience,
so "which filters are configured" is, while it may be technically
less correct, much closer to what the end-user perceives.

Thanks.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH] rebase: make warning less passive aggressive
  @ 2024-02-20 17:29  6% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-20 17:29 UTC (permalink / raw)
  To: Harmen Stoppels via GitGitGadget; +Cc: git, Harmen Stoppels

"Harmen Stoppels via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Harmen Stoppels <me@harmenstoppels.nl>
>
> When you run `git rebase --continue` when no rebase is in progress, git
> outputs `fatal: no rebase in progress?` which is not a question but a
> statement. This commit makes it appear as a statement.

"This commit makes it appear" -> "Make it appear" (see
SubmittingPatches).

>  builtin/rebase.c | 2 +-

This change is very good, but a commit that touches code should not
touch po/ localizations in this project.  They are updated to match
the code change by respective language teams.

>  po/bg.po         | 2 +-
>  po/ca.po         | 2 +-
>  po/de.po         | 2 +-
>  po/el.po         | 2 +-
>  po/es.po         | 2 +-
>  po/fr.po         | 2 +-
>  po/id.po         | 2 +-
>  po/it.po         | 2 +-
>  po/ko.po         | 2 +-
>  po/pl.po         | 2 +-
>  po/pt_PT.po      | 2 +-
>  po/ru.po         | 2 +-
>  po/sv.po         | 2 +-
>  po/tr.po         | 2 +-
>  po/uk.po         | 2 +-
>  po/vi.po         | 2 +-
>  po/zh_CN.po      | 2 +-
>  po/zh_TW.po      | 2 +-
>  19 files changed, 19 insertions(+), 19 deletions(-)
>
> diff --git a/builtin/rebase.c b/builtin/rebase.c
> index 5b086f651a6..415783c4a21 100644
> --- a/builtin/rebase.c
> +++ b/builtin/rebase.c
> @@ -1254,7 +1254,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
>  		die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
>  
>  	if (options.action != ACTION_NONE && !in_progress)
> -		die(_("No rebase in progress?"));
> +		die(_("No rebase in progress"));
>  
>  	if (options.action == ACTION_EDIT_TODO && !is_merge(&options))
>  		die(_("The --edit-todo action can only be used during "

Interestingly this change does not break any test in t/ directory,
which means we have a gap in test coverage.  It should not be any
part of this patch, but we may want to add a test to exercise this
codepath (#leftoverbits).

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] unit-tests: do show relative file paths on non-Windows, too
  @ 2024-02-13 20:48  6%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-13 20:48 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Phillip Wood, git, Randall S. Becker

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

>> +		/*
>> +		 * The path could be relative (t/unit-tests/test-lib.c)
>> +		 * or full (/home/user/git/t/unit-tests/test-lib.c).
>> +		 * Check the slash between "t" and "unit-tests".
>> +		 */
>> +		prefix_len = len - needle_len;
>> +		if (prefix[prefix_len + 1] == '/') {
>> +			/* Oh, we're not Windows */
>> +			for (size_t i = 0; i < needle_len; i++)
>> +				if (needle[i] == '\\')
>> +					needle[i] = '/';
>
> This looks very similar to the `convert_slashes()` function that is
> defined in `compat/mingw.h`.

I lifted it from your later loop in the function, but given that
many of the things that needed on Windows came from you, it is not
surprising if you have another copy there ;-)

> It might be a good opportunity to rename that
> function and move it to `git-compat-util.h`, then use it here and once
> more below at the end of `make_relative()`.

Right.  But not as part of the -rc fix.  Let's leave it as
#leftoverbits.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] prune: mark rebase autostash and orig-head as reachable
  @ 2024-02-09 18:04  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-09 18:04 UTC (permalink / raw)
  To: Phillip Wood via GitGitGadget
  Cc: git, Orgad Shaneh, Eric Sunshine, Phillip Wood

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +static void add_rebase_files(struct rev_info *revs)
> +{
> +	struct strbuf buf = STRBUF_INIT;
> +	size_t len;
> +	const char *path[] = {
> +		"rebase-apply/autostash",
> +		"rebase-apply/orig-head",
> +		"rebase-merge/autostash",
> +		"rebase-merge/orig-head",
> +	};

Yuck.

Having this table here makes the sequencer subsystem even less
maintainable than it already is.  I wonder if we can at least
somehow share some of these?  #leftoverbits.

Thanks.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH 1/2] show-ref --verify: accept pseudorefs
  2024-02-07 17:12  6%   ` Junio C Hamano
@ 2024-02-08 14:34  0%     ` phillip.wood123
  0 siblings, 0 replies; 200+ results
From: phillip.wood123 @ 2024-02-08 14:34 UTC (permalink / raw)
  To: Junio C Hamano, Phillip Wood via GitGitGadget
  Cc: git, Patrick Steinhardt, Phillip Wood

Hi Junio

On 07/02/2024 17:12, Junio C Hamano wrote:
> "Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:
> I think the helper you picked is the most sensible one, modulo a few
> nits.
> 
>   - We would want to teach refname_is_safe() to honor is_pseudoref()
>     from Karthik's series to make rules more consistent.

Yes, I held off sending this series waiting for a while but then got 
impatient. We may want to split out a helper from is_pseudoref() that 
just checks the name without trying to read the ref for callers like 
this which are going to read the ref anyway.

>   - The refname_is_safe() helper is not just about the stuff at the
>     root level.  While starts_with("refs/") is overly lenient, it
>     rejects nonsense like "refs/../trash".  We would want to lose
>     "starts_with() ||" part of the condition from here.

I left the "starts_with()" in as we check the refname when we look it up 
with read_ref() so it seemed like wasted effort to do it here as well.

> These are minor non-blocking nits that we should keep in mind only
> for longer term maintenance, #leftoverbits after the dust settles.
 >
> Will queue.

Thanks

Phillip

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 1/2] show-ref --verify: accept pseudorefs
  @ 2024-02-07 17:12  6%   ` Junio C Hamano
  2024-02-08 14:34  0%     ` phillip.wood123
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2024-02-07 17:12 UTC (permalink / raw)
  To: Phillip Wood via GitGitGadget; +Cc: git, Patrick Steinhardt, Phillip Wood

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> ... when CHERRY_PICK_HEAD exists. By calling refname_is_safe() instead
> of comparing the refname to "HEAD" we can accept all one-level refs that
> contain only uppercase ascii letters and underscores.

Geez.  We have at least three implementations to determine if a ref
is a valid name?

> diff --git a/builtin/show-ref.c b/builtin/show-ref.c
> index 79955c2856e..1c15421e600 100644
> --- a/builtin/show-ref.c
> +++ b/builtin/show-ref.c
> @@ -172,7 +172,7 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,
>  	while (*refs) {
>  		struct object_id oid;
>  
> -		if ((starts_with(*refs, "refs/") || !strcmp(*refs, "HEAD")) &&
> +		if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) &&

I think the helper you picked is the most sensible one, modulo a few
nits.

 - We would want to teach refname_is_safe() to honor is_pseudoref()
   from Karthik's series to make rules more consistent.

 - The refname_is_safe() helper is not just about the stuff at the
   root level.  While starts_with("refs/") is overly lenient, it
   rejects nonsense like "refs/../trash".  We would want to lose
   "starts_with() ||" part of the condition from here.

These are minor non-blocking nits that we should keep in mind only
for longer term maintenance, #leftoverbits after the dust settles.

Will queue.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 0/2] index-pack: fsck honor checks
  @ 2024-02-01 16:44  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-02-01 16:44 UTC (permalink / raw)
  To: John Cai; +Cc: Jonathan Tan, John Cai via GitGitGadget, git

John Cai <johncai86@gmail.com> writes:

>>> Thanks for clarifying! Would you mind providing a patch to revise the wording
>>> here to make it clearer? I would try but I feel like I might get the wording
>>> wrong.
>>
>> I think the wording there is already mostly correct, except maybe make
>> everything plural (a tree -> trees, a .gitmodules blob -> .gitmodules
>> blobs, hash of that blob -> hashes of those blobs). We might also need
>> to modify a test to show that the current code indeed handles the plural
>> situation correctly. I don't have time right now to get to this, so
>> hopefully someone could pick this up.
>
> Thanks! It sounds like we may want to tackle this as part of another patch.

Yeah, the existing documentation has been with our users for some
time, and it is not ultra urgent to fix it in that sense.  I'd say
that it can even wait until JTan gets bored with what he's doing and
needs some distraction himself ;-) 

As long as our collective mind remembers it as #leftoverbits it
would be sufficient.

Thanks, both.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 3/4] config: factor out global config file retrieval
  @ 2024-01-19 23:04  6%           ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-01-19 23:04 UTC (permalink / raw)
  To: Patrick Steinhardt
  Cc: Kristoffer Haugsbakk, git, stolee, Eric Sunshine, Taylor Blau

Patrick Steinhardt <ps@pks.im> writes:

> Yeah, you're right that `git_system_config()` is bad in the same way. In
> fact I think it's worse here because we have both `git_config_system()`
> and `git_system_config()`, which has certainly confused me multiple
> times in the past. So I'd be happy to see it renamed, as well, either
> now or in a follow-up patch series.

OK, let's make a note #leftoverbits here and merge the topic down to
'next'.  By the time it graduates to 'master', we may have a clean-up
patch to rename them.

Thanks, all.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] git-p4: stop reaching into the refdb
  @ 2024-01-11 21:20  6% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2024-01-11 21:20 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git

Patrick Steinhardt <ps@pks.im> writes:

> The git-p4 tool creates a bunch of temporary branches that share a
> common prefix "refs/git-p4-tmp/". These branches get cleaned up via
> git-update-ref(1) after the import has finished. Once done, we try to
> manually remove the now supposedly-empty ".git/refs/git-p4-tmp/"
> directory.
>
> This last step can fail in case there still are any temporary branches
> around that we failed to delete because `os.rmdir()` refuses to delete a
> non-empty directory. It can thus be seen as kind of a sanity check to
> verify that we really did delete all temporary branches.

Wow, thanks for being very careful.  I would just have said "there
is no need for such rmdir---what's a single empty unused directory
between friends, which will be reused later when you run 'git p4'
again?" without thinking things through.

> This is a modification in behaviour for the "files" backend because the
> empty directory does not get deleted anymore. But arguably we should not
> care about such implementation details of the ref backend anyway, and
> this should not cause any user-visible change in behaviour.

Independently, it would be sensible to improve the files backend so
that it removes a subdirectory outside the hierarchies that are
created by refs/files-backend.c:files_init_db() when it becomes
empty (#leftoverbits).

And such a change would also have triggered the error from
os.rmdir(), so this patch is doubly welcomed.

Thanks.




> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  git-p4.py | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/git-p4.py b/git-p4.py
> index 0eb3bb4c47..3ea1c405e5 100755
> --- a/git-p4.py
> +++ b/git-p4.py
> @@ -4251,7 +4251,8 @@ def run(self, args):
>          if self.tempBranches != []:
>              for branch in self.tempBranches:
>                  read_pipe(["git", "update-ref", "-d", branch])
> -            os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation))
> +            if len(read_pipe(["git", "for-each-ref", self.tempBranchLocation])) > 0:
> +                   die("There are unexpected temporary branches")
>  
>          # Create a symbolic ref p4/HEAD pointing to p4/<branch> to allow
>          # a convenient shortcut refname "p4".

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] revision: parse integer arguments to --max-count, --skip, etc., more carefully
  @ 2023-12-12 22:05  6%         ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2023-12-12 22:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Britton Kerin

On Tue, Dec 12, 2023 at 07:09:02AM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > This all looks pretty reasonable to me.
> >
> > I couldn't help but think, though, that surely we have some helpers for
> > this already? But the closest seems to be git_parse_int(), which also
> > allows unit factors. I'm not sure if allowing "-n 1k" would be a feature
> > or a bug. ;)
> 
> The change in question is meant to be a pure fix to replace a careless
> use of atoi().  I do not mind to see a separate patch to add such a
> feature later on top.

Oh, I mostly meant that I would have turned to git_parse_int() as that
already-existing helper, but it is not suitable because of the extra
unit-handling. I think your patch draws the line in the right place.

> > I wonder if there are more spots that could benefit.
> 
> "git grep -e 'atoi('" would give somebody motivated a decent set of
> #microproject ideas, but many hits are not suited for strtol_i(),
> which is designed to parse an integer at the end of a string.  Some
> places use atoi() immediately followed by strspn() to skip over
> digits, which means they are parsing an integer and want to continue
> reading after the integer, which is incompatible with what
> strtol_i() wants to do.  They need either a separate helper or an
> updated strtol_i() that optionally allows you to parse the prefix
> and report where the integer ended, e.g., something like:

Yeah, I agree this might be a good microproject (or leftoverbits) area,
and the semantics for the helper you propose make sense to me.

-Peff

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] sequencer: remove use of comment character
  2023-10-30  4:00  6% ` Junio C Hamano
@ 2023-10-30 17:26  0%   ` Elijah Newren
  0 siblings, 0 replies; 200+ results
From: Elijah Newren @ 2023-10-30 17:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Tony Tung via GitGitGadget, git, Tony Tung

On Sun, Oct 29, 2023 at 9:01 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Tony Tung via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Tony Tung <tonytung@merly.org>
> >
> > Instead of using the hardcoded `# `, use the
> > user-defined comment_line_char.  Adds a test
> > to prevent regressions.
>
> Good spotting.
>
> Two observations.
>
>  (1) There are a few more places that need similar treatment in the
>      same file; you may want to fix them all while at it.
>
>  (2) The second argument to strbuf_commented_addf() is always the
>      comment_line_char global variable, not just inside this file
>      but all callers across the codebase.  We probably should drop
>      it and have the strbuf_commented_addf() helper itself refer to
>      the global.  That way, if we ever want to change the global
>      variable reference to something else (e.g. function call), we
>      only have to touch a single place.
>
> The latter is meant as #leftoverbits and will be a lot wider
> clean-up that we may want to do long after this patch hits out
> codebase.  The "other places" I spotted for the former are the
> following, but needs to be taken with a huge grain of salt, as it
> has not even been compile tested.
>
> Thanks.
>
>  sequencer.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git c/sequencer.c w/sequencer.c
> index d584cac8ed..33208b1660 100644
> --- c/sequencer.c
> +++ w/sequencer.c
> @@ -1893,8 +1893,8 @@ static void update_squash_message_for_fixup(struct strbuf *msg)
>         size_t orig_msg_len;
>         int i = 1;
>
> -       strbuf_addf(&buf1, "# %s\n", _(first_commit_msg_str));
> -       strbuf_addf(&buf2, "# %s\n", _(skip_first_commit_msg_str));
> +       strbuf_addf(&buf1, comment_line_char, "%s\n", _(first_commit_msg_str));
> +       strbuf_addf(&buf2, comment_line_char, "%s\n", _(skip_first_commit_msg_str));
>         s = start = orig_msg = strbuf_detach(msg, &orig_msg_len);
>         while (s) {
>                 const char *next;
> @@ -2269,8 +2269,8 @@ static int do_pick_commit(struct repository *r,
>                 next = parent;
>                 next_label = msg.parent_label;
>                 if (opts->commit_use_reference) {
> -                       strbuf_addstr(&msgbuf,
> -                               "# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
> +                       strbuf_commented_addf(&msgbuf, comment_line_char, "%s",
> +                               "*** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
>                 } else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) &&
>                            /*
>                             * We don't touch pre-existing repeated reverts, because
>

I thought the point of the comment_line_char was so that commit
messages could have lines starting with '#'.  That rationale doesn't
apply to the TODO list generation or parsing, and I'm not sure if we
want to add the same complexity there.  If we do want to add the same
complexity there, I'm worried that making these changes are
insufficent; there are some other hardcoded '#' references in the code
(as a quick greps for '".*#' and "'#'" will turn up).  Since those
other references include parsing as well as generation, I think we
might actually be introducing bugs in the TODO list handling if we
only partially convert it, but someone would need to double check.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] sequencer: remove use of comment character
  @ 2023-10-30  4:00  6% ` Junio C Hamano
  2023-10-30 17:26  0%   ` Elijah Newren
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-30  4:00 UTC (permalink / raw)
  To: Tony Tung via GitGitGadget; +Cc: git, Tony Tung

"Tony Tung via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Tony Tung <tonytung@merly.org>
>
> Instead of using the hardcoded `# `, use the
> user-defined comment_line_char.  Adds a test
> to prevent regressions.

Good spotting.

Two observations.

 (1) There are a few more places that need similar treatment in the
     same file; you may want to fix them all while at it.

 (2) The second argument to strbuf_commented_addf() is always the
     comment_line_char global variable, not just inside this file
     but all callers across the codebase.  We probably should drop
     it and have the strbuf_commented_addf() helper itself refer to
     the global.  That way, if we ever want to change the global
     variable reference to something else (e.g. function call), we
     only have to touch a single place.

The latter is meant as #leftoverbits and will be a lot wider
clean-up that we may want to do long after this patch hits out
codebase.  The "other places" I spotted for the former are the
following, but needs to be taken with a huge grain of salt, as it
has not even been compile tested.

Thanks.

 sequencer.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git c/sequencer.c w/sequencer.c
index d584cac8ed..33208b1660 100644
--- c/sequencer.c
+++ w/sequencer.c
@@ -1893,8 +1893,8 @@ static void update_squash_message_for_fixup(struct strbuf *msg)
 	size_t orig_msg_len;
 	int i = 1;
 
-	strbuf_addf(&buf1, "# %s\n", _(first_commit_msg_str));
-	strbuf_addf(&buf2, "# %s\n", _(skip_first_commit_msg_str));
+	strbuf_addf(&buf1, comment_line_char, "%s\n", _(first_commit_msg_str));
+	strbuf_addf(&buf2, comment_line_char, "%s\n", _(skip_first_commit_msg_str));
 	s = start = orig_msg = strbuf_detach(msg, &orig_msg_len);
 	while (s) {
 		const char *next;
@@ -2269,8 +2269,8 @@ static int do_pick_commit(struct repository *r,
 		next = parent;
 		next_label = msg.parent_label;
 		if (opts->commit_use_reference) {
-			strbuf_addstr(&msgbuf,
-				"# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
+			strbuf_commented_addf(&msgbuf, comment_line_char, "%s",
+				"*** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
 		} else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) &&
 			   /*
 			    * We don't touch pre-existing repeated reverts, because

^ permalink raw reply related	[relevance 6%]

* Re: [PATCH v3 3/3] rev-list: add commit object support in `--missing` option
  2023-10-20 16:41  5%         ` Junio C Hamano
@ 2023-10-24 11:34  0%           ` Karthik Nayak
  0 siblings, 0 replies; 200+ results
From: Karthik Nayak @ 2023-10-24 11:34 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, ps

On Fri, Oct 20, 2023 at 6:41 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> Junio C Hamano <gitster@pobox.com> writes:
>
> > Rather, I was wondering if we need to use object flags to mark these
> > objects, or can do what we want to do without using any object flags
> > at all.  For the purpose of reporting "missing" objects, wouldn't it
> > be sufficient to walk the object graph and report our findings as we
> > go?  To avoid reporting the same object twice, as we reasonably can
> > expect that the missing objects are minority (compared to the total
> > number of objects), perhaps the codepath that makes such a report
> > can use a hashmap of object_ids or something, for example.
>
> Digging from the bottom,
>
>  * builtin/rev-list.c:show_commit() gets "struct rev_list_info *"
>    that has "struct rev_info *" [*].
>
>  * list-objects.c:do_traverse() calls revision.c:get_revision() to
>    obtain commits, some of which may be missing ones, and things
>    behind get_revision() are responsible for marking the commit as
>    missing.  It has "struct traversal_context *", among whose
>    members is the "revs" member that is the "struct rev_info *".
>
>  * revision.c:get_revision() and machinery behind it ultimately
>    discovers a missing commit in the revision.c:process_parents()
>    that loops over the parents commit_list.  It of course has access
>    to "struct rev_info *".
>
> So, presumably, if we add a new member to "struct rev_info" that
> optionally [*] points at an oidset that records the object names of
> missing objects we discovered so far (i.e., the set of missing
> objects), the location we set the MISSING bit of a commit can
> instead add the object name of the commit to the set.  And we can
> export a function that takes "struct rev_info *" and "struct object
> *" (or "struct object_id *") to check for membership in the "set of
> missing objects", which would be used where we checked the MISSING
> bit of a commit.
>
> I do not know the performance implications of going this route, but
> if we do not find a suitable vacant bit, we do not have to use any
> object flags bit to do this, if we go this route, I would think.  I
> may be missing some details that breaks the above outline, though.
>
>
> [Footnotes]
>
>  * A potential #leftoverbits tangent.
>
>    Why is "rev_list_info" structure declared in <bisect.h>?  I
>    suspect that this is a fallout from recent header file shuffling,
>    but given who uses it (among which is rev-list:show_commit() that
>    has very little to do with bisection and uses the information in
>    rev_list_info when doing its normal non-bisect things), it does
>    not make much sense.
>
>  * When .do_not_die_on_missing_objects is false, it can and should
>    be left NULL, but presumably we use the "do not die" bit even
>    when we are not necessarily collecting the missing objects?  So
>    the new member cannot replace the "do not die" bit completely.

Thanks for the suggestion, this does seem like a good way to go ahead without
using flags. The only performance issue being if there are too many commits
which are missing, then oidset would be large.

But I think that's okay though.

> Thanks for researching.  It sounds like it may be a better bit to
> steal than the one used by the commit-graph, as long as there is no
> reason to expect that blame may want to work in a corrupt repository
> with missing objects, but when it happens, we may regret the
> decision we are making here.
>

I don't see blame working with missing commits though, because it relies on
parsing commits to get information to show to the user. So I think it's a safe
bit to steal. Also, when the time comes we could always release the bit and
move to the solution you mentioned above.

Anyways on the whole I think keeping it future compatible makes a lot
more sense.
I'll send a patch series to implement an oidset instead of flags soon.

- Karthik

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-23  0:20  0%       ` Junio C Hamano
@ 2023-10-23 22:15  0%         ` Andy Koppe
  0 siblings, 0 replies; 200+ results
From: Andy Koppe @ 2023-10-23 22:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, stolee

On 23/10/2023 01:20, Junio C Hamano wrote:
> Andy Koppe <andy.koppe@gmail.com> writes:
> 
>>>    [2/7] is a trivial readability improvement.  It obviously should be
>>>          left outside the scope of this series, but we should notice
>>>          the same pattern in similar color tables (e.g., wt-status.c
>>>          has one, diff.c has another) and perform the same clean-up as
>>>          a #leftoverbits item.
>>
>> Okay, I've removed that commit in v2. (I should have mentioned in the
>> commit message that it was triggered by the inconsistency with the
>> immediately following color_decorate_slots array, which uses
>> designated initializers.)
> 
> Sorry, that is not what I meant.  [2/7] as a preliminary clean-up to
> work in the same area does make very much sense.  What I meant to be
> "outside the scope" was to make similar fixes to other color tables
> that this series does not care about.

Ah, sorry for misreading. Commit reinstated in v3.


>> Fair enough, although the array already contains HEAD and refs/stash
>> as singletons.
> 
> But these deserve to be singletons, don't they?  There is no other
> thing that behaves like HEAD; there is no other thing that behaves
> like stash; and they do not behave like each other.

They do indeed, but arguably the pseudorefs are singletons rather than a 
namespace like refs/heads as well, as there is a defined and documented 
set of them.


>> I've rewritten things to not touch the ref_namespace array.
> 
> Well, the namespace_info mechanism still may be a good place to have
> the necessary information; it may be that the current implementation
> detail of how a given ref is classified to one of the namespaces is
> too limiting---it essentially allows the string match with the .ref
> member.  But we can imagine that it could be extended a bit, e.g.
> 
> 	struct ref_namespace_info {
> 		char *ref;
> 		int (*membership)(const char *, const struct ref_namespace_info *);
> 		... other members ...;
> 	};
> 
> where the .membership member is used in add_ref_decoration() to
> determine the membership of a given "refname" to the namespace "i"
> perhaps like so:
> 
> 	struct ref_namespace_info *info = &ref_namespace[i];
> 
> 	if (!info->decoration)
> 		continue;
> +	if (info->membership) {
> +		if (info->membership(refname, info)) {
> +			deco_type = info->decoration;
> +			break;
> +		}
> +	} else if (info->exact) {
> -	if (info->exact) {
> 		if (!strcmp(refname, info->ref)) {
> 			deco_type = info_decoration;
> 			break;
> 	}
> 
> Then you can arrange the pseudoref class to use .membership function
> perhaps like this:
> 
> 	static int pseudoref_namespace_membership(
> 		const char *refname, const struct ref_namespace_info *info UNUSED
> 	)
> 	{
> 		return is_pseudoref(refname);
> 	}
> 
> and make them all into a single class.

That's an interesting idea, but I'm not convinced it would buy us much, 
while also potentially complicating things for any other uses of the 
ref_namespace array.

My premise here is that we do need a list of the documented pseudorefs, 
so that we can iterate through them and add the ones that do exist to 
the decorations, whereby I admit that shoe-horning that list into the 
ref_namespace array wasn't a good idea. If that premise is wrong, and 
there's a better way to discover the pseudorefs, the following might be 
moot.

Sending each found pseudoref through add_ref_decoration() and its lookup 
of ref_namespace would just confirm what we already know: it's a 
pseudoref. Which is why both my initial attempt and the current one 
don't actually invoke add_ref_decoration() for them.

Could you have a closer look at the current design? It handles the 
pseudorefs separately from proper refs, with their own iteration and 
callback functions, which I think makes for simpler more self-contained 
changes than v1 or the approach suggested above.


> Having said that, I do not think it makes much sense to decorate a
> commit off of refs/stash, as the true richeness of the stash is not
> in its history but in its reflog, which the decoration code does not
> dig into.  But obviously it is not a part of the topic we are
> discussing (unless, of course, we are not "adding" new decoration
> sources and colors, but we are improving the decoration sources and
> colors by adding new useful ones while retiring existing useless
> ones).

I agree refs/stash is a weird one, and that it could be subsumed into 
the color.decoration.ref setting for 'refs/*' that I'm adding here, 
which is also why I chose the same default color for it. I'd be happy to 
drop color.decoration.stash if the minor break in compatibility for 
anyone who has customized it is acceptable. The setting would be quietly 
ignored.

Another related thought: the '--clear-decorations' option of git-log 
seems unfortunately named as it suggests the opposite of what it 
actually does, which is to enable all decorations (unless subsequently 
constrained with '--decorate-refs{,--exclude}=...').

Regards,
Andy

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 04/11] t: convert tests to not write references via the filesystem
  2023-10-18 21:18  5%   ` Junio C Hamano
@ 2023-10-23 13:58  0%     ` Patrick Steinhardt
  0 siblings, 0 replies; 200+ results
From: Patrick Steinhardt @ 2023-10-23 13:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Han-Wen Nienhuys

[-- Attachment #1: Type: text/plain, Size: 5886 bytes --]

On Wed, Oct 18, 2023 at 02:18:27PM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <ps@pks.im> writes:
> 
> > @@ -434,7 +432,7 @@ test_expect_success 'Query "main@{2005-05-28}" (past end of history)' '
> >  	test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e
> >  '
> >  
> > -rm -f .git/$m .git/logs/$m expect
> > +git update-ref -d $m
> 
> We are not clearing "expect" file.  I do not know if it matters
> here, but I am only recording what I noticed.

Oops, will fix.

> > diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
> > index 10a539158c4..5cce24f1006 100755
> > --- a/t/t1450-fsck.sh
> > +++ b/t/t1450-fsck.sh
> > @@ -115,15 +115,16 @@ test_expect_success 'zlib corrupt loose object output ' '
> >  '
> >  
> >  test_expect_success 'branch pointing to non-commit' '
> > -	git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
> > +	tree_oid=$(git rev-parse --verify HEAD^{tree}) &&
> > +	test-tool ref-store main update-ref msg refs/heads/invalid $tree_oid $ZERO_OID REF_SKIP_OID_VERIFICATION &&
> 
> I have mixed feelings on this.
> 
> In olden days, plumbing commands tended to allow to pass anything
> the user told them to use, but in more recent versions of Git, we,
> probably by mistake, managed to butcher some of the plumbing
> commands to make them unable to deliberately "break" repositories,
> one victim being "update-ref", i.e.
> 
>     $ git update-ref refs/heads/invalid HEAD^{tree}
> 
> is rejected these days (I just checked with v1.3.0 and it allows me
> to do this), and that is one of the reasons why we manually broke
> the repository in these tests.

My first try was indeed to use git-update-ref(1) to update the ref to
the tree object, and I was surprised to learn that it would not let me
do so.

> We need to have a warning message in
> comments near the implementation of "ref-store update-ref" that says
> never ever attempt to share code with the production version of
> update-ref---otherwise this (or the "safety" given to the plumbing
> command, possibly by mistake) will be broken, depending on which
> direction such a sharing goes.  On the other hand, forcing us to
> keep two separate implementations, one deliberately loose to allow
> us corrupt repositories, the other for production and actively used,
> would mean the former one that is only used for validation would risk
> bitrotting.

Wouldn't any eventual bitrot be contained by the tests though? As our
use of the test helper grows via this patch series its behaviour will
also be verified more thoroughly.

> >  	test_when_finished "git update-ref -d refs/heads/invalid" &&
> 
> Not a problem this patch introduces, but I think it is a better
> discipline to have when_finished clean-up routine prepared before we
> do actual damage, i.e. if I were writing this test today from scratch,
> I would expect it to be before "git rev-parse >.git/refs/heads/invalid"
> is done.

I'll fix this while at it.

> >  	test_must_fail git fsck 2>out &&
> >  	test_i18ngrep "not a commit" out
> >  '
> 
> A #leftoverbit that is not relevant to the topic; we should clean
> these test_i18ngrep and replace them with a plain "grep".
> 
> >  test_expect_success 'HEAD link pointing at a funny object' '
> > -	test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
> > -	mv .git/HEAD .git/SAVED_HEAD &&
> > +	saved_head=$(git rev-parse --verify HEAD) &&
> > +	test_when_finished "git update-ref HEAD ${saved_head}" &&
> >  	echo $ZERO_OID >.git/HEAD &&
> 
> Are you sure .git/HEAD when this test is entered is a detached HEAD?
> The title of the test says "HEAD link", and I take it to mean HEAD
> is a symlink, and we save it away, while we create a loose ref that
> points at 0{40} in a detached HEAD state.  Actually, the original
> would also work if HEAD is detached on entry.  In either case,
> moving SAVED_HEAD back to HEAD would restore the original state.
> 
> But the updated one only works if HEAD upon entry is already
> detached.  Is this intended?

Yes and no -- it's a reflection of the state when this test runs. One
problem in this test suite here is that many of the tests' states are
heavily interwoven with each other, which only makes this harder to
refactor without making any assumptions.

Well. Instead of restoring to whatever the state was previous to the
test we could also restore it to something sane-ish like "master". That
of course breaks other tests though... I'll investigate.

> > @@ -131,8 +132,8 @@ test_expect_success 'HEAD link pointing at a funny object' '
> >  '
> >  
> >  test_expect_success 'HEAD link pointing at a funny place' '
> > -	test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
> > -	mv .git/HEAD .git/SAVED_HEAD &&
> > +	saved_head=$(git rev-parse --verify HEAD) &&
> > +	test_when_finished "git update-ref --no-deref HEAD ${saved_head}" &&
> 
> Likewise.  Use of "update-ref" in the previous one vs "update-ref
> --no-deref" in this one to recover from the damage the tests make
> makes me feel that we may be assuming too much.
> 
> >  	echo "ref: refs/funny/place" >.git/HEAD &&
> 
> Even though "git symbolic-ref" refuses to point HEAD outside refs/,
> as plumbing command should, it allows it to point it outside refs/heads/.
> so this line should probably become
> 
> 	git symbolic-ref HEAD refs/funny/place
> 
> in the same spirit as the rest of the series.

Yup, this will be adressed in a later patch.

Patrick

> > @@ -391,7 +393,7 @@ test_expect_success 'tag pointing to nonexistent' '
> >  
> >  	tag=$(git hash-object -t tag -w --stdin <invalid-tag) &&
> >  	test_when_finished "remove_object $tag" &&
> > -	echo $tag >.git/refs/tags/invalid &&
> > +	git update-ref refs/tags/invalid $tag &&
> 
> Good (not just this one, but similar ones throughout this patch).
> 
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-22 21:49  0%     ` Andy Koppe
@ 2023-10-23  0:20  0%       ` Junio C Hamano
  2023-10-23 22:15  0%         ` Andy Koppe
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-23  0:20 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git

Andy Koppe <andy.koppe@gmail.com> writes:

>>   [2/7] is a trivial readability improvement.  It obviously should be
>>         left outside the scope of this series, but we should notice
>>         the same pattern in similar color tables (e.g., wt-status.c
>>         has one, diff.c has another) and perform the same clean-up as
>>         a #leftoverbits item.
>
> Okay, I've removed that commit in v2. (I should have mentioned in the
> commit message that it was triggered by the inconsistency with the
> immediately following color_decorate_slots array, which uses
> designated initializers.)

Sorry, that is not what I meant.  [2/7] as a preliminary clean-up to
work in the same area does make very much sense.  What I meant to be
"outside the scope" was to make similar fixes to other color tables
that this series does not care about.

>>         .ref = "refs/", the implementation of the search must know
>>         that it is a fallback position (i.e. if it found a match with
>>         the fallback .ref = "refs/" , unless it looked at all other
>>         entries that could begin with "refs/" and are more specific,
>>         it needs to keep going).
>
> Fair points. I've rewritten things to not touch the ref_namespace array.

Well, the namespace_info mechanism still may be a good place to have
the necessary information; it may be that the current implementation
detail of how a given ref is classified to one of the namespaces is
too limiting---it essentially allows the string match with the .ref
member.  But we can imagine that it could be extended a bit, e.g.

	struct ref_namespace_info {
		char *ref;
		int (*membership)(const char *, const struct ref_namespace_info *);
		... other members ...;
	};

where the .membership member is used in add_ref_decoration() to
determine the membership of a given "refname" to the namespace "i"
perhaps like so:

	struct ref_namespace_info *info = &ref_namespace[i];

	if (!info->decoration)
		continue;
+	if (info->membership) {
+		if (info->membership(refname, info)) {
+			deco_type = info->decoration;
+			break;
+		}
+	} else if (info->exact) {
-	if (info->exact) {
		if (!strcmp(refname, info->ref)) {
			deco_type = info_decoration;
			break;
	}

Then you can arrange the pseudoref class to use .membership function
perhaps like this:

	static int pseudoref_namespace_membership(
		const char *refname, const struct ref_namespace_info *info UNUSED
	)
	{
		return is_pseudoref(refname);
	}

and make them all into a single class.

What I called a bad design was to reuse the namespace_info code
without extending it to suit our needs.

This comment will probably affect everything below.

>>   [6/7] This is pretty straight-forward, assuming that the existing
>>         is_pseudoref_syntax() function does the right thing.  I am
>>         not sure about that, though.  A refname with '-' is allowed
>>         to be called a pseudoref???
>>         Also, not a fault of this patch, but the "_syntax" in its
>>         name is totally unnecessary, I would think.  At first glance,
>>         I suspected that the excuse to append _syntax may have been
>>         to signal the fact that the helper function does not check if
>>         there actually is such a ref, but examining a few helpers
>>         defined nearby tells us that such an excuse does not make
>>         sense:
>
> I've dropped the use of that function from the change, checking
> against the actual pseudoref names instead.
>
>>   [7/7] Allowing pseudorefs to optionally used when decorating might
>>         be a good idea, but I do not think it is particularly a good
>>         design decision to enable it by default.
>
> Okay!
>
>>         Each of them forming a separate "namespace" also looks like a
>>         poor design, as being able to group multiple things into one
>>         family and treat them the same way is the primary point of
>>         "namespace", I would think.
>
> Fair enough, although the array already contains HEAD and refs/stash
> as singletons.

But these deserve to be singletons, don't they?  There is no other
thing that behaves like HEAD; there is no other thing that behaves
like stash; and they do not behave like each other.

Having said that, I do not think it makes much sense to decorate a
commit off of refs/stash, as the true richeness of the stash is not
in its history but in its reflog, which the decoration code does not
dig into.  But obviously it is not a part of the topic we are
discussing (unless, of course, we are not "adding" new decoration
sources and colors, but we are improving the decoration sources and
colors by adding new useful ones while retiring existing useless
ones).

Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-22  0:13  6%   ` Junio C Hamano
@ 2023-10-22 21:49  0%     ` Andy Koppe
  2023-10-23  0:20  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Andy Koppe @ 2023-10-22 21:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On 22/10/2023 01:13, Junio C Hamano wrote:
> Andy Koppe <andy.koppe@gmail.com> writes:
>> This series is to replace the 'decorate: add color.decorate.symbols
>> config option' patch proposed at:
>> https://lore.kernel.org/git/20231003205442.22963-1-andy.koppe@gmail.com
> 
> If that is the case, it probably would have been nicer to mark the
> series as [PATCH v2].

Thanks, I wasn't sure about that due to the change in title and increase 
in scope. I shall err towards version-bumping in any future such cases.

> Also, can you make messages [1/7]..[7/7] replies to [0/7] when you
> send them out?  It seems that all 8 of them (including the cover
> letter) are replies to the previous round, which looked a bit
> unusual.

Not quite sure how that happened, but I think my mistake was passing 
--in-reply-to to git-format-patch instead of git-send-email.

>   [2/7] is a trivial readability improvement.  It obviously should be
>         left outside the scope of this series, but we should notice
>         the same pattern in similar color tables (e.g., wt-status.c
>         has one, diff.c has another) and perform the same clean-up as
>         a #leftoverbits item.

Okay, I've removed that commit in v2. (I should have mentioned in the 
commit message that it was triggered by the inconsistency with the 
immediately following color_decorate_slots array, which uses designated 
initializers.)

>   [4/7] The name of new member .include added to ref_namespace_info
>         will not be understood by anybody unless they are too deeply
>         obsessed by decoration mechansim.  As the namespace_info
>         covers far wider interest, so a name that *shouts* that it is
>         about decoration filter must be used to be understood by
>         readers of the code

Agreed.

>   [5/7] I am not sure if "other refs" should be an item in the
>         namespace_info array.  If it is truly "catch-all", then
>         shouldn't the refs in other namespaces without their own
>         decoration (e.g. ones in refs/notes/ and refs/prefetch/) be
>         colored in the same way as this new class?

They would, because add_ref_decoration() skips ref_namespace entries 
without a decoration type, so they would fall through to "refs/" and 
pick up the DECORATION_REF type.

>         And if so, having
>         it as an independent element that sits next to these other
>         classes smells like a strange design. >
>         Another more worrying thing is that existing .ref members are
>         designed to never overlap with each other, but this one
>         obviously does.  When a caller with a ref (or a pseudoref)
>         asks "which namespace does this one belong to", does the
>         existing code still do the right thing with this new element?
>         Without it, because there was no overlap, an implementation
>         can randomly search in the namespace_info table and stop at
>         the first hit, but now with the overlapping and widely open
>         .ref = "refs/", the implementation of the search must know
>         that it is a fallback position (i.e. if it found a match with
>         the fallback .ref = "refs/" , unless it looked at all other
>         entries that could begin with "refs/" and are more specific,
>         it needs to keep going).

Fair points. I've rewritten things to not touch the ref_namespace array.
>   [6/7] This is pretty straight-forward, assuming that the existing
>         is_pseudoref_syntax() function does the right thing.  I am
>         not sure about that, though.  A refname with '-' is allowed
>         to be called a pseudoref???
> 
>         Also, not a fault of this patch, but the "_syntax" in its
>         name is totally unnecessary, I would think.  At first glance,
>         I suspected that the excuse to append _syntax may have been
>         to signal the fact that the helper function does not check if
>         there actually is such a ref, but examining a few helpers
>         defined nearby tells us that such an excuse does not make
>         sense:

I've dropped the use of that function from the change, checking against 
the actual pseudoref names instead.

>   [7/7] Allowing pseudorefs to optionally used when decorating might
>         be a good idea, but I do not think it is particularly a good
>         design decision to enable it by default.

Okay!

>         Each of them forming a separate "namespace" also looks like a
>         poor design, as being able to group multiple things into one
>         family and treat them the same way is the primary point of
>         "namespace", I would think.

Fair enough, although the array already contains HEAD and refs/stash as 
singletons. I had vacillated about shoe-horning the pseudorefs in there, 
and was swayed by having a single place to define which (pseudo)refs 
should be included in decorations by default. That motivation goes away 
with all the pseudorefs off by default.

I've rewritten things to handle the pseudorefs separately from the 
ref_namespace array, with iteration functions similar to the ones used 
for HEAD and proper refs.

 >         You do not want to say "I want
 >         to decorate off of ORIG_HEAD and FETCH_HEAD"; instead you
 >         would want to say "I want to decorate off of any pseudoref".

They can now all be enabled with --clear-decorations or 
log.initialDecorationSet=all, or be controlled individually with the 
other filter options.

Thank you very much for the review!
Andy

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  @ 2023-10-22  0:13  6%   ` Junio C Hamano
  2023-10-22 21:49  0%     ` Andy Koppe
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-22  0:13 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git

Andy Koppe <andy.koppe@gmail.com> writes:

> This patch series adds three slots to the color.decorate.<slot> config
> option:
> - 'symbol' for coloring the punctuation symbols used around the refs in
>   decorations, which currently use the same color as the commit hash.
> - 'ref' for coloring refs other than branches, remote-tracking branches,
>   tags and the stash, which currently are not colored when included in
>   decorations through custom decoration filter options.
> - 'pseudoref' for coloring pseudorefs such as ORIG_HEAD or MERGE_HEAD.
>   Include them in decorations by default.
>
> This series is to replace the 'decorate: add color.decorate.symbols
> config option' patch proposed at:
> https://lore.kernel.org/git/20231003205442.22963-1-andy.koppe@gmail.com

If that is the case, it probably would have been nicer to mark the
series as [PATCH v2].

Also, can you make messages [1/7]..[7/7] replies to [0/7] when you
send them out?  It seems that all 8 of them (including the cover
letter) are replies to the previous round, which looked a bit
unusual.


As to the contents of the series:

 [1/7] nicely lays out the color documentation; I do not think the
       extra verbosity was absolutely needed for existing ones
       (e.g., when a reader sees 'tag', the reader knows the color
       will be applied to tags), but the more exotic ones the series
       will be adding may deserve extra explanation on what they
       are, so I guess it is OK.

 [2/7] is a trivial readability improvement.  It obviously should be
       left outside the scope of this series, but we should notice
       the same pattern in similar color tables (e.g., wt-status.c
       has one, diff.c has another) and perform the same clean-up as
       a #leftoverbits item.

 [3/7] They way _NIL color is used to control the defaulting looked
       a bit unusual, but clever way to use a non-constant color
       defined elsewhere as its default.  A similar trick is used in
       wt-status.c:color() for STATUS_ONBRANCH, so this is nothing
       new.

 [4/7] The name of new member .include added to ref_namespace_info
       will not be understood by anybody unless they are too deeply
       obsessed by decoration mechansim.  As the namespace_info
       covers far wider interest, so a name that *shouts* that it is
       about decoration filter must be used to be understood by
       readers of the code.

       To be quite honest, "decoration filter" is probably a name
       that will not be understood by anybody, but coming up with a
       better name for it is probably outside the scope of this
       series.

 [5/7] I am not sure if "other refs" should be an item in the
       namespace_info array.  If it is truly "catch-all", then
       shouldn't the refs in other namespaces without their own
       decoration (e.g. ones in refs/notes/ and refs/prefetch/) be
       colored in the same way as this new class?  And if so, having
       it as an independent element that sits next to these other
       classes smells like a strange design.

       Another more worrying thing is that existing .ref members are
       designed to never overlap with each other, but this one
       obviously does.  When a caller with a ref (or a pseudoref)
       asks "which namespace does this one belong to", does the
       existing code still do the right thing with this new element?
       Without it, because there was no overlap, an implementation
       can randomly search in the namespace_info table and stop at
       the first hit, but now with the overlapping and widely open
       .ref = "refs/", the implementation of the search must know
       that it is a fallback position (i.e. if it found a match with
       the fallback .ref = "refs/" , unless it looked at all other
       entries that could begin with "refs/" and are more specific,
       it needs to keep going).

 [6/7] This is pretty straight-forward, assuming that the existing
       is_pseudoref_syntax() function does the right thing.  I am
       not sure about that, though.  A refname with '-' is allowed
       to be called a pseudoref???

       Also, not a fault of this patch, but the "_syntax" in its
       name is totally unnecessary, I would think.  At first glance,
       I suspected that the excuse to append _syntax may have been
       to signal the fact that the helper function does not check if
       there actually is such a ref, but examining a few helpers
       defined nearby tells us that such an excuse does not make
       sense:

           int is_per_worktree_ref(const char *) {
		   return starts_with(refname, "refs/worktree/") ||
			  starts_with(refname, "refs/bisect/") ||
			  starts_with(refname, "refs/rewritten/");
	   }
           int is_pseudoref_syntax(const char *);
           int is_current_worktree_ref(const char *ref) {
                   return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
           }

       All these three work on the refname and based on what is in
       that refname string, decides what kind of ref it is.  There
       is nothing especially "syntax" about the second one, and we
       should rename it as part of #leftoverbits clean-up effort.

       Another unrelated tangent is that is_per_worktree_ref() shown
       above and the namespace_info array we saw earlier are not
       even aware of each other, which is maintenance nightmare
       waiting to happen.

 [7/7] Allowing pseudorefs to optionally used when decorating might
       be a good idea, but I do not think it is particularly a good
       design decision to enable it by default.  

       Each of them forming a separate "namespace" also looks like a
       poor design, as being able to group multiple things into one
       family and treat them the same way is the primary point of
       "namespace", I would think.  You do not want to say "I want
       to decorate off of ORIG_HEAD and FETCH_HEAD"; instead you
       would want to say "I want to decorate off of any pseudoref".



^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 3/3] rev-list: add commit object support in `--missing` option
  @ 2023-10-20 16:41  5%         ` Junio C Hamano
  2023-10-24 11:34  0%           ` Karthik Nayak
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-20 16:41 UTC (permalink / raw)
  To: Karthik Nayak; +Cc: git, ps

Junio C Hamano <gitster@pobox.com> writes:

> Rather, I was wondering if we need to use object flags to mark these
> objects, or can do what we want to do without using any object flags
> at all.  For the purpose of reporting "missing" objects, wouldn't it
> be sufficient to walk the object graph and report our findings as we
> go?  To avoid reporting the same object twice, as we reasonably can
> expect that the missing objects are minority (compared to the total
> number of objects), perhaps the codepath that makes such a report
> can use a hashmap of object_ids or something, for example.

Digging from the bottom,

 * builtin/rev-list.c:show_commit() gets "struct rev_list_info *"
   that has "struct rev_info *" [*].

 * list-objects.c:do_traverse() calls revision.c:get_revision() to
   obtain commits, some of which may be missing ones, and things
   behind get_revision() are responsible for marking the commit as
   missing.  It has "struct traversal_context *", among whose
   members is the "revs" member that is the "struct rev_info *".

 * revision.c:get_revision() and machinery behind it ultimately
   discovers a missing commit in the revision.c:process_parents()
   that loops over the parents commit_list.  It of course has access
   to "struct rev_info *".

So, presumably, if we add a new member to "struct rev_info" that
optionally [*] points at an oidset that records the object names of
missing objects we discovered so far (i.e., the set of missing
objects), the location we set the MISSING bit of a commit can
instead add the object name of the commit to the set.  And we can
export a function that takes "struct rev_info *" and "struct object
*" (or "struct object_id *") to check for membership in the "set of
missing objects", which would be used where we checked the MISSING
bit of a commit.

I do not know the performance implications of going this route, but
if we do not find a suitable vacant bit, we do not have to use any
object flags bit to do this, if we go this route, I would think.  I
may be missing some details that breaks the above outline, though.


[Footnotes]

 * A potential #leftoverbits tangent.

   Why is "rev_list_info" structure declared in <bisect.h>?  I
   suspect that this is a fallout from recent header file shuffling,
   but given who uses it (among which is rev-list:show_commit() that
   has very little to do with bisection and uses the information in
   rev_list_info when doing its normal non-bisect things), it does
   not make much sense.

 * When .do_not_die_on_missing_objects is false, it can and should
   be left NULL, but presumably we use the "do not die" bit even
   when we are not necessarily collecting the missing objects?  So
   the new member cannot replace the "do not die" bit completely.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v5 11/14] replay: use standard revision ranges
  @ 2023-10-19 19:49  6%     ` Linus Arver
  0 siblings, 0 replies; 200+ results
From: Linus Arver @ 2023-10-19 19:49 UTC (permalink / raw)
  To: Christian Couder, git
  Cc: Junio C Hamano, Patrick Steinhardt, Johannes Schindelin,
	Elijah Newren, John Cai, Derrick Stolee, Phillip Wood,
	Calvin Wan, Toon Claes, Dragan Simic, Christian Couder

This patch's documentation bits LGTM. The comments I have below are all
nits and I don't think they are enough to require a re-roll. If v5 is
accepted as-is, then this stuff could be #leftoverbits for a future
(minor) cleanup.

Thanks!

Christian Couder <christian.couder@gmail.com> writes:

> From: Elijah Newren <newren@gmail.com>
> 
> +DESCRIPTION
> +-----------
> +
> +Takes a range of commits and replays them onto a new location. Leaves
> +the working tree and the index untouched, and updates no
> +references.

Nit: in v4 you had

     Does
    +not touch the working tree or index, and does not update any
    +references. 

and the "does not update any references" sounds more natural than
"updates no references".

> The output of this command is meant to be used as input to
> +`git update-ref --stdin`, which would update the relevant branches
> +(see the OUTPUT section below).
> +
> +THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.

Nit: add "IN THE FUTURE" at the end.

> +EXAMPLES
> +--------
> +
> +To simply rebase `mybranch` onto `target`:

Nit: s/To simply rebase/Rebase

or, remove "simply" because it doesn't add much value.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 04/11] t: convert tests to not write references via the filesystem
  @ 2023-10-18 21:18  5%   ` Junio C Hamano
  2023-10-23 13:58  0%     ` Patrick Steinhardt
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-18 21:18 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Han-Wen Nienhuys

Patrick Steinhardt <ps@pks.im> writes:

> @@ -434,7 +432,7 @@ test_expect_success 'Query "main@{2005-05-28}" (past end of history)' '
>  	test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e
>  '
>  
> -rm -f .git/$m .git/logs/$m expect
> +git update-ref -d $m

We are not clearing "expect" file.  I do not know if it matters
here, but I am only recording what I noticed.

> diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
> index 10a539158c4..5cce24f1006 100755
> --- a/t/t1450-fsck.sh
> +++ b/t/t1450-fsck.sh
> @@ -115,15 +115,16 @@ test_expect_success 'zlib corrupt loose object output ' '
>  '
>  
>  test_expect_success 'branch pointing to non-commit' '
> -	git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
> +	tree_oid=$(git rev-parse --verify HEAD^{tree}) &&
> +	test-tool ref-store main update-ref msg refs/heads/invalid $tree_oid $ZERO_OID REF_SKIP_OID_VERIFICATION &&

I have mixed feelings on this.

In olden days, plumbing commands tended to allow to pass anything
the user told them to use, but in more recent versions of Git, we,
probably by mistake, managed to butcher some of the plumbing
commands to make them unable to deliberately "break" repositories,
one victim being "update-ref", i.e.

    $ git update-ref refs/heads/invalid HEAD^{tree}

is rejected these days (I just checked with v1.3.0 and it allows me
to do this), and that is one of the reasons why we manually broke
the repository in these tests.  We need to have a warning message in
comments near the implementation of "ref-store update-ref" that says
never ever attempt to share code with the production version of
update-ref---otherwise this (or the "safety" given to the plumbing
command, possibly by mistake) will be broken, depending on which
direction such a sharing goes.  On the other hand, forcing us to
keep two separate implementations, one deliberately loose to allow
us corrupt repositories, the other for production and actively used,
would mean the former one that is only used for validation would risk
bitrotting.

>  	test_when_finished "git update-ref -d refs/heads/invalid" &&

Not a problem this patch introduces, but I think it is a better
discipline to have when_finished clean-up routine prepared before we
do actual damage, i.e. if I were writing this test today from scratch,
I would expect it to be before "git rev-parse >.git/refs/heads/invalid"
is done.

>  	test_must_fail git fsck 2>out &&
>  	test_i18ngrep "not a commit" out
>  '

A #leftoverbit that is not relevant to the topic; we should clean
these test_i18ngrep and replace them with a plain "grep".

>  test_expect_success 'HEAD link pointing at a funny object' '
> -	test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
> -	mv .git/HEAD .git/SAVED_HEAD &&
> +	saved_head=$(git rev-parse --verify HEAD) &&
> +	test_when_finished "git update-ref HEAD ${saved_head}" &&
>  	echo $ZERO_OID >.git/HEAD &&

Are you sure .git/HEAD when this test is entered is a detached HEAD?
The title of the test says "HEAD link", and I take it to mean HEAD
is a symlink, and we save it away, while we create a loose ref that
points at 0{40} in a detached HEAD state.  Actually, the original
would also work if HEAD is detached on entry.  In either case,
moving SAVED_HEAD back to HEAD would restore the original state.

But the updated one only works if HEAD upon entry is already
detached.  Is this intended?

> @@ -131,8 +132,8 @@ test_expect_success 'HEAD link pointing at a funny object' '
>  '
>  
>  test_expect_success 'HEAD link pointing at a funny place' '
> -	test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
> -	mv .git/HEAD .git/SAVED_HEAD &&
> +	saved_head=$(git rev-parse --verify HEAD) &&
> +	test_when_finished "git update-ref --no-deref HEAD ${saved_head}" &&

Likewise.  Use of "update-ref" in the previous one vs "update-ref
--no-deref" in this one to recover from the damage the tests make
makes me feel that we may be assuming too much.

>  	echo "ref: refs/funny/place" >.git/HEAD &&

Even though "git symbolic-ref" refuses to point HEAD outside refs/,
as plumbing command should, it allows it to point it outside refs/heads/.
so this line should probably become

	git symbolic-ref HEAD refs/funny/place

in the same spirit as the rest of the series.

> @@ -391,7 +393,7 @@ test_expect_success 'tag pointing to nonexistent' '
>  
>  	tag=$(git hash-object -t tag -w --stdin <invalid-tag) &&
>  	test_when_finished "remove_object $tag" &&
> -	echo $tag >.git/refs/tags/invalid &&
> +	git update-ref refs/tags/invalid $tag &&

Good (not just this one, but similar ones throughout this patch).



^ permalink raw reply	[relevance 5%]

* Re: [PATCH 06/20] commit-graph: check consistency of fanout table
  @ 2023-10-11 14:45  6%   ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2023-10-11 14:45 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Mon, Oct 09, 2023 at 05:04:58PM -0400, Jeff King wrote:
> We use bsearch_hash() to look up items in the oid index of a
> commit-graph. It also has a fanout table to reduce the initial range in
> which we'll search. But since the fanout comes from the on-disk file, a
> corrupted or malicious file can cause us to look outside of the
> allocated index memory.

This is all very well written and explained. The patch LGTM.

> ---
> So I actually implemented the bsearch_hash() bounds checks and wrote
> tests for midx and idx files before realizing how they handle this. ;)
> Which makes sense, because the usual outcome for a corrupted idx file is
> for it to say "non-monotonic index", which I have seen lead to user
> confusion. Arguably we should have it say something about "hey, your idx
> file seems to be corrupted, because...". But that can be its own topic.

Yeah, I definitely agree that that is out of scope here, and can be left
as #leftoverbits.

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: How To Pick And Work On A Microproject
  2023-10-06  9:02  5%   ` Christian Couder
@ 2023-10-06 19:03  8%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-10-06 19:03 UTC (permalink / raw)
  To: Christian Couder; +Cc: git, Naomi Ibe, Kaartic Sivaraam

Christian Couder <christian.couder@gmail.com> writes:

> I am not sure how others feel about this, but I think it would be
> better in the future to not have to prepare such pages, and to just
> have a section with a number of examples of good microprojects on this
> https://git.github.io/General-Microproject-Information/ page. It will
> be easier to update this section when we know about other good ideas
> or better ideas, or when we want to remove an idea that we don't
> consider good anymore, or just update an idea.

If we have curated one-stop shop for microproject candidates to make
it easy to find them, it would be a vast improvement over the status
quo.  The easier for us to update the contents of the list, the
better for participants.  Having only one place that we need to look
at is one way to do so, and the general microproject information
page would be the best place to host it.  I like it.

>> Then it goes on to suggest finding a bug report, but I tend to think
>> that fixing them is way oversized to be a good microproject.
>
> I agree that it's oversized for most bugs. I have just added the
> following paragraph at the end of this "Searching for bug reports"
> subsection:
>
> "Also some bugs are difficult to understand and require too much or
> too difficult work for a microproject, so don’t spend too much time on
> them if it appears that they might not be simple to fix, and don’t
> hesitate to ask on the mailing list if they are a good microproject."

Would that be better, or would it be simpler to gut the whole
paragraph about bug reports?  This is "how to pick a microproject",
not "how to pick your main project to work on during your mentoring
program".

Unlike #leftoverbits that sometimes cover trivial but boring style
normalization and easy refactoring of code into helper functions, I
have never seen a bug report on the list that may make a good
microproject.  If we were to add a curated list of microproject idea
on the general microproject information page, it probably is better
to remove these mentions of bugreports and #leftoverbits, so that
readers will not get distracted.  "Don't hesitate to ask" so that
they may try to tackle more challenging one, if they wish, is a good
thing to say nevertheless.

Thanks.

^ permalink raw reply	[relevance 8%]

* Re: How To Pick And Work On A Microproject
  2023-10-05 22:42  6% ` Junio C Hamano
@ 2023-10-06  9:02  5%   ` Christian Couder
  2023-10-06 19:03  8%     ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Christian Couder @ 2023-10-06  9:02 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Naomi Ibe, Kaartic Sivaraam

On Fri, Oct 6, 2023 at 12:42 AM Junio C Hamano <gitster@pobox.com> wrote:
>
> Naomi Ibe <naomi.ibeh69@gmail.com> writes:
>
> > "Select a microproject and check that it has not yet been taken or
> > discussed by searching the mailing list. Public Inbox is your friend."
>
> Yeah, that is VERY unfriendly.  There is no mention on the pool of
> microproject ideas from which you can "select" here.  I wonder if
> some HTML link is missing in the sentence (i.e., clicking a word
> leading to a page that lists what you can select from), or it has
> always been like this.

This sentence has been like that for a long time. I have just improved
it to the following:

"* Select a microproject and check that it has not yet been taken or
  discussed by searching the mailing list. Please read all the
  sections below related to finding or selecting a microproject."

I have also made it clearer that the list these sentences are in is a
"Summary of the steps needed to complete a microproject" by adding a
section with that title.

> Later in the same document, I see
>
>     How to find other ideas for microprojects
>
>     First check the specific page(s) or information about Git
>     microprojects related to your program that should have been
>     published on this site or on the GSoC or Outreachy site. But then
>     still read on everything below!
>
> which is much more realistic, as long as the "specific page(s)" are
> well curated (which I have no idea myself, as I have never been in
> the mentoring pool).  Naomi, have you checked and found such a page
> on Outreachy site?

There is no such page as I haven't taken the time to write one. But I
have added the following paragraph just below the above one:

"It’s also possible that we haven’t taken the time to put up a page
listing microprojects ideas for your program. The pages we used to
create for that were named “XXXX Applicant Microprojects” where XXXX
is the program name and a date, for example “SoC 2016 Applicant
Microprojects” for the GSoC in 2016, or “Outreachy Winter 2021-2022
Applicant Microprojects” for Outreachy in 2021-2022. See the following
directory to find these old pages that might still be useful:

https://git.github.io/Historical-SoC-Outreachy/"

I am not sure how others feel about this, but I think it would be
better in the future to not have to prepare such pages, and to just
have a section with a number of examples of good microprojects on this
https://git.github.io/General-Microproject-Information/ page. It will
be easier to update this section when we know about other good ideas
or better ideas, or when we want to remove an idea that we don't
consider good anymore, or just update an idea.

> Then it goes on to suggest finding a bug report, but I tend to think
> that fixing them is way oversized to be a good microproject.

I agree that it's oversized for most bugs. I have just added the
following paragraph at the end of this "Searching for bug reports"
subsection:

"Also some bugs are difficult to understand and require too much or
too difficult work for a microproject, so don’t spend too much time on
them if it appears that they might not be simple to fix, and don’t
hesitate to ask on the mailing list if they are a good microproject."

> And finally it gives a casual mention of good+first+issue, which is
> probably the closest to what _should_ be listed as the first place
> to try (sorry, I however do not know how well the list is curated,
> either, but from a cursory look it looks legit).
>
> https://github.com/gitgitgadget/git/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
>
> There also is a mention of #leftoverbits in the document, but by its
> nature, they can easily become stale or irrelevant, and they tend to
> be more real issues, and I would expect them to be unnecessarily
> harder than what dip-your-toe-in-the-water-and-say-hello
> microprojects need to be.

I have just added the following at the end of the subsection about
#leftoverbits:

"As for bugs, and many things really, you can also ask if you are not
sure it's simple enough to fix."

Thanks for reviewing the doc!

^ permalink raw reply	[relevance 5%]

* Re: How To Pick And Work On A Microproject
  @ 2023-10-05 22:42  6% ` Junio C Hamano
  2023-10-06  9:02  5%   ` Christian Couder
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-10-05 22:42 UTC (permalink / raw)
  To: Christian Couder; +Cc: git, Naomi Ibe

Naomi Ibe <naomi.ibeh69@gmail.com> writes:

> "Select a microproject and check that it has not yet been taken or
> discussed by searching the mailing list. Public Inbox is your friend."

Yeah, that is VERY unfriendly.  There is no mention on the pool of
microproject ideas from which you can "select" here.  I wonder if
some HTML link is missing in the sentence (i.e., clicking a word
leading to a page that lists what you can select from), or it has
always been like this.

Later in the same document, I see

    How to find other ideas for microprojects

    First check the specific page(s) or information about Git
    microprojects related to your program that should have been
    published on this site or on the GSoC or Outreachy site. But then
    still read on everything below!

which is much more realistic, as long as the "specific page(s)" are
well curated (which I have no idea myself, as I have never been in
the mentoring pool).  Naomi, have you checked and found such a page
on Outreachy site?

Then it goes on to suggest finding a bug report, but I tend to think
that fixing them is way oversized to be a good microproject.


And finally it gives a casual mention of good+first+issue, which is
probably the closest to what _should_ be listed as the first place
to try (sorry, I however do not know how well the list is curated,
either, but from a cursory look it looks legit).

https://github.com/gitgitgadget/git/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22

There also is a mention of #leftoverbits in the document, but by its
nature, they can easily become stale or irrelevant, and they tend to
be more real issues, and I would expect them to be unnecessarily
harder than what dip-your-toe-in-the-water-and-say-hello
microprojects need to be.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 08/10] commit-graph: free write-context entries before overwriting
  @ 2023-10-05 17:51  6%   ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2023-10-05 17:51 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Tue, Oct 03, 2023 at 04:30:55PM -0400, Jeff King wrote:
> diff --git a/commit-graph.c b/commit-graph.c
> index 4aa2f294f1..744b7eb1a3 100644
> --- a/commit-graph.c
> +++ b/commit-graph.c
> @@ -2065,9 +2065,11 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
>  			free(graph_name);
>  		}
>
> +		free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
>  		ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1] = xstrdup(hash_to_hex(file_hash));
>  		final_graph_name = get_split_graph_filename(ctx->odb,
>  					ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 1]);
> +		free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1]);
>  		ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 1] = final_graph_name;
>
>  		result = rename(ctx->graph_name, final_graph_name);

This hunk makes sense. It might be nice in the future to do something
like:

--- 8< ---
diff --git a/commit-graph.c b/commit-graph.c
index 5e8a3a5085..cadccbe276 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -59,7 +59,7 @@ void git_test_write_commit_graph_or_die(void)

 #define GRAPH_EXTRA_EDGES_NEEDED 0x80000000
 #define GRAPH_EDGE_LAST_MASK 0x7fffffff
-#define GRAPH_PARENT_NONE 0x70000000
+tdefine GRAPH_PARENT_NONE 0x70000000

 #define GRAPH_LAST_EDGE 0x80000000

@@ -1033,11 +1033,11 @@ struct write_commit_graph_context {
 	uint64_t progress_cnt;

 	char *base_graph_name;
-	int num_commit_graphs_before;
-	int num_commit_graphs_after;
-	char **commit_graph_filenames_before;
-	char **commit_graph_filenames_after;
-	char **commit_graph_hash_after;
+	struct {
+		size_t nr;
+		char **fname;
+		char **hash;
+	} graphs_before, graphs_after;
 	uint32_t new_num_commits_in_base;
 	struct commit_graph *new_base_graph;
--- >8 ---

...making the corresponding changes throughout the rest of the file. But
that is definitely out of scope here, and could easily be left for
another day.

#leftoverbits

Thanks,
Taylor

^ permalink raw reply related	[relevance 6%]

* Re: [PATCH 2/2] builtin/repack.c: implement support for `--cruft-max-size`
  @ 2023-10-02 20:30  5%     ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2023-10-02 20:30 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: git, Junio C Hamano, Jeff King, Jonathan Tan

On Fri, Sep 08, 2023 at 01:21:44PM +0200, Patrick Steinhardt wrote:
> On Thu, Sep 07, 2023 at 05:52:04PM -0400, Taylor Blau wrote:
> [snip]
> > @@ -125,17 +133,39 @@ static void mark_packs_for_deletion_1(struct string_list *names,
> >  		if (len < hexsz)
> >  			continue;
> >  		sha1 = item->string + len - hexsz;
> > -		/*
> > -		 * Mark this pack for deletion, which ensures that this
> > -		 * pack won't be included in a MIDX (if `--write-midx`
> > -		 * was given) and that we will actually delete this pack
> > -		 * (if `-d` was given).
> > -		 */
> > -		if (!string_list_has_string(names, sha1))
> > -			item->util = (void*)1;
> > +
> > +		if (pack_is_retained(item)) {
> > +			item->util = NULL;
> > +		} else if (!string_list_has_string(names, sha1)) {
> > +			/*
> > +			 * Mark this pack for deletion, which ensures
> > +			 * that this pack won't be included in a MIDX
> > +			 * (if `--write-midx` was given) and that we
> > +			 * will actually delete this pack (if `-d` was
> > +			 * given).
> > +			 */
> > +			item->util = DELETE_PACK;
> > +		}
>
> I find the behaviour of this function a tad surprising as it doesn't
> only mark a pack for deletion, but it also marks a pack as not being
> retained anymore. Shouldn't we rather:
>
>     if (pack_is_retained(item)) {
>         // Theoretically speaking we shouldn't even do this bit here as
>         // we _un_mark the pack for deletion. But at least we shouldn't
>         // be removing the `RETAIN_PACK` bit, I'd think.
>         item->util &= ~DELETE_PACK;
>     } else if (!string_list_has_string(names, sha1)) {
>         // And here we shouldn't discard the `RETAIN_PACK` bit either.
>         item->util |= DELETE_PACK;
>     }

I think the new version should address these issues. But yeah, I
definitely understand your confusion here. I think what's written in
this patch is OK, because we check only whether the `->util` field is
non-NULL before deleting, which is why we have to remove the RETAINED
bit.

But the new version looks like this instead:

    if (pack_is_retained(item))
        pack_unmark_for_deletion(item);
    else if (!string_list_has_string(names, sha1))
        pack_mark_for_deletion(item);

the RETAINED bits still stick around (pack_unmark_for_deletion() just
does `item->util &= ~DELETE_PACK`), but we don't consult them after
mark_packs_for_deletion_1() has finished executing. Instead we just
check for the existence of the DELETE_PACK bit, rather than whether or
not the whole util field is NULL.

> > @@ -799,6 +831,72 @@ static void remove_redundant_bitmaps(struct string_list *include,
> >  	strbuf_release(&path);
> >  }
> >
> > +static int existing_cruft_pack_cmp(const void *va, const void *vb)
> > +{
> > +	struct packed_git *a = *(struct packed_git **)va;
> > +	struct packed_git *b = *(struct packed_git **)vb;
> > +
> > +	if (a->pack_size < b->pack_size)
> > +		return -1;
> > +	if (a->pack_size > b->pack_size)
> > +		return 1;
> > +	return 0;
> > +}
> > +
> > +static void collapse_small_cruft_packs(FILE *in, unsigned long max_size,
>
> We might want to use `size_t` to denote file sizes instead of `unsigned
> long`.

We can safely change these to use size_t, but let's leave OPT_MAGNITUDE
alone (and treat that portion as #leftoverbits).

> > +		p = existing_cruft[i];
> > +		proposed = st_add(total_size, p->pack_size);
> > +
> > +		if (proposed <= max_size) {
> > +			total_size = proposed;
> > +			fprintf(in, "-%s\n", pack_basename(p));
> > +		} else {
> > +			retain_cruft_pack(existing, p);
> > +			fprintf(in, "%s\n", pack_basename(p));
> > +		}
>
> It's a bit funny that we re-check whether we have exceeded the maximum
> size in subsequente iterations once we hit the limit, but it arguably
> makes the logic a bit simpler.

Yeah. Those checks are all noops (IOW, once we end up in the else
branch, we'll stay there for the rest of the loop). But we don't want to
break early, because we have to call retain_cruft_pack() on everything.
In theory you could do something like:

    for (i = 0; i < existing_cruft_nr; i++) {
        size_t proposed;
        p = existing_cruft[i];
        proposed = st_add(total_size, p->pack_size);

        if (proposed <= max_size) {
            total_size = proposed;
            fprintf(in, "-%s\n", pack_basename(p));
        } else {
            break;
        }
    }

    for (; i < existing_cruft_nr; i++) {
        retain_cruft_pack(existing, existing_cruft[i]);
        fprintf(in, "%s\n", pack_basename(existing_cruft[i]));
    }

But I think that the above is slightly more error-prone than what is
written in the original patch. I have only the vaguest of preferences
towards the former, but I'm happy to change it around if you feel
strongly.

> If I understand correctly, we only collapse small cruft packs in case
> we're not expiring any objects at the same time. Is there an inherent
> reason why? I would imagine that it can indeed be useful to expire
> objects contained in cruft packs and then have git-repack(1) recombine
> whatever is left into larger packs.
>
> If the reason is basically "it's complicated" then that is fine with me,
> we can still implement the functionality at a later point in time. But
> until then I think that we should let callers know that the two options
> are incompatible with each other by producing an error when both are
> passed.

Your understanding is correct. We could try to leave existing cruft
packs alone when none of their objects are removed as a result of
pruning, but that case should be relatively rare. Another thing you
could do is handle cruft packs which have only part of their objects
being pruned by combining the non-pruned parts into a new pack.

The latter should be mostly straightforward to implement, but since
we're often ending up with very few cruft objects post-pruning, it
likely wouldn't help much.

Thanks,
Taylor

^ permalink raw reply	[relevance 5%]

* [TOPIC 11/12] Improving new contributor on-boarding
  @ 2023-10-02 15:22  4% ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2023-10-02 15:22 UTC (permalink / raw)
  To: git

(Presenter: Jonathan Nieder, Notetaker: Xing Huang, Ronald Bhuleskar)

* (Jonathan Nieder) Not as structured of a conversation, but I see a lot of
  interest, let's see how the conversation goes. Any open sourced project can be
  scary for newcomers; the git project in particular has its unique aspects of
  its workflow, such as the mailing list that rejects http formatted mails, etc.
  I think overall we are welcoming. Ideally, we would like to attract all types
  of contributors, in part because they help different kinds of users have more
  of a voice.
* I am interested in how to make the onboarding process easier for the new
  contributors; what do we see to make things easier? MyFirstContribution works
  well as a tutorial doc, what is the next step for someone after they send
  their first patch and get their first review in reply? How do you find a
  mentor? Things like how to interpret the reviewer's tone can be hard to
  navigate.
* (Emily) We can mark a patcher as a beginner's patch - the golang (?) project,
  for example, assigns a mentor to newcomers. We have a mentorship list that's
  inactive; could we use the same volunteers from there to give more hands-on
  mentoring?
* (Jonathan Tan) We could use a guideline on what's expected in terms of code
  quality.
* (Taylor) Folks who are newer contributors or haven't contributed much, do you
  have perspectives to share?
   * (Vincenzo) Finding a starting point, a problem to tackle, was difficult.
   * #leftoverbits search term is listed in our
     Documentation/ReviewingGuidelines.txt, but Taylor suspects no new comers
     are looking into it.
   * People in the project will start looking at the next event and get to meet
     the person face to face to have a less daunting relationship.
   * (Phillip) There is a lot of information for  new contributors to digest in
     CodingGuidelines, SubmittingPatches and MyFirstContribution. How do we find
     a balance between providing useful guidelines and overwhelming them?
   * (Jacob Stopak) As a newcomer, sent an idea that was too big to solve
     completely myself, but I would have liked to know where it was going, what
     is my part, what others will help with, and to be able to participate more
     in its implementation instead of it being done by others.
* (Jonathan Nieder) The mailing list is noisy and someone interested in a
  specific topic but the mailing list is flooded with lot of other things,
  unless they are specifically cc-ed on the right things. There's no easy middle
  ground between "my life is in the list" and "I only see what is sent to me".
* (Jakub) There's a bit of a middle ground - you can use a newsreader
* (Jonathan) In a project with a bug tracker, it's easier to know who is
j assigned to and who the collaborators are on something and what to expect
  moving forward. The information is in one place. In the Git project, if
  someone sends a patch on something I'm interested in, I have to interpret why
  they're doing that - do they want to take this over? Are they giving me a
  suggestion?
* (Han Young) Han finds contributor guide to be lacking in details, he finds
  READMEs and discord to be complementary to his newcomer experience.
* (Emily) Which of these ideas should be implemented that makes the most sense?
   * Auto assign 1:1 mentors to new contributors
   * Split up the doc a bit more
   * Wiki: Where to start
   * Have more conferences
   * Have a bug tracker
   * Process documentation: What to do when a review comes in, next steps beyond
     what MyFirstContribution describes.
* (Taylor) The mentor assignment bit is what excites me the most
   * Most new contributors use GitGitGadget, it could notice new contributors
     and find a mentor for them
   * The key there would be documenting what that relationship should look like.
     Helps with clear guidelines on avoiding the kind of hijacking case Jacob
     mentioned (sorry about that!)
* (Jonathan Nieder) Great thing to do if we have a pool of mentors available.
  This cultiire is appreciated.
   * (Emily) Such culture is ingrained in Google in the form of community
     contribution. (Junio) Hmm, where are the reviewers? :)
* (Glen) Discord or other informal channels are easier for mini-mentoring.
* (Jeff Hosteler) GitGitGadget is also doing mini-mentoring recently at a small
  scale that polishes before the author submits.
   * (Emily) Mostly GitHubbers? Should others pitch in?
   * (Jeff Hostetler) I think I'm auto-subscribed because I have write access to
     the repo.
   * (Junio) I've done some reviews there (it shouldn't be limited to GitHub
     folks).
* (Jacob) Thanks much for the documentation, step-by-step instructions are great
   * I used instructions on how to send patches with "git send-email". I didn't
     use GitGitGadget because it wasn't clear to me what it is.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH 1/4] merge-ort: drop custom err() function
  2023-09-16  2:54  5%   ` Elijah Newren
@ 2023-09-16  5:50  0%     ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2023-09-16  5:50 UTC (permalink / raw)
  To: Elijah Newren; +Cc: git

On Fri, Sep 15, 2023 at 07:54:28PM -0700, Elijah Newren wrote:

> Oops, when I simplified the err() function copied from
> merge-recursive.c in one way, I failed to notice that it enabled
> further simplifications.

Ah, I didn't even realize that it had been copied from there. That makes
a lot more sense now.

> >   2. It formats the error string into a strbuf, prepending "error: ",
> >      and then feeds the result into error(). But this is wrong! The
> >      error() function already adds the prefix, so we end up with:
> >
> >         error: error: Failed to execute internal merge
> 
> ...and the same problem can be found in merge-recursive.c's err() function.
> 
> Not sure what current opinions on whether we should bother fixing
> those up.  I do intend on nuking merge-recursive.c, but I obviously
> haven't had much Git time this year.

Hmm, I'm not sure that it does. It has this code:

          if (opt->buffer_output < 2)
                  flush_output(opt);
          else {
                  strbuf_complete(&opt->obuf, '\n');
                  strbuf_addstr(&opt->obuf, "error: ");
          }

so we only add the extra "error:" tag when we are in a buffering mode
that writes into the strbuf (indicated by a high buffer_output field).

And then later, after formatting the new string into opt->obuf, we do
this:

          if (opt->buffer_output > 1)
                  strbuf_addch(&opt->obuf, '\n');
          else {
                  error("%s", opt->obuf.buf);
                  strbuf_reset(&opt->obuf);
          }

So we call error() iff buffer is low, in which case we would not have
added the prefix earlier. And that makes sense. If we are collecting
messages in obuf, we cannot use error(), and we have to handle the
prefix ourselves.

So I think it's correct? If you started with merge-recursive's err() and
then stripped it down to remove the extra buffering stuff, I can see
that it would be a natural error to accidentally leave in the extra
prefix while doing so.

I certainly find the code confusing (the split "< 2" and "> 1"
conditions to trigger related cases is a nice obfuscation bonus), but I
_think_ it's right. And if the end goal is to ditch merge-recursive.c, I
don't think it's worth spending any more brain power on it.

> > A few of these messages starts with capital letters, which is unlike our
> > usual error message style. I didn't clean that up here. We could do so
> > on top,
> 
> There are two of these.  In my defense, they were copied verbatim from
> merge-recursive.c.  And I, um, never noticed the problem over there
> before copying.  Or after.

That makes sense. We have a ton of these lurking in the code base. I
usually try to clean them up when I touch relevant lines, but I wasn't
sure about the path_msg thing here.

> Yeah, all callers of err()/error() are for things that should never
> happen regardless of repository contents and should result in an
> instant abort, whereas anything calling path_msg() is a conflict or
> informational message that is expected for various kinds of repository
> data -- these messages are accumulated and later shown.

That makes sense in general. And I think most of these err() calls are
of that form (in fact, I'd expect most corruption to just trigger a
die() at a low level anyway, but we've been slowly lib-ifying that
away).

The one that gave me pause was my "the external merge driver gave us a
failure" case that I used for testing. In theory we could say "oops,
your merge driver is broken" and keep going. But I think it's not just
"broken", but "oops, your merge driver died with a signal", since a
non-zero exit just means conflicts. So at that point probably something
really has gone terribly wrong (not necessarily with Git, but with your
merge driver!).

> Another distinction is that any call to path_msg() is associated to a
> very specific path (or a few specific paths in special cases like
> renames or add/add with conflict modes), whereas none of the calls to
> err()/error() have a specific path they are about.  This serves a few
> purposes:

I think some of them are about specific paths. We hit err() if
merge_3way() returns -1, but that call can of course also result in a
regular conflict.

But if they're catastrophic errors anyway (as above), this part is kind
of moot.

> Anyway, long story short is that I think continuing to use error()
> instead of path_msg() or something else makes sense here.  The capital
> to lowercase cleanups make sense; we could even #leftoverbits for that
> piece.

Sounds good. I'll post a patch in a second, just to take care of it
while we're thinking about it.

-Peff

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 1/4] merge-ort: drop custom err() function
  @ 2023-09-16  2:54  5%   ` Elijah Newren
  2023-09-16  5:50  0%     ` Jeff King
  0 siblings, 1 reply; 200+ results
From: Elijah Newren @ 2023-09-16  2:54 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Thu, Sep 14, 2023 at 2:39 AM Jeff King <peff@peff.net> wrote:
>
> The merge-ort code has an err() function, but it's really just error()
> in disguise. It differs in two ways:
>
>   1. It takes a "struct merge_options" argument. But the function
>      completely ignores it! We can simply remove it.

Oops, when I simplified the err() function copied from
merge-recursive.c in one way, I failed to notice that it enabled
further simplifications.

>   2. It formats the error string into a strbuf, prepending "error: ",
>      and then feeds the result into error(). But this is wrong! The
>      error() function already adds the prefix, so we end up with:
>
>         error: error: Failed to execute internal merge

...and the same problem can be found in merge-recursive.c's err() function.

Not sure what current opinions on whether we should bother fixing
those up.  I do intend on nuking merge-recursive.c, but I obviously
haven't had much Git time this year.

> So let's just drop this function entirely and call error() directly, as
> the functions are otherwise identical (note that they both always return
> -1).
>
> Presumably nobody noticed the bogus messages because they are quite hard
> to trigger (they are mostly internal errors reading and writing
> objects). However, one easy trigger is a custom merge driver which dies
> by signal; we have a test already here, but we were not checking the
> contents of stderr.

Thanks for catching this.

> Signed-off-by: Jeff King <peff@peff.net>
> ---
> A few of these messages starts with capital letters, which is unlike our
> usual error message style. I didn't clean that up here. We could do so
> on top,

There are two of these.  In my defense, they were copied verbatim from
merge-recursive.c.  And I, um, never noticed the problem over there
before copying.  Or after.

> but I actually wonder if some of these ought to be using
> path_msg() and continuing instead, to give output closer to other
> conflict or error cases (e.g., conflicts caused by missing submodule
> objects). But I dunno. I guess these are all more clearly "woah,
> something is totally wrong" that we do not expect to happen, so it
> probably isn't a big deal to just abort.

Yeah, all callers of err()/error() are for things that should never
happen regardless of repository contents and should result in an
instant abort, whereas anything calling path_msg() is a conflict or
informational message that is expected for various kinds of repository
data -- these messages are accumulated and later shown.

Another distinction is that any call to path_msg() is associated to a
very specific path (or a few specific paths in special cases like
renames or add/add with conflict modes), whereas none of the calls to
err()/error() have a specific path they are about.  This serves a few
purposes:
  * We've had reports before that users get confused when there are
multiple conflict messages about a path and they do not occur
together.  The structure of the merge machinery is such that it often
has to process conflicts by type and then by path, rather than by path
and then by type.  If a merge has many conflicts, processing by type
and then by path, combined with printing as you go, naturally results
in cases where there are multiple conflict type messages for a single
path, but the messages are separated by dozens or hundreds of lines of
conflict messages about other paths.  By accumulating and printing
later, at print time we can sort based on path and provide nicer
output (though renames and such might still cause some separation of
related messages).
  * Accumulating and printing conflict & informational messages later
is also more friendly for use by other tools such as merge-tree or
rebase that may want to only conditionally print the messages or even
operate on the structured data (the specific paths and conflict types
recorded with them) in some special way.  Dscho and I talked about
that for his webby-merge-ui-for-github tool he was working on.

Anyway, long story short is that I think continuing to use error()
instead of path_msg() or something else makes sense here.  The capital
to lowercase cleanups make sense; we could even #leftoverbits for that
piece.


>  merge-ort.c           | 28 +++++-----------------------
>  t/t6406-merge-attr.sh |  3 ++-
>  2 files changed, 7 insertions(+), 24 deletions(-)
>
> diff --git a/merge-ort.c b/merge-ort.c
> index 8631c99700..027ecc7f78 100644
> --- a/merge-ort.c
> +++ b/merge-ort.c
> @@ -721,23 +721,6 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
>         renames->callback_data_nr = renames->callback_data_alloc = 0;
>  }
>
> -__attribute__((format (printf, 2, 3)))
> -static int err(struct merge_options *opt, const char *err, ...)
> -{
> -       va_list params;
> -       struct strbuf sb = STRBUF_INIT;
> -
> -       strbuf_addstr(&sb, "error: ");
> -       va_start(params, err);
> -       strbuf_vaddf(&sb, err, params);
> -       va_end(params);
> -
> -       error("%s", sb.buf);
> -       strbuf_release(&sb);
> -
> -       return -1;
> -}
> -
>  static void format_commit(struct strbuf *sb,
>                           int indent,
>                           struct repository *repo,
> @@ -2122,13 +2105,12 @@ static int handle_content_merge(struct merge_options *opt,
>                                           &result_buf);
>
>                 if ((merge_status < 0) || !result_buf.ptr)
> -                       ret = err(opt, _("Failed to execute internal merge"));
> +                       ret = error(_("Failed to execute internal merge"));
>
>                 if (!ret &&
>                     write_object_file(result_buf.ptr, result_buf.size,
>                                       OBJ_BLOB, &result->oid))
> -                       ret = err(opt, _("Unable to add %s to database"),
> -                                 path);
> +                       ret = error(_("Unable to add %s to database"), path);
>
>                 free(result_buf.ptr);
>                 if (ret)
> @@ -3518,10 +3500,10 @@ static int read_oid_strbuf(struct merge_options *opt,
>         unsigned long size;
>         buf = repo_read_object_file(the_repository, oid, &type, &size);
>         if (!buf)
> -               return err(opt, _("cannot read object %s"), oid_to_hex(oid));
> +               return error(_("cannot read object %s"), oid_to_hex(oid));
>         if (type != OBJ_BLOB) {
>                 free(buf);
> -               return err(opt, _("object %s is not a blob"), oid_to_hex(oid));
> +               return error(_("object %s is not a blob"), oid_to_hex(oid));
>         }
>         strbuf_attach(dst, buf, size, size + 1);
>         return 0;
> @@ -4973,7 +4955,7 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
>                  * TRANSLATORS: The %s arguments are: 1) tree hash of a merge
>                  * base, and 2-3) the trees for the two trees we're merging.
>                  */
> -               err(opt, _("collecting merge info failed for trees %s, %s, %s"),
> +               error(_("collecting merge info failed for trees %s, %s, %s"),
>                     oid_to_hex(&merge_base->object.oid),
>                     oid_to_hex(&side1->object.oid),
>                     oid_to_hex(&side2->object.oid));
> diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
> index 9677180a5b..05ad13b23e 100755
> --- a/t/t6406-merge-attr.sh
> +++ b/t/t6406-merge-attr.sh
> @@ -179,7 +179,8 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal'
>
>         >./please-abort &&
>         echo "* merge=custom" >.gitattributes &&
> -       test_must_fail git merge main &&
> +       test_must_fail git merge main 2>err &&
> +       grep "^error: Failed to execute internal merge" err &&
>         git ls-files -u >output &&
>         git diff --name-only HEAD >>output &&
>         test_must_be_empty output
> --
> 2.42.0.628.g8a27295885

Thanks for fixing this up.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH] diff --stat: add config option to limit filename width
  2023-09-12 17:11  6%     ` Junio C Hamano
@ 2023-09-12 17:48  0%       ` Dragan Simic
  0 siblings, 0 replies; 200+ results
From: Dragan Simic @ 2023-09-12 17:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On 2023-09-12 19:11, Junio C Hamano wrote:
> Dragan Simic <dsimic@manjaro.org> writes:
> 
>>> Someday, as a follow-up after the dust from this topic settles, we
>>> would probably want to look at how these rev.diffopt.* members are
>>> initialized and refactor the common code out to a helper.  It would
>>> allow us to instead of doing this ...
>> 
>> Another good point.  If you agree, I'd prefer to have my patch
>> accepted and merged as-is, ...
> 
> That is exactly what I meant by "follow-up after the dust settles".
> 
> All of the "we should probably do this and that in the future" are
> called #leftoverbits comments.  Food for thought, something people
> can use to find inspiration for areas they may want to work on, that
> has no impact to how "complete" the current patch being discussed
> is.

Sounds great, thank you.  I already have a couple of code cleanups to 
work on, which I'll do in the following days and send the patches.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] diff --stat: add config option to limit filename width
  @ 2023-09-12 17:11  6%     ` Junio C Hamano
  2023-09-12 17:48  0%       ` Dragan Simic
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-09-12 17:11 UTC (permalink / raw)
  To: Dragan Simic; +Cc: git

Dragan Simic <dsimic@manjaro.org> writes:

>> Someday, as a follow-up after the dust from this topic settles, we
>> would probably want to look at how these rev.diffopt.* members are
>> initialized and refactor the common code out to a helper.  It would
>> allow us to instead of doing this ...
>
> Another good point.  If you agree, I'd prefer to have my patch
> accepted and merged as-is, ...

That is exactly what I meant by "follow-up after the dust settles".

All of the "we should probably do this and that in the future" are
called #leftoverbits comments.  Food for thought, something people
can use to find inspiration for areas they may want to work on, that
has no impact to how "complete" the current patch being discussed
is.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 2/3] update-index: add --show-index-version
  @ 2023-09-12  5:54  5%   ` Linus Arver
  0 siblings, 0 replies; 200+ results
From: Linus Arver @ 2023-09-12  5:54 UTC (permalink / raw)
  To: Junio C Hamano, git

Junio C Hamano <gitster@pobox.com> writes:

> "git update-index --version N" is used to set the index format

s/--version/--index-version

> version to a specific version, but there was no way to query the
> current version used in the on-disk index file.
>
> Teach the command a new "--show-index-version" option, and also
> teach the "--index-version N" option to report what the version was
> when run with the "--verbose" option.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  Documentation/git-update-index.txt |  6 +++++-
>  builtin/update-index.c             | 19 +++++++++++++------
>  t/t2107-update-index-basic.sh      | 16 ++++++++++++++++
>  3 files changed, 34 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
> index a367f8d65a..3f204891ce 100644
> --- a/Documentation/git-update-index.txt
> +++ b/Documentation/git-update-index.txt
> @@ -162,7 +162,8 @@ you will need to handle the situation manually.
>  	Write the resulting index out in the named on-disk format version.
>  	Supported versions are 2, 3 and 4. The current default version is 2
>  	or 3, depending on whether extra features are used, such as
> -	`git add -N`.
> +	`git add -N`.  With `--verbose` option, also reports the

How about

    `git add -N`.  With `--verbose`, also report the

> +	version the index file uses before and after this command.
>  +
>  Version 4 performs a simple pathname compression that reduces index
>  size by 30%-50% on large repositories, which results in faster load
> @@ -171,6 +172,9 @@ and support for it was added to libgit2 in 2016 and to JGit in 2020.
>  Older editions of this manual page called it "relatively young", but
>  it should be considered mature technology these days.
>
> +--show-index-version::
> +	Report the index format version used by the on-disk index file.
> +	See `--index-version` above.

Looks good.

>  -z::
>  	Only meaningful with `--stdin` or `--index-info`; paths are
> diff --git a/builtin/update-index.c b/builtin/update-index.c
> index 5fab9ad2ec..e713e2a04c 100644
> --- a/builtin/update-index.c
> +++ b/builtin/update-index.c
> @@ -1089,6 +1089,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
>  			resolve_undo_clear_callback),
>  		OPT_INTEGER(0, "index-version", &preferred_index_format,
>  			N_("write index in this format")),
> +		OPT_SET_INT(0, "show-index-version", &preferred_index_format,
> +			    N_("show index format version"), -1),

How about

    "show on-disk index format version"

for the help text? Also "report" may be preferable instead of "show" for
consistency with the manpage.

Also, I think it would be easier to read if we didn't overload
preferred_index_format here and instead used a new variable (perhaps named
"show_index_format").

And I just realized that we are now using not only "show" and "report"
interchangeably in this patch, but also "format" and "version" ---
it would be nice to clean up as #leftoverbits.

>  		OPT_BOOL(0, "split-index", &split_index,
>  			N_("enable or disable split index")),
>  		OPT_BOOL(0, "untracked-cache", &untracked_cache,
> @@ -1181,15 +1183,20 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
>
>  	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
>  	if (preferred_index_format) {
> -		if (preferred_index_format < INDEX_FORMAT_LB ||
> -		    INDEX_FORMAT_UB < preferred_index_format)
> +		if (preferred_index_format < 0) {
> +			printf(_("%d\n"), the_index.version);
> +		} else if (preferred_index_format < INDEX_FORMAT_LB ||
> +			   INDEX_FORMAT_UB < preferred_index_format) {
>  			die("index-version %d not in range: %d..%d",
>  			    preferred_index_format,
>  			    INDEX_FORMAT_LB, INDEX_FORMAT_UB);
> -
> -		if (the_index.version != preferred_index_format)
> -			the_index.cache_changed |= SOMETHING_CHANGED;
> -		the_index.version = preferred_index_format;
> +		} else {
> +			if (the_index.version != preferred_index_format)
> +				the_index.cache_changed |= SOMETHING_CHANGED;
> +			report(_("index-version: was %d, set to %d"),
> +			       the_index.version, preferred_index_format);
> +			the_index.version = preferred_index_format;
> +		}
>  	}

Looks good. But if you decide to use a new variable like
"show_index_format" as suggested above, you might want to refactor this
out to a separate function. Then you could obviously do away with the
chained if/else and replace them with early returns, which would be
easier to read.

>  	if (read_from_stdin) {
> diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
> index 89b285fa3a..c78d1e9396 100755
> --- a/t/t2107-update-index-basic.sh
> +++ b/t/t2107-update-index-basic.sh
> @@ -111,4 +111,20 @@ test_expect_success '--chmod=+x and chmod=-x in the same argument list' '
>  	test_cmp expect actual
>  '
>
> +test_expect_success '--index-version' '
> +	git commit --allow-empty -m snap &&
> +	git reset --hard &&

Not sure why this "git reset --hard" is needed here --- is it to clear
out state from previous test cases? If so, perhaps it's better to run
this as the very first command in this test case?

But this also makes me wonder why "git commit --allow-empty -m snap" is
even necessary (if we already have a git repo)?

> +	git update-index --index-version 2 >actual &&
> +	test_must_be_empty actual &&

Before we do "--index-version 2", it may be desirable to run the
"--show-index-version" flag first to see what we have before modifying
it with "2".

> +	git update-index --show-index-version >actual &&
> +	echo 2 >expect &&
> +	test_cmp expect actual &&
> +
> +	git update-index --index-version 4 --verbose >actual &&
> +	echo "index-version: was 2, set to 4" >expect &&
> +	test_cmp expect actual
> +'

How about adding this check below to check what happens if the newly-set
version is the same as the existing version?

        git update-index --index-version 4 --verbose >actual &&
        echo "index-version: was 4, set to 4" >expect &&
        test_cmp expect actual

And also how about a similar check, but for downgrading from a higher
version number to a lower one?

        git update-index --index-version 2 --verbose >actual &&
        echo "index-version: was 4, set to 2" >expect &&
        test_cmp expect actual

> +
>  test_done
> --
> 2.42.0-rc2-7-gf9972720e9

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v2 05/10] parse-options: prefer opt->value to globals in callbacks
  2023-09-02  7:34  6%   ` René Scharfe
@ 2023-09-05  6:52  0%     ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2023-09-05  6:52 UTC (permalink / raw)
  To: René Scharfe; +Cc: git, Junio C Hamano

On Sat, Sep 02, 2023 at 09:34:32AM +0200, René Scharfe wrote:

> >  static int option_parse_if_missing(const struct option *opt,
> >  				   const char *arg, int unset)
> >  {
> > -	return trailer_set_if_missing(&if_missing, arg);
> > +	return trailer_set_if_missing(opt->value, arg);
> >  }
> 
> Not your fault, but these all silently exit if "arg" contains an
> unrecognized value.  Reporting the error would be better.

Hmm, yeah. On the config side, git_trailer_default_config() issues a
warning after the functions return -1. I'd have guessed we at least
printed a usage message or something here, but we don't even do that.
You get a silent 129 exit code.

Gross, but it's something I think we should fix separately, as it's
orthogonal to this series.

> >  static void new_trailers_clear(struct list_head *trailers)
> > @@ -97,11 +97,11 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
> >  		OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
> >  		OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
> >
> > -		OPT_CALLBACK(0, "where", NULL, N_("action"),
> > +		OPT_CALLBACK(0, "where", &where, N_("action"),
> >  			     N_("where to place the new trailer"), option_parse_where),
> > -		OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
> > +		OPT_CALLBACK(0, "if-exists", &if_exists, N_("action"),
> >  			     N_("action if trailer already exists"), option_parse_if_exists),
> > -		OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
> > +		OPT_CALLBACK(0, "if-missing", &if_missing, N_("action"),
> >  			     N_("action if trailer is missing"), option_parse_if_missing),
> 
> And I wonder if "action" should be replaced by "(after|before|end|start)",
> "(addIfDifferent|addIfDifferentNeighbor|add|replace|doNothing)" and
> "(doNothing|add)", respectively.  Gets a bit long in the middle, but would
> be more helpful.  #leftoverbits

I don't have a strong opinion. It is sometimes nice to provide more
detail to save the user having to look it up separately. But sometimes
those details can be overwhelming and make it hard to read, especially
if they grow over time. I'm thinking less of "-h" output and more of
people like to put:

  git foo [--optionA|--optionB|--optionC]

and so on, until eventually the options block is like 4 lines long. Just
saying [options] and then listing them is more friendly. I'm not sure if
we're approaching that kind of problem here or not.

-Peff

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 05/10] parse-options: prefer opt->value to globals in callbacks
  @ 2023-09-02  7:34  6%   ` René Scharfe
  2023-09-05  6:52  0%     ` Jeff King
  0 siblings, 1 reply; 200+ results
From: René Scharfe @ 2023-09-02  7:34 UTC (permalink / raw)
  To: Jeff King, git; +Cc: Junio C Hamano

Am 31.08.23 um 23:21 schrieb Jeff King:
> We have several parse-options callbacks that ignore their "opt"
> parameters entirely. This is a little unusual, as we'd normally put the
> result of the parsing into opt->value. In the case of these callbacks,
> though, they directly manipulate global variables instead (and in
> most cases the caller sets opt->value to NULL in the OPT_CALLBACK
> declaration).
>
> The immediate symptom we'd like to deal with is that the unused "opt"
> variables trigger -Wunused-parameter. But how to fix that is debatable.
> One option is to annotate them with UNUSED. But another is to have the
> caller pass in the appropriate variable via opt->value, and use it. That
> has the benefit of making the callbacks reusable (in theory at least),
> and makes it clear from the OPT_CALLBACK declaration which variables
> will be affected (doubly so for the cases in builtin/fast-export.c,
> where we do set opt->value, but it is completely ignored!).

Which allows turning global variables into local ones later, so unlocks
more cleanup potential.

> The slight downside is that we lose type safety, since they're now
> passing through void pointers.
>
> I went with the "just use them" approach here. The loss of type safety
> is unfortunate, but that is already an issue with most of the other
> callbacks. If we want to try to address that, we should do so more
> consistently (and this patch would prepare these callbacks for whatever
> we choose to do there).

Makes sense.  The types used below look OK to me.

> Note that in the cases in builtin/fast-export.c, we are passing
> anonymous enums. We'll have to give them names so that we can declare
> the appropriate pointer type within the callbacks.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
>  builtin/checkout-index.c     |  8 +++++---
>  builtin/describe.c           |  6 ++++--
>  builtin/fast-export.c        | 36 +++++++++++++++++++++---------------
>  builtin/fetch.c              |  4 ++--
>  builtin/interpret-trailers.c | 12 ++++++------
>  builtin/pack-objects.c       | 21 ++++++++++++---------
>  6 files changed, 50 insertions(+), 37 deletions(-)
>
> diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
> index 6687a495ff..6ef6ac4c2e 100644
> --- a/builtin/checkout-index.c
> +++ b/builtin/checkout-index.c
> @@ -193,14 +193,16 @@ static const char * const builtin_checkout_index_usage[] = {
>  static int option_parse_stage(const struct option *opt,
>  			      const char *arg, int unset)
>  {
> +	int *stage = opt->value;
> +
>  	BUG_ON_OPT_NEG(unset);
>
>  	if (!strcmp(arg, "all")) {
> -		checkout_stage = CHECKOUT_ALL;
> +		*stage = CHECKOUT_ALL;
>  	} else {
>  		int ch = arg[0];
>  		if ('1' <= ch && ch <= '3')
> -			checkout_stage = arg[0] - '0';
> +			*stage = arg[0] - '0';
>  		else
>  			die(_("stage should be between 1 and 3 or all"));
>  	}
> @@ -238,7 +240,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
>  			N_("write the content to temporary files")),
>  		OPT_STRING(0, "prefix", &state.base_dir, N_("string"),
>  			N_("when creating files, prepend <string>")),
> -		OPT_CALLBACK_F(0, "stage", NULL, "(1|2|3|all)",
> +		OPT_CALLBACK_F(0, "stage", &checkout_stage, "(1|2|3|all)",
>  			N_("copy out the files from named stage"),
>  			PARSE_OPT_NONEG, option_parse_stage),
>  		OPT_END()
> diff --git a/builtin/describe.c b/builtin/describe.c
> index b28a4a1f82..718b5c3073 100644
> --- a/builtin/describe.c
> +++ b/builtin/describe.c
> @@ -561,9 +561,11 @@ static void describe(const char *arg, int last_one)
>  static int option_parse_exact_match(const struct option *opt, const char *arg,
>  				    int unset)
>  {
> +	int *val = opt->value;
> +
>  	BUG_ON_OPT_ARG(arg);
>
> -	max_candidates = unset ? DEFAULT_CANDIDATES : 0;
> +	*val = unset ? DEFAULT_CANDIDATES : 0;
>  	return 0;
>  }
>
> @@ -578,7 +580,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "long",       &longformat, N_("always use long format")),
>  		OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")),
>  		OPT__ABBREV(&abbrev),
> -		OPT_CALLBACK_F(0, "exact-match", NULL, NULL,
> +		OPT_CALLBACK_F(0, "exact-match", &max_candidates, NULL,
>  			       N_("only output exact matches"),
>  			       PARSE_OPT_NOARG, option_parse_exact_match),
>  		OPT_INTEGER(0, "candidates", &max_candidates,
> diff --git a/builtin/fast-export.c b/builtin/fast-export.c
> index 56dc69fac1..70aff515ac 100644
> --- a/builtin/fast-export.c
> +++ b/builtin/fast-export.c
> @@ -33,9 +33,9 @@ static const char *fast_export_usage[] = {
>  };
>
>  static int progress;
> -static enum { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT;
> -static enum { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT;
> -static enum { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT;
> +static enum signed_tag_mode { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT;
> +static enum tag_of_filtered_mode { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT;
> +static enum reencode_mode { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT;
>  static int fake_missing_tagger;
>  static int use_done_feature;
>  static int no_data;
> @@ -53,16 +53,18 @@ static struct revision_sources revision_sources;
>  static int parse_opt_signed_tag_mode(const struct option *opt,
>  				     const char *arg, int unset)
>  {
> +	enum signed_tag_mode *val = opt->value;
> +
>  	if (unset || !strcmp(arg, "abort"))
> -		signed_tag_mode = SIGNED_TAG_ABORT;
> +		*val = SIGNED_TAG_ABORT;
>  	else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
> -		signed_tag_mode = VERBATIM;
> +		*val = VERBATIM;
>  	else if (!strcmp(arg, "warn"))
> -		signed_tag_mode = WARN;
> +		*val = WARN;
>  	else if (!strcmp(arg, "warn-strip"))
> -		signed_tag_mode = WARN_STRIP;
> +		*val = WARN_STRIP;
>  	else if (!strcmp(arg, "strip"))
> -		signed_tag_mode = STRIP;
> +		*val = STRIP;
>  	else
>  		return error("Unknown signed-tags mode: %s", arg);
>  	return 0;
> @@ -71,12 +73,14 @@ static int parse_opt_signed_tag_mode(const struct option *opt,
>  static int parse_opt_tag_of_filtered_mode(const struct option *opt,
>  					  const char *arg, int unset)
>  {
> +	enum tag_of_filtered_mode *val = opt->value;
> +
>  	if (unset || !strcmp(arg, "abort"))
> -		tag_of_filtered_mode = TAG_FILTERING_ABORT;
> +		*val = TAG_FILTERING_ABORT;
>  	else if (!strcmp(arg, "drop"))
> -		tag_of_filtered_mode = DROP;
> +		*val = DROP;
>  	else if (!strcmp(arg, "rewrite"))
> -		tag_of_filtered_mode = REWRITE;
> +		*val = REWRITE;
>  	else
>  		return error("Unknown tag-of-filtered mode: %s", arg);
>  	return 0;
> @@ -85,21 +89,23 @@ static int parse_opt_tag_of_filtered_mode(const struct option *opt,
>  static int parse_opt_reencode_mode(const struct option *opt,
>  				   const char *arg, int unset)
>  {
> +	enum reencode_mode *val = opt->value;
> +
>  	if (unset) {
> -		reencode_mode = REENCODE_ABORT;
> +		*val = REENCODE_ABORT;
>  		return 0;
>  	}
>
>  	switch (git_parse_maybe_bool(arg)) {
>  	case 0:
> -		reencode_mode = REENCODE_NO;
> +		*val = REENCODE_NO;
>  		break;
>  	case 1:
> -		reencode_mode = REENCODE_YES;
> +		*val = REENCODE_YES;
>  		break;
>  	default:
>  		if (!strcasecmp(arg, "abort"))
> -			reencode_mode = REENCODE_ABORT;
> +			*val = REENCODE_ABORT;
>  		else
>  			return error("Unknown reencoding mode: %s", arg);
>  	}
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index 8f93529505..fd134ba74d 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -176,7 +176,7 @@ static int parse_refmap_arg(const struct option *opt, const char *arg, int unset
>  	 * "git fetch --refmap='' origin foo"
>  	 * can be used to tell the command not to store anywhere
>  	 */
> -	refspec_append(&refmap, arg);
> +	refspec_append(opt->value, arg);
>
>  	return 0;
>  }
> @@ -2204,7 +2204,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
>  			   PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules),
>  		OPT_BOOL(0, "update-shallow", &update_shallow,
>  			 N_("accept refs that update .git/shallow")),
> -		OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"),
> +		OPT_CALLBACK_F(0, "refmap", &refmap, N_("refmap"),
>  			       N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
>  		OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
>  		OPT_IPVERSION(&family),
> diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
> index c5e8345265..6aadce6a1e 100644
> --- a/builtin/interpret-trailers.c
> +++ b/builtin/interpret-trailers.c
> @@ -26,19 +26,19 @@ static enum trailer_if_missing if_missing;
>  static int option_parse_where(const struct option *opt,
>  			      const char *arg, int unset)
>  {
> -	return trailer_set_where(&where, arg);
> +	return trailer_set_where(opt->value, arg);
>  }
>
>  static int option_parse_if_exists(const struct option *opt,
>  				  const char *arg, int unset)
>  {
> -	return trailer_set_if_exists(&if_exists, arg);
> +	return trailer_set_if_exists(opt->value, arg);
>  }
>
>  static int option_parse_if_missing(const struct option *opt,
>  				   const char *arg, int unset)
>  {
> -	return trailer_set_if_missing(&if_missing, arg);
> +	return trailer_set_if_missing(opt->value, arg);
>  }

Not your fault, but these all silently exit if "arg" contains an
unrecognized value.  Reporting the error would be better.

>  static void new_trailers_clear(struct list_head *trailers)
> @@ -97,11 +97,11 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
>  		OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
>
> -		OPT_CALLBACK(0, "where", NULL, N_("action"),
> +		OPT_CALLBACK(0, "where", &where, N_("action"),
>  			     N_("where to place the new trailer"), option_parse_where),
> -		OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
> +		OPT_CALLBACK(0, "if-exists", &if_exists, N_("action"),
>  			     N_("action if trailer already exists"), option_parse_if_exists),
> -		OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
> +		OPT_CALLBACK(0, "if-missing", &if_missing, N_("action"),
>  			     N_("action if trailer is missing"), option_parse_if_missing),

And I wonder if "action" should be replaced by "(after|before|end|start)",
"(addIfDifferent|addIfDifferentNeighbor|add|replace|doNothing)" and
"(doNothing|add)", respectively.  Gets a bit long in the middle, but would
be more helpful.  #leftoverbits

>  		OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
> diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> index d2a162d528..492372ee5d 100644
> --- a/builtin/pack-objects.c
> +++ b/builtin/pack-objects.c
> @@ -4120,29 +4120,32 @@ static void add_extra_kept_packs(const struct string_list *names)
>  static int option_parse_quiet(const struct option *opt, const char *arg,
>  			      int unset)
>  {
> +	int *val = opt->value;
> +
>  	BUG_ON_OPT_ARG(arg);
>
>  	if (!unset)
> -		progress = 0;
> -	else if (!progress)
> -		progress = 1;
> +		*val = 0;
> +	else if (!*val)
> +		*val = 1;
>  	return 0;
>  }
>
>  static int option_parse_index_version(const struct option *opt,
>  				      const char *arg, int unset)
>  {
> +	struct pack_idx_option *popts = opt->value;
>  	char *c;
>  	const char *val = arg;
>
>  	BUG_ON_OPT_NEG(unset);
>
> -	pack_idx_opts.version = strtoul(val, &c, 10);
> -	if (pack_idx_opts.version > 2)
> +	popts->version = strtoul(val, &c, 10);
> +	if (popts->version > 2)
>  		die(_("unsupported index version %s"), val);
>  	if (*c == ',' && c[1])
> -		pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
> -	if (*c || pack_idx_opts.off32_limit & 0x80000000)
> +		popts->off32_limit = strtoul(c+1, &c, 0);
> +	if (*c || popts->off32_limit & 0x80000000)
>  		die(_("bad index version '%s'"), val);
>  	return 0;
>  }
> @@ -4190,7 +4193,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
>  		LIST_OBJECTS_FILTER_INIT;
>
>  	struct option pack_objects_options[] = {
> -		OPT_CALLBACK_F('q', "quiet", NULL, NULL,
> +		OPT_CALLBACK_F('q', "quiet", &progress, NULL,
>  			       N_("do not show progress meter"),
>  			       PARSE_OPT_NOARG, option_parse_quiet),
>  		OPT_SET_INT(0, "progress", &progress,
> @@ -4200,7 +4203,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "all-progress-implied",
>  			 &all_progress_implied,
>  			 N_("similar to --all-progress when progress meter is shown")),
> -		OPT_CALLBACK_F(0, "index-version", NULL, N_("<version>[,<offset>]"),
> +		OPT_CALLBACK_F(0, "index-version", &pack_idx_opts, N_("<version>[,<offset>]"),
>  		  N_("write the pack index file in the specified idx format version"),
>  		  PARSE_OPT_NONEG, option_parse_index_version),
>  		OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] .github/workflows: add coverity action
  @ 2023-08-29  8:18  2% ` Johannes Schindelin
  0 siblings, 0 replies; 200+ results
From: Johannes Schindelin @ 2023-08-29  8:18 UTC (permalink / raw)
  To: Taylor Blau; +Cc: git, Junio C Hamano, Jeff King

Hi Taylor,

On Mon, 21 Aug 2023, Taylor Blau wrote:

> diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
> new file mode 100644
> index 0000000000..26b9145d9e
> --- /dev/null
> +++ b/.github/workflows/coverity.yml
> @@ -0,0 +1,35 @@
> +name: Coverity
> +
> +on:
> +  push:
> +    branches:
> +      - master
> +    tags:
> +      - '*'

I would consider it too late to do a Coverity analysis when the version
is already tagged. Therefore, I would like to see this `tags: *' part go.

And I agree with Peff that we should activate this build for `next`, too.
And for good measure for `maint` (and maybe `maint-*`, although those
branches are typically not pushed to `git/git`).

> +
> +jobs:
> +  coverity:
> +    runs-on: ubuntu-latest
> +    env:
> +      HAVE_COVERITY_TOKEN: ${{ secrets.COVERITY_SCAN_EMAIL != '' && secrets.COVERITY_SCAN_TOKEN != '' }}
> +    steps:
> +      - id: check-coverity
> +        name: check whether Coverity token is configured
> +        run: |
> +          echo "enabled=$HAVE_COVERITY_TOKEN" >>$GITHUB_OUTPUT

The canonical output for a step that has no other outputs is called
`result`. That output name is handled by linters such as
https://rhysd.github.io/actionlint/, too, in contrast to outputs with
different names that may be set in a free-form `run:` step that is
impossible to parse by `actionlint`.

But I see a bigger problem: Contrary to what the commit message claims,
the design makes this workflow far from a no-op: There will always be the
need for a VM to be spun up, to receive the orchestration script, to
download the necessary Actions (in this instance,
`vapier/coverity-scan-action`), only to check environment variables, see
that actually nothing needs to be done, update the job's and the run's
status (claiming "success" even if nothing was sent to Coverity) and then
shut down.

We discussed this in the past, as it is a great waste of resources (even
if other people pay for it, it still costs money [*1*] and electricity),
and for some of us even more relevant: it is a great waste of time because
when you are already waiting for 20 queued jobs to be picked up, having to
wait for the next build agent to become available only to spend, I don't
know, half a minute (wall clock time)? on getting this workflow run
queued, the next build agent to become available, the job to be set up,
the first step to be run, the others to be skipped, and then to wrap it
all up by updating the run as completed. I would not fault anyone for
being frustrated with this.

Therefore, I would strongly suggest looking for alternative ways to skip
this workflow run, before applying this patch.

I see these viable alternatives, all pulling the `if:` directive from the
step level to the job level, just like the `l10n.yml` workflow does [*2*],
to avoid even starting the job unless really needed:

- Limit it to the primary repository, `git/git`:

	if: github.event.repository.fork == false

  This is what Git for Windows does in the build that validates the
  revision to use in the `git-for-windows/setup-git-for-windows-sdk`
  Action that is used in Git's CI runs to build and test Git on Windows:
  https://github.com/git-for-windows/git-sdk-64/blob/894191270a78/.github/workflows/ci-artifacts.yml#L14

  While this still clutters the list of workflow runs with plenty of
  skipped runs (see https://github.com/git/git/actions/workflows/l10n.yml
  for an example how this looks), at least it avoids wasting a build agent
  on essentially only checking for the presence of two secrets.

  Developers wishing to run this workflow in their fork could always
  create a branch, edit the workflow to remove this `if:` directive, and
  push the branch to their fork.

- Limit it to `git/git` explicitly, by name:

	if: github.event.repository.owner.login == 'git'

  This is how we run the `vs-build`/`vs-test` combo only in the
  `git-for-windows` fork:
  https://github.com/git/git/blob/v2.42.0/.github/workflows/main.yml#L150

  The advantage here is that it would be slightly more obvious what we are
  doing here than checking `fork == false`, as the org name is mentioned
  explicitly.

- Limit it to `git/git` but also allow it to be triggered manually:

	if: github.event.repository.fork == false || github.event_name == 'workflow_dispatch'

  This is what Git for Windows does in the test verifying that it works in
  the "Nano Server" container image that allows for kind of a minimal
  Windows system to be run via Docker:
  https://github.com/git-for-windows/git-sdk-64/blob/894191270a78/.github/workflows/nano-server.yml#L7

  The advantage of allowing the workflow to be triggered via a
  `workflow_dispatch` is that developers wishing to run this workflow in
  their fork would not need to edit the GitHub workflow but could run it
  unmodified. For details, see
  https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow

- Limit it by repository "topics" (think: "repository tags"):

	if: contains(github.event.repository.topics, 'has-coverity-secrets')

  On GitHub, every repository can be annotated with "topics", i.e. a list
  of labels (which in other scenarios would be called "tags"). These
  topics can be seen by the GitHub workflow run, _before_ even starting a
  job, via the `github.event.repository` attribute.

  This is how InnoSetup does it:
  https://github.com/jrsoftware/issrc/blob/main/.github/workflows/build.yml#L12
  The primary repository does not have the secrets required to run this
  workflow, and hence does not have the "has-issrc-build-env" topic as
  can be seen here: https://github.com/jrsoftware/issrc (look below the
  "About" section on the right side, where you see the topics "installer"
  and "inno-setup"). My personal fork does have them secrets, and the
  topic "has-issrc-build-env" says as much: https://github.com/dscho/issrc

  The advantage of this solution is that it is very easy to "turn on and
  off" the workflow on a repository level, simply by adding or removing
  the "has-coverity-secrets" topic. See:
  https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/classifying-your-repository-with-topics

  The downside is that this method is somewhat unintuitive and needs the
  developer to read documentation (*shudder*) to know what they need to
  do.

I have no strong preference as long as the job is skipped whenever the
Coverity build (read: the `coverity` GitHub workflow run) should be
skipped.

> +      - uses: actions/checkout@v3
> +        if: steps.check-coverity.outputs.enabled == 'true'
> +      - run: ci/install-dependencies.sh
> +        env:
> +          CC: gcc
> +          CC_PACKAGE: gcc-9
> +          jobname: linux-gcc-default

How about modifying `ci/install-dependencies.sh` to introduce a new job
name, `coverity`, that is handled like `linux-gcc-default`? I.e. something
like this:

-- snip --
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 107757a1fea..e6a894e507d 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -74,7 +74,7 @@ Documentation)
 	test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
 	sudo gem install --version 1.5.8 asciidoctor
 	;;
-linux-gcc-default)
+linux-gcc-default|coverity)
 	sudo apt-get -q update
 	sudo apt-get -q -y install $UBUNTU_COMMON_PKGS
 	;;
diff --git a/ci/lib.sh b/ci/lib.sh
index 1b0cc2b57db..7a196aa0d17 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -227,7 +227,7 @@ export SKIP_DASHED_BUILT_INS=YesPlease

 case "$runs_on_pool" in
 ubuntu-latest)
-	if test "$jobname" = "linux-gcc-default"
+	if test "$jobname" = "linux-gcc-default" ||  test "$jobname" = "coverity"
 	then
 		break
 	fi
-- snap --

That would be a lot cleaner and would also allow for Coverity-specific
things in this step that won't affect `linux-gcc-default` at the same
time.

> +          runs_on_pool: ubuntu-latest
> +        if: steps.check-coverity.outputs.enabled == 'true'
> +      - uses: vapier/coverity-scan-action@v1

In contrast to the other Actions we use in Git, this one is neither
provided by GitHub nor by the Git (or Git for Windows) project [*3*].

The recommended way to handle such third-party Actions is to pin them by
full length commit SHA:
https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions

This is particularly important because we're passing secret values to that
Action.

> +        if: steps.check-coverity.outputs.enabled == 'true'
> +        with:
> +          email: ${{ secrets.COVERITY_SCAN_EMAIL }}
> +          token: ${{ secrets.COVERITY_SCAN_TOKEN }}
> +          command: make -j8
> +

The commit message would make for a fine place to describe the role of
these `COVERITY_SCAN_*` secrets, how to obtain them, and how to configure
them (i.e. providing a link to
https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository).

The reason I am suggesting that is that many a time, I have authored
commits like this one, only to puzzle about the exact steps to configure
the the thing properly when I needed it six months later, and regretting
dearly not having had the foresight to help my future self while writing
the commit message.

Another important issue that should be discussed in the commit message is
the matter of Coverity's false positives. I regularly dread going through
the new reports in Coverity (I am doing this for git-for-windows) because
of the many falsely pointed out "buffer overruns" when working e.g. with
`strvec` where Coverity assumes that its `empty_strvec` is ever written
to.

In Git for Windows, I have not had any luck with suppressing these false
reports. For what it's worth, this is the "model file" I am currently
using:

-- snip --
/* modelfile for git */

char strbuf_slopbuf[64];

void *malloc(size_t);
void *calloc(size_t, size_t);
void *realloc(void *, size_t);
void free(void *);

void *xrealloc(void *ptr, size_t size)
{
	void *ret = realloc(ptr, size);
	if (!ret) __coverity_panic__();
	return ret;
}

void *xmalloc(size_t size)
{
	void *mem = malloc(size);
	if (!mem) __coverity_panic__();
	return mem;
}

void xcalloc(size_t num, size_t size)
{
	void *ret = calloc(num, size);
	if (!ret)  __coverity_panic__();
	return ret;
}

void usage(const char *err) {
  __coverity_panic__();
}

void usagef(const char *err, ...) {
  __coverity_panic__();
}

void die(const char *err, ...)  {
  __coverity_panic__();
}

void die_errno(const char *err, ...) {
  __coverity_panic__();
}

void BUG_fl(const char *file, int line, const char *fmt, ...) {
  __coverity_panic__();
}

struct strbuf {
	size_t alloc;
	size_t len;
	char *buf;
};

void strbuf_setlen(struct strbuf *sb, size_t len)
{
        sb->len = len;
	sb->buf[len] = '\0';
}

void strbuf_grow(struct strbuf *sb, size_t amount);

void *memcpy(void *dest, const void *src, size_t n);

void strbuf_add(struct strbuf *sb, const void *data, size_t len)
{
	strbuf_grow(sb, len);
	memcpy(sb->buf + sb->len, data, len);
	sb->len = len;
	sb->buf[len] = '\0';
}

void *memmove(void *dest, const void *src, size_t n);

void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
				   const void *data, size_t dlen)
{
	if (pos > sb->len)
		die("`pos' is too far after the end of the buffer");
	if (pos + len > sb->len)
		die("`pos + len' is too far after the end of the buffer");

	if (dlen >= len)
		strbuf_grow(sb, dlen - len);
	memmove(sb->buf + pos + dlen,
			sb->buf + pos + len,
			sb->len - pos - len);
	memcpy(sb->buf + pos, data, dlen);
	sb->len = sb->len + dlen - len;
	sb->buf[sb->len + dlen - len] = '\0';
}
-- snap --

It is getting a bit ridiculous at this point, the size of it and the
meager benefit it reaps. But it is better than nothing, I guess.

The reason I would really like to see an extensive discussion about this
in the commit message is that this place would be _the_ most logical
habitat for such a description, to help developers who want to set up
their own Coverity coverage (either in their own Git fork, or even in a
separate project) trying to learn from the Git project.

Ciao,
Johannes

Footnote *1*: In case it was unclear: Build agents are essentially virtual
machines. Those virtual machines are destroyed after every run, and
recreated to a pristine state before picking up the next job. To avoid
having to wait for a virtual machine to be created whenever a job needs to
be run, there is a pool of virtual machines ready to run. There have been
times when we ran so many jobs in the Git project that we drained that
pool and had to wait, painfully, for the virtual machines to be created
which, let me tell you, is not a matter of a mere couple of seconds.

This complexity is reflected in the pricing you can see at
https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions

Just to put things into perspective: In our security work, we have to run
our GitHub workflow in a private repository, where GitHub Actions are not
provided free of cost by GitHub. We have a very nice donation from GitHub
in the form of 50,000 build minutes we can use every month. If we spent
all of those minutes running on Linux (i.e. the cheapest option), GitHub
would essentially donate $400 to us. That's what we usually spend in a
matter of days preparing for security releases: The workflow run to
validate v2.39.3, for example, while taking "only" 36 minutes and 1 second
wall clock time, used up over 12 hours of those 50,000 build minutes, and
every time we iterated, we pushed 11 branches and 11 tags. Three
iterations in, we were out of build minutes.

All this is to say: We, the Git project, are not exactly cautious when it
comes to spending GitHub Actions build minutes. I really would love to see
us all to become a lot more mindful on this matter.

Footnote *2*:
https://github.com/git/git/blob/v2.42.0/.github/workflows/l10n.yml#L13

Footnote *3*: We do already use a third-party Action in `l10n.yml`:
`mshick/add-pr-comment@v1`. As you can verify easily, this is not pinned
by full length commit SHA. But then, this step only gets the
`GITHUB_TOKEN` secret, which only has the permission to write to the Pull
Request (i.e. add a comment), not to write to the repository.

Still, we will probably want to pin that Action at some stage, better safe
'n sorry. #leftoverbits

^ permalink raw reply related	[relevance 2%]

* Re: [Leftoverbits] exit code clean-up?
  2023-08-17  5:36  7%       ` Jeff King
@ 2023-08-17 16:03  8%         ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-08-17 16:03 UTC (permalink / raw)
  To: Jeff King; +Cc: git

Jeff King <peff@peff.net> writes:

> We _could_ document "128 means something really unexpected happened and
> we called die() deep in the code". But even that seems misleading to me,
> as we also die() for everyday shallow things (like "the name you gave is
> not valid"). The value really means very little in practice, and the
> biggest reason not to change it is that we know it doesn't conflict with
> any codes that programs _do_ promise are meaningful (like "1" from "diff
> --exit-code").

Yeah, I forgot to say that we should mention 128 to tell the users
that it is a meaningless positive number chosen to signal a general
error and it is set sufficiently high so that it won't conflict with
a range of low positive numbers certain subcommands use to convey
specific meaning in their errors.  And you said it nicely above.

With that clarified, my vote still goes to the "do not overly tied
to what the current implementation happens to do" route.

Thanks.

^ permalink raw reply	[relevance 8%]

* Re: [Leftoverbits] exit code clean-up?
  2023-08-16 17:04  6%     ` [Leftoverbits] exit code clean-up? Junio C Hamano
  2023-08-17  5:36  7%       ` Jeff King
@ 2023-08-17  9:24  8%       ` Oswald Buddenhagen
  1 sibling, 0 replies; 200+ results
From: Oswald Buddenhagen @ 2023-08-17  9:24 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Wed, Aug 16, 2023 at 10:04:28AM -0700, Junio C Hamano wrote:
>"git help git" does not have "EXIT CODES" section, and it is assumed 
>that the "common sense" of older generation [...] that exiting with 0 
>is success and non-zero is failure is shared among its users, which 
>might not be warranted these days.
>
well, that's actually a standard (exit(3) has things to say about it), 
and given how shell scripts treat exit codes, there is no wiggle room 
here. just about every shell intro tutorial explains it.

>We could either
>
> * Be more prescriptive and add "EXIT CODES" section to each and
>   every document to describe how we fail in the current code.
>
>or
>
> * Describe "In general, 0 is success, non-zero is failure, but some
>   commands may signal more than that with its non-zero exit codes"
>   in "git help git", and add "EXIT CODES" section to the manual
>   page of the commands whose exit codes matter (there are a
>   handful, like "git diff --exit-code" that explicitly says "1" is
>   the signal that it found difference as opposed to it failing).
>
i'd go with the second, with some minor modifications:
- 1 is the by far most common non-zero error code (and it matches 
   EXIT_FAILURE on all relevant systems), so it's ok to state that. it 
   may be wise to actually check that commands don't deviate from it 
   needlessly.
- the canonical name of the section appears to be "EXIT STATUS"

regards

^ permalink raw reply	[relevance 8%]

* Re: [Leftoverbits] exit code clean-up?
  2023-08-16 17:04  6%     ` [Leftoverbits] exit code clean-up? Junio C Hamano
@ 2023-08-17  5:36  7%       ` Jeff King
  2023-08-17 16:03  8%         ` Junio C Hamano
  2023-08-17  9:24  8%       ` Oswald Buddenhagen
  1 sibling, 1 reply; 200+ results
From: Jeff King @ 2023-08-17  5:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Wed, Aug 16, 2023 at 10:04:28AM -0700, Junio C Hamano wrote:

> We could either
> 
>  * Be more prescriptive and add "EXIT CODES" section to each and
>    every document to describe how we fail in the current code.
> 
> or
> 
>  * Describe "In general, 0 is success, non-zero is failure, but some
>    commands may signal more than that with its non-zero exit codes"
>    in "git help git", and add "EXIT CODES" section to the manual
>    page of the commands whose exit codes matter (there are a
>    handful, like "git diff --exit-code" that explicitly says "1" is
>    the signal that it found difference as opposed to it failing).
> 
> I'd prefer if community agrees that we should do the latter, but I
> am OK if the community consensus goes the other way.

I left some notes on upload-pack specifically elsewhere in the thread,
in which I argue that we should definitely not lock ourselves into its
current behavior.

But in the more general sense, yeah, I think that trying to document
specific exit codes for each command is a mistake. It is not just "let's
find which exit codes they use and document them". I suspect it is a
rat's nest of unplanned behaviors that come from unexpected die() calls
deep in the stack. We would not necessarily want to make promises about
what is happening in those, nor do I think it would even be sensible to
find every possible exit.

We _could_ document "128 means something really unexpected happened and
we called die() deep in the code". But even that seems misleading to me,
as we also die() for everyday shallow things (like "the name you gave is
not valid"). The value really means very little in practice, and the
biggest reason not to change it is that we know it doesn't conflict with
any codes that programs _do_ promise are meaningful (like "1" from "diff
--exit-code").

So saying "0 is success, non-zero is failure, and some commands may
document specific codes" is the closest thing to the reality of what we
as developers know and have planned.  (Of course another project is not
just to figure out the possible situations/codes but to catalogue and
organize them. But that seems like an order of magnitude more work, if
not several orders).

-Peff

^ permalink raw reply	[relevance 7%]

* [Leftoverbits] exit code clean-up?
  @ 2023-08-16 17:04  6%     ` Junio C Hamano
  2023-08-17  5:36  7%       ` Jeff King
  2023-08-17  9:24  8%       ` Oswald Buddenhagen
  0 siblings, 2 replies; 200+ results
From: Junio C Hamano @ 2023-08-16 17:04 UTC (permalink / raw)
  To: git

Patrick earlier found that Gitaly's CI pipeline was being overly
picky and complained about the unintended change of the exit code of
"git fetch" in the affected codepath from 128 to 1 in a recent
change that went to 'next', made by 7ba7c52d (upload-pack: fix race
condition in error messages, 2023-08-10).

The thing is, we follow that exiting with 0 is success, and exiting
with non-zero means failure, and we generally do not specify which
non-zero value is used for the latter in our documentation.  This
particular case (i.e. "git fetch") certainly does not say anything
about how failure is signaled to the calling program.  "git help
git" does not have "EXIT CODES" section, and it is assumed that the
"common sense" of older generation (gee, this project is more than
18 years old) that exiting with 0 is success and non-zero is failure
is shared among its users, which might not be warranted these days.

We could either

 * Be more prescriptive and add "EXIT CODES" section to each and
   every document to describe how we fail in the current code.

or

 * Describe "In general, 0 is success, non-zero is failure, but some
   commands may signal more than that with its non-zero exit codes"
   in "git help git", and add "EXIT CODES" section to the manual
   page of the commands whose exit codes matter (there are a
   handful, like "git diff --exit-code" that explicitly says "1" is
   the signal that it found difference as opposed to it failing).

I'd prefer if community agrees that we should do the latter, but I
am OK if the community consensus goes the other way.

If we were to go the former, the task becomes larger but it would be
embarrassingly parallelizable.  Folks with extra time on their hand
can lend their eyes to tackle each command, find what exit code we
use in the current code, add "EXIT CODES" section to the documentation,
and extend test coverage to ensure their findings will stay unless
we deliberately change it in the future.

If we were to go the latter, the task will be significantly smaller.
We need to come up with a careful phrasing to add to "git help git"
and/or "git help cli" to give the general principle of zero vs
non-zero whose exact values are left unspecified and should not be
depended upon.  We also need to identify the special cases where the
exact values have meanings (like the "git diff --exit-code" example
above), describe them by adding "EXIT CODES" section to the manual
pages of these selected commands, and extend test coverage to ensure
these values are kept intact across future changes.

Comments?

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags
  @ 2023-08-07  5:28  5%     ` Linus Arver
  0 siblings, 0 replies; 200+ results
From: Linus Arver @ 2023-08-07  5:28 UTC (permalink / raw)
  To: Junio C Hamano, Linus Arver via GitGitGadget; +Cc: git

Junio C Hamano <gitster@pobox.com> writes:

> "Linus Arver via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> @@ -114,8 +114,10 @@ OPTIONS
>>  	Specify where all new trailers will be added.  A setting
>>  	provided with '--where' overrides all configuration variables
>
> Obviously this is not a new issue, but "all configuration variables"
> is misleading (the same comment applies to the description of the
> "--[no-]if-exists" and the "--[no-]if-missing" options).

Agreed.

> If I am reading the code correctly, --where=value overrides the
> trailer.where variable and nothing else, and --no-where stops the
> overriding of the trailer.where variable.  Ditto for the other two
> with their relevant configuration variables.

That is also my understanding. Will update to remove the "all" wording.

On a separate note, I've realized there are more fixes to be done in
this area (as I get more familiar with the codebase). For example, we
have the following language in builtin/interpret-trailers.c inside
cmd_interpret_trailers():

    OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")),

which should be fixed in similar style to what you suggested above,
probably with:

    OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply trailer.* configuration variables")),

When I reroll, I will include these additional fixes so expect the patch
series to grow (probably ~12 patches instead of the ~5).

One more thing. I think the documentation
(Documentation/git-interpret-trailers.txt) uses the word "<token>" in
two different ways. For example, if we have in the input

    subject line

    body text

    Acked-by: Foo

the docs treat the word "Acked-by:" as the <token>. However, it defines
the relevant configuration section like this:

    trailer.<token>.key::
            This `key` will be used instead of <token> in the trailer. At
            the end of this key, a separator can appear and then some
            space characters. By default the only valid separator is ':',
            but this can be changed using the `trailer.separators` config
            variable.
    +
    If there is a separator, then the key will be used instead of both the
    <token> and the default separator when adding the trailer.

So if I configure this like

   git config trailer.ack.key "Acked-by" &&

the <token> is both the longer-form "Acked-by:" (per the meaning so far
in the doc) but also the shorter string "ack" per the
"trailer.<token>.key" configuration section syntax. This secondary
meaning is repeated again in the very start of the doc when we define
the --trailer option syntax as

    SYNOPSIS
    --------
    [verse]
    'git interpret-trailers' [--in-place] [--trim-empty]
                [(--trailer <token>[(=|:)<value>])...]
                [--parse] [<file>...]

because the <token> here could be (using the example above) either
"Acked-by" (as in "--trailer=Acked-by:...") if we did not configure
"trailer.ack.key", or just "ack" (as in "--trailer=ack:...") if we did
configure it. These two scenarios would give identical "Acked-by: ..."
output.

This is confusing and I don't like how we overload this "token" word
(not to mention we already have the word "key" which we don't really use
much in the docs).

I am inclined to replace most uses of the word "<token>" with "<key>"
while leaving the "trailer.<token>.key" configuration syntax intact.
This will result in a large diff but I think the removal of the double
meaning is worth it, and will include this fix also in the next reroll.

The main reason I bring this up is because this means also having to
update our funciton names like "token_len_without_separator" in
trailer.c, to be "key_len_without_separator" if we want the nomenclature
in the trailer.c internals to be consistent with the (updated)
user-facing docs. I am not sure whether we want to do this as part of
the same reroll, or if we should leave it as #leftoverbits for a future
series.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH 8/9] repack: implement `--filter-to` for storing filtered out objects
  2023-06-21 12:25  6%       ` Taylor Blau
@ 2023-06-21 16:44  0%         ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-06-21 16:44 UTC (permalink / raw)
  To: Taylor Blau
  Cc: Christian Couder, git, John Cai, Jonathan Tan, Jonathan Nieder,
	Derrick Stolee, Patrick Steinhardt, Christian Couder

Taylor Blau <me@ttaylorr.com> writes:

> In other words, I would be fine with something like:
>
> --- 8< ---
> diff --git a/builtin/repack.c b/builtin/repack.c
> index 0541c3ce15..1890f283ee 100644
> --- a/builtin/repack.c
> +++ b/builtin/repack.c
> @@ -866,6 +866,10 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>  	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
>  		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");
>
> +	/* --expire-to implies cruft */
> +	if (expire_to)
> +		pack_everything |= PACK_CRUFT;
> +
>  	if (pack_everything & PACK_CRUFT) {
>  		pack_everything |= ALL_INTO_ONE;
>
> --- >8 ---
>
> But that sounds like a good candidate for some #leftoverbits.

It does.  Thanks.


^ permalink raw reply	[relevance 0%]

* Re: [PATCH 8/9] repack: implement `--filter-to` for storing filtered out objects
  @ 2023-06-21 12:25  6%       ` Taylor Blau
  2023-06-21 16:44  0%         ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Taylor Blau @ 2023-06-21 12:25 UTC (permalink / raw)
  To: Christian Couder
  Cc: git, Junio C Hamano, John Cai, Jonathan Tan, Jonathan Nieder,
	Derrick Stolee, Patrick Steinhardt, Christian Couder

On Wed, Jun 21, 2023 at 02:08:38PM +0200, Christian Couder wrote:
> > > @@ -1073,8 +1077,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
> > >               strvec_push(&cmd.args, "--incremental");
> > >       }
> > >
> > > -     if (po_args.filter)
> > > -             prepare_pack_filtered_cmd(&pack_filtered_cmd, &po_args, packtmp);
> > > +     if (po_args.filter) {
> > > +             if (!filter_to)
> > > +                     filter_to = packtmp;
> > > +             prepare_pack_filtered_cmd(&pack_filtered_cmd, &po_args, filter_to);
> > > +     }
> >
> > Would you want an "} else if (filter_to)" here to die and show the usage
> > message, since --filter-to needs --filter? Or maybe it should imply
> > --filter-to.
>
> In the doc for --expire-to=<dir> there is "Only useful with `--cruft
> -d`" and I don't think there is a check to see if --cruft and -d have
> been passed when --expire-to is passed. So I am not sure if it's
> better to be consistent with --expire-to or not.

TBH, I don't think that my decision at the time to silently accept
--expire-to without --cruft was the right one. It should at least
require --cruft, or imply it. It doesn't make a ton of sense to use
without -d, but doing so is OK, so I wouldn't consider that a failing
condition.

In other words, I would be fine with something like:

--- 8< ---
diff --git a/builtin/repack.c b/builtin/repack.c
index 0541c3ce15..1890f283ee 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -866,6 +866,10 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
 		die(_("options '%s' and '%s' cannot be used together"), "--keep-unreachable", "-A");

+	/* --expire-to implies cruft */
+	if (expire_to)
+		pack_everything |= PACK_CRUFT;
+
 	if (pack_everything & PACK_CRUFT) {
 		pack_everything |= ALL_INTO_ONE;

--- >8 ---

But that sounds like a good candidate for some #leftoverbits.

In the meantime, I would be absolutely fine with deviating from the
existing behavior of --expire-to w.r.t --cruft.

Thanks,
Taylor

^ permalink raw reply related	[relevance 6%]

* Re: Which macOS versions does Git support?
  2023-05-20  7:36  6%     ` M Hickford
@ 2023-05-22 19:24  0%       ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2023-05-22 19:24 UTC (permalink / raw)
  To: M Hickford; +Cc: Carlo Marcelo Arenas Belón, Taylor Blau, Git Mailing List

On Sat, May 20, 2023 at 08:36:58AM +0100, M Hickford wrote:

> > FWIW Mac OS X 10.5 (Leopard) was last updated in 2009 and also happens to
> > be the last one that can run in PowerPC, so sadly there is a non zero
> > number of users for it (MacPorts uses a minimum of 10.4 for that reason)
> 
> Interesting! https://ports.macports.org/port/git/details/ It looks
> like the most recent build is from 2021
> https://ports.macports.org/port/git/builds/?builder_name__name=10.5_ppc_legacy
> .   https://ports.macports.org/port/git/stats/?days=365&days_ago=0
> shows 10 total PowerPC downloads in the past year between versions
> 10.4, 10.5 and 10.6

One nice thing here is that the credential helpers are pretty
independent from the rest of Git. If new versions of the helper drop
support for the old API, people on ancient systems can still use the old
helper. We'd just have to make a decision about how much to help them:

  1. (least help) Tell them to dig it out of git.git history, build, and
     stuff the resulting binary somewhere.

  2. (most help) Support both, selected by an #ifdef and a Makefile
     knob, and maybe even turn the knob automatically based on "uname
     -r".

  3. (middle ground) Rewrite with the new API, but leave the old helper
     as contrib/osxkeychain-old or something. Still easy-ish to build,
     but carries less maintenance burden.

> I don't have the equipment or expertise to develop on macOS, so I'll
> leave the API migration as a potential future #leftoverbits

I'd probably do (3), but as I also lack equipment or expertise, I'm not
planning on working on it myself (and I'd let whoever does decide to do
that work have the final say on approach).

> Reading the keychain docs more carefully, the new API only supports a
> fixed set of attribute keys such as 'kSecAttrComment', so discount my
> original "further motivation"

Bummer. Thanks for looking into this, though.

-Peff

^ permalink raw reply	[relevance 0%]

* Re: Which macOS versions does Git support?
  @ 2023-05-20  7:36  6%     ` M Hickford
  2023-05-22 19:24  0%       ` Jeff King
  0 siblings, 1 reply; 200+ results
From: M Hickford @ 2023-05-20  7:36 UTC (permalink / raw)
  To: Carlo Marcelo Arenas Belón
  Cc: Jeff King, M Hickford, Taylor Blau, Git Mailing List

On Sat, 20 May 2023 at 01:37, Carlo Marcelo Arenas Belón
<carenas@gmail.com> wrote:
>
> On Fri, May 19, 2023 at 05:09:17AM -0400, Jeff King wrote:
> >
> > I'd guess that anything older than 2009 is probably not worth worrying
> > about.

Thanks Jeff, Jeff and Carlo for your replies.

>
> FWIW Mac OS X 10.5 (Leopard) was last updated in 2009 and also happens to
> be the last one that can run in PowerPC, so sadly there is a non zero
> number of users for it (MacPorts uses a minimum of 10.4 for that reason)

Interesting! https://ports.macports.org/port/git/details/ It looks
like the most recent build is from 2021
https://ports.macports.org/port/git/builds/?builder_name__name=10.5_ppc_legacy
.   https://ports.macports.org/port/git/stats/?days=365&days_ago=0
shows 10 total PowerPC downloads in the past year between versions
10.4, 10.5 and 10.6

>
> Carlo

I don't have the equipment or expertise to develop on macOS, so I'll
leave the API migration as a potential future #leftoverbits

Reading the keychain docs more carefully, the new API only supports a
fixed set of attribute keys such as 'kSecAttrComment', so discount my
original "further motivation"
https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values?language=objc

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 06/15] builtin/for-each-ref.c: add `--exclude` option
  @ 2023-05-09 20:22  6%     ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2023-05-09 20:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jeff King, Derrick Stolee

On Mon, May 08, 2023 at 04:22:08PM -0700, Junio C Hamano wrote:
> Taylor Blau <me@ttaylorr.com> writes:
>
> > diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
> > index c01fa6fefe..449da61e11 100644
> > --- a/builtin/for-each-ref.c
> > +++ b/builtin/for-each-ref.c
> > @@ -14,6 +14,7 @@ static char const * const for_each_ref_usage[] = {
> >  	N_("git for-each-ref [--points-at <object>]"),
> >  	N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"),
> >  	N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
> > +	N_("git for-each-ref [--exclude=<pattern> ...]"),
> >  	NULL
> >  };
>
> I think the original is already wrong, but the easiest thing we can
> do in order to avoid making it worse is to drop this hunk, as the
> existing usage is this:
>
> static char const * const for_each_ref_usage[] = {
> 	N_("git for-each-ref [<options>] [<pattern>]"),
> 	N_("git for-each-ref [--points-at <object>]"),
> 	N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"),
> 	N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
> 	NULL
> };
>
> and this series merely adds a new "--exclude=<pattern>" as one of
> the "<options>".
>
> As we can see from the fact that for example
>
>  $ git for-each-ref --no-merged next refs/heads/\?\?/\*
>
> works just fine, exactly the same thing can be said about the other
> --points-at/--merged/--no-merged/--contains/--no-contains options.
>
> The SYNOPSIS section of the manual page is fine.

Good point, will tweak; thanks.

> > @@ -2169,6 +2169,15 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
> >  	return match_pattern(filter, filter->name_patterns, refname);
> >  }
> >
> > +static int filter_exclude_match(struct ref_filter *filter, const char *refname)
> > +{
> > +	if (!filter->exclude.nr)
> > +		return 0;
> > +	if (filter->match_as_path)
> > +		return match_name_as_path(filter, filter->exclude.v, refname);
> > +	return match_pattern(filter, filter->exclude.v, refname);
> > +}
>
> Earlier I made a comment about .name_patterns member becoming
> unnecessary, but I think what should need to happen is instead
> match_pattern() and match_name_as_path() to lose the "filter"
> parameter, and take a boolean "ignore_case" instead.

Agreed.

> > +cat >expected <<\EOF
> > +refs/tags/bar
> > +refs/tags/baz
> > +refs/tags/foo/one
> > +refs/tags/testtag
> > +EOF
> > +
> > +test_expect_success 'exercise patterns with pattern exclusions' '
> > +	for tag in foo/one foo/two foo/three bar baz
> > +	do
> > +		git tag "$tag" || return 1
> > +	done &&
> > +	test_when_finished "git tag -d foo/one foo/two foo/three bar baz" &&
> > +	git for-each-ref --format="%(refname)" \
> > +		refs/tags/ --exclude="refs/tags/foo/t*" >actual &&
> > +	test_cmp expected actual
> > +'
>
> These are doing as Romans do, so I won't comment on the outdated
> pattern of preparing the expectation outside the test script.  After
> the dust settles, somebody needs to go in and clean it up.

Yeah, I figured that this series was already getting pretty long, but
that it would be expedient to propagate forward this pattern. But it
should be cleaned up. Let's tag it with #leftoverbits accordingly.

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: bug? round-trip through fast-import/fast-export loses files
  2023-03-21 18:31  0%   ` Jeff King
@ 2023-03-22  3:07  0%     ` Elijah Newren
  0 siblings, 0 replies; 200+ results
From: Elijah Newren @ 2023-03-22  3:07 UTC (permalink / raw)
  To: Jeff King; +Cc: Miguel Torroja, Priedhorsky, Reid, git

On Tue, Mar 21, 2023 at 11:31 AM Jeff King <peff@peff.net> wrote:
>
> On Mon, Mar 20, 2023 at 06:57:21PM -0700, Elijah Newren wrote:
>
> > Honestly, looking back at those two patches of mine, I think both were
> > rather suboptimal.  A better solution that would handle both F->D and
> > D->F would be having fast-export sort the diff_filepairs such that it
> > processes the deletes before the modifies.  Another improved solution
> > would be having fast-import sort the files given to it and handling
> > deletes first.  Either should fix this.
> >
> > Might be a good task for a new contributor.  Any takers?  (Tagging as
> > #leftoverbits.)
>
> There was a patch a while ago, but it didn't get applied:
>
>   https://lore.kernel.org/git/1493079137-1838-1-git-send-email-miguel.torroja@gmail.com/
>
> It got hung up on the fact that fast-export can also generate renames,
> and ordering there is tricky. I stand by the sentiment from back then
> that it is still worth it to order things to make the no-rename case
> work, even if there are still corner cases with renames (since you can
> have a cycle of renames, you should not use them if you want to be
> robust against this kind of ordering dependency).

Ah, thanks for the heads up.  Stinkin' renames.  ;-)  I tend to forget
those in the fast-export/fast-import context since fast-export doesn't
detect renames by default (and e.g. filter-repo would turn them off if
they were on by default).

So, I think we probably need to have the fix in fast-import.
Currently, parse_new_commit() calls the various file_change_*()
functions immediately, which in turn immediately call the various
tree_content_*() functions (e.g. file_change_cr() for a rename will
call both tree_content_remove() and tree_content_set()).  Instead of
immediately handling all these, I think that queueing all the
file_change_*() calls up, splitting the renames into delete + modify,
and sorting all the deletes first should fix things for both F->D and
D->F, even when cycles of renames are present as per your example in
that thread.

^ permalink raw reply	[relevance 0%]

* Re: bug? round-trip through fast-import/fast-export loses files
  2023-03-21  1:57  6% ` Elijah Newren
  2023-03-21 15:54  0%   ` Priedhorsky, Reid
@ 2023-03-21 18:31  0%   ` Jeff King
  2023-03-22  3:07  0%     ` Elijah Newren
  1 sibling, 1 reply; 200+ results
From: Jeff King @ 2023-03-21 18:31 UTC (permalink / raw)
  To: Elijah Newren; +Cc: Miguel Torroja, Priedhorsky, Reid, git

On Mon, Mar 20, 2023 at 06:57:21PM -0700, Elijah Newren wrote:

> Honestly, looking back at those two patches of mine, I think both were
> rather suboptimal.  A better solution that would handle both F->D and
> D->F would be having fast-export sort the diff_filepairs such that it
> processes the deletes before the modifies.  Another improved solution
> would be having fast-import sort the files given to it and handling
> deletes first.  Either should fix this.
> 
> Might be a good task for a new contributor.  Any takers?  (Tagging as
> #leftoverbits.)

There was a patch a while ago, but it didn't get applied:

  https://lore.kernel.org/git/1493079137-1838-1-git-send-email-miguel.torroja@gmail.com/

It got hung up on the fact that fast-export can also generate renames,
and ordering there is tricky. I stand by the sentiment from back then
that it is still worth it to order things to make the no-rename case
work, even if there are still corner cases with renames (since you can
have a cycle of renames, you should not use them if you want to be
robust against this kind of ordering dependency).

-Peff

^ permalink raw reply	[relevance 0%]

* Re: bug? round-trip through fast-import/fast-export loses files
  2023-03-21  1:57  6% ` Elijah Newren
@ 2023-03-21 15:54  0%   ` Priedhorsky, Reid
  2023-03-21 18:31  0%   ` Jeff King
  1 sibling, 0 replies; 200+ results
From: Priedhorsky, Reid @ 2023-03-21 15:54 UTC (permalink / raw)
  To: git; +Cc: Elijah Newren


> On Mar 20, 2023, at 7:57 PM, Elijah Newren <newren@gmail.com> wrote:
> 
> Thanks for the well-written bug report, including not only a testcase
> but even the relevant bits of the fast-export output.

😁

> A better solution that would handle both F->D and
> D->F would be having fast-export sort the diff_filepairs such that it
> processes the deletes before the modifies.

In fact, the successful workaround in my own code is to re-order the fast-export output in exactly this way (i.e., sort the lines so all the D lines come before all the M lines).

> Another improved solution
> would be having fast-import sort the files given to it and handling
> deletes first.  Either should fix this.
> 
> Might be a good task for a new contributor.  Any takers?  (Tagging as
> #leftoverbits.)

Let me take a look, but I can’t guarantee anything.

HTH,
Reid

—
he/his


^ permalink raw reply	[relevance 0%]

* Re: bug? round-trip through fast-import/fast-export loses files
  @ 2023-03-21  1:57  6% ` Elijah Newren
  2023-03-21 15:54  0%   ` Priedhorsky, Reid
  2023-03-21 18:31  0%   ` Jeff King
  0 siblings, 2 replies; 200+ results
From: Elijah Newren @ 2023-03-21  1:57 UTC (permalink / raw)
  To: Priedhorsky, Reid; +Cc: git

Hi,

On Mon, Mar 20, 2023 at 11:23 AM Priedhorsky, Reid <reidpr@lanl.gov> wrote:
>
>   Hello,
>
>   I believe I’ve found a bug in Git. It seems that (1) round-tripping through
>   fast-export/fast-import a repository (2) that contains a commit that changes
>   a file to a directory (3) deletes the contents of that directory from the
>   repository.
>
> Thank you for filling out a Git bug report!
> Please answer the following questions to help us understand your issue.
>
> What did you do before the bug happened? (Steps to reproduce your issue)
>
>   Run this shell script:
>
>   ~~~~
>   #!/bin/bash
>
>   set -ex
>
>   mkdir -p /tmp/weirdal
>   cd /tmp/weirdal
>   git --version
>
>   # init repo
>   rm -Rf wd
>   mkdir wd
>   cd wd
>   git init -b main
>
>   # first commit - foo is a file
>   touch foo
>   git add -A
>   git commit -m 'file'
>
>   # second commit - foo is a directory
>   rm foo
>   mkdir foo
>   touch foo/bar
>   git add -A
>   git commit -m 'directory'
>
>   # the contents of foo are in the working dir and the repo
>   git status
>   ls -lR
>   git ls-tree --name-only -r HEAD
>
>   # import/export repository (add --full-tree to work around bug)
>   git fast-export --no-data -- --all > ../export
>   cat ../export
>   git fast-import --force --quiet < ../export
>
>   # bug: foo is still in the WD but not the repo; should still be both
>   git status
>   ls -lR
>   git ls-tree --name-only -r HEAD
>   #git fast-export --no-data -- --all | diff -u --text ../export - || true
>   ~~~~
>
> What did you expect to happen? (Expected behavior)
>
>   Repo should be unchanged, i.e.:
>
>   + git status
>   On branch main
>   nothing to commit, working tree clean
>
> What happened instead? (Actual behavior)
>
>   Git thinks foo/bar has been staged:
>
>   + git status
>   On branch main
>   Changes to be committed:
>     (use "git restore --staged <file>..." to unstage)
>           new file:   foo/bar
>
> What's different between what you expected and what actually happened?
>
>   File foo/bar is staged when it should be unchanged.
>
> Anything else you want to add:
>
>   This also happens in 2.38.1 built from source.
>
>   The bad behavior can be worked around with “--full-tree” on fast-export, but
>   the real repo where I want to do this is pretty large, so I’d prefer not to.
>
>   Note the “git fast-export” output:
>
>     commit refs/heads/main
>     mark :2
>     author Reid Priedhorsky <reidpr@lanl.gov> 1679330805 -0600
>     committer Reid Priedhorsky <reidpr@lanl.gov> 1679330805 -0600
>     data 10
>     directory
>     from :1
>     M 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 foo/bar
>     D foo
>
>   It looks to me like the “M ... foo/bar” is being processed before “D foo”
>   when it should happen in the opposite order.

Thanks for the well-written bug report, including not only a testcase
but even the relevant bits of the fast-export output.  I thought I had
fixed D/F issues in fast-export & fast-import before, and indeed a
search turns up both of

253fb5f889 (fast-import: Improve robustness when D->F changes provided
in wrong order, 2010-07-09)
060df62422 (fast-export: Fix output order of D/F changes, 2010-07-09)

However, it looks like both of those only considered D->F (directory
becomes a file) changes, whereas you specifically have a case of F->D
(file becoming a directory).

Honestly, looking back at those two patches of mine, I think both were
rather suboptimal.  A better solution that would handle both F->D and
D->F would be having fast-export sort the diff_filepairs such that it
processes the deletes before the modifies.  Another improved solution
would be having fast-import sort the files given to it and handling
deletes first.  Either should fix this.

Might be a good task for a new contributor.  Any takers?  (Tagging as
#leftoverbits.)

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v9 6/6] diff-lib: parallelize run_diff_files for submodules
  @ 2023-03-07  8:41  3%     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2023-03-07  8:41 UTC (permalink / raw)
  To: Calvin Wan; +Cc: git, chooglen, newren, jonathantanmy, phillip.wood123


On Thu, Mar 02 2023, Calvin Wan wrote:

Some of this is stuff I probably should have noted in earlier rounds,
sorry, but then again the diff-churn in those made it harder to review,
now that that's mostly out of the way (yay!) ....

> +submodule.diffJobs::
> +	Specifies how many submodules are diffed at the same time. A
> +	positive integer allows up to that number of submodules diffed
> +	in parallel. A value of 0 will give some reasonable default.
> +	If unset, it defaults to 1. The diff operation is used by many

Nit: Maybe start a new paragraph as of "The diff..."?

> +	other git commands such as add, merge, diff, status, stash and
> +	more. Note that the expensive part of the diff operation is

Nit: Maybe change 'add', 'merge' etc. to linkgit:git-add[1], or quote
them?

> +	reading the index from cache or memory. Therefore multiple jobs

With how much we conflate "the cache" and "index" saying "the index from
cache" might be especially confusing. I think we can just skip " from
cache or memory" here.

>  static int match_stat_with_submodule(struct diff_options *diffopt,
>  				     const struct cache_entry *ce,
>  				     struct stat *st, unsigned ce_option,
> -				     unsigned *dirty_submodule)
> +				     unsigned *dirty_submodule, int *defer_submodule_status,

Nit: The other one is an "unsigned", shouldn't "defer_submodule_status"
also be (more on this below).

> +				     unsigned *ignore_untracked)
>  {
>  	int changed = ie_match_stat(diffopt->repo->index, ce, st, ce_option);
> +	int defer = 0;
> +
>  	if (S_ISGITLINK(ce->ce_mode)) {
>  		struct diff_flags orig_flags = diffopt->flags;
>  		if (!diffopt->flags.override_submodule_config)
>  			set_diffopt_flags_from_submodule_config(diffopt, ce->name);

The meaty functional change here looks *much* better, thanks! I.e. this
is pretty much what I suggested in
https://lore.kernel.org/git/230208.861qn01s4g.gmgdl@evledraar.gmail.com/

> -		if (diffopt->flags.ignore_submodules)
> +		if (diffopt->flags.ignore_submodules) {

Not worth a re-roll in itself, but FWIW I think this change would be
marginally easier to follow with *a* preceding refactoring change, but
per the above &
https://lore.kernel.org/git/230209.867cwrzk1l.gmgdl@evledraar.gmail.com/
I just didn't think v7's 6/7
(https://lore.kernel.org/git/20230207181706.363453-7-calvinwan@google.com/)
was what we needed there.

I.e. in this case a leading change that would add these braces would
make this a bit easier to read...

>  			changed = 0;
> -		else if (!diffopt->flags.ignore_dirty_submodules &&

...ditto this line, which would stay the same.

> -			 (!changed || diffopt->flags.dirty_submodules))
> -			*dirty_submodule = is_submodule_modified(ce->name,
> -								 diffopt->flags.ignore_untracked_in_submodules);

Here you are incorrectly changing the indentation of this away from our
usual coding style, which...

> +		} else if (!diffopt->flags.ignore_dirty_submodules &&
> +			   (!changed || diffopt->flags.dirty_submodules)) {
> +			if (defer_submodule_status && *defer_submodule_status) {

Hrm, if if I remove that "&& *defer_submodule_status" all of our tests
pass, the only two callers of this function are one where this is NULL,
and where it's non-NULL but pre-initilized to 1, and the caller will
check if it's then flipped to 0.

> +				defer = 1;
> +				*ignore_untracked = diffopt->flags.ignore_untracked_in_submodules;
> +			} else {
> +				*dirty_submodule = is_submodule_modified(ce->name,
> +					 diffopt->flags.ignore_untracked_in_submodules);

...needlessly inflates the diff here, at least under -w and move
detection, as we correctly detect the "*dirty_submodule" line as the
same, but the "diffopt->flags" line also has a re-indentation change
unrelated to adding the "else" scope.

> +			}
> +		}
>  		diffopt->flags = orig_flags;
>  	}
> +
> +	if (defer_submodule_status)
> +		*defer_submodule_status = defer;

Having read this whole thing to the end again I think this on top would
be much simpler (if I'm right about it being functionally equivalent),
and would address some of the above:
	
	diff --git a/diff-lib.c b/diff-lib.c
	index 7fe6ced9501..d5c823f512a 100644
	--- a/diff-lib.c
	+++ b/diff-lib.c
	@@ -78,7 +78,6 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
	 				     unsigned *ignore_untracked)
	 {
	 	int changed = ie_match_stat(diffopt->repo->index, ce, st, ce_option);
	-	int defer = 0;
	 
	 	if (S_ISGITLINK(ce->ce_mode)) {
	 		struct diff_flags orig_flags = diffopt->flags;
	@@ -88,8 +87,8 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
	 			changed = 0;
	 		} else if (!diffopt->flags.ignore_dirty_submodules &&
	 			   (!changed || diffopt->flags.dirty_submodules)) {
	-			if (defer_submodule_status && *defer_submodule_status) {
	-				defer = 1;
	+			if (defer_submodule_status) {
	+				*defer_submodule_status = 1;
	 				*ignore_untracked = diffopt->flags.ignore_untracked_in_submodules;
	 			} else {
	 				*dirty_submodule = is_submodule_modified(ce->name,
	@@ -99,8 +98,6 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
	 		diffopt->flags = orig_flags;
	 	}
	 
	-	if (defer_submodule_status)
	-		*defer_submodule_status = defer;
	 	return changed;
	 }
	 
	@@ -153,7 +150,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
	 		unsigned int newmode;
	 		struct cache_entry *ce = istate->cache[i];
	 		int changed;
	-		int defer_submodule_status = 1;
	+		int defer_submodule_status = 0;
	 
	 		if (diff_can_quit_early(&revs->diffopt))
	 			break;

We could also just leave it, but I for one found it a bit hard to follow
that this interface seems to be a tri-state (NULL, set to 0, set to 1),
but really it's dual-state, i.e. NULL or a "tell me to defer this" bit.
	
>  	return changed;
>  }
>  
> @@ -124,6 +140,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
>  			      ? CE_MATCH_RACY_IS_DIRTY : 0);
>  	uint64_t start = getnanotime();
>  	struct index_state *istate = revs->diffopt.repo->index;
> +	struct string_list submodules = STRING_LIST_INIT_NODUP;
>  
>  	diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
>  
> @@ -136,7 +153,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
>  		unsigned int newmode;
>  		struct cache_entry *ce = istate->cache[i];
>  		int changed;
> -		unsigned dirty_submodule = 0;
> +		int defer_submodule_status = 1;

Hrm, having suggested the diff above I just noticed this now, I ended up
inverting this, but found the "defer_submodule_status" name a bit odd,
can't we just keep "unsigned dirty_submodule"? (that would also address
the change from "unsigned" to "int" noted above, which is seeminly
unnecessary).

But maybe I'm missing a subtlety here, and we should have "deferred
status" as apposed to "dirty submodule", but in any case the new one
looks like it doesn't need negative values.

> +	}
> +	if (submodules.nr) {
> +		unsigned long parallel_jobs;
> +		struct string_list_item *item;
> +
> +		if (git_config_get_ulong("submodule.diffjobs", &parallel_jobs))
> +			parallel_jobs = 1;
> +		else if (!parallel_jobs)
> +			parallel_jobs = online_cpus();

Given that online_cpus() returns int the "unsigned long" is slightly odd
here, but it's because git_config_get_ulong() exist, but we have no
git_config_get_uint(), so this is OK (but could be cleaned up as some
#leftoverbits).

> +		if (get_submodules_status(&submodules, parallel_jobs))
> +			die(_("submodule status failed"));

Here we're adding get_submodules_status(), and returning the actual
error code from "status", but then ignoring it here, and returning 128
for any non-zero.

I think this would be better as either:

	code = get_submodules_status(...);
	die_message(...)
	exit(code);

Or to just have the function itself return !!status, i.e. a "ok" or "not
ok".

Admittedly a nit, but I have spent quite a bit of time chasing down
various exit-code losses in the submodule code, and it would be nice if
we just carry the code up, or more explicitly ignore it, but don't add
code that seems to care about it, but really doesn't.

I also changed this "die" to a "BUG" and our tests passed, so we have no
tests for when "status" failed, will such a thing even happen in
practice?

> +		for_each_string_list_item(item, &submodules) {
> +			struct submodule_status_util *util = item->util;
> +
> +			record_file_diff(&revs->diffopt, util->newmode,
> +					 util->dirty_submodule, util->changed,
> +					 istate, util->ce);
> +		}
>  	}
> +	string_list_clear(&submodules, 1);
>  	diffcore_std(&revs->diffopt);
>  	diff_flush(&revs->diffopt);
>  	trace_performance_since(start, "diff-files");
> @@ -322,7 +379,7 @@ static int get_stat_data(const struct index_state *istate,
>  			return -1;
>  		}
>  		changed = match_stat_with_submodule(diffopt, ce, &st,
> -						    0, dirty_submodule);
> +						    0, dirty_submodule, NULL, NULL);
>  		if (changed) {
>  			mode = ce_mode_from_stat(ce, st.st_mode);
>  			oid = null_oid();
> diff --git a/submodule.c b/submodule.c
> index 426074cebb..6f6e150a3f 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -1373,6 +1373,13 @@ int submodule_touches_in_range(struct repository *r,
>  	return ret;
>  }
>  
> +struct submodule_parallel_status {
> +	size_t index_count;
> +	int result;
> +
> +	struct string_list *submodule_names;
> +};

Hrm, actually reading a bit more I think part of my comments above are
incorrect, i.e. this "result" seems like an exit code, but really in the
guts of the API we're ignoring the actual code we get, and just setting
this to 1.

Per the above I think it might be OK to ignore the exit code (or not),
but I really wish we did this more explicitly, e.g. if you want to
ignore it call this something like "failed", not "result", and make it
an "unsigned int failed:1" to firmly indicate that it's a boolean at the
API level.

> +struct status_task {
> +	const char *path;

I think we should call this "ce_path", but more on that below.

> +	struct strbuf out;
> +	int ignore_untracked;

Continued type mismatch commentary: Elsewhere in this diff this is
"unsigned", and this compiles for me if I make it "unsigned int
ignore_untracked:1", so let's set it to such a flag instead?

> +static int status_finish(int retvalue, struct strbuf *err,
> +			 void *cb, void *task_cb)
> +{
> +	struct submodule_parallel_status *sps = cb;
> +	struct status_task *task = task_cb;
> +	struct string_list_item *it =
> +		string_list_lookup(sps->submodule_names, task->path);
> +	struct submodule_status_util *util = it->util;
> +	struct string_list list = STRING_LIST_INIT_DUP;
> +	struct string_list_item *item;
> +
> +	if (retvalue) {
> +		sps->result = 1;
> +		strbuf_addf(err, _(STATUS_PORCELAIN_FAIL_ERROR), task->path);
> +	}
> +
> +	string_list_split(&list, task->out.buf, '\n', -1);

I think I noted in some earlier round that taking a string and splitting
it by \n was a bit wasteful in the test code, but this uses the same
pattern.

Maybe it's not a performance concern here either, but won't we
potentially have to parse some very large statuses here?

Aside from that, I haven't tried or reviewed this bit in detail, but
this seems to be making things harder than they need to be. Why are we
buffering up all of the output into "out" here, only to split it by "\n"
later on, and then consider each line as a status line?

Shouldn't we be allocating this string_list to begin with, and append to
it in the "status_on_stderr_output" callback instead?

> +	for_each_string_list_item(item, &list) {
> +		if (parse_status_porcelain(item->string,
> +					   strlen(item->string),
> +					   &util->dirty_submodule,
> +					   util->ignore_untracked))

OK, this seemingly buggy bit of error handling seems to actually be OK
on further review, because we'll BUG() out in the function if it fails,
so the non-zero return here just means "we're done here".

> +			break;
> +	}

Style: drop the braces here, as this is just a for/if/body with a single
body line.

> +int get_submodules_status(struct string_list *submodules,
> +			  int max_parallel_jobs)
> +{
> +	struct submodule_parallel_status sps = {
> +		.submodule_names = submodules,
> +	};
> +	const struct run_process_parallel_opts opts = {
> +		.tr2_category = "submodule",
> +		.tr2_label = "parallel/status",
> +
> +		.processes = max_parallel_jobs,
> +
> +		.get_next_task = get_next_submodule_status,
> +		.start_failure = status_start_failure,
> +		.on_stderr_output = status_on_stderr_output,
> +		.task_finished = status_finish,
> +		.data = &sps,
> +	};
> +
> +	string_list_sort(sps.submodule_names);
> +	run_processes_parallel(&opts);
> +
> +	return sps.result;

All OK, except as noted above the "result" here is just "did we fail?".

> +}
> +
>  int submodule_uses_gitfile(const char *path)
>  {
>  	struct child_process cp = CHILD_PROCESS_INIT;
> diff --git a/submodule.h b/submodule.h
> index b52a4ff1e7..08d278a414 100644
> --- a/submodule.h
> +++ b/submodule.h
> @@ -41,6 +41,13 @@ struct submodule_update_strategy {
>  	.type = SM_UPDATE_UNSPECIFIED, \
>  }
>  
> +struct submodule_status_util {
> +	int changed, ignore_untracked;
> +	unsigned dirty_submodule, newmode;
> +	struct cache_entry *ce;
> +	const char *path;

Re "ce_path" above: What's the point of adding a "path" here if we
already have "ce"? You just seem to assign "path" to "ce->name"
always. I tried this fix-up on top & it worked:
	
	diff --git a/diff-lib.c b/diff-lib.c
	index d5c823f512a..39d8179f0ed 100644
	--- a/diff-lib.c
	+++ b/diff-lib.c
	@@ -294,7 +294,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
	 					.ignore_untracked = ignore_untracked,
	 					.newmode = newmode,
	 					.ce = ce,
	-					.path = ce->name,
	 				};
	 				struct string_list_item *item;
	 
	diff --git a/submodule.c b/submodule.c
	index 3eba00f1533..c220d85815a 100644
	--- a/submodule.c
	+++ b/submodule.c
	@@ -2002,11 +2002,11 @@ get_status_task_from_index(struct submodule_parallel_status *sps,
	 		struct submodule_status_util *util = sps->submodule_names->items[sps->index_count].util;
	 		struct status_task *task;
	 
	-		if (!verify_submodule_git_directory(util->path))
	+		if (!verify_submodule_git_directory(util->ce->name))
	 			continue;
	 
	 		task = xmalloc(sizeof(*task));
	-		task->path = util->path;
	+		task->path = util->ce->name;
	 		task->ignore_untracked = util->ignore_untracked;
	 		strbuf_init(&task->out, 0);
	 		sps->index_count++;
	diff --git a/submodule.h b/submodule.h
	index 3b6abca05cd..3427c495573 100644
	--- a/submodule.h
	+++ b/submodule.h
	@@ -45,7 +45,6 @@ struct submodule_status_util {
	 	int changed, ignore_untracked;
	 	unsigned dirty_submodule, newmode;
	 	struct cache_entry *ce;
	-	const char *path;
	 };
	 
	 int is_gitmodules_unmerged(struct index_state *istate);

I'd be all for actually narrowing the scope of data we get in general,
i.e. do we need all of the "ce" members? I didn't check, but doing this
just seems like needless duplication.

> @@ -94,6 +101,8 @@ int fetch_submodules(struct repository *r,
>  		     int command_line_option,
>  		     int default_option,
>  		     int quiet, int max_parallel_jobs);
> +int get_submodules_status(struct string_list *submodules,
> +			  int max_parallel_jobs);

It would be nice to get some API docs for the new function, re its
"result" behavior etc. noted above

>  unsigned is_submodule_modified(const char *path, int ignore_untracked);
>  int submodule_uses_gitfile(const char *path);
>  
> diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
> index 40164ae07d..1c747cc325 100755
> --- a/t/t4027-diff-submodule.sh
> +++ b/t/t4027-diff-submodule.sh
> @@ -34,6 +34,25 @@ test_expect_success setup '
>  	subtip=$3 subprev=$2
>  '
>  
> +test_expect_success 'diff in superproject with submodules respects parallel settings' '
> +	test_when_finished "rm -f trace.out" &&
> +	(
> +		GIT_TRACE=$(pwd)/trace.out git diff &&
> +		grep "1 tasks" trace.out &&
> +		>trace.out &&
> +
> +		git config submodule.diffJobs 8 &&
> +		GIT_TRACE=$(pwd)/trace.out git diff &&
> +		grep "8 tasks" trace.out &&
> +		>trace.out &&
> +
> +		GIT_TRACE=$(pwd)/trace.out git -c submodule.diffJobs=0 diff &&
> +		grep "preparing to run up to [0-9]* tasks" trace.out &&
> +		! grep "up to 0 tasks" trace.out &&
> +		>trace.out
> +	)
> +'
> +
>  test_expect_success 'git diff --raw HEAD' '
>  	hexsz=$(test_oid hexsz) &&
>  	git diff --raw --abbrev=$hexsz HEAD >actual &&
> @@ -70,6 +89,18 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree)' '
>  	test_cmp expect.body actual.body
>  '
>  
> +test_expect_success 'git diff HEAD with dirty submodule (work tree, parallel)' '
> +	(
> +		cd sub &&
> +		git reset --hard &&
> +		echo >>world
> +	) &&
> +	git -c submodule.diffJobs=8 diff HEAD >actual &&
> +	sed -e "1,/^@@/d" actual >actual.body &&
> +	expect_from_to >expect.body $subtip $subprev-dirty &&
> +	test_cmp expect.body actual.body
> +'
> +
>  test_expect_success 'git diff HEAD with dirty submodule (index)' '
>  	(
>  		cd sub &&
> diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
> index d050091345..7da64e4c4c 100755
> --- a/t/t7506-status-submodule.sh
> +++ b/t/t7506-status-submodule.sh
> @@ -412,4 +412,29 @@ test_expect_success 'status with added file in nested submodule (short)' '
>  	EOF
>  '
>  
> +test_expect_success 'status in superproject with submodules respects parallel settings' '
> +	test_when_finished "rm -f trace.out" &&
> +	(
> +		GIT_TRACE=$(pwd)/trace.out git status &&
> +		grep "1 tasks" trace.out &&
> +		>trace.out &&
> +
> +		git config submodule.diffJobs 8 &&
> +		GIT_TRACE=$(pwd)/trace.out git status &&
> +		grep "8 tasks" trace.out &&
> +		>trace.out &&
> +
> +		GIT_TRACE=$(pwd)/trace.out git -c submodule.diffJobs=0 status &&
> +		grep "preparing to run up to [0-9]* tasks" trace.out &&
> +		! grep "up to 0 tasks" trace.out &&
> +		>trace.out
> +	)
> +'
> +
> +test_expect_success 'status in superproject with submodules (parallel)' '
> +	git -C super status --porcelain >output &&
> +	git -C super -c submodule.diffJobs=8 status --porcelain >output_parallel &&
> +	diff output output_parallel

Shouldn't this be a "test_cmp" instead of "diff", and use "actual" and
"expect" instead of "output" and "output_parallel"?

I'd also rename the test to something like "output with
submodule.diffJobs=N equals submodule.diffJobs=1".

Except is that even correct? Don't we need to set submodule.diffJobs=1
explicitly so it doesn't default to online_cpus() here? Maybe I missed
an earlier config setup...

^ permalink raw reply	[relevance 3%]

* Re: How to find places where I can contribute?
  @ 2023-02-20 21:31  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-02-20 21:31 UTC (permalink / raw)
  To: Christian Couder; +Cc: Divyanshu Agrawal, git

Christian Couder <christian.couder@gmail.com> writes:

>> 1. What is the equivalent for the Git project? How can I find issues/features
>> that I can work on?
>>
>> 2. Is there a way I can find bugs/issues that are likely easy for a new
>> contributor to pick up? Similar to a "good-first-issue" label on GitHub?
>
> We have the following documentation:
>
> https://git.github.io/General-Microproject-Information/
>
> There is also the microproject idea page from last year's GSoC:
>
> https://git.github.io/SoC-2022-Microprojects/

While these are good for GSoC applicants before they do a real
project, I didn't read the "where I can contribute?" as such---it
asks for something more real, not a toy "dip my toes" practice.

Perhaps looking for #leftoverbits in the list archive may be another
approach that would give readers a problem with real upsides?

Thanks.



^ permalink raw reply	[relevance 6%]

* Re: [PATCH] cache-tree: fix strbuf growth in prime_cache_tree_rec()
  2023-02-06 16:18  6%     ` Ævar Arnfjörð Bjarmason
@ 2023-02-12 11:20  0%       ` René Scharfe
  0 siblings, 0 replies; 200+ results
From: René Scharfe @ 2023-02-12 11:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, Derrick Stolee
  Cc: Git List, Junio C Hamano, Victoria Dye

Am 06.02.23 um 17:18 schrieb Ævar Arnfjörð Bjarmason:
>
> On Mon, Feb 06 2023, Derrick Stolee wrote:
>
>> On 2/5/2023 4:12 PM, Ævar Arnfjörð Bjarmason wrote:
>
>>> Or even just:
>>>
>>> 	strbuf_addf(tree_path, "%*.s/", (int)entry.pathlen, entry.path);
>>
>> Please do not add "addf" functions that can be run in tight loops.
>> It's faster to do strbuf_add() followed by strbuf_addch().
>
> Good point.
>
> I wondered just how much slower, and it's up to 3x! At least according
> to this[1] artificial test case (where I usurped a random test helper).
>
> I wondered if we could just handle some common strbuf_addf() cases
> ourselves, and the benchmark shows (manually annotated, too lazy to set
> up the -n option):
>
> 	git hyperfine -L rev HEAD~5,HEAD~4,HEAD~3,HEAD~2,HEAD~1,HEAD~0 -s 'make CFLAGS=-O3' './t/helper/test-tool online-cpus' -r 3
> 	[...]
> 	Summary
> 	  './t/helper/test-tool online-cpus' in 'HEAD~0' ran <== strbuf_add() + strbuf_addch()
> 	    1.06 ± 0.11 times faster than './t/helper/test-tool online-cpus' in 'HEAD~1' <== strbuf_addstr() + strbuf_addch()
> 	    1.18 ± 0.12 times faster than './t/helper/test-tool online-cpus' in 'HEAD~4' <== hand optimized strbuf_addf() for "%sC"
> 	    1.33 ± 0.18 times faster than './t/helper/test-tool online-cpus' in 'HEAD~2' <== hand optimized strbuf_addf() for "%*sC"
> 	    2.63 ± 0.05 times faster than './t/helper/test-tool online-cpus' in 'HEAD~5' <== strbuf_addf("%s/")
> 	    2.92 ± 0.25 times faster than './t/helper/test-tool online-cpus' in 'HEAD~3' <== strbuf_addf("%*s/")

Woah!

> The "hand optimization" just being a very stupid handling of "%sC" for
> arbitrary values of a single char "C", and ditto for "%*sC" (which
> curiously is slower here).

"%*s" adds padding if needed, your version doesn't.  Perhaps you thought
of "%.*s"?  That might be relevant because for "%*s" vsnprintf(3) needs
to run strlen(3) again on the argument, while for "%.*s" it can stop
when the given length is reached.

> So, for truly hot loops we'd still want to use the add + addch, but if
> anyone's interested (hashtag #leftoverbits) it looks like we could get
> some easy wins (and reduction in code size, as we could stop worrying
> about addf being slow in most cases) with some very dumb minimal
> vaddf(), which could handle these cases (but not anything involving
> padding etc.).
>
> I didn't dig, but wouldn't be surprised if the reason is that C
> libraries need to carry a relatively fat & general sprintf() for all
> those edge cases, locale handling etc, whereas most of our use could
> trivially be represented as some sequence of addstr()/addf() etc.

If that's the reason then resisting the urge to handle ever more cases
in strbuf_addf() would be quite important.

> Another interesting approach (and this is very #leftoverbits) would be
> to perform the same optimization with coccinelle.
>
> I.e. our current use of it is purely "this code X should be written like
> Y, and we should commit Y".
>
> But there's no reason for why we couldn't effectively implement our own
> compiler optimizations for our own APIs with it, so just grab "%s/" etc,
> unpack that in OCaml, then emit strbuf_add() + strbuf_addch(), and that
> would be what the C compiler would see.

Extracting the %s is technically possible using a semantic patch without
scripting:

   @@
   expression sb, str;
   format fmt =~ "^s$";
   @@
   + strbuf_addstr(sb, str);
     strbuf_addf(sb, "%@fmt@..."
   - , str
   + + 2
     );

The "+ 2" is ugly and runs afoul of compiler warning -Wstring-plus-int,
though.  Resolving this probably requires Python scripting as in
https://github.com/coccinelle/coccinelle/blob/master/demos/format.cocci,
or the OCaml magic you have in mind.  I have to admit that I don't even
understand the linked examples, however. :-/

The warning can be avoided by using an array subscription, by the way,
but that's even uglier:

   @@
   expression sb, str;
   format fmt =~ "^s$";
   @@
   + strbuf_addstr(sb, str);
     strbuf_addf(sb,
   + &
     "%@fmt@..."
   - , str
   + [2]
     );

>
> 1.
>
> 	9d23ffb1117 addf + nolen
> 	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
> 	index 8cb0d53840f..c802ec579d0 100644
> 	--- a/t/helper/test-online-cpus.c
> 	+++ b/t/helper/test-online-cpus.c
> 	@@ -1,9 +1,17 @@
> 	 #include "test-tool.h"
> 	 #include "git-compat-util.h"
> 	 #include "thread-utils.h"
> *	+#include "strbuf.h"
>
> 	 int cmd__online_cpus(int argc, const char **argv)
> 	 {
> 	-	printf("%d\n", online_cpus());
> 	+	struct strbuf sb = STRBUF_INIT;
> 	+	const char *const str = "Hello, World";
> 	+
> 	+	for (size_t i = 0; i < 10000000; i++) {
> 	+		strbuf_reset(&sb);
> 	+		strbuf_addf(&sb, "%s/", str);
> 	+		puts(sb.buf);
> 	+	}
> 	 	return 0;
> 	 }
> 	9f74eff5623 addf + nolen optimize
> 	diff --git a/strbuf.c b/strbuf.c
> 	index c383f41a3c5..750e5e6a5b4 100644
> 	--- a/strbuf.c
> 	+++ b/strbuf.c
> 	@@ -332,8 +332,16 @@ void strbuf_addchars(struct strbuf *sb, int c, size_t n)
> 	 void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
> 	 {
> 	 	va_list ap;
> 	+
> 	 	va_start(ap, fmt);
> 	-	strbuf_vaddf(sb, fmt, ap);
> 	+	if (*fmt == '%' && *(fmt + 1) == 's' && *(fmt + 2) && !*(fmt + 3)) {
> 	+		const char *arg = va_arg(ap, const char *);
> 	+
> 	+		strbuf_addstr(sb, arg);
> 	+		strbuf_addch(sb, *(fmt + 2));
> 	+	} else {
> 	+		strbuf_vaddf(sb, fmt, ap);
> 	+	}
> 	 	va_end(ap);
> 	 }
>
> 	ca60bb9b479 addf + len
> 	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
> 	index c802ec579d0..7257e622015 100644
> 	--- a/t/helper/test-online-cpus.c
> 	+++ b/t/helper/test-online-cpus.c
> 	@@ -7,10 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
> 	 {
> 	 	struct strbuf sb = STRBUF_INIT;
> 	 	const char *const str = "Hello, World";
> 	+	const size_t len = strlen(str);
>
> 	 	for (size_t i = 0; i < 10000000; i++) {
> 	 		strbuf_reset(&sb);
> 	-		strbuf_addf(&sb, "%s/", str);
> 	+		strbuf_addf(&sb, "%*s/", (int)len, str);
> 	 		puts(sb.buf);
> 	 	}
> 	 	return 0;
> 	1f47987d095 addf + len optimize
> 	diff --git a/strbuf.c b/strbuf.c
> 	index 750e5e6a5b4..88801268f7a 100644
> 	--- a/strbuf.c
> 	+++ b/strbuf.c
> 	@@ -334,11 +334,16 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
> 	 	va_list ap;
>
> 	 	va_start(ap, fmt);
> 	-	if (*fmt == '%' && *(fmt + 1) == 's' && *(fmt + 2) && !*(fmt + 3)) {
> 	+	if (*fmt == '%' &&
> 	+	    *(fmt + 1) == '*' &&
> 	+	    *(fmt + 2) == 's' &&
> 	+	    *(fmt + 3) &&
> 	+	    !*(fmt + 4)) {
> 	+		int len = va_arg(ap, int);
> 	 		const char *arg = va_arg(ap, const char *);
>
> 	-		strbuf_addstr(sb, arg);
> 	-		strbuf_addch(sb, *(fmt + 2));
> 	+		strbuf_add(sb, arg, len);
> 	+		strbuf_addch(sb, *(fmt + 3));
> 	 	} else {
> 	 		strbuf_vaddf(sb, fmt, ap);
> 	 	}
> 	55c698c0b95 addstr
> 	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
> 	index 7257e622015..2716b44ca15 100644
> 	--- a/t/helper/test-online-cpus.c
> 	+++ b/t/helper/test-online-cpus.c
> 	@@ -7,11 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
> 	 {
> 	 	struct strbuf sb = STRBUF_INIT;
> 	 	const char *const str = "Hello, World";
> 	-	const size_t len = strlen(str);
>
> 	 	for (size_t i = 0; i < 10000000; i++) {
> 	 		strbuf_reset(&sb);
> 	-		strbuf_addf(&sb, "%*s/", (int)len, str);
> 	+		strbuf_addstr(&sb, str);
> 	+		strbuf_addch(&sb, '/');
> 	 		puts(sb.buf);
> 	 	}
> 	 	return 0;
> 	b17fb99bf7e (HEAD -> master) add
> 	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
> 	index 2716b44ca15..5e52b622c4d 100644
> 	--- a/t/helper/test-online-cpus.c
> 	+++ b/t/helper/test-online-cpus.c
> 	@@ -7,10 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
> 	 {
> 	 	struct strbuf sb = STRBUF_INIT;
> 	 	const char *const str = "Hello, World";
> 	+	const size_t len = strlen(str);
>
> 	 	for (size_t i = 0; i < 10000000; i++) {
> 	 		strbuf_reset(&sb);
> 	-		strbuf_addstr(&sb, str);
> 	+		strbuf_add(&sb, str, len);
> 	 		strbuf_addch(&sb, '/');
> 	 		puts(sb.buf);
> 	 	}

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] cache-tree: fix strbuf growth in prime_cache_tree_rec()
  2023-02-11  2:15  6%       ` Jeff King
@ 2023-02-11  2:46  0%         ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-02-11  2:46 UTC (permalink / raw)
  To: Jeff King
  Cc: René Scharfe, Ævar Arnfjörð Bjarmason,
	Git List, Victoria Dye

Jeff King <peff@peff.net> writes:

>> ...  I do not feel it too strongly but we
>> might want to rename _grow() to _grow_by() and make _grow() call it
>> while giving deprecation warning X-<.
>
> Having been confused by that myself, I would be happy to see such a
> name change.

If we did not know how useless explicit growth control is, we would
likely have a pair of helpers, _grow_by() and _grow_to(), but given
that ...

>> There are ~45 calls to strbuf_grow() in C files other than strbuf.c;
>> I suspect probably a half or more of them can and should be removed
>> to reduce the resulting code size without hurting anything.
>
> My gut feeling is that your suspicion is giving strbuf_grow() users too
> much credit. ;) And having looked at the first 7 grep hits, every single
> one of them seemed pointless to me.

... we'd only have a very limited number of callers for which the
helper makes sense, I am not sure if it is even worth the renaming.

Or just rename it to _grow_to() while fixing what it does, as
grow_to() is what programmers would expect naturally?

> I wonder if these would make a good #leftoverbits / micro-project
> candidate.

The task is to pick one or two from these 45 hits, analyze what
would happen if we remove the _grow() calls.  For many of them, the
result of such analysis would say the calls are pointless, but for
some, there hopefully are solid reasons why explicit sizing makes
sense.  The former will be just removed, while the latter will be
kept with a new in-code comment to record why it is worth having the
call.  The parameter may need to be updated for them at the same
time.

It can be done extremely poorly without breaking anything in the
test suite, or it can be done expertly.  Unless the result are
reviewed competently, it may make a rather poor micro-project
experience.

So, I dunno.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] cache-tree: fix strbuf growth in prime_cache_tree_rec()
  @ 2023-02-11  2:15  6%       ` Jeff King
  2023-02-11  2:46  0%         ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Jeff King @ 2023-02-11  2:15 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: René Scharfe, Ævar Arnfjörð Bjarmason,
	Git List, Victoria Dye

On Fri, Feb 10, 2023 at 12:33:00PM -0800, Junio C Hamano wrote:

> > strbuf_setlen() truncates the string to the directory name.  strbuf_grow() then
> > makes enough room to add that directory name again (that's what I mean with
> > "double") plus the entry path.  We don't add the directory name a second time,
> > so we don't need to make room for it.
> 
> Yeah, I think I made the same mistake number of years ago, thinking
> that strbuf_grow() was to grow the buffer to the given size, but in
> reality it is to grow the buffer by the given size, which felt a bit
> unnatural, at least to me.  I do not feel it too strongly but we
> might want to rename _grow() to _grow_by() and make _grow() call it
> while giving deprecation warning X-<.

Having been confused by that myself, I would be happy to see such a
name change.

> There are ~45 calls to strbuf_grow() in C files other than strbuf.c;
> I suspect probably a half or more of them can and should be removed
> to reduce the resulting code size without hurting anything.

My gut feeling is that your suspicion is giving strbuf_grow() users too
much credit. ;) And having looked at the first 7 grep hits, every single
one of them seemed pointless to me.

I wonder if these would make a good #leftoverbits / micro-project
candidate.

-Peff

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] cache-tree: fix strbuf growth in prime_cache_tree_rec()
  @ 2023-02-06 16:18  6%     ` Ævar Arnfjörð Bjarmason
  2023-02-12 11:20  0%       ` René Scharfe
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2023-02-06 16:18 UTC (permalink / raw)
  To: Derrick Stolee; +Cc: René Scharfe, Git List, Junio C Hamano, Victoria Dye


On Mon, Feb 06 2023, Derrick Stolee wrote:

> On 2/5/2023 4:12 PM, Ævar Arnfjörð Bjarmason wrote:
> [...]
>> One wonders if (even for this index-related code) we really need such
>> careful management of growth, and could instead do with:
>> 
>> 	strbuf_setlen(tree_path, base_path_len);
>> 	strbuf_add(tree_path, entry.path, entry.pathlen);
>> 	strbuf_addch(tree_path, '/');
>
> This would be my preferred way to go here.

*nod*

>> Or even just:
>> 
>> 	strbuf_addf(tree_path, "%*.s/", (int)entry.pathlen, entry.path);
>
> Please do not add "addf" functions that can be run in tight loops.
> It's faster to do strbuf_add() followed by strbuf_addch().

Good point.

I wondered just how much slower, and it's up to 3x! At least according
to this[1] artificial test case (where I usurped a random test helper).

I wondered if we could just handle some common strbuf_addf() cases
ourselves, and the benchmark shows (manually annotated, too lazy to set
up the -n option):

	git hyperfine -L rev HEAD~5,HEAD~4,HEAD~3,HEAD~2,HEAD~1,HEAD~0 -s 'make CFLAGS=-O3' './t/helper/test-tool online-cpus' -r 3
	[...]
	Summary
	  './t/helper/test-tool online-cpus' in 'HEAD~0' ran <== strbuf_add() + strbuf_addch()
	    1.06 ± 0.11 times faster than './t/helper/test-tool online-cpus' in 'HEAD~1' <== strbuf_addstr() + strbuf_addch()
	    1.18 ± 0.12 times faster than './t/helper/test-tool online-cpus' in 'HEAD~4' <== hand optimized strbuf_addf() for "%sC"
	    1.33 ± 0.18 times faster than './t/helper/test-tool online-cpus' in 'HEAD~2' <== hand optimized strbuf_addf() for "%*sC"
	    2.63 ± 0.05 times faster than './t/helper/test-tool online-cpus' in 'HEAD~5' <== strbuf_addf("%s/")
	    2.92 ± 0.25 times faster than './t/helper/test-tool online-cpus' in 'HEAD~3' <== strbuf_addf("%*s/")

The "hand optimization" just being a very stupid handling of "%sC" for
arbitrary values of a single char "C", and ditto for "%*sC" (which
curiously is slower here).

So, for truly hot loops we'd still want to use the add + addch, but if
anyone's interested (hashtag #leftoverbits) it looks like we could get
some easy wins (and reduction in code size, as we could stop worrying
about addf being slow in most cases) with some very dumb minimal
vaddf(), which could handle these cases (but not anything involving
padding etc.).

I didn't dig, but wouldn't be surprised if the reason is that C
libraries need to carry a relatively fat & general sprintf() for all
those edge cases, locale handling etc, whereas most of our use could
trivially be represented as some sequence of addstr()/addf() etc.

Another interesting approach (and this is very #leftoverbits) would be
to perform the same optimization with coccinelle.

I.e. our current use of it is purely "this code X should be written like
Y, and we should commit Y".

But there's no reason for why we couldn't effectively implement our own
compiler optimizations for our own APIs with it, so just grab "%s/" etc,
unpack that in OCaml, then emit strbuf_add() + strbuf_addch(), and that
would be what the C compiler would see.

1.
	
	9d23ffb1117 addf + nolen
	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
	index 8cb0d53840f..c802ec579d0 100644
	--- a/t/helper/test-online-cpus.c
	+++ b/t/helper/test-online-cpus.c
	@@ -1,9 +1,17 @@
	 #include "test-tool.h"
	 #include "git-compat-util.h"
	 #include "thread-utils.h"
*	+#include "strbuf.h"
	 
	 int cmd__online_cpus(int argc, const char **argv)
	 {
	-	printf("%d\n", online_cpus());
	+	struct strbuf sb = STRBUF_INIT;
	+	const char *const str = "Hello, World";
	+
	+	for (size_t i = 0; i < 10000000; i++) {
	+		strbuf_reset(&sb);
	+		strbuf_addf(&sb, "%s/", str);
	+		puts(sb.buf);
	+	}
	 	return 0;
	 }
	9f74eff5623 addf + nolen optimize
	diff --git a/strbuf.c b/strbuf.c
	index c383f41a3c5..750e5e6a5b4 100644
	--- a/strbuf.c
	+++ b/strbuf.c
	@@ -332,8 +332,16 @@ void strbuf_addchars(struct strbuf *sb, int c, size_t n)
	 void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
	 {
	 	va_list ap;
	+
	 	va_start(ap, fmt);
	-	strbuf_vaddf(sb, fmt, ap);
	+	if (*fmt == '%' && *(fmt + 1) == 's' && *(fmt + 2) && !*(fmt + 3)) {
	+		const char *arg = va_arg(ap, const char *);
	+
	+		strbuf_addstr(sb, arg);
	+		strbuf_addch(sb, *(fmt + 2));
	+	} else {
	+		strbuf_vaddf(sb, fmt, ap);
	+	}
	 	va_end(ap);
	 }
	 
	ca60bb9b479 addf + len
	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
	index c802ec579d0..7257e622015 100644
	--- a/t/helper/test-online-cpus.c
	+++ b/t/helper/test-online-cpus.c
	@@ -7,10 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
	 {
	 	struct strbuf sb = STRBUF_INIT;
	 	const char *const str = "Hello, World";
	+	const size_t len = strlen(str);
	 
	 	for (size_t i = 0; i < 10000000; i++) {
	 		strbuf_reset(&sb);
	-		strbuf_addf(&sb, "%s/", str);
	+		strbuf_addf(&sb, "%*s/", (int)len, str);
	 		puts(sb.buf);
	 	}
	 	return 0;
	1f47987d095 addf + len optimize
	diff --git a/strbuf.c b/strbuf.c
	index 750e5e6a5b4..88801268f7a 100644
	--- a/strbuf.c
	+++ b/strbuf.c
	@@ -334,11 +334,16 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
	 	va_list ap;
	 
	 	va_start(ap, fmt);
	-	if (*fmt == '%' && *(fmt + 1) == 's' && *(fmt + 2) && !*(fmt + 3)) {
	+	if (*fmt == '%' &&
	+	    *(fmt + 1) == '*' &&
	+	    *(fmt + 2) == 's' &&
	+	    *(fmt + 3) &&
	+	    !*(fmt + 4)) {
	+		int len = va_arg(ap, int);
	 		const char *arg = va_arg(ap, const char *);
	 
	-		strbuf_addstr(sb, arg);
	-		strbuf_addch(sb, *(fmt + 2));
	+		strbuf_add(sb, arg, len);
	+		strbuf_addch(sb, *(fmt + 3));
	 	} else {
	 		strbuf_vaddf(sb, fmt, ap);
	 	}
	55c698c0b95 addstr
	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
	index 7257e622015..2716b44ca15 100644
	--- a/t/helper/test-online-cpus.c
	+++ b/t/helper/test-online-cpus.c
	@@ -7,11 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
	 {
	 	struct strbuf sb = STRBUF_INIT;
	 	const char *const str = "Hello, World";
	-	const size_t len = strlen(str);
	 
	 	for (size_t i = 0; i < 10000000; i++) {
	 		strbuf_reset(&sb);
	-		strbuf_addf(&sb, "%*s/", (int)len, str);
	+		strbuf_addstr(&sb, str);
	+		strbuf_addch(&sb, '/');
	 		puts(sb.buf);
	 	}
	 	return 0;
	b17fb99bf7e (HEAD -> master) add
	diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c
	index 2716b44ca15..5e52b622c4d 100644
	--- a/t/helper/test-online-cpus.c
	+++ b/t/helper/test-online-cpus.c
	@@ -7,10 +7,11 @@ int cmd__online_cpus(int argc, const char **argv)
	 {
	 	struct strbuf sb = STRBUF_INIT;
	 	const char *const str = "Hello, World";
	+	const size_t len = strlen(str);
	 
	 	for (size_t i = 0; i < 10000000; i++) {
	 		strbuf_reset(&sb);
	-		strbuf_addstr(&sb, str);
	+		strbuf_add(&sb, str, len);
	 		strbuf_addch(&sb, '/');
	 		puts(sb.buf);
	 	}

^ permalink raw reply	[relevance 6%]

* Re: [GSoC][PATCH] merge: use reverse_commit_list() for list reversal
  2023-02-03 18:02  6%   ` Elijah Newren
@ 2023-02-03 19:07  0%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2023-02-03 19:07 UTC (permalink / raw)
  To: Elijah Newren; +Cc: Kousik Sanagavarapu, git

Elijah Newren <newren@gmail.com> writes:

> Also, gitgitgadget #1156 was opened because of my suggestion to do
> this as a "leftoverbit", i.e. I was suggesting it as a micro-project
> to new people.  I should have checked at the time that it was a valid
> micro-project, but neglected to do so.  You merely came along and
> started implementing what was suggested.
>
> Anyway, the point of the GSoC microprojects are to make sure you are
> familiar with how to format and submit patches to the mailing list and
> respond; having the code you contribute in a microproject be accepted
> is not required, just a bonus.  And you clearly managed to send the
> patch to the list, had a correctly formatted commit message (short
> summary with area and correct lack of capitalization, good
> descriptions, signed-off-by), got the additional notes for reviewers
> (very helpful!) in the correct spot, etc., so I still see this as a
> successful microproject for you.  I apologize for not doing my due
> diligence when I suggested it, and for us not catching that it should
> have been closed when someone implemented the valid half of the
> suggestion last year.

One possible action item for us may be to rename or give comment to
highlight the in-place destructive nature of the function to make it
easier for developers to use (or avoid misusing) it.

^ permalink raw reply	[relevance 0%]

* Re: [GSoC][PATCH] merge: use reverse_commit_list() for list reversal
  @ 2023-02-03 18:02  6%   ` Elijah Newren
  2023-02-03 19:07  0%     ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Elijah Newren @ 2023-02-03 18:02 UTC (permalink / raw)
  To: Kousik Sanagavarapu; +Cc: git

On Fri, Feb 3, 2023 at 9:49 AM Kousik Sanagavarapu <five231003@gmail.com> wrote:
>
> Now, I think I understand the mistake that I did. Even if it did work
> for one merge strategy, the code would not be good as the helper function
> is not doing what it is intended to do. In any case, I should have been
> more careful submitting the patch.
>
> On a side note, I think we can now close the issue #1156 on gitgitgadget? As
> with builtin/merge.c out of the way, the only other case is in revision.c
> and the use of the helper function there is inapproriate.
>
> Thanks for the explanation.

Yeah, it should have been closed back when
https://lore.kernel.org/git/CANsrJQd0v2V9H8HPkiH2179C1c-NOSTRRB8YXt8v6R0YAbFPDQ@mail.gmail.com/
was submitted.  But none of us caught it.

Also, gitgitgadget #1156 was opened because of my suggestion to do
this as a "leftoverbit", i.e. I was suggesting it as a micro-project
to new people.  I should have checked at the time that it was a valid
micro-project, but neglected to do so.  You merely came along and
started implementing what was suggested.

Anyway, the point of the GSoC microprojects are to make sure you are
familiar with how to format and submit patches to the mailing list and
respond; having the code you contribute in a microproject be accepted
is not required, just a bonus.  And you clearly managed to send the
patch to the list, had a correctly formatted commit message (short
summary with area and correct lack of capitalization, good
descriptions, signed-off-by), got the additional notes for reviewers
(very helpful!) in the correct spot, etc., so I still see this as a
successful microproject for you.  I apologize for not doing my due
diligence when I suggested it, and for us not catching that it should
have been closed when someone implemented the valid half of the
suggestion last year.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] grep: fall back to interpreter if JIT memory allocation fails
  2023-01-30 20:08  6%               ` Junio C Hamano
@ 2023-01-31  7:30  0%                 ` Mathias Krause
  0 siblings, 0 replies; 200+ results
From: Mathias Krause @ 2023-01-31  7:30 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Ævar Arnfjörð Bjarmason,
	Carlo Marcelo Arenas Belón

On 30.01.23 21:08, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
> 
>> If we were to keep that "die", it is absolutely required, I would
>> think.  Users who got their Git with JIT-enabled pcre2 may be
>> viewing JIT merely as "a clever optimization the implementation is
>> allowed to use when able", without knowing and more importantly
>> without wanting to know how to disable it from within their
>> patterns.
>>
>> But can't we drop that die() if we took the v1 route?
> 
> Having said all that, I do not mind queuing v2 if the "use *NO_JIT
> to disable" is added to the message to help users who are forced to
> redo the query.
> 
> And in practice, it shouldn't make that much difference, because the
> only scenario (other than the SELinux-like situation where JIT is
> compiled in but does not work at all) that the difference may matter
> would happen when a non-trivial portion of the patterns users use
> are not workable with JIT, but if that were the case, we would have
> written JIT off as not mature enough and not yet usable long time
> ago.  So, in practice, patterns refused by JIT would be a very tiny
> minority to matter in real life, and "failing fast to inconvenience
> users" would not be too bad.

Exactly!

> So while I still think v1's simplicity is the right thing to have
> here, I think it is waste of our braincell to compare v1 vs v2.  As
> v2 gives smaller incremental behaviour change perceived by end
> users, if somebody really wanted to, I'd expect that a low-hanging
> fruit #leftoverbit on top of such a patch, after the dust settles,
> would be to
> 
>  (1) rename pcre2_jit_functional() to fall_back_to_interpreter() or
>      something,
> 
>  (2) add a configuration variable to tell fall_back_to_interpreter()
>      that any form of JIT error is allowed to fall back to
>      interpreter().
> 
> and such a patch will essentially give back the simplicity of v1 to
> folks who opt into the configuration.

Fair enough. But aside from the W|X memory allocation denial exception
is the likelihood to run into the limitations of PCRE2's JIT requiring
the interpreter fallback so little (as otherwise we'd see it in the past
already), I think, the demand for such a knob is basically nonexistent.

Thanks,
Mathias

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2] grep: fall back to interpreter if JIT memory allocation fails
  @ 2023-01-30 20:08  6%               ` Junio C Hamano
  2023-01-31  7:30  0%                 ` Mathias Krause
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2023-01-30 20:08 UTC (permalink / raw)
  To: Mathias Krause
  Cc: git, Ævar Arnfjörð Bjarmason,
	Carlo Marcelo Arenas Belón

Junio C Hamano <gitster@pobox.com> writes:

> If we were to keep that "die", it is absolutely required, I would
> think.  Users who got their Git with JIT-enabled pcre2 may be
> viewing JIT merely as "a clever optimization the implementation is
> allowed to use when able", without knowing and more importantly
> without wanting to know how to disable it from within their
> patterns.
>
> But can't we drop that die() if we took the v1 route?

Having said all that, I do not mind queuing v2 if the "use *NO_JIT
to disable" is added to the message to help users who are forced to
redo the query.

And in practice, it shouldn't make that much difference, because the
only scenario (other than the SELinux-like situation where JIT is
compiled in but does not work at all) that the difference may matter
would happen when a non-trivial portion of the patterns users use
are not workable with JIT, but if that were the case, we would have
written JIT off as not mature enough and not yet usable long time
ago.  So, in practice, patterns refused by JIT would be a very tiny
minority to matter in real life, and "failing fast to inconvenience
users" would not be too bad.

So while I still think v1's simplicity is the right thing to have
here, I think it is waste of our braincell to compare v1 vs v2.  As
v2 gives smaller incremental behaviour change perceived by end
users, if somebody really wanted to, I'd expect that a low-hanging
fruit #leftoverbit on top of such a patch, after the dust settles,
would be to

 (1) rename pcre2_jit_functional() to fall_back_to_interpreter() or
     something,

 (2) add a configuration variable to tell fall_back_to_interpreter()
     that any form of JIT error is allowed to fall back to
     interpreter().

and such a patch will essentially give back the simplicity of v1 to
folks who opt into the configuration.

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 3/7] rebase: remove --allow-empty-message from incompatible opts
  @ 2023-01-21 15:09  6%     ` Phillip Wood
  0 siblings, 0 replies; 200+ results
From: Phillip Wood @ 2023-01-21 15:09 UTC (permalink / raw)
  To: Elijah Newren via GitGitGadget, git
  Cc: Derrick Stolee, Elijah Newren, Eric Sunshine, Martin Ågren,
	Phillip Wood

Hi Elijah

On 21/01/2023 01:55, Elijah Newren via GitGitGadget wrote:
> From: Elijah Newren <newren@gmail.com>
> 
> --allow-empty-message was turned into a no-op and even documented
> as such; the flag is simply ignored.  Since the flag is ignored, it
> shouldn't be documented as being incompatible with other flags.

The patch looks fine. Just to note that

#leftoverbits - I notice there is some code in builtin/rebase.c, 
builtin/revert.c and sequencer.[ch] related to this option that could be 
removed. The setting seems to be completely ignored by the sequencer and 
so could be removed from struct replay_opts.

Best Wishes

Phillip

> Signed-off-by: Elijah Newren <newren@gmail.com>
> ---
>   Documentation/git-rebase.txt | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 00d21d7287d..3929535c0cd 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> @@ -640,7 +640,6 @@ are incompatible with the following options:
>    * --merge
>    * --strategy
>    * --strategy-option
> - * --allow-empty-message
>    * --[no-]autosquash
>    * --rebase-merges
>    * --interactive

^ permalink raw reply	[relevance 6%]

* "test_atexit" v.s. "test_when_finished" (was: [PATCH 3/3] t1509: facilitate repeated script invocations)
  @ 2022-12-08 13:14  5%         ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-12-08 13:14 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Eric Sunshine, Eric Sunshine via GitGitGadget, git


On Thu, Dec 08 2022, Johannes Schindelin wrote:

> On Mon, 5 Dec 2022, Eric Sunshine wrote:
>
>> On Mon, Dec 5, 2022 at 9:48 PM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:
>> > On Mon, Nov 21 2022, Eric Sunshine via GitGitGadget wrote:
>>> [...]
>> > This is an existing wart, but I also wondered why the "expected",
>> > "result" etc. was needed. Either we could make the tests creating those
>> > do a "test_when_finished" removal of it, or better yet just create those
>> > in the trash directory.
>
> An even better suggestion would be to use `test_atexit`, of course.

Why?

For assets that are only needed within a given test we prefer cleaning
them up with "test_when_finished", there's legitimate uses for
"test_atexit", but those are for global state.

In this case (and again, we're discussing the #leftoverbits if someone
wants to poke at this again) the tests in question could relatively
easily be changed to do the creation and cleanup of the files that are
"test_cmp"'d (or similar) within the lifetime of individual tests
("test_when_finished"), rather than the lifetime of the script
("test_atexit").

A good reason for why we do it way is that it has a nice interaction
with "--immediate --debug".

On failure we'll skip the cleanup for the current test that just failed,
but we're not distracted by scratch files from earlier tests, those
would have already been cleaned up if they used the same
"test_when_finished" pattern.

If you use "test_atexit" to do that all subsequent tests need to deal
with the sum of your scratch files, until they're cleaned up in one big
operation at the end.

It not only makes that debugging case harder, but also to write tests,
as you'll need to contend with more unwanted global state in your test
playground the further down the test file you are.

So I think what you're recommending here is an anti-pattern for the
common case.

There *are* cases where we really do need the "global cleanup",
e.g. tests that spawn the apache httpd use "test_atexit" rather than
"test_when_finished", we don't want to have to start/stop the httpd for each test.

We should leave "test_atexit" for those sorts of cases, not routine
per-test scratch file creation.

I semi-regularly run into cases where a stale "httpd" is left running in
the background from such tests (and not after I kill -9'd a test), so I
suspect we also have tricky races in that are, that probably aren't
improved by "test_atexit".

^ permalink raw reply	[relevance 5%]

* Re: [PATCH] maintenance: compare output of pthread functions for inequality with 0
  2022-12-02 18:10  6% ` Ævar Arnfjörð Bjarmason
@ 2022-12-02 18:44  0%   ` Jeff Hostetler
  0 siblings, 0 replies; 200+ results
From: Jeff Hostetler @ 2022-12-02 18:44 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, Rose via GitGitGadget; +Cc: git, Seija



On 12/2/22 1:10 PM, Ævar Arnfjörð Bjarmason wrote:
> 
> On Fri, Dec 02 2022, Rose via GitGitGadget wrote:
> 
>> From: Seija <doremylover123@gmail.com>
>>
>> The documentation for pthread_create and pthread_sigmask state that:
>>
>> "On success, pthread_create() returns 0;
>> on error, it returns an error number"
>>
>> As such, we ought to check for an error
>> by seeing if the output is not 0.
>>
>> Checking for "less than" is a mistake
>> as the error code numbers can be greater than 0.
>>
>> Signed-off-by: Seija <doremylover123@gmail.com>
>> ---
>>      maintenance: compare output of pthread functions for inequality with 0
>>      
>>      The documentation for pthread_create and pthread_sigmask state that "On
>>      success, pthread_create() returns 0; on error, it returns an error
>>      number, and the contents of *thread are undefined."
>>      
>>      As such, we ought to check for an error by seeing if the output is not
>>      0, rather than being less than 0, since nothing stops these functions
>>      from returning a positive number.
>>      
>>      Signed-off by: Seija doremylover123@gmail.com
>>
>> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1389%2FAtariDreams%2Faddress-v1
>> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1389/AtariDreams/address-v1
>> Pull-Request: https://github.com/git/git/pull/1389
>>
>>   builtin/fsmonitor--daemon.c | 4 ++--
>>   run-command.c               | 2 +-
>>   2 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
>> index 6f30a4f93a7..52a08bb3b57 100644
>> --- a/builtin/fsmonitor--daemon.c
>> +++ b/builtin/fsmonitor--daemon.c
>> @@ -1209,7 +1209,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
>>   	 * events.
>>   	 */
>>   	if (pthread_create(&state->listener_thread, NULL,
>> -			   fsm_listen__thread_proc, state) < 0) {
>> +			   fsm_listen__thread_proc, state)) {
>>   		ipc_server_stop_async(state->ipc_server_data);
>>   		err = error(_("could not start fsmonitor listener thread"));
>>   		goto cleanup;
>> @@ -1220,7 +1220,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
>>   	 * Start the health thread to watch over our process.
>>   	 */
>>   	if (pthread_create(&state->health_thread, NULL,
>> -			   fsm_health__thread_proc, state) < 0) {
>> +			   fsm_health__thread_proc, state)) {
>>   		ipc_server_stop_async(state->ipc_server_data);
>>   		err = error(_("could not start fsmonitor health thread"));
>>   		goto cleanup;
>> diff --git a/run-command.c b/run-command.c
>> index 48b9ba6d6f0..756f1839aab 100644
>> --- a/run-command.c
>> +++ b/run-command.c
>> @@ -1019,7 +1019,7 @@ static void *run_thread(void *data)
>>   		sigset_t mask;
>>   		sigemptyset(&mask);
>>   		sigaddset(&mask, SIGPIPE);
>> -		if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) {
>> +		if (pthread_sigmask(SIG_BLOCK, &mask, NULL)) {
>>   			ret = error("unable to block SIGPIPE in async thread");
>>   			return (void *)ret;
>>   		}
>>
>> base-commit: 805265fcf7a737664a8321aaf4a0587b78435184
> 
> This looks good to me, and skimming through the rest of the
> pthread_create() it seems the rest of the code in-tree is correct.
> 
> But (and especially if you're interested) we really should follow-up
> here and fix the "error()" etc. part of this. After this we have cases
> in-tree where we on failure:

But to be clear, the pthread_ changes are good by themselves and can
be considered a single task that could be advanced without any
extra stuff.

All of the following, if of interest to you or anyone else, should
be done in one or more separate/later and independent series.

> 
>   * Call die_errno() (good)
>   * Call die(), error() etc., but with a manual strerror() argument,
>     these should just use the *_errno() helper.
>   * Don't report on the errno at all, e.g. in this case shown here.
> 
> It seems to me that all of these should be using die_errno(),
> error_errno() etc.
> 
> Or maybe it's the other way around, and we should not rely on the global
> "errno", but always capture the return value, and give that to
> strerror() (or set "errno = ret", and call {die,error,warning}_errno()).
> 
> In any case, some low-hanging #leftoverbits there...
> 

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] maintenance: compare output of pthread functions for inequality with 0
  @ 2022-12-02 18:10  6% ` Ævar Arnfjörð Bjarmason
  2022-12-02 18:44  0%   ` Jeff Hostetler
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-12-02 18:10 UTC (permalink / raw)
  To: Rose via GitGitGadget; +Cc: git, Seija


On Fri, Dec 02 2022, Rose via GitGitGadget wrote:

> From: Seija <doremylover123@gmail.com>
>
> The documentation for pthread_create and pthread_sigmask state that:
>
> "On success, pthread_create() returns 0;
> on error, it returns an error number"
>
> As such, we ought to check for an error
> by seeing if the output is not 0.
>
> Checking for "less than" is a mistake
> as the error code numbers can be greater than 0.
>
> Signed-off-by: Seija <doremylover123@gmail.com>
> ---
>     maintenance: compare output of pthread functions for inequality with 0
>     
>     The documentation for pthread_create and pthread_sigmask state that "On
>     success, pthread_create() returns 0; on error, it returns an error
>     number, and the contents of *thread are undefined."
>     
>     As such, we ought to check for an error by seeing if the output is not
>     0, rather than being less than 0, since nothing stops these functions
>     from returning a positive number.
>     
>     Signed-off by: Seija doremylover123@gmail.com
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1389%2FAtariDreams%2Faddress-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1389/AtariDreams/address-v1
> Pull-Request: https://github.com/git/git/pull/1389
>
>  builtin/fsmonitor--daemon.c | 4 ++--
>  run-command.c               | 2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
> index 6f30a4f93a7..52a08bb3b57 100644
> --- a/builtin/fsmonitor--daemon.c
> +++ b/builtin/fsmonitor--daemon.c
> @@ -1209,7 +1209,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
>  	 * events.
>  	 */
>  	if (pthread_create(&state->listener_thread, NULL,
> -			   fsm_listen__thread_proc, state) < 0) {
> +			   fsm_listen__thread_proc, state)) {
>  		ipc_server_stop_async(state->ipc_server_data);
>  		err = error(_("could not start fsmonitor listener thread"));
>  		goto cleanup;
> @@ -1220,7 +1220,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
>  	 * Start the health thread to watch over our process.
>  	 */
>  	if (pthread_create(&state->health_thread, NULL,
> -			   fsm_health__thread_proc, state) < 0) {
> +			   fsm_health__thread_proc, state)) {
>  		ipc_server_stop_async(state->ipc_server_data);
>  		err = error(_("could not start fsmonitor health thread"));
>  		goto cleanup;
> diff --git a/run-command.c b/run-command.c
> index 48b9ba6d6f0..756f1839aab 100644
> --- a/run-command.c
> +++ b/run-command.c
> @@ -1019,7 +1019,7 @@ static void *run_thread(void *data)
>  		sigset_t mask;
>  		sigemptyset(&mask);
>  		sigaddset(&mask, SIGPIPE);
> -		if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) {
> +		if (pthread_sigmask(SIG_BLOCK, &mask, NULL)) {
>  			ret = error("unable to block SIGPIPE in async thread");
>  			return (void *)ret;
>  		}
>
> base-commit: 805265fcf7a737664a8321aaf4a0587b78435184

This looks good to me, and skimming through the rest of the
pthread_create() it seems the rest of the code in-tree is correct.

But (and especially if you're interested) we really should follow-up
here and fix the "error()" etc. part of this. After this we have cases
in-tree where we on failure:

 * Call die_errno() (good)
 * Call die(), error() etc., but with a manual strerror() argument,
   these should just use the *_errno() helper.
 * Don't report on the errno at all, e.g. in this case shown here.

It seems to me that all of these should be using die_errno(),
error_errno() etc.

Or maybe it's the other way around, and we should not rely on the global
"errno", but always capture the return value, and give that to
strerror() (or set "errno = ret", and call {die,error,warning}_errno()).

In any case, some low-hanging #leftoverbits there...


^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 7/9] bundle-uri: allow relative URLs in bundle lists
  @ 2022-12-02 16:03  6%       ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-12-02 16:03 UTC (permalink / raw)
  To: Victoria Dye, Derrick Stolee via GitGitGadget, git
  Cc: gitster, me, newren, avarab, mjcheetham, steadmon, chooglen,
	jonathantanmy, dyroneteng

On 11/28/2022 8:25 PM, Victoria Dye wrote:
> Derrick Stolee via GitGitGadget wrote:

>> +	if (!list->baseURI) {
>> +		struct strbuf baseURI = STRBUF_INIT;
>> +		strbuf_addstr(&baseURI, uri);
>> +
>> +		/*
>> +		 * If the URI does not end with a trailing slash, then
>> +		 * remove the filename portion of the path. This is
>> +		 * important for relative URIs.
>> +		 */
>> +		strbuf_strip_file_from_path(&baseURI);
>> +		list->baseURI = strbuf_detach(&baseURI, NULL);
>
> Is the 'baseURI' is set to the URI of the first bundle (ordered by hash)? If
> data is distributed across multiple CDNs, couldn't this be a suboptimal
> choice? For example, if the first bundle is on 'A.com', but every other
> bundle is on 'B.org'?

The baseURI is set to one of two things:

1. The URI used for the clone, specifying the way the client connected to
   the Git server, or

2. The URI used to download the bundle list itself.

This allows the same bundle list file to be distributed to multiple CDNs,
assuming that the bundles themselves will have the same relative position
to the list.

>> +	/**
>> +	 * The baseURI of a bundle_list is used as the base for any
>> +	 * relative URIs advertised by the bundle list at that location.
>> +	 *
>> +	 * When the list is generated from a Git server, then use that
>> +	 * server's location.
>
> Hmmm, I think I'm missing something with my earlier comment. I thought the
> 'uri' argument to 'bundle_uri_parse_config_format()' was an individual
> bundle's URI? What's the "server's location" in this context?

I can work to make this concept clearer by rewording this comment.

>> @@ -40,6 +40,8 @@ static int cmd__bundle_uri_parse(int argc, const char **argv, enum input_mode mo
>>
>>  	init_bundle_list(&list);
>>
>> +	list.baseURI = xstrdup("<uri>");
>
> Using a hardcoded value here leads to pretty different behavior in
> 'test-bundle-uri.c' vs. starting with an unset 'list.baseURI' in something
> like 'clone'. Why does this need to be set to '<uri>' for the tests?

In this part of the test helper, we are not making a connection to a server
and instead parsing a bundle list file directly. To demonstrate how the
relative paths work during this parsing, we add a bogus baseURI here so
we can clearly see where the relative paths were parsed versus using the
URI as an absolute URI.


>> +test_expect_success 'bundle_uri_parse_line(): relative URIs' '
>> +	cat >in <<-\EOF &&
>> +	bundle.one.uri=bundle.bdl
>> +	bundle.two.uri=../bundle.bdl
>> +	bundle.three.uri=sub/dir/bundle.bdl
>> +	EOF
>> +
>> +	cat >expect <<-\EOF &&
>> +	[bundle]
>> +		version = 1
>> +		mode = all
>> +	[bundle "one"]
>> +		uri = <uri>/bundle.bdl
>> +	[bundle "two"]
>> +		uri = bundle.bdl
>
> This seems a little strange, but it looks like '<uri>/../bundle.bdl'
> normalizes to 'bundle.bdl' because '<uri>' is treated like a regular path
> element (like a directory).
>
> Out of curiosity, what would happen if 'bundle.two.uri' was
> '../../bundle.bdl'?

It will fail! The error message is

	"fatal: cannot strip one component off url '.'"

This is disappointing that an erroneous bundle list could cause a 'git
clone' command to die(), when we want the bundle URI feature to allow the
clone to continue normally even if the bundle downloads fail. I will mark
this for #leftoverbits, since it would involve changing the interface for
chop_last_dir() and relative_url() in remote.c.

At minimum, I will document this with a test case.

Thanks,
-Stolee

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] send-email: relay '-v N' to format-patch
  @ 2022-11-28 12:34  6%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-11-28 12:34 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Kyle Meyer, git


On Sun, Nov 27 2022, Junio C Hamano wrote:

> Kyle Meyer <kyle@kyleam.com> writes:
>
>> Here's a patch handling the -v case.  I don't plan on working on a more
>> complete fix for the other cases (as I mentioned before, I don't use
>> send-email to drive format-patch), but in my opinion the -v fix by
>> itself is still valuable.
>
> Yup, I think it is a good place to stop for the first patch.  Other
> people can add more when they discover the need, and anything more
> complex [*] is probably not worth the effort, I would think.
>
>     Side note: [*] we could imagine running "git format-patch -h"
>     (or a new variant of it), parse its output and populate the
>     %options dynamically, for example.
>
> Will queue.  Thanks.

This is just a comment on the #leftoverbits: I've looked at this option
parsing in "git-send-email" before, and IMO the right long-term fix is
to split out the *.perl code into a "git send-email--helper", and do the
option parsing in C using our parse_options().

Some of it will be a bit of a hassle, but it should be much easier after
8de2e2e41b2 (Merge branch 'ab/send-email-optim', 2021-07-22) (and the
subsquent regression fix).



^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 2/2] worktree add: add --orphan flag
  2022-11-19  3:09  0%             ` Jacob Abel
@ 2022-11-19 11:50  0%               ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-11-19 11:50 UTC (permalink / raw)
  To: Jacob Abel; +Cc: Eric Sunshine, git, Taylor Blau


On Sat, Nov 19 2022, Jacob Abel wrote:

> On 22/11/15 11:35PM, Ævar Arnfjörð Bjarmason wrote:
>>
>> On Tue, Nov 15 2022, Eric Sunshine wrote:
>>
>> > On Tue, Nov 15, 2022 at 4:13 PM Ævar Arnfjörð Bjarmason
>> > <avarab@gmail.com> wrote:
>> >> On Thu, Nov 10 2022, Jacob Abel wrote:
>> >> > Adds support for creating an orphan branch when adding a new worktree.
>> >> > This functionality is equivalent to git switch's --orphan flag.
>> >> >
>> >> > The original reason this feature was implemented was to allow a user
>> >> > to initialise a new repository using solely the worktree oriented
>> >> > workflow. Example usage included below.
>> >> >
>> >> > $ GIT_DIR=".git" git init --bare
>> >> > $ git worktree add --orphan master master/
>> >> >
>> >> > Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
>> >> > ---
>> >> > +Create a worktree containing an orphan branch named `<branch>` with a
>> >> > +clean working directory.  See `--orphan` in linkgit:git-switch[1] for
>> >> > +more details.
>> >>
>> >> Seeing as "git switch" is still marked "EXPERIMENTAL", it may be prudent
>> >> in general to avoid linking to it in lieu of "git checkout".
>> >>
>> >> In this case in particular though the "more details" are almost
>> >> completely absent from the "git-switch" docs, and they don't (which is
>> >> their won flaw) link to the more detailed "git-checkout" docs.
>> >>
>> >> But for this patch, it seems much better to link to the "checkout" docs,
>> >> no?
>> >
>> > Sorry, no. The important point here is that the --orphan option being
>> > added to `git worktree add` closely follows the behavior of `git
>> > switch --orphan`, which is quite different from the behavior of `git
>> > checkout --orphan`.
>> >
>> > The `git switch --orphan` documentation doesn't seem particularly
>> > lacking; it correctly describes the (very) simplified behavior of that
>> > command over `git checkout --orphan`. I might agree that there isn't
>> > much reason to link to git-switch for "more details", though, since
>> > there isn't really anything else that needs to be said.
>>
>> Aside from what it says now: 1/2 of what I'm saying is that linking to
>> it while it says it's "EXPERIMENTAL" might be either jumping the gun.
>>
>> Or maybe we should just declare it non-"EXPERIMENTAL", but in any case
>> this unrelated topic might want to avoid that altogether and just link
>> to the "checkout" version.
>>
>> A quick grep of our docs (for linkgit:git-switch) that this would be the
>> first mention outside of user-manual.txt where we link to it when it's
>> not in the context of "checkout or switch", or where we're explaining
>> something switch-specific (i.e. the "suggestDetachingHead" advice).
>>
>> Having said that I don't really care, just a suggestion...
>>
>> > If we did want to say something else here, we might copy one sentence
>> > from the `git checkout --orphan` documentation:
>> >
>> >     The first commit made on this new branch will have no parents and
>> >     it will be the root of a new history totally disconnected from all
>> >     the other branches and commits.
>> >
>> > The same sentence could be added to `git switch --orphan`
>> > documentation, but that's outside the scope of this patch series (thus
>> > can be done later by someone).
>>
>> I think I was partially confused by skimming the SYNOPSIS and thinking
>> this supported <start-point> like checkout, which as I found in
>> https://lore.kernel.org/git/221115.86edu3kfqz.gmgdl@evledraar.gmail.com/
>> just seems to be a missing assertion where we want to die() if that's
>> provided in this mode.
>>
>> What I also found a bit confusing (but maybe it's just me) is that the
>> "with a clean working directory" seemed at first to be drawing a
>> distinction between this behavior and that of "git switch", but from
>> poking at it some more it seems to be expressing "this is like git
>> switch's --orphan" with that.
>>
>> I think instead of "clean working tree" it would be better to talk about
>> "tracked files", as "git switch --orphan" does, which AFAICT is what it
>> means. But then again the reason "switch" does that is because you have
>> *existing* tracked files, which inherently doesn't apply for "worktree".
>>
>> Hrm.
>>
>> So, I guess it depends on your mental model of this operation, but at
>> least I think it's more intuitive to explain it in terms of "git
>> checkout --orphan", not "git switch --orphan". I.e.:
>>
>> 	Create a worktree containing an orphan branch named
>> 	`<branch>`. This works like linkgit:git-checkout[1]'s `--orphan'
>> 	option, except '<start-point>` isn't supported, and the "clear
>> 	the index" doesn't apply (as "worktree add" will always have a
>> 	new index)".
>>
>> Whereas defining this in terms of git-switch's "All tracked files are
>> removed" might just be more confusing. What files? Since it's "worktree
>> add" there weren't any in the first place.
>>
>> Anyway, I don't mind it as it is, but maybe the above write-up helps for
>> #leftoverbits if we ever want to unify these docs. I.e. AFAICT we could:
>>
>>  * Link from git-worktree to git-checkout, saying the above
>>  * Link from git-switch to git-checkout, ditto, but that we also "remove
>>    tracked files [of the current HEAD]".
>
> Apologies for the mistake in the SYNOPSIS. As mentioned in the other replies
> I've updated it as you indicated to correct that.
>
> As for a path forwards on the referencing of either git-checkout or git-switch
> from git-worktree, I think I'm leaning towards Eric's approach (in his reply
> to this message) where we don't reference either and fully outline the
> behavior itself.

Yeah, that makes sense.

>>
>> >> > +test_expect_success '"add" --orphan/-b mutually exclusive' '
>> >> > +     test_must_fail git worktree add --orphan poodle -b poodle bamboo
>> >> > +'
>> >> > +
>> >> > +test_expect_success '"add" --orphan/-B mutually exclusive' '
>> >> > +     test_must_fail git worktree add --orphan poodle -B poodle bamboo
>> >> > +'
>> >> > +
>> >> > +test_expect_success '"add" --orphan/--detach mutually exclusive' '
>> >> > +     test_must_fail git worktree add --orphan poodle --detach bamboo
>> >> > +'
>> >> > +
>> >> > +test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
>> >> > +     test_must_fail git worktree add --orphan poodle --no-checkout bamboo
>> >> > +'
>> >> > +
>> >> > +test_expect_success '"add" -B/--detach mutually exclusive' '
>> >> > +     test_must_fail git worktree add -B poodle --detach bamboo main
>> >> > +'
>> >> > +
>> >>
>> >> This would be much better as a for-loop:
>> >>
>> >> for opt in -b -B ...
>> >> do
>> >>         test_expect_success "...$opt" '<test here, uses $opt>'
>> >> done
>> >>
>> >> Note the ""-quotes for the description, and '' for the test, that's not
>> >> a mistake, we eval() the latter.
>> >
>> > Such a loop would need to be more complex than this, wouldn't it, to
>> > account for all the combinations? I'd normally agree about the loop,
>> > but given that it requires extra complexity, I don't really mind
>> > seeing the individual tests spelled out manually in this case; they're
>> > dead simple to understand as written. I don't feel strongly either
>> > way, but I also don't want to ask for extra work from the patch author
>> > for a subjective change.
>>
>> Yeah, it's probably not worth it. This is partially cleaning up existing
>> tests, but maybe:
>>
>> 	diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
>> 	index 93c340f4aff..5acfd48f418 100755
>> 	--- a/t/t2400-worktree-add.sh
>> 	+++ b/t/t2400-worktree-add.sh
>> 	@@ -298,37 +298,21 @@ test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
>> 	 	test_must_fail git -C mish/mash symbolic-ref HEAD
>> 	 '
>>
>> 	-test_expect_success '"add" -b/-B mutually exclusive' '
>> 	-	test_must_fail git worktree add -b poodle -B poodle bamboo main
>> 	-'
>> 	-
>> 	-test_expect_success '"add" -b/--detach mutually exclusive' '
>> 	-	test_must_fail git worktree add -b poodle --detach bamboo main
>> 	-'
>> 	-
>> 	-test_expect_success '"add" -B/--detach mutually exclusive' '
>> 	-	test_must_fail git worktree add -B poodle --detach bamboo main
>> 	-'
>> 	-
>> 	-test_expect_success '"add" --orphan/-b mutually exclusive' '
>> 	-	test_must_fail git worktree add --orphan poodle -b poodle bamboo
>> 	-'
>> 	-
>> 	-test_expect_success '"add" --orphan/-B mutually exclusive' '
>> 	-	test_must_fail git worktree add --orphan poodle -B poodle bamboo
>> 	-'
>> 	-
>> 	-test_expect_success '"add" --orphan/--detach mutually exclusive' '
>> 	-	test_must_fail git worktree add --orphan poodle --detach bamboo
>> 	-'
>> 	-
>> 	-test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
>> 	-	test_must_fail git worktree add --orphan poodle --no-checkout bamboo
>> 	-'
>> 	-
>> 	-test_expect_success '"add" -B/--detach mutually exclusive' '
>> 	-	test_must_fail git worktree add -B poodle --detach bamboo main
>> 	-'
>> 	+test_wt_add_excl() {
>> 	+	local opts="$@" &&
>> 	+	test_expect_success "'worktree add' with '$opts' has mutually exclusive options" '
>> 	+		test_must_fail git worktree add $opts
>> 	+	'
>> 	+}
>> 	+test_wt_add_excl -b poodle -B poodle bamboo main
>> 	+test_wt_add_excl -b poodle --orphan poodle bamboo
>> 	+test_wt_add_excl -b poodle --detach bamboo main
>> 	+test_wt_add_excl -B poodle --detach bamboo main
>> 	+test_wt_add_excl -B poodle --detach bamboo main
>> 	+test_wt_add_excl -B poodle --orphan poodle bamboo
>> 	+test_wt_add_excl --orphan poodle --detach bamboo
>> 	+test_wt_add_excl --orphan poodle --no-checkout bamboo
>> 	+test_wt_add_excl --orphan poodle bamboo main
>>
>> 	 test_expect_success '"add -B" fails if the branch is checked out' '
>> 	 	git rev-parse newmain >before &&
>>
>> I re-arranged that a bit, but probably not worth a loop. I *did* spot in
>> doing that that if I sort the options I end up with a duplicate test,
>> i.e. we test "-B poodle --detach bamboo main" twice.
>>
>> That seems to be added by mistake in 2/2, i.e. it's the existing test
>> you can see in the diff context, just added at the end.
>
> This is much clearer and more succinct. I've applied this to 2/2 for v4.

Great, nice that it helped!

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v3 2/2] worktree add: add --orphan flag
  2022-11-15 22:35  4%           ` Ævar Arnfjörð Bjarmason
@ 2022-11-19  3:09  0%             ` Jacob Abel
  2022-11-19 11:50  0%               ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 200+ results
From: Jacob Abel @ 2022-11-19  3:09 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Eric Sunshine, git, Taylor Blau

On 22/11/15 11:35PM, Ævar Arnfjörð Bjarmason wrote:
>
> On Tue, Nov 15 2022, Eric Sunshine wrote:
>
> > On Tue, Nov 15, 2022 at 4:13 PM Ævar Arnfjörð Bjarmason
> > <avarab@gmail.com> wrote:
> >> On Thu, Nov 10 2022, Jacob Abel wrote:
> >> > Adds support for creating an orphan branch when adding a new worktree.
> >> > This functionality is equivalent to git switch's --orphan flag.
> >> >
> >> > The original reason this feature was implemented was to allow a user
> >> > to initialise a new repository using solely the worktree oriented
> >> > workflow. Example usage included below.
> >> >
> >> > $ GIT_DIR=".git" git init --bare
> >> > $ git worktree add --orphan master master/
> >> >
> >> > Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
> >> > ---
> >> > +Create a worktree containing an orphan branch named `<branch>` with a
> >> > +clean working directory.  See `--orphan` in linkgit:git-switch[1] for
> >> > +more details.
> >>
> >> Seeing as "git switch" is still marked "EXPERIMENTAL", it may be prudent
> >> in general to avoid linking to it in lieu of "git checkout".
> >>
> >> In this case in particular though the "more details" are almost
> >> completely absent from the "git-switch" docs, and they don't (which is
> >> their won flaw) link to the more detailed "git-checkout" docs.
> >>
> >> But for this patch, it seems much better to link to the "checkout" docs,
> >> no?
> >
> > Sorry, no. The important point here is that the --orphan option being
> > added to `git worktree add` closely follows the behavior of `git
> > switch --orphan`, which is quite different from the behavior of `git
> > checkout --orphan`.
> >
> > The `git switch --orphan` documentation doesn't seem particularly
> > lacking; it correctly describes the (very) simplified behavior of that
> > command over `git checkout --orphan`. I might agree that there isn't
> > much reason to link to git-switch for "more details", though, since
> > there isn't really anything else that needs to be said.
>
> Aside from what it says now: 1/2 of what I'm saying is that linking to
> it while it says it's "EXPERIMENTAL" might be either jumping the gun.
>
> Or maybe we should just declare it non-"EXPERIMENTAL", but in any case
> this unrelated topic might want to avoid that altogether and just link
> to the "checkout" version.
>
> A quick grep of our docs (for linkgit:git-switch) that this would be the
> first mention outside of user-manual.txt where we link to it when it's
> not in the context of "checkout or switch", or where we're explaining
> something switch-specific (i.e. the "suggestDetachingHead" advice).
>
> Having said that I don't really care, just a suggestion...
>
> > If we did want to say something else here, we might copy one sentence
> > from the `git checkout --orphan` documentation:
> >
> >     The first commit made on this new branch will have no parents and
> >     it will be the root of a new history totally disconnected from all
> >     the other branches and commits.
> >
> > The same sentence could be added to `git switch --orphan`
> > documentation, but that's outside the scope of this patch series (thus
> > can be done later by someone).
>
> I think I was partially confused by skimming the SYNOPSIS and thinking
> this supported <start-point> like checkout, which as I found in
> https://lore.kernel.org/git/221115.86edu3kfqz.gmgdl@evledraar.gmail.com/
> just seems to be a missing assertion where we want to die() if that's
> provided in this mode.
>
> What I also found a bit confusing (but maybe it's just me) is that the
> "with a clean working directory" seemed at first to be drawing a
> distinction between this behavior and that of "git switch", but from
> poking at it some more it seems to be expressing "this is like git
> switch's --orphan" with that.
>
> I think instead of "clean working tree" it would be better to talk about
> "tracked files", as "git switch --orphan" does, which AFAICT is what it
> means. But then again the reason "switch" does that is because you have
> *existing* tracked files, which inherently doesn't apply for "worktree".
>
> Hrm.
>
> So, I guess it depends on your mental model of this operation, but at
> least I think it's more intuitive to explain it in terms of "git
> checkout --orphan", not "git switch --orphan". I.e.:
>
> 	Create a worktree containing an orphan branch named
> 	`<branch>`. This works like linkgit:git-checkout[1]'s `--orphan'
> 	option, except '<start-point>` isn't supported, and the "clear
> 	the index" doesn't apply (as "worktree add" will always have a
> 	new index)".
>
> Whereas defining this in terms of git-switch's "All tracked files are
> removed" might just be more confusing. What files? Since it's "worktree
> add" there weren't any in the first place.
>
> Anyway, I don't mind it as it is, but maybe the above write-up helps for
> #leftoverbits if we ever want to unify these docs. I.e. AFAICT we could:
>
>  * Link from git-worktree to git-checkout, saying the above
>  * Link from git-switch to git-checkout, ditto, but that we also "remove
>    tracked files [of the current HEAD]".

Apologies for the mistake in the SYNOPSIS. As mentioned in the other replies
I've updated it as you indicated to correct that.

As for a path forwards on the referencing of either git-checkout or git-switch
from git-worktree, I think I'm leaning towards Eric's approach (in his reply
to this message) where we don't reference either and fully outline the
behavior itself.

>
> >> > +test_expect_success '"add" --orphan/-b mutually exclusive' '
> >> > +     test_must_fail git worktree add --orphan poodle -b poodle bamboo
> >> > +'
> >> > +
> >> > +test_expect_success '"add" --orphan/-B mutually exclusive' '
> >> > +     test_must_fail git worktree add --orphan poodle -B poodle bamboo
> >> > +'
> >> > +
> >> > +test_expect_success '"add" --orphan/--detach mutually exclusive' '
> >> > +     test_must_fail git worktree add --orphan poodle --detach bamboo
> >> > +'
> >> > +
> >> > +test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
> >> > +     test_must_fail git worktree add --orphan poodle --no-checkout bamboo
> >> > +'
> >> > +
> >> > +test_expect_success '"add" -B/--detach mutually exclusive' '
> >> > +     test_must_fail git worktree add -B poodle --detach bamboo main
> >> > +'
> >> > +
> >>
> >> This would be much better as a for-loop:
> >>
> >> for opt in -b -B ...
> >> do
> >>         test_expect_success "...$opt" '<test here, uses $opt>'
> >> done
> >>
> >> Note the ""-quotes for the description, and '' for the test, that's not
> >> a mistake, we eval() the latter.
> >
> > Such a loop would need to be more complex than this, wouldn't it, to
> > account for all the combinations? I'd normally agree about the loop,
> > but given that it requires extra complexity, I don't really mind
> > seeing the individual tests spelled out manually in this case; they're
> > dead simple to understand as written. I don't feel strongly either
> > way, but I also don't want to ask for extra work from the patch author
> > for a subjective change.
>
> Yeah, it's probably not worth it. This is partially cleaning up existing
> tests, but maybe:
>
> 	diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
> 	index 93c340f4aff..5acfd48f418 100755
> 	--- a/t/t2400-worktree-add.sh
> 	+++ b/t/t2400-worktree-add.sh
> 	@@ -298,37 +298,21 @@ test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
> 	 	test_must_fail git -C mish/mash symbolic-ref HEAD
> 	 '
>
> 	-test_expect_success '"add" -b/-B mutually exclusive' '
> 	-	test_must_fail git worktree add -b poodle -B poodle bamboo main
> 	-'
> 	-
> 	-test_expect_success '"add" -b/--detach mutually exclusive' '
> 	-	test_must_fail git worktree add -b poodle --detach bamboo main
> 	-'
> 	-
> 	-test_expect_success '"add" -B/--detach mutually exclusive' '
> 	-	test_must_fail git worktree add -B poodle --detach bamboo main
> 	-'
> 	-
> 	-test_expect_success '"add" --orphan/-b mutually exclusive' '
> 	-	test_must_fail git worktree add --orphan poodle -b poodle bamboo
> 	-'
> 	-
> 	-test_expect_success '"add" --orphan/-B mutually exclusive' '
> 	-	test_must_fail git worktree add --orphan poodle -B poodle bamboo
> 	-'
> 	-
> 	-test_expect_success '"add" --orphan/--detach mutually exclusive' '
> 	-	test_must_fail git worktree add --orphan poodle --detach bamboo
> 	-'
> 	-
> 	-test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
> 	-	test_must_fail git worktree add --orphan poodle --no-checkout bamboo
> 	-'
> 	-
> 	-test_expect_success '"add" -B/--detach mutually exclusive' '
> 	-	test_must_fail git worktree add -B poodle --detach bamboo main
> 	-'
> 	+test_wt_add_excl() {
> 	+	local opts="$@" &&
> 	+	test_expect_success "'worktree add' with '$opts' has mutually exclusive options" '
> 	+		test_must_fail git worktree add $opts
> 	+	'
> 	+}
> 	+test_wt_add_excl -b poodle -B poodle bamboo main
> 	+test_wt_add_excl -b poodle --orphan poodle bamboo
> 	+test_wt_add_excl -b poodle --detach bamboo main
> 	+test_wt_add_excl -B poodle --detach bamboo main
> 	+test_wt_add_excl -B poodle --detach bamboo main
> 	+test_wt_add_excl -B poodle --orphan poodle bamboo
> 	+test_wt_add_excl --orphan poodle --detach bamboo
> 	+test_wt_add_excl --orphan poodle --no-checkout bamboo
> 	+test_wt_add_excl --orphan poodle bamboo main
>
> 	 test_expect_success '"add -B" fails if the branch is checked out' '
> 	 	git rev-parse newmain >before &&
>
> I re-arranged that a bit, but probably not worth a loop. I *did* spot in
> doing that that if I sort the options I end up with a duplicate test,
> i.e. we test "-B poodle --detach bamboo main" twice.
>
> That seems to be added by mistake in 2/2, i.e. it's the existing test
> you can see in the diff context, just added at the end.

This is much clearer and more succinct. I've applied this to 2/2 for v4.


^ permalink raw reply	[relevance 0%]

* Re: [PATCH] builtin/gc.c: fix use-after-free in maintenance_unregister()
  2022-11-16 15:14  6%       ` Ævar Arnfjörð Bjarmason
@ 2022-11-16 20:14  0%         ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2022-11-16 20:14 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Derrick Stolee, Taylor Blau, git, Johannes Schindelin,
	Ronan Pigott, Jeff Hostetler

On Wed, Nov 16, 2022 at 04:14:30PM +0100, Ævar Arnfjörð Bjarmason wrote:
> >> Copying from other zero-initializations of `struct config_set`:
> >>
> >>     $ git grep -oh 'struct config_set.*= {.*' | sort | uniq -c
> >>           3 struct config_set cs = { { 0 } };
> >
> > Yes, without the double braces the compiler will complain on
> > macOS, I believe.
>
> Ah, that was sorted in 54795d37d9e (config.mak.dev: disable suggest
> braces error on old clang versions, 2022-10-10).
>
> It's fine here, we can follow-up for the #leftoverbits of changing those
> some other time.

Thanks for the reference to 54795d37d9e, Ævar.

There are a small handful of these sitting around in our codebase:

    $ git grep '{ { '
    builtin/gc.c:   struct config_set cs = { { 0 } };
    builtin/worktree.c:             struct config_set cs = { { 0 } };
    oidmap.h:#define OIDMAP_INIT { { NULL } }
    oidset.h:#define OIDSET_INIT { { 0 } }
    reftable/stack_test.c:  struct reftable_ref_record refs[2] = { { NULL } };
    reftable/stack_test.c:  struct reftable_log_record logs[2] = { { NULL } };
    reftable/stack_test.c:  struct reftable_ref_record refs[2] = { { NULL } };
    reftable/stack_test.c:  struct reftable_log_record logs[2] = { { NULL } };
    reftable/stack_test.c:  struct reftable_log_record logs[20] = { { NULL } };
    reset.c:        struct tree_desc desc[2] = { { NULL }, { NULL } };
    t/helper/test-ref-store.c:static struct flag_definition empty_flags[] = { { NULL, 0 } };
    worktree.c:     struct config_set cs = { { 0 } };

But I tend to agree that I'm not all that eager to go and change these
for the sake of changing them. I think we can slowly let them age out of
the codebase when we're touching nearby areas in the future.

Thanks,
Taylor

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] builtin/gc.c: fix use-after-free in maintenance_unregister()
  @ 2022-11-16 15:14  6%       ` Ævar Arnfjörð Bjarmason
  2022-11-16 20:14  0%         ` Taylor Blau
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-11-16 15:14 UTC (permalink / raw)
  To: Derrick Stolee; +Cc: Taylor Blau, git, Johannes Schindelin, Ronan Pigott


On Wed, Nov 16 2022, Derrick Stolee wrote:

> On 11/15/22 2:54 PM, Taylor Blau wrote:
>> On Tue, Nov 15, 2022 at 08:41:44PM +0100, Ævar Arnfjörð Bjarmason wrote:
>>>> @@ -1543,6 +1543,7 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
>>>>  	int found = 0;
>>>>  	struct string_list_item *item;
>>>>  	const struct string_list *list;
>>>> +	struct config_set cs = { { 0 } };
>>>
>>> Just "{ 0 }" here instead? I see it may have been copied from some older
>>> pre-image though, and they'll do the same in either case, so it's not
>>> important...
>> 
>> Copying from other zero-initializations of `struct config_set`:
>> 
>>     $ git grep -oh 'struct config_set.*= {.*' | sort | uniq -c
>>           3 struct config_set cs = { { 0 } };
>
> Yes, without the double braces the compiler will complain on
> macOS, I believe.

Ah, that was sorted in 54795d37d9e (config.mak.dev: disable suggest
braces error on old clang versions, 2022-10-10).

It's fine here, we can follow-up for the #leftoverbits of changing those
some other time.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 2/2] worktree add: add --orphan flag
  @ 2022-11-15 22:35  4%           ` Ævar Arnfjörð Bjarmason
  2022-11-19  3:09  0%             ` Jacob Abel
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-11-15 22:35 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Jacob Abel, git, Taylor Blau


On Tue, Nov 15 2022, Eric Sunshine wrote:

> On Tue, Nov 15, 2022 at 4:13 PM Ævar Arnfjörð Bjarmason
> <avarab@gmail.com> wrote:
>> On Thu, Nov 10 2022, Jacob Abel wrote:
>> > Adds support for creating an orphan branch when adding a new worktree.
>> > This functionality is equivalent to git switch's --orphan flag.
>> >
>> > The original reason this feature was implemented was to allow a user
>> > to initialise a new repository using solely the worktree oriented
>> > workflow. Example usage included below.
>> >
>> > $ GIT_DIR=".git" git init --bare
>> > $ git worktree add --orphan master master/
>> >
>> > Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
>> > ---
>> > +Create a worktree containing an orphan branch named `<branch>` with a
>> > +clean working directory.  See `--orphan` in linkgit:git-switch[1] for
>> > +more details.
>>
>> Seeing as "git switch" is still marked "EXPERIMENTAL", it may be prudent
>> in general to avoid linking to it in lieu of "git checkout".
>>
>> In this case in particular though the "more details" are almost
>> completely absent from the "git-switch" docs, and they don't (which is
>> their won flaw) link to the more detailed "git-checkout" docs.
>>
>> But for this patch, it seems much better to link to the "checkout" docs,
>> no?
>
> Sorry, no. The important point here is that the --orphan option being
> added to `git worktree add` closely follows the behavior of `git
> switch --orphan`, which is quite different from the behavior of `git
> checkout --orphan`.
>
> The `git switch --orphan` documentation doesn't seem particularly
> lacking; it correctly describes the (very) simplified behavior of that
> command over `git checkout --orphan`. I might agree that there isn't
> much reason to link to git-switch for "more details", though, since
> there isn't really anything else that needs to be said.

Aside from what it says now: 1/2 of what I'm saying is that linking to
it while it says it's "EXPERIMENTAL" might be either jumping the gun.

Or maybe we should just declare it non-"EXPERIMENTAL", but in any case
this unrelated topic might want to avoid that altogether and just link
to the "checkout" version.

A quick grep of our docs (for linkgit:git-switch) that this would be the
first mention outside of user-manual.txt where we link to it when it's
not in the context of "checkout or switch", or where we're explaining
something switch-specific (i.e. the "suggestDetachingHead" advice).

Having said that I don't really care, just a suggestion...

> If we did want to say something else here, we might copy one sentence
> from the `git checkout --orphan` documentation:
>
>     The first commit made on this new branch will have no parents and
>     it will be the root of a new history totally disconnected from all
>     the other branches and commits.
>
> The same sentence could be added to `git switch --orphan`
> documentation, but that's outside the scope of this patch series (thus
> can be done later by someone).

I think I was partially confused by skimming the SYNOPSIS and thinking
this supported <start-point> like checkout, which as I found in
https://lore.kernel.org/git/221115.86edu3kfqz.gmgdl@evledraar.gmail.com/
just seems to be a missing assertion where we want to die() if that's
provided in this mode.

What I also found a bit confusing (but maybe it's just me) is that the
"with a clean working directory" seemed at first to be drawing a
distinction between this behavior and that of "git switch", but from
poking at it some more it seems to be expressing "this is like git
switch's --orphan" with that.

I think instead of "clean working tree" it would be better to talk about
"tracked files", as "git switch --orphan" does, which AFAICT is what it
means. But then again the reason "switch" does that is because you have
*existing* tracked files, which inherently doesn't apply for "worktree".

Hrm.

So, I guess it depends on your mental model of this operation, but at
least I think it's more intuitive to explain it in terms of "git
checkout --orphan", not "git switch --orphan". I.e.:

	Create a worktree containing an orphan branch named
	`<branch>`. This works like linkgit:git-checkout[1]'s `--orphan'
	option, except '<start-point>` isn't supported, and the "clear
	the index" doesn't apply (as "worktree add" will always have a
	new index)".

Whereas defining this in terms of git-switch's "All tracked files are
removed" might just be more confusing. What files? Since it's "worktree
add" there weren't any in the first place.

Anyway, I don't mind it as it is, but maybe the above write-up helps for
#leftoverbits if we ever want to unify these docs. I.e. AFAICT we could:

 * Link from git-worktree to git-checkout, saying the above
 * Link from git-switch to git-checkout, ditto, but that we also "remove
   tracked files [of the current HEAD]".

>> > +test_expect_success '"add" --orphan/-b mutually exclusive' '
>> > +     test_must_fail git worktree add --orphan poodle -b poodle bamboo
>> > +'
>> > +
>> > +test_expect_success '"add" --orphan/-B mutually exclusive' '
>> > +     test_must_fail git worktree add --orphan poodle -B poodle bamboo
>> > +'
>> > +
>> > +test_expect_success '"add" --orphan/--detach mutually exclusive' '
>> > +     test_must_fail git worktree add --orphan poodle --detach bamboo
>> > +'
>> > +
>> > +test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
>> > +     test_must_fail git worktree add --orphan poodle --no-checkout bamboo
>> > +'
>> > +
>> > +test_expect_success '"add" -B/--detach mutually exclusive' '
>> > +     test_must_fail git worktree add -B poodle --detach bamboo main
>> > +'
>> > +
>>
>> This would be much better as a for-loop:
>>
>> for opt in -b -B ...
>> do
>>         test_expect_success "...$opt" '<test here, uses $opt>'
>> done
>>
>> Note the ""-quotes for the description, and '' for the test, that's not
>> a mistake, we eval() the latter.
>
> Such a loop would need to be more complex than this, wouldn't it, to
> account for all the combinations? I'd normally agree about the loop,
> but given that it requires extra complexity, I don't really mind
> seeing the individual tests spelled out manually in this case; they're
> dead simple to understand as written. I don't feel strongly either
> way, but I also don't want to ask for extra work from the patch author
> for a subjective change.

Yeah, it's probably not worth it. This is partially cleaning up existing
tests, but maybe:
	
	diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
	index 93c340f4aff..5acfd48f418 100755
	--- a/t/t2400-worktree-add.sh
	+++ b/t/t2400-worktree-add.sh
	@@ -298,37 +298,21 @@ test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
	 	test_must_fail git -C mish/mash symbolic-ref HEAD
	 '
	 
	-test_expect_success '"add" -b/-B mutually exclusive' '
	-	test_must_fail git worktree add -b poodle -B poodle bamboo main
	-'
	-
	-test_expect_success '"add" -b/--detach mutually exclusive' '
	-	test_must_fail git worktree add -b poodle --detach bamboo main
	-'
	-
	-test_expect_success '"add" -B/--detach mutually exclusive' '
	-	test_must_fail git worktree add -B poodle --detach bamboo main
	-'
	-
	-test_expect_success '"add" --orphan/-b mutually exclusive' '
	-	test_must_fail git worktree add --orphan poodle -b poodle bamboo
	-'
	-
	-test_expect_success '"add" --orphan/-B mutually exclusive' '
	-	test_must_fail git worktree add --orphan poodle -B poodle bamboo
	-'
	-
	-test_expect_success '"add" --orphan/--detach mutually exclusive' '
	-	test_must_fail git worktree add --orphan poodle --detach bamboo
	-'
	-
	-test_expect_success '"add" --orphan/--no-checkout mutually exclusive' '
	-	test_must_fail git worktree add --orphan poodle --no-checkout bamboo
	-'
	-
	-test_expect_success '"add" -B/--detach mutually exclusive' '
	-	test_must_fail git worktree add -B poodle --detach bamboo main
	-'
	+test_wt_add_excl() {
	+	local opts="$@" &&
	+	test_expect_success "'worktree add' with '$opts' has mutually exclusive options" '
	+		test_must_fail git worktree add $opts
	+	'
	+}
	+test_wt_add_excl -b poodle -B poodle bamboo main
	+test_wt_add_excl -b poodle --orphan poodle bamboo
	+test_wt_add_excl -b poodle --detach bamboo main
	+test_wt_add_excl -B poodle --detach bamboo main
	+test_wt_add_excl -B poodle --detach bamboo main
	+test_wt_add_excl -B poodle --orphan poodle bamboo
	+test_wt_add_excl --orphan poodle --detach bamboo
	+test_wt_add_excl --orphan poodle --no-checkout bamboo
	+test_wt_add_excl --orphan poodle bamboo main
	 
	 test_expect_success '"add -B" fails if the branch is checked out' '
	 	git rev-parse newmain >before &&
	
I re-arranged that a bit, but probably not worth a loop. I *did* spot in
doing that that if I sort the options I end up with a duplicate test,
i.e. we test "-B poodle --detach bamboo main" twice.

That seems to be added by mistake in 2/2, i.e. it's the existing test
you can see in the diff context, just added at the end.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH] builtin/gc.c: fix use-after-free in maintenance_unregister()
  @ 2022-11-15 19:51  6%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-11-15 19:51 UTC (permalink / raw)
  To: Derrick Stolee
  Cc: Taylor Blau, git, git-security, Johannes Schindelin, Ronan Pigott


On Tue, Nov 15 2022, Derrick Stolee wrote:

> On 11/15/2022 1:53 PM, Taylor Blau wrote:
>> While trying to fix a move based on an uninitialized value (along with a
>> declaration after the first statement), be0fd57228
>> (maintenance --unregister: fix uninit'd data use &
>> -Wdeclaration-after-statement, 2022-11-15) unintentionally introduced a
>> use-after-free.
>> 
>> The problem arises when `maintenance_unregister()` sees a non-NULL
>> `config_file` string and thus tries to call
>> git_configset_get_value_multi() to lookup the corresponding values.
>> 
>> We store the result off, and then call git_configset_clear(), which
>> frees the pointer that we just stored. We then try to read that
>> now-freed pointer a few lines below, and there we have our
>> use-after-free:
>
> Makes sense why this needs to be pulled out to a larger scope, but
> also why it's so easy to make this mistake.

Yeah, the config API's full of foot-guns, although here we return a
"const struct string_list *", not a "struct string_list *", so in
retrospect this should be rather obvious...

But still, we should probably as #leftoverbits make it behave
consistently wrt naming. I.e. in this case it's
git_configset_get_value_multi() really behaves like a
git_configset_get_string_tmp(), and there's no equivalent of a
git_configset_get_string() (i.e. xstrdup()'d) for *_multi().

>> +	struct config_set cs = { { 0 } };
>> 
>>  	argc = parse_options(argc, argv, prefix, options,
>>  			     builtin_maintenance_unregister_usage, 0);
>> @@ -1551,12 +1552,9 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
>>  				   options);
>> 
>>  	if (config_file) {
>> -		struct config_set cs;
>> -
>>  		git_configset_init(&cs);
>>  		git_configset_add_file(&cs, config_file);
>>  		list = git_configset_get_value_multi(&cs, key);
>> -		git_configset_clear(&cs);
>
> That the list depends on the configset and not exist as an
> independent entity is non-obvious, but I'm sure is rooted
> in some kind of memory-saving optimization.

Yes, and it's probably worth keeping that, but I haven't benchmarked
etc. This is only a problem in practice if you're constructing your own
configset, e.g. here because we have a custom config file. So for most
users this API is safe in general, i.e. we free() it, but it's the
config that's in "the_repository" normally, so it outlives any "normal"
code.

>>  	} else {
>>  		list = git_config_get_value_multi(key);
>>  	}
>> @@ -1592,6 +1590,7 @@ static int maintenance_unregister(int argc, const char **argv, const char *prefi
>>  		die(_("repository '%s' is not registered"), maintpath);
>>  	}
>> 
>> +	git_configset_clear(&cs);
>>  	free(maintpath);
>>  	return 0;
>>  }
>
> Thanks for drilling down on this. LGTM.

On the related subject of config API foot-guns, it would be great if you
could look over the in-flight series I have to make related parts of the
config API safe by default [1].

8/9 there fixes 6 segfaults, 3 of which are git blame'd to you :), and
9/9 a foot-gun-y interaction with the strvec API, which you'll also
probably find interesting...

1. https://lore.kernel.org/git/cover-v2-0.9-00000000000-20221101T225822Z-avarab@gmail.com/

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v4 8/8] rebase: cleanup action handling
  @ 2022-10-21 17:54  6%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-10-21 17:54 UTC (permalink / raw)
  To: Phillip Wood via GitGitGadget
  Cc: git, Phillip Wood, Christian Couder, Elijah Newren,
	Ævar Arnfjörð Bjarmason, Calvin Wan,
	Emily Shaffer, Glen Choo, Victoria Dye, Phillip Wood

"Phillip Wood via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> Treating the action as a string is a hang over from the scripted
> rebase. The last commit removed the only remaining use of the action
> that required a string so lets convert the other action users to use
> the existing action enum instead. If we ever need the action name as a
> string in the future the action_names array exists exactly for that
> purpose.

Nice.


#leftoverbit

Perhaps a clean-up worth making after the dust settles from this
series would be to use designated initialisers to avoid names and
their string values going out of sync, perhaps like

	static const char *action_names[] = {
		[ACTION_NONE] = "undefined",
		[ACTION_CONTINUE] = "continue",
		...
		[ACTION_SHOW_CURRENT_PATCH] = "show_current_patch",
	};

Unless the final element is something that must stay at the end even
when adding new member to a collection, it is a good idea to keep a
(seemingly unnecessary) comma at the end.  That would make it easier
to add a new member without unnecessary patch noise.


^ permalink raw reply	[relevance 6%]

* Re: [suggestion] Fail cherry-pick if it overwrites untracked files with the matching file names
  @ 2022-10-16  2:07  6%   ` Elijah Newren
  0 siblings, 0 replies; 200+ results
From: Elijah Newren @ 2022-10-16  2:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Rupinderjeet Singh, git

On Sat, Oct 15, 2022 at 12:23 PM Junio C Hamano <gitster@pobox.com> wrote:
[...]
> Files in a working tree controlled by git fall into one of three
> classes.  Tracked files are those that are known to the index and
> appear in "git ls-files" output.  Among the others, ignored files
> are those that .gitignore mechanism says are expendable.  The rest
> are "untracked", possibly containing valuable contents that should
> not be lost as the user may choose to 'git add' them later.
>
> Not just cherry-pick but any merge-related operations, including
> "checkout", follow this semantics.  Untracked files are kept, but
> ignored files are expendable and will be removed if they are in the
> way to complete the operation the user asks.
>
>     $ rm .gitignore
>     $ git checkout master
>     error: The following untracked working tree files would be overwritten by checkout:
>             file
>     Please move or remove them before you switch branches.
>     Aborting
>
>     $ echo file >.gitignore
>     $ git checkout master
>     ... this should succeed, removing "file" whose contents were
>     ... marked expendable.

There is a command line option meant to allow tweaking this behavior:
--[no-]overwrite-ignore.  The default, as Junio explains above, is
--overwrite-ignore.  The --no-overwrite-ignore option works for `git
checkout`.  It also can work for `git merge`, but *only* if the merge
results in a fast-forward.  Although there is code in unpack_trees()
to handle this alternate behavior by just setting a simple flag, we
don't bother setting that flag in most merge paths even when the user
specifies that option.  It was just never hooked up.  And several
other related commands (am, reset, stash, rebase) don't even accept
such a flag even though for consistency they probably should.

I've been meaning to get back to it and hook up this command line flag
for the occasional user that wants this alternative behavior.
However, it's not an issue for me or the direct users I support, and
complaints about this behavior from the community are quite rare too,
so I just haven't been too motivated to work on it.  If someone else
wants to take a stab, it should be pretty easy.  Just grep for
"preserve_ignored.*FIXME".  And maybe read up on these two commits for
context:
    04988c8d18 ("unpack-trees: introduce preserve_ignored to
unpack_trees_options", 2021-09-27)
    1b5f37334a ("Remove ignored files by default when they are in the
way", 2021-09-27)

Maybe I should just tag this as #leftoverbits to see if someone else
picks it up?

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v3 1/3] maintenance: add 'unregister --force'
  @ 2022-09-26 20:49  6%       ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-09-26 20:49 UTC (permalink / raw)
  To: Junio C Hamano, Derrick Stolee via GitGitGadget
  Cc: git, vdye, SZEDER Gábor, Ævar Arnfjörð Bjarmason

On 9/26/2022 3:23 PM, Junio C Hamano wrote:
> "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 
>> @@ -11,7 +11,7 @@ SYNOPSIS
>>  [verse]
>>  'git maintenance' run [<options>]
>>  'git maintenance' start [--scheduler=<scheduler>]
>> -'git maintenance' (stop|register|unregister)
>> +'git maintenance' (stop|register|unregister) [<options>]
> 
> An unrelated tangent, but should register complain when given in a
> repository that is already registered as well?  Just being curious.

Let's leave that as a #leftoverbits and perhaps as something to
consider next to something like 'git maintenance list' to list the
currently-registered repositories.

Thanks,
-Stolee

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] Documentation: add ReviewingGuidelines
  2022-09-19 19:12  3% ` [PATCH v2] " Victoria Dye via GitGitGadget
@ 2022-09-22 13:29  0%   ` Phillip Wood
  0 siblings, 0 replies; 200+ results
From: Phillip Wood @ 2022-09-22 13:29 UTC (permalink / raw)
  To: Victoria Dye via GitGitGadget, git
  Cc: derrickstolee, Johannes.Schindelin, steadmon, chooglen, gitster,
	Victoria Dye, Elijah Newren

Hi Victoria

Thanks for working on this, sorry it has taken me a while to get round 
to looking at it. I think it makes a really useful addition to our 
documentation. I've left a few comments below, the only one I feel 
strongly about is adding something to say what the purpose of the review 
should be and emphasizing positive comments earlier in the document.

On 19/09/2022 20:12, Victoria Dye via GitGitGadget wrote:
> From: Victoria Dye <vdye@github.com>

> diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
> new file mode 100644
> index 00000000000..0e323d54779
> --- /dev/null
> +++ b/Documentation/ReviewingGuidelines.txt
> @@ -0,0 +1,162 @@
> +Reviewing Patches in the Git Project
> +====================================
> +
> +Introduction
> +------------
> +The Git development community is a widely distributed, diverse, ever-changing
> +group of individuals. Asynchronous communication via the Git mailing list poses
> +unique challenges when reviewing or discussing patches. This document contains
> +some guiding principles and helpful tools you can use to make your reviews both
> +more efficient for yourself and more effective for other contributors.
> +
> +Note that none of the recommendations here are binding or in any way a
> +requirement of participation in the Git community. They are provided as a
> +resource to supplement your skills as a contributor.
> +
> +Principles
> +----------
> +
> +Selecting patch(es) to review
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +If you are looking for a patch series in need of review, start by checking
> +latest "What's cooking in git.git" email
> +(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
> +cooking" emails & replies can be found using the query `s:"What's cooking"` on
> +the https://lore.kernel.org/git/[`lore.kernel.org` mailing list archive];
> +alternatively, you can find the contents of the "What's cooking" email tracked
> +in `whats-cooking.txt` on the `todo` branch of Git. Topics tagged with "Needs
> +review" and those in the "[New Topics]" section are typically those that would
> +benefit the most from additional review.
> +
> +Patches can also be searched manually in the mailing list archive using a query
> +like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
> +your expertise or interest.
> +
> +If you've already contributed to Git, you may also be CC'd in another
> +contributor's patch series. These are topics where the author feels that your
> +attention is warranted. This may be because their patch changes something you
> +wrote previously (making you a good judge of whether the new approach does or
> +doesn't work), or because you have the expertise to provide an exceptionally

[optional] Maybe this says something about me, but the use of 
"exceptionally" here feels like it is setting quite high expectations 
for the review. Perhaps we could say "particularly" instead

> +helpful review. There is no requirement to review these patches but, in the
> +spirit of open source collaboration, you should strongly consider doing so.
> +
> +Reviewing patches
> +~~~~~~~~~~~~~~~~~
> +While every contributor takes their own approach to reviewing patches, here are
> +some general pieces of advice to make your reviews as clear and helpful as
> +possible. The advice is broken into two rough categories: high-level reviewing
> +guidance, and concrete tips for interacting with patches on the mailing list.
> +
> +==== High-level guidance

I think it would be worth adding something here (or maybe extending the 
previous paragraph) to state the purpose of the review and emphasize the 
importance of positive comments. Maybe something like this (which is a 
reworked version of your final list item)

The purpose of the review is to provide constructive feedback explaining 
how you think the patch could be improved or in some cases why the patch 
is not suitable for inclusion. As well as pointing out any problems it 
is helpful to provide positive feedback on aspects that you particularly 
liked. You should also feel free to "think outloud" in your review 
describing how you read & understood a complex section of a patch. It is 
also useful to ask questions about anything that confused you

> +- Remember to review the content of commit messages for correctness and clarity,
> +  in addition to the code change in the patch's diff. The commit message of a
> +  patch should accurately and fully explain the code change being made in the
> +  diff.
> +
> +- Reviewing test coverage is an important - but easy to overlook - component of
> +  reviews. A patch's changes may be covered by existing tests, or new tests may
> +  be introduced to exercise new behavior. Checking out a patch or series locally
> +  allows you to manually mutate lines of new & existing tests to verify expected
> +  pass/fail behavior. You can use this information to verify proper coverage or
> +  to suggest additional tests the author could add.
> +
> +- When providing a recommendation, be as clear as possible about whether you
> +  consider it "blocking" (the code would be broken or otherwise made worse if an
> +  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
> +  the recommendation, but acceptance of the series does not require it).
> +  Non-blocking recommendations can be particularly ambiguous when they are
> +  related to - but outside the scope of - a series ("nice-to-have"s), or when
> +  they represent only stylistic differences between the author and reviewer.
> +
> +- When commenting on an issue, try to include suggestions for how the author
> +  could fix it. This not only helps the author to understand and fix the issue,
> +  it also deepens and improves your understanding of the topic.
> +
> +- Reviews do not need to exclusively point out problems. Feel free to "think out
> +  loud" in your review: describe how you read & understood a complex section of
> +  a patch, ask a question about something that confused you, point out something
> +  you found exceptionally well-written, etc. In particular, uplifting feedback
> +  goes a long way towards encouraging contributors to participate more actively
> +  in the Git community.

As I said above I'd like to see this come higher up the list

> +==== Performing your review
> +- Provide your review comments per-patch in a plaintext "Reply-All" email to the
> +  relevant patch. Comments should be made inline, immediately below the relevant
> +  section(s).
> +
> +- You may find that the limited context provided in the patch diff is sometimes
> +  insufficient for a thorough review. In such cases, you can review patches in
> +  your local tree by either applying patches with linkgit:git-am[1] or checking
> +  out the associated branch from https://github.com/gitster/git once the series
> +  is tracked there.
> +
> +- Large, complicated patch diffs are sometimes unavoidable, such as when they
> +  refactor existing code. If you find such a patch difficult to parse, try
> +  reviewing the diff produced with the `--color-moved` and/or
> +  `--ignore-space-change` options.

[optional] --ignore-space-change is quite a blunt instrument, perhaps we 
could suggest using --color-moved-ws=allow-indentation-change which I 
find particularly useful for refactorings. I'd also second Elijah's 
suggestion to mention --color-words for documentation changes.

> +- If a patch is long, you are encouraged to delete parts of it that are
> +  unrelated to your review from the email reply. Make sure to leave enough
> +  context for readers to understand your comments!
> +
> +- If you cannot complete a full review of a series all at once, consider letting
> +  the author know (on- or off-list) if/when you plan to review the rest of the
> +  series.
> +
> +Completing a review
> +~~~~~~~~~~~~~~~~~~~
> +Once each patch of a series is reviewed, the author (and/or other contributors)
> +may discuss the review(s). This may result in no changes being applied, or the
> +author will send a new version of their patch(es).
> +
> +After a series is rerolled in response to your or others' review, make sure to
> +re-review the updates. 

[optional] Maybe add

When re-reviewing the series it is helpful to inspect the range diff to 
see what the author has changed since your last review.

> If you are happy with the state of the patch series,
> +explicitly indicate your approval (typically with a reply to the latest
> +version's cover letter). Optionally, you can let the author know that they can
> +add a "Reviewed-by: <you>" trailer if they resubmit the reviewed patch verbatim
> +in a later iteration of the series.
> +
> +Finally, subsequent "What's cooking" emails may explicitly ask whether a
> +reviewed topic is ready for merging to the `next` branch (typically phrased
> +"Will merge to \'next\'?"). You can help the maintainer and author by responding
> +with a short description of the state of your (and others', if applicable)
> +review, including the links to the relevant thread(s).
> +
> +Terminology
> +-----------
> +nit: ::
> +	Denotes a small issue that should be fixed, such as a typographical error
> +	or mis-alignment of conditions in an `if()` statement.
> +
> +aside: ::
> +optional: ::
> +non-blocking: ::
> +	Indicates to the reader that the following comment should not block the
> +	acceptance of the patch or series. These are typically recommendations
> +	related to code organization & style, or musings about topics related to
> +	the patch in question, but beyond its scope.

[optional] The reference to code style made me wonder if we should add 
something recommending that reviewers refer patch authors to our coding 
guidelines where appropriate.

Thanks again for working on this

Phillip

> +
> +s/<before>/<after>/::
> +	Shorthand for "you wrote <before>, but I think you meant <after>," usually
> +	for misspellings or other typographical errors. The syntax is a reference
> +	to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
> +	`vim`, and `perl`.
> +
> +cover letter::
> +	The "Patch 0" of a multi-patch series. This email describes the
> +	high-level intent and structure of the patch series to readers on the
> +	Git mailing list. It is also where the changelog notes and range-diff of
> +	subsequent versions are provided by the author.
> ++
> +On single-patch submissions, cover letter content is typically not sent as a
> +separate email. Instead, it is inserted between the end of the patch's commit
> +message (after the `---`) and the beginning of the diff.
> +
> +#leftoverbits::
> +  Used by either an author or a reviewer to describe features or suggested
> +  changes that are out-of-scope of a given patch or series, but are relevant
> +  to the topic for the sake of discussion.
> +
> +See Also
> +--------
> +link:MyFirstContribution.html[MyFirstContribution]
> 
> base-commit: 79f2338b3746d23454308648b2491e5beba4beff


^ permalink raw reply	[relevance 0%]

* [PATCH v2] Documentation: add ReviewingGuidelines
  2022-09-09 18:13  4% [PATCH] Documentation: add ReviewingGuidelines Victoria Dye via GitGitGadget
  2022-09-15 23:25  0% ` Josh Steadmon
@ 2022-09-19 19:12  3% ` Victoria Dye via GitGitGadget
  2022-09-22 13:29  0%   ` Phillip Wood
  1 sibling, 1 reply; 200+ results
From: Victoria Dye via GitGitGadget @ 2022-09-19 19:12 UTC (permalink / raw)
  To: git
  Cc: derrickstolee, Johannes.Schindelin, steadmon, chooglen, gitster,
	Victoria Dye, Victoria Dye

From: Victoria Dye <vdye@github.com>

Add a reviewing guidelines document including advice and common terminology
used in Git mailing list reviews. The document is included in the
'TECH_DOCS' list in order to include it in Git's published documentation.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <derrickstolee@github.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Josh Steadmon <steadmon@google.com>
Signed-off-by: Victoria Dye <vdye@github.com>
---
    Documentation: add ReviewingGuidelines
    
    This patch follows up on a discussion a few weeks ago in the Git IRC
    standup [1], where it was mentioned that it would be nice to have
    consistent definitions for common review terminology (like 'nit:'). The
    "ReviewingGuidelines" document created here builds on that idea, as well
    as past discussions around the idea of advice for reviewers (similar to
    the guidelines for new contributors in MyFirstContribution [2]).
    
    The goal of this document is to clarify & standardize some of the more
    niche concepts important to the Git project ("What's cooking" emails,
    terminology), as well as provide general reviewing advice based on my
    observations of effective reviews from others on the mailing list.
    
    One thing that's particularly important to me here is that the advice
    presented here does not gatekeep or otherwise denigrate the personal
    preferences or style of reviewers. With that in mind, one of the things
    I'm looking for in reviews of this document is making sure that the tone
    & content reflect that more positive/encouraging intent. And, of course,
    I'm happy to hear what other tips & terminology people think would be
    helpful to include!
    
    
    Changes since V1
    ================
    
     * Reorganized "Principles" section advice into "High-level guidance"
       and "Performing your review" subsections.
     * Dropped recommendation to comment on cover letter with "LGTM" if you
       have no other recommendations (somewhat redundant with the
       "Completing a review" section, and such comments don't tend to add
       value except when coming from highly-experienced reviewers anyway).
     * Added clarity & modified reasoning for why reviewing CC'd patches is
       helpful.
     * Miscellaneous other revisions recommended by [3].
    
    Thanks!
    
     * Victoria
    
    [1]
    https://colabti.org/irclogger/irclogger_log/git-devel?date=2022-08-29#l53
    [2] https://git-scm.com/docs/MyFirstContribution [3]
    https://lore.kernel.org/git/xmqqwnacibbm.fsf@gitster.g/

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1348%2Fvdye%2Ffeature%2Freviewing-guidelines-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1348/vdye/feature/reviewing-guidelines-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1348

Range-diff vs v1:

 1:  b2ed5641c24 ! 1:  7326058b23a Documentation: add ReviewingGuidelines
     @@ Commit message
      
          Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
          Helped-by: Derrick Stolee <derrickstolee@github.com>
     +    Helped-by: Junio C Hamano <gitster@pobox.com>
     +    Helped-by: Josh Steadmon <steadmon@google.com>
          Signed-off-by: Victoria Dye <vdye@github.com>
      
       ## Documentation/Makefile ##
     @@ Documentation/ReviewingGuidelines.txt (new)
      +latest "What's cooking in git.git" email
      +(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
      +cooking" emails & replies can be found using the query `s:"What's cooking"` on
     -+the mailing list archive; alternatively, you can find the contents of the
     -+"What's cooking" email tracked in `whats-cooking.txt` on the `todo` branch of
     -+Git. Topics tagged with "Needs review" and those in the "[New Topics]" section
     -+are typically those that would benefit the most from additional review.
     ++the https://lore.kernel.org/git/[`lore.kernel.org` mailing list archive];
     ++alternatively, you can find the contents of the "What's cooking" email tracked
     ++in `whats-cooking.txt` on the `todo` branch of Git. Topics tagged with "Needs
     ++review" and those in the "[New Topics]" section are typically those that would
     ++benefit the most from additional review.
      +
      +Patches can also be searched manually in the mailing list archive using a query
      +like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
      +your expertise or interest.
      +
      +If you've already contributed to Git, you may also be CC'd in another
     -+contributor's patch series. These are usually topics where the author feels that
     -+your attention is warranted; this may be due to prior contributions,
     -+demonstrated expertise, and/or interest in related topics. There is no
     -+requirement to review these series, but you may find them easier to review as a
     -+result of your preexisting background knowledge on the topic.
     ++contributor's patch series. These are topics where the author feels that your
     ++attention is warranted. This may be because their patch changes something you
     ++wrote previously (making you a good judge of whether the new approach does or
     ++doesn't work), or because you have the expertise to provide an exceptionally
     ++helpful review. There is no requirement to review these patches but, in the
     ++spirit of open source collaboration, you should strongly consider doing so.
      +
      +Reviewing patches
      +~~~~~~~~~~~~~~~~~
      +While every contributor takes their own approach to reviewing patches, here are
     -+some general pieces of advice to make your reviews to be as clear and helpful as
     -+possible.
     -+
     -+- Provide your review comments per-patch in a plaintext "Reply-All" email to the
     -+  relevant patch. Comments should be made inline, immediately below the relevant
     -+  section(s).
     ++some general pieces of advice to make your reviews as clear and helpful as
     ++possible. The advice is broken into two rough categories: high-level reviewing
     ++guidance, and concrete tips for interacting with patches on the mailing list.
      +
     ++==== High-level guidance
      +- Remember to review the content of commit messages for correctness and clarity,
      +  in addition to the code change in the patch's diff. The commit message of a
      +  patch should accurately and fully explain the code change being made in the
      +  diff.
      +
     -+- You may find that the limited context provided in the patch diff is sometimes
     -+  insufficient for a thorough review. In such cases, you can review patches in
     -+  your local tree by either applying patches with linkgit:git-am[1] or checking
     -+  out the associated branch from https://github.com/gitster/git once the series
     -+  is tracked there.
     -+
     -+- Large, complicated patch diffs are sometimes unavoidable, such as when they
     -+  refactor existing code. If you find such a patch difficult to parse, try
     -+  reviewing the diff produced with the `--color-moved` and/or
     -+  `--ignore-space-change` options.
     -+
      +- Reviewing test coverage is an important - but easy to overlook - component of
      +  reviews. A patch's changes may be covered by existing tests, or new tests may
      +  be introduced to exercise new behavior. Checking out a patch or series locally
     @@ Documentation/ReviewingGuidelines.txt (new)
      +  pass/fail behavior. You can use this information to verify proper coverage or
      +  to suggest additional tests the author could add.
      +
     -+- If a patch is long, you can delete parts of it that are unrelated to your
     -+  review from the email reply. Make sure to leave enough context for readers to
     -+  understand your comments!
     ++- When providing a recommendation, be as clear as possible about whether you
     ++  consider it "blocking" (the code would be broken or otherwise made worse if an
     ++  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
     ++  the recommendation, but acceptance of the series does not require it).
     ++  Non-blocking recommendations can be particularly ambiguous when they are
     ++  related to - but outside the scope of - a series ("nice-to-have"s), or when
     ++  they represent only stylistic differences between the author and reviewer.
      +
     -+- When pointing out an issue, try to include suggestions for how the author
     ++- When commenting on an issue, try to include suggestions for how the author
      +  could fix it. This not only helps the author to understand and fix the issue,
      +  it also deepens and improves your understanding of the topic.
      +
     @@ Documentation/ReviewingGuidelines.txt (new)
      +  goes a long way towards encouraging contributors to participate more actively
      +  in the Git community.
      +
     -+- When providing a recommendation, be as clear as possible about whether you
     -+  consider it "blocking" (the code would be broken or otherwise made worse if an
     -+  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
     -+  the recommendation, but acceptance of the series does not require it).
     -+  Non-blocking recommendations can be particularly ambiguous when they are
     -+  related to - but outside the scope of - a series ("nice-to-have"s), or when
     -+  they represent only stylistic differences between the author and reviewer.
     ++==== Performing your review
     ++- Provide your review comments per-patch in a plaintext "Reply-All" email to the
     ++  relevant patch. Comments should be made inline, immediately below the relevant
     ++  section(s).
     ++
     ++- You may find that the limited context provided in the patch diff is sometimes
     ++  insufficient for a thorough review. In such cases, you can review patches in
     ++  your local tree by either applying patches with linkgit:git-am[1] or checking
     ++  out the associated branch from https://github.com/gitster/git once the series
     ++  is tracked there.
     ++
     ++- Large, complicated patch diffs are sometimes unavoidable, such as when they
     ++  refactor existing code. If you find such a patch difficult to parse, try
     ++  reviewing the diff produced with the `--color-moved` and/or
     ++  `--ignore-space-change` options.
     ++
     ++- If a patch is long, you are encouraged to delete parts of it that are
     ++  unrelated to your review from the email reply. Make sure to leave enough
     ++  context for readers to understand your comments!
      +
      +- If you cannot complete a full review of a series all at once, consider letting
      +  the author know (on- or off-list) if/when you plan to review the rest of the
      +  series.
      +
     -+- If you read and review a series but find nothing that warrants inline
     -+  commentary, reply to the series' cover letter to indicate that you've reviewed
     -+  the changes.
     -+
      +Completing a review
      +~~~~~~~~~~~~~~~~~~~
      +Once each patch of a series is reviewed, the author (and/or other contributors)
     @@ Documentation/ReviewingGuidelines.txt (new)
      +re-review the updates. If you are happy with the state of the patch series,
      +explicitly indicate your approval (typically with a reply to the latest
      +version's cover letter). Optionally, you can let the author know that they can
     -+add a "Reviewed-by: <you>" trailer to subsequent versions of their series.
     ++add a "Reviewed-by: <you>" trailer if they resubmit the reviewed patch verbatim
     ++in a later iteration of the series.
      +
      +Finally, subsequent "What's cooking" emails may explicitly ask whether a
      +reviewed topic is ready for merging to the `next` branch (typically phrased
     -+"Will merge to 'next'?"). You can help the maintainer and author by responding
     ++"Will merge to \'next\'?"). You can help the maintainer and author by responding
      +with a short description of the state of your (and others', if applicable)
     -+review.
     ++review, including the links to the relevant thread(s).
      +
      +Terminology
      +-----------


 Documentation/Makefile                |   1 +
 Documentation/ReviewingGuidelines.txt | 162 ++++++++++++++++++++++++++
 2 files changed, 163 insertions(+)
 create mode 100644 Documentation/ReviewingGuidelines.txt

diff --git a/Documentation/Makefile b/Documentation/Makefile
index bd6b6fcb930..d3a19df8bed 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -101,6 +101,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases
 API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
 SP_ARTICLES += $(API_DOCS)
 
+TECH_DOCS += ReviewingGuidelines
 TECH_DOCS += MyFirstContribution
 TECH_DOCS += MyFirstObjectWalk
 TECH_DOCS += SubmittingPatches
diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
new file mode 100644
index 00000000000..0e323d54779
--- /dev/null
+++ b/Documentation/ReviewingGuidelines.txt
@@ -0,0 +1,162 @@
+Reviewing Patches in the Git Project
+====================================
+
+Introduction
+------------
+The Git development community is a widely distributed, diverse, ever-changing
+group of individuals. Asynchronous communication via the Git mailing list poses
+unique challenges when reviewing or discussing patches. This document contains
+some guiding principles and helpful tools you can use to make your reviews both
+more efficient for yourself and more effective for other contributors.
+
+Note that none of the recommendations here are binding or in any way a
+requirement of participation in the Git community. They are provided as a
+resource to supplement your skills as a contributor.
+
+Principles
+----------
+
+Selecting patch(es) to review
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you are looking for a patch series in need of review, start by checking
+latest "What's cooking in git.git" email
+(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
+cooking" emails & replies can be found using the query `s:"What's cooking"` on
+the https://lore.kernel.org/git/[`lore.kernel.org` mailing list archive];
+alternatively, you can find the contents of the "What's cooking" email tracked
+in `whats-cooking.txt` on the `todo` branch of Git. Topics tagged with "Needs
+review" and those in the "[New Topics]" section are typically those that would
+benefit the most from additional review.
+
+Patches can also be searched manually in the mailing list archive using a query
+like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
+your expertise or interest.
+
+If you've already contributed to Git, you may also be CC'd in another
+contributor's patch series. These are topics where the author feels that your
+attention is warranted. This may be because their patch changes something you
+wrote previously (making you a good judge of whether the new approach does or
+doesn't work), or because you have the expertise to provide an exceptionally
+helpful review. There is no requirement to review these patches but, in the
+spirit of open source collaboration, you should strongly consider doing so.
+
+Reviewing patches
+~~~~~~~~~~~~~~~~~
+While every contributor takes their own approach to reviewing patches, here are
+some general pieces of advice to make your reviews as clear and helpful as
+possible. The advice is broken into two rough categories: high-level reviewing
+guidance, and concrete tips for interacting with patches on the mailing list.
+
+==== High-level guidance
+- Remember to review the content of commit messages for correctness and clarity,
+  in addition to the code change in the patch's diff. The commit message of a
+  patch should accurately and fully explain the code change being made in the
+  diff.
+
+- Reviewing test coverage is an important - but easy to overlook - component of
+  reviews. A patch's changes may be covered by existing tests, or new tests may
+  be introduced to exercise new behavior. Checking out a patch or series locally
+  allows you to manually mutate lines of new & existing tests to verify expected
+  pass/fail behavior. You can use this information to verify proper coverage or
+  to suggest additional tests the author could add.
+
+- When providing a recommendation, be as clear as possible about whether you
+  consider it "blocking" (the code would be broken or otherwise made worse if an
+  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
+  the recommendation, but acceptance of the series does not require it).
+  Non-blocking recommendations can be particularly ambiguous when they are
+  related to - but outside the scope of - a series ("nice-to-have"s), or when
+  they represent only stylistic differences between the author and reviewer.
+
+- When commenting on an issue, try to include suggestions for how the author
+  could fix it. This not only helps the author to understand and fix the issue,
+  it also deepens and improves your understanding of the topic.
+
+- Reviews do not need to exclusively point out problems. Feel free to "think out
+  loud" in your review: describe how you read & understood a complex section of
+  a patch, ask a question about something that confused you, point out something
+  you found exceptionally well-written, etc. In particular, uplifting feedback
+  goes a long way towards encouraging contributors to participate more actively
+  in the Git community.
+
+==== Performing your review
+- Provide your review comments per-patch in a plaintext "Reply-All" email to the
+  relevant patch. Comments should be made inline, immediately below the relevant
+  section(s).
+
+- You may find that the limited context provided in the patch diff is sometimes
+  insufficient for a thorough review. In such cases, you can review patches in
+  your local tree by either applying patches with linkgit:git-am[1] or checking
+  out the associated branch from https://github.com/gitster/git once the series
+  is tracked there.
+
+- Large, complicated patch diffs are sometimes unavoidable, such as when they
+  refactor existing code. If you find such a patch difficult to parse, try
+  reviewing the diff produced with the `--color-moved` and/or
+  `--ignore-space-change` options.
+
+- If a patch is long, you are encouraged to delete parts of it that are
+  unrelated to your review from the email reply. Make sure to leave enough
+  context for readers to understand your comments!
+
+- If you cannot complete a full review of a series all at once, consider letting
+  the author know (on- or off-list) if/when you plan to review the rest of the
+  series.
+
+Completing a review
+~~~~~~~~~~~~~~~~~~~
+Once each patch of a series is reviewed, the author (and/or other contributors)
+may discuss the review(s). This may result in no changes being applied, or the
+author will send a new version of their patch(es).
+
+After a series is rerolled in response to your or others' review, make sure to
+re-review the updates. If you are happy with the state of the patch series,
+explicitly indicate your approval (typically with a reply to the latest
+version's cover letter). Optionally, you can let the author know that they can
+add a "Reviewed-by: <you>" trailer if they resubmit the reviewed patch verbatim
+in a later iteration of the series.
+
+Finally, subsequent "What's cooking" emails may explicitly ask whether a
+reviewed topic is ready for merging to the `next` branch (typically phrased
+"Will merge to \'next\'?"). You can help the maintainer and author by responding
+with a short description of the state of your (and others', if applicable)
+review, including the links to the relevant thread(s).
+
+Terminology
+-----------
+nit: ::
+	Denotes a small issue that should be fixed, such as a typographical error
+	or mis-alignment of conditions in an `if()` statement.
+
+aside: ::
+optional: ::
+non-blocking: ::
+	Indicates to the reader that the following comment should not block the
+	acceptance of the patch or series. These are typically recommendations
+	related to code organization & style, or musings about topics related to
+	the patch in question, but beyond its scope.
+
+s/<before>/<after>/::
+	Shorthand for "you wrote <before>, but I think you meant <after>," usually
+	for misspellings or other typographical errors. The syntax is a reference
+	to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
+	`vim`, and `perl`.
+
+cover letter::
+	The "Patch 0" of a multi-patch series. This email describes the
+	high-level intent and structure of the patch series to readers on the
+	Git mailing list. It is also where the changelog notes and range-diff of
+	subsequent versions are provided by the author.
++
+On single-patch submissions, cover letter content is typically not sent as a
+separate email. Instead, it is inserted between the end of the patch's commit
+message (after the `---`) and the beginning of the diff.
+
+#leftoverbits::
+  Used by either an author or a reviewer to describe features or suggested
+  changes that are out-of-scope of a given patch or series, but are relevant
+  to the topic for the sake of discussion.
+
+See Also
+--------
+link:MyFirstContribution.html[MyFirstContribution]

base-commit: 79f2338b3746d23454308648b2491e5beba4beff
-- 
gitgitgadget

^ permalink raw reply related	[relevance 3%]

* Re: [PATCH] Documentation: add ReviewingGuidelines
  2022-09-15 23:25  0% ` Josh Steadmon
@ 2022-09-19 18:17  0%   ` Glen Choo
  0 siblings, 0 replies; 200+ results
From: Glen Choo @ 2022-09-19 18:17 UTC (permalink / raw)
  To: Josh Steadmon, Victoria Dye via GitGitGadget
  Cc: git, derrickstolee, Johannes.Schindelin, gitster, Victoria Dye

Josh Steadmon <steadmon@google.com> writes:

> I like all the advice here, thanks for the patch!

I agree, I think this doc is a great step forward. Thanks!

>                                                   My only quibble is
> that the items in the "Reviewing patches" section might be worth
> re-ordering based on topic / importance.

I share this preference for organizing around the topic, especially
since it make it easier for us to think about what topics we haven't
adequately addressed. For example, I'm interested in how reviewers can
sustainably review and avoid burnout while still providing the reviews
that the project needs. (Perhaps we could help reviewers figure out when
they've hit the point of diminishing returns in their review?)

Nevertheless, I don't think this should block this patch from getting
merged; I find the doc very helpful as-is.

>
> On 2022.09.09 18:13, Victoria Dye via GitGitGadget wrote:
>> From: Victoria Dye <vdye@github.com>
>> 
>> Add a reviewing guidelines document including advice and common terminology
>> used in Git mailing list reviews. The document is included in the
>> 'TECH_DOCS' list in order to include it in Git's published documentation.
>> 
>> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
>> Helped-by: Derrick Stolee <derrickstolee@github.com>
>> Signed-off-by: Victoria Dye <vdye@github.com>
>> ---
>>     Documentation: add ReviewingGuidelines
>>     
>>     This patch follows up on a discussion a few weeks ago in the Git IRC
>>     standup [1], where it was mentioned that it would be nice to have
>>     consistent definitions for common review terminology (like 'nit:'). The
>>     "ReviewingGuidelines" document created here builds on that idea, as well
>>     as past discussions around the idea of advice for reviewers (similar to
>>     the guidelines for new contributors in MyFirstContribution [2]).
>>     
>>     The goal of this document is to clarify & standardize some of the more
>>     niche concepts important to the Git project ("What's cooking" emails,
>>     terminology), as well as provide general reviewing advice based on my
>>     observations of effective reviews from others on the mailing list.
>>     
>>     One thing that's particularly important to me here is that the advice
>>     presented here does not gatekeep or otherwise denigrate the personal
>>     preferences or style of reviewers. With that in mind, one of the things
>>     I'm looking for in reviews of this document is making sure that the tone
>>     & content reflect that more positive/encouraging intent. And, of course,
>>     I'm happy to hear what other tips & terminology people think would be
>>     helpful to include!
>>     
>>     Thanks!
>>     
>>      * Victoria
>>     
>>     [1]
>>     https://colabti.org/irclogger/irclogger_log/git-devel?date=2022-08-29#l53
>>     [2] https://git-scm.com/docs/MyFirstContribution
>> 
>> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1348%2Fvdye%2Ffeature%2Freviewing-guidelines-v1
>> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1348/vdye/feature/reviewing-guidelines-v1
>> Pull-Request: https://github.com/gitgitgadget/git/pull/1348
>> 
>>  Documentation/Makefile                |   1 +
>>  Documentation/ReviewingGuidelines.txt | 160 ++++++++++++++++++++++++++
>>  2 files changed, 161 insertions(+)
>>  create mode 100644 Documentation/ReviewingGuidelines.txt
>> 
>> diff --git a/Documentation/Makefile b/Documentation/Makefile
>> index bd6b6fcb930..d3a19df8bed 100644
>> --- a/Documentation/Makefile
>> +++ b/Documentation/Makefile
>> @@ -101,6 +101,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases
>>  API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
>>  SP_ARTICLES += $(API_DOCS)
>>  
>> +TECH_DOCS += ReviewingGuidelines
>>  TECH_DOCS += MyFirstContribution
>>  TECH_DOCS += MyFirstObjectWalk
>>  TECH_DOCS += SubmittingPatches
>> diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
>> new file mode 100644
>> index 00000000000..bcc59baf863
>> --- /dev/null
>> +++ b/Documentation/ReviewingGuidelines.txt
>> @@ -0,0 +1,160 @@
>> +Reviewing Patches in the Git Project
>> +====================================
>> +
>> +Introduction
>> +------------
>> +The Git development community is a widely distributed, diverse, ever-changing
>> +group of individuals. Asynchronous communication via the Git mailing list poses
>> +unique challenges when reviewing or discussing patches. This document contains
>> +some guiding principles and helpful tools you can use to make your reviews both
>> +more efficient for yourself and more effective for other contributors.
>> +
>> +Note that none of the recommendations here are binding or in any way a
>> +requirement of participation in the Git community. They are provided as a
>> +resource to supplement your skills as a contributor.
>> +
>> +Principles
>> +----------
>> +
>> +Selecting patch(es) to review
>> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> +If you are looking for a patch series in need of review, start by checking
>> +latest "What's cooking in git.git" email
>> +(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
>> +cooking" emails & replies can be found using the query `s:"What's cooking"` on
>> +the mailing list archive; alternatively, you can find the contents of the
>> +"What's cooking" email tracked in `whats-cooking.txt` on the `todo` branch of
>> +Git. Topics tagged with "Needs review" and those in the "[New Topics]" section
>> +are typically those that would benefit the most from additional review.
>> +
>> +Patches can also be searched manually in the mailing list archive using a query
>> +like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
>> +your expertise or interest.
>> +
>> +If you've already contributed to Git, you may also be CC'd in another
>> +contributor's patch series. These are usually topics where the author feels that
>> +your attention is warranted; this may be due to prior contributions,
>> +demonstrated expertise, and/or interest in related topics. There is no
>> +requirement to review these series, but you may find them easier to review as a
>> +result of your preexisting background knowledge on the topic.
>> +
>> +Reviewing patches
>> +~~~~~~~~~~~~~~~~~
>> +While every contributor takes their own approach to reviewing patches, here are
>> +some general pieces of advice to make your reviews to be as clear and helpful as
>> +possible.
>> +
>> +- Provide your review comments per-patch in a plaintext "Reply-All" email to the
>> +  relevant patch. Comments should be made inline, immediately below the relevant
>> +  section(s).
>> +
>> +- Remember to review the content of commit messages for correctness and clarity,
>> +  in addition to the code change in the patch's diff. The commit message of a
>> +  patch should accurately and fully explain the code change being made in the
>> +  diff.
>> +
>> +- You may find that the limited context provided in the patch diff is sometimes
>> +  insufficient for a thorough review. In such cases, you can review patches in
>> +  your local tree by either applying patches with linkgit:git-am[1] or checking
>> +  out the associated branch from https://github.com/gitster/git once the series
>> +  is tracked there.
>> +
>> +- Large, complicated patch diffs are sometimes unavoidable, such as when they
>> +  refactor existing code. If you find such a patch difficult to parse, try
>> +  reviewing the diff produced with the `--color-moved` and/or
>> +  `--ignore-space-change` options.
>> +
>> +- Reviewing test coverage is an important - but easy to overlook - component of
>> +  reviews. A patch's changes may be covered by existing tests, or new tests may
>> +  be introduced to exercise new behavior. Checking out a patch or series locally
>> +  allows you to manually mutate lines of new & existing tests to verify expected
>> +  pass/fail behavior. You can use this information to verify proper coverage or
>> +  to suggest additional tests the author could add.
>> +
>> +- If a patch is long, you can delete parts of it that are unrelated to your
>> +  review from the email reply. Make sure to leave enough context for readers to
>> +  understand your comments!
>> +
>> +- When pointing out an issue, try to include suggestions for how the author
>> +  could fix it. This not only helps the author to understand and fix the issue,
>> +  it also deepens and improves your understanding of the topic.
>> +
>> +- Reviews do not need to exclusively point out problems. Feel free to "think out
>> +  loud" in your review: describe how you read & understood a complex section of
>> +  a patch, ask a question about something that confused you, point out something
>> +  you found exceptionally well-written, etc. In particular, uplifting feedback
>> +  goes a long way towards encouraging contributors to participate more actively
>> +  in the Git community.
>> +
>> +- When providing a recommendation, be as clear as possible about whether you
>> +  consider it "blocking" (the code would be broken or otherwise made worse if an
>> +  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
>> +  the recommendation, but acceptance of the series does not require it).
>> +  Non-blocking recommendations can be particularly ambiguous when they are
>> +  related to - but outside the scope of - a series ("nice-to-have"s), or when
>> +  they represent only stylistic differences between the author and reviewer.
>> +
>> +- If you cannot complete a full review of a series all at once, consider letting
>> +  the author know (on- or off-list) if/when you plan to review the rest of the
>> +  series.
>> +
>> +- If you read and review a series but find nothing that warrants inline
>> +  commentary, reply to the series' cover letter to indicate that you've reviewed
>> +  the changes.
>> +
>> +Completing a review
>> +~~~~~~~~~~~~~~~~~~~
>> +Once each patch of a series is reviewed, the author (and/or other contributors)
>> +may discuss the review(s). This may result in no changes being applied, or the
>> +author will send a new version of their patch(es).
>> +
>> +After a series is rerolled in response to your or others' review, make sure to
>> +re-review the updates. If you are happy with the state of the patch series,
>> +explicitly indicate your approval (typically with a reply to the latest
>> +version's cover letter). Optionally, you can let the author know that they can
>> +add a "Reviewed-by: <you>" trailer to subsequent versions of their series.
>> +
>> +Finally, subsequent "What's cooking" emails may explicitly ask whether a
>> +reviewed topic is ready for merging to the `next` branch (typically phrased
>> +"Will merge to 'next'?"). You can help the maintainer and author by responding
>> +with a short description of the state of your (and others', if applicable)
>> +review.
>> +
>> +Terminology
>> +-----------
>> +nit: ::
>> +	Denotes a small issue that should be fixed, such as a typographical error
>> +	or mis-alignment of conditions in an `if()` statement.
>> +
>> +aside: ::
>> +optional: ::
>> +non-blocking: ::
>> +	Indicates to the reader that the following comment should not block the
>> +	acceptance of the patch or series. These are typically recommendations
>> +	related to code organization & style, or musings about topics related to
>> +	the patch in question, but beyond its scope.
>> +
>> +s/<before>/<after>/::
>> +	Shorthand for "you wrote <before>, but I think you meant <after>," usually
>> +	for misspellings or other typographical errors. The syntax is a reference
>> +	to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
>> +	`vim`, and `perl`.
>> +
>> +cover letter::
>> +	The "Patch 0" of a multi-patch series. This email describes the
>> +	high-level intent and structure of the patch series to readers on the
>> +	Git mailing list. It is also where the changelog notes and range-diff of
>> +	subsequent versions are provided by the author.
>> ++
>> +On single-patch submissions, cover letter content is typically not sent as a
>> +separate email. Instead, it is inserted between the end of the patch's commit
>> +message (after the `---`) and the beginning of the diff.
>> +
>> +#leftoverbits::
>> +  Used by either an author or a reviewer to describe features or suggested
>> +  changes that are out-of-scope of a given patch or series, but are relevant
>> +  to the topic for the sake of discussion.
>> +
>> +See Also
>> +--------
>> +link:MyFirstContribution.html[MyFirstContribution]
>> 
>> base-commit: 79f2338b3746d23454308648b2491e5beba4beff
>> -- 
>> gitgitgadget

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] Documentation: add ReviewingGuidelines
  2022-09-09 18:13  4% [PATCH] Documentation: add ReviewingGuidelines Victoria Dye via GitGitGadget
@ 2022-09-15 23:25  0% ` Josh Steadmon
  2022-09-19 18:17  0%   ` Glen Choo
  2022-09-19 19:12  3% ` [PATCH v2] " Victoria Dye via GitGitGadget
  1 sibling, 1 reply; 200+ results
From: Josh Steadmon @ 2022-09-15 23:25 UTC (permalink / raw)
  To: Victoria Dye via GitGitGadget
  Cc: git, derrickstolee, Johannes.Schindelin, chooglen, gitster, Victoria Dye

I like all the advice here, thanks for the patch! My only quibble is
that the items in the "Reviewing patches" section might be worth
re-ordering based on topic / importance. For example, I think
"philosophy" items like "patches should include test coverage" is more
important than tips on how to use diff flags, and so it would make sense
to be listed earlier. But this is subjective, and the doc is short so
in practice it probably doesn't matter.

Thanks again!

Reviewed-by: Josh Steadmon <steadmon@google.com>


On 2022.09.09 18:13, Victoria Dye via GitGitGadget wrote:
> From: Victoria Dye <vdye@github.com>
> 
> Add a reviewing guidelines document including advice and common terminology
> used in Git mailing list reviews. The document is included in the
> 'TECH_DOCS' list in order to include it in Git's published documentation.
> 
> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> Helped-by: Derrick Stolee <derrickstolee@github.com>
> Signed-off-by: Victoria Dye <vdye@github.com>
> ---
>     Documentation: add ReviewingGuidelines
>     
>     This patch follows up on a discussion a few weeks ago in the Git IRC
>     standup [1], where it was mentioned that it would be nice to have
>     consistent definitions for common review terminology (like 'nit:'). The
>     "ReviewingGuidelines" document created here builds on that idea, as well
>     as past discussions around the idea of advice for reviewers (similar to
>     the guidelines for new contributors in MyFirstContribution [2]).
>     
>     The goal of this document is to clarify & standardize some of the more
>     niche concepts important to the Git project ("What's cooking" emails,
>     terminology), as well as provide general reviewing advice based on my
>     observations of effective reviews from others on the mailing list.
>     
>     One thing that's particularly important to me here is that the advice
>     presented here does not gatekeep or otherwise denigrate the personal
>     preferences or style of reviewers. With that in mind, one of the things
>     I'm looking for in reviews of this document is making sure that the tone
>     & content reflect that more positive/encouraging intent. And, of course,
>     I'm happy to hear what other tips & terminology people think would be
>     helpful to include!
>     
>     Thanks!
>     
>      * Victoria
>     
>     [1]
>     https://colabti.org/irclogger/irclogger_log/git-devel?date=2022-08-29#l53
>     [2] https://git-scm.com/docs/MyFirstContribution
> 
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1348%2Fvdye%2Ffeature%2Freviewing-guidelines-v1
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1348/vdye/feature/reviewing-guidelines-v1
> Pull-Request: https://github.com/gitgitgadget/git/pull/1348
> 
>  Documentation/Makefile                |   1 +
>  Documentation/ReviewingGuidelines.txt | 160 ++++++++++++++++++++++++++
>  2 files changed, 161 insertions(+)
>  create mode 100644 Documentation/ReviewingGuidelines.txt
> 
> diff --git a/Documentation/Makefile b/Documentation/Makefile
> index bd6b6fcb930..d3a19df8bed 100644
> --- a/Documentation/Makefile
> +++ b/Documentation/Makefile
> @@ -101,6 +101,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases
>  API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
>  SP_ARTICLES += $(API_DOCS)
>  
> +TECH_DOCS += ReviewingGuidelines
>  TECH_DOCS += MyFirstContribution
>  TECH_DOCS += MyFirstObjectWalk
>  TECH_DOCS += SubmittingPatches
> diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
> new file mode 100644
> index 00000000000..bcc59baf863
> --- /dev/null
> +++ b/Documentation/ReviewingGuidelines.txt
> @@ -0,0 +1,160 @@
> +Reviewing Patches in the Git Project
> +====================================
> +
> +Introduction
> +------------
> +The Git development community is a widely distributed, diverse, ever-changing
> +group of individuals. Asynchronous communication via the Git mailing list poses
> +unique challenges when reviewing or discussing patches. This document contains
> +some guiding principles and helpful tools you can use to make your reviews both
> +more efficient for yourself and more effective for other contributors.
> +
> +Note that none of the recommendations here are binding or in any way a
> +requirement of participation in the Git community. They are provided as a
> +resource to supplement your skills as a contributor.
> +
> +Principles
> +----------
> +
> +Selecting patch(es) to review
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +If you are looking for a patch series in need of review, start by checking
> +latest "What's cooking in git.git" email
> +(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
> +cooking" emails & replies can be found using the query `s:"What's cooking"` on
> +the mailing list archive; alternatively, you can find the contents of the
> +"What's cooking" email tracked in `whats-cooking.txt` on the `todo` branch of
> +Git. Topics tagged with "Needs review" and those in the "[New Topics]" section
> +are typically those that would benefit the most from additional review.
> +
> +Patches can also be searched manually in the mailing list archive using a query
> +like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
> +your expertise or interest.
> +
> +If you've already contributed to Git, you may also be CC'd in another
> +contributor's patch series. These are usually topics where the author feels that
> +your attention is warranted; this may be due to prior contributions,
> +demonstrated expertise, and/or interest in related topics. There is no
> +requirement to review these series, but you may find them easier to review as a
> +result of your preexisting background knowledge on the topic.
> +
> +Reviewing patches
> +~~~~~~~~~~~~~~~~~
> +While every contributor takes their own approach to reviewing patches, here are
> +some general pieces of advice to make your reviews to be as clear and helpful as
> +possible.
> +
> +- Provide your review comments per-patch in a plaintext "Reply-All" email to the
> +  relevant patch. Comments should be made inline, immediately below the relevant
> +  section(s).
> +
> +- Remember to review the content of commit messages for correctness and clarity,
> +  in addition to the code change in the patch's diff. The commit message of a
> +  patch should accurately and fully explain the code change being made in the
> +  diff.
> +
> +- You may find that the limited context provided in the patch diff is sometimes
> +  insufficient for a thorough review. In such cases, you can review patches in
> +  your local tree by either applying patches with linkgit:git-am[1] or checking
> +  out the associated branch from https://github.com/gitster/git once the series
> +  is tracked there.
> +
> +- Large, complicated patch diffs are sometimes unavoidable, such as when they
> +  refactor existing code. If you find such a patch difficult to parse, try
> +  reviewing the diff produced with the `--color-moved` and/or
> +  `--ignore-space-change` options.
> +
> +- Reviewing test coverage is an important - but easy to overlook - component of
> +  reviews. A patch's changes may be covered by existing tests, or new tests may
> +  be introduced to exercise new behavior. Checking out a patch or series locally
> +  allows you to manually mutate lines of new & existing tests to verify expected
> +  pass/fail behavior. You can use this information to verify proper coverage or
> +  to suggest additional tests the author could add.
> +
> +- If a patch is long, you can delete parts of it that are unrelated to your
> +  review from the email reply. Make sure to leave enough context for readers to
> +  understand your comments!
> +
> +- When pointing out an issue, try to include suggestions for how the author
> +  could fix it. This not only helps the author to understand and fix the issue,
> +  it also deepens and improves your understanding of the topic.
> +
> +- Reviews do not need to exclusively point out problems. Feel free to "think out
> +  loud" in your review: describe how you read & understood a complex section of
> +  a patch, ask a question about something that confused you, point out something
> +  you found exceptionally well-written, etc. In particular, uplifting feedback
> +  goes a long way towards encouraging contributors to participate more actively
> +  in the Git community.
> +
> +- When providing a recommendation, be as clear as possible about whether you
> +  consider it "blocking" (the code would be broken or otherwise made worse if an
> +  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
> +  the recommendation, but acceptance of the series does not require it).
> +  Non-blocking recommendations can be particularly ambiguous when they are
> +  related to - but outside the scope of - a series ("nice-to-have"s), or when
> +  they represent only stylistic differences between the author and reviewer.
> +
> +- If you cannot complete a full review of a series all at once, consider letting
> +  the author know (on- or off-list) if/when you plan to review the rest of the
> +  series.
> +
> +- If you read and review a series but find nothing that warrants inline
> +  commentary, reply to the series' cover letter to indicate that you've reviewed
> +  the changes.
> +
> +Completing a review
> +~~~~~~~~~~~~~~~~~~~
> +Once each patch of a series is reviewed, the author (and/or other contributors)
> +may discuss the review(s). This may result in no changes being applied, or the
> +author will send a new version of their patch(es).
> +
> +After a series is rerolled in response to your or others' review, make sure to
> +re-review the updates. If you are happy with the state of the patch series,
> +explicitly indicate your approval (typically with a reply to the latest
> +version's cover letter). Optionally, you can let the author know that they can
> +add a "Reviewed-by: <you>" trailer to subsequent versions of their series.
> +
> +Finally, subsequent "What's cooking" emails may explicitly ask whether a
> +reviewed topic is ready for merging to the `next` branch (typically phrased
> +"Will merge to 'next'?"). You can help the maintainer and author by responding
> +with a short description of the state of your (and others', if applicable)
> +review.
> +
> +Terminology
> +-----------
> +nit: ::
> +	Denotes a small issue that should be fixed, such as a typographical error
> +	or mis-alignment of conditions in an `if()` statement.
> +
> +aside: ::
> +optional: ::
> +non-blocking: ::
> +	Indicates to the reader that the following comment should not block the
> +	acceptance of the patch or series. These are typically recommendations
> +	related to code organization & style, or musings about topics related to
> +	the patch in question, but beyond its scope.
> +
> +s/<before>/<after>/::
> +	Shorthand for "you wrote <before>, but I think you meant <after>," usually
> +	for misspellings or other typographical errors. The syntax is a reference
> +	to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
> +	`vim`, and `perl`.
> +
> +cover letter::
> +	The "Patch 0" of a multi-patch series. This email describes the
> +	high-level intent and structure of the patch series to readers on the
> +	Git mailing list. It is also where the changelog notes and range-diff of
> +	subsequent versions are provided by the author.
> ++
> +On single-patch submissions, cover letter content is typically not sent as a
> +separate email. Instead, it is inserted between the end of the patch's commit
> +message (after the `---`) and the beginning of the diff.
> +
> +#leftoverbits::
> +  Used by either an author or a reviewer to describe features or suggested
> +  changes that are out-of-scope of a given patch or series, but are relevant
> +  to the topic for the sake of discussion.
> +
> +See Also
> +--------
> +link:MyFirstContribution.html[MyFirstContribution]
> 
> base-commit: 79f2338b3746d23454308648b2491e5beba4beff
> -- 
> gitgitgadget

^ permalink raw reply	[relevance 0%]

* [PATCH] Documentation: add ReviewingGuidelines
@ 2022-09-09 18:13  4% Victoria Dye via GitGitGadget
  2022-09-15 23:25  0% ` Josh Steadmon
  2022-09-19 19:12  3% ` [PATCH v2] " Victoria Dye via GitGitGadget
  0 siblings, 2 replies; 200+ results
From: Victoria Dye via GitGitGadget @ 2022-09-09 18:13 UTC (permalink / raw)
  To: git
  Cc: derrickstolee, Johannes.Schindelin, steadmon, chooglen, gitster,
	Victoria Dye, Victoria Dye

From: Victoria Dye <vdye@github.com>

Add a reviewing guidelines document including advice and common terminology
used in Git mailing list reviews. The document is included in the
'TECH_DOCS' list in order to include it in Git's published documentation.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Helped-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Victoria Dye <vdye@github.com>
---
    Documentation: add ReviewingGuidelines
    
    This patch follows up on a discussion a few weeks ago in the Git IRC
    standup [1], where it was mentioned that it would be nice to have
    consistent definitions for common review terminology (like 'nit:'). The
    "ReviewingGuidelines" document created here builds on that idea, as well
    as past discussions around the idea of advice for reviewers (similar to
    the guidelines for new contributors in MyFirstContribution [2]).
    
    The goal of this document is to clarify & standardize some of the more
    niche concepts important to the Git project ("What's cooking" emails,
    terminology), as well as provide general reviewing advice based on my
    observations of effective reviews from others on the mailing list.
    
    One thing that's particularly important to me here is that the advice
    presented here does not gatekeep or otherwise denigrate the personal
    preferences or style of reviewers. With that in mind, one of the things
    I'm looking for in reviews of this document is making sure that the tone
    & content reflect that more positive/encouraging intent. And, of course,
    I'm happy to hear what other tips & terminology people think would be
    helpful to include!
    
    Thanks!
    
     * Victoria
    
    [1]
    https://colabti.org/irclogger/irclogger_log/git-devel?date=2022-08-29#l53
    [2] https://git-scm.com/docs/MyFirstContribution

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1348%2Fvdye%2Ffeature%2Freviewing-guidelines-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1348/vdye/feature/reviewing-guidelines-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1348

 Documentation/Makefile                |   1 +
 Documentation/ReviewingGuidelines.txt | 160 ++++++++++++++++++++++++++
 2 files changed, 161 insertions(+)
 create mode 100644 Documentation/ReviewingGuidelines.txt

diff --git a/Documentation/Makefile b/Documentation/Makefile
index bd6b6fcb930..d3a19df8bed 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -101,6 +101,7 @@ SP_ARTICLES += howto/coordinate-embargoed-releases
 API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
 SP_ARTICLES += $(API_DOCS)
 
+TECH_DOCS += ReviewingGuidelines
 TECH_DOCS += MyFirstContribution
 TECH_DOCS += MyFirstObjectWalk
 TECH_DOCS += SubmittingPatches
diff --git a/Documentation/ReviewingGuidelines.txt b/Documentation/ReviewingGuidelines.txt
new file mode 100644
index 00000000000..bcc59baf863
--- /dev/null
+++ b/Documentation/ReviewingGuidelines.txt
@@ -0,0 +1,160 @@
+Reviewing Patches in the Git Project
+====================================
+
+Introduction
+------------
+The Git development community is a widely distributed, diverse, ever-changing
+group of individuals. Asynchronous communication via the Git mailing list poses
+unique challenges when reviewing or discussing patches. This document contains
+some guiding principles and helpful tools you can use to make your reviews both
+more efficient for yourself and more effective for other contributors.
+
+Note that none of the recommendations here are binding or in any way a
+requirement of participation in the Git community. They are provided as a
+resource to supplement your skills as a contributor.
+
+Principles
+----------
+
+Selecting patch(es) to review
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you are looking for a patch series in need of review, start by checking
+latest "What's cooking in git.git" email
+(https://lore.kernel.org/git/xmqqilm1yp3m.fsf@gitster.g/[example]). The "What's
+cooking" emails & replies can be found using the query `s:"What's cooking"` on
+the mailing list archive; alternatively, you can find the contents of the
+"What's cooking" email tracked in `whats-cooking.txt` on the `todo` branch of
+Git. Topics tagged with "Needs review" and those in the "[New Topics]" section
+are typically those that would benefit the most from additional review.
+
+Patches can also be searched manually in the mailing list archive using a query
+like `s:"PATCH" -s:"Re:"`. You can browse these results for topics relevant to
+your expertise or interest.
+
+If you've already contributed to Git, you may also be CC'd in another
+contributor's patch series. These are usually topics where the author feels that
+your attention is warranted; this may be due to prior contributions,
+demonstrated expertise, and/or interest in related topics. There is no
+requirement to review these series, but you may find them easier to review as a
+result of your preexisting background knowledge on the topic.
+
+Reviewing patches
+~~~~~~~~~~~~~~~~~
+While every contributor takes their own approach to reviewing patches, here are
+some general pieces of advice to make your reviews to be as clear and helpful as
+possible.
+
+- Provide your review comments per-patch in a plaintext "Reply-All" email to the
+  relevant patch. Comments should be made inline, immediately below the relevant
+  section(s).
+
+- Remember to review the content of commit messages for correctness and clarity,
+  in addition to the code change in the patch's diff. The commit message of a
+  patch should accurately and fully explain the code change being made in the
+  diff.
+
+- You may find that the limited context provided in the patch diff is sometimes
+  insufficient for a thorough review. In such cases, you can review patches in
+  your local tree by either applying patches with linkgit:git-am[1] or checking
+  out the associated branch from https://github.com/gitster/git once the series
+  is tracked there.
+
+- Large, complicated patch diffs are sometimes unavoidable, such as when they
+  refactor existing code. If you find such a patch difficult to parse, try
+  reviewing the diff produced with the `--color-moved` and/or
+  `--ignore-space-change` options.
+
+- Reviewing test coverage is an important - but easy to overlook - component of
+  reviews. A patch's changes may be covered by existing tests, or new tests may
+  be introduced to exercise new behavior. Checking out a patch or series locally
+  allows you to manually mutate lines of new & existing tests to verify expected
+  pass/fail behavior. You can use this information to verify proper coverage or
+  to suggest additional tests the author could add.
+
+- If a patch is long, you can delete parts of it that are unrelated to your
+  review from the email reply. Make sure to leave enough context for readers to
+  understand your comments!
+
+- When pointing out an issue, try to include suggestions for how the author
+  could fix it. This not only helps the author to understand and fix the issue,
+  it also deepens and improves your understanding of the topic.
+
+- Reviews do not need to exclusively point out problems. Feel free to "think out
+  loud" in your review: describe how you read & understood a complex section of
+  a patch, ask a question about something that confused you, point out something
+  you found exceptionally well-written, etc. In particular, uplifting feedback
+  goes a long way towards encouraging contributors to participate more actively
+  in the Git community.
+
+- When providing a recommendation, be as clear as possible about whether you
+  consider it "blocking" (the code would be broken or otherwise made worse if an
+  issue isn't fixed) or "non-blocking" (the patch could be made better by taking
+  the recommendation, but acceptance of the series does not require it).
+  Non-blocking recommendations can be particularly ambiguous when they are
+  related to - but outside the scope of - a series ("nice-to-have"s), or when
+  they represent only stylistic differences between the author and reviewer.
+
+- If you cannot complete a full review of a series all at once, consider letting
+  the author know (on- or off-list) if/when you plan to review the rest of the
+  series.
+
+- If you read and review a series but find nothing that warrants inline
+  commentary, reply to the series' cover letter to indicate that you've reviewed
+  the changes.
+
+Completing a review
+~~~~~~~~~~~~~~~~~~~
+Once each patch of a series is reviewed, the author (and/or other contributors)
+may discuss the review(s). This may result in no changes being applied, or the
+author will send a new version of their patch(es).
+
+After a series is rerolled in response to your or others' review, make sure to
+re-review the updates. If you are happy with the state of the patch series,
+explicitly indicate your approval (typically with a reply to the latest
+version's cover letter). Optionally, you can let the author know that they can
+add a "Reviewed-by: <you>" trailer to subsequent versions of their series.
+
+Finally, subsequent "What's cooking" emails may explicitly ask whether a
+reviewed topic is ready for merging to the `next` branch (typically phrased
+"Will merge to 'next'?"). You can help the maintainer and author by responding
+with a short description of the state of your (and others', if applicable)
+review.
+
+Terminology
+-----------
+nit: ::
+	Denotes a small issue that should be fixed, such as a typographical error
+	or mis-alignment of conditions in an `if()` statement.
+
+aside: ::
+optional: ::
+non-blocking: ::
+	Indicates to the reader that the following comment should not block the
+	acceptance of the patch or series. These are typically recommendations
+	related to code organization & style, or musings about topics related to
+	the patch in question, but beyond its scope.
+
+s/<before>/<after>/::
+	Shorthand for "you wrote <before>, but I think you meant <after>," usually
+	for misspellings or other typographical errors. The syntax is a reference
+	to "substitute" command commonly found in Unix tools such as `ed`, `sed`,
+	`vim`, and `perl`.
+
+cover letter::
+	The "Patch 0" of a multi-patch series. This email describes the
+	high-level intent and structure of the patch series to readers on the
+	Git mailing list. It is also where the changelog notes and range-diff of
+	subsequent versions are provided by the author.
++
+On single-patch submissions, cover letter content is typically not sent as a
+separate email. Instead, it is inserted between the end of the patch's commit
+message (after the `---`) and the beginning of the diff.
+
+#leftoverbits::
+  Used by either an author or a reviewer to describe features or suggested
+  changes that are out-of-scope of a given patch or series, but are relevant
+  to the topic for the sake of discussion.
+
+See Also
+--------
+link:MyFirstContribution.html[MyFirstContribution]

base-commit: 79f2338b3746d23454308648b2491e5beba4beff
-- 
gitgitgadget

^ permalink raw reply related	[relevance 4%]

* Re: [PATCH v3 2/2] diff.c: More changes and tests around utf8_strwidth()
  @ 2022-09-02 10:12  5%   ` Johannes Schindelin
  0 siblings, 0 replies; 200+ results
From: Johannes Schindelin @ 2022-09-02 10:12 UTC (permalink / raw)
  To: Torsten Bögershausen; +Cc: git, alexander.s.m

Hi Torsten,

On Fri, 2 Sep 2022, tboegi@web.de wrote:

> diff --git a/diff.c b/diff.c
> index b5df464de5..cf38e1dc88 100644
> --- a/diff.c
> +++ b/diff.c
> [...]
> @@ -2753,10 +2754,14 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>  			if (slash)
>  				name = slash;
>  		}
> +		if (len > utf8_strwidth(name))
> +			num_padding_spaces = len - utf8_strwidth(name);

Here, we determine how many spaces are needed for padding. The value is
later used in three instances, and from the diff it is not immediately
obvious that all code paths are covered. I did verify locally that this is
the case, though, so all is good.

>
>  		if (file->is_binary) {
> -			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> -			strbuf_addf(&out, " %*s", number_width, "Bin");

This was already a bit wasteful by calling `strbuf_addf()` twice, where
one time would have sufficed. (This applies to the other two code paths
below, too.)

> +			strbuf_addf(&out, " %s%s ", prefix,  name);
> +			if (num_padding_spaces)
> +				strbuf_addchars(&out, ' ', num_padding_spaces);
> +			strbuf_addf(&out, "| %*s", number_width, "Bin");

Instead of fixing this, we now add yet another `strbuf*()` call.

But this could be done more elegantly, via a single `strbuf_addf()` call:

			strbuf_addf(&out, "%s%s%*s | %*s",
				    prefix, name, num_padding_spaces, "",
				    number_width, "Bin");

By the way, it would flow much better, I think, if we used the
short-and-sweet variable name `padding` instead of `num_padding_spaces`.

>  			if (!added && !deleted) {
>  				strbuf_addch(&out, '\n');
>  				emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
> @@ -2776,8 +2781,10 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>  			continue;
>  		}
>  		else if (file->is_unmerged) {
> -			strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> -			strbuf_addstr(&out, " Unmerged\n");
> +			strbuf_addf(&out, " %s%s ", prefix,  name);
> +			if (num_padding_spaces)
> +				strbuf_addchars(&out, ' ', num_padding_spaces);
> +			strbuf_addstr(&out, "| Unmerged\n");

This can become

			strbuf_addf(&out, " %s%s%*s | Unmerged",
				    prefix, name, padding, "");

instead.

>  			emit_diff_symbol(options, DIFF_SYMBOL_STATS_LINE,
>  					 out.buf, out.len, 0);
>  			strbuf_reset(&out);
> @@ -2803,8 +2810,10 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>  				add = total - del;
>  			}
>  		}
> -		strbuf_addf(&out, " %s%-*s |", prefix, len, name);
> -		strbuf_addf(&out, " %*"PRIuMAX"%s",
> +		strbuf_addf(&out, " %s%s ", prefix,  name);
> +		if (num_padding_spaces)
> +			strbuf_addchars(&out, ' ', num_padding_spaces);
> +		strbuf_addf(&out, "| %*"PRIuMAX"%s",
>  			number_width, added + deleted,
>  			added + deleted ? " " : "");

And this reads better as

		strbuf_addf(&out, " %s%s%*s | %*"PRIuMAX"%s",
			    prefix, name, padding, "",
			    number_width, added + deleted,
			    added + deleted ? " " : "");

If we modify the code in this manner, we avoid repeating a pretty
unreadable pattern three times, using a much more readable pattern
instead.

Random note: The existing code (not your fault) is hard to follow because
it calls `show_graph()` for `add` and `del` always, even if their counts
are zero (in which case `show_graph()` returns early), while the
separating space is appended in the otherwise unrelated `strbuf_addf()`
call before that, but uses the (unscaled) `added + deleted` as condition
for that separator. It would be much easier to follow like this:

		strbuf_addf(&out, " %s%s%*s | %*"PRIuMAX",
			    prefix, name, padding, "",
			    number_width, added + deleted);

		if (add || del) {
			strbuf_addch(&out, ' ');
			show_graph(&out, '+', add, add_c, reset);
			show_graph(&out, '-', del, del_c, reset);
		}

But I consider this #leftoverbits, not something to burden your
contribution with.

Ciao,
Dscho

>  		show_graph(&out, '+', add, add_c, reset);

^ permalink raw reply	[relevance 5%]

* Re: [PATCH] is_promisor_object(): fix use-after-free of tree buffer
  @ 2022-08-15 22:53  6%       ` Jeff King
  0 siblings, 0 replies; 200+ results
From: Jeff King @ 2022-08-15 22:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Andrew Olsen, Jonathan Tan, git

On Sun, Aug 14, 2022 at 10:32:12PM -0700, Junio C Hamano wrote:

> > We're in the middle of walking through the entries of a tree object via
> > process_tree_contents(). We see a blob (or it could even be another tree
> > entry) that we don't have, so we call is_promisor_object() to check it.
> > That function loops over all of the objects in the promisor packfile,
> > including the tree we're currently walking.
> 
> I forgot that the above "loops over" happens only once to populate
> the oidset hashtable, and briefly wondered if we are being grossly
> inefficient by scanning pack .idx file each time we encounter a
> missing object.  "Upon first call, that function loops over
> ... walking, to prepare a hashtable to answer if any object id is
> referred to by an object in promisor packs" would have helped ;-).

Right. When you have worked in an area, sometimes it is easy to forget
which things are common knowledge and which are not. :) I don't mind at
all if you want to amend the commit message as you apply.

> > It may also be a good direction for this function in general, as there
> > are other possible optimizations that rely on doing some analysis before
> > parsing:
> >
> >   - we could detect blobs and avoid reading their contents; they can't
> >     link to other objects, but parse_object() doesn't know that we don't
> >     care about checking their hashes.
> >
> >   - we could avoid allocating object structs entirely for most objects
> >     (since we really only need them in the oidset), which would save
> >     some memory.
> >
> >   - promisor commits could use the commit-graph rather than loading the
> >     object from disk
> >
> > This commit doesn't do any of those optimizations, but I think it argues
> > that this direction is reasonable, rather than relying on parse_object()
> > and trying to teach it to give us more information about whether it
> > parsed.
> 
> Yeah, all of the future bits sound sensible. 

I very intentionally didn't work on those things yet, because I wanted
to make sure we got a simple fix in as quickly as possible. That said, I
don't have immediate plans for them. They are perhaps not quite small
enough for #leftoverbits, but I think they might also be nice bite-sized
chunks for somebody wanting to get their feet wet in that part of the
code.

-Peff

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] mingw: include the Python parts in the build
  @ 2022-08-10  9:29  6%       ` Johannes Schindelin
  0 siblings, 0 replies; 200+ results
From: Johannes Schindelin @ 2022-08-10  9:29 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Junio C Hamano, Johannes Schindelin via GitGitGadget, git

Hi Hannes,

On Fri, 29 Jul 2022, Johannes Sixt wrote:

> Am 29.07.22 um 16:29 schrieb Johannes Schindelin:
> > Now, I vaguely remember that j6t said that they switched to MSYS2 some
> > time ago, but all I found on the Git mailing list was
> > https://lore.kernel.org/git/6c2bbca7-7a8f-d3d8-04b6-31494a3e1b43@kdbg.org/
> > which says that in 2017, MSys1 was still used by the person who apart from
> > myself did the most crucial work to support Git on Windows (and that
> > counts a lot in my book, so in this instance I am willing to bear a bit
> > more maintenance burden than I otherwise would for a single person, even
> > if the Windows-specific part of `config.mak.uname` is quite messy, I
> > admit).
> >
> > Hannes, do you still build with MSys1?
>
> Thank you for keeping me in the loop. No, I have long since switched to
> the Git for Windows tool set, i.e., MSYS2 + MinGW64. I don't know if
> anybody is still using MSys1 + MinGW. There's likely no reason to keep
> the MSys1 config section.

Excellent. I've added a #leftoverbits ticket here:
https://github.com/gitgitgadget/git/issues/1319

Ciao,
Dscho

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v7 08/10] docs: move pack format docs to man section 5
  @ 2022-08-03 16:25  5%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-08-03 16:25 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Eric Sunshine, Philippe Blain, Derrick Stolee, Taylor Blau,
	Jeff King, Teng Long

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> @@ -125,7 +139,7 @@ Git index format
>      entry is encoded as if the path name for the previous entry is an
>      empty string).  At the beginning of an entry, an integer N in the
>      variable width encoding (the same encoding as the offset is encoded
> -    for OFS_DELTA pack entries; see pack-format.txt) is stored, followed
> +    for OFS_DELTA pack entries; see linkgit:gitformat-pack[5]) is stored, followed

Possible #leftoverbits for cleaning up around here are:

 * Update the above description to use the term "offset encoding"
   from gitformat-patck[5] to give readers the term to look for;

 * Update <varint.h> and mention that the encode/decode pair
   declared there are to handle variable-length integers in the
   "offset encoding".

 * We might want to add an entry to the glossary, but the varint
   representation is not end-user facing, so it may not be necessary
   and the mention in <varint.h> would be enough.

> diff --git a/Documentation/technical/cruft-packs.txt b/Documentation/gitformat-pack-cruft.txt
> similarity index 96%
> rename from Documentation/technical/cruft-packs.txt
> rename to Documentation/gitformat-pack-cruft.txt
> index d81f3a8982f..908f752bd84 100644
> --- a/Documentation/technical/cruft-packs.txt
> +++ b/Documentation/gitformat-pack-cruft.txt
> @@ -1,4 +1,17 @@
> -= Cruft packs
> +gitformat-pack-cruft(5)
> +=======================
> +
> +NAME
> +----
> +gitformat-pack-cruft - The cruft pack file format
> +
> +SYNOPSIS
> +--------
> +[verse]
> +$GIT_DIR/objects/pack/pack-*.mtimes

I do not think this is quite right.

A reader who wants to learn about cruft packs, they need to know:

 * what a packfile is and what is in .pack/.idx pair, as a
   prerequisite information, that is described elsewhere

 * what it is, what it is used for, and how it is meant to be used,
   why the mtimes from the original loose objects need to be kept,
   all of which is not file-format per-se, but is part of the
   design, described in the original technical/cruft-packs.txt

 * how .mtimes file records the _additional_ pieces of per-object
   information only maintained for the "cruft pack" objects.

The original technical/cruft-packs.txt document was the design
document for the cruft packs feature as a whole, and it made sense
to write about both design and the implementation detail of the
mtimes format.

But that is not "cruft pack file format".  I think this can be fixed
either by having at least two documents (one for "cruft packs"
overall design, plus another one for "mtimes file format"), or by
having one document that is clearly more than "file format".  The
posted patch gives us a mixture of the two, that results in neither
of the two.

Stepping back a bit, unless we have separate .pack(5) and .idx(5)
manual pages, I suspect that having the format of .pack, .idx, .midx,
and .mtimes described in the same "file formats for packfiles" document
might make more sense.  After all, those who come to the packfile format
document from "pack protocol" document do not mind that the former talks
about .idx file, which they would find no use for.

I hope Taylor can help us with his input when he comes back from his
honeymoon.

> diff --git a/Documentation/technical/pack-format.txt b/Documentation/gitformat-pack.txt
> similarity index 95%
> rename from Documentation/technical/pack-format.txt
> rename to Documentation/gitformat-pack.txt
> index b520aa9c45b..546c99f8871 100644
> --- a/Documentation/technical/pack-format.txt
> +++ b/Documentation/gitformat-pack.txt
> @@ -1,5 +1,29 @@
> -Git pack format
> -===============
> +gitformat-pack(5)
> +=================
> +
> +NAME
> +----
> +gitformat-pack - Git pack format

OK.

> diff --git a/command-list.txt b/command-list.txt
> index ed859fdd798..4f30a6c30c8 100644
> --- a/command-list.txt
> +++ b/command-list.txt
> @@ -210,7 +210,12 @@ gitdiffcore                             guide
>  giteveryday                             guide
>  gitfaq                                  guide
>  gitformat-bundle                        developerinterfaces
> +gitformat-chunk                         developerinterfaces
>  gitformat-commit-graph                  developerinterfaces
> +gitformat-index                         developerinterfaces
> +gitformat-pack                          developerinterfaces
> +gitformat-pack-cruft                    developerinterfaces
> +gitformat-signature                     developerinterfaces
>  gitglossary                             guide
>  githooks                                userinterfaces
>  gitignore                               userinterfaces

OK.

^ permalink raw reply	[relevance 5%]

* Re: [PATCH 1/2] t/t0021: convert the rot13-filter.pl script to C
  @ 2022-07-23  4:59  6%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-07-23  4:59 UTC (permalink / raw)
  To: Matheus Tavares; +Cc: git, gitster, larsxschneider, christian.couder


On Fri, Jul 22 2022, Matheus Tavares wrote:

Looking a bit closer...

> however, that we still use the script as a wrapper at
> this commit, in order to minimize the amount of changes it introduces
> and help reviewers. At the next commit we will properly remove the
> script and adjust the affected tests to use test-tool.

I'd prefer if we just squashed this, if you want to avoid some of the
diff verbosity you could leave the PERL prereq on all the
test_expect_success and remove it in a 2/2 (we just wouldn't run the
test until then).

But I think it's all boilerplate, so just doing it in one step would be
better, reasoning about the in-between steps is harder IMO (e.g. "exec"
escaping or whatever)>

> +static char *rot13(char *str)
> +{
> +	char *c;
> +	for (c = str; *c; c++) {
> +		if (*c >= 'a' && *c <= 'z')
> +			*c = 'a' + (*c - 'a' + 13) % 26;
> +		else if (*c >= 'A' && *c <= 'Z')
> +			*c = 'A' + (*c - 'A' + 13) % 26;
> +	}
> +	return str;
> +}

Looks fine, but we should probably put in our CodingGuidelines at some
point that we don't care about EBCDIC, as this isn't portable C (but
probably portable enough, as we can probably assume ASCII) :)

> +static struct string_list *packet_read_capabilities(void)
> +{
> +	struct string_list *caps = xmalloc(sizeof(*caps));

malloc here...

> +	string_list_init_dup(caps);
> +	while (1) {
> +		int size;
> +		char *buf = packet_read_line(0, &size);
> +		if (!buf)
> +			break;
> +		string_list_append_nodup(caps,
> +					 skip_key_dup(buf, size, "capability"));
> +	}
> +	return caps;
> +}
> +
> +/* Read remote capabilities and check them against capabilities we require */
> +static struct string_list *packet_read_and_check_capabilities(
> +		struct string_list *required_caps)
> +{
> +	struct string_list *remote_caps = packet_read_capabilities();

...and here...
> +	struct string_list_item *item;
> +	for_each_string_list_item(item, required_caps) {
> +		if (!unsorted_string_list_has_string(remote_caps, item->string)) {
> +			die("required '%s' capability not available from remote",
> +			    item->string);
> +		}
> +	}
> +	return remote_caps;

...we'll return it...

> +	remote_caps = packet_read_and_check_capabilities(&supported_caps);
> +	packet_check_and_write_capabilities(remote_caps, &requested_caps);
> +	fprintf(logfile, "init handshake complete\n");
> +
> +	string_list_clear(&supported_caps, 0);
> +	string_list_clear(remote_caps, 0);

..and here you're missing a free(), but I wonder why not just declare
this string_list in this function, and pass it down instead?

It's unfortunate that none of these tests seem to pass with
SANITIZE=leak already, but the new command seems not to leak from a
trivial glance except for in that one case.

Not knowing much about the filtering mechanism, I wonder if this code
here wouldn't be better as a built-in some day. I.e. isn't this all
shimmy we need to talk to some arbitrary conversion filter, except for
the rot13 part?

So if we just invoked a "tr" with run_command() to do the actual rot13
filtering we could do any sort of arbitrary replacement, and present a
variant of this this command as a "if you can't be bothered with
packet-line" in gitattributes(5)...

...but maybe that's hopeless for some reason I'm missing, in any case,
more #leftoverbits.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH v5 00/12] rebase: update branches in multi-part topic
  2022-07-19 18:33  2%   ` [PATCH v5 00/12] rebase: update branches in multi-part topic Derrick Stolee via GitGitGadget
  2022-07-21  4:35  0%     ` Elijah Newren
@ 2022-07-21 14:04  0%     ` Phillip Wood
  1 sibling, 0 replies; 200+ results
From: Phillip Wood @ 2022-07-21 14:04 UTC (permalink / raw)
  To: Derrick Stolee via GitGitGadget, git
  Cc: gitster, johannes.schindelin, me, Jeff Hostetler, Elijah Newren,
	SZEDER Gábor, Derrick Stolee

Hi Stolee

I'm afraid I've only had time to have a quick look at patches 8 & 9. The 
error propagation is looking better but I did notice a couple of calls 
to write_update_refs_state() where we don't propagate the return value.

Best Wishes

Phillip

On 19/07/2022 19:33, Derrick Stolee via GitGitGadget wrote:
> This series is based on ds/branch-checked-out.
> 
> This is a feature I've wanted for quite a while. When working on the sparse
> index topic, I created a long RFC that actually broke into three topics for
> full review upstream. These topics were sequential, so any feedback on an
> earlier one required updates to the later ones. I would work on the full
> feature and use interactive rebase to update the full list of commits.
> However, I would need to update the branches pointing to those sub-topics.
> 
> This series adds a new --update-refs option to 'git rebase' (along with a
> rebase.updateRefs config option) that adds 'update-ref' commands into the
> TODO list. This is powered by the commit decoration machinery.
> 
> As an example, here is my in-progress bundle URI RFC split into subtopics as
> they appear during the TODO list of a git rebase -i --update-refs:
> 
> pick 2d966282ff3 docs: document bundle URI standard
> pick 31396e9171a remote-curl: add 'get' capability
> pick 54c6ab70f67 bundle-uri: create basic file-copy logic
> pick 96cb2e35af1 bundle-uri: add support for http(s):// and file://
> pick 6adaf842684 fetch: add --bundle-uri option
> pick 6c5840ed77e fetch: add 'refs/bundle/' to log.excludeDecoration
> update-ref refs/heads/bundle-redo/fetch
> 
> pick 1e3f6546632 clone: add --bundle-uri option
> pick 9e4a6fe9b68 clone: --bundle-uri cannot be combined with --depth
> update-ref refs/heads/bundle-redo/clone
> 
> pick 5451cb6599c bundle-uri: create bundle_list struct and helpers
> pick 3029c3aca15 bundle-uri: create base key-value pair parsing
> pick a8b2de79ce8 bundle-uri: create "key=value" line parsing
> pick 92625a47673 bundle-uri: unit test "key=value" parsing
> pick a8616af4dc2 bundle-uri: limit recursion depth for bundle lists
> pick 9d6809a8d53 bundle-uri: parse bundle list in config format
> pick 287a732b54c bundle-uri: fetch a list of bundles
> update-ref refs/heads/bundle-redo/list
> 
> pick b09f8226185 protocol v2: add server-side "bundle-uri" skeleton
> pick 520204dcd1c bundle-uri client: add minimal NOOP client
> pick 62e8b457b48 bundle-uri client: add "git ls-remote-bundle-uri"
> pick 00eae925043 bundle-uri: serve URI advertisement from bundle.* config
> pick 4277440a250 bundle-uri client: add boolean transfer.bundleURI setting
> pick caf4599a81d bundle-uri: allow relative URLs in bundle lists
> pick df255000b7e bundle-uri: download bundles from an advertised list
> pick d71beabf199 clone: unbundle the advertised bundles
> pick c9578391976 t5601: basic bundle URI tests
> # Ref refs/heads/bundle-redo/rfc-3 checked out at '/home/stolee/_git/git-bundles'
> 
> update-ref refs/heads/bundle-redo/advertise
> 
> 
> Here is an outline of the series:
> 
>   * Patch 1 updates some tests for branch_checked_out() to use 'git bisect'
>     and 'git rebase' as black-boxes instead of manually editing files inside
>     $GIT_DIR. (Thanks, Junio!)
>   * Patch 2 updates some tests for branch_checked_out() for the 'apply'
>     backend.
>   * Patch 3 updates branch_checked_out() to parse the
>     rebase-merge/update-refs file to block concurrent ref updates and
>     checkouts on branches selected by --update-refs.
>   * Patch 4 updates the todo list documentation to remove some unnecessary
>     dots in the 'merge' command. This makes it consistent with the 'fixup'
>     command before we document the 'update-ref' command.
>   * Patch 5 updates the definition of todo_command_info to use enum values as
>     array indices.
>   * Patches 6-8 implement the --update-refs logic itself.
>   * Patch 9 specifically updates the update-refs file every time the user
>     edits the todo-list (Thanks Phillip!)
>   * Patch 10 adds the rebase.updateRefs config option similar to
>     rebase.autoSquash.
>   * Patch 11 ignores the HEAD ref when creating the todo list instead of
>     making a comment (Thanks Elijah!)
>   * Patch 12 adds messaging to the end of the rebase stating which refs were
>     updated (Thanks Elijah!)
> 
> During review, we have identified some areas that would be good for
> #leftoverbits:
> 
>   * Warn the user when they add an 'update-ref ' command but is checked out
>     in another worktree.
>   * The checks in patch 9 are quadratic. They could be sped up using
>     hashtables.
>   * Consider whether we should include an 'update-ref ' command for the HEAD
>     ref, so that all refs are updated in the same way. This might help
>     confused users.
>   * The error message for failed ref updates could include information on the
>     commit IDs that would have been used. This can help the user fix the
>     situation by updating the refs manually.
>   * Modify the --update-refs option from a boolean to an
>     optionally-string-parameter that specifies refspecs for the 'update-ref'
>     commands.
> 
> 
> Updates in v5
> =============
> 
>   * Rename 'wt_dir' to 'wt_git_dir' for clarity.
>   * The documented behavior around 'fixup!' and 'squash!' commits was
>     incorrect, so update the commit message, documentation, and test to
>     demonstrate the actual behavior.
>   * Use CALLOC_ARRAY() to be more idiomatic.
>   * Be much more careful about propagating errors.
>   * Commit message typo: "We an" to "We can"
>   * Remove unnecessary null OID check when writing refs, since those would
>     already be removed by a previous step.
> 
> 
> Updates in v4
> =============
> 
> This version took longer than I'd hoped (I had less time to work on it than
> anticipated) but it also has some major updates. These major updates are
> direct responses to the significant review this series has received. Thank
> you!
> 
>   * The update-refs file now stores "ref/before/after" triples (still
>     separated by lines). This allows us to store the "before" OID of a ref in
>     addition to the "after" that we will write to that ref at the end of the
>     rebase. This allows us to do a "force-with-lease" update. The
>     branch_checked_out() updates should prevent Git from updating those refs
>     while under the rebase, but older versions and third-party tools don't
>     have that protection.
>   * The update-refs file is updated with every update to the todo-list file.
>     This allows for some advanced changes to the file, including removing,
>     adding, and duplicating 'update-ref' commands.
>   * The message at the end of the rebase process now lists which refs were
>     updated with the update-ref steps. This includes any ref updates that
>     fail.
>   * The branch_checked_out() tests now use 'git bisect' and 'git rebase' as
>     black-boxes instead of testing their internals directly.
> 
> Here are the more minor updates:
> 
>   * Dropped an unnecessary stat() call.
>   * Updated commit messages to include extra details, based on confusion in
>     last round.
>   * The HEAD branch no longer appears as a comment line in the initial todo
>     list.
>   * The update-refs file is now written using a lockfile.
>   * Tests now use test_cmp_rev.
>   * A memory leak ('path' variable) is resolved.
> 
> 
> Updates in v3
> =============
> 
>   * The branch_checked_out() API was extracted to its own topic and is now
>     the ds/branch-checked-out branch. This series is now based on that one.
>   * The for_each_decoration() API was removed, since it became trivial once
>     it did not take a commit directly.
>   * The branch_checked_out() tests did not verify the rebase-apply data (for
>     the apply backend), so that is fixed.
>   * Instead of using the 'label' command and a final 'update-refs' command in
>     the todo list, use a new 'update-ref ' command. This command updates the
>     rebase-merge/update-refs file with the OID of HEAD at these steps. At the
>     very end of the rebase sequence, those refs are updated to the stored OID
>     values (assuming that they were not removed by the user, in which case we
>     notice that the OID is the null OID and we do nothing).
>   * New tests are added.
>   * The todo-list comment documentation has some new formatting updates, but
>     also includes a description of 'update-refs' in this version.
> 
> 
> Updates in v2
> =============
> 
> As recommended by the excellent feedback, I have removed the 'exec' commands
> in favor of the 'label' commands and a new 'update-refs' command at the very
> end. This way, there is only one step that updates all of the refs at the
> end instead of updating refs during the rebase. If a user runs 'git rebase
> --abort' in the middle, then their refs are still where they need to be.
> 
> Based on some of the discussion, it seemed like one way to do this would be
> to have an 'update-ref ' command that would take the place of these 'label'
> commands. However, this would require two things that make it a bit awkward:
> 
>   1. We would need to replicate the storage of those positions during the
>      rebase. 'label' already does this pretty well. I've added the
>      "for-update-refs/" label to help here.
>   2. If we want to close out all of the refs as the rebase is finishing, then
>      that "step" becomes invisible to the user (and a bit more complicated to
>      insert). Thus, the 'update-refs' step performs this action. If the user
>      wants to do things after that step, then they can do so by editing the
>      TODO list.
> 
> Other updates:
> 
>   * The 'keep_decorations' parameter was renamed to 'update_refs'.
>   * I added tests for --rebase-merges=rebase-cousins to show how these labels
>     interact with other labels and merge commands.
>   * I changed the order of the insertion of these update-refs labels to be
>     before the fixups are rearranged. This fixes a bug where the tip commit
>     is a fixup! so its decorations are never inspected (and they would be in
>     the wrong place even if they were). The fixup! commands are properly
>     inserted between a pick and its following label command. Tests
>     demonstrate this is correct.
>   * Numerous style choices are updated based on feedback.
> 
> Thank you for all of the detailed review and ideas in this space. I
> appreciate any more ideas that can make this feature as effective as it can
> be.
> 
> Thanks, -Stolee
> 
> Derrick Stolee (12):
>    t2407: test bisect and rebase as black-boxes
>    t2407: test branches currently using apply backend
>    branch: consider refs under 'update-refs'
>    rebase-interactive: update 'merge' description
>    sequencer: define array with enum values
>    sequencer: add update-ref command
>    rebase: add --update-refs option
>    rebase: update refs from 'update-ref' commands
>    sequencer: rewrite update-refs as user edits todo list
>    rebase: add rebase.updateRefs config option
>    sequencer: ignore HEAD ref under --update-refs
>    sequencer: notify user of --update-refs activity
> 
>   Documentation/config/rebase.txt |   3 +
>   Documentation/git-rebase.txt    |  10 +
>   branch.c                        |  13 +
>   builtin/rebase.c                |  10 +
>   rebase-interactive.c            |  15 +-
>   sequencer.c                     | 474 +++++++++++++++++++++++++++++++-
>   sequencer.h                     |  23 ++
>   t/lib-rebase.sh                 |  15 +
>   t/t2407-worktree-heads.sh       | 103 +++++--
>   t/t3404-rebase-interactive.sh   | 273 ++++++++++++++++++
>   10 files changed, 895 insertions(+), 44 deletions(-)
> 
> 
> base-commit: 9bef0b1e6ec371e786c2fba3edcc06ad040a536c
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1247%2Fderrickstolee%2Frebase-keep-decorations-v5
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1247/derrickstolee/rebase-keep-decorations-v5
> Pull-Request: https://github.com/gitgitgadget/git/pull/1247
> 
> Range-diff vs v4:
> 
>    1:  9e53a27017a =  1:  9e53a27017a t2407: test bisect and rebase as black-boxes
>    2:  540a3be256f =  2:  540a3be256f t2407: test branches currently using apply backend
>    3:  bf301a054e3 !  3:  1089a0edb73 branch: consider refs under 'update-refs'
>       @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_squash_onto, "rebase-merge/squash-
>        + * rebase_path_update_refs() returns the path to this file for a given
>        + * worktree directory. For the current worktree, pass the_repository->gitdir.
>        + */
>       -+static char *rebase_path_update_refs(const char *wt_dir)
>       ++static char *rebase_path_update_refs(const char *wt_git_dir)
>        +{
>       -+	return xstrfmt("%s/rebase-merge/update-refs", wt_dir);
>       ++	return xstrfmt("%s/rebase-merge/update-refs", wt_git_dir);
>        +}
>        +
>         /*
>    4:  dec95681d2b =  4:  d1cce4f06aa rebase-interactive: update 'merge' description
>    5:  b2c09600918 =  5:  4c086d477f0 sequencer: define array with enum values
>    6:  fa7ecb718cf =  6:  7b3d6601960 sequencer: add update-ref command
>    7:  3ec2cc922f9 !  7:  7efb55e4f14 rebase: add --update-refs option
>       @@ Commit message
>            --fixup commit at the tip of the feature to apply correctly to the sub
>            branch, even if it is fixing up the most-recent commit in that part.
>        
>       -    One potential problem here is that refs decorating commits that are
>       -    already marked as "fixup!" or "squash!" will not be included in this
>       -    list. Generally, the reordering of the "fixup!" and "squash!" is likely
>       -    to change the relative order of these refs, so it is not recommended.
>       -    The workflow here is intended to allow these kinds of commits at the tip
>       -    of the rebased branch while the other sub branches come along for the
>       -    ride without intervention.
>       -
>            This change update the documentation and builtin to accept the
>            --update-refs option as well as updating the todo file with the
>            'update-ref' commands. Tests are added to ensure that these todo
>       @@ Documentation/git-rebase.txt: provided. Otherwise an explicit `--no-reschedule-f
>        +--no-update-refs::
>        +	Automatically force-update any branches that point to commits that
>        +	are being rebased. Any branches that are checked out in a worktree
>       -+	or point to a `squash! ...` or `fixup! ...` commit are not updated
>       -+	in this way.
>       ++	are not updated in this way.
>        +
>         INCOMPATIBLE OPTIONS
>         --------------------
>       @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
>         			 N_("move commits that begin with "
>         			    "squash!/fixup! under -i")),
>        +		OPT_BOOL(0, "update-refs", &options.update_refs,
>       -+			 N_("update local refs that point to commits "
>       ++			 N_("update branches that point to commits "
>        +			    "that are being rebased")),
>         		{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
>         			N_("GPG-sign commits"),
>       @@ t/t3404-rebase-interactive.sh: test_expect_success 'ORIG_HEAD is updated correct
>        +	git branch -f second HEAD~3 &&
>        +	git branch -f third HEAD~1 &&
>        +	git commit --allow-empty --fixup=third &&
>       ++	git branch -f is-not-reordered &&
>       ++	git commit --allow-empty --fixup=HEAD~4 &&
>        +	git branch -f shared-tip &&
>        +	(
>        +		set_cat_todo_editor &&
>        +
>        +		cat >expect <<-EOF &&
>        +		pick $(git log -1 --format=%h J) J
>       ++		fixup $(git log -1 --format=%h update-refs) fixup! J # empty
>        +		update-ref refs/heads/second
>        +		update-ref refs/heads/first
>        +		pick $(git log -1 --format=%h K) K
>        +		pick $(git log -1 --format=%h L) L
>       -+		fixup $(git log -1 --format=%h update-refs) fixup! L # empty
>       ++		fixup $(git log -1 --format=%h is-not-reordered) fixup! L # empty
>        +		update-ref refs/heads/third
>        +		pick $(git log -1 --format=%h M) M
>        +		update-ref refs/heads/no-conflict-branch
>       ++		update-ref refs/heads/is-not-reordered
>        +		update-ref refs/heads/shared-tip
>        +		EOF
>        +
>    8:  fb5f64c5201 !  8:  e7a91bdffbd rebase: update refs from 'update-ref' commands
>       @@ sequencer.c: struct update_ref_record {
>         
>        +static struct update_ref_record *init_update_ref_record(const char *ref)
>        +{
>       -+	struct update_ref_record *rec = xmalloc(sizeof(*rec));
>       ++	struct update_ref_record *rec;
>       ++
>       ++	CALLOC_ARRAY(rec, 1);
>        +
>        +	oidcpy(&rec->before, null_oid());
>        +	oidcpy(&rec->after, null_oid());
>       @@ sequencer.c: leave_merge:
>         
>        -static int do_update_ref(struct repository *r, const char *ref_name)
>        +static int write_update_refs_state(struct string_list *refs_to_oids)
>       - {
>       ++{
>        +	int result = 0;
>        +	struct lock_file lock = LOCK_INIT;
>        +	FILE *fp = NULL;
>       @@ sequencer.c: leave_merge:
>        +}
>        +
>        +static int do_update_ref(struct repository *r, const char *refname)
>       -+{
>       + {
>        +	struct string_list_item *item;
>        +	struct string_list list = STRING_LIST_INIT_DUP;
>        +
>       -+	sequencer_get_update_refs_state(r->gitdir, &list);
>       ++	if (sequencer_get_update_refs_state(r->gitdir, &list))
>       ++		return -1;
>        +
>        +	for_each_string_list_item(item, &list) {
>        +		if (!strcmp(item->string, refname)) {
>        +			struct update_ref_record *rec = item->util;
>       -+			read_ref("HEAD", &rec->after);
>       ++			if (read_ref("HEAD", &rec->after))
>       ++				return -1;
>        +			break;
>        +		}
>        +	}
>       @@ sequencer.c: leave_merge:
>        +	struct string_list refs_to_oids = STRING_LIST_INIT_DUP;
>        +	struct ref_store *refs = get_main_ref_store(r);
>        +
>       -+	sequencer_get_update_refs_state(r->gitdir, &refs_to_oids);
>       ++	if ((res = sequencer_get_update_refs_state(r->gitdir, &refs_to_oids)))
>       ++		return res;
>        +
>        +	for_each_string_list_item(item, &refs_to_oids) {
>        +		struct update_ref_record *rec = item->util;
>        +
>       -+		if (oideq(&rec->after, the_hash_algo->null_oid)) {
>       -+			/*
>       -+			 * Ref was not updated. User may have deleted the
>       -+			 * 'update-ref' step.
>       -+			 */
>       -+			continue;
>       -+		}
>       -+
>        +		res |= refs_update_ref(refs, "rewritten during rebase",
>        +				       item->string,
>        +				       &rec->after, &rec->before,
>       @@ sequencer.c: leave_merge:
>         {
>         	int i = todo_list->current;
>        @@ sequencer.c: cleanup_head_ref:
>       +
>       + 		strbuf_release(&buf);
>         		strbuf_release(&head_ref);
>       ++
>       ++		if (do_update_refs(r))
>       ++			return -1;
>         	}
>         
>       -+	do_update_refs(r);
>       -+
>         	/*
>       - 	 * Sequence of picks finished successfully; cleanup by
>       - 	 * removing the .git/sequencer directory
>        @@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
>         
>         			sti = string_list_insert(&ctx->refs_to_oids,
>       @@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
>         		}
>         
>         		item->offset_in_buf = base_offset;
>       +@@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
>       +  */
>       + static int todo_list_add_update_ref_commands(struct todo_list *todo_list)
>       + {
>       +-	int i;
>       ++	int i, res;
>       + 	static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
>       + 	static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
>       + 	static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
>        @@ sequencer.c: static int todo_list_add_update_ref_commands(struct todo_list *todo_list)
>         		}
>         	}
>         
>       -+	write_update_refs_state(&ctx.refs_to_oids);
>       ++	res = write_update_refs_state(&ctx.refs_to_oids);
>        +
>         	string_list_clear(&ctx.refs_to_oids, 1);
>       ++
>       ++	if (res) {
>       ++		/* we failed, so clean up the new list. */
>       ++		free(ctx.items);
>       ++		return res;
>       ++	}
>       ++
>         	free(todo_list->items);
>         	todo_list->items = ctx.items;
>       + 	todo_list->nr = ctx.items_nr;
>        
>         ## t/t2407-worktree-heads.sh ##
>        @@ t/t2407-worktree-heads.sh: test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer
>    9:  29c7c76805a !  9:  95e2bbcedb1 sequencer: rewrite update-refs as user edits todo list
>       @@ Commit message
>        
>            We can test that this works by rewriting the todo-list several times in
>            the course of a rebase. Check that each ref is locked or unlocked for
>       -    updates after each todo-list update. We an also verify that the ref
>       +    updates after each todo-list update. We can also verify that the ref
>            update fails if a concurrent process updates one of the refs after the
>            rebase process records the "locked" ref location.
>        
>   10:  c0022d07579 ! 10:  a73b02568f3 rebase: add rebase.updateRefs config option
>       @@ Documentation/config/rebase.txt: rebase.autoStash::
>        
>         ## Documentation/git-rebase.txt ##
>        @@ Documentation/git-rebase.txt: start would be overridden by the presence of
>       + 	Automatically force-update any branches that point to commits that
>         	are being rebased. Any branches that are checked out in a worktree
>       - 	or point to a `squash! ...` or `fixup! ...` commit are not updated
>       - 	in this way.
>       + 	are not updated in this way.
>        ++
>        +If the configuration variable `rebase.updateRefs` is set, then this option
>        +can be used to override and disable this setting.
>   11:  d53b4ff2cee = 11:  2a6577974c7 sequencer: ignore HEAD ref under --update-refs
>   12:  d5cd4b49e46 ! 12:  ec080ce1e90 sequencer: notify user of --update-refs activity
>       @@ sequencer.c: static int do_update_ref(struct repository *r, const char *refname)
>        +	struct strbuf update_msg = STRBUF_INIT;
>        +	struct strbuf error_msg = STRBUF_INIT;
>         
>       - 	sequencer_get_update_refs_state(r->gitdir, &refs_to_oids);
>       + 	if ((res = sequencer_get_update_refs_state(r->gitdir, &refs_to_oids)))
>       + 		return res;
>         
>         	for_each_string_list_item(item, &refs_to_oids) {
>         		struct update_ref_record *rec = item->util;
>        +		int loop_res;
>         
>       - 		if (oideq(&rec->after, the_hash_algo->null_oid)) {
>       - 			/*
>       -@@ sequencer.c: static int do_update_refs(struct repository *r)
>       - 			continue;
>       - 		}
>       -
>        -		res |= refs_update_ref(refs, "rewritten during rebase",
>        -				       item->string,
>        -				       &rec->after, &rec->before,
>       @@ sequencer.c: static int do_update_refs(struct repository *r)
>         }
>         
>        @@ sequencer.c: cleanup_head_ref:
>       + 		strbuf_release(&buf);
>         		strbuf_release(&head_ref);
>       - 	}
>         
>       --	do_update_refs(r);
>       -+	do_update_refs(r, opts->quiet);
>       +-		if (do_update_refs(r))
>       ++		if (do_update_refs(r, opts->quiet))
>       + 			return -1;
>       + 	}
>         
>       - 	/*
>       - 	 * Sequence of picks finished successfully; cleanup by
>        
>         ## t/t3404-rebase-interactive.sh ##
>        @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs updates refs correctly' '
>       @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs updates refs c
>         
>         test_expect_success 'respect user edits to update-ref steps' '
>        @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs: check failed ref update' '
>       + 	# the lock in the update-refs file.
>         	git rev-parse third >.git/refs/heads/second &&
>         
>       - 	git rebase --continue 2>err &&
>       +-	git rebase --continue 2>err &&
>        -	grep "update_ref failed for ref '\''refs/heads/second'\''" err
>       ++	test_must_fail git rebase --continue 2>err &&
>        +	grep "update_ref failed for ref '\''refs/heads/second'\''" err &&
>        +
>        +	cat >expect <<-\EOF &&
> 

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 00/12] rebase: update branches in multi-part topic
  2022-07-21  4:35  0%     ` Elijah Newren
@ 2022-07-21 12:12  0%       ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-07-21 12:12 UTC (permalink / raw)
  To: Elijah Newren, Derrick Stolee via GitGitGadget
  Cc: Git Mailing List, Junio C Hamano, Johannes Schindelin,
	Taylor Blau, Jeff Hostetler, Phillip Wood, SZEDER Gábor

On 7/21/2022 12:35 AM, Elijah Newren wrote:
> On Tue, Jul 19, 2022 at 11:33 AM Derrick Stolee via GitGitGadget

>> During review, we have identified some areas that would be good for
>> #leftoverbits:
>>
>>  * Warn the user when they add an 'update-ref ' command but is checked out
>>    in another worktree.
>>  * The checks in patch 9 are quadratic. They could be sped up using
>>    hashtables.
>>  * Consider whether we should include an 'update-ref ' command for the HEAD
>>    ref, so that all refs are updated in the same way. This might help
>>    confused users.
> 
> Not necessarily so they are updated in the same way; the behind the
> scenes mechanism could perhaps still be different.  Just so that if
> the user looks for the "list of things being updated" they don't get
> surprised that HEAD is missing.

Noted.
 
>>  * The error message for failed ref updates could include information on the
>>    commit IDs that would have been used. This can help the user fix the
>>    situation by updating the refs manually.
>>  * Modify the --update-refs option from a boolean to an
>>    optionally-string-parameter that specifies refspecs for the 'update-ref'
>>    commands.
> 
> refspecs?  Is that the term you really mean here?

Probably "ref namespaces" or "ref prefixes" would be better.

>> Updates in v5
>> =============
>>
>>  * Rename 'wt_dir' to 'wt_git_dir' for clarity.
>>  * The documented behavior around 'fixup!' and 'squash!' commits was
>>    incorrect, so update the commit message, documentation, and test to
>>    demonstrate the actual behavior.
>>  * Use CALLOC_ARRAY() to be more idiomatic.
>>  * Be much more careful about propagating errors.
>>  * Commit message typo: "We an" to "We can"
>>  * Remove unnecessary null OID check when writing refs, since those would
>>    already be removed by a previous step.
> 
> Thanks, I've read over the range-diff and these changes look good to
> me.  One thing I'm curious about (sorry to bring this up so late):
> "pick" commands come with the old commit hash.  Perhaps the update-ref
> commands should too?  (e.g. "update-ref refs/heads/topic from
> <OLDHASH>")

I don't personally see the value here other than to make it harder
for someone to add new commands (and confusing when wanting to
create a brand new ref). We could consider adding a comment in the
future without any backwards compatibility issues:

	update-ref refs/heads/my-ref # was 0123dead

Thanks,
-Stolee

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 00/12] rebase: update branches in multi-part topic
  2022-07-19 18:33  2%   ` [PATCH v5 00/12] rebase: update branches in multi-part topic Derrick Stolee via GitGitGadget
@ 2022-07-21  4:35  0%     ` Elijah Newren
  2022-07-21 12:12  0%       ` Derrick Stolee
  2022-07-21 14:04  0%     ` Phillip Wood
  1 sibling, 1 reply; 200+ results
From: Elijah Newren @ 2022-07-21  4:35 UTC (permalink / raw)
  To: Derrick Stolee via GitGitGadget
  Cc: Git Mailing List, Junio C Hamano, Johannes Schindelin,
	Taylor Blau, Jeff Hostetler, Phillip Wood, SZEDER Gábor,
	Derrick Stolee

On Tue, Jul 19, 2022 at 11:33 AM Derrick Stolee via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> This series is based on ds/branch-checked-out.
>
> This is a feature I've wanted for quite a while. When working on the sparse
> index topic, I created a long RFC that actually broke into three topics for
> full review upstream. These topics were sequential, so any feedback on an
> earlier one required updates to the later ones. I would work on the full
> feature and use interactive rebase to update the full list of commits.
> However, I would need to update the branches pointing to those sub-topics.
>
> This series adds a new --update-refs option to 'git rebase' (along with a
> rebase.updateRefs config option) that adds 'update-ref' commands into the
> TODO list. This is powered by the commit decoration machinery.
>
> As an example, here is my in-progress bundle URI RFC split into subtopics as
> they appear during the TODO list of a git rebase -i --update-refs:
>
> pick 2d966282ff3 docs: document bundle URI standard
> pick 31396e9171a remote-curl: add 'get' capability
> pick 54c6ab70f67 bundle-uri: create basic file-copy logic
> pick 96cb2e35af1 bundle-uri: add support for http(s):// and file://
> pick 6adaf842684 fetch: add --bundle-uri option
> pick 6c5840ed77e fetch: add 'refs/bundle/' to log.excludeDecoration
> update-ref refs/heads/bundle-redo/fetch
>
> pick 1e3f6546632 clone: add --bundle-uri option
> pick 9e4a6fe9b68 clone: --bundle-uri cannot be combined with --depth
> update-ref refs/heads/bundle-redo/clone
>
> pick 5451cb6599c bundle-uri: create bundle_list struct and helpers
> pick 3029c3aca15 bundle-uri: create base key-value pair parsing
> pick a8b2de79ce8 bundle-uri: create "key=value" line parsing
> pick 92625a47673 bundle-uri: unit test "key=value" parsing
> pick a8616af4dc2 bundle-uri: limit recursion depth for bundle lists
> pick 9d6809a8d53 bundle-uri: parse bundle list in config format
> pick 287a732b54c bundle-uri: fetch a list of bundles
> update-ref refs/heads/bundle-redo/list
>
> pick b09f8226185 protocol v2: add server-side "bundle-uri" skeleton
> pick 520204dcd1c bundle-uri client: add minimal NOOP client
> pick 62e8b457b48 bundle-uri client: add "git ls-remote-bundle-uri"
> pick 00eae925043 bundle-uri: serve URI advertisement from bundle.* config
> pick 4277440a250 bundle-uri client: add boolean transfer.bundleURI setting
> pick caf4599a81d bundle-uri: allow relative URLs in bundle lists
> pick df255000b7e bundle-uri: download bundles from an advertised list
> pick d71beabf199 clone: unbundle the advertised bundles
> pick c9578391976 t5601: basic bundle URI tests
> # Ref refs/heads/bundle-redo/rfc-3 checked out at '/home/stolee/_git/git-bundles'
>
> update-ref refs/heads/bundle-redo/advertise
>
>
> Here is an outline of the series:
>
>  * Patch 1 updates some tests for branch_checked_out() to use 'git bisect'
>    and 'git rebase' as black-boxes instead of manually editing files inside
>    $GIT_DIR. (Thanks, Junio!)
>  * Patch 2 updates some tests for branch_checked_out() for the 'apply'
>    backend.
>  * Patch 3 updates branch_checked_out() to parse the
>    rebase-merge/update-refs file to block concurrent ref updates and
>    checkouts on branches selected by --update-refs.
>  * Patch 4 updates the todo list documentation to remove some unnecessary
>    dots in the 'merge' command. This makes it consistent with the 'fixup'
>    command before we document the 'update-ref' command.
>  * Patch 5 updates the definition of todo_command_info to use enum values as
>    array indices.
>  * Patches 6-8 implement the --update-refs logic itself.
>  * Patch 9 specifically updates the update-refs file every time the user
>    edits the todo-list (Thanks Phillip!)
>  * Patch 10 adds the rebase.updateRefs config option similar to
>    rebase.autoSquash.
>  * Patch 11 ignores the HEAD ref when creating the todo list instead of
>    making a comment (Thanks Elijah!)
>  * Patch 12 adds messaging to the end of the rebase stating which refs were
>    updated (Thanks Elijah!)
>
> During review, we have identified some areas that would be good for
> #leftoverbits:
>
>  * Warn the user when they add an 'update-ref ' command but is checked out
>    in another worktree.
>  * The checks in patch 9 are quadratic. They could be sped up using
>    hashtables.
>  * Consider whether we should include an 'update-ref ' command for the HEAD
>    ref, so that all refs are updated in the same way. This might help
>    confused users.

Not necessarily so they are updated in the same way; the behind the
scenes mechanism could perhaps still be different.  Just so that if
the user looks for the "list of things being updated" they don't get
surprised that HEAD is missing.

>  * The error message for failed ref updates could include information on the
>    commit IDs that would have been used. This can help the user fix the
>    situation by updating the refs manually.
>  * Modify the --update-refs option from a boolean to an
>    optionally-string-parameter that specifies refspecs for the 'update-ref'
>    commands.

refspecs?  Is that the term you really mean here?


> Updates in v5
> =============
>
>  * Rename 'wt_dir' to 'wt_git_dir' for clarity.
>  * The documented behavior around 'fixup!' and 'squash!' commits was
>    incorrect, so update the commit message, documentation, and test to
>    demonstrate the actual behavior.
>  * Use CALLOC_ARRAY() to be more idiomatic.
>  * Be much more careful about propagating errors.
>  * Commit message typo: "We an" to "We can"
>  * Remove unnecessary null OID check when writing refs, since those would
>    already be removed by a previous step.

Thanks, I've read over the range-diff and these changes look good to
me.  One thing I'm curious about (sorry to bring this up so late):
"pick" commands come with the old commit hash.  Perhaps the update-ref
commands should too?  (e.g. "update-ref refs/heads/topic from
<OLDHASH>")

^ permalink raw reply	[relevance 0%]

* [PATCH v5 00/12] rebase: update branches in multi-part topic
    @ 2022-07-19 18:33  2%   ` Derrick Stolee via GitGitGadget
  2022-07-21  4:35  0%     ` Elijah Newren
  2022-07-21 14:04  0%     ` Phillip Wood
  1 sibling, 2 replies; 200+ results
From: Derrick Stolee via GitGitGadget @ 2022-07-19 18:33 UTC (permalink / raw)
  To: git
  Cc: gitster, johannes.schindelin, me, Jeff Hostetler, Phillip Wood,
	Elijah Newren, SZEDER Gábor, Derrick Stolee

This series is based on ds/branch-checked-out.

This is a feature I've wanted for quite a while. When working on the sparse
index topic, I created a long RFC that actually broke into three topics for
full review upstream. These topics were sequential, so any feedback on an
earlier one required updates to the later ones. I would work on the full
feature and use interactive rebase to update the full list of commits.
However, I would need to update the branches pointing to those sub-topics.

This series adds a new --update-refs option to 'git rebase' (along with a
rebase.updateRefs config option) that adds 'update-ref' commands into the
TODO list. This is powered by the commit decoration machinery.

As an example, here is my in-progress bundle URI RFC split into subtopics as
they appear during the TODO list of a git rebase -i --update-refs:

pick 2d966282ff3 docs: document bundle URI standard
pick 31396e9171a remote-curl: add 'get' capability
pick 54c6ab70f67 bundle-uri: create basic file-copy logic
pick 96cb2e35af1 bundle-uri: add support for http(s):// and file://
pick 6adaf842684 fetch: add --bundle-uri option
pick 6c5840ed77e fetch: add 'refs/bundle/' to log.excludeDecoration
update-ref refs/heads/bundle-redo/fetch

pick 1e3f6546632 clone: add --bundle-uri option
pick 9e4a6fe9b68 clone: --bundle-uri cannot be combined with --depth
update-ref refs/heads/bundle-redo/clone

pick 5451cb6599c bundle-uri: create bundle_list struct and helpers
pick 3029c3aca15 bundle-uri: create base key-value pair parsing
pick a8b2de79ce8 bundle-uri: create "key=value" line parsing
pick 92625a47673 bundle-uri: unit test "key=value" parsing
pick a8616af4dc2 bundle-uri: limit recursion depth for bundle lists
pick 9d6809a8d53 bundle-uri: parse bundle list in config format
pick 287a732b54c bundle-uri: fetch a list of bundles
update-ref refs/heads/bundle-redo/list

pick b09f8226185 protocol v2: add server-side "bundle-uri" skeleton
pick 520204dcd1c bundle-uri client: add minimal NOOP client
pick 62e8b457b48 bundle-uri client: add "git ls-remote-bundle-uri"
pick 00eae925043 bundle-uri: serve URI advertisement from bundle.* config
pick 4277440a250 bundle-uri client: add boolean transfer.bundleURI setting
pick caf4599a81d bundle-uri: allow relative URLs in bundle lists
pick df255000b7e bundle-uri: download bundles from an advertised list
pick d71beabf199 clone: unbundle the advertised bundles
pick c9578391976 t5601: basic bundle URI tests
# Ref refs/heads/bundle-redo/rfc-3 checked out at '/home/stolee/_git/git-bundles'

update-ref refs/heads/bundle-redo/advertise


Here is an outline of the series:

 * Patch 1 updates some tests for branch_checked_out() to use 'git bisect'
   and 'git rebase' as black-boxes instead of manually editing files inside
   $GIT_DIR. (Thanks, Junio!)
 * Patch 2 updates some tests for branch_checked_out() for the 'apply'
   backend.
 * Patch 3 updates branch_checked_out() to parse the
   rebase-merge/update-refs file to block concurrent ref updates and
   checkouts on branches selected by --update-refs.
 * Patch 4 updates the todo list documentation to remove some unnecessary
   dots in the 'merge' command. This makes it consistent with the 'fixup'
   command before we document the 'update-ref' command.
 * Patch 5 updates the definition of todo_command_info to use enum values as
   array indices.
 * Patches 6-8 implement the --update-refs logic itself.
 * Patch 9 specifically updates the update-refs file every time the user
   edits the todo-list (Thanks Phillip!)
 * Patch 10 adds the rebase.updateRefs config option similar to
   rebase.autoSquash.
 * Patch 11 ignores the HEAD ref when creating the todo list instead of
   making a comment (Thanks Elijah!)
 * Patch 12 adds messaging to the end of the rebase stating which refs were
   updated (Thanks Elijah!)

During review, we have identified some areas that would be good for
#leftoverbits:

 * Warn the user when they add an 'update-ref ' command but is checked out
   in another worktree.
 * The checks in patch 9 are quadratic. They could be sped up using
   hashtables.
 * Consider whether we should include an 'update-ref ' command for the HEAD
   ref, so that all refs are updated in the same way. This might help
   confused users.
 * The error message for failed ref updates could include information on the
   commit IDs that would have been used. This can help the user fix the
   situation by updating the refs manually.
 * Modify the --update-refs option from a boolean to an
   optionally-string-parameter that specifies refspecs for the 'update-ref'
   commands.


Updates in v5
=============

 * Rename 'wt_dir' to 'wt_git_dir' for clarity.
 * The documented behavior around 'fixup!' and 'squash!' commits was
   incorrect, so update the commit message, documentation, and test to
   demonstrate the actual behavior.
 * Use CALLOC_ARRAY() to be more idiomatic.
 * Be much more careful about propagating errors.
 * Commit message typo: "We an" to "We can"
 * Remove unnecessary null OID check when writing refs, since those would
   already be removed by a previous step.


Updates in v4
=============

This version took longer than I'd hoped (I had less time to work on it than
anticipated) but it also has some major updates. These major updates are
direct responses to the significant review this series has received. Thank
you!

 * The update-refs file now stores "ref/before/after" triples (still
   separated by lines). This allows us to store the "before" OID of a ref in
   addition to the "after" that we will write to that ref at the end of the
   rebase. This allows us to do a "force-with-lease" update. The
   branch_checked_out() updates should prevent Git from updating those refs
   while under the rebase, but older versions and third-party tools don't
   have that protection.
 * The update-refs file is updated with every update to the todo-list file.
   This allows for some advanced changes to the file, including removing,
   adding, and duplicating 'update-ref' commands.
 * The message at the end of the rebase process now lists which refs were
   updated with the update-ref steps. This includes any ref updates that
   fail.
 * The branch_checked_out() tests now use 'git bisect' and 'git rebase' as
   black-boxes instead of testing their internals directly.

Here are the more minor updates:

 * Dropped an unnecessary stat() call.
 * Updated commit messages to include extra details, based on confusion in
   last round.
 * The HEAD branch no longer appears as a comment line in the initial todo
   list.
 * The update-refs file is now written using a lockfile.
 * Tests now use test_cmp_rev.
 * A memory leak ('path' variable) is resolved.


Updates in v3
=============

 * The branch_checked_out() API was extracted to its own topic and is now
   the ds/branch-checked-out branch. This series is now based on that one.
 * The for_each_decoration() API was removed, since it became trivial once
   it did not take a commit directly.
 * The branch_checked_out() tests did not verify the rebase-apply data (for
   the apply backend), so that is fixed.
 * Instead of using the 'label' command and a final 'update-refs' command in
   the todo list, use a new 'update-ref ' command. This command updates the
   rebase-merge/update-refs file with the OID of HEAD at these steps. At the
   very end of the rebase sequence, those refs are updated to the stored OID
   values (assuming that they were not removed by the user, in which case we
   notice that the OID is the null OID and we do nothing).
 * New tests are added.
 * The todo-list comment documentation has some new formatting updates, but
   also includes a description of 'update-refs' in this version.


Updates in v2
=============

As recommended by the excellent feedback, I have removed the 'exec' commands
in favor of the 'label' commands and a new 'update-refs' command at the very
end. This way, there is only one step that updates all of the refs at the
end instead of updating refs during the rebase. If a user runs 'git rebase
--abort' in the middle, then their refs are still where they need to be.

Based on some of the discussion, it seemed like one way to do this would be
to have an 'update-ref ' command that would take the place of these 'label'
commands. However, this would require two things that make it a bit awkward:

 1. We would need to replicate the storage of those positions during the
    rebase. 'label' already does this pretty well. I've added the
    "for-update-refs/" label to help here.
 2. If we want to close out all of the refs as the rebase is finishing, then
    that "step" becomes invisible to the user (and a bit more complicated to
    insert). Thus, the 'update-refs' step performs this action. If the user
    wants to do things after that step, then they can do so by editing the
    TODO list.

Other updates:

 * The 'keep_decorations' parameter was renamed to 'update_refs'.
 * I added tests for --rebase-merges=rebase-cousins to show how these labels
   interact with other labels and merge commands.
 * I changed the order of the insertion of these update-refs labels to be
   before the fixups are rearranged. This fixes a bug where the tip commit
   is a fixup! so its decorations are never inspected (and they would be in
   the wrong place even if they were). The fixup! commands are properly
   inserted between a pick and its following label command. Tests
   demonstrate this is correct.
 * Numerous style choices are updated based on feedback.

Thank you for all of the detailed review and ideas in this space. I
appreciate any more ideas that can make this feature as effective as it can
be.

Thanks, -Stolee

Derrick Stolee (12):
  t2407: test bisect and rebase as black-boxes
  t2407: test branches currently using apply backend
  branch: consider refs under 'update-refs'
  rebase-interactive: update 'merge' description
  sequencer: define array with enum values
  sequencer: add update-ref command
  rebase: add --update-refs option
  rebase: update refs from 'update-ref' commands
  sequencer: rewrite update-refs as user edits todo list
  rebase: add rebase.updateRefs config option
  sequencer: ignore HEAD ref under --update-refs
  sequencer: notify user of --update-refs activity

 Documentation/config/rebase.txt |   3 +
 Documentation/git-rebase.txt    |  10 +
 branch.c                        |  13 +
 builtin/rebase.c                |  10 +
 rebase-interactive.c            |  15 +-
 sequencer.c                     | 474 +++++++++++++++++++++++++++++++-
 sequencer.h                     |  23 ++
 t/lib-rebase.sh                 |  15 +
 t/t2407-worktree-heads.sh       | 103 +++++--
 t/t3404-rebase-interactive.sh   | 273 ++++++++++++++++++
 10 files changed, 895 insertions(+), 44 deletions(-)


base-commit: 9bef0b1e6ec371e786c2fba3edcc06ad040a536c
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1247%2Fderrickstolee%2Frebase-keep-decorations-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1247/derrickstolee/rebase-keep-decorations-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1247

Range-diff vs v4:

  1:  9e53a27017a =  1:  9e53a27017a t2407: test bisect and rebase as black-boxes
  2:  540a3be256f =  2:  540a3be256f t2407: test branches currently using apply backend
  3:  bf301a054e3 !  3:  1089a0edb73 branch: consider refs under 'update-refs'
     @@ sequencer.c: static GIT_PATH_FUNC(rebase_path_squash_onto, "rebase-merge/squash-
      + * rebase_path_update_refs() returns the path to this file for a given
      + * worktree directory. For the current worktree, pass the_repository->gitdir.
      + */
     -+static char *rebase_path_update_refs(const char *wt_dir)
     ++static char *rebase_path_update_refs(const char *wt_git_dir)
      +{
     -+	return xstrfmt("%s/rebase-merge/update-refs", wt_dir);
     ++	return xstrfmt("%s/rebase-merge/update-refs", wt_git_dir);
      +}
      +
       /*
  4:  dec95681d2b =  4:  d1cce4f06aa rebase-interactive: update 'merge' description
  5:  b2c09600918 =  5:  4c086d477f0 sequencer: define array with enum values
  6:  fa7ecb718cf =  6:  7b3d6601960 sequencer: add update-ref command
  7:  3ec2cc922f9 !  7:  7efb55e4f14 rebase: add --update-refs option
     @@ Commit message
          --fixup commit at the tip of the feature to apply correctly to the sub
          branch, even if it is fixing up the most-recent commit in that part.
      
     -    One potential problem here is that refs decorating commits that are
     -    already marked as "fixup!" or "squash!" will not be included in this
     -    list. Generally, the reordering of the "fixup!" and "squash!" is likely
     -    to change the relative order of these refs, so it is not recommended.
     -    The workflow here is intended to allow these kinds of commits at the tip
     -    of the rebased branch while the other sub branches come along for the
     -    ride without intervention.
     -
          This change update the documentation and builtin to accept the
          --update-refs option as well as updating the todo file with the
          'update-ref' commands. Tests are added to ensure that these todo
     @@ Documentation/git-rebase.txt: provided. Otherwise an explicit `--no-reschedule-f
      +--no-update-refs::
      +	Automatically force-update any branches that point to commits that
      +	are being rebased. Any branches that are checked out in a worktree
     -+	or point to a `squash! ...` or `fixup! ...` commit are not updated
     -+	in this way.
     ++	are not updated in this way.
      +
       INCOMPATIBLE OPTIONS
       --------------------
     @@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
       			 N_("move commits that begin with "
       			    "squash!/fixup! under -i")),
      +		OPT_BOOL(0, "update-refs", &options.update_refs,
     -+			 N_("update local refs that point to commits "
     ++			 N_("update branches that point to commits "
      +			    "that are being rebased")),
       		{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
       			N_("GPG-sign commits"),
     @@ t/t3404-rebase-interactive.sh: test_expect_success 'ORIG_HEAD is updated correct
      +	git branch -f second HEAD~3 &&
      +	git branch -f third HEAD~1 &&
      +	git commit --allow-empty --fixup=third &&
     ++	git branch -f is-not-reordered &&
     ++	git commit --allow-empty --fixup=HEAD~4 &&
      +	git branch -f shared-tip &&
      +	(
      +		set_cat_todo_editor &&
      +
      +		cat >expect <<-EOF &&
      +		pick $(git log -1 --format=%h J) J
     ++		fixup $(git log -1 --format=%h update-refs) fixup! J # empty
      +		update-ref refs/heads/second
      +		update-ref refs/heads/first
      +		pick $(git log -1 --format=%h K) K
      +		pick $(git log -1 --format=%h L) L
     -+		fixup $(git log -1 --format=%h update-refs) fixup! L # empty
     ++		fixup $(git log -1 --format=%h is-not-reordered) fixup! L # empty
      +		update-ref refs/heads/third
      +		pick $(git log -1 --format=%h M) M
      +		update-ref refs/heads/no-conflict-branch
     ++		update-ref refs/heads/is-not-reordered
      +		update-ref refs/heads/shared-tip
      +		EOF
      +
  8:  fb5f64c5201 !  8:  e7a91bdffbd rebase: update refs from 'update-ref' commands
     @@ sequencer.c: struct update_ref_record {
       
      +static struct update_ref_record *init_update_ref_record(const char *ref)
      +{
     -+	struct update_ref_record *rec = xmalloc(sizeof(*rec));
     ++	struct update_ref_record *rec;
     ++
     ++	CALLOC_ARRAY(rec, 1);
      +
      +	oidcpy(&rec->before, null_oid());
      +	oidcpy(&rec->after, null_oid());
     @@ sequencer.c: leave_merge:
       
      -static int do_update_ref(struct repository *r, const char *ref_name)
      +static int write_update_refs_state(struct string_list *refs_to_oids)
     - {
     ++{
      +	int result = 0;
      +	struct lock_file lock = LOCK_INIT;
      +	FILE *fp = NULL;
     @@ sequencer.c: leave_merge:
      +}
      +
      +static int do_update_ref(struct repository *r, const char *refname)
     -+{
     + {
      +	struct string_list_item *item;
      +	struct string_list list = STRING_LIST_INIT_DUP;
      +
     -+	sequencer_get_update_refs_state(r->gitdir, &list);
     ++	if (sequencer_get_update_refs_state(r->gitdir, &list))
     ++		return -1;
      +
      +	for_each_string_list_item(item, &list) {
      +		if (!strcmp(item->string, refname)) {
      +			struct update_ref_record *rec = item->util;
     -+			read_ref("HEAD", &rec->after);
     ++			if (read_ref("HEAD", &rec->after))
     ++				return -1;
      +			break;
      +		}
      +	}
     @@ sequencer.c: leave_merge:
      +	struct string_list refs_to_oids = STRING_LIST_INIT_DUP;
      +	struct ref_store *refs = get_main_ref_store(r);
      +
     -+	sequencer_get_update_refs_state(r->gitdir, &refs_to_oids);
     ++	if ((res = sequencer_get_update_refs_state(r->gitdir, &refs_to_oids)))
     ++		return res;
      +
      +	for_each_string_list_item(item, &refs_to_oids) {
      +		struct update_ref_record *rec = item->util;
      +
     -+		if (oideq(&rec->after, the_hash_algo->null_oid)) {
     -+			/*
     -+			 * Ref was not updated. User may have deleted the
     -+			 * 'update-ref' step.
     -+			 */
     -+			continue;
     -+		}
     -+
      +		res |= refs_update_ref(refs, "rewritten during rebase",
      +				       item->string,
      +				       &rec->after, &rec->before,
     @@ sequencer.c: leave_merge:
       {
       	int i = todo_list->current;
      @@ sequencer.c: cleanup_head_ref:
     + 
     + 		strbuf_release(&buf);
       		strbuf_release(&head_ref);
     ++
     ++		if (do_update_refs(r))
     ++			return -1;
       	}
       
     -+	do_update_refs(r);
     -+
       	/*
     - 	 * Sequence of picks finished successfully; cleanup by
     - 	 * removing the .git/sequencer directory
      @@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
       
       			sti = string_list_insert(&ctx->refs_to_oids,
     @@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
       		}
       
       		item->offset_in_buf = base_offset;
     +@@ sequencer.c: static int add_decorations_to_list(const struct commit *commit,
     +  */
     + static int todo_list_add_update_ref_commands(struct todo_list *todo_list)
     + {
     +-	int i;
     ++	int i, res;
     + 	static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
     + 	static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
     + 	static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
      @@ sequencer.c: static int todo_list_add_update_ref_commands(struct todo_list *todo_list)
       		}
       	}
       
     -+	write_update_refs_state(&ctx.refs_to_oids);
     ++	res = write_update_refs_state(&ctx.refs_to_oids);
      +
       	string_list_clear(&ctx.refs_to_oids, 1);
     ++
     ++	if (res) {
     ++		/* we failed, so clean up the new list. */
     ++		free(ctx.items);
     ++		return res;
     ++	}
     ++
       	free(todo_list->items);
       	todo_list->items = ctx.items;
     + 	todo_list->nr = ctx.items_nr;
      
       ## t/t2407-worktree-heads.sh ##
      @@ t/t2407-worktree-heads.sh: test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer
  9:  29c7c76805a !  9:  95e2bbcedb1 sequencer: rewrite update-refs as user edits todo list
     @@ Commit message
      
          We can test that this works by rewriting the todo-list several times in
          the course of a rebase. Check that each ref is locked or unlocked for
     -    updates after each todo-list update. We an also verify that the ref
     +    updates after each todo-list update. We can also verify that the ref
          update fails if a concurrent process updates one of the refs after the
          rebase process records the "locked" ref location.
      
 10:  c0022d07579 ! 10:  a73b02568f3 rebase: add rebase.updateRefs config option
     @@ Documentation/config/rebase.txt: rebase.autoStash::
      
       ## Documentation/git-rebase.txt ##
      @@ Documentation/git-rebase.txt: start would be overridden by the presence of
     + 	Automatically force-update any branches that point to commits that
       	are being rebased. Any branches that are checked out in a worktree
     - 	or point to a `squash! ...` or `fixup! ...` commit are not updated
     - 	in this way.
     + 	are not updated in this way.
      ++
      +If the configuration variable `rebase.updateRefs` is set, then this option
      +can be used to override and disable this setting.
 11:  d53b4ff2cee = 11:  2a6577974c7 sequencer: ignore HEAD ref under --update-refs
 12:  d5cd4b49e46 ! 12:  ec080ce1e90 sequencer: notify user of --update-refs activity
     @@ sequencer.c: static int do_update_ref(struct repository *r, const char *refname)
      +	struct strbuf update_msg = STRBUF_INIT;
      +	struct strbuf error_msg = STRBUF_INIT;
       
     - 	sequencer_get_update_refs_state(r->gitdir, &refs_to_oids);
     + 	if ((res = sequencer_get_update_refs_state(r->gitdir, &refs_to_oids)))
     + 		return res;
       
       	for_each_string_list_item(item, &refs_to_oids) {
       		struct update_ref_record *rec = item->util;
      +		int loop_res;
       
     - 		if (oideq(&rec->after, the_hash_algo->null_oid)) {
     - 			/*
     -@@ sequencer.c: static int do_update_refs(struct repository *r)
     - 			continue;
     - 		}
     - 
      -		res |= refs_update_ref(refs, "rewritten during rebase",
      -				       item->string,
      -				       &rec->after, &rec->before,
     @@ sequencer.c: static int do_update_refs(struct repository *r)
       }
       
      @@ sequencer.c: cleanup_head_ref:
     + 		strbuf_release(&buf);
       		strbuf_release(&head_ref);
     - 	}
       
     --	do_update_refs(r);
     -+	do_update_refs(r, opts->quiet);
     +-		if (do_update_refs(r))
     ++		if (do_update_refs(r, opts->quiet))
     + 			return -1;
     + 	}
       
     - 	/*
     - 	 * Sequence of picks finished successfully; cleanup by
      
       ## t/t3404-rebase-interactive.sh ##
      @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs updates refs correctly' '
     @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs updates refs c
       
       test_expect_success 'respect user edits to update-ref steps' '
      @@ t/t3404-rebase-interactive.sh: test_expect_success '--update-refs: check failed ref update' '
     + 	# the lock in the update-refs file.
       	git rev-parse third >.git/refs/heads/second &&
       
     - 	git rebase --continue 2>err &&
     +-	git rebase --continue 2>err &&
      -	grep "update_ref failed for ref '\''refs/heads/second'\''" err
     ++	test_must_fail git rebase --continue 2>err &&
      +	grep "update_ref failed for ref '\''refs/heads/second'\''" err &&
      +
      +	cat >expect <<-\EOF &&

-- 
gitgitgadget

^ permalink raw reply	[relevance 2%]

* Re: [PATCH v4 12/12] sequencer: notify user of --update-refs activity
  @ 2022-07-19 16:09  6%       ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-07-19 16:09 UTC (permalink / raw)
  To: Elijah Newren, Derrick Stolee via GitGitGadget
  Cc: Git Mailing List, Junio C Hamano, Johannes Schindelin,
	Taylor Blau, Jeff Hostetler, Phillip Wood

On 7/16/2022 6:09 PM, Elijah Newren wrote:
> On Tue, Jul 12, 2022 at 6:07 AM Derrick Stolee via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
>>
>> From: Derrick Stolee <derrickstolee@github.com>
>>
>> When the user runs 'git rebase -i --update-refs', the end message still
>> says only
>>
>>   Successfully rebased and updated <HEAD-ref>.
>>
>> Update the sequencer to collect the successful (and unsuccessful) ref
>> updates due to the --update-refs option, so the end message now says
>>
>>   Successfully rebased and updated <HEAD-ref>.
>>   Updated the following refs with --update-refs:
>>         refs/heads/first
>>         refs/heads/third
> 
> This seems good.
> 
>>   Failed to update the following refs with --update-refs:
>>         refs/heads/second
> 
> This is good, but I think it could be improved.  Could we also include
> the commit to which rebase would have updated the branch to?  That
> would allow the user to manually update it if they want, or at least
> see a range-diff between what we would have updated it to and what it
> now has.  Without that information, the user might have difficulty
> correcting that branch.

Would you mind if I left this as something for #leftoverbits? I
expect that a follow-up series will be necessary once we have more
user feedback. This isn't the only item delayed until after more
feedback.

Thanks,
-Stolee

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 0/3] doc: unify config info on some cmds
  2022-07-14 17:44  6% [PATCH 0/3] doc: unify config info on some cmds Matheus Tavares
@ 2022-07-14 21:17  0% ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-07-14 21:17 UTC (permalink / raw)
  To: Matheus Tavares; +Cc: git


On Thu, Jul 14 2022, Matheus Tavares wrote:

> These three patches attempt to remove duplication between some
> config/*.txt and git-*.txt files, to facilitate maintenance and fix any
> divergences.
>
> This series targets the most straightforward conversions, but there are
> also other commands whose config documentation could possibly be unified
> (maybe #leftoverbits):

Great think alike & all that, these patches are pretty much what I've
had locally & been meaning to submit for (check notes) around a year and
a half. So having this move forward is great.

Here's a cleaned up version of what I have, which I figure is probably
better linked-to than contributing to my E-Mail quota :):

	https://github.com/git/git/compare/master...avar:git:avar/doc-config-includes

I cleaned that up just now for this discussion, but I've had these
relatively more messy changes on top too, but I think those could/should
follow:

	https://github.com/avar/git/compare/avar/doc-config-includes...avar:git:avar/doc-config-includes-split

I in that second part I end up e.g. splitting config/gc.txt into that
and config/gc/rerere.txt, so that we can include the latter in both
config/gc.txt (which is included in git-gc.txt) and in git-rerere.txt
(along with config/rerere.txt itself).

I.e. to have all CONFIGURATION sections discuss all the config relevant
to that command, if possible. Not just in the straightforward cases, but
also e.g. the "rerere" case where it needs to "borrow" a part of the
"gc" section.

Another notable one is the config/color.txt, i.e. we want "git branch"
and the like to discuss its part of the "color" configuration.

Anyway, I'm happy to have your versions of this, although maybe the
range-diff below is useful to you to see if there's anything you'd like
to change or steal (it's to the part one above).

The one thing I'd like you to reconsider is to drop the idea of adding
these "ifndef::git-grep[]" defines and the like. In your version it
yields an arguably better result.

But I think what we should be going for is the more general direction
outlined above, at which point that becomes quite a mess of
ifdefs. I.e. config/gc/rerere.txt would need to know what it's going to
get include in, which would be N number of manpages in the genreal case,
not just "main or config" as this series leaves it.

I think the solution I have to that in 1/9 in that first series is a
better trade-off, i.e. we just (eventually, your series doesn't need to
do that) include some standard wording saying that what you're looking
at in git-CMD(1) is transcluded as-is from the relevant part of
git-config(1). I.e.:

	Everything below this line in this section is selectively included
	from the linkgit:git-config[1] documentation. The content is the same
	as what's found there:

What do you think about doing that instead?

 -:  ----------- >  1:  5d0a4562ea8 docs: add and use include template for config/* includes
 -:  ----------- >  2:  450a9d82bf2 docs: include a CONFIGURATION section
 -:  ----------- >  3:  03cdf2d4e4e docs: add includes to the CONFIGURATION section
 -:  ----------- >  4:  959b6ccd6e2 docs: move config discussion to CONFIGURATION section
 1:  439cfdf858f !  5:  f20f207ece7 doc: grep: unify configuration variables definitions
    @@
      ## Metadata ##
    -Author: Matheus Tavares <matheus.bernardino@usp.br>
    +Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    doc: grep: unify configuration variables definitions
    +    grep docs: de-duplicate configuration sections
     
    -    The configuration variables for git-grep are duplicated in
    -    "Documentation/git-grep.txt" and "Documentation/config/grep.txt", which
    -    gqcan make maintenance difficult. The first also contains a definition
    -    that is not present in the latter (grep.fullName), and the latter
    -    received a wording improvement that was not replicated in the former:
    -    see 91028f765 ("grep: clarify what `grep.patternType=default` means",
    -    2021-12-05).
    +    Include the "config/grep.txt" file in "git-grep.txt", instead of
    +    repeating an almost identical description of the "grep" configuration
    +    variables in two places.
     
    -    To avoid such problems, unify the information in one file and include it
    -    in the other.
    +    There is no loss of information here that isn't shown in the addition
    +    to "grep.txt". This change was made by copying the contents of
    +    "git-grep.txt"'s version over the "grep.txt" version. Aside from the
    +    change "grep.txt" being made here the two were identical.
     
    -    Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
    +    This documentation started being copy/pasted around in
    +    b22520a37c8 (grep: allow -E and -n to be turned on by default via
    +    configuration, 2011-03-30). After that in e.g. 6453f7b3486 (grep: add
    +    grep.fullName config variable, 2014-03-17) they started drifting
    +    apart, with only grep.fullName being described in the command
    +    documentation.
    +
    +    In 434e6e753fe (config.txt: move grep.* to a separate file,
    +    2018-10-27) we gained the include, but didn't do this next step, let's
    +    do it now.
    +
    +    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Documentation/config/grep.txt ##
     @@ Documentation/config/grep.txt: grep.extendedRegexp::
    @@ Documentation/config/grep.txt: grep.extendedRegexp::
      grep.threads::
     -	Number of grep worker threads to use.
     -	See `grep.threads` in linkgit:git-grep[1] for more information.
    -+	Number of grep worker threads to use. See `--threads`
    -+ifndef::git-grep[]
    -+	in linkgit:git-grep[1]
    -+endif::git-grep[]
    -+	for more information.
    ++	Number of grep worker threads to use. If unset (or set to 0), Git will
    ++	use as many threads as the number of logical cores available.
     +
     +grep.fullName::
     +	If set to true, enable `--full-name` option by default.
    @@ Documentation/config/grep.txt: grep.extendedRegexp::
      	If set to true, fall back to git grep --no-index if git grep
     
      ## Documentation/git-grep.txt ##
    -@@ Documentation/git-grep.txt: registered in the index file, or blobs in given tree objects.  Patterns
    - are lists of one or more search expressions separated by newline
    - characters.  An empty string as search expression matches all lines.
    - 
    --
    - OPTIONS
    - -------
    - --cached::
    -@@ Documentation/git-grep.txt: providing this option will cause it to die.
    - 	custom hunk-header' in linkgit:gitattributes[5]).
    - 
    - --threads <num>::
    --	Number of grep worker threads to use.
    --	See `grep.threads` in 'CONFIGURATION' for more information.
    -+	Number of grep worker threads to use. If not provided (or set to
    -+	0), Git will use as many worker threads as the number of logical
    -+	cores available. The default value can also be set with the
    -+	`grep.threads` configuration.
    - 
    - -f <file>::
    - 	Read patterns from <file>, one per line.
     @@ Documentation/git-grep.txt: performance in this case, it might be desirable to use `--threads=1`.
      CONFIGURATION
      -------------
    @@ Documentation/git-grep.txt: performance in this case, it might be desirable to u
     -grep.fallbackToNoIndex::
     -	If set to true, fall back to git grep --no-index if git grep
     -	is executed outside of a git repository.  Defaults to false.
    --
    -+:git-grep: 1
    ++include::includes/cmd-config-section-all.txt[]
    + 
     +include::config/grep.txt[]
      
      GIT
 2:  a25a6d89647 <  -:  ----------- doc: apply: unify configuration variables definitions
 -:  ----------- >  6:  58f8fccef11 send-email docs: de-duplicate configuration sections
 -:  ----------- >  7:  acb6fc2aef5 apply docs: de-duplicate configuration sections
 3:  699dda58fc6 !  8:  c8725b99483 doc: notes: unify config variable definitions
    @@
      ## Metadata ##
    -Author: Matheus Tavares <matheus.bernardino@usp.br>
    +Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    doc: notes: unify config variable definitions
    +    notes docs: de-duplicate configuration sections
     
    -    Unify duplicated configuration descriptions from git-notes.txt and
    -    config.txt in order to facilitate maintenance and update. There are some
    -    discrepancies between these two files: git-notes.txt received two
    -    updates that were not made in config.txt: see 66c4c32
    -    ("Documentation/notes: simplify treatment of default display refs",
    -    2010-05-08) and c5ce183 ("Documentation/notes: clean up description of
    -    rewriting configuration", 2010-05-08 ). And there was also an update to
    -    config.txt not propagated to git-notes.txt: see 2b4aa89 ("Documentation:
    -    basic configuration of notes.rewriteRef", 2011-09-13). Let's make sure
    -    to include all these three updates in the unified version.
    +    Let's also fix the "git-notes(1)" docs so that we link to
    +    "git-config(1)", not "git-log(1)" as a reference for the "notes" docs.
     
    -    Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
    +    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Documentation/config/notes.txt ##
     @@ Documentation/config/notes.txt: notes.mergeStrategy::
    - 	Which merge strategy to choose by default when resolving notes
      	conflicts.  Must be one of `manual`, `ours`, `theirs`, `union`, or
      	`cat_sort_uniq`.  Defaults to `manual`.  See "NOTES MERGE STRATEGIES"
    --	section of linkgit:git-notes[1] for more information on each strategy.
    -+	section
    -+ifdef::git-notes[above]
    -+ifndef::git-notes[of linkgit:git-notes[1]]
    -+	for more information on each strategy.
    + 	section of linkgit:git-notes[1] for more information on each strategy.
    +++
    ++This setting can be overridden by passing the `--strategy` option to
    ++linkgit:git-notes[1].
      
      notes.<name>.mergeStrategy::
      	Which merge strategy to choose when doing a notes merge into
    - 	refs/notes/<name>.  This overrides the more general
    --	"notes.mergeStrategy".  See the "NOTES MERGE STRATEGIES" section in
    --	linkgit:git-notes[1] for more information on the available strategies.
    -+	"notes.mergeStrategy".  See the "NOTES MERGE STRATEGIES" section
    -+ifdef::git-notes[above]
    -+ifndef::git-notes[in linkgit:git-notes[1]]
    -+	for more information on the available strategies.
    +@@ Documentation/config/notes.txt: notes.<name>.mergeStrategy::
    + 	linkgit:git-notes[1] for more information on the available strategies.
      
      notes.displayRef::
     -	The (fully qualified) refname from which to show notes when
    @@ Documentation/config/notes.txt: notes.mergeStrategy::
     -	several times.  A warning will be issued for refs that do not
     -	exist, but a glob that does not match any refs is silently
     -	ignored.
    --+
    --This setting can be overridden with the `GIT_NOTES_DISPLAY_REF`
    --environment variable, which must be a colon separated list of refs or
    --globs.
    --+
    --The effective value of "core.notesRef" (possibly overridden by
    --GIT_NOTES_REF) is also implicitly added to the list of refs to be
    --displayed.
     +	Which ref (or refs, if a glob or specified more than once), in
     +	addition to the default set by `core.notesRef` or
     +	`GIT_NOTES_REF`, to read notes from when showing commit
     +	messages with the 'git log' family of commands.
    -+	This setting can be overridden on the command line or by the
    -+	`GIT_NOTES_DISPLAY_REF` environment variable.
    -+	See linkgit:git-log[1].
    + +
    + This setting can be overridden with the `GIT_NOTES_DISPLAY_REF`
    + environment variable, which must be a colon separated list of refs or
    + globs.
    + +
    ++A warning will be issued for refs that do not exist,
    ++but a glob that does not match any refs is silently ignored.
    +++
    ++This setting can be disabled by the `--no-notes` option to the 'git
    ++log' family of commands, or by the `--notes=<ref>` option accepted by
    ++those commands.
    +++
    + The effective value of "core.notesRef" (possibly overridden by
    + GIT_NOTES_REF) is also implicitly added to the list of refs to be
    + displayed.
      
      notes.rewrite.<command>::
      	When rewriting commits with <command> (currently `amend` or
    @@ Documentation/config/notes.txt: notes.mergeStrategy::
     +	notes from the original to the rewritten commit.  Defaults to
     +	`true`.  See also "`notes.rewriteRef`" below.
     ++
    -+This setting can be overridden by the `GIT_NOTES_REWRITE_REF`
    -+environment variable.
    ++This setting can be overridden with the `GIT_NOTES_REWRITE_REF`
    ++environment variable, which must be a colon separated list of refs or
    ++globs.
      
      notes.rewriteMode::
    --	When copying notes during a rewrite (see the
    --	"notes.rewrite.<command>" option), determines what to do if
    --	the target commit already has a note.  Must be one of
    --	`overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`.
    --	Defaults to `concatenate`.
    -+	When copying notes during a rewrite, what to do if the target
    -+	commit already has a note.  Must be one of `overwrite`,
    -+	`concatenate`, `cat_sort_uniq`, or `ignore`.  Defaults to
    -+	`concatenate`.
    - +
    - This setting can be overridden with the `GIT_NOTES_REWRITE_MODE`
    - environment variable.
    + 	When copying notes during a rewrite (see the
    +@@ Documentation/config/notes.txt: environment variable.
      
      notes.rewriteRef::
      	When copying notes during a rewrite, specifies the (fully
    @@ Documentation/config/notes.txt: notes.mergeStrategy::
     -environment variable, which must be a colon separated list of refs or
     -globs.
     +Can be overridden with the `GIT_NOTES_REWRITE_REF` environment variable.
    ++See `notes.rewrite.<command>` above for a further description of its format.
    +
    + ## Documentation/git-log.txt ##
    +@@ Documentation/git-log.txt: log.showSignature::
    + mailmap.*::
    + 	See linkgit:git-shortlog[1].
    + 
    +-notes.displayRef::
    +-	Which refs, in addition to the default set by `core.notesRef`
    +-	or `GIT_NOTES_REF`, to read notes from when showing commit
    +-	messages with the `log` family of commands.  See
    +-	linkgit:git-notes[1].
    +-+
    +-May be an unabbreviated ref name or a glob and may be specified
    +-multiple times.  A warning will be issued for refs that do not exist,
    +-but a glob that does not match any refs is silently ignored.
    +-+
    +-This setting can be disabled by the `--no-notes` option,
    +-overridden by the `GIT_NOTES_DISPLAY_REF` environment variable,
    +-and overridden by the `--notes=<ref>` option.
    ++include::includes/cmd-config-section-rest.txt[]
    ++
    ++include::config/notes.txt[]
    + 
    + GIT
    + ---
     
      ## Documentation/git-notes.txt ##
    +@@ Documentation/git-notes.txt: using the `--notes` option. Such notes are added as a patch commentary
    + after a three dash separator line.
    + 
    + To change which notes are shown by 'git log', see the
    +-"notes.displayRef" configuration in linkgit:git-log[1].
    ++"notes.displayRef" configuration in linkgit:git-config[1].
    + 
    + See the "notes.rewrite.<command>" configuration for a way to carry
    + notes across commands that rewrite commits.
     @@ Documentation/git-notes.txt: core.notesRef::
      	This setting can be overridden through the environment and
      	command line.
    @@ Documentation/git-notes.txt: core.notesRef::
     -+
     -This setting can be overridden by the `GIT_NOTES_REWRITE_REF`
     -environment variable.
    --
    ++include::includes/cmd-config-section-rest.txt[]
    + 
     -notes.rewriteMode::
     -	When copying notes during a rewrite, what to do if the target
     -	commit already has a note.  Must be one of `overwrite`,
    @@ Documentation/git-notes.txt: core.notesRef::
     -enable note rewriting.
     -+
     -Can be overridden with the `GIT_NOTES_REWRITE_REF` environment variable.
    --
    -+:git-notes: 1
     +include::config/notes.txt[]
      
    + 
      ENVIRONMENT
    - -----------
 -:  ----------- >  9:  cffa925ccf9 log docs: de-duplicate configuration sections

^ permalink raw reply	[relevance 0%]

* [PATCH 0/3] doc: unify config info on some cmds
@ 2022-07-14 17:44  6% Matheus Tavares
  2022-07-14 21:17  0% ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 200+ results
From: Matheus Tavares @ 2022-07-14 17:44 UTC (permalink / raw)
  To: git

These three patches attempt to remove duplication between some
config/*.txt and git-*.txt files, to facilitate maintenance and fix any
divergences.

This series targets the most straightforward conversions, but there are
also other commands whose config documentation could possibly be unified
(maybe #leftoverbits):

- git-log.txt and config/log.txt have some duplications, but with
  different wordings, which could probably be standardized.

- git-send-email.txt has some config definitions "inlined" with the
  descriptions about the CLI options (e.g. sendemail.xmailer). Not sure
  if it is worth unifying the configs in this case.

- Some cmds like format-patch, status, and branch have some config variables
  defined at config/*, but not at git-*.txt. Maybe the latter could
  mention something like "See the full list of available <cmd>.*
  configuration variables at git-config(1)."

Matheus Tavares (3):
  doc: grep: unify configuration variables definitions
  doc: apply: unify configuration variables definitions
  doc: notes: unify configuration variables definitions

 Documentation/config/apply.txt |  7 +++-
 Documentation/config/grep.txt  | 10 ++++--
 Documentation/config/notes.txt | 62 ++++++++++++++++------------------
 Documentation/git-apply.txt    |  9 ++---
 Documentation/git-grep.txt     | 37 ++++----------------
 Documentation/git-notes.txt    | 54 ++---------------------------
 6 files changed, 53 insertions(+), 126 deletions(-)

-- 
2.37.0


^ permalink raw reply	[relevance 6%]

* Re: [PATCH 1/3] checkout: document bug where delayed checkout counts entries twice
  @ 2022-07-13 17:57  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-07-13 17:57 UTC (permalink / raw)
  To: Matheus Tavares; +Cc: git

Matheus Tavares <matheus.bernardino@usp.br> writes:

> At the end of a `git checkout <pathspec>` operation, git reports how
> many paths were checked out with a message like "Updated N paths from
> the index". However, entries that end up on the delayed checkout queue
> (as requested by a long-running process filter) get counted twice,
> producing a wrong number in the final report. We will fix this bug in an
> upcoming commit. For now, only document/demonstrate it with a
> test_expect_failure.
>
> Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
> ---
>  t/t0021-conversion.sh | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>
> diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
> index bad37abad2..00df9b5c18 100755
> --- a/t/t0021-conversion.sh
> +++ b/t/t0021-conversion.sh
> @@ -1132,4 +1132,26 @@ do
>  	'
>  done
>  
> +test_expect_failure PERL 'delayed checkout correctly reports the number of updated entries' '

It is unfortunate that we depend on Perl only to run rot13-filter;
I'll leave a #leftoverbit label here to remind us to write a
"test-tool rot13-filter" someday.  No need to do so in this series.

> +	rm -rf repo &&
> +	git init repo &&
> +	(
> +		cd repo &&
> +		git config filter.delay.process "../rot13-filter.pl delayed.log clean smudge delay" &&
> +		git config filter.delay.required true &&
> +
> +		echo "*.a filter=delay" >.gitattributes &&
> +		echo a >test-delay10.a &&
> +		echo a >test-delay11.a &&
> +		git add . &&
> +		git commit -m files &&
> +
> +		rm *.a &&
> +		git checkout . 2>err &&
> +		grep "IN: smudge test-delay10.a .* \\[DELAYED\\]" delayed.log &&
> +		grep "IN: smudge test-delay11.a .* \\[DELAYED\\]" delayed.log &&
> +		grep "Updated 2 paths from the index" err
> +	)
> +'
> +
>  test_done

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v6 1/5] Documentation/git-config.txt: add SCOPES section
  2022-06-30 22:32  5%     ` Taylor Blau
@ 2022-07-06 17:44  0%       ` Glen Choo
  0 siblings, 0 replies; 200+ results
From: Glen Choo @ 2022-07-06 17:44 UTC (permalink / raw)
  To: Taylor Blau, Glen Choo via GitGitGadget
  Cc: git, brian m. carlson, Derrick Stolee, Junio C Hamano,
	Emily Shaffer, Jonathan Tan,
	Ævar Arnfjörð Bjarmason


Hi! Thanks so much for lending your attention to this version again, I
really appreciate this wording feedback in particular, because the
Review Club reviewers and I agonized a lot over the wording and couldn't
come up with great alternatives to what I wrote in the patch, and your
suggestions are super helpful.

Taylor Blau <me@ttaylorr.com> writes:

> On Thu, Jun 30, 2022 at 06:13:55PM +0000, Glen Choo via GitGitGadget wrote:
>> From: Glen Choo <chooglen@google.com>
>> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
>> index 9376e39aef2..f93d437b898 100644
>> --- a/Documentation/git-config.txt
>> +++ b/Documentation/git-config.txt
>> @@ -297,8 +297,8 @@ The default is to use a pager.
>>  FILES
>>  -----
>>
>> -If not set explicitly with `--file`, there are four files where
>> -'git config' will search for configuration options:
>> +By default, 'git config' will read configuration options from multiple
>> +files:
>>
>>  $(prefix)/etc/gitconfig::
>>  	System-wide configuration file.
>> @@ -322,27 +322,63 @@ $GIT_DIR/config.worktree::
>>  	This is optional and is only searched when
>>  	`extensions.worktreeConfig` is present in $GIT_DIR/config.
>>
>> -If no further options are given, all reading options will read all of these
>> -files that are available. If the global or the system-wide configuration
>> -file are not available they will be ignored. If the repository configuration
>> -file is not available or readable, 'git config' will exit with a non-zero
>> -error code. However, in neither case will an error message be issued.
>> +You may also provide additional configuration parameters when running any
>> +git command by using the `-c` option. See linkgit:git[1] for details.
>> +
>> +Options will be read from all of these files that are available. If the
>> +global or the system-wide configuration file are not available they will be
>> +ignored. If the repository configuration file is not available or readable,
>> +'git config' will exit with a non-zero error code. However, in neither case
>> +will an error message be issued.
>
> Nit: the last sentence is a little awkwardly worded. Perhaps just:
> "Note that neither case produces an error message".

Good suggestion. I didn't change this sentence, but I agree that it's
worth improving.

>> -All writing options will per default write to the repository specific
>> +By default, options are only written to the repository specific
>>  configuration file. Note that this also affects options like `--replace-all`
>
> Should we mention that this is the same as the "local" scope below?

Also a good idea.

>>  and `--unset`. *'git config' will only ever change one file at a time*.
>>
>> -You can override these rules using the `--global`, `--system`,
>> -`--local`, `--worktree`, and `--file` command-line options; see
>> -<<OPTIONS>> above.
>> +You can change the way options are read/written by specifying the path to a
>> +file (`--file`), or by specifying a configuration scope (`--system`,
>> +`--global`, `--local`, `--worktree`); see <<OPTIONS>> above.
>
> I think this paragraph could be slightly more descriptive about what
> `--file` does while still linking out to <<OPTIONS>> above for more
> detailed information. In the pre-image, we say:
>
>     If not set explicitly with `--file`, there are four files will `git
>     config will search`.
>
> So I wonder if something more descriptive in this section might be:
>
>     You can limit which configuration sources are read to or written
>     from by specifying the path of a file with the `--file` option, or
>     by specifying a scope with `--system`, `--global`, `--local`, or
>     `--worktree`. For more, see <<OPTIONS>> above.
>
> I don't think that's so different form what you wrote, but I think it's
> a little clearer particularly what `--file` does (instead of "change the
> way options are read/written" it "limit[s] which configuration sources
> are read to or written from").

I think this is _much_ clearer, actually. Thanks!

>> +
>> +SCOPES
>> +------
>> +
>> +Each configuration source falls within a configuration scope. The scopes
>> +are:
>> +
>> +system::
>> +	$(prefix)/etc/gitconfig
>> +
>> +global::
>> +	$XDG_CONFIG_HOME/git/config
>> ++
>> +~/.gitconfig
>> +
>> +local::
>> +	$GIT_DIR/config
>> +
>> +worktree::
>> +	$GIT_DIR/config.worktree
>> +
>> +command::
>> +	environment variables
>> ++
>> +the `-c` option
>> +
>> +With the exception of 'command', each scope corresponds to a command line
>> +option - `--system`, `--global`, `--local`, `--worktree`.
>
> I think a colon after "option" is more appropriate than a single "-"
> dash character, but this is definitely a trivial matter that I have no
> strong opinion on.
>
> One thing that this reminds me of (which I don't think is worth taking
> up here, but perhaps in a future series, or as #leftoverbits) would be
> promoting these scopes behind a single option. Back in the day, you
> could ask for values out of `git config` by specifying their type with
> `--int`, `--bool`, or similar. In e3e042b185 (Merge branch
> 'tb/config-type', 2018-05-08), we changed to
> `--type=<int|bool|color|etc>`, which unified things and made it clearer
> which options were grouped together by a single concept.
>
> I think a similar change would make sense here, that is to replace
> `--system`, `--global` (and so on) with `--scope=system`,
> `--scope=global`, etc.
>
> But that's not material to this series, and just something to think
> about for later on if you end up thinking it's a good idea.

This sounds like a great idea, actually. I agree that `--scope` is
probably a lot easier to reason about than having N scope flags, and
that this probably belongs in a future series.

>> +
>> +When reading options, specifying a scope will only read options from the
>> +files within that scope. When writing options, specifying a scope will write
>> +to the files within that scope (instead of the repository specific
>> +configuration file). See <<OPTIONS>> above for a complete description.
>>
>> +Most configuration options are respected regardless of the scope it is
>> +defined in, but some options are only respected in certain scopes. See the
>> +option's documentation for the full details.
>
> I assume "the option's" is referring to whichever configuration variable
> we're talking about. So it may be clearer to say "See the *respective*
> option's documentation for more information" or similar.

Good idea. Thanks again!

>
> Thanks,
> Taylor

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 3/5] pack-bitmap.c: using error() instead of silently returning -1
  @ 2022-07-05 18:23  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-07-05 18:23 UTC (permalink / raw)
  To: Teng Long; +Cc: avarab, derrickstolee, git, git, me, tenglong.tl

Teng Long <dyroneteng@gmail.com> writes:

> It's more accurate here with your suggestion. At the same time I
> found there actually exists many similar place like "ignore ENOENT
> silently" in repo. And I think it's not worth to impove them right now
> in this patch, if you want to do that it could in another pathset and
> please tell me.

It is sufficien to just mark it as #leftoverbits to find and fix
places where the code means to ignore only a missing optional file
but ignores all other errors it gets from open/fopen instead.

>> > @@ -394,7 +394,7 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
>> >
>> >  	if (!is_pack_valid(packfile)) {
>> >  		close(fd);
>> > -		return -1;
>> > +		return error(_("packfile is invalid"));
>>
>> Same "sometimes redundant" comment applies here, but not due to this
>> part of the code but due to the helpers called from is_pack_valid().
>
> Let me try to know about it, the "helpers" means the place where invoke
> is_pack_valid() like here. In fact, in is_pack_valid() they already
> return the errors in various scenarios, so it would be no need to
> return another error.

Yup.  is_pack_valid() calls open_packed_git() and the helper
functions that are called from that call chain are full of calls to
error() that tell specifically what exactly went wrong.  But ...

>> Namely, packfile.c::open_packed_git_1() is mostly chatty, but is
>> silent upon "unable to open" and "unable to fstat" (which I think is
>> safe to make chatty as well---we do not want to special case ENOENT
>> in open_packed_git(), so "cannot open because it is not there" is an
>> error).

... the error coverage is not complete.  There are some (rare) code
paths that silently "return -1", not "return error(_("..."))".  They
should be updated to say something; otherwise we will silently fail
in these "rare" codepaths.

> "cannot open because it is not there" is an error, but I think it will
> also could be a BUG, actually I'm not very sure for clarify the
> difference bwtween the use of the two, but I will look into it to dig
> something out.

The code may have many reasons to believe that a file should exist
there and try to open it, but it may find the file missing, but I
would suspect that it is never a BUG.  You may have run stat() on
the path earlier and you know it existed, but by the time you try to
open it, some other process may have removed it.  You may have found
the .idx file and expect that the corresponding .pack file to exist,
but the .pack file may be missing.  You may have just written a file
and you expect to be able to open it, but some other process may
have removed it already, or you may have run out of file descriptors
and cannot open it.  These are all runtime errors that deserve to be
reported via error() or die(), but never BUG().

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] pack-objects.h: remove outdated pahole results
  2022-07-01 18:16  6% ` Jeff King
@ 2022-07-01 19:48  0%   ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2022-07-01 19:48 UTC (permalink / raw)
  To: Jeff King; +Cc: Taylor Blau, git, gitster, pclouds

On Fri, Jul 01, 2022 at 02:16:26PM -0400, Jeff King wrote:
> On Tue, Jun 28, 2022 at 02:30:20PM -0400, Taylor Blau wrote:
>
> > Even though this comment was written in a good spirit, it is updated
> > infrequently enough that is serves to confuse rather than to encourage
> > contributors to update the appropriate values when the modify the
> > definition of object_entry.
> >
> > For that reason, eliminate the confusion by removing the comment
> > altogether.
>
> I agree the actual numbers aren't helping anybody. We _could_ leave a
> comment that says "we store a lot of these in memory; be careful of
> where and how you add new fields to avoid increasing the struct size".
> And then people can run "pahole" before and after their changes.
>
> But then that is also true of other structs (like "struct object"), and
> we do not bother there. So it probably is fine not to annotate this
> specifically.

We have such a comment at the very type of the block comment above
`struct object_entry`'s definition:

    "The size of struct nearly determines pack-object's memory
    consumption. This struct is packed tight for that reason. When you
    add or reorder something in this struct, think a bit about this".

thanks to Duy back in 3b13a5f263 (pack-objects: reorder members to
shrink struct object_entry, 2018-04-14).

> Speaking of which, I suspect quite a lot of memory could be saved if
> "pack-objects --revs" freed the object structs it allocates during its
> traversal. Unless we're generating bitmaps, I don't think they get used
> again after the initial packing list is generated. At peak you'd
> still be storing all of the object_entry structs alongside the objects
> as you finish the traversal, but it wouldn't overlap with any memory
> used for the delta search, and of course we'd be at that peak for a much
> smaller time.
>
> Not a blocker for your patch obviously, but maybe a fun experiment in an
> adjacent area. Possibly even an ambitious #leftoverbits opportunity. :)

Challenge accepted! ;-)

Thanks,
Taylor

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] pack-objects.h: remove outdated pahole results
  @ 2022-07-01 18:16  6% ` Jeff King
  2022-07-01 19:48  0%   ` Taylor Blau
  0 siblings, 1 reply; 200+ results
From: Jeff King @ 2022-07-01 18:16 UTC (permalink / raw)
  To: Taylor Blau; +Cc: git, gitster, pclouds

On Tue, Jun 28, 2022 at 02:30:20PM -0400, Taylor Blau wrote:

> Even though this comment was written in a good spirit, it is updated
> infrequently enough that is serves to confuse rather than to encourage
> contributors to update the appropriate values when the modify the
> definition of object_entry.
> 
> For that reason, eliminate the confusion by removing the comment
> altogether.

I agree the actual numbers aren't helping anybody. We _could_ leave a
comment that says "we store a lot of these in memory; be careful of
where and how you add new fields to avoid increasing the struct size".
And then people can run "pahole" before and after their changes.

But then that is also true of other structs (like "struct object"), and
we do not bother there. So it probably is fine not to annotate this
specifically.

Speaking of which, I suspect quite a lot of memory could be saved if
"pack-objects --revs" freed the object structs it allocates during its
traversal. Unless we're generating bitmaps, I don't think they get used
again after the initial packing list is generated. At peak you'd
still be storing all of the object_entry structs alongside the objects
as you finish the traversal, but it wouldn't overlap with any memory
used for the delta search, and of course we'd be at that peak for a much
smaller time.

Not a blocker for your patch obviously, but maybe a fun experiment in an
adjacent area. Possibly even an ambitious #leftoverbits opportunity. :)

-Peff

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v6 1/5] Documentation/git-config.txt: add SCOPES section
  @ 2022-06-30 22:32  5%     ` Taylor Blau
  2022-07-06 17:44  0%       ` Glen Choo
  0 siblings, 1 reply; 200+ results
From: Taylor Blau @ 2022-06-30 22:32 UTC (permalink / raw)
  To: Glen Choo via GitGitGadget
  Cc: git, brian m. carlson, Derrick Stolee, Junio C Hamano,
	Emily Shaffer, Jonathan Tan,
	Ævar Arnfjörð Bjarmason, Glen Choo

On Thu, Jun 30, 2022 at 06:13:55PM +0000, Glen Choo via GitGitGadget wrote:
> From: Glen Choo <chooglen@google.com>
>
> In a subsequent commit, we will introduce "protected configuration",
> which is easiest to describe in terms of configuration scopes (i.e. it's
> the union of the 'system', 'global', and 'command' scopes). This
> description is fine for ML discussions, but it's inadequate for end
> users because we don't provide a good description of "configuration
> scopes" in the public docs.
>
> 145d59f482 (config: add '--show-scope' to print the scope of a config
> value, 2020-02-10) introduced the word "scope" to our public docs, but
> that only enumerates the scopes and assumes the user can figure out
> those values mean.

Thanks, I think that "scope" is an appropriate term here. When I
originally read this patch, I was thinking that "origin" would be more
appropriate, since I was recalling the `--show-origin` option to `git
config`. But that shows the file name, and `--show-scope` is a separate
option entirely.

The latter is definitely more appropriate here, so I think this choice
of naming is good and makes sense.

> diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
> index 9376e39aef2..f93d437b898 100644
> --- a/Documentation/git-config.txt
> +++ b/Documentation/git-config.txt
> @@ -297,8 +297,8 @@ The default is to use a pager.
>  FILES
>  -----
>
> -If not set explicitly with `--file`, there are four files where
> -'git config' will search for configuration options:
> +By default, 'git config' will read configuration options from multiple
> +files:
>
>  $(prefix)/etc/gitconfig::
>  	System-wide configuration file.
> @@ -322,27 +322,63 @@ $GIT_DIR/config.worktree::
>  	This is optional and is only searched when
>  	`extensions.worktreeConfig` is present in $GIT_DIR/config.
>
> -If no further options are given, all reading options will read all of these
> -files that are available. If the global or the system-wide configuration
> -file are not available they will be ignored. If the repository configuration
> -file is not available or readable, 'git config' will exit with a non-zero
> -error code. However, in neither case will an error message be issued.
> +You may also provide additional configuration parameters when running any
> +git command by using the `-c` option. See linkgit:git[1] for details.
> +
> +Options will be read from all of these files that are available. If the
> +global or the system-wide configuration file are not available they will be
> +ignored. If the repository configuration file is not available or readable,
> +'git config' will exit with a non-zero error code. However, in neither case
> +will an error message be issued.

Nit: the last sentence is a little awkwardly worded. Perhaps just:
"Note that neither case produces an error message".

> -All writing options will per default write to the repository specific
> +By default, options are only written to the repository specific
>  configuration file. Note that this also affects options like `--replace-all`

Should we mention that this is the same as the "local" scope below?

>  and `--unset`. *'git config' will only ever change one file at a time*.
>
> -You can override these rules using the `--global`, `--system`,
> -`--local`, `--worktree`, and `--file` command-line options; see
> -<<OPTIONS>> above.
> +You can change the way options are read/written by specifying the path to a
> +file (`--file`), or by specifying a configuration scope (`--system`,
> +`--global`, `--local`, `--worktree`); see <<OPTIONS>> above.

I think this paragraph could be slightly more descriptive about what
`--file` does while still linking out to <<OPTIONS>> above for more
detailed information. In the pre-image, we say:

    If not set explicitly with `--file`, there are four files will `git
    config will search`.

So I wonder if something more descriptive in this section might be:

    You can limit which configuration sources are read to or written
    from by specifying the path of a file with the `--file` option, or
    by specifying a scope with `--system`, `--global`, `--local`, or
    `--worktree`. For more, see <<OPTIONS>> above.

I don't think that's so different form what you wrote, but I think it's
a little clearer particularly what `--file` does (instead of "change the
way options are read/written" it "limit[s] which configuration sources
are read to or written from").

> +
> +SCOPES
> +------
> +
> +Each configuration source falls within a configuration scope. The scopes
> +are:
> +
> +system::
> +	$(prefix)/etc/gitconfig
> +
> +global::
> +	$XDG_CONFIG_HOME/git/config
> ++
> +~/.gitconfig
> +
> +local::
> +	$GIT_DIR/config
> +
> +worktree::
> +	$GIT_DIR/config.worktree
> +
> +command::
> +	environment variables
> ++
> +the `-c` option
> +
> +With the exception of 'command', each scope corresponds to a command line
> +option - `--system`, `--global`, `--local`, `--worktree`.

I think a colon after "option" is more appropriate than a single "-"
dash character, but this is definitely a trivial matter that I have no
strong opinion on.

One thing that this reminds me of (which I don't think is worth taking
up here, but perhaps in a future series, or as #leftoverbits) would be
promoting these scopes behind a single option. Back in the day, you
could ask for values out of `git config` by specifying their type with
`--int`, `--bool`, or similar. In e3e042b185 (Merge branch
'tb/config-type', 2018-05-08), we changed to
`--type=<int|bool|color|etc>`, which unified things and made it clearer
which options were grouped together by a single concept.

I think a similar change would make sense here, that is to replace
`--system`, `--global` (and so on) with `--scope=system`,
`--scope=global`, etc.

But that's not material to this series, and just something to think
about for later on if you end up thinking it's a good idea.

> +
> +When reading options, specifying a scope will only read options from the
> +files within that scope. When writing options, specifying a scope will write
> +to the files within that scope (instead of the repository specific
> +configuration file). See <<OPTIONS>> above for a complete description.
>
> +Most configuration options are respected regardless of the scope it is
> +defined in, but some options are only respected in certain scopes. See the
> +option's documentation for the full details.

I assume "the option's" is referring to whichever configuration variable
we're talking about. So it may be clearer to say "See the *respective*
option's documentation for more information" or similar.

Thanks,
Taylor

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v3 2/2] tests: add tests for grep --max-count
  @ 2022-06-22 18:10  6%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-06-22 18:10 UTC (permalink / raw)
  To: Carlos López via GitGitGadget
  Cc: git, Martin Ågren [ ], Paul Eggert [ ], Carlos L.

"Carlos López via GitGitGadget"  <gitgitgadget@gmail.com> writes:

> From: =?UTF-8?q?Carlos=20L=C3=B3pez?= <00xc@protonmail.com>
>
> Add tests for grep's -m / --max-count to check if the option correctly
> outputs limited results, and that it interacts properly with other flags
> that could likely be used in conjunction.
>
> Signed-off-by: Carlos López 00xc@protonmail.com
> ---
>  t/t7810-grep.sh | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 83 insertions(+)

This is better done as part of the previous patch.  The new tests
protect the new code from future breakage.

> diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
> index 69356011713..7b1b8a3cd93 100755
> --- a/t/t7810-grep.sh
> +++ b/t/t7810-grep.sh
> @@ -77,6 +77,7 @@ test_expect_success setup '
>  	# Say hello.
>  	function hello() {
>  	  echo "Hello world."
> +	  echo "Hello again."
>  	} # hello
>  
>  	# Still a no-op.
> @@ -595,6 +596,88 @@ test_expect_success 'grep --files-without-match --quiet' '
>  	test_must_be_empty actual
>  '
>  
> +cat >expected <<EOF &&
> +EOF
> +
> +test_expect_success 'grep --max-count 0 (must exit with non-zero)' '
> +	test_must_fail git grep --max-count 0 foo >actual &&
> +	test_cmp expected actual
> +'

For this particular one, "test_must_be_empty actual" would suffice,
without comparing with the expected output.

> +cat >expected <<EOF &&
> +file:foo mmap bar
> +EOF
> +
> +test_expect_success 'grep --max-count 1' '
> +	git grep --max-count 1 foo >actual &&
> +	test_cmp expected actual
> +'

Writing expected output outside test_expect_success that uses it is
a quite old style but that is because this test script is pretty
much ancient, so mimicking it is OK.  We'd need to come back later
when the tree is quiescent to clean them up, though (#leftoverbits).

> ...
> +	test_cmp expected actual
> +'

The new tests seem to give us a reasonable test coverage.  We could
discard one of the "-m1" vs "-m3" in the early ones, as they do not
give much extra test coverage over the other, to reduce repetition.

We do not test a case where we pick up-to N matches each from
multiple files, though.  Perhaps

    git grep -m1 -e o -- hello.\*

may stop after hitting "No-op." in hello.ps1 and "stdio" in hello.c,
which may make a good test, perhaps?

Thanks.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] revision: mark blobs needed for resolve-undo as reachable
  @ 2022-06-15 20:47  6%           ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2022-06-15 20:47 UTC (permalink / raw)
  To: Jeff King
  Cc: Taylor Blau, Derrick Stolee,
	Ævar Arnfjörð Bjarmason, Junio C Hamano, git

On Tue, Jun 14, 2022 at 11:48:20PM -0400, Jeff King wrote:
> On Tue, Jun 14, 2022 at 10:02:32PM -0400, Taylor Blau wrote:
>
> > --- >8 ---
> >
> > diff --git a/string-list.h b/string-list.h
> > index d5a744e143..425abc55f4 100644
> > --- a/string-list.h
> > +++ b/string-list.h
> > @@ -143,7 +143,7 @@ int for_each_string_list(struct string_list *list,
> >
> >  /** Iterate over each item, as a macro. */
> >  #define for_each_string_list_item(item,list)            \
> > -	for (item = (list)->items;                      \
> > +	for (item = (list) ? (list)->items : NULL;      \
> >  	     item && item < (list)->items + (list)->nr; \
> >  	     ++item)
> >
> > --- 8< ---
> >
> > > but even with your suggestion, I get this compiler error:
> >
> > ...so did I. Though I'm not sure I understand the compiler's warning
> > here. Surely the thing being passed as list in the macro expansion
> > _won't_ always evaluate to non-NULL, will it?
>
> In the general case, no, but in this specific expansion of the macro, it
> is passing the address of a local variable (&cpath), which will never be
> NULL. The compiler is overeager here; the check is indeed pointless in
> this expansion, but warning on useless macro-expanded code isn't
> helpful, since other macro users need it.

Ah, that makes sense. The compiler is warning us that the macro-expanded
version of for_each_string_list_item() has a ternary expression that
will never evaluate its right-hand side in cases where it can prove the
second argument to the macro is non-NULL.

> Hiding it in a function seems to work, even with -O2 inlining, like:
>
> diff --git a/string-list.h b/string-list.h
> index d5a744e143..b28b135e11 100644
> --- a/string-list.h
> +++ b/string-list.h
> @@ -141,9 +141,14 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
>  int for_each_string_list(struct string_list *list,
>  			 string_list_each_func_t func, void *cb_data);
>
> +static inline struct string_list_item *string_list_first_item(const struct string_list *list)
> +{
> +	return list ? list->items : NULL;
> +}
> +
>  /** Iterate over each item, as a macro. */
>  #define for_each_string_list_item(item,list)            \
> -	for (item = (list)->items;                      \
> +	for (item = string_list_first_item(list);       \
>  	     item && item < (list)->items + (list)->nr; \
>  	     ++item)

That works, nice. I don't really want to mess up the tree too much this
close to a release, but this sort of clean-up seems good to do. I know
Stolee identified a handful of spots that would benefit from it. Some
good #leftoverbits, I guess :-).

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] t5510-fetch: upgrade to a more modern style
  2022-04-01 20:11  0% ` Junio C Hamano
@ 2022-04-02  7:32  0%   ` Elia Pinto
  0 siblings, 0 replies; 200+ results
From: Elia Pinto @ 2022-04-02  7:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Il giorno ven 1 apr 2022 alle ore 22:11 Junio C Hamano
<gitster@pobox.com> ha scritto:
>
> Elia Pinto <gitter.spiros@gmail.com> writes:
>
> > Clean up the code style so all the tests, and not just a few,
> > that chdir around isolate themselves in a subshell.
> >
> > Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
> > ---
> > this patch was inspired by a Junio #leftoverbit
> > https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/
> >  t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------
> >  1 file changed, 477 insertions(+), 450 deletions(-)
> >
> > diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> > index 6f38a69fbb..d0b249d276 100755
> > --- a/t/t5510-fetch.sh
> > +++ b/t/t5510-fetch.sh
> > @@ -48,342 +48,349 @@ test_expect_success "clone and setup child repos" '
> >  '
> >
> >  test_expect_success "fetch test" '
> > -     cd "$D" &&
> > -     echo >file updated by origin &&
> > -     git commit -a -m "updated by origin" &&
> > -     cd two &&
> > -     git fetch &&
> > -     git rev-parse --verify refs/heads/one &&
> > -     mine=$(git rev-parse refs/heads/one) &&
> > -     his=$(cd ../one && git rev-parse refs/heads/main) &&
> > -     test "z$mine" = "z$his"
> > +     (
> > +             cd "$D" &&
> > +             echo >file updated by origin &&
> > +             git commit -a -m "updated by origin" &&
> > +             (
> > +                     cd two &&
> > +                     git fetch &&
> > +                     git rev-parse --verify refs/heads/one &&
> > +                     mine=$(git rev-parse refs/heads/one) &&
> > +                     his=$(cd ../one && git rev-parse refs/heads/main) &&
> > +                     test "z$mine" = "z$his"
> > +             )
> > +     )
> >  '
>
> I think the idea of the "first unconditionally go to $D and then do
> these things" pattern was that these tests anticipate that the step
> before them will leave the process in an unexpected directory when
> they begin.  If the original version of this test fails when we
> created the first commit "updated by origin", the next test piece
> will start in "$D" directory, and if we successfully run it to the
> end, the next test piece will start in "$D/ two".
>
> Now, the point of this patch is to make sure each test piece will
> not chdir around by isolating the parts that run in different
> directories inside subshells.  The purpose of doing so is?  It is to
> relieve later tests from having to worry about "going back to the
> known starting place".
>
> So, it is dubious that we want the subshell around the whole thing,
> whose first command is to go to "$D", after we apply this patch.
> Removal of that part was the primary reason why we are writing this
> patch.
That is fine. I had misinterpreted your answer here
https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/

So the right thing to do is to leave "cd $ D" not in a subshell while
the actual test yes.
But at this point "cd $D" should be removed from subsequent tests, as
it is redundant.
In fact, if the first test of the chain fails, all the others would
always execute
with the current directory equal to $D for sure.
>
> So I'd expect that the above test piece would become more like
> in "git diff -w" output.
>
> It is important to notice that the reason why we had 'cd "$D"' in
> this test is *not* because the previous test has chdir'ed around,
> but to look similar to later tests in the series.
>
> Thanks.
>
>
> diff --git c/t/t5510-fetch.sh w/t/t5510-fetch.sh
> index 6f38a69fbb..1ed27607e2 100755
> --- c/t/t5510-fetch.sh
> +++ w/t/t5510-fetch.sh
> @@ -48,15 +48,16 @@ test_expect_success "clone and setup child repos" '
>  '
>
>  test_expect_success "fetch test" '
> -       cd "$D" &&
>         echo >file updated by origin &&
>         git commit -a -m "updated by origin" &&
> +       (
>                 cd two &&
>                 git fetch &&
>                 git rev-parse --verify refs/heads/one &&
>                 mine=$(git rev-parse refs/heads/one) &&
>                 his=$(cd ../one && git rev-parse refs/heads/main) &&
>                 test "z$mine" = "z$his"
> +       )
>  '
>
>  test_expect_success "fetch test for-merge" '

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] t5510-fetch: upgrade to a more modern style
  2022-03-31 17:54  1% [PATCH] t5510-fetch: upgrade to a more modern style Elia Pinto
@ 2022-04-01 20:11  0% ` Junio C Hamano
  2022-04-02  7:32  0%   ` Elia Pinto
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-04-01 20:11 UTC (permalink / raw)
  To: Elia Pinto; +Cc: git

Elia Pinto <gitter.spiros@gmail.com> writes:

> Clean up the code style so all the tests, and not just a few,
> that chdir around isolate themselves in a subshell.
>
> Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
> ---
> this patch was inspired by a Junio #leftoverbit
> https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/
>  t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------
>  1 file changed, 477 insertions(+), 450 deletions(-)
>
> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> index 6f38a69fbb..d0b249d276 100755
> --- a/t/t5510-fetch.sh
> +++ b/t/t5510-fetch.sh
> @@ -48,342 +48,349 @@ test_expect_success "clone and setup child repos" '
>  '
>  
>  test_expect_success "fetch test" '
> -	cd "$D" &&
> -	echo >file updated by origin &&
> -	git commit -a -m "updated by origin" &&
> -	cd two &&
> -	git fetch &&
> -	git rev-parse --verify refs/heads/one &&
> -	mine=$(git rev-parse refs/heads/one) &&
> -	his=$(cd ../one && git rev-parse refs/heads/main) &&
> -	test "z$mine" = "z$his"
> +	(
> +		cd "$D" &&
> +		echo >file updated by origin &&
> +		git commit -a -m "updated by origin" &&
> +		(
> +			cd two &&
> +			git fetch &&
> +			git rev-parse --verify refs/heads/one &&
> +			mine=$(git rev-parse refs/heads/one) &&
> +			his=$(cd ../one && git rev-parse refs/heads/main) &&
> +			test "z$mine" = "z$his"
> +		)
> +	)
>  '

I think the idea of the "first unconditionally go to $D and then do
these things" pattern was that these tests anticipate that the step
before them will leave the process in an unexpected directory when
they begin.  If the original version of this test fails when we
created the first commit "updated by origin", the next test piece
will start in "$D" directory, and if we successfully run it to the
end, the next test piece will start in "$D/ two".

Now, the point of this patch is to make sure each test piece will
not chdir around by isolating the parts that run in different
directories inside subshells.  The purpose of doing so is?  It is to
relieve later tests from having to worry about "going back to the
known starting place".

So, it is dubious that we want the subshell around the whole thing,
whose first command is to go to "$D", after we apply this patch.
Removal of that part was the primary reason why we are writing this
patch.

So I'd expect that the above test piece would become more like
in "git diff -w" output.

It is important to notice that the reason why we had 'cd "$D"' in
this test is *not* because the previous test has chdir'ed around,
but to look similar to later tests in the series.

Thanks.


diff --git c/t/t5510-fetch.sh w/t/t5510-fetch.sh
index 6f38a69fbb..1ed27607e2 100755
--- c/t/t5510-fetch.sh
+++ w/t/t5510-fetch.sh
@@ -48,15 +48,16 @@ test_expect_success "clone and setup child repos" '
 '
 
 test_expect_success "fetch test" '
-	cd "$D" &&
 	echo >file updated by origin &&
 	git commit -a -m "updated by origin" &&
+	(
 		cd two &&
 		git fetch &&
 		git rev-parse --verify refs/heads/one &&
 		mine=$(git rev-parse refs/heads/one) &&
 		his=$(cd ../one && git rev-parse refs/heads/main) &&
 		test "z$mine" = "z$his"
+	)
 '
 
 test_expect_success "fetch test for-merge" '

^ permalink raw reply related	[relevance 0%]

* [PATCH] t5510-fetch: upgrade to a more modern style
@ 2022-03-31 17:54  1% Elia Pinto
  2022-04-01 20:11  0% ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Elia Pinto @ 2022-03-31 17:54 UTC (permalink / raw)
  To: git; +Cc: Elia Pinto

Clean up the code style so all the tests, and not just a few,
that chdir around isolate themselves in a subshell.

Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
---
this patch was inspired by a Junio #leftoverbit
https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/
 t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------
 1 file changed, 477 insertions(+), 450 deletions(-)

diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 6f38a69fbb..d0b249d276 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -48,342 +48,349 @@ test_expect_success "clone and setup child repos" '
 '
 
 test_expect_success "fetch test" '
-	cd "$D" &&
-	echo >file updated by origin &&
-	git commit -a -m "updated by origin" &&
-	cd two &&
-	git fetch &&
-	git rev-parse --verify refs/heads/one &&
-	mine=$(git rev-parse refs/heads/one) &&
-	his=$(cd ../one && git rev-parse refs/heads/main) &&
-	test "z$mine" = "z$his"
+	(
+		cd "$D" &&
+		echo >file updated by origin &&
+		git commit -a -m "updated by origin" &&
+		(
+			cd two &&
+			git fetch &&
+			git rev-parse --verify refs/heads/one &&
+			mine=$(git rev-parse refs/heads/one) &&
+			his=$(cd ../one && git rev-parse refs/heads/main) &&
+			test "z$mine" = "z$his"
+		)
+	)
 '
 
 test_expect_success "fetch test for-merge" '
-	cd "$D" &&
-	cd three &&
-	git fetch &&
-	git rev-parse --verify refs/heads/two &&
-	git rev-parse --verify refs/heads/one &&
-	main_in_two=$(cd ../two && git rev-parse main) &&
-	one_in_two=$(cd ../two && git rev-parse one) &&
-	{
-		echo "$one_in_two	" &&
-		echo "$main_in_two	not-for-merge"
-	} >expected &&
-	cut -f -2 .git/FETCH_HEAD >actual &&
-	test_cmp expected actual'
+	(
+		cd "$D" &&
+		(
+			cd three &&
+			git fetch &&
+			git rev-parse --verify refs/heads/two &&
+			git rev-parse --verify refs/heads/one &&
+			main_in_two=$(cd ../two && git rev-parse main) &&
+			one_in_two=$(cd ../two && git rev-parse one) &&
+			{
+				echo "$one_in_two	" &&
+				echo "$main_in_two	not-for-merge"
+			} >expected &&
+			cut -f -2 .git/FETCH_HEAD >actual &&
+			test_cmp expected actual
+		)
+	)
+'
 
 test_expect_success 'fetch --prune on its own works as expected' '
-	cd "$D" &&
-	git clone . prune &&
-	cd prune &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-
-	git fetch --prune origin &&
-	test_must_fail git rev-parse origin/extrabranch
+	(
+		cd "$D" &&
+		git clone . prune &&
+		cd prune &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		git fetch --prune origin &&
+		test_must_fail git rev-parse origin/extrabranch
+	)
 '
 
 test_expect_success 'fetch --prune with a branch name keeps branches' '
-	cd "$D" &&
-	git clone . prune-branch &&
-	cd prune-branch &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-
-	git fetch --prune origin main &&
-	git rev-parse origin/extrabranch
+	(
+		cd "$D" &&
+		git clone . prune-branch &&
+		cd prune-branch &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		git fetch --prune origin main &&
+		git rev-parse origin/extrabranch
+	)
 '
 
 test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
-	cd "$D" &&
-	git clone . prune-namespace &&
-	cd prune-namespace &&
-
-	git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
-	git rev-parse origin/main
+	(
+		cd "$D" &&
+		git clone . prune-namespace &&
+		cd prune-namespace &&
+		git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
+		git rev-parse origin/main
+	)
 '
 
 test_expect_success 'fetch --prune handles overlapping refspecs' '
-	cd "$D" &&
-	git update-ref refs/pull/42/head main &&
-	git clone . prune-overlapping &&
-	cd prune-overlapping &&
-	git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
-
-	git fetch --prune origin &&
-	git rev-parse origin/main &&
-	git rev-parse origin/pr/42 &&
-
-	git config --unset-all remote.origin.fetch &&
-	git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
-	git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
-
-	git fetch --prune origin &&
-	git rev-parse origin/main &&
-	git rev-parse origin/pr/42
+	(
+		cd "$D" &&
+		git update-ref refs/pull/42/head main &&
+		git clone . prune-overlapping &&
+		cd prune-overlapping &&
+		git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+		git fetch --prune origin &&
+		git rev-parse origin/main &&
+		git rev-parse origin/pr/42 &&
+		git config --unset-all remote.origin.fetch &&
+		git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+		git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+		git fetch --prune origin &&
+		git rev-parse origin/main &&
+		git rev-parse origin/pr/42
+	)
 '
 
 test_expect_success 'fetch --prune --tags prunes branches but not tags' '
-	cd "$D" &&
-	git clone . prune-tags &&
-	cd prune-tags &&
-	git tag sometag main &&
-	# Create what looks like a remote-tracking branch from an earlier
-	# fetch that has since been deleted from the remote:
-	git update-ref refs/remotes/origin/fake-remote main &&
-
-	git fetch --prune --tags origin &&
-	git rev-parse origin/main &&
-	test_must_fail git rev-parse origin/fake-remote &&
-	git rev-parse sometag
+	(
+		cd "$D" &&
+		git clone . prune-tags &&
+		cd prune-tags &&
+		git tag sometag main &&
+		# Create what looks like a remote-tracking branch from an earlier
+		# fetch that has since been deleted from the remote:
+		git update-ref refs/remotes/origin/fake-remote main &&
+		git fetch --prune --tags origin &&
+		git rev-parse origin/main &&
+		test_must_fail git rev-parse origin/fake-remote &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success 'fetch --prune --tags with branch does not prune other things' '
-	cd "$D" &&
-	git clone . prune-tags-branch &&
-	cd prune-tags-branch &&
-	git tag sometag main &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-
-	git fetch --prune --tags origin main &&
-	git rev-parse origin/extrabranch &&
-	git rev-parse sometag
+	(
+		cd "$D" &&
+		git clone . prune-tags-branch &&
+		cd prune-tags-branch &&
+		git tag sometag main &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		git fetch --prune --tags origin main &&
+		git rev-parse origin/extrabranch &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
-	cd "$D" &&
-	git clone . prune-tags-refspec &&
-	cd prune-tags-refspec &&
-	git tag sometag main &&
-	git update-ref refs/remotes/origin/foo/otherbranch main &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-
-	git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
-	test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
-	git rev-parse origin/extrabranch &&
-	git rev-parse sometag
+	(
+		cd "$D" &&
+		git clone . prune-tags-refspec &&
+		cd prune-tags-refspec &&
+		git tag sometag main &&
+		git update-ref refs/remotes/origin/foo/otherbranch main &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+		test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+		git rev-parse origin/extrabranch &&
+		git rev-parse sometag
+	)
 '
 
 test_expect_success REFFILES 'fetch --prune fails to delete branches' '
-	cd "$D" &&
-	git clone . prune-fail &&
-	cd prune-fail &&
-	git update-ref refs/remotes/origin/extrabranch main &&
-	: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&
-	>.git/packed-refs.new &&
-
-	test_must_fail git fetch --prune origin
+	(
+		cd "$D" &&
+		git clone . prune-fail &&
+		cd prune-fail &&
+		git update-ref refs/remotes/origin/extrabranch main &&
+		: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&
+		>.git/packed-refs.new &&
+		test_must_fail git fetch --prune origin
+	)
 '
 
 test_expect_success 'fetch --atomic works with a single branch' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	git branch atomic-branch &&
-	oid=$(git rev-parse atomic-branch) &&
-	echo "$oid" >expected &&
-
-	git -C atomic fetch --atomic origin &&
-	git -C atomic rev-parse origin/atomic-branch >actual &&
-	test_cmp expected actual &&
-	test $oid = "$(git -C atomic rev-parse --verify FETCH_HEAD)"
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		git branch atomic-branch &&
+		oid=$(git rev-parse atomic-branch) &&
+		echo "$oid" >expected &&
+		git -C atomic fetch --atomic origin &&
+		git -C atomic rev-parse origin/atomic-branch >actual &&
+		test_cmp expected actual &&
+		test $oid = "$(git -C atomic rev-parse --verify FETCH_HEAD)"
+	)
 '
 
 test_expect_success 'fetch --atomic works with multiple branches' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	git branch atomic-branch-1 &&
-	git branch atomic-branch-2 &&
-	git branch atomic-branch-3 &&
-	git rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual &&
-
-	git -C atomic fetch --atomic origin &&
-	git -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected &&
-	test_cmp expected actual
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		git branch atomic-branch-1 &&
+		git branch atomic-branch-2 &&
+		git branch atomic-branch-3 &&
+		git rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual &&
+		git -C atomic fetch --atomic origin &&
+		git -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected &&
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'fetch --atomic works with mixed branches and tags' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	git branch atomic-mixed-branch &&
-	git tag atomic-mixed-tag &&
-	git rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual &&
-
-	git -C atomic fetch --tags --atomic origin &&
-	git -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected &&
-	test_cmp expected actual
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		git branch atomic-mixed-branch &&
+		git tag atomic-mixed-tag &&
+		git rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual &&
+		git -C atomic fetch --tags --atomic origin &&
+		git -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected &&
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'fetch --atomic prunes references' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git branch atomic-prune-delete &&
-	git clone . atomic &&
-	git branch --delete atomic-prune-delete &&
-	git branch atomic-prune-create &&
-	git rev-parse refs/heads/atomic-prune-create >actual &&
-
-	git -C atomic fetch --prune --atomic origin &&
-	test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete &&
-	git -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected &&
-	test_cmp expected actual
+	(
+		cd "$D" &&
+		git branch atomic-prune-delete &&
+		git clone . atomic &&
+		git branch --delete atomic-prune-delete &&
+		git branch atomic-prune-create &&
+		git rev-parse refs/heads/atomic-prune-create >actual &&
+		git -C atomic fetch --prune --atomic origin &&
+		test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete &&
+		git -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected &&
+		test_cmp expected actual
+	)
 '
 
 test_expect_success 'fetch --atomic aborts with non-fast-forward update' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git branch atomic-non-ff &&
-	git clone . atomic &&
-	git rev-parse HEAD >actual &&
-
-	git branch atomic-new-branch &&
-	parent_commit=$(git rev-parse atomic-non-ff~) &&
-	git update-ref refs/heads/atomic-non-ff $parent_commit &&
-
-	test_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* &&
-	test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch &&
-	git -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected &&
-	test_cmp expected actual &&
-	test_must_be_empty atomic/.git/FETCH_HEAD
+	(
+		cd "$D" &&
+		git branch atomic-non-ff &&
+		git clone . atomic &&
+		git rev-parse HEAD >actual &&
+		git branch atomic-new-branch &&
+		parent_commit=$(git rev-parse atomic-non-ff~) &&
+		git update-ref refs/heads/atomic-non-ff $parent_commit &&
+		test_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* &&
+		test_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch &&
+		git -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected &&
+		test_cmp expected actual &&
+		test_must_be_empty atomic/.git/FETCH_HEAD
+	)
 '
 
 test_expect_success 'fetch --atomic executes a single reference transaction only' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	git branch atomic-hooks-1 &&
-	git branch atomic-hooks-2 &&
-	head_oid=$(git rev-parse HEAD) &&
-
-	cat >expected <<-EOF &&
-		prepared
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
-		committed
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
-	EOF
-
-	rm -f atomic/actual &&
-	test_hook -C atomic reference-transaction <<-\EOF &&
-		( echo "$*" && cat ) >>actual
-	EOF
-
-	git -C atomic fetch --atomic origin &&
-	test_cmp expected atomic/actual
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		git branch atomic-hooks-1 &&
+		git branch atomic-hooks-2 &&
+		head_oid=$(git rev-parse HEAD) &&
+		cat >expected <<-EOF &&
+			prepared
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
+			committed
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2
+		EOF
+		rm -f atomic/actual &&
+		write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
+			( echo "$*" && cat ) >>actual
+		EOF
+		git -C atomic fetch --atomic origin &&
+		test_cmp expected atomic/actual
+	)
 '
 
 test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	git branch atomic-hooks-abort-1 &&
-	git branch atomic-hooks-abort-2 &&
-	git branch atomic-hooks-abort-3 &&
-	git tag atomic-hooks-abort &&
-	head_oid=$(git rev-parse HEAD) &&
-
-	cat >expected <<-EOF &&
-		prepared
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
-		$ZERO_OID $head_oid refs/tags/atomic-hooks-abort
-		aborted
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
-		$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
-		$ZERO_OID $head_oid refs/tags/atomic-hooks-abort
-	EOF
-
-	rm -f atomic/actual &&
-	test_hook -C atomic/.git reference-transaction <<-\EOF &&
-		( echo "$*" && cat ) >>actual
-		exit 1
-	EOF
-
-	git -C atomic for-each-ref >expected-refs &&
-	test_must_fail git -C atomic fetch --tags --atomic origin &&
-	git -C atomic for-each-ref >actual-refs &&
-	test_cmp expected-refs actual-refs &&
-	test_must_be_empty atomic/.git/FETCH_HEAD
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		git branch atomic-hooks-abort-1 &&
+		git branch atomic-hooks-abort-2 &&
+		git branch atomic-hooks-abort-3 &&
+		git tag atomic-hooks-abort &&
+		head_oid=$(git rev-parse HEAD) &&
+		cat >expected <<-EOF &&
+			prepared
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
+			$ZERO_OID $head_oid refs/tags/atomic-hooks-abort
+			aborted
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2
+			$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3
+			$ZERO_OID $head_oid refs/tags/atomic-hooks-abort
+		EOF
+		rm -f atomic/actual &&
+		write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
+			( echo "$*" && cat ) >>actual
+			exit 1
+		EOF
+		git -C atomic for-each-ref >expected-refs &&
+		test_must_fail git -C atomic fetch --tags --atomic origin &&
+		git -C atomic for-each-ref >actual-refs &&
+		test_cmp expected-refs actual-refs &&
+		test_must_be_empty atomic/.git/FETCH_HEAD
+	)
 '
 
 test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git clone . atomic &&
-	oid=$(git rev-parse HEAD) &&
-
-	git branch atomic-fetch-head-1 &&
-	git -C atomic fetch --atomic origin atomic-fetch-head-1 &&
-	test_line_count = 1 atomic/.git/FETCH_HEAD &&
-
-	git branch atomic-fetch-head-2 &&
-	git -C atomic fetch --atomic --append origin atomic-fetch-head-2 &&
-	test_line_count = 2 atomic/.git/FETCH_HEAD &&
-	cp atomic/.git/FETCH_HEAD expected &&
-
-	test_hook -C atomic reference-transaction <<-\EOF &&
-		exit 1
-	EOF
-
-	git branch atomic-fetch-head-3 &&
-	test_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 &&
-	test_cmp expected atomic/.git/FETCH_HEAD
+	(
+		cd "$D" &&
+		git clone . atomic &&
+		oid=$(git rev-parse HEAD) &&
+		git branch atomic-fetch-head-1 &&
+		git -C atomic fetch --atomic origin atomic-fetch-head-1 &&
+		test_line_count = 1 atomic/.git/FETCH_HEAD &&
+		git branch atomic-fetch-head-2 &&
+		git -C atomic fetch --atomic --append origin atomic-fetch-head-2 &&
+		test_line_count = 2 atomic/.git/FETCH_HEAD &&
+		cp atomic/.git/FETCH_HEAD expected &&
+		write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
+			exit 1
+		EOF
+		git branch atomic-fetch-head-3 &&
+		test_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 &&
+		test_cmp expected atomic/.git/FETCH_HEAD
+	)
 '
 
 test_expect_success 'fetch --atomic --prune executes a single reference transaction only' '
 	test_when_finished "rm -rf \"$D\"/atomic" &&
-
-	cd "$D" &&
-	git branch scheduled-for-deletion &&
-	git clone . atomic &&
-	git branch -D scheduled-for-deletion &&
-	git branch new-branch &&
-	head_oid=$(git rev-parse HEAD) &&
-
-	# Fetching with the `--atomic` flag should update all references in a
-	# single transaction.
-	cat >expected <<-EOF &&
-		prepared
-		$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
-		$ZERO_OID $head_oid refs/remotes/origin/new-branch
-		committed
-		$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
-		$ZERO_OID $head_oid refs/remotes/origin/new-branch
-	EOF
-
-	test_hook -C atomic reference-transaction <<-\EOF &&
-		( echo "$*" && cat ) >>actual
-	EOF
-
-	git -C atomic fetch --atomic --prune origin &&
-	test_cmp expected atomic/actual
+	(
+		cd "$D" &&
+		git branch scheduled-for-deletion &&
+		git clone . atomic &&
+		git branch -D scheduled-for-deletion &&
+		git branch new-branch &&
+		head_oid=$(git rev-parse HEAD) &&
+		# Fetching with the `--atomic` flag should update all references in a
+		# single transaction.
+		cat >expected <<-EOF &&
+			prepared
+			$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
+			$ZERO_OID $head_oid refs/remotes/origin/new-branch
+			committed
+			$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion
+			$ZERO_OID $head_oid refs/remotes/origin/new-branch
+		EOF
+		write_script atomic/.git/hooks/reference-transaction <<-\EOF &&
+			( echo "$*" && cat ) >>actual
+		EOF
+		git -C atomic fetch --atomic --prune origin &&
+		test_cmp expected atomic/actual
+	)
 '
 
 test_expect_success '--refmap="" ignores configured refspec' '
-	cd "$TRASH_DIRECTORY" &&
-	git clone "$D" remote-refs &&
-	git -C remote-refs rev-parse remotes/origin/main >old &&
-	git -C remote-refs update-ref refs/remotes/origin/main main~1 &&
-	git -C remote-refs rev-parse remotes/origin/main >new &&
-	git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" &&
-	git -C remote-refs rev-parse remotes/origin/main >actual &&
-	test_cmp new actual &&
-	git -C remote-refs fetch origin &&
-	git -C remote-refs rev-parse remotes/origin/main >actual &&
-	test_cmp old actual
+	(
+		cd "$TRASH_DIRECTORY" &&
+		git clone "$D" remote-refs &&
+		git -C remote-refs rev-parse remotes/origin/main >old &&
+		git -C remote-refs update-ref refs/remotes/origin/main main~1 &&
+		git -C remote-refs rev-parse remotes/origin/main >new &&
+		git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" &&
+		git -C remote-refs rev-parse remotes/origin/main >actual &&
+		test_cmp new actual &&
+		git -C remote-refs fetch origin &&
+		git -C remote-refs rev-parse remotes/origin/main >actual &&
+		test_cmp old actual
+	)
 '
 
 test_expect_success '--refmap="" and --prune' '
@@ -397,89 +404,86 @@ test_expect_success '--refmap="" and --prune' '
 '
 
 test_expect_success 'fetch tags when there is no tags' '
-
-    cd "$D" &&
-
-    mkdir notags &&
-    cd notags &&
-    git init &&
-
-    git fetch -t ..
-
+	(
+		cd "$D" &&
+		mkdir notags &&
+		cd notags &&
+		git init &&
+		git fetch -t ..
+	)
 '
 
 test_expect_success 'fetch following tags' '
-
-	cd "$D" &&
-	git tag -a -m "annotated" anno HEAD &&
-	git tag light HEAD &&
-
-	mkdir four &&
-	cd four &&
-	git init &&
-
-	git fetch .. :track &&
-	git show-ref --verify refs/tags/anno &&
-	git show-ref --verify refs/tags/light
-
+	(
+		cd "$D" &&
+		git tag -a -m "annotated" anno HEAD &&
+		git tag light HEAD &&
+		mkdir four &&
+		cd four &&
+		git init &&
+		git fetch .. :track &&
+		git show-ref --verify refs/tags/anno &&
+		git show-ref --verify refs/tags/light
+	)
 '
 
 test_expect_success 'fetch uses remote ref names to describe new refs' '
-	cd "$D" &&
-	git init descriptive &&
-	(
-		cd descriptive &&
-		git config remote.o.url .. &&
-		git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
-		git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
-		git fetch o
-	) &&
-	git tag -a -m "Descriptive tag" descriptive-tag &&
-	git branch descriptive-branch &&
-	git checkout descriptive-branch &&
-	echo "Nuts" >crazy &&
-	git add crazy &&
-	git commit -a -m "descriptive commit" &&
-	git update-ref refs/others/crazy HEAD &&
 	(
-		cd descriptive &&
-		git fetch o 2>actual &&
-		test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual &&
-		test_i18ngrep "new tag.* -> descriptive-tag$" actual &&
-		test_i18ngrep "new ref.* -> crazy$" actual
-	) &&
-	git checkout main
+		cd "$D" &&
+		git init descriptive &&
+		(
+			cd descriptive &&
+			git config remote.o.url .. &&
+			git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
+			git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
+			git fetch o
+		) &&
+		git tag -a -m "Descriptive tag" descriptive-tag &&
+		git branch descriptive-branch &&
+		git checkout descriptive-branch &&
+		echo "Nuts" >crazy &&
+		git add crazy &&
+		git commit -a -m "descriptive commit" &&
+		git update-ref refs/others/crazy HEAD &&
+		(
+			cd descriptive &&
+			git fetch o 2>actual &&
+			test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual &&
+			test_i18ngrep "new tag.* -> descriptive-tag$" actual &&
+			test_i18ngrep "new ref.* -> crazy$" actual
+		) &&
+		git checkout main
+	)
 '
 
 test_expect_success 'fetch must not resolve short tag name' '
-
-	cd "$D" &&
-
-	mkdir five &&
-	cd five &&
-	git init &&
-
-	test_must_fail git fetch .. anno:five
-
+	(
+		cd "$D" &&
+		mkdir five &&
+		cd five &&
+		git init &&
+		test_must_fail git fetch .. anno:five
+	)
 '
 
 test_expect_success 'fetch can now resolve short remote name' '
-
-	cd "$D" &&
-	git update-ref refs/remotes/six/HEAD HEAD &&
-
-	mkdir six &&
-	cd six &&
-	git init &&
-
-	git fetch .. six:six
+	(
+		cd "$D" &&
+		git update-ref refs/remotes/six/HEAD HEAD &&
+		mkdir six &&
+		cd six &&
+		git init &&
+		git fetch .. six:six
+	)
 '
 
 test_expect_success 'create bundle 1' '
-	cd "$D" &&
-	echo >file updated again by origin &&
-	git commit -a -m "tip" &&
-	git bundle create --version=3 bundle1 main^..main
+	(
+		cd "$D" &&
+		echo >file updated again by origin &&
+		git commit -a -m "tip" &&
+		git bundle create --version=3 bundle1 main^..main
+	)
 '
 
 test_expect_success 'header of bundle looks right' '
@@ -495,43 +499,53 @@ test_expect_success 'header of bundle looks right' '
 '
 
 test_expect_success 'create bundle 2' '
-	cd "$D" &&
-	git bundle create bundle2 main~2..main
+	(
+		cd "$D" &&
+		git bundle create bundle2 main~2..main
+	)
 '
 
 test_expect_success 'unbundle 1' '
-	cd "$D/bundle" &&
-	git checkout -b some-branch &&
-	test_must_fail git fetch "$D/bundle1" main:main
+	(
+		cd "$D/bundle" &&
+		git checkout -b some-branch &&
+		test_must_fail git fetch "$D/bundle1" main:main
+	)
 '
 
 
 test_expect_success 'bundle 1 has only 3 files ' '
-	cd "$D" &&
-	test_bundle_object_count bundle1 3
+	(
+		cd "$D" &&
+		test_bundle_object_count bundle1 3
+	)
 '
 
 test_expect_success 'unbundle 2' '
-	cd "$D/bundle" &&
-	git fetch ../bundle2 main:main &&
-	test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+	(
+		cd "$D/bundle" &&
+		git fetch ../bundle2 main:main &&
+		test "tip" = "$(git log -1 --pretty=oneline main | cut -d" " -f2)"
+	)
 '
 
 test_expect_success 'bundle does not prerequisite objects' '
-	cd "$D" &&
-	touch file2 &&
-	git add file2 &&
-	git commit -m add.file2 file2 &&
-	git bundle create bundle3 -1 HEAD &&
-	test_bundle_object_count bundle3 3
+	(
+		cd "$D" &&
+		touch file2 &&
+		git add file2 &&
+		git commit -m add.file2 file2 &&
+		git bundle create bundle3 -1 HEAD &&
+		test_bundle_object_count bundle3 3
+	)
 '
 
 test_expect_success 'bundle should be able to create a full history' '
-
-	cd "$D" &&
-	git tag -a -m "1.0" v1.0 main &&
-	git bundle create bundle4 v1.0
-
+	(
+		cd "$D" &&
+		git tag -a -m "1.0" v1.0 main &&
+		git bundle create bundle4 v1.0
+	)
 '
 
 test_expect_success 'fetch with a non-applying branch.<name>.merge' '
@@ -581,15 +595,16 @@ test_expect_success 'quoting of a strangely named repo' '
 '
 
 test_expect_success 'bundle should record HEAD correctly' '
-
-	cd "$D" &&
-	git bundle create bundle5 HEAD main &&
-	git bundle list-heads bundle5 >actual &&
-	for h in HEAD refs/heads/main
-	do
-		echo "$(git rev-parse --verify $h) $h" || return 1
-	done >expect &&
-	test_cmp expect actual
+	(
+		cd "$D" &&
+		git bundle create bundle5 HEAD main &&
+		git bundle list-heads bundle5 >actual &&
+		for h in HEAD refs/heads/main
+		do
+			echo "$(git rev-parse --verify $h) $h" || return 1
+		done >expect &&
+		test_cmp expect actual
+	)
 
 '
 
@@ -601,127 +616,139 @@ test_expect_success 'mark initial state of origin/main' '
 '
 
 test_expect_success 'explicit fetch should update tracking' '
-
-	cd "$D" &&
-	git branch -f side &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git fetch origin main &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" != "$n" &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/side
+		cd "$D" &&
+		git branch -f side &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git fetch origin main &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" != "$n" &&
+			test_must_fail git rev-parse --verify refs/remotes/origin/side
+		)
 	)
 '
 
 test_expect_success 'explicit pull should update tracking' '
-
-	cd "$D" &&
-	git branch -f side &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git pull origin main &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" != "$n" &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/side
+		cd "$D" &&
+		git branch -f side &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git pull origin main &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" != "$n" &&
+			test_must_fail git rev-parse --verify refs/remotes/origin/side
+		)
 	)
 '
 
 test_expect_success 'explicit --refmap is allowed only with command-line refspec' '
-	cd "$D" &&
 	(
-		cd three &&
-		test_must_fail git fetch --refmap="*:refs/remotes/none/*"
+		cd "$D" &&
+		(
+			cd three &&
+			test_must_fail git fetch --refmap="*:refs/remotes/none/*"
+		)
 	)
 '
 
 test_expect_success 'explicit --refmap option overrides remote.*.fetch' '
-	cd "$D" &&
-	git branch -f side &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin main &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" = "$n" &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/side &&
-		git rev-parse --verify refs/remotes/other/main
+		cd "$D" &&
+		git branch -f side &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git fetch --refmap="refs/heads/*:refs/remotes/other/*" origin main &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" = "$n" &&
+			test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+			git rev-parse --verify refs/remotes/other/main
+		)
 	)
 '
 
 test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '
-	cd "$D" &&
-	git branch -f side &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git fetch --refmap="" origin main &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" = "$n" &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/side
+		cd "$D" &&
+		git branch -f side &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git fetch --refmap="" origin main &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" = "$n" &&
+			test_must_fail git rev-parse --verify refs/remotes/origin/side
+		)
 	)
 '
 
 test_expect_success 'configured fetch updates tracking' '
-
-	cd "$D" &&
-	git branch -f side &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git fetch origin &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" != "$n" &&
-		git rev-parse --verify refs/remotes/origin/side
+		cd "$D" &&
+		git branch -f side &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git fetch origin &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" != "$n" &&
+			git rev-parse --verify refs/remotes/origin/side
+		)
 	)
 '
 
 test_expect_success 'non-matching refspecs do not confuse tracking update' '
-	cd "$D" &&
-	git update-ref refs/odd/location HEAD &&
 	(
-		cd three &&
-		git update-ref refs/remotes/origin/main base-origin-main &&
-		git config --add remote.origin.fetch \
-			refs/odd/location:refs/remotes/origin/odd &&
-		o=$(git rev-parse --verify refs/remotes/origin/main) &&
-		git fetch origin main &&
-		n=$(git rev-parse --verify refs/remotes/origin/main) &&
-		test "$o" != "$n" &&
-		test_must_fail git rev-parse --verify refs/remotes/origin/odd
+		cd "$D" &&
+		git update-ref refs/odd/location HEAD &&
+		(
+			cd three &&
+			git update-ref refs/remotes/origin/main base-origin-main &&
+			git config --add remote.origin.fetch \
+				refs/odd/location:refs/remotes/origin/odd &&
+			o=$(git rev-parse --verify refs/remotes/origin/main) &&
+			git fetch origin main &&
+			n=$(git rev-parse --verify refs/remotes/origin/main) &&
+			test "$o" != "$n" &&
+			test_must_fail git rev-parse --verify refs/remotes/origin/odd
+		)
 	)
 '
 
 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
-
-	cd "$D" &&
-	test_must_fail git push seven no:no
-
+	(
+		cd "$D" &&
+		test_must_fail git push seven no:no
+	)
 '
 
 test_expect_success 'auto tag following fetches minimum' '
-
-	cd "$D" &&
-	git clone .git follow &&
-	git checkout HEAD^0 &&
 	(
-		for i in 1 2 3 4 5 6 7
-		do
-			echo $i >>file &&
-			git commit -m $i -a &&
-			git tag -a -m $i excess-$i || exit 1
-		done
-	) &&
-	git checkout main &&
-	(
-		cd follow &&
-		git fetch
+		cd "$D" &&
+		git clone .git follow &&
+		git checkout HEAD^0 &&
+		(
+			for i in 1 2 3 4 5 6 7
+			do
+				echo $i >>file &&
+				git commit -m $i -a &&
+				git tag -a -m $i excess-$i || exit 1
+			done
+		) &&
+		git checkout main &&
+		(
+			cd follow &&
+			git fetch
+		)
 	)
 '
 
-- 
2.35.1


^ permalink raw reply related	[relevance 1%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  2022-03-25 15:04  0%         ` Derrick Stolee
@ 2022-03-25 16:35  0%           ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-03-25 16:35 UTC (permalink / raw)
  To: Derrick Stolee
  Cc: Phillip Wood, Victoria Dye via GitGitGadget, git, Victoria Dye

Derrick Stolee <derrickstolee@github.com> writes:

> On 3/24/2022 1:33 PM, Junio C Hamano wrote:
>> Junio C Hamano <gitster@pobox.com> writes:
>>> #leftoverbit: we may want to discuss if it is a good idea to teach
>>> OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
>>> just "--<option>".
>
> Good idea!
>
>> Unfortunately, I merged these already to 'next' before seeing your
>> comment, so we'd need to go incremental.
>> 
>> How about this?
>
>> -		OPT_BOOL(0, "refresh", &refresh,
>> +		OPT_BOOL(0, "no-refresh", &no_refresh,
>>  				N_("skip refreshing the index after reset")),
>
> I'm pleasantly surprised that this still allows --refresh (in addition to
> --no-no-refresh). So, the only meaningful functional change is indeed the
> -h output.

Yeah, it is a pleasant easter egg surprise that --refresh is taken
as the opposite but its cousin that we allow --no-no-refresh is
somehow questionably ugly, albeit it does not hurt anybody, except
for purists who would certainly complain that --no-no-no-refresh is
not understood.



^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  2022-03-24 17:33  0%       ` Junio C Hamano
  2022-03-24 18:01  0%         ` Victoria Dye
@ 2022-03-25 15:04  0%         ` Derrick Stolee
  2022-03-25 16:35  0%           ` Junio C Hamano
  1 sibling, 1 reply; 200+ results
From: Derrick Stolee @ 2022-03-25 15:04 UTC (permalink / raw)
  To: Junio C Hamano, Phillip Wood
  Cc: Victoria Dye via GitGitGadget, git, Victoria Dye

On 3/24/2022 1:33 PM, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>> #leftoverbit: we may want to discuss if it is a good idea to teach
>> OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
>> just "--<option>".

Good idea!

> Unfortunately, I merged these already to 'next' before seeing your
> comment, so we'd need to go incremental.
> 
> How about this?

> -		OPT_BOOL(0, "refresh", &refresh,
> +		OPT_BOOL(0, "no-refresh", &no_refresh,
>  				N_("skip refreshing the index after reset")),

I'm pleasantly surprised that this still allows --refresh (in addition to
--no-no-refresh). So, the only meaningful functional change is indeed the
-h output.

Thanks,
-Stolee

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  2022-03-24 18:01  0%         ` Victoria Dye
@ 2022-03-24 20:36  0%           ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-03-24 20:36 UTC (permalink / raw)
  To: Victoria Dye
  Cc: Phillip Wood, Victoria Dye via GitGitGadget, git, Derrick Stolee

Victoria Dye <vdye@github.com> writes:

> Junio C Hamano wrote:
>> Junio C Hamano <gitster@pobox.com> writes:
>> 
>>> ... as you suggested, I think mimicking how existing commands with
>>> "--no-<option>" are shown, e.g. builtlin/update-ref.c does
>>> "--no-deref",
>>>
>>>     $ git update-ref -h 2>&1 | grep deref
>>>         --no-deref            update <refname> not the one it points to
>>>     $ git grep 'OPT_BOOL.*"no-deref"'
>>>     builtin/update-ref.c:		OPT_BOOL( 0 , "no-deref", &no_deref,
>>>
>>> would be a good approach.
>>>
>>>> The range-diff for the other changes looks good
>>>
>>> Thanks.
>>>
>>> #leftoverbit: we may want to discuss if it is a good idea to teach
>>> OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
>>> just "--<option>".
>> 
>> 
>> Unfortunately, I merged these already to 'next' before seeing your
>> comment, so we'd need to go incremental.
>> 
>> How about this?
>> 
>> ----- >8 --------- >8 --------- >8 --------- >8 -----
>> Subject: [PATCH] reset: show --no-refresh in the short-help
>> 
>> In the short help output from "git reset -h", the recently added
>> "--[no-]refresh" option is shown like so:
>> 
>>         --refresh             skip refreshing the index after reset
>> 
>> which explains what happens when the option is given in the negative
>> form, i.e. "--no-refresh".  We could rephrase the explanation to
>> read "refresh the index after reset (default)" to hint that the user
>> can say "--no-refresh" to override the default, but listing the
>> "--no-refresh" form in the list of options would be more helpful.
>> 
>> Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
>> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>> ---
>>  builtin/reset.c | 6 +++---
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>> 
>> diff --git c/builtin/reset.c w/builtin/reset.c
>> index 1d89faef5e..344fff8f3a 100644
>> --- c/builtin/reset.c
>> +++ w/builtin/reset.c
>> @@ -392,7 +392,7 @@ static int git_reset_config(const char *var, const char *value, void *cb)
>>  int cmd_reset(int argc, const char **argv, const char *prefix)
>>  {
>>  	int reset_type = NONE, update_ref_status = 0, quiet = 0;
>> -	int refresh = 1;
>> +	int no_refresh = 0;
>>  	int patch_mode = 0, pathspec_file_nul = 0, unborn;
>>  	const char *rev, *pathspec_from_file = NULL;
>>  	struct object_id oid;
>> @@ -400,7 +400,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
>>  	int intent_to_add = 0;
>>  	const struct option options[] = {
>>  		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
>> -		OPT_BOOL(0, "refresh", &refresh,
>> +		OPT_BOOL(0, "no-refresh", &no_refresh,
>>  				N_("skip refreshing the index after reset")),
>>  		OPT_SET_INT(0, "mixed", &reset_type,
>>  						N_("reset HEAD and index"), MIXED),
>> @@ -519,7 +519,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
>>  			if (read_from_tree(&pathspec, &oid, intent_to_add))
>>  				return 1;
>>  			the_index.updated_skipworktree = 1;
>> -			if (refresh && get_git_work_tree()) {
>> +			if (!no_refresh && get_git_work_tree()) {
>>  				uint64_t t_begin, t_delta_in_ms;
>>  
>>  				t_begin = getnanotime();
>
> This looks good to me, and it's passing all of the relevant tests. Thank you
> both for your help with this!

OK, will queue this on top.

Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  2022-03-24 17:33  0%       ` Junio C Hamano
@ 2022-03-24 18:01  0%         ` Victoria Dye
  2022-03-24 20:36  0%           ` Junio C Hamano
  2022-03-25 15:04  0%         ` Derrick Stolee
  1 sibling, 1 reply; 200+ results
From: Victoria Dye @ 2022-03-24 18:01 UTC (permalink / raw)
  To: Junio C Hamano, Phillip Wood
  Cc: Victoria Dye via GitGitGadget, git, Derrick Stolee

Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
> 
>> ... as you suggested, I think mimicking how existing commands with
>> "--no-<option>" are shown, e.g. builtlin/update-ref.c does
>> "--no-deref",
>>
>>     $ git update-ref -h 2>&1 | grep deref
>>         --no-deref            update <refname> not the one it points to
>>     $ git grep 'OPT_BOOL.*"no-deref"'
>>     builtin/update-ref.c:		OPT_BOOL( 0 , "no-deref", &no_deref,
>>
>> would be a good approach.
>>
>>> The range-diff for the other changes looks good
>>
>> Thanks.
>>
>> #leftoverbit: we may want to discuss if it is a good idea to teach
>> OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
>> just "--<option>".
> 
> 
> Unfortunately, I merged these already to 'next' before seeing your
> comment, so we'd need to go incremental.
> 
> How about this?
> 
> ----- >8 --------- >8 --------- >8 --------- >8 -----
> Subject: [PATCH] reset: show --no-refresh in the short-help
> 
> In the short help output from "git reset -h", the recently added
> "--[no-]refresh" option is shown like so:
> 
>         --refresh             skip refreshing the index after reset
> 
> which explains what happens when the option is given in the negative
> form, i.e. "--no-refresh".  We could rephrase the explanation to
> read "refresh the index after reset (default)" to hint that the user
> can say "--no-refresh" to override the default, but listing the
> "--no-refresh" form in the list of options would be more helpful.
> 
> Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  builtin/reset.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git c/builtin/reset.c w/builtin/reset.c
> index 1d89faef5e..344fff8f3a 100644
> --- c/builtin/reset.c
> +++ w/builtin/reset.c
> @@ -392,7 +392,7 @@ static int git_reset_config(const char *var, const char *value, void *cb)
>  int cmd_reset(int argc, const char **argv, const char *prefix)
>  {
>  	int reset_type = NONE, update_ref_status = 0, quiet = 0;
> -	int refresh = 1;
> +	int no_refresh = 0;
>  	int patch_mode = 0, pathspec_file_nul = 0, unborn;
>  	const char *rev, *pathspec_from_file = NULL;
>  	struct object_id oid;
> @@ -400,7 +400,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
>  	int intent_to_add = 0;
>  	const struct option options[] = {
>  		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
> -		OPT_BOOL(0, "refresh", &refresh,
> +		OPT_BOOL(0, "no-refresh", &no_refresh,
>  				N_("skip refreshing the index after reset")),
>  		OPT_SET_INT(0, "mixed", &reset_type,
>  						N_("reset HEAD and index"), MIXED),
> @@ -519,7 +519,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
>  			if (read_from_tree(&pathspec, &oid, intent_to_add))
>  				return 1;
>  			the_index.updated_skipworktree = 1;
> -			if (refresh && get_git_work_tree()) {
> +			if (!no_refresh && get_git_work_tree()) {
>  				uint64_t t_begin, t_delta_in_ms;
>  
>  				t_begin = getnanotime();

This looks good to me, and it's passing all of the relevant tests. Thank you
both for your help with this!

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  2022-03-24 17:13  6%     ` Junio C Hamano
@ 2022-03-24 17:33  0%       ` Junio C Hamano
  2022-03-24 18:01  0%         ` Victoria Dye
  2022-03-25 15:04  0%         ` Derrick Stolee
  0 siblings, 2 replies; 200+ results
From: Junio C Hamano @ 2022-03-24 17:33 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Victoria Dye via GitGitGadget, git, Victoria Dye, Derrick Stolee

Junio C Hamano <gitster@pobox.com> writes:

> ... as you suggested, I think mimicking how existing commands with
> "--no-<option>" are shown, e.g. builtlin/update-ref.c does
> "--no-deref",
>
>     $ git update-ref -h 2>&1 | grep deref
>         --no-deref            update <refname> not the one it points to
>     $ git grep 'OPT_BOOL.*"no-deref"'
>     builtin/update-ref.c:		OPT_BOOL( 0 , "no-deref", &no_deref,
>
> would be a good approach.
>
>> The range-diff for the other changes looks good
>
> Thanks.
>
> #leftoverbit: we may want to discuss if it is a good idea to teach
> OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
> just "--<option>".


Unfortunately, I merged these already to 'next' before seeing your
comment, so we'd need to go incremental.

How about this?

----- >8 --------- >8 --------- >8 --------- >8 -----
Subject: [PATCH] reset: show --no-refresh in the short-help

In the short help output from "git reset -h", the recently added
"--[no-]refresh" option is shown like so:

        --refresh             skip refreshing the index after reset

which explains what happens when the option is given in the negative
form, i.e. "--no-refresh".  We could rephrase the explanation to
read "refresh the index after reset (default)" to hint that the user
can say "--no-refresh" to override the default, but listing the
"--no-refresh" form in the list of options would be more helpful.

Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/reset.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git c/builtin/reset.c w/builtin/reset.c
index 1d89faef5e..344fff8f3a 100644
--- c/builtin/reset.c
+++ w/builtin/reset.c
@@ -392,7 +392,7 @@ static int git_reset_config(const char *var, const char *value, void *cb)
 int cmd_reset(int argc, const char **argv, const char *prefix)
 {
 	int reset_type = NONE, update_ref_status = 0, quiet = 0;
-	int refresh = 1;
+	int no_refresh = 0;
 	int patch_mode = 0, pathspec_file_nul = 0, unborn;
 	const char *rev, *pathspec_from_file = NULL;
 	struct object_id oid;
@@ -400,7 +400,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 	int intent_to_add = 0;
 	const struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
-		OPT_BOOL(0, "refresh", &refresh,
+		OPT_BOOL(0, "no-refresh", &no_refresh,
 				N_("skip refreshing the index after reset")),
 		OPT_SET_INT(0, "mixed", &reset_type,
 						N_("reset HEAD and index"), MIXED),
@@ -519,7 +519,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			if (read_from_tree(&pathspec, &oid, intent_to_add))
 				return 1;
 			the_index.updated_skipworktree = 1;
-			if (refresh && get_git_work_tree()) {
+			if (!no_refresh && get_git_work_tree()) {
 				uint64_t t_begin, t_delta_in_ms;
 
 				t_begin = getnanotime();

^ permalink raw reply related	[relevance 0%]

* Re: [PATCH v2 0/3] reset: make --no-refresh the only way to skip index refresh
  @ 2022-03-24 17:13  6%     ` Junio C Hamano
  2022-03-24 17:33  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-03-24 17:13 UTC (permalink / raw)
  To: Phillip Wood
  Cc: Victoria Dye via GitGitGadget, git, Victoria Dye, Derrick Stolee

Phillip Wood <phillip.wood123@gmail.com> writes:

> I should have been clearer in my comments that I think changing the
> option name no '--no-refresh' whilst retaining '--refresh' is 
> worthwhile. '--no-refresh' is the form that users will want most of
> the time and changing the option name means that the useful version
> will be shown by "reset -h".

I am OK with it shown as "--[no-]refresh" or even "--refresh" alone,
as long as the description describes the "refresh" behaviour and
makes it clear that it is the default, with the expectation that the
users know from other boolean options that "--option" listed in "-h"
would naturally take "--no-option".

But as posted, 

    $ rungit seen reset -h 2>&1 | grep refresh
        --refresh             skip refreshing the index after reset

the explanation given is for "--no-refresh" (which is wrong), so
we'd need some fix in the area.  We could rephrase it to read

        --refresh             refresh the index after reset (default)

but as you suggested, I think mimicking how existing commands with
"--no-<option>" are shown, e.g. builtlin/update-ref.c does
"--no-deref",

    $ git update-ref -h 2>&1 | grep deref
        --no-deref            update <refname> not the one it points to
    $ git grep 'OPT_BOOL.*"no-deref"'
    builtin/update-ref.c:		OPT_BOOL( 0 , "no-deref", &no_deref,

would be a good approach.

> The range-diff for the other changes looks good

Thanks.

#leftoverbit: we may want to discuss if it is a good idea to teach
OPT_BOOL() to list "--[no-]<option>" in "git cmd -h", instead of
just "--<option>".

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 00/41] use the stdlib EXIT_SUCCESS or EXIT_FAILURE exit status
  @ 2022-03-23 11:13  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-03-23 11:13 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: Elia Pinto, git

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> We also document for some of these programs that on failure we'll
> return 1 specifically, not whatever EXIT_FAILURE is.

I view this as a real issue.  EXIT_FAILURE could by happenstance be
defined to be the same value on all platforms we care about, but if
it leaves the possibility that the next major thing will break our
assumption, I do not see much point in adopting it.  Whole-sale
rewriting of 0 and 1 to EXIT_SUCCESS and EXIT_FAILURE smells like
adopting a bad standardization without thinking things through, only
for the sake of adopting "standardization".

> ... but we should fix the exit(-1) cases, and that's best done
> with some new GIT_TEST_ASSERT_NO_UNPORTABLE_EXIT testing or
> whatever.

That is probably a good #leftoverbit, even a candidate for future
#microprojects.

> I think we'd be much better off with something like this in
> git-compat-util.h:
>
>     #ifndef BYPASS_EXIT_SANITY
>     #ifdef EXIT_SUCCESS
>     #if EXIT_SUCCESS != 0
>     #error "git assumes EXIT_SUCCESS is 0, not whatever yours is, please report this. Build with -DBYPASS_EXIT_SANITY to continue building at your own risk"

This is not a good idea.  EXIT_SUCCESS does not have to be literally
0.  It only has to be a value that causes the process to exit with 0
when passed to exit().

>     #endif
>     #endif
>     #ifdef EXIT_FAILURE
>     #if EXIT_FAILURE != 0

I think you meant "!= 1".  If we were to take these 41 patches, we
must have this hunk, as we want our plumbing tools to be drivable by
shell scripts, i.e. 

	git foo ||
	case $? in
	1) # generic failure
		...
	esac

and we do not want to be forced to write something like

	. git-stdlib-util.sh ;# for platform-dependent $EXIT_FAILURE

	...
	git foo ||
	case $? in
	$EXIT_FAILURE) # generic failure
		...
	esac
	
instead.

^ permalink raw reply	[relevance 6%]

* Re: [RFC PATCH 1/1] Documentation/git-sparse-checkout.txt: add an OPTIONS section
  @ 2022-03-11 20:56  6%   ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-03-11 20:56 UTC (permalink / raw)
  To: Shaoxuan Yuan, git; +Cc: vdye, newren, bagasdotme

On 3/11/2022 8:21 AM, Shaoxuan Yuan wrote:
> Add an OPTIONS section to the manual and move the descriptions about
> these options from COMMANDS to the section.

This is a good goal.

> +OPTIONS
> +-------

However, there are a few issues with the current approach. First, I
believe it would be better to start with COMMANDS, then OPTIONS.

To be fair, we are not consistent here. These commands use OPTIONS
and then COMMANDS:

* git-commit-graph.txt
* git-remote.txt
* git-revert.txt

These use [SUB]COMMANDS and then OPTIONS:

* git-maintenance.txt
* git-notes.txt
* git-p4.txt
* git-stash.txt
* git-submodule.txt
* git-worktree.txt

My preference would be OPTIONS second (and we can clean up the
other docs as #leftoverbits). In particular, I noticed that
the SYNOPSIS for git-maintenance.txt is out of date.	

> +'--[no-]cone'::
> +	Use with ['set'|'reapply'].
> +	Specify using cone mode or not. The default is to use cone mode.
>  +
>  By default, the input list is considered a list of directories, matching
>  the output of `git ls-tree -d --name-only`.  This includes interpreting

The other issue is that this context is detailing information about
the 'set' command and the input it takes. You'll want to make sure
the information is properly grouped.

> @@ -78,6 +59,11 @@ with the `--sparse-index` option, and will likely be incompatible with
>  other new features as they are added.  See the "Non-cone Problems"
>  section below and the "Sparse Checkout" section of
>  linkgit:git-read-tree[1] for more details.
> +
> +'--[no-]sparse-index'::
> +	Use with ['set'|'reapply'].

I do like these clear indicators of which commands allow this
option. I wonder if it should instead be

	Use with the `set` and `reapply` commands.

Thanks,
-Stolee

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 03/24] format-patch: don't leak "extra_headers" or "ref_message_ids"
  @ 2022-03-09 20:34  6%   ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2022-03-09 20:34 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, Martin Ågren, Elijah Newren, Derrick Stolee

On Wed, Mar 09, 2022 at 02:16:33PM +0100, Ævar Arnfjörð Bjarmason wrote:
> @@ -1946,7 +1947,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  		strbuf_addch(&buf, '\n');
>  	}
>
> -	rev.extra_headers = strbuf_detach(&buf, NULL);
> +	extra_headers = strbuf_detach(&buf, NULL);
> +	rev.extra_headers = extra_headers;

Small nit, these two assignments could be combined on the same line
without wrapping. But obviously not a big deal.

> @@ -2173,8 +2175,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  		prepare_bases(&bases, base, list, nr);
>  	}
>
> -	if (in_reply_to || thread || cover_letter)
> -		rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
> +	if (in_reply_to || thread || cover_letter) {
> +		rev.ref_message_ids = xmalloc(sizeof(*rev.ref_message_ids));
> +		string_list_init_nodup(rev.ref_message_ids);
> +	}

OK, and this is the "while we're at it..." part of your commit message.
I did find this a little confusing to read at first, so wouldn't have
minded to see this and the rest of the change split across two patches,
but I think this is fine, too.

> @@ -2281,6 +2285,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
>  	strbuf_release(&rdiff1);
>  	strbuf_release(&rdiff2);
>  	strbuf_release(&rdiff_title);
> +	free(extra_headers);
> +	if (rev.ref_message_ids) {
> +		string_list_clear(rev.ref_message_ids, 0);

I was surprised to learn that string_list_clear() is not a noop when its
first argument is NULL.

Looking around, it probably wouldn't help that much. E.g., running
something like:

    git grep -B1 'string_list_clear(' | grep if -A1

doesn't turn up many results like the above. So maybe some good
#leftoverbits there, although maybe not.

> +		free(rev.ref_message_ids);

This could go in or out of the if-statement.

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v5 00/10] fetch --recurse-submodules: fetch unpopulated submodules
  2022-03-09 19:13  6%       ` Junio C Hamano
@ 2022-03-09 19:49  0%         ` Glen Choo
  0 siblings, 0 replies; 200+ results
From: Glen Choo @ 2022-03-09 19:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Tan, Ævar Arnfjörð Bjarmason

Junio C Hamano <gitster@pobox.com> writes:

> Glen Choo <chooglen@google.com> writes:
>
>> This uses a "first one wins approach", which obviously doesn't have
>> correctness guarantees. But in practice, I don't think this is likely to
>> cause problems:
>>
>> - As far as I can tell, the only value we read from .gitmodules is
>>   'submodule.<name>.fetchRecurseSubmodules', and this value gets
>>   overridden by two other values: the CLI option, and the config
>>   variable with the same name in .git/config.
>>
>>   During "git submodule init", we copy the config values from
>>   .gitmodules to .git/config. Since we can only fetch init-ed submodules
>>   anyway, it's quite unlikely that we will ever actually make use of the
>>   .gitmodules config.
>
> These are reasonable.
>
>> - Even if we do use the .gitmodules config values, it's unlikely that
>>   the values in .gitmodules will change often, so it _probably_ won't
>>   matter which one we choose.
>
> What bad things would we see if the value changes during the span of
> history of the superproject we fetched?  How often we would see
> broken behaviour is immaterial and breakage being rare is a no excuse
> to import a new code with designed-in flaw.  Unless the "rare" is
> "never", that is.

Makes sense, I'll keep this mind.

> I would think using ANY values from .gitmodules without having the
> end-user agree with the settings and copying the settings to the
> .git/config is a BUG.  So if it mattered from which superproject
> commit we took .gitmodules from, that would mean we already have
> such a bug and it is not a new problem.
>
> That would be a reasonable argument for this topic. Together with
> the previous point, i.e. we do not copy values we see in the in-tree
> .gitmodules file to .git/config anyway, it would make a good enough
> assurance, I would think.

To clarify, does this opinion of "don't use config values that aren't
copied into .git/config" extend to in-tree .gitmodules? Prior to this
series, we always read the in-tree .gitmodules to get the config - the
user does not need to copy the settings to .git/config, but we don't
pick a commit to read .gitmodules from.

If we still want to consider in-tree .gitmodules e.g. by merging
.git/config and .gitmodules, then we still have the new problem of
choosing the right .gitmodules.

If the answer is "no, we don't even consider in-tree .gitmodules"
(unless we really have to, like cloning a new submodule), that seems
pretty safe and predictable because we wouldn't have to look in two
different places to figure out what the user wants. And more crucially,
we'd never have to guess which .gitmodules to read - which will become
more of an issue as we add more support for init-ed but unpopulated
submodules.

> It leads to a possible #leftoverbit clean-up.  Because we only fetch
> submodules that are initialized, the API functions we are using in
> this series has no reason to require us to feed _a_ commit in the
> superproject to them so that they can find .gitmodules in them.

Hm, this is true; an initialized submodule should already have the
'expected' information in .git/config. And if we no longer have to fret
about whether we're reading the correct .gitmodules, we can revisit the
idea of "init a subrepo using only its name".

> Fixing the API can probably be left outside the scope of the topic,
> to be done soon after the dust from the topic settles, I think, to
> avoid distracting us from the topic.
>
> Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v5 00/10] fetch --recurse-submodules: fetch unpopulated submodules
  @ 2022-03-09 19:13  6%       ` Junio C Hamano
  2022-03-09 19:49  0%         ` Glen Choo
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-03-09 19:13 UTC (permalink / raw)
  To: Glen Choo; +Cc: git, Jonathan Tan, Ævar Arnfjörð Bjarmason

Glen Choo <chooglen@google.com> writes:

> This uses a "first one wins approach", which obviously doesn't have
> correctness guarantees. But in practice, I don't think this is likely to
> cause problems:
>
> - As far as I can tell, the only value we read from .gitmodules is
>   'submodule.<name>.fetchRecurseSubmodules', and this value gets
>   overridden by two other values: the CLI option, and the config
>   variable with the same name in .git/config.
>
>   During "git submodule init", we copy the config values from
>   .gitmodules to .git/config. Since we can only fetch init-ed submodules
>   anyway, it's quite unlikely that we will ever actually make use of the
>   .gitmodules config.

These are reasonable.

> - Even if we do use the .gitmodules config values, it's unlikely that
>   the values in .gitmodules will change often, so it _probably_ won't
>   matter which one we choose.

What bad things would we see if the value changes during the span of
history of the superproject we fetched?  How often we would see
broken behaviour is immaterial and breakage being rare is a no excuse
to import a new code with designed-in flaw.  Unless the "rare" is
"never", that is.

I would think using ANY values from .gitmodules without having the
end-user agree with the settings and copying the settings to the
.git/config is a BUG.  So if it mattered from which superproject
commit we took .gitmodules from, that would mean we already have
such a bug and it is not a new problem.

That would be a reasonable argument for this topic. Together with
the previous point, i.e. we do not copy values we see in the in-tree
.gitmodules file to .git/config anyway, it would make a good enough
assurance, I would think.

> - This only matters when the submodule is not in the index. If the
>   submodule _is_ in the index, we read .gitmodules from the filesystem
>   i.e. these patches shouldn't change the behavior for submodules in the
>   index.

How often we would see broken behaviour does not matter.  If it is
broken when the submodule is not in the index, we need to know.

But as you said, it does not sound likely that in-tree .gitmodules
matters.

It leads to a possible #leftoverbit clean-up.  Because we only fetch
submodules that are initialized, the API functions we are using in
this series has no reason to require us to feed _a_ commit in the
superproject to them so that they can find .gitmodules in them.

Fixing the API can probably be left outside the scope of the topic,
to be done soon after the dust from the topic settles, I think, to
avoid distracting us from the topic.

Thanks.



^ permalink raw reply	[relevance 6%]

* Re: [PATCH 02/11] revision: put object filter into struct rev_info
  2022-03-04 22:15  5%   ` Junio C Hamano
@ 2022-03-07 13:59  0%     ` Derrick Stolee
  0 siblings, 0 replies; 200+ results
From: Derrick Stolee @ 2022-03-07 13:59 UTC (permalink / raw)
  To: Junio C Hamano, Derrick Stolee via GitGitGadget
  Cc: git, stolee, avarab, zhiyou.jx, jonathantanmy

On 3/4/2022 5:15 PM, Junio C Hamano wrote:
> "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 
>>  static int try_bitmap_count(struct rev_info *revs,
>> -			    struct list_objects_filter_options *filter,
>>  			    int filter_provided_objects)
> 
> This makes quite a lot of sense as filter is now available as
> revs->filter.
> 
>>  {
>>  	uint32_t commit_count = 0,
>> @@ -436,7 +434,8 @@ static int try_bitmap_count(struct rev_info *revs,
>>  	 */
>>  	max_count = revs->max_count;
>>  
>> -	bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
>> +	bitmap_git = prepare_bitmap_walk(revs, revs->filter,
>> +					 filter_provided_objects);
> 
> And we should be able to do the same to prepare_bitmap_walk().  It
> is OK if such a change comes later and not as part of this commit.
> 
> Perhaps it is deliberate.  Unlike the helpers this step touches,
> namely, try_bitmap_count(), try_bitmap_traversal(), and
> try_bitmap_disk_usage(), prepare_bitmap_walk() is not a file-scope
> static helper and updating it will need touching many more places.

I'm making a note that this cleanup can happen in a follow-up series.
 
>> @@ -597,13 +595,17 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
>>  		}
>>  
>>  		if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) {
> 
> #leftoverbit.  We need to remember to clean this up, now "--filter"
> is well established (I am assuming this literal-string pasting is
> because we didn't know what the right and final word to be used as
> the option name back when this code was originally written), when
> the code around here is quiescent.

Good point.

>> -			parse_list_objects_filter(&filter_options, arg);
>> -			if (filter_options.choice && !revs.blob_objects)
>> +			if (!revs.filter)
>> +				CALLOC_ARRAY(revs.filter, 1);
>> +			parse_list_objects_filter(revs.filter, arg);
>> +			if (revs.filter->choice && !revs.blob_objects)
>>  				die(_("object filtering requires --objects"));
>>  			continue;
> 
> OK.  The original "filter_options" was a structure and not a pointer
> to a structure; now we have a pointer to a structure in revs as a
> member so we need an on-demand allocation.  CALLOC_ARRAY() instead
> of xcalloc(), when we know we are creating one element and not an
> array of elements whose size happens to be one, is not wrong but it
> does look strange.  Was there a reason why we avoid xcalloc()?

I think I've been using CALLOC_ARRAY(..., 1) over "... = xcalloc()"
for simplicity's sake for a while. I see quite a few across the
codebase, too, but I can swap the usage here if you feel that is
important.

> Makes me also wonder how big the filter_options structure is;
> because we will not use unbounded many revs structure, it may have
> been a simpler conversion to turn a static struct into an embedded
> struct member in a struct (instead of a member of a struct that is a
> pointer to a struct).  That way, we did not have to ...
>>>  		}
>>  		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
>> -			list_objects_filter_set_no_filter(&filter_options);
>> +			if (!revs.filter)
>> +				CALLOC_ARRAY(revs.filter, 1);
> 
> ... repeat the on-demand allocation.  If some code used to pass
> &filter_options in a parameter to helper functions, and such calling
> sites get rewritten to pass the value in the revs.filter pointer,
> and if revs hasn't gone through this codepath, these helper functions
> will start receiving NULL in their filter_options parameter, which
> they may or may not be prepared to take.  This "we get rid of a
> global struct and replace it with an on-demand allocated structure,
> pointer to which is stored in the revs structure" rewrite somehow
> makes me nervous.

I think the main idea is that the filter being NULL indicates "no
filter is used. Do a full object walk." If we use a static struct,
then we need to instead use revs->filter.filter_spec.nr, but that
is already being used as a BUG() statement:

const char *list_objects_filter_spec(struct list_objects_filter_options *filter)
{
	if (!filter->filter_spec.nr)
		BUG("no filter_spec available for this filter");

so a non-NULL filter with no specs is considered invalid, while
a NULL filter _is_ currently considered valid.

While we _could_ make that switch to using a static struct and
change our checks to allow empty specs, that would be a more
involved change. Maybe we can leave it for a follow up?

Thanks,
-Stolee

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 02/11] revision: put object filter into struct rev_info
  @ 2022-03-04 22:15  5%   ` Junio C Hamano
  2022-03-07 13:59  0%     ` Derrick Stolee
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-03-04 22:15 UTC (permalink / raw)
  To: Derrick Stolee via GitGitGadget
  Cc: git, stolee, avarab, zhiyou.jx, jonathantanmy, Derrick Stolee

"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:

>  static int try_bitmap_count(struct rev_info *revs,
> -			    struct list_objects_filter_options *filter,
>  			    int filter_provided_objects)

This makes quite a lot of sense as filter is now available as
revs->filter.

>  {
>  	uint32_t commit_count = 0,
> @@ -436,7 +434,8 @@ static int try_bitmap_count(struct rev_info *revs,
>  	 */
>  	max_count = revs->max_count;
>  
> -	bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
> +	bitmap_git = prepare_bitmap_walk(revs, revs->filter,
> +					 filter_provided_objects);

And we should be able to do the same to prepare_bitmap_walk().  It
is OK if such a change comes later and not as part of this commit.

Perhaps it is deliberate.  Unlike the helpers this step touches,
namely, try_bitmap_count(), try_bitmap_traversal(), and
try_bitmap_disk_usage(), prepare_bitmap_walk() is not a file-scope
static helper and updating it will need touching many more places.

> @@ -597,13 +595,17 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
>  		}
>  
>  		if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) {

#leftoverbit.  We need to remember to clean this up, now "--filter"
is well established (I am assuming this literal-string pasting is
because we didn't know what the right and final word to be used as
the option name back when this code was originally written), when
the code around here is quiescent.

> -			parse_list_objects_filter(&filter_options, arg);
> -			if (filter_options.choice && !revs.blob_objects)
> +			if (!revs.filter)
> +				CALLOC_ARRAY(revs.filter, 1);
> +			parse_list_objects_filter(revs.filter, arg);
> +			if (revs.filter->choice && !revs.blob_objects)
>  				die(_("object filtering requires --objects"));
>  			continue;

OK.  The original "filter_options" was a structure and not a pointer
to a structure; now we have a pointer to a structure in revs as a
member so we need an on-demand allocation.  CALLOC_ARRAY() instead
of xcalloc(), when we know we are creating one element and not an
array of elements whose size happens to be one, is not wrong but it
does look strange.  Was there a reason why we avoid xcalloc()?

Makes me also wonder how big the filter_options structure is;
because we will not use unbounded many revs structure, it may have
been a simpler conversion to turn a static struct into an embedded
struct member in a struct (instead of a member of a struct that is a
pointer to a struct).  That way, we did not have to ...

>  		}
>  		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
> -			list_objects_filter_set_no_filter(&filter_options);
> +			if (!revs.filter)
> +				CALLOC_ARRAY(revs.filter, 1);

... repeat the on-demand allocation.  If some code used to pass
&filter_options in a parameter to helper functions, and such calling
sites get rewritten to pass the value in the revs.filter pointer,
and if revs hasn't gone through this codepath, these helper functions
will start receiving NULL in their filter_options parameter, which
they may or may not be prepared to take.  This "we get rid of a
global struct and replace it with an on-demand allocated structure,
pointer to which is stored in the revs structure" rewrite somehow
makes me nervous.

> diff --git a/revision.h b/revision.h
> index 3c58c18c63a..1ddb73ab82e 100644
> --- a/revision.h
> +++ b/revision.h
> @@ -81,6 +81,7 @@ struct rev_cmdline_info {
>  
>  struct oidset;
>  struct topo_walk_info;
> +struct list_objects_filter_options;

Is the forward-declaration the only reason why we needed to have a
pointer to a(n opaque) struct, not an embedded struct, as a member?

>  struct rev_info {
>  	/* Starting list */
> @@ -94,6 +95,9 @@ struct rev_info {
>  	/* The end-points specified by the end user */
>  	struct rev_cmdline_info cmdline;
>  
> +	/* Object filter options. NULL for no filtering. */
> +	struct list_objects_filter_options *filter;
> +
>  	/* excluding from --branches, --refs, etc. expansion */
>  	struct string_list *ref_excludes;

^ permalink raw reply	[relevance 5%]

* Re: Please add support for "git merge --continue -S"
  @ 2022-02-28 22:53  5%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-02-28 22:53 UTC (permalink / raw)
  To: git; +Cc: Rolf Eike Beer, Ævar Arnfjörð Bjarmason

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> You can just drop the use of "merge --continue" entirely and use
> "commit" instead.
>
> Caveats related to this were recently discussed on-list:
> https://lore.kernel.org/git/CALRdAfcyfesNqfLhhe2GW_5V9s2hf++i6mZS1Lw5hqQYTca85w@mail.gmail.com/

Ah, that one.  We need to close the #leftoverbits on the topic.
Here is a starter.

----- >8 --------- >8 --------- >8 --------- >8 --------- >8 -----
Subject: merge: 'git merge --continue' is merely 'git commit'

Among the commands with "--continue", "merge --continue" came much
later, and it did not even need to exist.  The other commands with
"--continue", e.g. "rebase", deal with multi-step operations, and it
is worth to have a way to say "I am finished with this step, let's
CONTINUE WITH THE REST".  But in "merge", there is no remaining
thing to do after you are done with the conflict you saw.

In hindsight, we probably should have resisted the urge to add
"merge --continue", just for the sake of misguided "consistency"
perceived on non-existent similarity with other commands that truly
need "--continue".  What is called "merge --continue" should have
been called "merge --finish", if we needed to add something back
then.

The way to finish a conflicted merge has always been to run "git
commit" before "merge --continue" was added, and it still is not
just accepted but is the right way to finish a conflicted merge.

There is an argument that it makes it somehow "safer" to use "merge
--continue" because the command fails when there is no interrupted
merge going on, but what the user sees from "git commit" when there
is and there is not interrupted merge are so different, there is not
much "safety" benefit in practice.  We probably should deprecate and
eventually remove "git merge --continue" eventually, but one step at
a time.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/git-merge.txt | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git c/Documentation/git-merge.txt w/Documentation/git-merge.txt
index 3125473cc1..95f252598e 100644
--- c/Documentation/git-merge.txt
+++ w/Documentation/git-merge.txt
@@ -122,9 +122,9 @@ list.
 	stash entry will be saved to the stash list.
 
 --continue::
-	After a 'git merge' stops due to conflicts you can conclude the
-	merge by running 'git merge --continue' (see "HOW TO RESOLVE
-	CONFLICTS" section below).
+	After a 'git merge' stops due to conflicts, you can conclude
+	the merge with "git commit" (see "HOW TO RESOLVE CONFLICTS"
+	section below).  'git merge --continue' is a synonym for it.
 
 <commit>...::
 	Commits, usually other branch heads, to merge into our branch.
@@ -326,10 +326,9 @@ After seeing a conflict, you can do two things:
 
  * Resolve the conflicts.  Git will mark the conflicts in
    the working tree.  Edit the files into shape and
-   'git add' them to the index.  Use 'git commit' or
-   'git merge --continue' to seal the deal. The latter command
-   checks whether there is a (interrupted) merge in progress
-   before calling 'git commit'.
+   'git add' them to the index.  Use 'git commit' (or
+   'git merge --continue', which stops if there is no 
+   interrupted merge in progress) to seal the deal.
 
 You can work through the conflict with a number of tools:
 

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH v2 1/3] t7519: avoid file to index mtime race for untracked cache
  2022-02-25 19:07  6%     ` Junio C Hamano
@ 2022-02-27 22:12  0%       ` Tao Klerks
  0 siblings, 0 replies; 200+ results
From: Tao Klerks @ 2022-02-27 22:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Tao Klerks via GitGitGadget, git

On Fri, Feb 25, 2022 at 8:07 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Tao Klerks via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > In t7519 there is a test that writes files to disk, and immediately
> > writes the untracked index. Because of mtime-comparison logic that
>
> "untracked cache", I think.
>

Yep, fixed, thx.

> > uses a 1-second resolution, this means the cached entries are not
> > trusted/used under some circumstances
> > (see read-cache.c#is_racy_stat()).
> >
> > Untracked cache tests in t7063 use a 1-second delay to avoid this
> > issue, but we don't want to introduce arbitrary slowdowns, so instead
> > use test-tool chmtime to backdate the files slightly.
>
> Good approach.  Perhaps fixing 7063 can be marked as #leftoverbit?
>

Sure. Updated the commit msg.

I also started another thread with what that looks like - it's not very pretty
in the end because of Windows compatibility issues, and still incomplete
because (as far as I can tell) the sleep is used for a couple of different
purposes, and only one of them lends itself to chmtime manipulation.

^ permalink raw reply	[relevance 0%]

* [PATCH v3 0/3] Empty untracked cache performance issue
    @ 2022-02-27 21:56  5%   ` Tao Klerks via GitGitGadget
  2022-02-27 21:56  6%     ` [PATCH v3 1/3] t7519: avoid file to index mtime race for untracked cache Tao Klerks via GitGitGadget
  1 sibling, 1 reply; 200+ results
From: Tao Klerks via GitGitGadget @ 2022-02-27 21:56 UTC (permalink / raw)
  To: git; +Cc: Tao Klerks

This patchset addresses a performance issue with untracked cache. When a new
untracked cache structure is added to the index but remains empty,
subsequent "git status" calls populate it but do not write the index - so
they perform as though the index were disabled.

This situation can be caused in several different ways:

 * Running "git update-index --untracked-cache" on a repo that did not have
   the untracked cache
 * Modifying the git configuration to enable untracked cache, but then
   immediately running "git status -uall", causing the untracked cache to be
   created, but not used/populated (and the index written).
 * (likely others)

The patchset includes fixes to t7519, which otherwise starts failing because
it wasn't testing what it intended to.

Tao Klerks (3):
  t7519: avoid file to index mtime race for untracked cache
  t7519: populate untracked cache before test
  untracked-cache: write index when populating empty untracked cache

 dir.c                       | 10 +++++++---
 t/t7519-status-fsmonitor.sh |  7 +++++++
 2 files changed, 14 insertions(+), 3 deletions(-)


base-commit: 4c53a8c20f8984adb226293a3ffd7b88c3f4ac1a
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-986%2FTaoK%2Ftaok-empty-untracked-cache-bug-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-986/TaoK/taok-empty-untracked-cache-bug-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/986

Range-diff vs v2:

 1:  9421b71540d ! 1:  8b1f89c259e t7519: avoid file to index mtime race for untracked cache
     @@ Commit message
          t7519: avoid file to index mtime race for untracked cache
      
          In t7519 there is a test that writes files to disk, and immediately
     -    writes the untracked index. Because of mtime-comparison logic that
     -    uses a 1-second resolution, this means the cached entries are not
     -    trusted/used under some circumstances
     +    writes the index with the untracked cache. Because of
     +    mtime-comparison logic that uses a 1-second resolution, this means
     +    the cached entries are not trusted/used under some circumstances
          (see read-cache.c#is_racy_stat()).
      
          Untracked cache tests in t7063 use a 1-second delay to avoid this
          issue, but we don't want to introduce arbitrary slowdowns, so instead
     -    use test-tool chmtime to backdate the files slightly.
     +    use test-tool chmtime to backdate the files slightly. The t7063
     +    delays are a #leftoverbit, to be worked on in a separate series.
      
          This change doesn't actually affect the outcome of the test, but does
          enhance its validity, and becomes relevant after later changes.
 2:  d29a68e65a0 = 2:  c901f9d96ca t7519: populate untracked cache before test
 3:  190b27e518a = 3:  9795a08414a untracked-cache: write index when populating empty untracked cache

-- 
gitgitgadget

^ permalink raw reply	[relevance 5%]

* [PATCH v3 1/3] t7519: avoid file to index mtime race for untracked cache
  2022-02-27 21:56  5%   ` [PATCH v3 0/3] Empty untracked cache performance issue Tao Klerks via GitGitGadget
@ 2022-02-27 21:56  6%     ` Tao Klerks via GitGitGadget
  0 siblings, 0 replies; 200+ results
From: Tao Klerks via GitGitGadget @ 2022-02-27 21:56 UTC (permalink / raw)
  To: git; +Cc: Tao Klerks, Tao Klerks

From: Tao Klerks <tao@klerks.biz>

In t7519 there is a test that writes files to disk, and immediately
writes the index with the untracked cache. Because of
mtime-comparison logic that uses a 1-second resolution, this means
the cached entries are not trusted/used under some circumstances
(see read-cache.c#is_racy_stat()).

Untracked cache tests in t7063 use a 1-second delay to avoid this
issue, but we don't want to introduce arbitrary slowdowns, so instead
use test-tool chmtime to backdate the files slightly. The t7063
delays are a #leftoverbit, to be worked on in a separate series.

This change doesn't actually affect the outcome of the test, but does
enhance its validity, and becomes relevant after later changes.

Signed-off-by: Tao Klerks <tao@klerks.biz>
---
 t/t7519-status-fsmonitor.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index a6308acf006..3f984136ea9 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -324,13 +324,19 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
 		cd dot-git &&
 		mkdir -p .git/hooks &&
 		: >tracked &&
+		test-tool chmtime =-60 tracked &&
 		: >modified &&
+		test-tool chmtime =-60 modified &&
 		mkdir dir1 &&
 		: >dir1/tracked &&
+		test-tool chmtime =-60 dir1/tracked &&
 		: >dir1/modified &&
+		test-tool chmtime =-60 dir1/modified &&
 		mkdir dir2 &&
 		: >dir2/tracked &&
+		test-tool chmtime =-60 dir2/tracked &&
 		: >dir2/modified &&
+		test-tool chmtime =-60 dir2/modified &&
 		write_integration_script &&
 		git config core.fsmonitor .git/hooks/fsmonitor-test &&
 		git update-index --untracked-cache &&
-- 
gitgitgadget


^ permalink raw reply related	[relevance 6%]

* Re: [PATCH v2 1/3] t7519: avoid file to index mtime race for untracked cache
  @ 2022-02-25 19:07  6%     ` Junio C Hamano
  2022-02-27 22:12  0%       ` Tao Klerks
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-02-25 19:07 UTC (permalink / raw)
  To: Tao Klerks via GitGitGadget; +Cc: git, Tao Klerks

"Tao Klerks via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Tao Klerks <tao@klerks.biz>
>
> In t7519 there is a test that writes files to disk, and immediately
> writes the untracked index. Because of mtime-comparison logic that

"untracked cache", I think.

> uses a 1-second resolution, this means the cached entries are not
> trusted/used under some circumstances
> (see read-cache.c#is_racy_stat()).
>
> Untracked cache tests in t7063 use a 1-second delay to avoid this
> issue, but we don't want to introduce arbitrary slowdowns, so instead
> use test-tool chmtime to backdate the files slightly.

Good approach.  Perhaps fixing 7063 can be marked as #leftoverbit?

> This change doesn't actually affect the outcome of the test, but does
> enhance its validity, and becomes relevant after later changes.
>
> Signed-off-by: Tao Klerks <tao@klerks.biz>
> ---
>  t/t7519-status-fsmonitor.sh | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
> index a6308acf006..3f984136ea9 100755
> --- a/t/t7519-status-fsmonitor.sh
> +++ b/t/t7519-status-fsmonitor.sh
> @@ -324,13 +324,19 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
>  		cd dot-git &&
>  		mkdir -p .git/hooks &&
>  		: >tracked &&
> +		test-tool chmtime =-60 tracked &&
>  		: >modified &&
> +		test-tool chmtime =-60 modified &&
>  		mkdir dir1 &&
>  		: >dir1/tracked &&
> +		test-tool chmtime =-60 dir1/tracked &&
>  		: >dir1/modified &&
> +		test-tool chmtime =-60 dir1/modified &&
>  		mkdir dir2 &&
>  		: >dir2/tracked &&
> +		test-tool chmtime =-60 dir2/tracked &&
>  		: >dir2/modified &&
> +		test-tool chmtime =-60 dir2/modified &&
>  		write_integration_script &&
>  		git config core.fsmonitor .git/hooks/fsmonitor-test &&
>  		git update-index --untracked-cache &&

^ permalink raw reply	[relevance 6%]

* Re: [PATCH 08/17] builtin/pack-objects.c: --cruft without expiration
  @ 2022-02-23 23:34  5%     ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2022-02-23 23:34 UTC (permalink / raw)
  To: Derrick Stolee; +Cc: git, gitster, larsxschneider, peff, tytso

On Tue, Dec 07, 2021 at 10:17:28AM -0500, Derrick Stolee wrote:
> On 11/29/2021 5:25 PM, Taylor Blau wrote:
> > diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
> > +static int add_cruft_object_entry(const struct object_id *oid, enum object_type type,
> > +				  struct packed_git *pack, off_t offset,
> > +				  const char *name, uint32_t mtime)
> > +{
> > +	struct object_entry *entry;
> > +
> > +	display_progress(progress_state, ++nr_seen);
>
> I don't love the global nr_seen here, but it is pervasive through the
> file. OK.

Yeah; this is how all of the existing progress code works in
pack-objects.

> > +	entry = packlist_find(&to_pack, oid);
> > +	if (entry) {
> > +		if (name) {
> > +			entry->hash = pack_name_hash(name);
> > +			entry->no_try_delta = name && no_try_delta(name);
>
> This is already in an "if (name)" block, so "name &&" isn't needed.

Thanks; this is a copy-and-paste from add_object_entry(), where we
aren't in a conditional on "name". We could also fold the conditional on
whether or not name is NULL into no_try_delta itself, since all existing
calls look like "name && no_try_delta(name)".

So adding something like:

    if (!name)
      return 0;

to the beginning of no_try_delta()'s implementation would allow us to
get rid of the handful of "name &&"s. But I'm trying to avoid touching
other parts of pack-objects as much as I can, so I'll hold off for now.

> > +		}
> > +	} else {
> > +		if (!want_object_in_pack(oid, 0, &pack, &offset))
> > +			return 0;
> > +		if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) {
> > +			/*
> > +			 * If a traversed tree has a missing blob then we want
> > +			 * to avoid adding that missing object to our pack.
> > +			 *
> > +			 * This only applies to missing blobs, not trees,
> > +			 * because the traversal needs to parse sub-trees but
> > +			 * not blobs.
> > +			 *
> > +			 * Note we only perform this check when we couldn't
> > +			 * already find the object in a pack, so we're really
> > +			 * limited to "ensure non-tip blobs which don't exist in
> > +			 * packs do exist via loose objects". Confused?
> > +			 */
> > +			return 0;
> > +		}
> > +
> > +		entry = create_object_entry(oid, type, pack_name_hash(name),
> > +					    0, name && no_try_delta(name),
> > +					    pack, offset);
> > +	}
> > +
> > +	if (mtime > oe_cruft_mtime(&to_pack, entry))
> > +		oe_set_cruft_mtime(&to_pack, entry, mtime);
> > +	return 1;
>
> I was confused at this "return 1" here, while other cases return 0.
>
> It turns out that there are multiple methods in this file that have
> different semantics: add_loose_object() and add_object_entry_from_pack()
> are both called from iterators where "return 1" means "stop iterating"
> so they return 0 always. add_object_entry_from_bitmap() is used to
> iterate over a bitmap and "return 1" means "include this object".
>
> However, the return code for add_cruft_object_entry() is never used,
> so it should probably return void or swap the meanings to have nonzero
> mean an error occurred.

Yes, exactly. And thanks for tracing out both of the different
meanings/interpretations of these add_xyz_entry() functions. As you can
imagine, this implementation is copy-and-pasted from add_object_entry(),
which was specialized for this use here. At the time, I gave some effort
towards trying to share more code with add_object_entry() for this
special case, but it ended up being pretty awkward, hence the separate
implementation.

Ironically, add_object_entry()'s return code is also unused, so we could
probably clean that up, too. But like the above, I'll avoid it for now
in an effort to touch as little of pack-objects in this patch as I can.

> > +static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep)
> > +{
> > +	struct string_list_item *item = NULL;
> > +	for_each_string_list_item(item, packs) {
> > +		struct packed_git *p = item->util;
> > +		if (!p)
> > +			die(_("could not find pack '%s'"), item->string);
>
> Interesting that this is a potential issue. We are expecting the pack
> to be loaded before we get here. Is this more because some packs might
> not actually load, but it's fine as long as we don't mark them as kept?

Not quite "loaded" (though any pack structures that we look at by this
point will be fully "loaded"). Instead, we're making sure that all of
the packs names we read from stdin could be matched to packs that we
found in the repository (i.e., that we produce an appropriate error
message if we found "pack-does-not-exist.pack" on stdin).

This is all because we process input from stdin in two phases:

  - First, read all of the input into two string_lists, one for the
    packs we're about to discard (anything that start with '-'), and
    another for all of the "fresh" packs (i.e., anything that we're not
    going to discard).

  - Then, loop through all of the packed_git structs we have, querying
    both of the aforementioned string lists for input that matches each
    pack's `pack_name` field, and setting the `->util` pointer of the
    matching string_list_entry appropriately.

Following those two steps, any list entries that have a NULL util
pointer correspond with bogus input, so we want to call die() there.

> > +		p->pack_keep_in_core = keep;
> > +	}
> > +}
> ...
> > +static void read_cruft_objects(void)
> > +{
> > +	struct strbuf buf = STRBUF_INIT;
> > +	struct string_list discard_packs = STRING_LIST_INIT_DUP;
> > +	struct string_list fresh_packs = STRING_LIST_INIT_DUP;
> > +	struct packed_git *p;
> > +
> > +	ignore_packed_keep_in_core = 1;
>
> Here is a global that we are suddenly changing. Should we not be
> returning it to its initial state when this method is complete?

We could, although it won't matter in practice, because we'll want to
keep that setting around for our traversal, after which point
pack-objects will exit.

> > +static int option_parse_cruft_expiration(const struct option *opt,
> > +					 const char *arg, int unset)
> > +{
> > +	if (unset) {
> > +		cruft = 0;
>
> This unassignment of 'cruft' when cruft-expiration is unset with
> --no-cruft-expiration seems odd. I would expect
>
> 	git pack-objects --cruft --no-cruft-expiration
>
> to still make a cruft pack, but not expire anything. It seems that
> your code here makes --no-cruft-expiration disable the --cruft option.

Hmm. I could see compelling reasoning that goes both ways. On the one
hand, `--no-cruft-expiration` (to me, at least) seems to imply "set
`--cruft-expiration` to "never"). On the other hand, it also matches our
convention of `--no`-prefixed options to unset some value. This
implementation takes the latter approach, though we could easily change
it to set the cruft expiration to "never".

I don't have a strong opinion about which is better, so I'm happy to do
either if you have a better sense about which has more expected
behavior.

> > +		cruft_expiration = 0;
> > +	} else {
> > +		cruft = 1;
> > +		if (arg)
> > +			cruft_expiration = approxidate(arg);
> > +	}
> > +	return 0;
> > +}
> ..
> > +		OPT_BOOL(0, "cruft", &cruft, N_("create a cruft pack")),
> > +		OPT_CALLBACK_F(0, "cruft-expiration", NULL, N_("time"),
> > +		  N_("expire cruft objects older than <time>"),
> > +		  PARSE_OPT_OPTARG, option_parse_cruft_expiration),
>
> > -static int has_loose_object(const struct object_id *oid)
> > +int has_loose_object(const struct object_id *oid)
> >  {
> >  	return check_and_freshen(oid, 0);
> >  }
>
> I'm surprised this hasn't been modified to use a repository pointer.
> Adding another caller here isn't too much debt, though.

Yeah, check_and_freshen() doesn't have a variant that takes a
repository pointer. Good #leftoverbits, I guess!

> > +int has_loose_object(const struct object_id *);
> > +
> >  void assert_oid_type(const struct object_id *oid, enum object_type expect);
>
> ...
>
> > +	test_expect_success "unreachable packed objects are packed (expire $expire)" '
> > +		git init repo &&
> > +		test_when_finished "rm -fr repo" &&
> > +		(
> > +			cd repo &&
> > +
> > +			test_commit packed &&
> > +			git repack -Ad &&
> > +			test_commit other &&
> > +
> > +			git rev-list --objects --no-object-names packed.. >objects &&
> > +			keep="$(basename "$(ls $packdir/pack-*.pack)")" &&
> > +			other="$(git pack-objects --delta-base-offset \
> > +				$packdir/pack <objects)" &&
> > +			git prune-packed &&
> > +
> > +			test-tool chmtime --get -100 "$packdir/pack-$other.pack" >expect &&
>
> I am missing how this test creates _unreachable_ objects. I would expect removal of
> some refs or a 'git reset --hard' somewhere. What am I missing?

For this and the other tests the so-called "unreachable" objects are
technically reachable, but we can treat them as unreachable by putting
them in the "discard" packs list (or by not mentioning them at all to
`git pack-objects --cruft`).

> > +			# remove the unreachable tree, but leave the commit
> > +			# which has it as its root tree in-tact
>
> nit: "intact" is one word.

Thanks; fixed here and in the other test which was added by this commit.

Thanks,
Taylor

^ permalink raw reply	[relevance 5%]

* Re: [PATCH v3 0/3] replace test [-f|-d] with more verbose functions
  @ 2022-02-23 22:59  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-02-23 22:59 UTC (permalink / raw)
  To: COGONI Guillaume
  Cc: avarab, git.jonathan.bressat, git, guillaume.cogoni, matthieu.moy

COGONI Guillaume <cogoni.guillaume@gmail.com> writes:

> Make the code more readable in t/t3903-stash.sh and give more 
> friendly error message by replacing test [-f|-d] by the right 
> test_path_is_* functions.
> Add new functions like test_path_is_* to cover more specifics 
> cases like symbolic link or file that we explicitly refuse
> to be symbolic link.

All three look good to me.

Will queue.

As a possible #leftoverbits material, I suspect that we would
eventually want to be able to say

	test_path_is_file ! "$error_if_I_am_a_file"
	test_path_is_dir ! "$error_if_I_am_a_dir"
	test_path_is_symlink ! "$error_if_I_am_a_symlink"

so that we do not have to have the two ugly-looking special-case
combination "test_path_is_X_not_symlink" but just express what we
want with

	test_path_is_file "$path" && test_path_is_symlink ! "$path"

Once that happens, the two helpers introduced with 2/3 of this
series would become

	test_path_is_file_not_symlink () {
		test $# = 1 || BUG "1 param"
		test_path_is_file "$1" &&
		test_path_is_symlink ! "$1"
	}

But I do not want to see that as part of this series.  Let's
conclude this series and declare a success.

Thanks.




^ permalink raw reply	[relevance 6%]

* Re: When rebase.autoStash=true is used, 'git pull' merge process still complains when incoming changes are in a different place of the file than local changes
  @ 2022-02-23 21:23  6%   ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-02-23 21:23 UTC (permalink / raw)
  To: Phillip Wood; +Cc: Yuri, Git Mailing List

Phillip Wood <phillip.wood123@gmail.com> writes:

> On 17/02/2022 20:50, Yuri wrote:
>> I have a file "x" that has one local change and some incoming pulled
>> changes.
>> Pulled changes are contextually very far away, so it should be
>> possible to merge them without user interaction.
>> But git still complains:
>> $ git pull
>> Updating 91bfe02..522ccf2
>> error: Your local changes to the following files would be
>> overwritten by merge:
>>      x
>
> pull only uses rebase.autoStash if you ask it to rebase, if it is
> trying to merge then you need to pass --autostash on the command line
> or set merge.autoStash (assuming you want merge to always use
> --autostash).

I wonder if it would make a good #leftoverbit starter project to
introduce pull.autoStash so that those who want autostash only when
running "git pull" (but not "git merge" or "git rebase") can set it,
ignoring the settings of merge/rebase.autoStash variables.

Thanks.


^ permalink raw reply	[relevance 6%]

* Re: [PATCH v5 04/12] merge-tree: implement real merges
  2022-02-22  2:28  6%       ` Elijah Newren
@ 2022-02-22 16:25  0%         ` Johannes Schindelin
  0 siblings, 0 replies; 200+ results
From: Johannes Schindelin @ 2022-02-22 16:25 UTC (permalink / raw)
  To: Elijah Newren
  Cc: René Scharfe, Elijah Newren via GitGitGadget,
	Git Mailing List, Christian Couder, Taylor Blau,
	Johannes Altmanninger, Ramsay Jones, Christian Couder,
	Ævar Arnfjörð Bjarmason, Johannes Sixt,
	Josh Steadmon, Emily Shaffer

[-- Attachment #1: Type: text/plain, Size: 1769 bytes --]

Hi Elijah,

On Mon, 21 Feb 2022, Elijah Newren wrote:

> On Sun, Feb 20, 2022 at 1:03 AM René Scharfe <l.s.r@web.de> wrote:
> >
> > Am 20.02.22 um 07:54 schrieb Elijah Newren via GitGitGadget:
> [...]
> > > +     /*
> > > +      * Get the merge bases, in reverse order; see comment above
> > > +      * merge_incore_recursive in merge-ort.h
> > > +      */
> > > +     common = get_merge_bases(parent1, parent2);
> > > +     if (!common)
> > > +             die(_("refusing to merge unrelated histories"));
> > > +     for (j = common; j; j = j->next)
> > > +             commit_list_insert(j->item, &merge_bases);
> >
> > This loop creates a reversed copy of "common".  You could use
> > reverse_commit_list() instead to do it in-place and avoid the
> > allocations.  Only the copy, "merge_bases", is used below.
>
> Oh, good catch.  I probably should have been aware of this since
> someone requested I move the reverse_commit_list() function from
> merge-recursive.c to commit.c as part of my merge-ort work, but looks
> like I forgot about it and copied this command snippet from
> builtin/merge.c instead.  I have no excuse.

Ooops! I missed that the `reverse_commit_list()` function was moved to
`commit.c` by _you_, and had not been there all along (my fault, of
course, see 8918b0c9c26 (merge-recur: try to merge older merge bases
first, 2006-08-09)).

> However, I wonder if that means we could also apply this
> simplification to the code snippets in builtin/merge.c and sequencer.c
> that you can find with
>     git grep commit_list_insert.*reversed
> ?  Maybe #leftoverbits for that part?

Yes, that's a good idea. I summarized this left-over-bit in
https://github.com/gitgitgadget/git/issues/1156

Ciao,
Dscho

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] Provide config option to expect files outside sparse patterns
  @ 2022-02-22 12:11  6%     ` Johannes Schindelin
  0 siblings, 0 replies; 200+ results
From: Johannes Schindelin @ 2022-02-22 12:11 UTC (permalink / raw)
  To: Elijah Newren
  Cc: Elijah Newren via GitGitGadget, Git Mailing List,
	Jonathan Nieder, Jonathan Tan, Jose Lopes, Jeff Hostetler

Hi Elijah,

On Mon, 21 Feb 2022, Elijah Newren wrote:

> On Mon, Feb 21, 2022 at 12:34 PM Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> >
> > In addition to Stolee's feedback...
> >
> > On Sun, 20 Feb 2022, Elijah Newren via GitGitGadget wrote:
> >
> > > diff --git a/config.c b/config.c
> > > index 2bffa8d4a01..68e877a1d80 100644
> > > --- a/config.c
> > > +++ b/config.c
> > > @@ -1520,6 +1520,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
> > >               return 0;
> > >       }
> > >
> > > +     if (!strcmp(var, "core.expectfilesoutsidesparsepatterns")) {
> > > +             core_expect_files_outside_sparse_patterns = git_config_bool(var, value);
> > > +             return 0;
> > > +     }
> >
> > The `core` section is already quite crowded (for which I am partially
> > responsible, of course).
> >
> > Maybe it would be a good idea to introduce the `sparse` section, using
> > `sparse.allowFilesMatchingPatterns` or `sparse.applyPatternsToWorktree =
> > false`?
>
> That's a fair point.  At one point Stolee wanted to change from
> core.sparse* to sparse.* -- but by that point we already had users and
> would have had to deal with a bit of a migration story (and wondering
> what to do if people had both old and new config variables set
> inconsistently).

Right, migration is always hard.

And it's outside of the scope of this here patch series, of course.

> I'm not sure if it's optimal to try to keep the sparse settings
> together (thus put new ones under core), or try to avoid filling core.
> I guess if we moved towards sparse.* now, it might be an easier
> migration story if we only have two options to move.  And besides,
> we're already split between multiple sections with
> extensions.worktreeConfig, core.sparseCheckout{,Cone}, and
> index.sparse already...so maybe adding one more section would be par
> for the course.  ;-)

FWIW as a potential #leftoverbits, we could migrate those to `sparse.*`
where `sparse.*` would take precendence over `core.sparse*` and the usual
deprecation notice would be shown via the `advice` mechanism.

> So, I'm leaning towards sparse.expectFilesOutsideOfPatterns, but I'd
> like to hear Stolee's thoughts too.

Indeed, his opinion weighs more than mine on this matter.

Ciao,
Dscho

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v5 04/12] merge-tree: implement real merges
  @ 2022-02-22  2:28  6%       ` Elijah Newren
  2022-02-22 16:25  0%         ` Johannes Schindelin
  0 siblings, 1 reply; 200+ results
From: Elijah Newren @ 2022-02-22  2:28 UTC (permalink / raw)
  To: René Scharfe
  Cc: Elijah Newren via GitGitGadget, Git Mailing List,
	Christian Couder, Taylor Blau, Johannes Altmanninger,
	Ramsay Jones, Johannes Schindelin, Christian Couder,
	Ævar Arnfjörð Bjarmason, Johannes Sixt,
	Josh Steadmon, Emily Shaffer

On Sun, Feb 20, 2022 at 1:03 AM René Scharfe <l.s.r@web.de> wrote:
>
> Am 20.02.22 um 07:54 schrieb Elijah Newren via GitGitGadget:
[...]
> > +     /*
> > +      * Get the merge bases, in reverse order; see comment above
> > +      * merge_incore_recursive in merge-ort.h
> > +      */
> > +     common = get_merge_bases(parent1, parent2);
> > +     if (!common)
> > +             die(_("refusing to merge unrelated histories"));
> > +     for (j = common; j; j = j->next)
> > +             commit_list_insert(j->item, &merge_bases);
>
> This loop creates a reversed copy of "common".  You could use
> reverse_commit_list() instead to do it in-place and avoid the
> allocations.  Only the copy, "merge_bases", is used below.

Oh, good catch.  I probably should have been aware of this since
someone requested I move the reverse_commit_list() function from
merge-recursive.c to commit.c as part of my merge-ort work, but looks
like I forgot about it and copied this command snippet from
builtin/merge.c instead.  I have no excuse.

However, I wonder if that means we could also apply this
simplification to the code snippets in builtin/merge.c and sequencer.c
that you can find with
    git grep commit_list_insert.*reversed
?  Maybe #leftoverbits for that part?

^ permalink raw reply	[relevance 6%]

* [PATCH v3 4/5] date API: add basic API docs
  @ 2022-02-16  8:14  5%       ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-02-16  8:14 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

Add basic API doc comments to date.h, and while doing so move the the
parse_date_format() function adjacent to show_date(). This way all the
"struct date_mode" functions are grouped together. Documenting the
rest is one of our #leftoverbits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 date.h | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/date.h b/date.h
index c3a00d08ed6..bbd6a6477b5 100644
--- a/date.h
+++ b/date.h
@@ -1,6 +1,12 @@
 #ifndef DATE_H
 #define DATE_H
 
+/**
+ * The date mode type. This has DATE_NORMAL at an explicit "= 0" to
+ * accommodate a memset([...], 0, [...]) initialization when "struct
+ * date_mode" is used as an embedded struct member, as in the case of
+ * e.g. "struct pretty_print_context" and "struct rev_info".
+ */
 enum date_mode_type {
 	DATE_NORMAL = 0,
 	DATE_HUMAN,
@@ -24,7 +30,7 @@ struct date_mode {
 	.type = DATE_NORMAL, \
 }
 
-/*
+/**
  * Convenience helper for passing a constant type, like:
  *
  *   show_date(t, tz, DATE_MODE(NORMAL));
@@ -32,7 +38,22 @@ struct date_mode {
 #define DATE_MODE(t) date_mode_from_type(DATE_##t)
 struct date_mode *date_mode_from_type(enum date_mode_type type);
 
+/**
+ * Format <'time', 'timezone'> into static memory according to 'mode'
+ * and return it. The mode is an initialized "struct date_mode"
+ * (usually from the DATE_MODE() macro).
+ */
 const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
+
+/**
+ * Parse a date format for later use with show_date().
+ *
+ * When the "date_mode_type" is DATE_STRFTIME the "strftime_fmt"
+ * member of "struct date_mode" will be a malloc()'d format string to
+ * be used with strbuf_addftime().
+ */
+void parse_date_format(const char *format, struct date_mode *mode);
+
 void show_date_relative(timestamp_t time, struct strbuf *timebuf);
 int parse_date(const char *date, struct strbuf *out);
 int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
@@ -41,7 +62,6 @@ void datestamp(struct strbuf *out);
 #define approxidate(s) approxidate_careful((s), NULL)
 timestamp_t approxidate_careful(const char *, int *);
 timestamp_t approxidate_relative(const char *date);
-void parse_date_format(const char *format, struct date_mode *mode);
 int date_overflows(timestamp_t date);
 time_t tm_to_time_t(const struct tm *tm);
 #endif
-- 
2.35.1.1028.g2d2d4be19de


^ permalink raw reply related	[relevance 5%]

* Re: [PATCH v2 2/2] cat-file: add --batch-command mode
  @ 2022-02-08  0:49  4%     ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-02-08  0:49 UTC (permalink / raw)
  To: John Cai via GitGitGadget
  Cc: git, me, phillip.wood123, avarab, e, bagasdotme, Eric Sunshine, John Cai

"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: John Cai <johncai86@gmail.com>
>
> Add a new flag --batch-command that accepts commands and arguments
> from stdin, similar to git-update-ref --stdin.
>
> At GitLab, we use a pair of long running cat-file processes when
> accessing object content. One for iterating over object metadata with
> --batch-check, and the other to grab object contents with --batch.
>
> However, if we had --batch-command, we wouldn't need to keep both
> processes around, and instead just have one --batch-command process
> where we can flip between getting object info, and getting object
> contents. Since we have a pair of cat-file processes per repository,
> this means we can get rid of roughly half of long lived git cat-file
> processes. Given there are many repositories being accessed at any given
> time, this can lead to huge savings since on a given server.
>
> git cat-file --batch-command
>
> will enter an interactive command mode whereby the user can enter in
> commands and their arguments that get queued in memory:
>
> <command1> [arg1] [arg2] NL
> <command2> [arg1] [arg2] NL

If you mean you take one command with its args per line, use LF not
NL.

    $ git grep '\<NL\>' Documentation
    $ git grep '\<LF\>' Documentation

We may want to fix the sole offender in Documentation/config.txt
file (#leftoverbits).

> With this mechanism of queueing up commands and letting (A) issue a
> flush command, process (A) can control when the buffer is flushed and
> can guarantee it will receive all of the output when in --buffer mode.

Are we giving them guarantee when output will *not* come?  If (B) is
allowed to flush when it thinks it has too much in-core, it would
mean that (A) cannot keep issuing commands forever without reading
the response from (B), because (B) will eventually be blocked when
it tries to flush to a pipe that (A) is not reading.  I think there
should be some discussion on that, too.  IOW, --batch-command does
not allow (B) to flush until it gets "flush", or something like that.

> diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
> index bef76f4dd06..618dbd15338 100644
> --- a/Documentation/git-cat-file.txt
> +++ b/Documentation/git-cat-file.txt
> @@ -96,6 +96,25 @@ OPTIONS
>  	need to specify the path, separated by whitespace.  See the
>  	section `BATCH OUTPUT` below for details.
>  
> +--batch-command::
> +	Enter a command mode that reads commands and arguments from stdin.
> +	May not be combined with any other options or arguments except
> +	`--textconv` or `--filters`, in which case the input lines also need to
> +	specify the path, separated by whitespace.  See the section
> +	`BATCH OUTPUT` below for details.
> +
> +contents <object>::
> +	Print object contents for object reference <object>

Presumably this corresponds to what you get out of "--batch"?

> +info <object>::
> +	Print object info for object reference <object>

and this one "--batch-check"?

I expect that future readers will ask this same question because it
is not clear how "object contents" and "object info" are exactly
printed.  These two paragraphs may want to anticipate it and reduce
the need for readers to ask such a question.  

> +flush::
> +	Execute all preceding commands that were issued since the beginning or
> +	since the last flush command was issued. Only used with --buffer. When
> +	--buffer is not used, commands are flushed each time without issuing
> +	`flush`.

Here is a good place to also say "When --buffer is used, no output
will come until this is issued" or something.

> diff --git a/builtin/cat-file.c b/builtin/cat-file.c
> index 5f015e71096..6bfab74b58a 100644
> --- a/builtin/cat-file.c
> +++ b/builtin/cat-file.c
> @@ -26,6 +26,7 @@ struct batch_options {
>  	int unordered;
>  	int transform_mode; /* may be 'w' or 'c' for --filters or --textconv */
>  	const char *format;
> +	int command;

I am not sure if "command" is a good name.  Does it answer this
question clearly? "'command' as opposed to what?"

> @@ -508,6 +509,118 @@ static int batch_unordered_packed(const struct object_id *oid,
>  				      data);
>  }
>  
> +typedef void (*parse_cmd_fn_t)(struct batch_options *, const char *,
> +			       struct strbuf *, struct expand_data *);
> +
> +struct queued_cmd {
> +	parse_cmd_fn_t fn;
> +	const char *line;
> +};
> +
> +static void parse_cmd_contents(struct batch_options *opt,
> +			     const char *line,
> +			     struct strbuf *output,
> +			     struct expand_data *data)
> +{
> +	opt->print_contents = 1;
> +	batch_one_object(line, output, opt, data);
> +}
> +
> +static void parse_cmd_info(struct batch_options *opt,
> +			   const char *line,
> +			   struct strbuf *output,
> +			   struct expand_data *data)
> +{
> +	opt->print_contents = 0;
> +	batch_one_object(line, output, opt, data);
> +}

OK, these are as simple as expected.

> +static void flush_batch_calls(struct batch_options *opt,
> +		struct strbuf *output,
> +		struct expand_data *data,
> +		struct queued_cmd *cmds,
> +		int queued)
> +{
> +	int i;
> +	for(i = 0; i < queued; i++){

Missing SP around parentheses.

Excess brace pair wround a single-statement block.

> +		cmds[i].fn(opt, cmds[i].line, output, data);
> +	}
> +	fflush(stdout);
> +}
> +
> +static const struct parse_cmd {
> +	const char *prefix;
> +	parse_cmd_fn_t fn;
> +	unsigned takes_args;
> +} commands[] = {
> +	{ "contents", parse_cmd_contents, 1},
> +	{ "info", parse_cmd_info, 1},
> +};
> +
> +static void batch_objects_command(struct batch_options *opt,
> +				    struct strbuf *output,
> +				    struct expand_data *data)
> +{
> +	struct strbuf input = STRBUF_INIT;
> +	struct queued_cmd *cmds = NULL;
> +	size_t alloc = 0, nr = 0;
> +	int queued = 0;
> +
> +	while (!strbuf_getline(&input, stdin)) {
> +		int i;
> +		const struct parse_cmd *cmd = NULL;
> +		const char *p, *cmd_end;
> +		struct queued_cmd call = {0};
> +
> +		if (!input.len)
> +			die(_("empty command in input"));
> +		if (isspace(*input.buf))
> +			die(_("whitespace before command: '%s'"), input.buf);
> +
> +		if (skip_prefix(input.buf, "flush", &cmd_end)) {
> +			if (!opt->buffer_output)
> +				die(_("flush is only for --buffer mode"));
> +			if (*cmd_end)
> +				die(_("flush takes no arguments"));
> +			if (!queued)
> +				die(_("nothing to flush"));

I am not sure if this is a good idea at all.  What do we gain from
punishing an automated stupid loop that issues flush every once in a
while after issuing a handful real commands and issues another flush
after running out of the real commands for a good measure?

> +			flush_batch_calls(opt, output, data, cmds, queued);
> +			queued = 0;
> +			continue;
> +		}
> +
> +		for (i = 0; i < ARRAY_SIZE(commands); i++) {
> +			if (!skip_prefix(input.buf, commands[i].prefix, &cmd_end))
> +				continue;
> +
> +			cmd = &commands[i];
> +			if (cmd->takes_args)
> +				p = cmd_end + 1;

If somebody adds an entry with .takes_args==false, p will stay
uninitialized and used in the call ->fn() below, or passed to
xstrdup(p).  It probabloy should be initialized to NULL, and
xstrdup(p) below replaced with xstrdup_or_null(p).

> +			break;
> +		}
> +
> +		if (!cmd)
> +			die(_("unknown command: '%s'"), input.buf);
> +
> +		if (!opt->buffer_output) {
> +			cmd->fn(opt, p, output, data);
> +			continue;
> +		}
> +


> +		queued++;
> +		if (queued > nr) {
> +			ALLOC_GROW(cmds, nr+1, alloc);
> +			nr++;
> +		}
> +
> +		call.fn = cmd->fn;
> +		call.line = xstrdup(p);
> +		cmds[queued-1] = call;

Can nr and queued ever go out of sync?

If cmds is the usual <array, nr, alloc> tuple we let ALLOC_GROW() to
manage, alloc keeps track of how physically large the array is, and
nr indicates how many slots are filled.  Holding onto the block of
memory we used when discarding the accumulated items and reusing
that block without having to reallocate until we use the slots that
we have allocated is done by using only <nr, alloc> pair.

But the above code seems that it does not understand that, and
instead thinks it has to use "nr" for the "we have made the array
this big, so we do not have to realloc up to that point" pointer,
hence its use of a separate "queued".  IOW, the array growing code
above seems confused.

It is more customery (hence easier to follow by readers who work on
our code base) to lose queued and say

		ALLOC_GROW(cmds, nr + 1, alloc);
		cmds[nr++] = call;
		call.fn = cmd->fn;
		call.line = xstrdup_or_null(p);

instead of the above 9 lines.

> @@ -515,6 +628,7 @@ static int batch_objects(struct batch_options *opt)
>  	struct expand_data data;
>  	int save_warning;
>  	int retval = 0;
> +	const int command = opt->command;

This tells me that it is quite a misnomer.  This single bit is used
to differentiate between "other batch modes" and "--batch-command"
mode, which already smells like a misdesign, because we have, from
an end-user's point of view, three modes:

    --batch
    --batch-check
    --batch-command

so it would be far cleaner to have a single batch_mode enum that can
represent these three "batch modes", no?

>  	if (!opt->format)
>  		opt->format = "%(objectname) %(objecttype) %(objectsize)";
> @@ -590,6 +704,10 @@ static int batch_objects(struct batch_options *opt)
>  	save_warning = warn_on_object_refname_ambiguity;
>  	warn_on_object_refname_ambiguity = 0;
>  
> +	if (command) {
> +		batch_objects_command(opt, &output, &data);
> +		goto cleanup;
> +	}
>  	while (strbuf_getline(&input, stdin) != EOF) {
>  		if (data.split_on_whitespace) {
>  			/*
> @@ -608,6 +726,7 @@ static int batch_objects(struct batch_options *opt)
>  		batch_one_object(input.buf, &output, opt, &data);
>  	}
>  
> + cleanup:
>  	strbuf_release(&input);
>  	strbuf_release(&output);
>  	warn_on_object_refname_ambiguity = save_warning;
> @@ -636,6 +755,7 @@ static int batch_option_callback(const struct option *opt,
>  
>  	bo->enabled = 1;
>  	bo->print_contents = !strcmp(opt->long_name, "batch");
> +	bo->command = !strcmp(opt->long_name, "batch-command");

And this part needs fixing.  The original used to say

	we supoprt "batch" and something else (it turns out that
	"batch-check" is that something else, but the above code is
	so sloppy that it does not even tell readers that), and
	the .print_contents member is how you can tell them apart.

This patch is making it worse by introducing another member that can
be independently set or unset, pretending that the four combinations
all can make sense, but that is not the case, right?

So, perhaps a good first step would be to lose .print_contents
member and add .batch_command member that is used to more explicitly
name one of the three possibilities?

^ permalink raw reply	[relevance 4%]

* Re: [PATCH v2] receive-pack: purge temporary data if no command is ready to run
  2022-02-05  7:19  0%     ` Bojun Chen
@ 2022-02-05  8:02  0%       ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-02-05  8:02 UTC (permalink / raw)
  To: Bojun Chen
  Cc: git, Chen Bojun, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Teng Long

Bojun Chen <bojun.cbj@gmail.com> writes:

>> This check can _almost_ be doable without being able to access the
>> new objects, and as a follow-on work, it might not be a bad little
>> project to see how we can move the call to check_aliased_updates()
>> before this loop we are adding in this patch (#leftoverbits).
>>
>> Thanks.
>
> Thanks for your suggestion, I agree with you. But I'm confused should
> I continue in this patch or start a new patch.

Neither.

You are under no obligation to take such a different project, which
may be vaguely related to this one.  This early return by itself is
a worthwhile improvement, so let's concentrat on finishing this
topic first.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2] receive-pack: purge temporary data if no command is ready to run
  2022-02-04  1:17  6%   ` Junio C Hamano
@ 2022-02-05  7:19  0%     ` Bojun Chen
  2022-02-05  8:02  0%       ` Junio C Hamano
  0 siblings, 1 reply; 200+ results
From: Bojun Chen @ 2022-02-05  7:19 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Chen Bojun, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Teng Long

Junio C Hamano <gitster@pobox.com> 于2022年2月4日周五 09:17写道:
>
> Chen BoJun <bojun.cbj@gmail.com> writes:
>
> > +     /*
> > +      * If there is no command ready to run, should return directly to destroy
> > +      * temporary data in the quarantine area.
> > +      */
> > +     for (cmd = commands; cmd && cmd->error_string; cmd = cmd->next)
> > +             ; /* nothing */
> > +     if (!cmd)
> > +             return;
> > +
> >       /*
> >        * Now we'll start writing out refs, which means the objects need
> >        * to be in their final positions so that other processes can see them.
>
> One thing I notice is that the first thing we do, after making the
> new objects available to us, is to check if we are making any
> conflicting update, e.g.
>
>     git push origin master:master next:master
>
> would try to update the same ref with different objects, and will be
> rejected.
>
> This check can _almost_ be doable without being able to access the
> new objects, and as a follow-on work, it might not be a bad little
> project to see how we can move the call to check_aliased_updates()
> before this loop we are adding in this patch (#leftoverbits).
>
> Thanks.

Thanks for your suggestion, I agree with you. But I'm confused should
I continue in this patch or start a new patch.

^ permalink raw reply	[relevance 0%]

* [PATCH v2 4/5] date API: add basic API docs
  @ 2022-02-04 23:53  6%     ` Ævar Arnfjörð Bjarmason
    1 sibling, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-02-04 23:53 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

Add basic API doc comments to date.h, and while doing so move the the
parse_date_format() function adjacent to show_date(). This way all the
"struct date_mode" functions are grouped together. Documenting the
rest is one of our #leftoverbits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 date.h | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/date.h b/date.h
index c3a00d08ed6..4ed83506de9 100644
--- a/date.h
+++ b/date.h
@@ -1,6 +1,12 @@
 #ifndef DATE_H
 #define DATE_H
 
+/**
+ * The date mode type. This has DATE_NORMAL at an explicit "= 0" to
+ * accommodate a memset([...], 0, [...]) initialization when "struct
+ * date_mode" is used as an embedded struct member, as in the case of
+ * e.g. "struct pretty_print_context" and "struct rev_info".
+ */
 enum date_mode_type {
 	DATE_NORMAL = 0,
 	DATE_HUMAN,
@@ -24,7 +30,7 @@ struct date_mode {
 	.type = DATE_NORMAL, \
 }
 
-/*
+/**
  * Convenience helper for passing a constant type, like:
  *
  *   show_date(t, tz, DATE_MODE(NORMAL));
@@ -32,7 +38,21 @@ struct date_mode {
 #define DATE_MODE(t) date_mode_from_type(DATE_##t)
 struct date_mode *date_mode_from_type(enum date_mode_type type);
 
+/**
+ * Show the date given an initialized "struct date_mode" (usually from
+ * the DATE_MODE() macro).
+ */
 const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
+
+/**
+ * Parse a date format for later use with show_date().
+ *
+ * When the "date_mode_type" is DATE_STRFTIME the "strftime_fmt"
+ * member of "struct date_mode" will be a malloc()'d format string to
+ * be used with strbuf_addftime().
+ */
+void parse_date_format(const char *format, struct date_mode *mode);
+
 void show_date_relative(timestamp_t time, struct strbuf *timebuf);
 int parse_date(const char *date, struct strbuf *out);
 int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
@@ -41,7 +61,6 @@ void datestamp(struct strbuf *out);
 #define approxidate(s) approxidate_careful((s), NULL)
 timestamp_t approxidate_careful(const char *, int *);
 timestamp_t approxidate_relative(const char *date);
-void parse_date_format(const char *format, struct date_mode *mode);
 int date_overflows(timestamp_t date);
 time_t tm_to_time_t(const struct tm *tm);
 #endif
-- 
2.35.1.940.ge7a5b4b05f2


^ permalink raw reply related	[relevance 6%]

* Re: [PATCH v2] receive-pack: purge temporary data if no command is ready to run
  @ 2022-02-04  1:17  6%   ` Junio C Hamano
  2022-02-05  7:19  0%     ` Bojun Chen
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-02-04  1:17 UTC (permalink / raw)
  To: Chen BoJun
  Cc: git, Chen Bojun, Ævar Arnfjörð Bjarmason,
	Jiang Xin, Teng Long

Chen BoJun <bojun.cbj@gmail.com> writes:

> +	/*
> +	 * If there is no command ready to run, should return directly to destroy
> +	 * temporary data in the quarantine area.
> +	 */
> +	for (cmd = commands; cmd && cmd->error_string; cmd = cmd->next)
> +		; /* nothing */
> +	if (!cmd)
> +		return;
> +
>  	/*
>  	 * Now we'll start writing out refs, which means the objects need
>  	 * to be in their final positions so that other processes can see them.

One thing I notice is that the first thing we do, after making the
new objects available to us, is to check if we are making any
conflicting update, e.g.

    git push origin master:master next:master

would try to update the same ref with different objects, and will be
rejected.

This check can _almost_ be doable without being able to access the
new objects, and as a follow-on work, it might not be a bad little
project to see how we can move the call to check_aliased_updates()
before this loop we are adding in this patch (#leftoverbits).

Thanks.

^ permalink raw reply	[relevance 6%]

* [PATCH 4/5] date API: add basic API docs
  @ 2022-02-02 21:03  6%   ` Ævar Arnfjörð Bjarmason
    1 sibling, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2022-02-02 21:03 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

Add basic API doc comments to date.h, and while doing so move the the
parse_date_format() function adjacent to show_date(). This way all the
"struct date_mode" functions are grouped together. Documenting the
rest is one of our #leftoverbits.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 date.h | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/date.h b/date.h
index c3a00d08ed6..4ed83506de9 100644
--- a/date.h
+++ b/date.h
@@ -1,6 +1,12 @@
 #ifndef DATE_H
 #define DATE_H
 
+/**
+ * The date mode type. This has DATE_NORMAL at an explicit "= 0" to
+ * accommodate a memset([...], 0, [...]) initialization when "struct
+ * date_mode" is used as an embedded struct member, as in the case of
+ * e.g. "struct pretty_print_context" and "struct rev_info".
+ */
 enum date_mode_type {
 	DATE_NORMAL = 0,
 	DATE_HUMAN,
@@ -24,7 +30,7 @@ struct date_mode {
 	.type = DATE_NORMAL, \
 }
 
-/*
+/**
  * Convenience helper for passing a constant type, like:
  *
  *   show_date(t, tz, DATE_MODE(NORMAL));
@@ -32,7 +38,21 @@ struct date_mode {
 #define DATE_MODE(t) date_mode_from_type(DATE_##t)
 struct date_mode *date_mode_from_type(enum date_mode_type type);
 
+/**
+ * Show the date given an initialized "struct date_mode" (usually from
+ * the DATE_MODE() macro).
+ */
 const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
+
+/**
+ * Parse a date format for later use with show_date().
+ *
+ * When the "date_mode_type" is DATE_STRFTIME the "strftime_fmt"
+ * member of "struct date_mode" will be a malloc()'d format string to
+ * be used with strbuf_addftime().
+ */
+void parse_date_format(const char *format, struct date_mode *mode);
+
 void show_date_relative(timestamp_t time, struct strbuf *timebuf);
 int parse_date(const char *date, struct strbuf *out);
 int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
@@ -41,7 +61,6 @@ void datestamp(struct strbuf *out);
 #define approxidate(s) approxidate_careful((s), NULL)
 timestamp_t approxidate_careful(const char *, int *);
 timestamp_t approxidate_relative(const char *date);
-void parse_date_format(const char *format, struct date_mode *mode);
 int date_overflows(timestamp_t date);
 time_t tm_to_time_t(const struct tm *tm);
 #endif
-- 
2.35.0.913.g12b4baa2536


^ permalink raw reply related	[relevance 6%]

* Re: [PATCH] fetch --prune: exit with error if pruning fails
  2022-01-27 19:57  7% ` Junio C Hamano
@ 2022-01-28 11:04  0%   ` Thomas Gummerer
  0 siblings, 0 replies; 200+ results
From: Thomas Gummerer @ 2022-01-28 11:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes Schindelin, Taylor Blau


Junio C Hamano writes:

> Thomas Gummerer <t.gummerer@gmail.com> writes:
>
>> When pruning refs fails, we currently print an error to stderr, but
>> still exit 0 from 'git fetch'.  Since this is a genuine error fetch
>> should be exiting with some non-zero exit code.  Make it so.
>>
>> The --prune option was introduced in f360d844de ("builtin-fetch: add
>> --prune option", 2009-11-10).  Unfortunately it's unclear from that
>> commit whether ignoring the exit code was an oversight or
>> intentional, but it feels like an oversight.
>
> It is a good idea to signal, with a non-zero status, that the user
> needs to inspect the situation and possibly take a corrective
> action.  I however do not know if it is sufficient to just give the
> same exit status as returned by prune_refs(), which may or may not
> happen to crash with other possible non-zero exit status to make it
> indistinguishable from other kinds of errors.

Not sure I understand this correctly.  Are you saying that we should
take the return value from prune refs, and always munge that to the same
exit code for 'git fetch --prune' if it fails?  E.g. so prune_refs()
could return 1 or 2 or 3 or whatever, but we would always want the exit
code for 'fetch' to be 1?

Happy to implement that.

>> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
>> index 20f7110ec1..df824cc3d0 100755
>> --- a/t/t5510-fetch.sh
>> +++ b/t/t5510-fetch.sh
>> @@ -164,6 +164,16 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
>>  	git rev-parse sometag
>>  '
>>
>> +test_expect_success REFFILES 'fetch --prune fails to delete branches' '
>> +	cd "$D" &&
>> +	git clone . prune-fail &&
>> +	cd prune-fail &&
>> +	git update-ref refs/remotes/origin/extrabranch main &&
>> +	>.git/packed-refs.new &&
>> +	test_must_fail git fetch --prune origin
>
> Is it because the lockfile ".new" on packed-refs prevents deletion
> of refs but does not block creation and updates to existing refs
> that it is an effective test for the "--prune" issue?  If we somehow
> "locked" the whole ref updates, then the fetch would fail even
> without "--prune", so it may be "effective", but smells like knowing
> too much implementation detail.  Yuck, but I do not offhand think of
> any better way (it is easier to think of worse ways), so without
> further input, I would say that this is the best (or "least bad") we
> can do.

Yes, that's correct.  New refs will be created as loose refs, so they
don't care about packed-refs.  However deletions can potentially be
happening in packed-refs, and that's why it fails when 'packed-refs.new'
exists.

I don't love the test either, but I also can't think of a better way to
do this.

> Another tangent #leftoverbits is that many tests in this script are
> so old-style that chdir around without isolating themselves in
> subshells, while some do.  We may want to clean them up when the
> file is quiescent.
>
> Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] fetch --prune: exit with error if pruning fails
  @ 2022-01-27 19:57  7% ` Junio C Hamano
  2022-01-28 11:04  0%   ` Thomas Gummerer
  0 siblings, 1 reply; 200+ results
From: Junio C Hamano @ 2022-01-27 19:57 UTC (permalink / raw)
  To: Thomas Gummerer; +Cc: git, Johannes Schindelin, Taylor Blau

Thomas Gummerer <t.gummerer@gmail.com> writes:

> When pruning refs fails, we currently print an error to stderr, but
> still exit 0 from 'git fetch'.  Since this is a genuine error fetch
> should be exiting with some non-zero exit code.  Make it so.
>
> The --prune option was introduced in f360d844de ("builtin-fetch: add
> --prune option", 2009-11-10).  Unfortunately it's unclear from that
> commit whether ignoring the exit code was an oversight or
> intentional, but it feels like an oversight.

It is a good idea to signal, with a non-zero status, that the user
needs to inspect the situation and possibly take a corrective
action.  I however do not know if it is sufficient to just give the
same exit status as returned by prune_refs(), which may or may not
happen to crash with other possible non-zero exit status to make it
indistinguishable from other kinds of errors.

>  		if (rs->nr) {
> -			prune_refs(rs, ref_map, transport->url);
> +			retcode = prune_refs(rs, ref_map, transport->url);
>  		} else {
> -			prune_refs(&transport->remote->fetch,
> -				   ref_map,
> -				   transport->url);
> +			retcode = prune_refs(&transport->remote->fetch,
> +					     ref_map,
> +					     transport->url);
> +		}

It seems that it is possible for do_fetch() to return a negative
value, even without this patch.  The return value from prune_refs()
comes from refs.c::delete_refs(), which can come from error_errno()
that is -1, so this patch adds more of the same problem to existing
ones, though.

And the value propagates up to cmd_fetch() via fetch_one().  This
will be relayed to exit() without changing via this callchain:

    git.c::cmd_main()
      git.c::run_argv()
        git.c::handle_builtin()
          git.c::run_builtin()

This is not a new problem, which does not want to be corrected as
part of this patch, but let's leave a mental note as #leftoverbits
for now.

> +		if (retcode) {
> +			free_refs(ref_map);
> +			goto cleanup;
>  		}

This part is iffy.  We tried to prune refs, we may have removed some
of the refs missing from the other side but we may still have some
other refs that are missing from the other side due to the failure
we noticed.

Is it sensible to abort the fetching?  I am undecided, but without
further input, my gut reaction is that it is safe and may even be
better to treat this as a soft error and try to go closer to where
the user wanted to go as much as possible by continuing to fetch
from the other side, given that we have already paid for the cost of
discovering the refs from the other side.

> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> index 20f7110ec1..df824cc3d0 100755
> --- a/t/t5510-fetch.sh
> +++ b/t/t5510-fetch.sh
> @@ -164,6 +164,16 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
>  	git rev-parse sometag
>  '
>  
> +test_expect_success REFFILES 'fetch --prune fails to delete branches' '
> +	cd "$D" &&
> +	git clone . prune-fail &&
> +	cd prune-fail &&
> +	git update-ref refs/remotes/origin/extrabranch main &&
> +	>.git/packed-refs.new &&
> +	test_must_fail git fetch --prune origin

Is it because the lockfile ".new" on packed-refs prevents deletion
of refs but does not block creation and updates to existing refs
that it is an effective test for the "--prune" issue?  If we somehow
"locked" the whole ref updates, then the fetch would fail even
without "--prune", so it may be "effective", but smells like knowing
too much implementation detail.  Yuck, but I do not offhand think of
any better way (it is easier to think of worse ways), so without
further input, I would say that this is the best (or "least bad") we
can do.

Another tangent #leftoverbits is that many tests in this script are
so old-style that chdir around without isolating themselves in
subshells, while some do.  We may want to clean them up when the
file is quiescent.

Thanks.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] clone: support unusual remote ref configurations
  @ 2022-01-26 19:11  8% ` Junio C Hamano
  0 siblings, 0 replies; 200+ results
From: Junio C Hamano @ 2022-01-26 19:11 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git

Jonathan Tan <jonathantanmy@google.com> writes:

> When cloning a branchless and tagless but not refless remote using
> protocol v0 or v1, Git calls transport_fetch_refs() with an empty ref
> list. This makes the clone fail with the message "remote transport
> reported error".
>
> Git should have refrained from calling transport_fetch_refs(), just like
> it does in the case that the remote is refless. Therefore, teach Git to
> do this.

Makes sense.

> diff --git a/builtin/clone.c b/builtin/clone.c
> index 727e16e0ae..3df441eb71 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -862,7 +862,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  	const struct ref *refs, *remote_head;
>  	struct ref *remote_head_points_at = NULL;
>  	const struct ref *our_head_points_at;
> -	struct ref *mapped_refs;
> +	struct ref *mapped_refs = NULL;
>  	const struct ref *ref;
>  	struct strbuf key = STRBUF_INIT;
>  	struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
> @@ -1184,7 +1184,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  
>  	refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
>  
> -	if (refs) {
> +	if (refs)
> +		mapped_refs = wanted_peer_refs(refs, &remote->fetch);
> +
> +	if (mapped_refs) {
>  		int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));

OK, we used to decide on what they advertised and then filtered that
to what we are interested in inside the "true" side of the if/else.
If the result of filtering became empty, we declared a trouble.

Now we do the filtering first and decide on that.  No matter how
many uninteresting refs they advertise, if they show no refs of
interest to us, it is like they have an empty repository.

> @@ -1193,8 +1196,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  		 */
>  		initialize_repository_version(hash_algo, 1);
>  		repo_set_hash_algo(the_repository, hash_algo);
> -
> -		mapped_refs = wanted_peer_refs(refs, &remote->fetch);
>  		/*
>  		 * transport_get_remote_refs() may return refs with null sha-1
>  		 * in mapped_refs (see struct transport->get_refs_list

[start #leftoverbits]

I noticed these while reading outside the context of this patch.
None of them should be part of this patch, which deals only with the
case where mapped_refs becomes empty.

Here in the post-context of this hunk, there is a loop that iterates
over the original refs list, not the filtered mapped_refs list, to
compute "complete_refs_before_fetch".  Should we need to update the
loop to work on mapped_refs?

And after that, we compute remote_head using the original refs
list, not the mapped_refs list, when calling find_ref_by_name(),
but use mapped_refs when calling guess_remote_head().  The
inconsistency smells fishy.

[end #leftoverbits]


> @@ -1240,7 +1241,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  					option_branch, remote_name);
>  
>  		warning(_("You appear to have cloned an empty repository."));
> -		mapped_refs = NULL;

And we come here instead with the new code.  We claim "you appear to
have cloned an empty repository", which is much closer than
"reported an error".

> @@ -1271,7 +1271,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>  
>  	if (is_local)
>  		clone_local(path, git_dir);
> -	else if (refs && complete_refs_before_fetch) {
> +	else if (mapped_refs && complete_refs_before_fetch) {
>  		if (transport_fetch_refs(transport, mapped_refs))
>  			die(_("remote transport reported error"));
>  	}

And this is the other crux of the fix.  As the root cause of the
problems is to decide with NULL-ness of refs if we do something that
uses mapped_refs, this fixes the inconsistency.

Looking good.

Will queue.  Thanks.

> diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
> index 468bd3e13e..6c8d4c6cf1 100755
> --- a/t/t5700-protocol-v1.sh
> +++ b/t/t5700-protocol-v1.sh
> @@ -149,6 +149,21 @@ test_expect_success 'push with file:// using protocol v1' '
>  	grep "push< version 1" log
>  '
>  
> +test_expect_success 'cloning branchless tagless but not refless remote' '
> +	rm -rf server client &&
> +
> +	git -c init.defaultbranch=main init server &&
> +	echo foo >server/foo.txt &&
> +	git -C server add foo.txt &&
> +	git -C server commit -m "message" &&
> +	git -C server update-ref refs/notbranch/alsonottag HEAD &&
> +	git -C server checkout --detach &&
> +	git -C server branch -D main &&
> +	git -C server symbolic-ref HEAD refs/heads/nonexistentbranch &&
> +
> +	git -c protocol.version=1 clone "file://$(pwd)/server" client
> +'
> +
>  # Test protocol v1 with 'ssh://' transport
>  #
>  test_expect_success 'setup ssh wrapper' '

^ permalink raw reply	[relevance 8%]

* Re: [PATCH v2 1/2] sparse-checkout: custom tab completion tests
  2022-01-04 20:25  6%           ` Elijah Newren
@ 2022-01-05 14:05  0%             ` Lessley Dennington
  0 siblings, 0 replies; 200+ results
From: Lessley Dennington @ 2022-01-05 14:05 UTC (permalink / raw)
  To: Elijah Newren
  Cc: Junio C Hamano, Lessley Dennington via GitGitGadget,
	Git Mailing List, Derrick Stolee, johannes.schindelin



On 1/4/22 2:25 PM, Elijah Newren wrote:
> On Tue, Jan 4, 2022 at 11:26 AM Lessley Dennington
> <lessleydennington@gmail.com> wrote:
>>
>>
>>
>> On 12/31/21 4:20 PM, Junio C Hamano wrote:
>>> Elijah Newren <newren@gmail.com> writes:
>>>
>>>> Second, and this item is unrelated to your series but your comment
>>>> made me realize it....sparse-checkout unfortunately ignores prefix and
>>>> creates a bad .git/info/sparse-checkout file.  For example:
>>>> ...
>>>> I think the loss of the current working directory will be fixed by the
>>>> en/keep-cwd directory (currently in next and marked for merging to
>>>> master), but the fact that the wrong paths end up in the
>>>> sparse-checkout file is unfortunate.  It basically means that the
>>>> `set` and `add` subcommands of `sparse-checkout` can only be safely
>>>> run from the toplevel directory.
>>>
>>> You made it sound as if this is a fundamental limitation, but it
>>> sounds more like a bug that needs to be fixed (outside the
>>> completion series, of course) to me.
>>>
>> I can file a bug report if that's the correct way to proceed.
> 
> We don't really have a bug tracker.
> 
> We often just file an email, and add additional searchable strings
> (e.g. #leftoverbits, though that doesn't apply here), and then search
> via https://lore.kernel.org/git/.
> 
> There is 'git bugreport', but it just generates an email to send to
> the mailing list...but we already have the emails in this thread.
> 
> There is https://bugs.chromium.org/p/git/issues/list, which is used by
> a few folks, but I suspect I'm the only one who has looked at it that
> touches sparse-checkout related stuff.
> 
> There is https://github.com/git-for-windows/git/issues, but this isn't
> Windows specific.  (Sometimes they'll track stuff that isn't windows
> specific, but I've seen Dscho close out issues after being reported to
> this list.)
> 
> I've also kept private files with lists of things to work on.  Doesn't
> help anyone else track it.  (Which is why I'll sometimes use one of
> the two above trackers instead.)
> 
> ...not sure if that helps, but that's the basic state of our "bug tracking".

This is actually great context - thanks for providing! I'll go with the
email strategy for visibility and will base my format off [1].

[1]: 
https://lore.kernel.org/git/CABceR4bZmtC4rCwgxZ1BBYZP69VOUca1f_moJoP989vTUZWu9Q@mail.gmail.com/

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 1/2] sparse-checkout: custom tab completion tests
  @ 2022-01-04 20:25  6%           ` Elijah Newren
  2022-01-05 14:05  0%             ` Lessley Dennington
  0 siblings, 1 reply; 200+ results
From: Elijah Newren @ 2022-01-04 20:25 UTC (permalink / raw)
  To: Lessley Dennington
  Cc: Junio C Hamano, Lessley Dennington via GitGitGadget,
	Git Mailing List, Derrick Stolee, johannes.schindelin

On Tue, Jan 4, 2022 at 11:26 AM Lessley Dennington
<lessleydennington@gmail.com> wrote:
>
>
>
> On 12/31/21 4:20 PM, Junio C Hamano wrote:
> > Elijah Newren <newren@gmail.com> writes:
> >
> >> Second, and this item is unrelated to your series but your comment
> >> made me realize it....sparse-checkout unfortunately ignores prefix and
> >> creates a bad .git/info/sparse-checkout file.  For example:
> >> ...
> >> I think the loss of the current working directory will be fixed by the
> >> en/keep-cwd directory (currently in next and marked for merging to
> >> master), but the fact that the wrong paths end up in the
> >> sparse-checkout file is unfortunate.  It basically means that the
> >> `set` and `add` subcommands of `sparse-checkout` can only be safely
> >> run from the toplevel directory.
> >
> > You made it sound as if this is a fundamental limitation, but it
> > sounds more like a bug that needs to be fixed (outside the
> > completion series, of course) to me.
> >
> I can file a bug report if that's the correct way to proceed.

We don't really have a bug tracker.

We often just file an email, and add additional searchable strings
(e.g. #leftoverbits, though that doesn't apply here), and then search
via https://lore.kernel.org/git/.

There is 'git bugreport', but it just generates an email to send to
the mailing list...but we already have the emails in this thread.

There is https://bugs.chromium.org/p/git/issues/list, which is used by
a few folks, but I suspect I'm the only one who has looked at it that
touches sparse-checkout related stuff.

There is https://github.com/git-for-windows/git/issues, but this isn't
Windows specific.  (Sometimes they'll track stuff that isn't windows
specific, but I've seen Dscho close out issues after being reported to
this list.)

I've also kept private files with lists of things to work on.  Doesn't
help anyone else track it.  (Which is why I'll sometimes use one of
the two above trackers instead.)

...not sure if that helps, but that's the basic state of our "bug tracking".

^ permalink raw reply	[relevance 6%]

* Re: Regression in 8d92fb292706 ("dir: replace exponential algorithm with a linear one")
  2021-12-07  5:29  5% ` Elijah Newren
@ 2021-12-07  7:14  0%   ` Uwe Kleine-König
  0 siblings, 0 replies; 200+ results
From: Uwe Kleine-König @ 2021-12-07  7:14 UTC (permalink / raw)
  To: Elijah Newren; +Cc: Git Mailing List, Björn Lässig

[-- Attachment #1: Type: text/plain, Size: 6222 bytes --]

Hello,

first of all thanks for addressing my report, also to brian.

On Mon, Dec 06, 2021 at 09:29:59PM -0800, Elijah Newren wrote:
> On Mon, Dec 6, 2021 at 4:16 AM Uwe Kleine-König
> <u.kleine-koenig@pengutronix.de> wrote:
> > I admit this is somewhat of a corner case, still it happens in the
> > reality of our admin team ...
> > Initially this was noticed after upgrading the OS from Debian buster
> > (with git 2.20.1) to Debian bullseye (with git 2.30.2).
> >
> > (wgit is just a wrapper for git to call it from my ~/src/git.)
> >
> > This is the good ("old") case:
> >
> >         uwe@taurus:~/tmp/8d92fb29270$ wgit version
> >         git version 2.25.2.7.g0bbd0e8b5233
> >
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit init
> >         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/.git/
> >
> >         uwe@taurus:~/tmp/8d92fb292706$ mkdir subdir
> >         uwe@taurus:~/tmp/8d92fb292706$ cd subdir/
> >         uwe@taurus:~/tmp/8d92fb292706/subdir$ wgit init
> >         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/subdir/.git/
> >         uwe@taurus:~/tmp/8d92fb292706/subdir$ cd ..
> >
> >         uwe@taurus:~/tmp/8d92fb292706$ echo content > subdir/somefile
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit add subdir/somefile
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit status
> >         On branch master
> >
> >         No commits yet
> >
> >         Changes to be committed:
> >           (use "git rm --cached <file>..." to unstage)
> >                 new file:   subdir/somefile
> 
> Eek, that's bad.  I think there's a number of dragons going down that route.

Yes, as soon as you start to checkout files in one of the involved
repositories you implicitly change the other one. In this case git is
only used to track files in /etc and elsewhere, and there are two
mechanisms to track them. (Don't ask for the reasons, I don't know them.
:-) In this setup (I think) the dragons should be well fixed to their
chains.

> > with 8d92fb292706, the following happens:
> >
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit version
> >         git version 2.25.2.8.g8d92fb292706
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit init
> >         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/.git/
> >         uwe@taurus:~/tmp/8d92fb292706$ mkdir subdir
> >         uwe@taurus:~/tmp/8d92fb292706$ cd subdir/
> >         uwe@taurus:~/tmp/8d92fb292706/subdir$ wgit init
> >         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/subdir/.git/
> >         uwe@taurus:~/tmp/8d92fb292706/subdir$ cd ..
> >         uwe@taurus:~/tmp/8d92fb292706$ echo content > subdir/somefile
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit add subdir/somefile
> 
> Not optimal; more on this below.
> 
> >         uwe@taurus:~/tmp/8d92fb292706$ wgit status
> >         On branch master
> >
> >         No commits yet
> >
> >         Untracked files:
> >           (use "git add <file>..." to include in what will be committed)
> >                 subdir/
> >
> >         nothing added to commit but untracked files present (use "git add" to track)
> 
> This part looks good to me.
> 
> > So git after 8d92fb292706 doesn't add files from a subdirectory if
> > said subdirectory is tracked in git, too.
> >
> > While I'm not sure which of the two behaviours is the bogus one, this is
> > a change in behaviour that I guess wasn't intended in 8d92fb292706.
> 
> I put some effort separate from that commit into avoiding accidentally
> recursing into nested git dirs; see e.g. commit 09487f2cba ("clean:
> avoid removing untracked files in a nested git repository",
> 2019-09-17).  So, I was slightly surprised that some other commit
> hadn't fixed this.
> 
> However, it's not all that surprising to me that 8d92fb292706 affected
> this.  Prior to that commit, we visited untracked paths which were n
> directories deep a ridiculous 2^n times.  But what made it even more
> fun was that the status returned for any given path (tracked, ignored,
> not interesting to the traversal, etc.) was not always the same; later
> traversals might return something different than earlier traversals.
> That confusion made it real "fun" trying to ensure no regressions when
> reducing the number of visits to any given path from 2^n down to 1.
> The fact that side effects of the traversals (the population of the
> dir.entries and dir.ignored) could have essentially functioned to
> override a later traversal's return status certainly didn't help; it
> was such a mess.
> 
> But, interestingly, the fixed behavior here also depends pretty
> strongly on commit b9670c1f5e ("dir: fix checks on common prefix
> directory", 2019-12-19) which came months earlier.  This is
> particularly important in combination with the following comment from
> dir.h:
>     /**
>      * If set, recurse into a directory that looks like a Git directory.
>      * Otherwise it is shown as a directory.
>      */
>     DIR_NO_GITLINKS = 1<<3,
> which suggests that cmd_add() (which didn't set this flag) should have
> never been recursing into a Git-tracked directory.  In other words,
> this was a bug all along.
> 
> > Is this something that needs fixing?
> 
> I agree with brian elsewhere in this thread that not adding the file
> is correct.  However, two points:
> 
> * I would prefer to see a warning/error from git add when it doesn't
> add a path  (Any takers?  #leftoverbits maybe?)

Agreed, also maybe return an exit code != 0?

> * It is possible that one might want to be able to force the addition
> of files to an outer repository despite existing within a directory
> tracked by an inner git repository, perhaps with a double `--force`
> being passed to git-add (much like git-clean allows).  If so, that
> could be implemented via the addition of
>     dir.flags |= DIR_NO_GITLINKS;
> to cmd_add() when the double force is detected.

I think this would be good.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: Regression in 8d92fb292706 ("dir: replace exponential algorithm with a linear one")
  @ 2021-12-07  5:29  5% ` Elijah Newren
  2021-12-07  7:14  0%   ` Uwe Kleine-König
  0 siblings, 1 reply; 200+ results
From: Elijah Newren @ 2021-12-07  5:29 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: Git Mailing List, Björn Lässig

On Mon, Dec 6, 2021 at 4:16 AM Uwe Kleine-König
<u.kleine-koenig@pengutronix.de> wrote:
>
> Hello,
>
> I admit this is somewhat of a corner case, still it happens in the
> reality of our admin team ...
> Initially this was noticed after upgrading the OS from Debian buster
> (with git 2.20.1) to Debian bullseye (with git 2.30.2).
>
> (wgit is just a wrapper for git to call it from my ~/src/git.)
>
> This is the good ("old") case:
>
>         uwe@taurus:~/tmp/8d92fb29270$ wgit version
>         git version 2.25.2.7.g0bbd0e8b5233
>
>         uwe@taurus:~/tmp/8d92fb292706$ wgit init
>         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/.git/
>
>         uwe@taurus:~/tmp/8d92fb292706$ mkdir subdir
>         uwe@taurus:~/tmp/8d92fb292706$ cd subdir/
>         uwe@taurus:~/tmp/8d92fb292706/subdir$ wgit init
>         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/subdir/.git/
>         uwe@taurus:~/tmp/8d92fb292706/subdir$ cd ..
>
>         uwe@taurus:~/tmp/8d92fb292706$ echo content > subdir/somefile
>         uwe@taurus:~/tmp/8d92fb292706$ wgit add subdir/somefile
>         uwe@taurus:~/tmp/8d92fb292706$ wgit status
>         On branch master
>
>         No commits yet
>
>         Changes to be committed:
>           (use "git rm --cached <file>..." to unstage)
>                 new file:   subdir/somefile

Eek, that's bad.  I think there's a number of dragons going down that route.

> with 8d92fb292706, the following happens:
>
>         uwe@taurus:~/tmp/8d92fb292706$ wgit version
>         git version 2.25.2.8.g8d92fb292706
>         uwe@taurus:~/tmp/8d92fb292706$ wgit init
>         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/.git/
>         uwe@taurus:~/tmp/8d92fb292706$ mkdir subdir
>         uwe@taurus:~/tmp/8d92fb292706$ cd subdir/
>         uwe@taurus:~/tmp/8d92fb292706/subdir$ wgit init
>         Initialized empty Git repository in /home/uwe/tmp/8d92fb292706/subdir/.git/
>         uwe@taurus:~/tmp/8d92fb292706/subdir$ cd ..
>         uwe@taurus:~/tmp/8d92fb292706$ echo content > subdir/somefile
>         uwe@taurus:~/tmp/8d92fb292706$ wgit add subdir/somefile

Not optimal; more on this below.

>         uwe@taurus:~/tmp/8d92fb292706$ wgit status
>         On branch master
>
>         No commits yet
>
>         Untracked files:
>           (use "git add <file>..." to include in what will be committed)
>                 subdir/
>
>         nothing added to commit but untracked files present (use "git add" to track)

This part looks good to me.

> So git after 8d92fb292706 doesn't add files from a subdirectory if
> said subdirectory is tracked in git, too.
>
> While I'm not sure which of the two behaviours is the bogus one, this is
> a change in behaviour that I guess wasn't intended in 8d92fb292706.

I put some effort separate from that commit into avoiding accidentally
recursing into nested git dirs; see e.g. commit 09487f2cba ("clean:
avoid removing untracked files in a nested git repository",
2019-09-17).  So, I was slightly surprised that some other commit
hadn't fixed this.

However, it's not all that surprising to me that 8d92fb292706 affected
this.  Prior to that commit, we visited untracked paths which were n
directories deep a ridiculous 2^n times.  But what made it even more
fun was that the status returned for any given path (tracked, ignored,
not interesting to the traversal, etc.) was not always the same; later
traversals might return something different than earlier traversals.
That confusion made it real "fun" trying to ensure no regressions when
reducing the number of visits to any given path from 2^n down to 1.
The fact that side effects of the traversals (the population of the
dir.entries and dir.ignored) could have essentially functioned to
override a later traversal's return status certainly didn't help; it
was such a mess.

But, interestingly, the fixed behavior here also depends pretty
strongly on commit b9670c1f5e ("dir: fix checks on common prefix
directory", 2019-12-19) which came months earlier.  This is
particularly important in combination with the following comment from
dir.h:
    /**
     * If set, recurse into a directory that looks like a Git directory.
     * Otherwise it is shown as a directory.
     */
    DIR_NO_GITLINKS = 1<<3,
which suggests that cmd_add() (which didn't set this flag) should have
never been recursing into a Git-tracked directory.  In other words,
this was a bug all along.

> Is this something that needs fixing?

I agree with brian elsewhere in this thread that not adding the file
is correct.  However, two points:

* I would prefer to see a warning/error from git add when it doesn't
add a path  (Any takers?  #leftoverbits maybe?)

* It is possible that one might want to be able to force the addition
of files to an outer repository despite existing within a directory
tracked by an inner git repository, perhaps with a double `--force`
being passed to git-add (much like git-clean allows).  If so, that
could be implemented via the addition of
    dir.flags |= DIR_NO_GITLINKS;
to cmd_add() when the double force is detected.


Hope that helps,
Elijah

^ permalink raw reply	[relevance 5%]

* [PATCH v2 07/21] refs/files: remove "name exist?" check in lock_ref_oid_basic()
  @ 2021-10-16  9:39  4%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-10-16  9:39 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Han-Wen Nienhuys,
	Ævar Arnfjörð Bjarmason

In lock_ref_oid_basic() we'll happily lock a reference that doesn't
exist yet. That's normal, and is how references are initially born,
but we don't need to retain checks here in lock_ref_oid_basic() about
the state of the ref, when what we're checking is either checked
already, or something we're about to discover by trying to lock the
ref with raceproof_create_file().

The one exception is the caller in files_reflog_expire(), who passes
us a "type" to find out if the reference is a symref or not. We can
move the that logic over to that caller, which can now defer its
discovery of whether or not the ref is a symref until it's needed. In
the preceding commit an exhaustive regression test was added for that
case in a new test in "t1417-reflog-updateref.sh".

The improved diagnostics here were added in
5b2d8d6f218 (lock_ref_sha1_basic(): improve diagnostics for ref D/F
conflicts, 2015-05-11), and then much of the surrounding code went
away recently in my 245fbba46d6 (refs/files: remove unused "errno ==
EISDIR" code, 2021-08-23).

The refs_resolve_ref_unsafe() code being removed here looks like it
should be tasked with doing that, but it's actually redundant to other
code.

The reason for that is as noted in 245fbba46d6 this once widely used
function now only has a handful of callers left, which all handle this
case themselves.

To the extent that we're racy between their check and ours removing
this check actually improves the situation, as we'll be doing fewer
things between the not-under-lock initial check and acquiring the
lock.

Why this is OK for all the remaining callers of lock_ref_oid_basic()
is noted below. There are only two of those callers:

* "git branch -[cm] <oldbranch> <newbranch>":

  In files_copy_or_rename_ref() we'll call this when we copy or rename
  refs via rename_ref() and copy_ref(). but only after we've checked
  if the refname exists already via its own call to
  refs_resolve_ref_unsafe() and refs_rename_ref_available().

  As the updated comment to the latter here notes neither of those are
  actually needed. If we delete not only this code but also
  refs_rename_ref_available() we'll do just fine, we'll just emit a
  less friendly error message if e.g. "git branch -m A B/C" would have
  a D/F conflict with a "B" file.

  Actually we'd probably die before that in case reflogs for the
  branch existed, i.e. when the try to rename() or copy_file() the
  relevant reflog, since if we've got a D/F conflict with a branch
  name we'll probably also have the same with its reflogs (but not
  necessarily, we might have reflogs, but it might not).

  As some #leftoverbits that code seems buggy to me, i.e. the reflog
  "protocol" should be to get a lock on the main ref, and then perform
  ref and/or reflog operations. That code dates back to
  c976d415e53 (git-branch: add options and tests for branch renaming,
  2006-11-28) and probably pre-dated the solidifying of that
  convention. But in any case, that edge case is not our bug or
  problem right now.

* "git reflog expire <ref>":

  In files_reflog_expire() we'll call this without previous ref
  existence checking in files-backend.c, but that code is in turn
  called by code that's just finished checking if the refname whose
  reflog we're expiring exists.

  See ae35e16cd43 (reflog expire: don't lock reflogs using previously
  seen OID, 2021-08-23) for the current state of that code, and
  5e6f003ca8a (reflog_expire(): ignore --updateref for symbolic
  references, 2015-03-03) for the code we'd break if we only did a
  "update = !!ref" here, which is covered by the aforementioned
  regression test in "t1417-reflog-updateref.sh".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs/files-backend.c | 48 ++++++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/refs/files-backend.c b/refs/files-backend.c
index 0af6ee44552..16e78326381 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1001,7 +1001,7 @@ static int create_reflock(const char *path, void *cb)
  * Locks a ref returning the lock on success and NULL on failure.
  */
 static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
-					   const char *refname, int *type,
+					   const char *refname,
 					   struct strbuf *err)
 {
 	struct strbuf ref_file = STRBUF_INIT;
@@ -1013,16 +1013,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 	CALLOC_ARRAY(lock, 1);
 
 	files_ref_path(refs, &ref_file, refname);
-	if (!refs_resolve_ref_unsafe(&refs->base, refname,
-				     RESOLVE_REF_NO_RECURSE,
-				     &lock->old_oid, type)) {
-		if (!refs_verify_refname_available(&refs->base, refname,
-						   NULL, NULL, err))
-			strbuf_addf(err, "unable to resolve reference '%s': %s",
-				    refname, strerror(errno));
-
-		goto error_return;
-	}
 
 	/*
 	 * If the ref did not exist and we are creating it, make sure
@@ -1364,14 +1354,14 @@ static int commit_ref_update(struct files_ref_store *refs,
 			     struct strbuf *err);
 
 /*
- * Check whether an attempt to rename old_refname to new_refname would
- * cause a D/F conflict with any existing reference (other than
- * possibly old_refname). If there would be a conflict, emit an error
+ * Emit a better error message than lockfile.c's
+ * unable_to_lock_message() would in case there is a D/F conflict with
+ * another existing reference. If there would be a conflict, emit an error
  * message and return false; otherwise, return true.
  *
  * Note that this function is not safe against all races with other
- * processes (though rename_ref() catches some races that might get by
- * this check).
+ * processes, and that's not its job. We'll emit a more verbose error on D/f
+ * conflicts if we get past it into lock_ref_oid_basic().
  */
 static int refs_rename_ref_available(struct ref_store *refs,
 			      const char *old_refname,
@@ -1492,7 +1482,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 
 	logmoved = log;
 
-	lock = lock_ref_oid_basic(refs, newrefname, NULL, &err);
+	lock = lock_ref_oid_basic(refs, newrefname, &err);
 	if (!lock) {
 		if (copy)
 			error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
@@ -1514,7 +1504,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
 	goto out;
 
  rollback:
-	lock = lock_ref_oid_basic(refs, oldrefname, NULL, &err);
+	lock = lock_ref_oid_basic(refs, oldrefname, &err);
 	if (!lock) {
 		error("unable to lock %s for rollback: %s", oldrefname, err.buf);
 		strbuf_release(&err);
@@ -1921,7 +1911,7 @@ static int files_create_symref(struct ref_store *ref_store,
 	struct ref_lock *lock;
 	int ret;
 
-	lock = lock_ref_oid_basic(refs, refname, NULL, &err);
+	lock = lock_ref_oid_basic(refs, refname, &err);
 	if (!lock) {
 		error("%s", err.buf);
 		strbuf_release(&err);
@@ -3125,7 +3115,6 @@ static int files_reflog_expire(struct ref_store *ref_store,
 	struct strbuf log_file_sb = STRBUF_INIT;
 	char *log_file;
 	int status = 0;
-	int type;
 	struct strbuf err = STRBUF_INIT;
 	const struct object_id *oid;
 
@@ -3139,7 +3128,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
 	 * reference itself, plus we might need to update the
 	 * reference if --updateref was specified:
 	 */
-	lock = lock_ref_oid_basic(refs, refname, &type, &err);
+	lock = lock_ref_oid_basic(refs, refname, &err);
 	if (!lock) {
 		error("cannot lock ref '%s': %s", refname, err.buf);
 		strbuf_release(&err);
@@ -3201,9 +3190,20 @@ static int files_reflog_expire(struct ref_store *ref_store,
 		 * a reference if there are no remaining reflog
 		 * entries.
 		 */
-		int update = (flags & EXPIRE_REFLOGS_UPDATE_REF) &&
-			!(type & REF_ISSYMREF) &&
-			!is_null_oid(&cb.last_kept_oid);
+		int update = 0;
+
+		if ((flags & EXPIRE_REFLOGS_UPDATE_REF) &&
+		    !is_null_oid(&cb.last_kept_oid)) {
+			int ignore_errno;
+			int type;
+			const char *ref;
+
+			ref = refs_werrres_ref_unsafe(&refs->base, refname,
+						      RESOLVE_REF_NO_RECURSE,
+						      NULL, &type,
+						      &ignore_errno);
+			update = !!(ref && !(type & REF_ISSYMREF));
+		}
 
 		if (close_lock_file_gently(&reflog_lock)) {
 			status |= error("couldn't write %s: %s", log_file,
-- 
2.33.1.1338.g20da966911a


^ permalink raw reply related	[relevance 4%]

* [PATCH 0/2] test-lib.sh: add BAIL_OUT function, use it for SANITIZE=leak
@ 2021-10-14  0:47  6% Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-10-14  0:47 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

This series adds a BAIL_OUT function, and uses it when the new
GIT_TEST_PASSING_SANITIZE_LEAK=true mode is misused.

Once we have this function we'll be able to use it for any other error
that's a cause for aborting the entire test run.

I experimented with making BUG() and error() always be a "BAIL_OUT". I
think that's worth pursuing, but e.g. for the error about missing
"&&-chains" we'd need to support emitting multi-line messages.

TAP consumers only understand what follows the "Bail out!" message up
to the first "\n", so we can't quote the entire "test_expect_success",
as the "&&-chain" error does. I think emitting them with "say_error()"
beforehand (piped with ">&7" in the case of "BUG()") should work, but
let's leave those #leftoverbits for later.

Ævar Arnfjörð Bjarmason (2):
  test-lib.sh: de-duplicate error() teardown code
  test-lib.sh: use "Bail out!" syntax on bad SANITIZE=leak use

 t/test-lib.sh | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

-- 
2.33.1.1346.g48288c3c089


^ permalink raw reply	[relevance 6%]

* [PATCH 06/20] refs/files: remove "name exist?" check in lock_ref_oid_basic()
  @ 2021-10-14  0:06  4% ` Ævar Arnfjörð Bjarmason
    1 sibling, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-10-14  0:06 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Han-Wen Nienhuys,
	Ævar Arnfjörð Bjarmason

In lock_ref_oid_basic() we'll happily lock a reference that doesn't
exist yet. That's normal, and is how references are initially born,
but we don't need to retain checks here in lock_ref_oid_basic() about
the state of the ref, when what we're checking is either checked
already, or something we're about to discover by trying to lock the
ref with raceproof_create_file().

The improved diagnostics here were added in
5b2d8d6f218 (lock_ref_sha1_basic(): improve diagnostics for ref D/F
conflicts, 2015-05-11), and then much of the surrounding code went
away recently in my 245fbba46d6 (refs/files: remove unused "errno ==
EISDIR" code, 2021-08-23).

The refs_resolve_ref_unsafe() code being removed here looks like it
should be tasked with doing that, but it's actually redundant to other
code.

The reason for that is as noted in 245fbba46d6 this once widely used
function now only has a handful of callers left, which all handle this
case themselves.

To the extent that we're racy between their check and ours removing
this check actually improves the situation, as we'll be doing fewer
things between the not-under-lock initial check and acquiring the
lock.

Why this is OK for all the remaining callers of lock_ref_oid_basic()
is noted below. There are only two of those callers:

* "git branch -[cm] <oldbranch> <newbranch>":

  In files_copy_or_rename_ref() we'll call this when we copy or rename
  refs via rename_ref() and copy_ref(). but only after we've checked
  if the refname exists already via its own call to
  refs_resolve_ref_unsafe() and refs_rename_ref_available().

  As the updated comment to the latter here notes neither of those are
  actually needed. If we delete not only this code but also
  refs_rename_ref_available() we'll do just fine, we'll just emit a
  less friendly error message if e.g. "git branch -m A B/C" would have
  a D/F conflict with a "B" file.

  Actually we'd probably die before that in case reflogs for the
  branch existed, i.e. when the try to rename() or copy_file() the
  relevant reflog, since if we've got a D/F conflict with a branch
  name we'll probably also have the same with its reflogs (but not
  necessarily, we might have reflogs, but it might not).

  As some #leftoverbits that code seems buggy to me, i.e. the reflog
  "protocol" should be to get a lock on the main ref, and then perform
  ref and/or reflog operations. That code dates back to
  c976d415e53 (git-branch: add options and tests for branch renaming,
  2006-11-28) and probably pre-dated the solidifying of that
  convention. But in any case, that edge case is not our bug or
  problem right now.

* "git reflog expire <ref>":

  In files_reflog_expire() we'll call this without previous ref
  existence checking in files-backend.c, but that code is in turn
  called by code that's just finished checking if the refname whose
  reflog we're expiring exists.

  See ae35e16cd43 (reflog expire: don't lock reflogs using previously
  seen OID, 2021-08-23) for the current state of that code.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs/files-backend.c | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/refs/files-backend.c b/refs/files-backend.c
index 0af6ee44552..0dd21b2e205 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -1013,16 +1013,6 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
 	CALLOC_ARRAY(lock, 1);
 
 	files_ref_path(refs, &ref_file, refname);
-	if (!refs_resolve_ref_unsafe(&refs->base, refname,
-				     RESOLVE_REF_NO_RECURSE,
-				     &lock->old_oid, type)) {
-		if (!refs_verify_refname_available(&refs->base, refname,
-						   NULL, NULL, err))
-			strbuf_addf(err, "unable to resolve reference '%s': %s",
-				    refname, strerror(errno));
-
-		goto error_return;
-	}
 
 	/*
 	 * If the ref did not exist and we are creating it, make sure
@@ -1364,14 +1354,14 @@ static int commit_ref_update(struct files_ref_store *refs,
 			     struct strbuf *err);
 
 /*
- * Check whether an attempt to rename old_refname to new_refname would
- * cause a D/F conflict with any existing reference (other than
- * possibly old_refname). If there would be a conflict, emit an error
+ * Emit a better error message than lockfile.c's
+ * unable_to_lock_message() would in case there is a D/F conflict with
+ * another existing reference. If there would be a conflict, emit an error
  * message and return false; otherwise, return true.
  *
  * Note that this function is not safe against all races with other
- * processes (though rename_ref() catches some races that might get by
- * this check).
+ * processes, and that's not its job. We'll emit a more verbose error on D/f
+ * conflicts if we get past it into lock_ref_oid_basic().
  */
 static int refs_rename_ref_available(struct ref_store *refs,
 			      const char *old_refname,
-- 
2.33.1.1346.g48288c3c089


^ permalink raw reply related	[relevance 4%]

* Re: [PATCH] http: check CURLE_SSL_PINNEDPUBKEYNOTMATCH when emitting errors
  2021-09-24 10:08  5% [PATCH] http: check CURLE_SSL_PINNEDPUBKEYNOTMATCH when emitting errors Ævar Arnfjörð Bjarmason
@ 2021-10-10 21:42  0% ` SZEDER Gábor
  0 siblings, 0 replies; 200+ results
From: SZEDER Gábor @ 2021-10-10 21:42 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, Junio C Hamano, Jeff King

On Fri, Sep 24, 2021 at 12:08:20PM +0200, Ævar Arnfjörð Bjarmason wrote:
> Change the error shown when a http.pinnedPubKey doesn't match to point
> the http.pinnedPubKey variable 

I'm not sure what this means.  Between the repeated
'http.pinnedPubKey' config variable name and the "doesn't match to
point the ..." part I can't decipher it.

> added in aeff8a61216 (http: implement
> public key pinning, 2016-02-15), e.g.:
> 
>     git -c http.pinnedPubKey=sha256/someNonMatchingKey ls-remote https://github.com/git/git.git
>     fatal: unable to access 'https://github.com/git/git.git/' with http.pinnedPubkey configuration: SSL: public key does not match pinned public key!
> 
> Before this we'd emit the exact same thing without the " with
> http.pinnedPubkey configuration". The advantage of doing this is that
> we're going to get a translated message (everything after the ":" is
> hardcoded in English in libcurl), and we've got a reference to the
> git-specific configuration variable that's causing the error.
> 
> Unfortunately we can't test this easily, as there are no tests that
> require https:// in the test suite, and t/lib-httpd.sh doesn't know
> how to set up such tests. See [1] for the start of a discussion about
> what it would take to have divergent "t/lib-httpd/apache.conf" test
> setups. #leftoverbits
> 
> 1. https://lore.kernel.org/git/YUonS1uoZlZEt+Yd@coredump.intra.peff.net/
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
> 
> I had this waiting on the now-landed ab/http-drop-old-curl-plus due to
> adding a new entry to git-curl-compat.h.
> 
>  git-curl-compat.h | 3 ++-
>  http.c            | 4 ++++
>  http.h            | 1 +
>  remote-curl.c     | 4 ++++
>  4 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/git-curl-compat.h b/git-curl-compat.h
> index a308bdb3b9b..56a83b6bbd8 100644
> --- a/git-curl-compat.h
> +++ b/git-curl-compat.h
> @@ -64,16 +64,17 @@
>  #if LIBCURL_VERSION_NUM >= 0x072200
>  #define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0
>  #endif
>  
>  /**
>   * CURLOPT_PINNEDPUBLICKEY was added in 7.39.0, released in November
> - * 2014.
> + * 2014. CURLE_SSL_PINNEDPUBKEYNOTMATCH was added in that same version.
>   */
>  #if LIBCURL_VERSION_NUM >= 0x072c00
>  #define GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY 1
> +#define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1
>  #endif
>  
>  /**
>   * CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015.
>   *
>   * The CURL_HTTP_VERSION_2 alias (but not CURL_HTTP_VERSION_2_0) has
> diff --git a/http.c b/http.c
> index d7c20493d7f..b6735b51c31 100644
> --- a/http.c
> +++ b/http.c
> @@ -1486,12 +1486,16 @@ static int handle_curl_result(struct slot_results *results)
>  		 * certificate, bad password, or something else wrong
>  		 * with the certificate.  So we reject the credential to
>  		 * avoid caching or saving a bad password.
>  		 */
>  		credential_reject(&cert_auth);
>  		return HTTP_NOAUTH;
> +#ifdef GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH
> +	} else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) {
> +		return HTTP_NOMATCHPUBLICKEY;
> +#endif
>  	} else if (missing_target(results))
>  		return HTTP_MISSING_TARGET;
>  	else if (results->http_code == 401) {
>  		if (http_auth.username && http_auth.password) {
>  			credential_reject(&http_auth);
>  			return HTTP_NOAUTH;
> diff --git a/http.h b/http.h
> index 3db5a0cf320..df1590e53a4 100644
> --- a/http.h
> +++ b/http.h
> @@ -151,12 +151,13 @@ struct http_get_options {
>  #define HTTP_OK			0
>  #define HTTP_MISSING_TARGET	1
>  #define HTTP_ERROR		2
>  #define HTTP_START_FAILED	3
>  #define HTTP_REAUTH	4
>  #define HTTP_NOAUTH	5
> +#define HTTP_NOMATCHPUBLICKEY	6
>  
>  /*
>   * Requests a URL and stores the result in a strbuf.
>   *
>   * If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
>   */
> diff --git a/remote-curl.c b/remote-curl.c
> index 598cff7cde6..8700dbdc0ac 100644
> --- a/remote-curl.c
> +++ b/remote-curl.c
> @@ -496,12 +496,16 @@ static struct discovery *discover_refs(const char *service, int for_push)
>  		die(_("repository '%s' not found"),
>  		    transport_anonymize_url(url.buf));
>  	case HTTP_NOAUTH:
>  		show_http_message(&type, &charset, &buffer);
>  		die(_("Authentication failed for '%s'"),
>  		    transport_anonymize_url(url.buf));
> +	case HTTP_NOMATCHPUBLICKEY:
> +		show_http_message(&type, &charset, &buffer);
> +		die(_("unable to access '%s' with http.pinnedPubkey configuration: %s"),
> +		    transport_anonymize_url(url.buf), curl_errorstr);
>  	default:
>  		show_http_message(&type, &charset, &buffer);
>  		die(_("unable to access '%s': %s"),
>  		    transport_anonymize_url(url.buf), curl_errorstr);
>  	}
>  
> -- 
> 2.33.0.1231.g24d802460a8
> 

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 1/2] object.[ch]: mark object type names for translation
  2021-10-04 14:27  5%   ` [PATCH v2 1/2] object.[ch]: mark object type names for translation Ævar Arnfjörð Bjarmason
  2021-10-04 18:54  0%     ` Eric Sunshine
@ 2021-10-06 19:05  0%     ` Jeff King
  1 sibling, 0 replies; 200+ results
From: Jeff King @ 2021-10-06 19:05 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, Junio C Hamano

On Mon, Oct 04, 2021 at 04:27:01PM +0200, Ævar Arnfjörð Bjarmason wrote:

> Mark the "commit", "tree", "blob" and "tag" types for translation, and
> add an extern "unknown type" string for the OBJ_NONE case.
> 
> It is usually bad practice to translate individual words like this,
> but for e.g. the list list output emitted by the "short object ID dead
> is ambiguous" advice it makes sense.

We already seem to have a translatable string for "commit", but if I
look at say es.po, the translation is "confirmar", which is considering
it a verb. Now my Spanish is pretty rusty, so it's possible this works
as a noun, too. But if I look at other messages, like:

  #: builtin/commit.c:1623
  msgid "override date for commit"
  msgstr "sobrescribe la fecha del commit"

  #: builtin/commit.c:1626
  msgid "reuse message from specified commit"
  msgstr "reusar el mensaje de un commit específico"

then it's clear that "commit" as a noun is translated as "commit". I'm
not sure what facilities (if any) there are in gettext for having the
same string in different contexts.

I do note that this is already a problem. Of the five spots listed:

  #: builtin/commit.c:1625 builtin/commit.c:1626 builtin/commit.c:1632
  #: parse-options.h:329 ref-filter.h:90
  msgid "commit"
  msgstr "confirmar"

They all appear to want is as a noun. So maybe this is just
mis-translated for Spanish. It does feel like an accident in the making,
though.

> A subsequent commit will make that output translatable, and use these
> translation markings to do so. Well, we won't use "commit", but let's
> mark it up anyway for consistency. It'll probably come in handy sooner
> than later to have it already be translated, and it's to much of a
> burden to place on translators if they're translating the other three
> object types anyway.

I do wonder how useful it is to translate these type names in general.
Especially as used in this series, they're really technical terms, and
you are not going to escape the name "git commit" as a command. But I
don't ever use translated Git, so I'm not sure my opinion is all that
meaningful there.

> Aside: I think it would probably make sense to change the "NULL" entry
> for type_name() to be the "unknown type". I've ran into cases where
> type_name() was unconditionally interpolated in e.g. an sprintf()
> format, but let's leave that for #leftoverbits as that would be
> changing the behavior of the type_name() function.

IMHO this would be a bad idea. Even if there is a spot that uses the
result without checking for NULL, I'd much rather have Git segfault than
say, write out an object with a bogus name (as it would in index_mem(),
for example). So you really have to look over every caller, at which
point you may as well adjust the ones that aren't checking for NULL.

Now if you introduced type_name_human(), which auto-translated and
converted NULL to "unknown", then that would be easy to plug in
appropriately as you audited the callers.

>  static const char *object_type_strings[] = {
>  	NULL,		/* OBJ_NONE = 0 */
> -	"commit",	/* OBJ_COMMIT = 1 */
> -	"tree",		/* OBJ_TREE = 2 */
> -	"blob",		/* OBJ_BLOB = 3 */
> -	"tag",		/* OBJ_TAG = 4 */
> +	/*
> +	 * TRANSLATORS: "commit", "tree", "blob" and "tag" are the
> +	 * name of Git's object types. These names are interpolated
> +	 * stand-alone when doing so is unambiguous for translation
> +	 * and doesn't require extra context. E.g. as part of an
> +	 * already-translated string that needs to have a type name
> +	 * quoted verbatim, or the short description of a command-line
> +	 * option expecting a given type.
> +	 */
> +	N_("commit"),	/* OBJ_COMMIT = 1 */
> +	N_("tree"),	/* OBJ_TREE = 2 */
> +	N_("blob"),	/* OBJ_BLOB = 3 */
> +	N_("tag"),	/* OBJ_TAG = 4 */
>  };

This does make me feel slightly uneasy, just because so many parts of
Git rely on these _not_ being translated. But I see in your other
response that N_() really does nothing. So aside from possibly
misleading readers of the code, I think this is probably OK.

-Peff

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v2 1/2] object.[ch]: mark object type names for translation
  2021-10-04 14:27  5%   ` [PATCH v2 1/2] object.[ch]: mark object type names for translation Ævar Arnfjörð Bjarmason
@ 2021-10-04 18:54  0%     ` Eric Sunshine
  2021-10-06 19:05  0%     ` Jeff King
  1 sibling, 0 replies; 200+ results
From: Eric Sunshine @ 2021-10-04 18:54 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: Git List, Junio C Hamano, Jeff King

On Mon, Oct 4, 2021 at 10:27 AM Ævar Arnfjörð Bjarmason
<avarab@gmail.com> wrote:
> Mark the "commit", "tree", "blob" and "tag" types for translation, and
> add an extern "unknown type" string for the OBJ_NONE case.
>
> It is usually bad practice to translate individual words like this,
> but for e.g. the list list output emitted by the "short object ID dead

"list list"?

> is ambiguous" advice it makes sense.
>
> A subsequent commit will make that output translatable, and use these
> translation markings to do so. Well, we won't use "commit", but let's
> mark it up anyway for consistency. It'll probably come in handy sooner
> than later to have it already be translated, and it's to much of a
> burden to place on translators if they're translating the other three
> object types anyway.

At first I thought you meant s/to much/too much/, but that doesn't
seem to make sense (unless I'm misunderstanding), so perhaps you mean
s/to/not/.

> Aside: I think it would probably make sense to change the "NULL" entry
> for type_name() to be the "unknown type". I've ran into cases where
> type_name() was unconditionally interpolated in e.g. an sprintf()
> format, but let's leave that for #leftoverbits as that would be
> changing the behavior of the type_name() function.
>
> All of these will be new in the git.pot file, except "blob" which will
> be shared with a "cat-file" command-line option, see
> 7bcf3414535 (cat-file --textconv/--filters: allow specifying the path
> separately, 2016-09-09) for its introduction.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

^ permalink raw reply	[relevance 0%]

* [PATCH v2 1/2] object.[ch]: mark object type names for translation
  2021-10-04 14:27  3% ` [PATCH v2 " Ævar Arnfjörð Bjarmason
@ 2021-10-04 14:27  5%   ` Ævar Arnfjörð Bjarmason
  2021-10-04 18:54  0%     ` Eric Sunshine
  2021-10-06 19:05  0%     ` Jeff King
  0 siblings, 2 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-10-04 14:27 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

Mark the "commit", "tree", "blob" and "tag" types for translation, and
add an extern "unknown type" string for the OBJ_NONE case.

It is usually bad practice to translate individual words like this,
but for e.g. the list list output emitted by the "short object ID dead
is ambiguous" advice it makes sense.

A subsequent commit will make that output translatable, and use these
translation markings to do so. Well, we won't use "commit", but let's
mark it up anyway for consistency. It'll probably come in handy sooner
than later to have it already be translated, and it's to much of a
burden to place on translators if they're translating the other three
object types anyway.

Aside: I think it would probably make sense to change the "NULL" entry
for type_name() to be the "unknown type". I've ran into cases where
type_name() was unconditionally interpolated in e.g. an sprintf()
format, but let's leave that for #leftoverbits as that would be
changing the behavior of the type_name() function.

All of these will be new in the git.pot file, except "blob" which will
be shared with a "cat-file" command-line option, see
7bcf3414535 (cat-file --textconv/--filters: allow specifying the path
separately, 2016-09-09) for its introduction.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 object.c | 27 +++++++++++++++++++++++----
 object.h |  1 +
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/object.c b/object.c
index 4e85955a941..47dbe0d8a2a 100644
--- a/object.c
+++ b/object.c
@@ -22,12 +22,31 @@ struct object *get_indexed_object(unsigned int idx)
 
 static const char *object_type_strings[] = {
 	NULL,		/* OBJ_NONE = 0 */
-	"commit",	/* OBJ_COMMIT = 1 */
-	"tree",		/* OBJ_TREE = 2 */
-	"blob",		/* OBJ_BLOB = 3 */
-	"tag",		/* OBJ_TAG = 4 */
+	/*
+	 * TRANSLATORS: "commit", "tree", "blob" and "tag" are the
+	 * name of Git's object types. These names are interpolated
+	 * stand-alone when doing so is unambiguous for translation
+	 * and doesn't require extra context. E.g. as part of an
+	 * already-translated string that needs to have a type name
+	 * quoted verbatim, or the short description of a command-line
+	 * option expecting a given type.
+	 */
+	N_("commit"),	/* OBJ_COMMIT = 1 */
+	N_("tree"),	/* OBJ_TREE = 2 */
+	N_("blob"),	/* OBJ_BLOB = 3 */
+	N_("tag"),	/* OBJ_TAG = 4 */
 };
 
+/*
+ * TRANSLATORS: This is the short type name of an object that's not
+ * one of Git's known object types, as opposed to "commit", "tree",
+ * "blob" and "tag" above.
+ *
+ * A user is unlikely to ever encounter these, but they can be
+ * manually created with "git hash-object --literally".
+ */
+const char *unknown_type = N_("unknown type");
+
 const char *type_name(unsigned int type)
 {
 	if (type >= ARRAY_SIZE(object_type_strings))
diff --git a/object.h b/object.h
index 549f2d256bc..0510dc4b3ea 100644
--- a/object.h
+++ b/object.h
@@ -91,6 +91,7 @@ struct object {
 	struct object_id oid;
 };
 
+extern const char *unknown_type;
 const char *type_name(unsigned int type);
 int type_from_string_gently(const char *str, ssize_t, int gentle);
 #define type_from_string(str) type_from_string_gently(str, -1, 0)
-- 
2.33.0.1409.ge73c1ecc5b4


^ permalink raw reply related	[relevance 5%]

* [PATCH v2 0/2] i18n: improve translatability of ambiguous object output
  @ 2021-10-04 14:27  3% ` Ævar Arnfjörð Bjarmason
  2021-10-04 14:27  5%   ` [PATCH v2 1/2] object.[ch]: mark object type names for translation Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-10-04 14:27 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

A mostly-rewritten version in response to the discussion concluding at
http://lore.kernel.org/git/YVrudGOcUxblsfPY@coredump.intra.peff.net;
thanks a lot for the thorough review Jeff!

Ævar Arnfjörð Bjarmason (2):
  object.[ch]: mark object type names for translation
  object-name: make ambiguous object output translatable

 object-name.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-----
 object.c      | 27 ++++++++++++++++---
 object.h      |  1 +
 3 files changed, 90 insertions(+), 10 deletions(-)

Range-diff against v1:
1:  7085f951a12 ! 1:  55bde16aa23 object-name tests: tighten up advise() output test
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    object-name tests: tighten up advise() output test
    +    object.[ch]: mark object type names for translation
     
    -    Change tests added in 1ffa26c4614 (get_short_sha1: list ambiguous
    -    objects on error, 2016-09-26) to only care about the OIDs that are
    -    listed, which is what the test is trying to check for.
    +    Mark the "commit", "tree", "blob" and "tag" types for translation, and
    +    add an extern "unknown type" string for the OBJ_NONE case.
     
    -    This isn't needed by the subsequent commit, which won't change any of
    -    the output, but a mere tightening of the tests assertions to more
    -    closely match what we really want to test for here.
    +    It is usually bad practice to translate individual words like this,
    +    but for e.g. the list list output emitted by the "short object ID dead
    +    is ambiguous" advice it makes sense.
     
    -    Now if the advise() message itself were change the phrasing around the
    -    list of OIDs we won't have this test break. We're assuming that such
    -    output won't have a need to indent anything except the OIDs.
    +    A subsequent commit will make that output translatable, and use these
    +    translation markings to do so. Well, we won't use "commit", but let's
    +    mark it up anyway for consistency. It'll probably come in handy sooner
    +    than later to have it already be translated, and it's to much of a
    +    burden to place on translators if they're translating the other three
    +    object types anyway.
    +
    +    Aside: I think it would probably make sense to change the "NULL" entry
    +    for type_name() to be the "unknown type". I've ran into cases where
    +    type_name() was unconditionally interpolated in e.g. an sprintf()
    +    format, but let's leave that for #leftoverbits as that would be
    +    changing the behavior of the type_name() function.
    +
    +    All of these will be new in the git.pot file, except "blob" which will
    +    be shared with a "cat-file" command-line option, see
    +    7bcf3414535 (cat-file --textconv/--filters: allow specifying the path
    +    separately, 2016-09-09) for its introduction.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    - ## t/t1512-rev-parse-disambiguation.sh ##
    -@@ t/t1512-rev-parse-disambiguation.sh: test_expect_success 'ambiguity errors are not repeated (peel)' '
    + ## object.c ##
    +@@ object.c: struct object *get_indexed_object(unsigned int idx)
      
    - test_expect_success 'ambiguity hints' '
    - 	test_must_fail git rev-parse 000000000 2>stderr &&
    --	grep ^hint: stderr >hints &&
    --	# 16 candidates, plus one intro line
    --	test_line_count = 17 hints
    -+	grep "^hint:   " stderr >hints &&
    -+	# 16 candidates, minus surrounding prose
    -+	test_line_count = 16 hints
    - '
    + static const char *object_type_strings[] = {
    + 	NULL,		/* OBJ_NONE = 0 */
    +-	"commit",	/* OBJ_COMMIT = 1 */
    +-	"tree",		/* OBJ_TREE = 2 */
    +-	"blob",		/* OBJ_BLOB = 3 */
    +-	"tag",		/* OBJ_TAG = 4 */
    ++	/*
    ++	 * TRANSLATORS: "commit", "tree", "blob" and "tag" are the
    ++	 * name of Git's object types. These names are interpolated
    ++	 * stand-alone when doing so is unambiguous for translation
    ++	 * and doesn't require extra context. E.g. as part of an
    ++	 * already-translated string that needs to have a type name
    ++	 * quoted verbatim, or the short description of a command-line
    ++	 * option expecting a given type.
    ++	 */
    ++	N_("commit"),	/* OBJ_COMMIT = 1 */
    ++	N_("tree"),	/* OBJ_TREE = 2 */
    ++	N_("blob"),	/* OBJ_BLOB = 3 */
    ++	N_("tag"),	/* OBJ_TAG = 4 */
    + };
      
    - test_expect_success 'ambiguity hints respect type' '
    - 	test_must_fail git rev-parse 000000000^{commit} 2>stderr &&
    --	grep ^hint: stderr >hints &&
    --	# 5 commits, 1 tag (which is a committish), plus intro line
    --	test_line_count = 7 hints
    -+	grep "^hint:   " stderr >hints &&
    -+	# 5 commits, 1 tag (which is a committish), minus surrounding prose
    -+	test_line_count = 6 hints
    - '
    - 
    - test_expect_success 'failed type-selector still shows hint' '
    -@@ t/t1512-rev-parse-disambiguation.sh: test_expect_success 'failed type-selector still shows hint' '
    - 	echo 851 | git hash-object --stdin -w &&
    - 	echo 872 | git hash-object --stdin -w &&
    - 	test_must_fail git rev-parse ee3d^{commit} 2>stderr &&
    --	grep ^hint: stderr >hints &&
    --	test_line_count = 3 hints
    -+	grep "^hint:   " stderr >hints &&
    -+	test_line_count = 2 hints
    - '
    ++/*
    ++ * TRANSLATORS: This is the short type name of an object that's not
    ++ * one of Git's known object types, as opposed to "commit", "tree",
    ++ * "blob" and "tag" above.
    ++ *
    ++ * A user is unlikely to ever encounter these, but they can be
    ++ * manually created with "git hash-object --literally".
    ++ */
    ++const char *unknown_type = N_("unknown type");
    ++
    + const char *type_name(unsigned int type)
    + {
    + 	if (type >= ARRAY_SIZE(object_type_strings))
    +
    + ## object.h ##
    +@@ object.h: struct object {
    + 	struct object_id oid;
    + };
      
    - test_expect_success 'core.disambiguate config can prefer types' '
    ++extern const char *unknown_type;
    + const char *type_name(unsigned int type);
    + int type_from_string_gently(const char *str, ssize_t, int gentle);
    + #define type_from_string(str) type_from_string_gently(str, -1, 0)
2:  b6136380c28 ! 2:  c0e873543f5 object-name: make ambiguous object output translatable
    @@ Commit message
         tweaked in [2] to be more friendly to translators. By being able to
         customize the sprintf formats we're even ready for RTL languages.
     
    -    1. ef9b0370da6 (sha1-name.c: store and use repo in struct
    -       disambiguate_state, 2019-04-16)
    +    The "unknown type" message here is unreachable, and has been since
    +    [1], i.e. that code has never worked. If we craft an object of a bogus
    +    type with a conflicting prefix we'll just die:
    +
    +        $ git rev-parse 8315
    +        error: short object ID 8315 is ambiguous
    +        hint: The candidates are:
    +        fatal: invalid object type
    +
    +    But let's continue to pretend that this works, we can eventually use
    +    the API improvements in my ab/fsck-unexpected-type (once it lands) to
    +    inspect these objects and emit the actual type here, or at least not
    +    die as we emit "unknown type".
    +
    +    1. 1ffa26c461 (get_short_sha1: list ambiguous objects on error,
    +       2016-09-26)
         2. 5cc044e0257 (get_short_oid: sort ambiguous objects by type,
            then SHA-1, 2018-05-10)
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## object-name.c ##
    -@@ object-name.c: static int init_object_disambiguation(struct repository *r,
    - 	return 0;
    - }
    - 
    -+struct show_ambiguous_state {
    -+	const struct disambiguate_state *ds;
    -+	struct strbuf *advice;
    -+};
    -+
    - static int show_ambiguous_object(const struct object_id *oid, void *data)
    +@@ object-name.c: static int show_ambiguous_object(const struct object_id *oid, void *data)
      {
    --	const struct disambiguate_state *ds = data;
    -+	struct show_ambiguous_state *state = data;
    -+	const struct disambiguate_state *ds = state->ds;
    -+	struct strbuf *advice = state->advice;
    + 	const struct disambiguate_state *ds = data;
      	struct strbuf desc = STRBUF_INIT;
    ++	struct strbuf ci_ad = STRBUF_INIT;
    ++	struct strbuf ci_s = STRBUF_INIT;
      	int type;
    ++	const char *tag_desc = NULL;
    ++	const char *abbrev;
      
    + 	if (ds->fn && !ds->fn(ds->repo, oid, ds->cb_data))
    + 		return 0;
     @@ object-name.c: static int show_ambiguous_object(const struct object_id *oid, void *data)
      		if (commit) {
      			struct pretty_print_context pp = {0};
      			pp.date_mode.type = DATE_SHORT;
     -			format_commit_message(commit, " %ad - %s", &desc, &pp);
    -+			format_commit_message(commit, _(" %ad - %s"), &desc, &pp);
    ++			format_commit_message(commit, "%ad", &ci_ad, &pp);
    ++			format_commit_message(commit, "%s", &ci_s, &pp);
      		}
      	} else if (type == OBJ_TAG) {
      		struct tag *tag = lookup_tag(ds->repo, oid);
      		if (!parse_tag(tag) && tag->tag)
     -			strbuf_addf(&desc, " %s", tag->tag);
    -+			strbuf_addf(&desc, _(" %s"), tag->tag);
    ++			tag_desc = tag->tag;
      	}
      
     -	advise("  %s %s%s",
     -	       repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV),
     -	       type_name(type) ? type_name(type) : "unknown type",
     -	       desc.buf);
    -+	strbuf_addf(advice,
    -+		    /*
    -+		     * TRANSLATORS: This is a line of ambiguous object
    -+		     * output. E.g.:
    -+		     *
    -+		     *    "deadbeef commit 2021-01-01 - Some Commit Message\n"
    -+		     *    "deadbeef tag Some Tag Message\n"
    -+		     *    "deadbeef tree\n"
    -+		     *
    -+		     * I.e. the first argument is a short OID, the
    -+		     * second is the type name of the object, and the
    -+		     * third a description of the object, if it's a
    -+		     * commit or tag. In that case the " %ad - %s" and
    -+		     * " %s" formats above will be used for the third
    -+		     * argument.
    -+		     */
    -+		    _("  %s %s%s\n"),
    -+		    repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV),
    -+		    type_name(type) ? type_name(type) : "unknown type",
    -+		    desc.buf);
    - 
    - 	strbuf_release(&desc);
    - 	return 0;
    -@@ object-name.c: static enum get_oid_result get_short_oid(struct repository *r,
    - 	}
    - 
    - 	if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
    -+		struct strbuf sb = STRBUF_INIT;
    - 		struct oid_array collect = OID_ARRAY_INIT;
    -+		struct show_ambiguous_state as = {
    -+			.ds = &ds,
    -+			.advice = &sb,
    -+		};
    - 
    - 		error(_("short object ID %s is ambiguous"), ds.hex_pfx);
    - 
    -@@ object-name.c: static enum get_oid_result get_short_oid(struct repository *r,
    - 		if (!ds.ambiguous)
    - 			ds.fn = NULL;
    - 
    --		advise(_("The candidates are:"));
    - 		repo_for_each_abbrev(r, ds.hex_pfx, collect_ambiguous, &collect);
    - 		sort_ambiguous_oid_array(r, &collect);
    - 
    --		if (oid_array_for_each(&collect, show_ambiguous_object, &ds))
    -+		if (oid_array_for_each(&collect, show_ambiguous_object, &as))
    - 			BUG("show_ambiguous_object shouldn't return non-zero");
    -+
    ++	abbrev = repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV);
    ++	if (type == OBJ_COMMIT) {
     +		/*
    -+		 * TRANSLATORS: The argument is the list of ambiguous
    -+		 * objects composed in show_ambiguous_object(). See
    -+		 * its "TRANSLATORS" comment for details.
    ++		 * TRANSLATORS: This is a line of ambiguous commit
    ++		 * object output. E.g.:
    ++		 *
    ++		 *    "deadbeef commit 2021-01-01 - Some Commit Message"
    ++		 *
    ++		 * The second argument is the "commit" string from
    ++		 * object.c, it should (hopefully) already be
    ++		 * translated.
     +		 */
    -+		advise(_("The candidates are:\n\n%s"), sb.buf);
    ++		strbuf_addf(&desc, _("%s %s %s - %s"), abbrev, ci_ad.buf,
    ++			    _(type_name(type)), ci_s.buf);
    ++	} else if (tag_desc) {
    ++		/*
    ++		 * TRANSLATORS: This is a line of
    ++		 * ambiguous tag object output. E.g.:
    ++		 *
    ++		 *    "deadbeef tag Some Tag Message"
    ++		 *
    ++		 * The second argument is the "tag" string from
    ++		 * object.c, it should (hopefully) already be
    ++		 * translated.
    ++		 */
    ++		strbuf_addf(&desc, _("%s %s %s"), abbrev, _(type_name(type)),
    ++			    tag_desc);
    ++	} else {
    ++		const char *tname = type_name(type) ? _(type_name(type)) :
    ++			_(unknown_type);
    ++		/*
    ++		 * TRANSLATORS: This is a line of ambiguous <type>
    ++		 * object output. Where <type> is one of the object
    ++		 * types of "tree", "blob", "tag" ("commit" is handled
    ++		 * above).
    ++		 *
    ++		 *    "deadbeef tree"
    ++		 *    "deadbeef blob"
    ++		 *    "deadbeef tag"
    ++		 *    "deadbeef unknown type"
    ++		 *
    ++		 * Note that annotated tags use a separate format
    ++		 * outlined above.
    ++		 *
    ++		 * The second argument is the "tree", "blob" or "tag"
    ++		 * string from object.c, or the "unknown type" string
    ++		 * in the case of an unknown type. All of them should
    ++		 * (hopefully) already be translated.
    ++		 */
    ++		strbuf_addf(&desc, _("%s %s"), abbrev, tname);
    ++	}
     +
    - 		oid_array_clear(&collect);
    - 	}
    ++	/*
    ++	 * TRANSLATORS: This is line item of ambiguous object output,
    ++	 * translated above.
    ++	 */
    ++	advise(_("  %s\n"), desc.buf);
    + 
    + 	strbuf_release(&desc);
    ++	strbuf_release(&ci_ad);
    ++	strbuf_release(&ci_s);
    + 	return 0;
    + }
      
-- 
2.33.0.1409.ge73c1ecc5b4


^ permalink raw reply	[relevance 3%]

* [PATCH] http: check CURLE_SSL_PINNEDPUBKEYNOTMATCH when emitting errors
@ 2021-09-24 10:08  5% Ævar Arnfjörð Bjarmason
  2021-10-10 21:42  0% ` SZEDER Gábor
  0 siblings, 1 reply; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-09-24 10:08 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Jeff King, Ævar Arnfjörð Bjarmason

Change the error shown when a http.pinnedPubKey doesn't match to point
the http.pinnedPubKey variable added in aeff8a61216 (http: implement
public key pinning, 2016-02-15), e.g.:

    git -c http.pinnedPubKey=sha256/someNonMatchingKey ls-remote https://github.com/git/git.git
    fatal: unable to access 'https://github.com/git/git.git/' with http.pinnedPubkey configuration: SSL: public key does not match pinned public key!

Before this we'd emit the exact same thing without the " with
http.pinnedPubkey configuration". The advantage of doing this is that
we're going to get a translated message (everything after the ":" is
hardcoded in English in libcurl), and we've got a reference to the
git-specific configuration variable that's causing the error.

Unfortunately we can't test this easily, as there are no tests that
require https:// in the test suite, and t/lib-httpd.sh doesn't know
how to set up such tests. See [1] for the start of a discussion about
what it would take to have divergent "t/lib-httpd/apache.conf" test
setups. #leftoverbits

1. https://lore.kernel.org/git/YUonS1uoZlZEt+Yd@coredump.intra.peff.net/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---

I had this waiting on the now-landed ab/http-drop-old-curl-plus due to
adding a new entry to git-curl-compat.h.

 git-curl-compat.h | 3 ++-
 http.c            | 4 ++++
 http.h            | 1 +
 remote-curl.c     | 4 ++++
 4 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/git-curl-compat.h b/git-curl-compat.h
index a308bdb3b9b..56a83b6bbd8 100644
--- a/git-curl-compat.h
+++ b/git-curl-compat.h
@@ -64,16 +64,17 @@
 #if LIBCURL_VERSION_NUM >= 0x072200
 #define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0
 #endif
 
 /**
  * CURLOPT_PINNEDPUBLICKEY was added in 7.39.0, released in November
- * 2014.
+ * 2014. CURLE_SSL_PINNEDPUBKEYNOTMATCH was added in that same version.
  */
 #if LIBCURL_VERSION_NUM >= 0x072c00
 #define GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY 1
+#define GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH 1
 #endif
 
 /**
  * CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015.
  *
  * The CURL_HTTP_VERSION_2 alias (but not CURL_HTTP_VERSION_2_0) has
diff --git a/http.c b/http.c
index d7c20493d7f..b6735b51c31 100644
--- a/http.c
+++ b/http.c
@@ -1486,12 +1486,16 @@ static int handle_curl_result(struct slot_results *results)
 		 * certificate, bad password, or something else wrong
 		 * with the certificate.  So we reject the credential to
 		 * avoid caching or saving a bad password.
 		 */
 		credential_reject(&cert_auth);
 		return HTTP_NOAUTH;
+#ifdef GIT_CURL_HAVE_CURLE_SSL_PINNEDPUBKEYNOTMATCH
+	} else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) {
+		return HTTP_NOMATCHPUBLICKEY;
+#endif
 	} else if (missing_target(results))
 		return HTTP_MISSING_TARGET;
 	else if (results->http_code == 401) {
 		if (http_auth.username && http_auth.password) {
 			credential_reject(&http_auth);
 			return HTTP_NOAUTH;
diff --git a/http.h b/http.h
index 3db5a0cf320..df1590e53a4 100644
--- a/http.h
+++ b/http.h
@@ -151,12 +151,13 @@ struct http_get_options {
 #define HTTP_OK			0
 #define HTTP_MISSING_TARGET	1
 #define HTTP_ERROR		2
 #define HTTP_START_FAILED	3
 #define HTTP_REAUTH	4
 #define HTTP_NOAUTH	5
+#define HTTP_NOMATCHPUBLICKEY	6
 
 /*
  * Requests a URL and stores the result in a strbuf.
  *
  * If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
  */
diff --git a/remote-curl.c b/remote-curl.c
index 598cff7cde6..8700dbdc0ac 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -496,12 +496,16 @@ static struct discovery *discover_refs(const char *service, int for_push)
 		die(_("repository '%s' not found"),
 		    transport_anonymize_url(url.buf));
 	case HTTP_NOAUTH:
 		show_http_message(&type, &charset, &buffer);
 		die(_("Authentication failed for '%s'"),
 		    transport_anonymize_url(url.buf));
+	case HTTP_NOMATCHPUBLICKEY:
+		show_http_message(&type, &charset, &buffer);
+		die(_("unable to access '%s' with http.pinnedPubkey configuration: %s"),
+		    transport_anonymize_url(url.buf), curl_errorstr);
 	default:
 		show_http_message(&type, &charset, &buffer);
 		die(_("unable to access '%s': %s"),
 		    transport_anonymize_url(url.buf), curl_errorstr);
 	}
 
-- 
2.33.0.1231.g24d802460a8


^ permalink raw reply related	[relevance 5%]

* Re: [PATCH v6 03/22] cat-file tests: test for missing object with -t and -s
  @ 2021-09-16 22:52  6%       ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-09-16 22:52 UTC (permalink / raw)
  To: Taylor Blau; +Cc: git, Junio C Hamano, Jeff King, Jonathan Tan, Andrei Rybak


On Thu, Sep 16 2021, Taylor Blau wrote:

> On Tue, Sep 07, 2021 at 12:57:58PM +0200, Ævar Arnfjörð Bjarmason wrote:
>> Test for what happens when the -t and -s flags are asked to operate on
>> a missing object, this extends tests added in 3e370f9faf0 (t1006: add
>> tests for git cat-file --allow-unknown-type, 2015-05-03). The -t and
>> -s flags are the only ones that can be combined with
>> --allow-unknown-type, so let's test with and without that flag.
>
> I'm a little skeptical to have tests for all four pairs of `-t` or `-s`
> and "with `--allow-unknown-type` and without `--allow-unknown-type`".
>
> Testing both the presence and absence of `--allow-unknown-type` seems
> useful to me, but I'm not sure what testing `-t` and `-s` separately
> buys us.
>
> (If you really feel the need test both, I'd encourage looping like:

Thanks, I'll try to simplify it.

>     for arg in -t -s
>     do
>       test_must_fail git cat-file $arg $missing_oid >out 2>err &&
>       test_must_be_empty out &&
>       test_cmp expect.err err &&
>
>       test_must_fail git cat-file $arg --allow-unknown-type $missing_oid >out 2>err &&
>       test_must_be_empty out &&
>       test_cmp expect.err err
>     done &&
>
> but I would be equally or perhaps even happier to just have one of the
> two tests).

A loop like that can be further simplified as just (just inlining
arg=-s):

	test_must_fail git cat-file -s $missing_oid >out 2>err &&
	test_must_be_empty out &&
	test_cmp expect.err err &&

	test_must_fail git cat-file -s --allow-unknown-type $missing_oid >out 2>err &&
	test_must_be_empty out &&
	test_cmp expect.err err

:)

I.e. unless you end &&-chains in loops in the test framework with an ||
return 1 you're only testing your last iteration. Aside from whatever
I'm doing here I generally prefer to either just spell it out twice (if
small enough), or:

    for arg in -t -s
    do
        test_expect_success '...' "[... use $arg ...]"
    done

Which both nicely get around the issue of that easy-to-make mistake.

We've got some in-tree tests that are broken this way, well, at least
4cf67869b2a (list-objects.c: don't segfault for missing cmdline objects,
2018-12-05). But I think I'll leave that for a #leftoverbits submission
given my outstanding patch queue..., oh there's another one in
t1010-mktree.sh ... :)

^ permalink raw reply	[relevance 6%]

* Oddidies in the .mailmap parser & future syntax extensions
  @ 2021-09-10 16:48  4%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-09-10 16:48 UTC (permalink / raw)
  To: Gwyneth Morgan
  Cc: Fangyi Zhou, git, Birger Skogeng Pedersen,
	Birger Skogeng Pedersen, Brandon Williams, Brandon Williams,
	CB Bailey, Christopher Díaz Riveros,
	Christopher Díaz Riveros, Ed Maste, Jean-Noël Avila,
	Jean-Noel Avila, Jessica Clarke, Jiang Xin, Jiang Xin,
	Kazuhiro Kato, Kazuhiro Kato, Kevin Willford, Kevin Willford,
	Peter Kaestle, Peter Kaestle, Sibi Siddharthan, Sibi Siddharthan,
	Slavica Đukić,
	Slavica Djukic


[Changed subject]

On Fri, Sep 10 2021, Gwyneth Morgan wrote:

> On 2021-09-10 14:02:36+0100, Fangyi Zhou wrote:
>> Similar to a35b13fce0 (Update .mailmap, 2018-11-09).
>> 
>> This patch makes the output of `git shortlog -nse v2.10.0..master`
>> duplicate-free by taking/guessing the current and preferred
>> addresses for authors that appear with more than one address.
>
> The line for Jessica Clarke should probably just be
>
> Jessica Clarke <jrtc27@jrtc27.com>
>
> That works the same and doesn't put a reference to an old name.

It does work exactly the same!

More specifically this is an unintentional bug/misfeature/looseness in
the .mailmap parser, an entry like:

    Foo <foo@example.com> Bar

Is exactly equivalent to:

    Foo <foo@example.com>

I.e. we simply ignore the " Bar" part. The reason for this is that we're
internally treating nonsense input as if the line simply ended there.

Even having documented and tested some of this recently in 05b5ff219c2
(mailmap doc + tests: add better examples & test them, 2021-01-12) I
found this a bit surprising. I probably found out at the time, but
forgot and had to go source spelunking again.

I'd expect:

    Foo <foo@example.com> Bar

To be an alias/shorthand for:

    Foo <foo@example.com> Bar <foo@example.com>

Which is something that might be applicable / useful in some
cases.

E.g. a name might change over time from "Foo", to "Bar", to "Zar", but
just because we're at "Bar" and want to map "Foo" to "Bar", that might
not mean that we'd like to map any future name at the same address
(i.e. the future "Zar") to the same "Foo".

In practice I suspect that's more commonly what people do want to do,
maybe we should warn about it, I did mean to hook some pedantic mode of
the parser at some point up to git-fsck.

More annoying is that this:

    New <foo@example.com> <bar@example.com>
    <foo@example.com> <zar@example.com>

Doesn't mean the same as:

    New <foo@example.com> <bar@example.com>
    New <foo@example.com> <zar@example.com>

I.e. I'd expect the name to map to the empty string, *unless* we saw an
earlier address, i.e. just as we do for the first bar -> foo line (we
map it to a name of "New", we don't map it to an empty name).

So that's some #leftoverbits, perhaps someone somewhere relies on that,
but it seems like an obvious shorthand to have. I can't imagine it being
useful to map to empty names, and much of e.g. git.git's mailmap is
repeated entries with the same name over and over again.

I suppose we could also extend it to new syntax such as:

    New <foo@example.com> <bar@example.com> <zar@example.com>

Doing that would be strictly backwards compatible, i.e. now we'll
entirely ignore the 3rd E-Mail address. It does mean we also
accidentally support things like:

    New <foo@example.com> <bar@example.com> # A comment, because we ignore everything after the 2nd address

But don't tell anyone I told you that :) But that is something that
might technically have inadvertently closed the door to future syntax
extensions, but we could probably do them anyway, or at worst have some
heuristic.

Another useful thing might be to support:

    New <> Old <>

As an explicit mapping of the name "Old" wherever we see it to "New", or:

    New <> Old <>

To change just the name "Old" to "New" everywhere, without considering
the E-Mail address. Both of those are probably too crazy to be useful,
especially since if we supported that we'd logically also support:

    New <> <>

To assign all the commits to the name "New", but retain the address.

^ permalink raw reply	[relevance 4%]

* Re: [PATCH v2 4/4] pack-write: rename *.idx file into place last (really!)
  @ 2021-09-08  1:14  6%     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 200+ results
From: Ævar Arnfjörð Bjarmason @ 2021-09-08  1:14 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Taylor Blau,
	Ævar Arnfjörð Bjarmason


On Wed, Sep 08 2021, Ævar Arnfjörð Bjarmason wrote:

> Follow-up a preceding commit (pack-write.c: rename `.idx` file into
> place last, 2021-08-16)[1] and rename the *.idx file in-place after we
> write the *.bitmap. The preceding commit fixed the issue of *.idx
> being written before *.rev files, but did not do so for *.idx files.
>
> See 7cc8f971085 (pack-objects: implement bitmap writing, 2013-12-21)
> for commentary at the time when *.bitmap was implemented about how
> those files are written out, nothing in that commit contradicts what's
> being done here.
>
> Note that the referenced earlier commit[1] is overly optimistic about
> "clos[ing the] race", i.e. yes we'll now write the files in the right
> order, but we might still race due to our sloppy use of fsync(). See
> the thread at [2] for a rabbit hole of various discussions about
> filesystem races in the face of doing and not doing fsync() (and if
> doing fsync(), not doing it properly).

Actually I think it's a bit worse than that, we will unconditionally
fsync() the *.pack we write out, but in stage_tmp_packfiles() (the
behavior pre-dates both this series and its parent, I just think my
stage_tmp_packfiles() is easier to follow) we'll not write the *.idx
file with fsync() since we won't pass WRITE_IDX_VERIFY.

The same goes for *.rev (which oddly makes its fsync() conditional on
WRITE_IDX_VERIFY), but not *.bitmap, which fsyncs unconditionally just
like *.pack does.

And then of course we'll do all these in-place renames but nothing
fsyncs the fd of the directory, so the metadata and new names being
committed to disk & visible to other processes is anyone's guess.

But not only is that metadata commit not made, but due to the
inconsistent fsync() we might end up with an *.idx that's partial and
renamed in-place.

In any case, any such issues pre-date this series and the series by
Taylor it depends on, just adding some #leftoverbits for future fsync()
fixes since I spent time looking into it.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 04/24] Documentation: build 'technical/bitmap-format' by default
  @ 2021-07-26 18:49  6%             ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2021-07-26 18:49 UTC (permalink / raw)
  To: Jeff King; +Cc: git, dstolee, gitster, jonathantanmy

On Fri, Jul 23, 2021 at 03:39:25AM -0400, Jeff King wrote:
> The question here is: should we continue to omit it from the html build,
> since it does not render well (i.e., should we simply drop this patch).

I think that's a nice way of putting it. Since the HTML rendering is
terrible, let's just drop this patch and leave cleaning it up as
#leftoverbits.

Thanks,
Taylor

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2 14/24] pack-bitmap: write multi-pack bitmaps
  @ 2021-07-26 18:12  4%       ` Taylor Blau
  0 siblings, 0 replies; 200+ results
From: Taylor Blau @ 2021-07-26 18:12 UTC (permalink / raw)
  To: Jeff King; +Cc: git, dstolee, gitster, jonathantanmy

On Wed, Jul 21, 2021 at 08:09:19AM -0400, Jeff King wrote:
> On Mon, Jun 21, 2021 at 06:25:34PM -0400, Taylor Blau wrote:
>
> > +static int add_ref_to_pending(const char *refname,
> > +			      const struct object_id *oid,
> > +			      int flag, void *cb_data)
> > +{
> > +	struct rev_info *revs = (struct rev_info*)cb_data;
> > +	struct object *object;
> > +
> > +	if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) {
> > +		warning("symbolic ref is dangling: %s", refname);
> > +		return 0;
> > +	}
> > +
> > +	object = parse_object_or_die(oid, refname);
> > +	if (object->type != OBJ_COMMIT)
> > +		return 0;
> > +
> > +	add_pending_object(revs, object, "");
> > +	if (bitmap_is_preferred_refname(revs->repo, refname))
> > +		object->flags |= NEEDS_BITMAP;
> > +	return 0;
> > +}
>
> OK, so we'll look at each ref to get the set of commits that we want to
> traverse to put into the bitmap. Which is roughly the same as what the
> pack bitmap does. We only generate bitmaps for all-into-one repacks, so
> it is traversing all of the reachable objects. It is a little different
> in that the pack version is probably hitting reflogs, but IMHO we are
> better off to ignore reflogs for the purposes of bitmaps (I would
> suggest to do so in the pack-bitmap case, too, except that it is
> combined with the "what to pack" traversal there, and by the time we see
> each commit we don't know how we got there).

Right. And we might end up ignoring a lot of these commits, too: the
for-each-ref is just a starting point to enumerate everything, but we
only care about parts of the object graph that are contained in a pack
which is included in the MIDX we are writing (hence the bare "return"
you're commenting around below).

> > +static void bitmap_show_commit(struct commit *commit, void *_data)
> > +{
> > +	struct bitmap_commit_cb *data = _data;
> > +	if (oid_pos(&commit->object.oid, data->ctx->entries,
> > +		    data->ctx->entries_nr,
> > +		    bitmap_oid_access) > -1) {
>
> This "> -1" struck me as a little bit funny. Perhaps ">= 0" would be a
> more obvious way of saying "we found it"?

Sure. (I looked for other uses of oid_pos() to see what is more
common, but there really are vanishingly few uses.) Easier to read might
even be:

    int pos = oid_pos(...);
    if (pos < 0)
      return;
    ALLOC_GROW(...);

which is what I ended up going for.

> > +	/*
> > +	 * Pass selected commits in topo order to match the behavior of
> > +	 * pack-bitmaps when configured with delta islands.
> > +	 */
> > +	revs.topo_order = 1;
> > +	revs.sort_order = REV_SORT_IN_GRAPH_ORDER;
>
> Hmm. Why do we want to match this side effect of delta islands here?
>
> The only impact this has is on the order of commits we feed for bitmap
> selection (and during the actual generation phase, it may impact
> visitation order).
>
> Now I'm of the opinion that topo order is probably the best thing for
> bitmap generation (since the bitmaps themselves are connected to the
> graph structure). But if it is the best thing, shouldn't we perhaps be
> turning on topo-order for single-pack bitmaps, too?
>
> And if it isn't the best thing, then why would we want it here?

Heh, you were the one that suggested I bring this over to MIDX-based
bitmaps in the first place ;).

This comes from an investigation into why bitmap coverage had worsened
for some repositories using MIDX bitmaps at GitHub. The real reason was
resolved and unrelated to this, but trying to match the behavior of MIDX
bitmaps to our existing pack bitmap setup (which uses delta-islands) was
one strategy we tried while debugging.

I actually suspect that it doesn't really matter what order we feed this
list to bitmap_writer_select_commits() in, because the first thing that
it does is QSORT() the incoming list of commits in date order.

But it does mirror the behavior of our previous bitmap generation
settings, which has been running for years.

So... we could probably drop this hunk? I'd probably rather err on the
safe side and leave this alone since it matches a system that we know to
work well in practice.

> > +	if (prepare_revision_walk(&revs))
> > +		die(_("revision walk setup failed"));
>
> We call init_revisions(), and then go straight to
> prepare_revision_walk() with no call to setup_revisions() between. It
> doesn't seem to be clearly documented, but I think you're supposed to,
> as it finalizes some bits like diff_setup_done().
>
> I suspect it works OK in practice, and I did find a few other spots that
> do not call it (e.g., builtin/am.c:write_commit_patch). But most spots
> do at least an empty setup_revisions(0, NULL, &rev, NULL).

Sure, thanks.

> > +	/*
> > +	 * Build the MIDX-order index based on pdata.objects (which is already
> > +	 * in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of
> > +	 * this order).
> > +	 */
> > +	ALLOC_ARRAY(index, pdata.nr_objects);
> > +	for (i = 0; i < pdata.nr_objects; i++)
> > +		index[i] = (struct pack_idx_entry *)&pdata.objects[i];
>
> This cast is correct because the pack_idx_entry is at the start of each
> object_entry. But maybe:
>
>   index[i] = &pdata.objects[i].idx;
>
> would be less scary looking?

Definitely, and thanks (for this spot and the other one you mentioned).

> > +	bitmap_writer_select_commits(commits, commits_nr, -1);
>
> Not related to your patch, but I had to refresh my memory on what this
> "-1" was for. It's "max_bitmaps", and is ignored if it's negative. But
> the only callers pass "-1"! So we could get rid of it entirely.
>
> It probably makes sense to leave that cleanup out of this
> already-complicated series. But maybe worth doing later on top.

Yeah, seems like an easy topic for somebody interested in any
#leftoverbits could pick up. Once this lands, I'll be happy to take care
of it myself, too.

> > @@ -930,9 +1100,16 @@ static int write_midx_internal(const char *object_dir, struct multi_pack_index *
> >  		for (i = 0; i < ctx.m->num_packs; i++) {
> >  			ALLOC_GROW(ctx.info, ctx.nr + 1, ctx.alloc);
> >
> > +			if (prepare_midx_pack(the_repository, ctx.m, i)) {
> > +				error(_("could not load pack %s"),
> > +				      ctx.m->pack_names[i]);
> > +				result = 1;
> > +				goto cleanup;
> > +			}
>
> It might be worth a comment here. I can easily believe that there is
> some later part of the bitmap generation code that assumes the packs are
> loaded. But somebody reading this is not likely to understand why it's
> here.
>
> Should this be done conditionally only if we're writing a bitmap? (That
> might also make it obvious why we are doing it).

Ah. Actually, I don't think this was necessary before, but we *do* need
it now because we want to compare the pack mtime's for inferring a
preferred pack when one wasn't given. And we also need to open the pack
indexes, too, because we care about the object counts (to make sure that
we don't infer a preferred pack which has no objects).

Luckily, any new packs will be loaded (and likewise have their indexes
open, too), via the the add_pack_to_midx() callback that we pass as an
argument to for_each_file_in_pack_dir().

But we could do something like this instead:

--- 8< ---

diff --git a/midx.c b/midx.c
index 8426e1a0b1..a70a6bca81 100644
--- a/midx.c
+++ b/midx.c
@@ -1111,16 +1111,29 @@ static int write_midx_internal(const char *object_dir, struct multi_pack_index *
 		for (i = 0; i < ctx.m->num_packs; i++) {
 			ALLOC_GROW(ctx.info, ctx.nr + 1, ctx.alloc);

-			if (prepare_midx_pack(the_repository, ctx.m, i)) {
-				error(_("could not load pack"));
-				result = 1;
-				goto cleanup;
-			}
-
 			ctx.info[ctx.nr].orig_pack_int_id = i;
 			ctx.info[ctx.nr].pack_name = xstrdup(ctx.m->pack_names[i]);
-			ctx.info[ctx.nr].p = ctx.m->packs[i];
+			ctx.info[ctx.nr].p = NULL;
 			ctx.info[ctx.nr].expired = 0;
+
+			if (flags & MIDX_WRITE_REV_INDEX) {
+				/*
+				 * If generating a reverse index, need to have
+				 * packed_git's loaded to compare their
+				 * mtimes and object count.
+				 */
+				if (prepare_midx_pack(the_repository, ctx.m, i)) {
+					error(_("could not load pack"));
+					result = 1;
+					goto cleanup;
+				}
+
+				if (open_pack_index(ctx.m->packs[i]))
+					die(_("could not open index for %s"),
+					    ctx.m->packs[i]->pack_name);
+				ctx.info[ctx.nr].p = ctx.m->packs[i];
+			}
+
 			ctx.nr++;
 		}
 	}

--- >8 ---

> > @@ -1075,9 +1271,6 @@ static int write_midx_internal(const char *object_dir, struct multi_pack_index *
> >  	hold_lock_file_for_update(&lk, midx_name, LOCK_DIE_ON_ERROR);
> >  	f = hashfd(get_lock_file_fd(&lk), get_lock_file_path(&lk));
> >
> > -	if (ctx.m)
> > -		close_midx(ctx.m);
> > -
> >  	if (ctx.nr - dropped_packs == 0) {
> >  		error(_("no pack files to index."));
> >  		result = 1;
>
> I'm not sure what this hunk is doing. We do pick up the close_midx()
> call at the end of the function, amidst the other cleanup.
>
> I expect the answer is something like "we need it open when we generate
> the bitmaps". But it makes me wonder if we could hit any cases where we
> try to overwrite it while it's still open, which would cause problems on
> Windows.

The reason is kind of annoying. If we're building a MIDX bitmap
in-process (e.g., `git multi-pack-index write --bitmap`) then we'll call
prepare_packed_git() to build our pseudo-packing list which we pass to
the bitmap generation machinery.

But prepare_packed_git() calls prepare_packed_git_one() ->
for_each_file_in_pack_dir() with the prepare_pack() callback -> which
the wants to see if the MIDX we have open already knows about a given
pack so we avoid opening it twice.

But even though the MIDX would have gone away by this point (with the
previous close_midx() call that is removed above), we still hold onto
a pointer to it via the object_store's `multi_pack_index` pointer. And
then all the way down in packfile.c:prepare_pack() we try to pass a
now-defunct pointer as the first argument to midx_contains_pack(), and
crash.

And clearing out that `multi_pack_index` pointer is tricky, because the
MIDX would have to compare the odb's `object_dir` with its own (which is
brittle in its own right), but also would have to see if that object
store is pointing at *it*, and not some other MIDX.

So we do have to keep it open there. Which makes me wonder how this
could possibly work on Windows, because holding the MIDX open will make
the commit_lock_file() definitely fail. But it seems OK in the
Windows-based CI runs?

Puzzled.

Thanks,
Taylor

^ permalink raw reply related	[relevance 4%]

* Re: [PATCH 00/12] Fix all leaks in tests t0002-t0099: Part 2
  @ 2021-07-26  8:01  0%   ` Christian Couder
  0 siblings, 0 replies; 200+ results
From: Christian Couder @ 2021-07-26  8:01 UTC (permalink / raw)
  To: Elijah Newren; +Cc: Andrzej Hunt, Git Mailing List

On Mon, Jun 21, 2021 at 11:54 PM Elijah Newren <newren@gmail.com> wrote:
>
> On Sun, Jun 20, 2021 at 8:14 AM <andrzej@ahunt.org> wrote:
> >
> > From: Andrzej Hunt <andrzej@ahunt.org>
> >
> > This series plugs more of the leaks that were found while running
> > t0002-t0099 with LSAN.
> >
> > See also the first series (already merged) at [1]. I'm currently
> > expecting at least another 2 series before t0002-t0099 run leak free.
> > I'm not being particularly systematic about the order of patches -
> > although I am trying to send out "real" (if mostly small) leaks first,
> > before sending out the more boring patches that add free()/UNLEAK() to
> > cmd_* and direct helpers thereof.
>
> I've read over the series.  It provides some good clear fixes.  I
> noted on patches 2, 6, and 12 that a some greps suggested that leaks
> similar to the ones being fixed likely also affect other places of the
> codebase.  Those other places don't need to be fixed as part of this
> series, but they might be good items for #leftoverbits or GSoC early
> tasks (cc: Christian in case he wants to record those somewhere).

Yeah, thanks for letting me know!

^ permalink raw reply	[relevance 0%]

Results 1-200 of ~520   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2021-04-09 18:10     [PATCH 00/22] multi-pack reachability bitmaps Taylor Blau
2021-06-21 22:24     ` [PATCH v2 00/24] " Taylor Blau
2021-06-21 22:25       ` [PATCH v2 04/24] Documentation: build 'technical/bitmap-format' by default Taylor Blau
2021-07-21  9:58         ` Jeff King
2021-07-21 10:08           ` Jeff King
2021-07-21 17:23             ` Taylor Blau
2021-07-23  7:39               ` Jeff King
2021-07-26 18:49  6%             ` Taylor Blau
2021-06-21 22:25       ` [PATCH v2 14/24] pack-bitmap: write multi-pack bitmaps Taylor Blau
2021-07-21 12:09         ` Jeff King
2021-07-26 18:12  4%       ` Taylor Blau
2021-06-20 15:11     [PATCH 00/12] Fix all leaks in tests t0002-t0099: Part 2 andrzej
2021-06-21 21:54     ` Elijah Newren
2021-07-26  8:01  0%   ` Christian Couder
2021-06-24 18:29     [PATCH 0/3] Empty untracked cache performance issue Tao Klerks via GitGitGadget
2022-02-25 17:10     ` [PATCH v2 " Tao Klerks via GitGitGadget
2022-02-25 17:10       ` [PATCH v2 1/3] t7519: avoid file to index mtime race for untracked cache Tao Klerks via GitGitGadget
2022-02-25 19:07  6%     ` Junio C Hamano
2022-02-27 22:12  0%       ` Tao Klerks
2022-02-27 21:56  5%   ` [PATCH v3 0/3] Empty untracked cache performance issue Tao Klerks via GitGitGadget
2022-02-27 21:56  6%     ` [PATCH v3 1/3] t7519: avoid file to index mtime race for untracked cache Tao Klerks via GitGitGadget
2021-07-10 13:37     [PATCH v5 00/21] fsck: lib-ify object-file.c & better fsck "invalid object" error reporting Ævar Arnfjörð Bjarmason
2021-09-07 10:57     ` [PATCH v6 00/22] " Ævar Arnfjörð Bjarmason
2021-09-07 10:57       ` [PATCH v6 03/22] cat-file tests: test for missing object with -t and -s Ævar Arnfjörð Bjarmason
2021-09-16 19:57         ` Taylor Blau
2021-09-16 22:52  6%       ` Ævar Arnfjörð Bjarmason
2021-09-01  2:05     [PATCH 0/2] pack-write,repack: prevent opening packs too early Taylor Blau
2021-09-08  0:38     ` [PATCH v2 0/4] rename *.idx file into place last (also after *.bitmap) Ævar Arnfjörð Bjarmason
2021-09-08  0:38       ` [PATCH v2 4/4] pack-write: rename *.idx file into place last (really!) Ævar Arnfjörð Bjarmason
2021-09-08  1:14  6%     ` Ævar Arnfjörð Bjarmason
2021-09-10 13:02     [PATCH] .mailmap: Update mailmap Fangyi Zhou
2021-09-10 15:22     ` Gwyneth Morgan
2021-09-10 16:48  4%   ` Oddidies in the .mailmap parser & future syntax extensions Ævar Arnfjörð Bjarmason
2021-09-24 10:08  5% [PATCH] http: check CURLE_SSL_PINNEDPUBKEYNOTMATCH when emitting errors Ævar Arnfjörð Bjarmason
2021-10-10 21:42  0% ` SZEDER Gábor
2021-10-04  1:42     [PATCH 0/2] i18n: improve translatability of ambiguous object output Ævar Arnfjörð Bjarmason
2021-10-04 14:27  3% ` [PATCH v2 " Ævar Arnfjörð Bjarmason
2021-10-04 14:27  5%   ` [PATCH v2 1/2] object.[ch]: mark object type names for translation Ævar Arnfjörð Bjarmason
2021-10-04 18:54  0%     ` Eric Sunshine
2021-10-06 19:05  0%     ` Jeff King
2021-10-14  0:06     [PATCH 00/20] refs: stop having the API set "errno" Ævar Arnfjörð Bjarmason
2021-10-14  0:06  4% ` [PATCH 06/20] refs/files: remove "name exist?" check in lock_ref_oid_basic() Ævar Arnfjörð Bjarmason
2021-10-16  9:39     ` [PATCH v2 00/21] refs: stop having the API set "errno" Ævar Arnfjörð Bjarmason
2021-10-16  9:39  4%   ` [PATCH v2 07/21] refs/files: remove "name exist?" check in lock_ref_oid_basic() Ævar Arnfjörð Bjarmason
2021-10-14  0:47  6% [PATCH 0/2] test-lib.sh: add BAIL_OUT function, use it for SANITIZE=leak Ævar Arnfjörð Bjarmason
2021-11-16 19:31     [PATCH] t0006: date_mode can leak .strftime_fmt member Jeff King
2022-02-02 21:03     ` [PATCH 0/5] date.[ch] API: split from cache.h, add API docs, stop leaking memory Ævar Arnfjörð Bjarmason
2022-02-02 21:03  6%   ` [PATCH 4/5] date API: add basic API docs Ævar Arnfjörð Bjarmason
2022-02-04 23:53       ` [PATCH v2 0/5] date.[ch] API: split from cache.h, add API docs, stop leaking memory Ævar Arnfjörð Bjarmason
2022-02-04 23:53  6%     ` [PATCH v2 4/5] date API: add basic API docs Ævar Arnfjörð Bjarmason
2022-02-16  8:14         ` [PATCH v3 0/5] date.[ch] API: split from cache.h, add API docs, stop leaking memory Ævar Arnfjörð Bjarmason
2022-02-16  8:14  5%       ` [PATCH v3 4/5] date API: add basic API docs Ævar Arnfjörð Bjarmason
2021-11-29 22:25     [PATCH 00/17] cruft packs Taylor Blau
2021-11-29 22:25     ` [PATCH 08/17] builtin/pack-objects.c: --cruft without expiration Taylor Blau
2021-12-07 15:17       ` Derrick Stolee
2022-02-23 23:34  5%     ` Taylor Blau
2021-12-06 12:16     Regression in 8d92fb292706 ("dir: replace exponential algorithm with a linear one") Uwe Kleine-König
2021-12-07  5:29  5% ` Elijah Newren
2021-12-07  7:14  0%   ` Uwe Kleine-König
2021-12-30  0:32     [PATCH 0/2] sparse checkout: custom bash completion updates Lessley Dennington via GitGitGadget
2021-12-30 19:26     ` [PATCH v2 " Lessley Dennington via GitGitGadget
2021-12-30 19:26       ` [PATCH v2 1/2] sparse-checkout: custom tab completion tests Lessley Dennington via GitGitGadget
2021-12-31 20:03         ` Elijah Newren
2021-12-31 22:20           ` Junio C Hamano
2022-01-04 19:25             ` Lessley Dennington
2022-01-04 20:25  6%           ` Elijah Newren
2022-01-05 14:05  0%             ` Lessley Dennington
2022-01-24  1:26     [PATCH] receive-pack: purge temporary data if no command is ready to run BoJun via GitGitGadget
2022-01-29  6:35     ` [PATCH v2] " Chen BoJun
2022-02-04  1:17  6%   ` Junio C Hamano
2022-02-05  7:19  0%     ` Bojun Chen
2022-02-05  8:02  0%       ` Junio C Hamano
2022-01-24 18:09     [PATCH] clone: support unusual remote ref configurations Jonathan Tan
2022-01-26 19:11  8% ` Junio C Hamano
2022-01-27 15:37     [PATCH] fetch --prune: exit with error if pruning fails Thomas Gummerer
2022-01-27 19:57  7% ` Junio C Hamano
2022-01-28 11:04  0%   ` Thomas Gummerer
2022-02-03 19:08     [PATCH 0/2] Add cat-file --batch-command flag John Cai via GitGitGadget
2022-02-07 16:33     ` [PATCH v2 " John Cai via GitGitGadget
2022-02-07 16:33       ` [PATCH v2 2/2] cat-file: add --batch-command mode John Cai via GitGitGadget
2022-02-08  0:49  4%     ` Junio C Hamano
2022-02-12 20:34     [PATCH v4 00/12] In-core git merge-tree ("Server side merges") Elijah Newren via GitGitGadget
2022-02-20  6:54     ` [PATCH v5 " Elijah Newren via GitGitGadget
2022-02-20  6:54       ` [PATCH v5 04/12] merge-tree: implement real merges Elijah Newren via GitGitGadget
2022-02-20  9:03         ` René Scharfe
2022-02-22  2:28  6%       ` Elijah Newren
2022-02-22 16:25  0%         ` Johannes Schindelin
2022-02-17 20:50     When rebase.autoStash=true is used, 'git pull' merge process still complains when incoming changes are in a different place of the file than local changes Yuri
2022-02-22 16:37     ` Phillip Wood
2022-02-23 21:23  6%   ` Junio C Hamano
2022-02-18 18:48     [PATCH v2 2/2] Add new tests functions like test_path_is_* Junio C Hamano
2022-02-22 21:54     ` [PATCH v3 0/3] replace test [-f|-d] with more verbose functions COGONI Guillaume
2022-02-23 22:59  6%   ` Junio C Hamano
2022-02-20  5:05     [PATCH] Provide config option to expect files outside sparse patterns Elijah Newren via GitGitGadget
2022-02-21 20:34     ` Johannes Schindelin
2022-02-22  2:23       ` Elijah Newren
2022-02-22 12:11  6%     ` Johannes Schindelin
2022-02-23 17:55     [PATCH 00/11] Partial bundles Derrick Stolee via GitGitGadget
2022-02-23 17:55     ` [PATCH 02/11] revision: put object filter into struct rev_info Derrick Stolee via GitGitGadget
2022-03-04 22:15  5%   ` Junio C Hamano
2022-03-07 13:59  0%     ` Derrick Stolee
2022-02-28  9:48     Please add support for "git merge --continue -S" Rolf Eike Beer
2022-02-28 10:58     ` Ævar Arnfjörð Bjarmason
2022-02-28 22:53  5%   ` Junio C Hamano
2022-03-04  0:57     [PATCH v4 00/10] fetch --recurse-submodules: fetch unpopulated submodules Glen Choo
2022-03-08  0:14     ` [PATCH v5 " Glen Choo
2022-03-08  0:50       ` Junio C Hamano
2022-03-08 18:24         ` Glen Choo
2022-03-09 19:13  6%       ` Junio C Hamano
2022-03-09 19:49  0%         ` Glen Choo
2022-03-09 13:16     [PATCH 00/24] revision.[ch]: add and use release_revisions() Ævar Arnfjörð Bjarmason
2022-03-09 13:16     ` [PATCH 03/24] format-patch: don't leak "extra_headers" or "ref_message_ids" Ævar Arnfjörð Bjarmason
2022-03-09 20:34  6%   ` Taylor Blau
2022-03-11 13:21     [RFC PATCH 0/1] Documentation/git-sparse-checkout.txt: add an OPTIONS section Shaoxuan Yuan
2022-03-11 13:21     ` [RFC PATCH 1/1] " Shaoxuan Yuan
2022-03-11 20:56  6%   ` Derrick Stolee
2022-03-21 20:34     [PATCH 0/4] reset: make --no-refresh the only way to skip index refresh Victoria Dye via GitGitGadget
2022-03-23 18:17     ` [PATCH v2 0/3] " Victoria Dye via GitGitGadget
2022-03-24 11:11       ` Phillip Wood
2022-03-24 17:13  6%     ` Junio C Hamano
2022-03-24 17:33  0%       ` Junio C Hamano
2022-03-24 18:01  0%         ` Victoria Dye
2022-03-24 20:36  0%           ` Junio C Hamano
2022-03-25 15:04  0%         ` Derrick Stolee
2022-03-25 16:35  0%           ` Junio C Hamano
2022-03-21 22:54     [PATCH 00/41] use the stdlib EXIT_SUCCESS or EXIT_FAILURE exit status Elia Pinto
2022-03-22  8:26     ` Ævar Arnfjörð Bjarmason
2022-03-23 11:13  6%   ` Junio C Hamano
2022-03-31 17:54  1% [PATCH] t5510-fetch: upgrade to a more modern style Elia Pinto
2022-04-01 20:11  0% ` Junio C Hamano
2022-04-02  7:32  0%   ` Elia Pinto
2022-06-09 23:44     [PATCH] revision: mark blobs needed for resolve-undo as reachable Junio C Hamano
2022-06-13 15:15     ` Derrick Stolee
2022-06-14  0:24       ` Ævar Arnfjörð Bjarmason
2022-06-14 14:35         ` Derrick Stolee
2022-06-15  2:02           ` Taylor Blau
2022-06-15  3:48             ` Jeff King
2022-06-15 20:47  6%           ` Taylor Blau
2022-06-21  5:36     [PATCH v2] grep: add --max-count command line option Carlos L. via GitGitGadget
2022-06-22 17:07     ` [PATCH v3 0/2] " Carlos L. via GitGitGadget
2022-06-22 17:07       ` [PATCH v3 2/2] tests: add tests for grep --max-count Carlos López via GitGitGadget
2022-06-22 18:10  6%     ` Junio C Hamano
2022-06-27 18:36     [PATCH v5 0/5] config: introduce discovery.bare and protected config Glen Choo via GitGitGadget
2022-06-30 18:13     ` [PATCH v6 " Glen Choo via GitGitGadget
2022-06-30 18:13       ` [PATCH v6 1/5] Documentation/git-config.txt: add SCOPES section Glen Choo via GitGitGadget
2022-06-30 22:32  5%     ` Taylor Blau
2022-07-06 17:44  0%       ` Glen Choo
2022-06-28 13:25     [PATCH v3 0/8] rebase: update branches in multi-part topic Derrick Stolee via GitGitGadget
2022-07-12 13:06     ` [PATCH v4 00/12] " Derrick Stolee via GitGitGadget
2022-07-12 13:07       ` [PATCH v4 12/12] sequencer: notify user of --update-refs activity Derrick Stolee via GitGitGadget
2022-07-16 22:09         ` Elijah Newren
2022-07-19 16:09  6%       ` Derrick Stolee
2022-07-19 18:33  2%   ` [PATCH v5 00/12] rebase: update branches in multi-part topic Derrick Stolee via GitGitGadget
2022-07-21  4:35  0%     ` Elijah Newren
2022-07-21 12:12  0%       ` Derrick Stolee
2022-07-21 14:04  0%     ` Phillip Wood
2022-06-28 18:04     [PATCH v5 3/5] pack-bitmap.c: using error() instead of silently returning -1 Junio C Hamano
2022-07-05  9:04     ` Teng Long
2022-07-05 18:23  6%   ` Junio C Hamano
2022-06-28 18:30     [PATCH] pack-objects.h: remove outdated pahole results Taylor Blau
2022-07-01 18:16  6% ` Jeff King
2022-07-01 19:48  0%   ` Taylor Blau
2022-07-13  4:19     [PATCH 0/3] checkout: fix two bugs on count of updated entries Matheus Tavares
2022-07-13  4:19     ` [PATCH 1/3] checkout: document bug where delayed checkout counts entries twice Matheus Tavares
2022-07-13 17:57  6%   ` Junio C Hamano
2022-07-14 17:44  6% [PATCH 0/3] doc: unify config info on some cmds Matheus Tavares
2022-07-14 21:17  0% ` Ævar Arnfjörð Bjarmason
2022-07-22 19:42     [PATCH 0/2] t0021: convert perl script to C test-tool helper Matheus Tavares
2022-07-22 19:42     ` [PATCH 1/2] t/t0021: convert the rot13-filter.pl script to C Matheus Tavares
2022-07-23  4:59  6%   ` Ævar Arnfjörð Bjarmason
2022-07-28 14:01     [PATCH] mingw: include the Python parts in the build Johannes Schindelin via GitGitGadget
2022-07-28 17:29     ` Junio C Hamano
2022-07-29 14:29       ` Johannes Schindelin
2022-07-29 21:31         ` Johannes Sixt
2022-08-10  9:29  6%       ` Johannes Schindelin
2022-07-28 16:46     [PATCH v6 0/9] docs: create & use "(user|developer) interfaces" categories Ævar Arnfjörð Bjarmason
2022-08-02 12:56     ` [PATCH v7 00/10] " Ævar Arnfjörð Bjarmason
2022-08-02 12:56       ` [PATCH v7 08/10] docs: move pack format docs to man section 5 Ævar Arnfjörð Bjarmason
2022-08-03 16:25  5%     ` Junio C Hamano
2022-08-09 13:11     [BUG] Unicode filenames handling in `git log --stat` Alexander Meshcheryakov
2022-09-02  4:21     ` [PATCH v3 2/2] diff.c: More changes and tests around utf8_strwidth() tboegi
2022-09-02 10:12  5%   ` Johannes Schindelin
2022-08-10 21:33     [BUG] git rev-list --missing=allow-promisor Andrew Olsen
2022-08-11  8:12     ` Jeff King
2022-08-14  6:29       ` [PATCH] is_promisor_object(): fix use-after-free of tree buffer Jeff King
2022-08-15  5:32         ` Junio C Hamano
2022-08-15 22:53  6%       ` Jeff King
2022-09-09 18:13  4% [PATCH] Documentation: add ReviewingGuidelines Victoria Dye via GitGitGadget
2022-09-15 23:25  0% ` Josh Steadmon
2022-09-19 18:17  0%   ` Glen Choo
2022-09-19 19:12  3% ` [PATCH v2] " Victoria Dye via GitGitGadget
2022-09-22 13:29  0%   ` Phillip Wood
2022-09-22 13:37     [PATCH v2 0/2] scalar: make unregister idempotent Derrick Stolee via GitGitGadget
2022-09-26 18:48     ` [PATCH v3 0/3] " Derrick Stolee via GitGitGadget
2022-09-26 18:48       ` [PATCH v3 1/3] maintenance: add 'unregister --force' Derrick Stolee via GitGitGadget
2022-09-26 19:23         ` Junio C Hamano
2022-09-26 20:49  6%       ` Derrick Stolee
2022-10-12  9:35     [PATCH v3 0/8] rebase: make reflog messages independent of the backend Phillip Wood via GitGitGadget
2022-10-21  9:21     ` [PATCH v4 " Phillip Wood via GitGitGadget
2022-10-21  9:21       ` [PATCH v4 8/8] rebase: cleanup action handling Phillip Wood via GitGitGadget
2022-10-21 17:54  6%     ` Junio C Hamano
2022-10-15 18:09     [suggestion] Fail cherry-pick if it overwrites untracked files with the matching file names Rupinderjeet Singh
2022-10-15 18:35     ` Junio C Hamano
2022-10-16  2:07  6%   ` Elijah Newren
2022-11-01  1:07     [PATCH 0/9] Bundle URIs IV: advertise over protocol v2 Derrick Stolee via GitGitGadget
2022-11-16 19:51     ` [PATCH v2 " Derrick Stolee via GitGitGadget
2022-11-16 19:51       ` [PATCH v2 7/9] bundle-uri: allow relative URLs in bundle lists Derrick Stolee via GitGitGadget
2022-11-29  1:25         ` Victoria Dye
2022-12-02 16:03  6%       ` Derrick Stolee
2022-11-04  1:02     [PATCH 0/4] worktree: Support `--orphan` when creating new worktrees Jacob Abel
2022-11-04 21:34     ` [PATCH v2 0/2] " Jacob Abel
2022-11-10 23:32       ` [PATCH v3 " Jacob Abel
2022-11-10 23:32         ` [PATCH v3 2/2] worktree add: add --orphan flag Jacob Abel
2022-11-15 21:08           ` Ævar Arnfjörð Bjarmason
2022-11-15 21:29             ` Eric Sunshine
2022-11-15 22:35  4%           ` Ævar Arnfjörð Bjarmason
2022-11-19  3:09  0%             ` Jacob Abel
2022-11-19 11:50  0%               ` Ævar Arnfjörð Bjarmason
2022-11-15 18:53     [PATCH] builtin/gc.c: fix use-after-free in maintenance_unregister() Taylor Blau
2022-11-15 19:00     ` Derrick Stolee
2022-11-15 19:51  6%   ` Ævar Arnfjörð Bjarmason
2022-11-15 19:41     ` Ævar Arnfjörð Bjarmason
2022-11-15 19:54       ` Taylor Blau
2022-11-16 13:44         ` Derrick Stolee
2022-11-16 15:14  6%       ` Ævar Arnfjörð Bjarmason
2022-11-16 20:14  0%         ` Taylor Blau
2022-11-21  3:00     [PATCH 0/3] fix t1509-root-work-tree failure Eric Sunshine via GitGitGadget
2022-11-21  3:00     ` [PATCH 3/3] t1509: facilitate repeated script invocations Eric Sunshine via GitGitGadget
2022-12-06  2:42       ` Ævar Arnfjörð Bjarmason
2022-12-06  3:23         ` Eric Sunshine
2022-12-08 12:04           ` Johannes Schindelin
2022-12-08 13:14  5%         ` "test_atexit" v.s. "test_when_finished" (was: [PATCH 3/3] t1509: facilitate repeated script invocations) Ævar Arnfjörð Bjarmason
2022-11-26 20:21     [PATCH v2] send-email: relay '-v N' to format-patch Kyle Meyer
2022-11-27  1:25     ` Junio C Hamano
2022-11-28 12:34  6%   ` Ævar Arnfjörð Bjarmason
2022-12-02 17:02     [PATCH] maintenance: compare output of pthread functions for inequality with 0 Rose via GitGitGadget
2022-12-02 18:10  6% ` Ævar Arnfjörð Bjarmason
2022-12-02 18:44  0%   ` Jeff Hostetler
2022-12-16 12:15     [PATCH] grep: fall back to interpreter mode if JIT fails Mathias Krause
2023-01-27 15:49     ` [PATCH v2] grep: fall back to interpreter if JIT memory allocation fails Mathias Krause
2023-01-27 16:34       ` Junio C Hamano
2023-01-27 17:39         ` Junio C Hamano
2023-01-29 13:36           ` Mathias Krause
2023-01-29 17:15             ` Junio C Hamano
2023-01-30 11:08               ` Mathias Krause
2023-01-30 18:54                 ` Junio C Hamano
2023-01-30 20:08  6%               ` Junio C Hamano
2023-01-31  7:30  0%                 ` Mathias Krause
2023-01-20  4:56     [PATCH v2 0/2] rebase: mark --update-refs as requiring the merge backend Elijah Newren via GitGitGadget
2023-01-21  1:55     ` [PATCH v3 0/7] rebase: fix several code/testing/documentation issues around flag incompatibilities Elijah Newren via GitGitGadget
2023-01-21  1:55       ` [PATCH v3 3/7] rebase: remove --allow-empty-message from incompatible opts Elijah Newren via GitGitGadget
2023-01-21 15:09  6%     ` Phillip Wood
2023-02-02 23:46     [GSoC][PATCH] merge: use reverse_commit_list() for list reversal Elijah Newren
2023-02-03 17:49     ` Kousik Sanagavarapu
2023-02-03 18:02  6%   ` Elijah Newren
2023-02-03 19:07  0%     ` Junio C Hamano
2023-02-04 19:10     [PATCH] cache-tree: fix strbuf growth in prime_cache_tree_rec() René Scharfe
2023-02-05 21:12     ` Ævar Arnfjörð Bjarmason
2023-02-06 15:27       ` Derrick Stolee
2023-02-06 16:18  6%     ` Ævar Arnfjörð Bjarmason
2023-02-12 11:20  0%       ` René Scharfe
2023-02-10 20:20       ` René Scharfe
2023-02-10 20:33         ` Junio C Hamano
2023-02-11  2:15  6%       ` Jeff King
2023-02-11  2:46  0%         ` Junio C Hamano
2023-02-09  0:02     [PATCH v8 0/6] submodule: parallelize diff Calvin Wan
2023-03-02 21:52     ` [PATCH v9 " Calvin Wan
2023-03-02 22:02       ` [PATCH v9 6/6] diff-lib: parallelize run_diff_files for submodules Calvin Wan
2023-03-07  8:41  3%     ` Ævar Arnfjörð Bjarmason
2023-02-19 14:13     How to find places where I can contribute? Divyanshu Agrawal
2023-02-20  9:59     ` Christian Couder
2023-02-20 21:31  6%   ` Junio C Hamano
2023-03-20 17:10     bug? round-trip through fast-import/fast-export loses files Priedhorsky, Reid
2023-03-21  1:57  6% ` Elijah Newren
2023-03-21 15:54  0%   ` Priedhorsky, Reid
2023-03-21 18:31  0%   ` Jeff King
2023-03-22  3:07  0%     ` Elijah Newren
2023-05-08 21:59     [PATCH 00/15] refs: implement skip lists for packed backend Taylor Blau
2023-05-08 21:59     ` [PATCH 06/15] builtin/for-each-ref.c: add `--exclude` option Taylor Blau
2023-05-08 23:22       ` Junio C Hamano
2023-05-09 20:22  6%     ` Taylor Blau
2023-05-19  7:00     Which macOS versions does Git support? M Hickford
2023-05-19  9:09     ` Jeff King
2023-05-20  0:37       ` Carlo Marcelo Arenas Belón
2023-05-20  7:36  6%     ` M Hickford
2023-05-22 19:24  0%       ` Jeff King
2023-06-14 19:25     [PATCH 0/9] Repack objects into separate packfiles based on a filter Christian Couder
2023-06-14 19:25     ` [PATCH 8/9] repack: implement `--filter-to` for storing filtered out objects Christian Couder
2023-06-21 11:49       ` Taylor Blau
2023-06-21 12:08         ` Christian Couder
2023-06-21 12:25  6%       ` Taylor Blau
2023-06-21 16:44  0%         ` Junio C Hamano
2023-08-05  4:45     [PATCH 0/5] Fixes to trailer test script, help text, and documentation Linus Arver via GitGitGadget
2023-08-05  4:45     ` [PATCH 3/5] trailer: add tests to check defaulting behavior with --no-* flags Linus Arver via GitGitGadget
2023-08-07  1:13       ` Junio C Hamano
2023-08-07  5:28  5%     ` Linus Arver
2023-08-10 14:40     [PATCH] upload-pack: fix race condition in error messages Derrick Stolee via GitGitGadget
2023-08-16  6:06     ` [PATCH] upload-pack: fix exit code when denying fetch of unreachable object ID Patrick Steinhardt
2023-08-16 16:16       ` Junio C Hamano
2023-08-16 17:04  6%     ` [Leftoverbits] exit code clean-up? Junio C Hamano
2023-08-17  5:36  7%       ` Jeff King
2023-08-17 16:03  8%         ` Junio C Hamano
2023-08-17  9:24  8%       ` Oswald Buddenhagen
2023-08-18 23:37     [PATCH v2 0/3] "update-index --show-index-version" Junio C Hamano
2023-08-18 23:37     ` [PATCH v2 2/3] update-index: add --show-index-version Junio C Hamano
2023-09-12  5:54  5%   ` Linus Arver
2023-08-22  3:34     [PATCH] .github/workflows: add coverity action Taylor Blau
2023-08-29  8:18  2% ` Johannes Schindelin
2023-08-31 21:16     [PATCH v2 0/10] more unused parameters in parseopt callbacks Jeff King
2023-08-31 21:21     ` [PATCH v2 05/10] parse-options: prefer opt->value to globals in callbacks Jeff King
2023-09-02  7:34  6%   ` René Scharfe
2023-09-05  6:52  0%     ` Jeff King
2023-09-07  9:25     [PATCH v4 00/15] Introduce new `git replay` command Christian Couder
2023-10-10 12:38     ` [PATCH v5 00/14] " Christian Couder
2023-10-10 12:38       ` [PATCH v5 11/14] replay: use standard revision ranges Christian Couder
2023-10-19 19:49  6%     ` Linus Arver
2023-09-07 21:51     [PATCH 0/2] repack: implement `--cruft-max-size` Taylor Blau
2023-09-07 21:52     ` [PATCH 2/2] builtin/repack.c: implement support for `--cruft-max-size` Taylor Blau
2023-09-08 11:21       ` Patrick Steinhardt
2023-10-02 20:30  5%     ` Taylor Blau
2023-09-11 15:39     [PATCH] diff --stat: add config option to limit filename width Dragan Simic
2023-09-11 23:12     ` Junio C Hamano
2023-09-12  2:11       ` Dragan Simic
2023-09-12 17:11  6%     ` Junio C Hamano
2023-09-12 17:48  0%       ` Dragan Simic
2023-09-14  9:34     [PATCH 0/4] merge-ort unused parameter cleanups Jeff King
2023-09-14  9:39     ` [PATCH 1/4] merge-ort: drop custom err() function Jeff King
2023-09-16  2:54  5%   ` Elijah Newren
2023-09-16  5:50  0%     ` Jeff King
2023-10-02 15:15     Notes from the Git Contributor's Summit, 2023 Taylor Blau
2023-10-02 15:22  4% ` [TOPIC 11/12] Improving new contributor on-boarding Taylor Blau
2023-10-03 20:25     [PATCH 0/10] some commit-graph leak fixes Jeff King
2023-10-03 20:30     ` [PATCH 08/10] commit-graph: free write-context entries before overwriting Jeff King
2023-10-05 17:51  6%   ` Taylor Blau
2023-10-03 20:54     [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
2023-10-19 19:39     ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
2023-10-22  0:13  6%   ` Junio C Hamano
2023-10-22 21:49  0%     ` Andy Koppe
2023-10-23  0:20  0%       ` Junio C Hamano
2023-10-23 22:15  0%         ` Andy Koppe
2023-10-05 22:14     How To Pick And Work On A Microproject Naomi Ibe
2023-10-05 22:42  6% ` Junio C Hamano
2023-10-06  9:02  5%   ` Christian Couder
2023-10-06 19:03  8%     ` Junio C Hamano
2023-10-09 20:55     [PATCH 0/20] bounds-checks for chunk-based files Jeff King
2023-10-09 21:04     ` [PATCH 06/20] commit-graph: check consistency of fanout table Jeff King
2023-10-11 14:45  6%   ` Taylor Blau
2023-10-16 10:38     [PATCH v2 0/3] rev-list: add support for commits in `--missing` Karthik Nayak
2023-10-19 12:10     ` [PATCH v3 " Karthik Nayak
2023-10-19 12:10       ` [PATCH v3 3/3] rev-list: add commit object support in `--missing` option Karthik Nayak
2023-10-19 22:05         ` Junio C Hamano
2023-10-19 23:35           ` Junio C Hamano
2023-10-20 16:41  5%         ` Junio C Hamano
2023-10-24 11:34  0%           ` Karthik Nayak
2023-10-18  5:35     [PATCH 00/11] t: reduce direct disk access to data structures Patrick Steinhardt
2023-10-18  5:35     ` [PATCH 04/11] t: convert tests to not write references via the filesystem Patrick Steinhardt
2023-10-18 21:18  5%   ` Junio C Hamano
2023-10-23 13:58  0%     ` Patrick Steinhardt
2023-10-18 20:28     [PATCH v1 0/4] maintenance: use XDG config if it exists Kristoffer Haugsbakk
2024-01-14 21:43     ` [PATCH v2 " Kristoffer Haugsbakk
2024-01-14 21:43       ` [PATCH v2 3/4] config: factor out global config file retrieval Kristoffer Haugsbakk
2024-01-19  6:18         ` Patrick Steinhardt
2024-01-19  7:40           ` Kristoffer Haugsbakk
2024-01-19  7:59             ` Patrick Steinhardt
2024-01-19 23:04  6%           ` Junio C Hamano
2023-10-30  3:08     [PATCH] sequencer: remove use of comment character Tony Tung via GitGitGadget
2023-10-30  4:00  6% ` Junio C Hamano
2023-10-30 17:26  0%   ` Elijah Newren
2023-12-07 22:12     [BUG] rev-list doesn't validate arguments to -n option Britton Kerin
2023-12-08 20:36     ` Junio C Hamano
2023-12-08 22:35       ` [PATCH] revision: parse integer arguments to --max-count, --skip, etc., more carefully Junio C Hamano
2023-12-12  1:30         ` Jeff King
2023-12-12 15:09           ` Junio C Hamano
2023-12-12 22:05  6%         ` Jeff King
2024-01-11 13:47     [PATCH] git-p4: stop reaching into the refdb Patrick Steinhardt
2024-01-11 21:20  6% ` Junio C Hamano
2024-01-31 22:30     [PATCH v3 0/2] index-pack: fsck honor checks Jonathan Tan
2024-02-01  1:34     ` John Cai
2024-02-01 16:44  6%   ` Junio C Hamano
2024-02-07 16:44     [PATCH 0/2] show-ref --verify: accept psuedorefs Phillip Wood via GitGitGadget
2024-02-07 16:44     ` [PATCH 1/2] show-ref --verify: accept pseudorefs Phillip Wood via GitGitGadget
2024-02-07 17:12  6%   ` Junio C Hamano
2024-02-08 14:34  0%     ` phillip.wood123
2024-02-07 16:47     [PATCH v2 0/5] merge-tree: handle missing objects correctly Johannes Schindelin via GitGitGadget
2024-02-22 14:36     ` [PATCH v3 " Johannes Schindelin via GitGitGadget
2024-02-22 14:36       ` [PATCH v3 1/5] merge-tree: fail with a non-zero exit code on missing tree objects Johannes Schindelin via GitGitGadget
2024-02-22 17:13  6%     ` Junio C Hamano
2024-02-22 14:36       ` [PATCH v3 4/5] Always check `parse_tree*()`'s return value Johannes Schindelin via GitGitGadget
2024-02-22 17:58  5%     ` Junio C Hamano
2024-02-08 17:00     [PATCH] prune: mark rebase autostash and orig-head as reachable Phillip Wood via GitGitGadget
2024-02-09 16:19     ` [PATCH v2] " Phillip Wood via GitGitGadget
2024-02-09 18:04  6%   ` Junio C Hamano
2024-02-08 23:17     [PATCH] git: --no-lazy-fetch option Junio C Hamano
2024-02-15  5:30     ` Jeff King
2024-02-15 17:04       ` Junio C Hamano
2024-02-16 17:22         ` Junio C Hamano
2024-02-16 21:09           ` [PATCH] git: extend --no-lazy-fetch to work across subprocesses Junio C Hamano
2024-02-17  5:40             ` Jeff King
2024-02-27  6:04  7%           ` Junio C Hamano
2024-02-27  7:49  6%             ` Jeff King
2024-02-17  5:29           ` [PATCH] git: --no-lazy-fetch option Jeff King
2024-03-09  1:57  6%         ` Linus Arver
2024-02-11  8:57     [PATCH] unit-tests: do show relative file paths on non-Windows, too Junio C Hamano
2024-02-11 11:03     ` Phillip Wood
2024-02-11 15:58       ` [PATCH v2] " Junio C Hamano
2024-02-13 19:58         ` Johannes Schindelin
2024-02-13 20:48  6%       ` Junio C Hamano
2024-02-14 14:25     [PATCH v3 0/5] rev-list: allow missing tips with --missing Christian Couder
2024-02-28  9:10     ` [PATCH] revision: fix --missing=[print|allow*] for annotated tags Christian Couder
2024-02-28 17:46  6%   ` Junio C Hamano
2024-02-20 15:23     [PATCH] rebase: make warning less passive aggressive Harmen Stoppels via GitGitGadget
2024-02-20 17:29  6% ` Junio C Hamano
2024-02-21  8:35     [PATCH] git-remote.txt: fix typo Jakub Wilk
2024-02-21 18:18  6% ` Junio C Hamano
2024-03-05 21:24     [PATCH 00/22] avoid redundant pipelines Beat Bolli
2024-03-05 21:25     ` [PATCH 01/22] doc: avoid redundant use of cat Beat Bolli
2024-03-05 22:24  6%   ` Junio C Hamano
2024-03-15 19:45     ` [PATCH v2 00/22] avoid redundant pipelines Beat Bolli
2024-03-15 19:46       ` [PATCH v2 09/22] t/t4*: avoid redundant uses of cat Beat Bolli
2024-03-16  1:34  6%     ` Taylor Blau
2024-03-16  6:04  0%       ` Junio C Hamano
2024-03-07  9:14     [PATCH 0/15] allow multi-byte core.commentChar Jeff King
2024-03-07  9:26     ` [PATCH 11/15] find multi-byte comment chars in unterminated buffers Jeff King
2024-03-07 19:42       ` René Scharfe
2024-03-12  8:05         ` Jeff King
2024-03-14 19:37  6%       ` René Scharfe
2024-03-08 14:14     [PATCH 0/4] checkout: cleanup --conflict= Phillip Wood via GitGitGadget
2024-03-14 17:05     ` [PATCH v2 0/5] " Phillip Wood via GitGitGadget
2024-03-14 17:05       ` [PATCH v2 1/5] xdiff-interface: refactor parsing of merge.conflictstyle Phillip Wood via GitGitGadget
2024-03-14 17:19  6%     ` Junio C Hamano
2024-03-12 15:55     [PATCH 0/3] Improve the documentation and test coverage for whitespace and comments Dragan Simic
2024-03-12 15:55     ` [PATCH 1/3] config.txt: describe whitespace characters further and more accurately Dragan Simic
2024-03-14  1:18  5%   ` Junio C Hamano
2024-03-14  6:20  0%     ` Dragan Simic
2024-03-12 16:26     [PATCH] bugreport.c: fix a crash in `git bugreport` with `--no-suffix` option barroit via GitGitGadget
2024-03-13 15:59  7% ` Junio C Hamano
2024-03-18 12:47  6% [PATCH 0/2] git-compat-util: move convert_slashes from compat/mingw.h and rename it Mohit Marathe via GitGitGadget
2024-03-19 11:23     [PATCH v2 0/5] Fixes for Documentation/MyFirstObjectWalk.txt Dirk Gouders
2024-03-25 12:33     ` [PATCH v3 " Dirk Gouders
2024-03-25 17:50  6%   ` Junio C Hamano
2024-03-25 18:01  0%     ` Kyle Lippincott
2024-03-20  9:48     [PATCH] contrib: drop hg-to-git script Jeff King
2024-03-22  7:31     ` Johannes Schindelin
2024-03-22 15:58       ` Junio C Hamano
2024-03-22 23:43         ` Jeff King
2024-03-23 18:49  6%       ` Junio C Hamano
2024-03-22 22:17     [PATCH] editorconfig: add Makefiles to "text files" Max Gautier
2024-03-22 22:40     ` Junio C Hamano
2024-03-23 15:55       ` Max Gautier
2024-03-23 17:36  5%     ` Junio C Hamano
2024-03-24 21:43     [PATCH] pretty: find pretty formats case-insensitively Brian Lyles
2024-03-25  6:14     ` Jeff King
2024-03-25 18:12  6%   ` Junio C Hamano
2024-03-25 13:10     [GSoC] Microproject help vk
2024-03-25 20:51  6% ` Eric Sunshine
2024-03-25 21:23  0%   ` Junio C Hamano
2024-03-25 21:37  0%     ` Eric Sunshine
2024-03-30  8:10     [RFC] bisect: Introduce skip-when to automatically skip commits Olliver Schinagl
2024-04-05  6:50     ` Olliver Schinagl
2024-04-06  1:08       ` Junio C Hamano
2024-04-06 10:06         ` Olliver Schinagl
2024-04-06 13:50           ` Phillip Wood
2024-04-06 19:17             ` Olliver Schinagl
2024-04-07 14:09               ` phillip.wood123
2024-04-07 14:52                 ` Olliver Schinagl
2024-04-07 15:12                   ` phillip.wood123
2024-04-08 16:49  5%                 ` Junio C Hamano
2024-04-10 10:39  0%                   ` Olliver Schinagl
2024-04-04  9:39     [PATCH] sequencer: honor signoff opt in run_git_commit David Bimmler via GitGitGadget
2024-04-04 16:22  5% ` Junio C Hamano
2024-04-04 19:21  0%   ` Phillip Wood
2024-04-04 13:25     [PATCH 00/12] t: exercise Git/JGit reftable compatibility Patrick Steinhardt
2024-04-04 13:25     ` [PATCH 11/12] t0610: fix non-portable variable assignment Patrick Steinhardt
2024-04-05 16:02       ` Junio C Hamano
2024-04-05 16:12         ` [PATCH] CodingGuidelines: quote assigned value with "local" and "export" Junio C Hamano
2024-04-05 16:21  6%       ` Junio C Hamano
2024-04-14 16:47     [PATCH] imap-send: increase command size limit René Scharfe
2024-04-15 18:55     ` Jeff King
2024-04-16 16:08  6%   ` René Scharfe
2024-04-17  8:28     [PATCH 0/2] Use a "best effort" strategy in scheduled maintenance Johannes Schindelin via GitGitGadget
2024-04-17  8:28     ` [PATCH 2/2] maintenance: running maintenance should not stop on errors Johannes Schindelin via GitGitGadget
2024-04-17 15:41  6%   ` Junio C Hamano
2024-04-23 21:28     [PATCH v3 0/8] refs: add symref support to 'git-update-ref' Karthik Nayak
2024-04-26 15:24     ` [PATCH v4 0/7] add symref-* commands to 'git-update-ref --stdin' Karthik Nayak
2024-04-26 15:24       ` [PATCH v4 1/7] refs: accept symref values in `ref_transaction[_add]_update` Karthik Nayak
2024-04-26 19:31  6%     ` Junio C Hamano
2024-04-26 21:15  5%       ` Jeff King
2024-04-29  7:02  0%         ` Patrick Steinhardt
2024-04-29  7:55  0%           ` Jeff King
2024-04-26 15:24       ` [PATCH v4 2/7] files-backend: extract out `create_symref_lock` Karthik Nayak
2024-04-26 21:39  5%     ` Junio C Hamano
2024-04-28 19:57  0%       ` Karthik Nayak
2024-05-01 20:22       ` [PATCH v5 0/7] refs: add support for transactional symref updates Karthik Nayak
2024-05-01 20:22         ` [PATCH v5 4/7] " Karthik Nayak
2024-05-01 23:52           ` Junio C Hamano
2024-05-02  5:50             ` Karthik Nayak
2024-05-02  7:47  6%           ` Patrick Steinhardt
2024-05-02 11:10  0%             ` Karthik Nayak
2024-05-02 16:51  0%             ` Junio C Hamano
2024-04-29 16:48     [PATCH 0/3] color: add support for 12-bit RGB colors Beat Bolli
2024-04-29 16:48     ` [PATCH 3/3] " Beat Bolli
2024-04-30 10:57       ` Jeff King
2024-04-30 17:31  6%     ` Junio C Hamano
2024-04-30 18:41  0%       ` Junio C Hamano
2024-04-30  1:47     [PATCH v3 0/1] advice: add --no-advice global option James Liu
2024-05-03  7:17     ` [PATCH v4 0/3] advice: add "all" option to disable all hints James Liu
2024-05-03  7:17       ` [PATCH v4 1/3] doc: clean up usage documentation for --no-* opts James Liu
2024-05-03 17:30  6%     ` Junio C Hamano
2024-05-06  1:39  0%       ` James Liu
2024-05-23  4:20     [PATCH v2 1/3] Documentation: alias: rework notes into points Ian Wienand
2024-05-23  4:37     ` [PATCH v3 " Ian Wienand
2024-05-23 15:14  6%   ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).