git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Add git config variable for signoff
  @ 2022-12-19 17:26  6%   ` Prajwal S N
  0 siblings, 0 replies; 171+ results
From: Prajwal S N @ 2022-12-19 17:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

> I think the latest round was the thread leading to this message:
>
>   https://lore.kernel.org/git/xmqqpnfw8gyn.fsf@gitster-ct.c.googlers.com/
>
> There was an earlier round:
>
>   https://lore.kernel.org/git/20161229084701.GA3643@starla/

I went through these threads as well as the other related ones, and I
understand some of the arguments. It definitely makes sense to have
this specifically as opt-in, since it is important for developers to
be aware that they are adding a DCO to their commits. This is exactly
what my patch suggestion proposes - let us not touch the defaults for
signing off, but simply provide a `commit.signoff` config flag
identical to the existing `format.signoff` flag that works with `git
format-patch`. This would mean that only the developers who regularly
signoff every commit can add this to their config, taking full
responsibility for choosing to do so :)

Cheers,
Prajwal S N

^ permalink raw reply	[relevance 6%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  2022-12-07 23:04  0%         ` Junio C Hamano
@ 2022-12-08  7:27  0%           ` Jeff King
  0 siblings, 0 replies; 171+ results
From: Jeff King @ 2022-12-08  7:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Taylor Blau, David Caro, git

On Thu, Dec 08, 2022 at 08:04:46AM +0900, Junio C Hamano wrote:

> Taylor Blau <me@ttaylorr.com> writes:
> 
> >> > >     $ git commit --signoff[=[no-]dedup]
> > ...
> > Thanks, I look forward to seeing your work. It would be nice to
> > standardize on this `--signoff[=[no-]dedup]` thing throughout all of the
> > different commands that support it.
> 
> Also, if I am not mistaken, each of trailers can be configured to
> have its own semantics (e.g. .where and .ifExists).
> 
>  * Should we have similar override to these trailer tokens, not just
>    sign-off?

This made me curious about the opposite: is there config you can set to
get this behavior for --signoff? I think the answer is "no". You can do:

  git -c trailer.ifExists=addIfDifferent \
      commit --amend --trailer="Signed-off-by: Jeff King <peff@peff.net>"

to get the desired behavior, but using "--signoff" does not respect
trailer settings.

I feel like config is probably a better match for the use cases here,
because the decision about de-duping is not something you'd usually set
for one particular operation, but is more likely to be a project policy
about what the trailer means (and that includes Signed-off-by). So you'd
want to set it per-repo, not per-operation.

>  * Should we offer not just [no-]dedup (which is equivalent to
>    switching from addIfDifferentNeighbor to addIfDifferent) but
>    other customization?  This affects what --signoff should be
>    allowed to take for consistency across trailers.

Yeah, writing the above made me wonder if --signoff should behave
exactly like:

  --trailer="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"

For the most part that would not change any behavior unless you set
trailer.signed-off-by.*, and setting those presumably signals intent
that you expect them to take effect. The one exception is that the
generic trailer.ifExists, etc, would start affecting --signoff, which
_might_ be a surprise. If we wanted to retain the behavior there, we
could say "--signoff is special, and doesn't respect generic trailer
config".

Alternatively, it would be nice if there was an easy way to put your
ident into a trailer (what I wrote above doesn't really work unless you
have those variables in your environment, and of course it's a lot of
typing). I think you can hack it up like:

  git config trailer.sign.key Signed-off-by
  git config trailer.sign.cmd \
    'git var GIT_COMMITTER_IDENT | sed "s/>.*/>/";:'
  git commit --trailer=sign

which is only a little more typing than --signoff, but it's not very
ergonomic.

-Peff

^ permalink raw reply	[relevance 0%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  2022-12-07 22:13  0%       ` Taylor Blau
@ 2022-12-07 23:04  0%         ` Junio C Hamano
  2022-12-08  7:27  0%           ` Jeff King
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2022-12-07 23:04 UTC (permalink / raw)
  To: Taylor Blau; +Cc: David Caro, git

Taylor Blau <me@ttaylorr.com> writes:

>> > >     $ git commit --signoff[=[no-]dedup]
> ...
> Thanks, I look forward to seeing your work. It would be nice to
> standardize on this `--signoff[=[no-]dedup]` thing throughout all of the
> different commands that support it.

Also, if I am not mistaken, each of trailers can be configured to
have its own semantics (e.g. .where and .ifExists).

 * Should we have similar override to these trailer tokens, not just
   sign-off?

 * Should we offer not just [no-]dedup (which is equivalent to
   switching from addIfDifferentNeighbor to addIfDifferent) but
   other customization?  This affects what --signoff should be
   allowed to take for consistency across trailers.



^ permalink raw reply	[relevance 0%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  2022-12-07  8:40  0%     ` David Caro
@ 2022-12-07 22:13  0%       ` Taylor Blau
  2022-12-07 23:04  0%         ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Taylor Blau @ 2022-12-07 22:13 UTC (permalink / raw)
  To: David Caro; +Cc: Junio C Hamano, git

On Wed, Dec 07, 2022 at 09:40:27AM +0100, David Caro wrote:
> On 12/07 13:11, Junio C Hamano wrote:
> > Taylor Blau <me@ttaylorr.com> writes:
> >
> > >> I propose enabling it for commit, merge and am.
> > >
> > > So I think that there are some legitimate uses outside of 'format-patch'
> > > that we may want to keep the existing behavior. So I don't think we
> > > should necessarily change the default to have other commands outside of
> > > 'format-patch' start passing APPEND_SIGNOFF_DEDUP.
> > >
> > > But I could see a future where we add a new option that controls whether
> > > or not we pass that flag, perhaps:
> > >
> > >     $ git commit --signoff[=[no-]dedup]
> >
> > That sounds sensible.
>
> Agree, I will implement this then for commit for now, thanks!

Thanks, I look forward to seeing your work. It would be nice to
standardize on this `--signoff[=[no-]dedup]` thing throughout all of the
different commands that support it.

According to:

    $ git grep -- '--signoff' -- Documentation/git-*.txt

that list is: `git am`, `git cherry-pick`, `git format-patch`, `git
rebase`, and `git revert`. But there are others, too, via an include of
`signoff-option.txt`, so that is `git commit`, `git merge`, and `git
pull`.

Phew ;-).

Thanks,
Taylor

^ permalink raw reply	[relevance 0%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  2022-12-07  4:11  0%   ` Junio C Hamano
@ 2022-12-07  8:40  0%     ` David Caro
  2022-12-07 22:13  0%       ` Taylor Blau
  0 siblings, 1 reply; 171+ results
From: David Caro @ 2022-12-07  8:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Taylor Blau, git

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

On 12/07 13:11, Junio C Hamano wrote:
> Taylor Blau <me@ttaylorr.com> writes:
> 
> >> I propose enabling it for commit, merge and am.
> >
> > So I think that there are some legitimate uses outside of 'format-patch'
> > that we may want to keep the existing behavior. So I don't think we
> > should necessarily change the default to have other commands outside of
> > 'format-patch' start passing APPEND_SIGNOFF_DEDUP.
> >
> > But I could see a future where we add a new option that controls whether
> > or not we pass that flag, perhaps:
> >
> >     $ git commit --signoff[=[no-]dedup]
> 
> That sounds sensible.

Agree, I will implement this then for commit for now, thanks!

-- 
David Caro
SRE - Cloud Services
Wikimedia Foundation <https://wikimediafoundation.org/>
PGP Signature: 7180 83A2 AC8B 314F B4CE  1171 4071 C7E1 D262 69C3

"Imagine a world in which every single human being can freely share in the
sum of all knowledge. That's our commitment."

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

^ permalink raw reply	[relevance 0%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  2022-12-07  1:50  4% ` Taylor Blau
@ 2022-12-07  4:11  0%   ` Junio C Hamano
  2022-12-07  8:40  0%     ` David Caro
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2022-12-07  4:11 UTC (permalink / raw)
  To: Taylor Blau; +Cc: David Caro, git

Taylor Blau <me@ttaylorr.com> writes:

>> I propose enabling it for commit, merge and am.
>
> So I think that there are some legitimate uses outside of 'format-patch'
> that we may want to keep the existing behavior. So I don't think we
> should necessarily change the default to have other commands outside of
> 'format-patch' start passing APPEND_SIGNOFF_DEDUP.
>
> But I could see a future where we add a new option that controls whether
> or not we pass that flag, perhaps:
>
>     $ git commit --signoff[=[no-]dedup]

That sounds sensible.

^ permalink raw reply	[relevance 0%]

* Re: Skipping adding Signed-off-by even if it's not the last on git commit
  @ 2022-12-07  1:50  4% ` Taylor Blau
  2022-12-07  4:11  0%   ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Taylor Blau @ 2022-12-07  1:50 UTC (permalink / raw)
  To: David Caro; +Cc: git

Hi David,

On Tue, Dec 06, 2022 at 06:06:46PM +0100, David Caro wrote:
> I have noticed that when requesting git commit to add the
> Signed-off-by header, it will add it even if it already exists as long
> as it's not the last in the footer.
>
> It seems that the functionality to do so has been there for a while
> (see [1]) and it's being used effectively on format-patch, but it was
> never enabled for the rest of commands.

Right; bab4d1097c (sequencer.c: teach append_signoff how to detect
duplicate s-o-b, 2013-02-12) introduced the APPEND_SIGNOFF_DEDUP flag,
which instructs append_signoff() to avoid adding a Signed-off-by
trailer if one already exists anywhere in the trailers section of the
target commit.

As bab4d1097c hints, this is desirable in some situations. However,
adding duplicated S-o-b trailers is useful in other situations. For
example, if you and I exchange a patch back and forth on this list, it
might go something like:

  1. I write up an initial patch, add my Singed-off-by, and send it to
     the list.

  2. You notice that some aspects can be improved, so you apply and
     modify the commit locally, adding your own Signed-off-by.

  3. I pick up your changes as part of a new version of the patch
     series, and resubmit it to the list, adding my own Signed-off-by
     again.

There are a couple of small things worth noting there. First, in (2),
the changes that you introduced were large enough to be worth crediting
(e.g., you didn't suggest a typofix or to modify the amount of spacing
on a line or similar), but not large enough to change the author of the
patch.

Likewise, in (3), the second instance of my Signed-off-by indicates that
I am OK with the changes that you wrote, and I certify the new version
of the patch as my own work.

One such instance is in 0ca6ead81e (alias.c: reject too-long cmdline
strings in split_cmdline(), 2022-09-28). Another is in b3c5f5cb04
(submodule: move core cmd_update() logic to C, 2022-03-15).

If you're curious to dig up more in your own project, here's a little
shell snippet I wrote up to find some examples:

    git rev-list --no-merges HEAD |
    while read rev
    do
      git -P show -s -1 --format='%(trailers:key=Signed-off-by,unfold=true)' "$rev" |
      grep -v '^$' | sort | uniq -c | grep -vq "^      1 " && echo "$rev"
    done

> I propose enabling it for commit, merge and am.

So I think that there are some legitimate uses outside of 'format-patch'
that we may want to keep the existing behavior. So I don't think we
should necessarily change the default to have other commands outside of
'format-patch' start passing APPEND_SIGNOFF_DEDUP.

But I could see a future where we add a new option that controls whether
or not we pass that flag, perhaps:

    $ git commit --signoff[=[no-]dedup]

?

Thanks,
Taylor

^ permalink raw reply	[relevance 4%]

* Re: git format-patch -s enhancement
  2021-08-16 16:36  5% ` Jeff King
@ 2021-08-16 21:49  0%   ` jim.cromie
  0 siblings, 0 replies; 171+ results
From: jim.cromie @ 2021-08-16 21:49 UTC (permalink / raw)
  To: Jeff King; +Cc: git

On Mon, Aug 16, 2021 at 10:37 AM Jeff King <peff@peff.net> wrote:
>
> On Sun, Aug 15, 2021 at 05:07:34PM -0600, jim.cromie@gmail.com wrote:
>
> > git format-patch -s is sub-optimal :
> > it appends the SoB,
> > which falls after the snips
> > ---
> > changelog ...
> > that the commit message may contain
> >
> >
> > So it misfires on any maintainer scripts
> > expecting the SoB above the 1st snip.
> >
> > The workaround is manual SoBs above any snips.
> >
> > I note this in -s doc,
> >
> >            Add a Signed-off-by trailer to the commit message, using
> > the committer identity of yourself.
> >            See the signoff option in git-commit(1) for more information.
> >
> > "trailer" is really "document current working behavior"
> > (normative docu-speak, so to speak;)
> >
> > Ideal behavior is to find 1st in-body  --- snip
> > and insert there
>
> The big disconnect here is that "---" snip lines are not meant to be
> meaningful within commit messages themselves. They are part of the
> process of sticking a commit message into an email. So format-patch and
> git-am know about them, but "git commit" for example doesn't.
>
> So "git commit --signoff" probably shouldn't take them into account when
> deciding the end of a commit message. The user might or might not have
> meant "---" to be syntactically meaningful, depending on whether they
> plan to send the message with format-patch (and changing the behavior
> now is questionable).
>
> Doing so with "git format-patch --signoff" is a slightly different
> question.  The current behavior is working as intended, in the sense
> that it signs off just as "commit -s" would, and then separately sticks
> the result into the email. The fact that "---" in the commit message is
> indistinguishable from the ones added by format-patch is mostly an
> accident.
>
> That said, it's kind of a useful accident for some workflows, exactly
> because you can carry these non-commit-message notes inside the commit
> message. And since we know how any in-commit-message "---" will be
> treated by git-am on the other side, it might be reasonable for
> format-patch to start considering them to be syntactically significant.
>
> So I guess I would disagree that it's a bug exactly, in that the
> workflow you're advocating was never meant to be supported. But I don't
> see any reason we couldn't be a little friendlier to it, if somebody
> wanted to teach format-patch to do so.
>

agreed, notabug.

but it might fall afoul of others' mail handler scripts,
Ive had a couple replys implying missed delivery,
maybe because of details like '---'

Im just gonna add my SoB either at commit time, or manually.
It will be interesting to see what happens to an SoB in a commit
when its revised and --- changelogged

thanks


> An alternative workflow would be to use git-notes to attach the
> changelog data to the commit. Those are shown after the "---" by
> format-patch already. Unfortunately, keeping them up to date is kind of
> annoying. Ages ago, I had a patch to let you modify them while editing
> the commit message, which makes it pretty seamless:
>
>   https://lore.kernel.org/git/20110225133056.GA1026@sigill.intra.peff.net/
>
> I carried the patch in my local build for a while, but never really
> ended up using it. So I never polished it further. But I think it's
> still fundamentally a reasonable idea, if somebody is interested in
> carrying it forward. If so, here's the version I've been rebasing
> forward over the years:
>
>   https://github.com/peff/git jk/commit-notes-wip
>
> but it doesn't seem to actually pass its own tests anymore (so it may or
> may not be a helpful starting point. ;) ).
>
> -Peff

^ permalink raw reply	[relevance 0%]

* Re: git format-patch -s enhancement
  @ 2021-08-16 16:36  5% ` Jeff King
  2021-08-16 21:49  0%   ` jim.cromie
  0 siblings, 1 reply; 171+ results
From: Jeff King @ 2021-08-16 16:36 UTC (permalink / raw)
  To: jim.cromie; +Cc: git

On Sun, Aug 15, 2021 at 05:07:34PM -0600, jim.cromie@gmail.com wrote:

> git format-patch -s is sub-optimal :
> it appends the SoB,
> which falls after the snips
> ---
> changelog ...
> that the commit message may contain
> 
> 
> So it misfires on any maintainer scripts
> expecting the SoB above the 1st snip.
> 
> The workaround is manual SoBs above any snips.
> 
> I note this in -s doc,
> 
>            Add a Signed-off-by trailer to the commit message, using
> the committer identity of yourself.
>            See the signoff option in git-commit(1) for more information.
> 
> "trailer" is really "document current working behavior"
> (normative docu-speak, so to speak;)
> 
> Ideal behavior is to find 1st in-body  --- snip
> and insert there

The big disconnect here is that "---" snip lines are not meant to be
meaningful within commit messages themselves. They are part of the
process of sticking a commit message into an email. So format-patch and
git-am know about them, but "git commit" for example doesn't.

So "git commit --signoff" probably shouldn't take them into account when
deciding the end of a commit message. The user might or might not have
meant "---" to be syntactically meaningful, depending on whether they
plan to send the message with format-patch (and changing the behavior
now is questionable).

Doing so with "git format-patch --signoff" is a slightly different
question.  The current behavior is working as intended, in the sense
that it signs off just as "commit -s" would, and then separately sticks
the result into the email. The fact that "---" in the commit message is
indistinguishable from the ones added by format-patch is mostly an
accident.

That said, it's kind of a useful accident for some workflows, exactly
because you can carry these non-commit-message notes inside the commit
message. And since we know how any in-commit-message "---" will be
treated by git-am on the other side, it might be reasonable for
format-patch to start considering them to be syntactically significant.

So I guess I would disagree that it's a bug exactly, in that the
workflow you're advocating was never meant to be supported. But I don't
see any reason we couldn't be a little friendlier to it, if somebody
wanted to teach format-patch to do so.

An alternative workflow would be to use git-notes to attach the
changelog data to the commit. Those are shown after the "---" by
format-patch already. Unfortunately, keeping them up to date is kind of
annoying. Ages ago, I had a patch to let you modify them while editing
the commit message, which makes it pretty seamless:

  https://lore.kernel.org/git/20110225133056.GA1026@sigill.intra.peff.net/

I carried the patch in my local build for a while, but never really
ended up using it. So I never polished it further. But I think it's
still fundamentally a reasonable idea, if somebody is interested in
carrying it forward. If so, here's the version I've been rebasing
forward over the years:

  https://github.com/peff/git jk/commit-notes-wip

but it doesn't seem to actually pass its own tests anymore (so it may or
may not be a helpful starting point. ;) ).

-Peff

^ permalink raw reply	[relevance 5%]

* [PATCH 1/2] t6020: fix bash incompatible issue
  @ 2021-06-01 14:49  4% ` Jiang Xin
  0 siblings, 0 replies; 171+ results
From: Jiang Xin @ 2021-06-01 14:49 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason, Junio C Hamano, Git List
  Cc: Jiang Xin, Jeff King

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

Ævar reported that the function `make_user_friendly_and_stable_output()`
failed on a i386 box (gcc45) in the gcc farm boxes with error:

    sed: couldn't re-allocate memory

It turns out that older versions of bash (4.3) or dash (0.5.7) cannot
evaluate expression like `${A%${A#???????}}` used to get the leading 7
characters of variable A.

Replace the complex expressions so that t6020 works on older version of
bash or dash.

Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 t/t6020-bundle-misc.sh | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index 881f72fd44..c6a8ea7f76 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -77,7 +77,8 @@ test_commit_setvar () {
 		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
 		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
 	fi &&
-	eval $var=$oid
+	suffix=${oid#???????} &&
+	eval $var=${oid%$suffix}
 }
 
 # Format the output of git commands to make a user-friendly and stable
@@ -85,25 +86,25 @@ test_commit_setvar () {
 # about future changes of the commit ID and spaces of the output.
 make_user_friendly_and_stable_output () {
 	sed \
-		-e "s/${A%${A#???????}}[0-9a-f]*/<COMMIT-A>/g" \
-		-e "s/${B%${B#???????}}[0-9a-f]*/<COMMIT-B>/g" \
-		-e "s/${C%${C#???????}}[0-9a-f]*/<COMMIT-C>/g" \
-		-e "s/${D%${D#???????}}[0-9a-f]*/<COMMIT-D>/g" \
-		-e "s/${E%${E#???????}}[0-9a-f]*/<COMMIT-E>/g" \
-		-e "s/${F%${F#???????}}[0-9a-f]*/<COMMIT-F>/g" \
-		-e "s/${G%${G#???????}}[0-9a-f]*/<COMMIT-G>/g" \
-		-e "s/${H%${H#???????}}[0-9a-f]*/<COMMIT-H>/g" \
-		-e "s/${I%${I#???????}}[0-9a-f]*/<COMMIT-I>/g" \
-		-e "s/${J%${J#???????}}[0-9a-f]*/<COMMIT-J>/g" \
-		-e "s/${K%${K#???????}}[0-9a-f]*/<COMMIT-K>/g" \
-		-e "s/${L%${L#???????}}[0-9a-f]*/<COMMIT-L>/g" \
-		-e "s/${M%${M#???????}}[0-9a-f]*/<COMMIT-M>/g" \
-		-e "s/${N%${N#???????}}[0-9a-f]*/<COMMIT-N>/g" \
-		-e "s/${O%${O#???????}}[0-9a-f]*/<COMMIT-O>/g" \
-		-e "s/${P%${P#???????}}[0-9a-f]*/<COMMIT-P>/g" \
-		-e "s/${TAG1%${TAG1#???????}}[0-9a-f]*/<TAG-1>/g" \
-		-e "s/${TAG2%${TAG2#???????}}[0-9a-f]*/<TAG-2>/g" \
-		-e "s/${TAG3%${TAG3#???????}}[0-9a-f]*/<TAG-3>/g" \
+		-e "s/$A[0-9a-f]*/<COMMIT-A>/g" \
+		-e "s/$B[0-9a-f]*/<COMMIT-B>/g" \
+		-e "s/$C[0-9a-f]*/<COMMIT-C>/g" \
+		-e "s/$D[0-9a-f]*/<COMMIT-D>/g" \
+		-e "s/$E[0-9a-f]*/<COMMIT-E>/g" \
+		-e "s/$F[0-9a-f]*/<COMMIT-F>/g" \
+		-e "s/$G[0-9a-f]*/<COMMIT-G>/g" \
+		-e "s/$H[0-9a-f]*/<COMMIT-H>/g" \
+		-e "s/$I[0-9a-f]*/<COMMIT-I>/g" \
+		-e "s/$J[0-9a-f]*/<COMMIT-J>/g" \
+		-e "s/$K[0-9a-f]*/<COMMIT-K>/g" \
+		-e "s/$L[0-9a-f]*/<COMMIT-L>/g" \
+		-e "s/$M[0-9a-f]*/<COMMIT-M>/g" \
+		-e "s/$N[0-9a-f]*/<COMMIT-N>/g" \
+		-e "s/$O[0-9a-f]*/<COMMIT-O>/g" \
+		-e "s/$P[0-9a-f]*/<COMMIT-P>/g" \
+		-e "s/$TAG1[0-9a-f]*/<TAG-1>/g" \
+		-e "s/$TAG2[0-9a-f]*/<TAG-2>/g" \
+		-e "s/$TAG3[0-9a-f]*/<TAG-3>/g" \
 		-e "s/ *\$//"
 }
 
-- 
2.32.0.rc0


^ permalink raw reply related	[relevance 4%]

* Re: [PATCH v9 2/2] [GSOC] trailer: add new .cmd config option
  2021-04-14 20:33  4%               ` Junio C Hamano
@ 2021-04-15 15:32  0%                 ` ZheNing Hu
  0 siblings, 0 replies; 171+ results
From: ZheNing Hu @ 2021-04-15 15:32 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Christian Couder, ZheNing Hu via GitGitGadget, git

Junio C Hamano <gitster@pobox.com> 于2021年4月15日周四 上午4:33写道:
>
> ZheNing Hu <adlternative@gmail.com> writes:
>
> >> So I am waiting to hear why it is not a misfeature.  If it is not,
> >> then surely I am fine to keep it for now and add a workaround later,
> >> but until that happens, I do not think "commit --trailer" can be
> >> used as a way to allow end-users emulate "-s" for their favorite
> >> trailer like helped-by, acked-by, etc.
> >>
> >
> > If it is really necessary to solve this "empty execution" in .cmd,
>
> > Maybe we need to consider two points:
> > * Do we need a new config flag as you said `[implicitExecution = false]`
> > or just drop it? Has anyone been relying on the "empty execution" of
> > .command before? This may be worthy of concern.
>
> Yes, if it is useful sometimes to run the .command or .cmd with
> empty <value> even when nobody asks for it on the command line with
> a "--trailer=<key>:<value>" option, then I agree that the users
> should be able to choose between running and not running [*].
>
> > *  Do we need `trailer.<token>.runMode` as Christan said before?
> > I rejected his this suggestion before, and now I regret it a bit.
>
> So far, I haven't heard anything that indicates it is a useful
> behaviour for .command, so my preference is to get rid of the
> behaviour when we introduce .cmd to deprecate .command; yes, until
> we get rid of .command, the behaviour between the two would be
> inconsistent but that is unavoidable when making a bugfix that is
> backward incompatible.
>
> When (and only when) anybody finds a credible use case, we can add a
> mechanism to optionally turn it on (e.g. .runMode).
>
> That is my thinking right at this moment, but that's of course
> subject to change when a use case that would be helped by having
> this extra execution.
>
>
> [Footnote]
>
> * Right now, all I know is that not being able to turn it off makes
>   it impossible to use "git commit --trailer" as a more general
>   substitute for "git commit --signoff" without breaking other
>   trailers (e.g. --trim-empty may get rid of the result of the extra
>   execution, but would remove other trailers that can be
>   legitimately empty).  And making it on by default with
>   configuration would mean that even though we designed .cmd as a
>   better version of the .command feature with its misdesign
>   corrected, we'd inherit one misdesign from it, which defeats one
>   third of the point of introducing the .cmd in the first place ;-)

Perhaps such a modification can meet our temporary needs!

@@ -721,9 +738,10 @@ static void process_command_line_args(struct
list_head *arg_head,
        char *cl_separators = xstrfmt("=%s", separators);

        /* Add an arg item for each configured trailer with a command */
        list_for_each(pos, &conf_head) {
                item = list_entry(pos, struct arg_item, list);
-               if (item->conf.cmd || item->conf.command)
+               if (item->conf.command)

I'm so busy today that I probably haven't had time to put this into a
patch today,
If this solution is reasonable, I will send a new version of the patch tomorrow.
As you said, first solve the misfeature, and we can add [trailer.runMode] later.

Thanks, Junio!
--
ZheNing Hu

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v9 2/2] [GSOC] trailer: add new .cmd config option
  @ 2021-04-14 20:33  4%               ` Junio C Hamano
  2021-04-15 15:32  0%                 ` ZheNing Hu
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2021-04-14 20:33 UTC (permalink / raw)
  To: ZheNing Hu; +Cc: Christian Couder, ZheNing Hu via GitGitGadget, git

ZheNing Hu <adlternative@gmail.com> writes:

>> So I am waiting to hear why it is not a misfeature.  If it is not,
>> then surely I am fine to keep it for now and add a workaround later,
>> but until that happens, I do not think "commit --trailer" can be
>> used as a way to allow end-users emulate "-s" for their favorite
>> trailer like helped-by, acked-by, etc.
>>
>
> If it is really necessary to solve this "empty execution" in .cmd,

> Maybe we need to consider two points:
> * Do we need a new config flag as you said `[implicitExecution = false]`
> or just drop it? Has anyone been relying on the "empty execution" of
> .command before? This may be worthy of concern.

Yes, if it is useful sometimes to run the .command or .cmd with
empty <value> even when nobody asks for it on the command line with
a "--trailer=<key>:<value>" option, then I agree that the users
should be able to choose between running and not running [*].

> *  Do we need `trailer.<token>.runMode` as Christan said before?
> I rejected his this suggestion before, and now I regret it a bit.

So far, I haven't heard anything that indicates it is a useful
behaviour for .command, so my preference is to get rid of the
behaviour when we introduce .cmd to deprecate .command; yes, until
we get rid of .command, the behaviour between the two would be
inconsistent but that is unavoidable when making a bugfix that is
backward incompatible.

When (and only when) anybody finds a credible use case, we can add a
mechanism to optionally turn it on (e.g. .runMode).

That is my thinking right at this moment, but that's of course
subject to change when a use case that would be helped by having
this extra execution.


[Footnote]

* Right now, all I know is that not being able to turn it off makes
  it impossible to use "git commit --trailer" as a more general
  substitute for "git commit --signoff" without breaking other
  trailers (e.g. --trim-empty may get rid of the result of the extra
  execution, but would remove other trailers that can be
  legitimately empty).  And making it on by default with
  configuration would mean that even though we designed .cmd as a
  better version of the .command feature with its misdesign
  corrected, we'd inherit one misdesign from it, which defeats one
  third of the point of introducing the .cmd in the first place ;-)

^ permalink raw reply	[relevance 4%]

* [PATCH 2/3] [GSOC] interpret-trailers: add own-identity option
  @ 2021-03-19 12:06  3% ` ZheNing Hu via GitGitGadget
  0 siblings, 0 replies; 171+ results
From: ZheNing Hu via GitGitGadget @ 2021-03-19 12:06 UTC (permalink / raw)
  To: git
  Cc: Bradley M. Kuhn, Junio C Hamano, Brandon Casey, Shourya Shukla,
	Christian Couder, Rafael Silva,
	Đoàn Trần Công Danh, ZheNing Hu, ZheNing Hu

From: ZheNing Hu <adlternative@gmail.com>

`git commit --trailer="Signed-off-by: \
$(git config user.name) <$(git config user.email)>"`
is difficult for users to add their own identities,
so teach interpret-trailers a new option `--own-identity`
which allow if we're optionalise <value> in `--trailer`,
by substitute user's identity if missing. This will help
the use of `commit --trailer` as easy as `commit --signoff`.

Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
 Documentation/git-interpret-trailers.txt | 13 +++++++++++++
 builtin/interpret-trailers.c             |  6 ++++--
 t/t7513-interpret-trailers.sh            | 12 ++++++++++++
 trailer.c                                | 18 ++++++++++++++++--
 trailer.h                                |  3 ++-
 5 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-interpret-trailers.txt b/Documentation/git-interpret-trailers.txt
index 96ec6499f001..25f6732d9e6d 100644
--- a/Documentation/git-interpret-trailers.txt
+++ b/Documentation/git-interpret-trailers.txt
@@ -84,6 +84,19 @@ OPTIONS
 	trailer to the input messages. See the description of this
 	command.
 
+--own-identity::
+	Used with `--trailer`. Those trailers without value with the
+	`--own-identity` option all will add the user's own identity.
+	For example,` git interpret-trailers --trailer "A:B" --trailer \
+	"Signed-off-by" --trailer "Helped-by" --own-identity --inplace a.txt`
+	will output:
+	"
+	A:B
+	Signed-off-by: C O Mitter <committer@example.com>
+	Helped-by: C O Mitter <committer@example.com>
+	"
+	in `a.txt`.
+
 --where <placement>::
 --no-where::
 	Specify where all new trailers will be added.  A setting
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 84748eafc01b..be7f502a58d7 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -47,6 +47,7 @@ static void new_trailers_clear(struct list_head *trailers)
 	list_for_each_safe(pos, tmp, trailers) {
 		item = list_entry(pos, struct new_trailer_item, list);
 		list_del(pos);
+		free(item->text);
 		free(item);
 	}
 }
@@ -66,7 +67,7 @@ static int option_parse_trailer(const struct option *opt,
 		return -1;
 
 	item = xmalloc(sizeof(*item));
-	item->text = arg;
+	item->text = xstrdup(arg);
 	item->where = where;
 	item->if_exists = if_exists;
 	item->if_missing = if_missing;
@@ -94,7 +95,8 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
 	struct option options[] = {
 		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_BOOL(0, "own-identity", &opts.own_identity,
+			     N_("specify the user's own identity for omitted trailers value")),
 		OPT_CALLBACK(0, "where", NULL, N_("action"),
 			     N_("where to place the new trailer"), option_parse_where),
 		OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 6602790b5f4c..f82cee93bfb2 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -63,6 +63,18 @@ test_expect_success 'without config' '
 	test_cmp expected actual
 '
 
+test_expect_success 'without config with --own-identity' '
+	cat >expected <<-\EOF &&
+
+	Acked-by: A B <C>
+	Helped-by: C O Mitter <committer@example.com>
+	Signed-off-by: C O Mitter <committer@example.com>
+	EOF
+	git interpret-trailers --trailer "Acked-by: A B <C>" --trailer "Helped-by" \
+	--trailer "Signed-off-by" --own-identity empty >actual &&
+	test_cmp expected actual
+'
+
 test_expect_success 'without config in another order' '
 	sed -e "s/ Z\$/ /" >expected <<-\EOF &&
 
diff --git a/trailer.c b/trailer.c
index 249ed618ed8e..cd4f85e71c9a 100644
--- a/trailer.c
+++ b/trailer.c
@@ -690,8 +690,18 @@ static void add_arg_item(struct list_head *arg_head, char *tok, char *val,
 	list_add_tail(&new_item->list, arg_head);
 }
 
+static void add_user_own_identity(struct new_trailer_item *item)
+{
+	struct strbuf buf = STRBUF_INIT;
+	strbuf_addstr(&buf, item->text);
+	strbuf_add(&buf, "=", 1);
+	strbuf_addstr(&buf, fmt_name(WANT_COMMITTER_IDENT));
+	free(item->text);
+	item->text = buf.buf;
+}
+
 static void process_command_line_args(struct list_head *arg_head,
-				      struct list_head *new_trailer_head)
+				      struct list_head *new_trailer_head, int own_identity)
 {
 	struct arg_item *item;
 	struct strbuf tok = STRBUF_INIT;
@@ -728,6 +738,10 @@ static void process_command_line_args(struct list_head *arg_head,
 			error(_("empty trailer token in trailer '%.*s'"),
 			      (int) sb.len, sb.buf);
 			strbuf_release(&sb);
+		} else if (separator_pos == -1 && own_identity) {
+				add_user_own_identity(tr);
+				pos = pos->prev;
+				continue;
 		} else {
 			parse_trailer(&tok, &val, &conf, tr->text,
 				      separator_pos);
@@ -1048,7 +1062,7 @@ void process_trailers(const char *file,
 
 	if (!opts->only_input) {
 		LIST_HEAD(arg_head);
-		process_command_line_args(&arg_head, new_trailer_head);
+		process_command_line_args(&arg_head, new_trailer_head ,opts->own_identity);
 		process_trailers_lists(&head, &arg_head);
 	}
 
diff --git a/trailer.h b/trailer.h
index 795d2fccfd95..235dfdfa1978 100644
--- a/trailer.h
+++ b/trailer.h
@@ -57,7 +57,7 @@ struct trailer_info {
 struct new_trailer_item {
 	struct list_head list;
 
-	const char *text;
+	char *text;
 
 	enum trailer_where where;
 	enum trailer_if_exists if_exists;
@@ -73,6 +73,7 @@ struct process_trailer_options {
 	int no_divider;
 	int key_only;
 	int value_only;
+	int own_identity;
 	const struct strbuf *separator;
 	const struct strbuf *key_value_separator;
 	int (*filter)(const struct strbuf *, void *);
-- 
gitgitgadget


^ permalink raw reply related	[relevance 3%]

* [PATCH v2] [GSOC] commit: add trailer command
  2021-03-11  7:16  2% [PATCH] [GSOC] commit: provides multiple common signatures ZheNing Hu via GitGitGadget
  2021-03-11 15:03  0% ` Shourya Shukla
  2021-03-11 17:28  0% ` Junio C Hamano
@ 2021-03-12 15:54  5% ` ZheNing Hu via GitGitGadget
  2 siblings, 0 replies; 171+ results
From: ZheNing Hu via GitGitGadget @ 2021-03-12 15:54 UTC (permalink / raw)
  To: git
  Cc: Bradley M. Kuhn, Junio C Hamano, Brandon Casey, Shourya Shukla,
	ZheNing Hu, ZheNing Hu

From: ZheNing Hu <adlternative@gmail.com>

Historically, Git has supported the 'Signed-off-by' commit trailer
using the '--signoff' and the '-s' option from the command line.
But users may need to provide richer trailer information from the
command line such as "Helped-by", "Reported-by", "Mentored-by",

Now use `--trailer <token>[(=|:)<value>]` pass the trailers to
`interpret-trailers` and generate trailers in commit messages.

Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
    [GSOC] commit: provides multiple signatures from command line
    
    Now maintainers or developers can also use commit
    --trailer="Signed-off-by:commiter<email>" from the command line to
    provide trailers to commit messages. This solution may be more
    generalized than v1.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-901%2Fadlternative%2Fcommit-with-multiple-signatures-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-901/adlternative/commit-with-multiple-signatures-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/901

Range-diff vs v1:

 1:  e9389e72ac65 ! 1:  4c507d17db4f [GSOC] commit: provides multiple common signatures
     @@ Metadata
      Author: ZheNing Hu <adlternative@gmail.com>
      
       ## Commit message ##
     -    [GSOC] commit: provides multiple common signatures
     +    [GSOC] commit: add trailer command
      
     -    Similar to "Helped-by", "Reported-by", "Reviewed-by", "Mentored-by"
     -    these signatures are often seen in git commit messages. After
     -    referring to the simple implementation of `commit --signoff`
     -    and `send-email -cc=" commiter <email>"`, I am considering
     -    whether to provide multiple signature parameters from the
     -    command line. I think this might help maintainers and
     -    developers directly uses the shell to provide these signatures
     -    instead of multiple times repetitive writing those trailers
     -    each time.
     +    Historically, Git has supported the 'Signed-off-by' commit trailer
     +    using the '--signoff' and the '-s' option from the command line.
     +    But users may need to provide richer trailer information from the
     +    command line such as "Helped-by", "Reported-by", "Mentored-by",
      
     -    To achieve this goal, i refactored the `append_signoff` design and
     -    provided `append_message` and `append_message_string_list` interfaces,
     -    providing new ways to generate those various signatures.
     -
     -    Users now can use `commit -H "helper <eamil>"` to generate "Helped-by" trailer,
     -    `commit -R "reviewer <eamil>"` to generate "Reviewed-by" trailer,
     -    `commit -r "reporter <eamil> "`to generate "Reported-by" trailer,
     -    `commit -M "mentor <eamil>"` to generate "Mentored-by" trailer.
     +    Now use `--trailer <token>[(=|:)<value>]` pass the trailers to
     +    `interpret-trailers` and generate trailers in commit messages.
      
          Signed-off-by: ZheNing Hu <adlternative@gmail.com>
      
     @@ Documentation/git-commit.txt: SYNOPSIS
       	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
       	   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
      -	   [-S[<keyid>]] [--] [<pathspec>...]
     -+	   [-S[<keyid>]] [--] [<pathspec>...] [(-H|--helped-by)=<address>...]
     -+	   [(-R|--reviewed-by)=<address>...] [(-r|--reported-by)=<address>...]
     -+	   [(-M|--mentored)=<address>...]
     ++	   [-S[<keyid>]] [--] [<pathspec>...] [(--trailer <token>[(=|:)<value>])...]
       
       DESCRIPTION
       -----------
     @@ Documentation/git-commit.txt: The `-m` option is mutually exclusive with `-c`, `
       
       include::signoff-option.txt[]
       
     -+-H=<address>...::
     -+--helped-by=<address>...::
     -+	Add one or more `Helped-by` trailer by the committer at the end of the commit
     -+	log message.
     -+
     -+-R=<address>...::
     -+--reviewed-by=<address>...::
     -+	Add one or more `Reviewed-by` trailer by the committer at the end of the commit
     -+	log message.
     -+
     -+-r=<address>...::
     -+--reported-by=<address>...::
     -+	Add one or more `Reported-by` trailer by the committer at the end of the commit
     -+	log message.
     -+
     -+-M=<address>...::
     -+--mentored-by=<address>...::
     -+	Add one or more `Mentored-by` trailer by the committer at the end of the commit
     -+	log message.
     ++--trailer <token>[(=|:)<value>]::
     ++	Specify a (<token>, <value>) pair that should be applied as a
     ++	trailer. (e.g.  `git commit --trailer "Signed-off-by:C O Mitter <committer@example.com>" \
     ++	--trailer "Helped-by:C O Mitter <committer@example.com>"`will add the "Signed-off" trailer
     ++	and the "Helped-by" trailer in the commit message.)
      +
       -n::
       --no-verify::
     @@ builtin/commit.c: static int config_commit_verbose = -1; /* unspecified */
       static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
       static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
       static char *sign_commit, *pathspec_from_file;
     -+static struct string_list helped_by = STRING_LIST_INIT_NODUP;
     -+static struct string_list mentored_by = STRING_LIST_INIT_NODUP;
     -+static struct string_list reviewed_by = STRING_LIST_INIT_NODUP;
     -+static struct string_list reported_by = STRING_LIST_INIT_NODUP;
     ++struct child_process run_trailer = CHILD_PROCESS_INIT;
     ++static const char *trailer;
       
       /*
        * The default commit message cleanup mode will remove the lines
     -@@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const char *prefix,
     - 	if (signoff)
     - 		append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
     - 
     -+	if(helped_by.items)
     -+		append_message_string_list(&sb, "Helped-by: ", &helped_by, ignore_non_trailer(sb.buf, sb.len), 0);
     -+	if(reviewed_by.items)
     -+		append_message_string_list(&sb, "Reviewed-by: ", &reviewed_by, ignore_non_trailer(sb.buf, sb.len), 0);
     -+	if(reported_by.items)
     -+		append_message_string_list(&sb, "Reported-by: ", &reported_by, ignore_non_trailer(sb.buf, sb.len), 0);
     -+	if(mentored_by.items)
     -+		append_message_string_list(&sb, "Mentored-by: ", &mentored_by, ignore_non_trailer(sb.buf, sb.len), 0);
     -+
     -+	string_list_clear(&helped_by, 0);
     -+	string_list_clear(&reviewed_by, 0);
     -+	string_list_clear(&reported_by, 0);
     -+	string_list_clear(&mentored_by, 0);
     -+
     - 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
     - 		die_errno(_("could not write commit template"));
     +@@ builtin/commit.c: static struct strbuf message = STRBUF_INIT;
       
     -@@ builtin/commit.c: static int git_commit_config(const char *k, const char *v, void *cb)
     - 	return git_status_config(k, v, s);
     - }
     + static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
       
     -+static int help_callback(const struct option *opt, const char *arg, int unset)
     -+{
     -+	if (unset)
     -+		string_list_clear(&helped_by, 0);
     -+	else
     -+		string_list_append(&helped_by, arg);
     -+	return 0;
     -+}
     -+
     -+static int review_callback(const struct option *opt, const char *arg, int unset)
     ++static int opt_pass_trailer(const struct option *opt, const char *arg, int unset)
      +{
     -+	if (unset)
     -+		string_list_clear(&reviewed_by, 0);
     -+	else
     -+		string_list_append(&reviewed_by, arg);
     -+	return 0;
     -+}
     -+
     -+static int report_callback(const struct option *opt, const char *arg, int unset)
     -+{
     -+	if (unset)
     -+		string_list_clear(&reported_by, 0);
     -+	else
     -+		string_list_append(&reported_by, arg);
     -+	return 0;
     -+}
     -+
     -+static int mentor_callback(const struct option *opt, const char *arg, int unset)
     -+{
     -+	if (unset)
     -+		string_list_clear(&mentored_by, 0);
     -+	else
     -+		string_list_append(&mentored_by, arg);
     ++	if (unset) {
     ++		strvec_clear(&run_trailer.args);
     ++		return -1;
     ++	}
     ++	run_trailer.git_cmd = 1;
     ++	strvec_pushl(&run_trailer.args, "--trailer", arg, NULL);
      +	return 0;
      +}
      +
     - int cmd_commit(int argc, const char **argv, const char *prefix)
     + static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
       {
     - 	static struct wt_status s;
     + 	enum wt_status_format *value = (enum wt_status_format *)opt->value;
     +@@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const char *prefix,
     + 
     + 	fclose(s->fp);
     + 
     ++	run_command(&run_trailer);
     ++
     + 	/*
     + 	 * Reject an attempt to record a non-merge empty commit without
     + 	 * explicit --allow-empty. In the cherry-pick case, it may be
      @@ builtin/commit.c: int cmd_commit(int argc, const char **argv, const char *prefix)
       		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
       		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
       		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
     -+		OPT_CALLBACK('H', "helped-by", NULL, N_("email"), N_("add a Helped-by trailer"), help_callback),
     -+		OPT_CALLBACK('r', "reported-by", NULL, N_("email"), N_("add a Reported-by trailer"), report_callback),
     -+		OPT_CALLBACK('R', "reviewed-by", NULL, N_("email"), N_("add a Reviewed-by trailer"), review_callback),
     -+		OPT_CALLBACK('M', "mentored-by", NULL, N_("email"), N_("add a Mentored-by trailer"), mentor_callback),
     ++		OPT_CALLBACK(0, "trailer", &trailer, N_("trailer"), N_("trailer(s) to add"), opt_pass_trailer),
       		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
       		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
       		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
      @@ builtin/commit.c: int cmd_commit(int argc, const char **argv, const char *prefix)
     - 	struct commit_extra_header *extra = NULL;
     - 	struct strbuf err = STRBUF_INIT;
     - 
     -+	helped_by.strdup_strings = 1;
     -+	reviewed_by.strdup_strings = 1;
     -+	reported_by.strdup_strings = 1;
     -+	mentored_by.strdup_strings = 1;
     -+
     - 	if (argc == 2 && !strcmp(argv[1], "-h"))
     - 		usage_with_options(builtin_commit_usage, builtin_commit_options);
     - 
     -
     - ## sequencer.c ##
     -@@ sequencer.c: int sequencer_pick_revisions(struct repository *r,
     - 	return res;
     - }
     - 
     --void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
     -+void append_message(struct strbuf *msgbuf, struct strbuf *sob,
     -+			size_t ignore_footer, unsigned flag)
     - {
     - 	unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
     --	struct strbuf sob = STRBUF_INIT;
     - 	int has_footer;
     - 
     --	strbuf_addstr(&sob, sign_off_header);
     --	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
     --	strbuf_addch(&sob, '\n');
     --
     - 	if (!ignore_footer)
     - 		strbuf_complete_line(msgbuf);
     - 
     -@@ sequencer.c: void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
     - 	 * If the whole message buffer is equal to the sob, pretend that we
     - 	 * found a conforming footer with a matching sob
     - 	 */
     --	if (msgbuf->len - ignore_footer == sob.len &&
     --	    !strncmp(msgbuf->buf, sob.buf, sob.len))
     -+	if (msgbuf->len - ignore_footer == sob->len &&
     -+	    !strncmp(msgbuf->buf, sob->buf, sob->len))
     - 		has_footer = 3;
     - 	else
     --		has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
     -+		has_footer = has_conforming_footer(msgbuf, sob, ignore_footer);
     - 
     - 	if (!has_footer) {
     - 		const char *append_newlines = NULL;
     -@@ sequencer.c: void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
     - 
     - 	if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
     - 		strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
     --				sob.buf, sob.len);
     -+				sob->buf, sob->len);
     -+}
     -+
     -+void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
     -+{
     -+	struct strbuf sob = STRBUF_INIT;
     -+	strbuf_addstr(&sob, sign_off_header);
     -+	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
     -+	strbuf_addch(&sob, '\n');
     -+	append_message(msgbuf, &sob, ignore_footer, flag);
     -+	strbuf_release(&sob);
     -+}
     - 
     -+void append_message_string_list(struct strbuf *msgbuf, const char *header,
     -+		struct string_list *sobs, size_t ignore_footer, unsigned flag) {
     -+	int i;
     -+	struct strbuf sob = STRBUF_INIT;
     -+
     -+	for ( i = 0; i < sobs->nr; i++)
     -+	{
     -+		strbuf_addstr(&sob, header);
     -+		strbuf_addstr(&sob, sobs->items[i].string);
     -+		strbuf_addch(&sob, '\n');
     -+		append_message(msgbuf, &sob, ignore_footer, flag);
     -+		strbuf_reset(&sob);
     -+	}
     - 	strbuf_release(&sob);
     - }
     - 
     -
     - ## sequencer.h ##
     -@@ sequencer.h: int todo_list_rearrange_squash(struct todo_list *todo_list);
     -  * and the new signoff will be spliced into the buffer before those bytes.
     -  */
     - void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
     -+void append_message(struct strbuf *msgbuf, struct strbuf *sob,
     -+		size_t ignore_footer, unsigned flag);
     -+void append_message_string_list(struct strbuf *msgbuf, const char*header,
     -+		struct string_list *sobs, size_t ignore_footer, unsigned flag);
     - 
     - void append_conflicts_hint(struct index_state *istate,
     - 		struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);
     + 			die(_("could not parse HEAD commit"));
     + 	}
     + 	verbose = -1; /* unspecified */
     ++	strvec_pushl(&run_trailer.args, "interpret-trailers",
     ++		"--in-place", "--where=end", git_path_commit_editmsg(), NULL);
     + 	argc = parse_and_validate_options(argc, argv, builtin_commit_options,
     + 					  builtin_commit_usage,
     + 					  prefix, current_head, &s);
      
       ## t/t7502-commit-porcelain.sh ##
      @@ t/t7502-commit-porcelain.sh: test_expect_success 'sign off' '
       
       '
       
     -+test_expect_success 'helped-by' '
     -+
     ++test_expect_success 'trailer' '
      +	>file1 &&
      +	git add file1 &&
     -+	git commit --helped-by="foo <bar@frotz>" \
     -+	--helped-by="foo2 <bar2@frotz>" -m "thank you" &&
     -+	git cat-file commit HEAD >commit.msg &&
     -+	sed -ne "s/Helped-by: //p" commit.msg >actual &&
     -+	cat >expected <<-\EOF &&
     -+	foo <bar@frotz>
     -+	foo2 <bar2@frotz>
     -+	EOF
     -+	test_cmp expected actual
     -+
     -+'
     -+
     -+test_expect_success 'reported-by' '
     -+
     -+	>file2 &&
     -+	git add file2 &&
     -+	git commit --reported-by="foo <bar@frotz>" \
     -+	--reported-by="foo2 <bar2@frotz>" -m "thank you" &&
     -+	git cat-file commit HEAD >commit.msg &&
     -+	sed -ne "s/Reported-by: //p" commit.msg >actual &&
     -+	cat >expected <<-\EOF &&
     -+	foo <bar@frotz>
     -+	foo2 <bar2@frotz>
     -+	EOF
     -+	test_cmp expected actual
     -+
     -+'
     -+
     -+test_expect_success 'reviewed-by' '
     -+
     -+	>file3 &&
     -+	git add file3 &&
     -+	git commit --reviewed-by="foo <bar@frotz>" \
     -+	--reviewed-by="foo2 <bar2@frotz>" -m "thank you" &&
     -+	git cat-file commit HEAD >commit.msg &&
     -+	sed -ne "s/Reviewed-by: //p" commit.msg >actual &&
     -+	cat >expected <<-\EOF &&
     -+	foo <bar@frotz>
     -+	foo2 <bar2@frotz>
     -+	EOF
     -+	test_cmp expected actual
     -+
     -+'
     -+
     -+test_expect_success 'mentored-by' '
     -+
     -+	>file4 &&
     -+	git add file4 &&
     -+	git commit --mentored-by="foo <bar@frotz>" \
     -+	--mentored-by="foo2 <bar2@frotz>" -m "thank you" &&
     -+	git cat-file commit HEAD >commit.msg &&
     -+	sed -ne "s/Mentored-by: //p" commit.msg >actual &&
     -+	cat >expected <<-\EOF &&
     -+	foo <bar@frotz>
     -+	foo2 <bar2@frotz>
     -+	EOF
     -+	test_cmp expected actual
     -+
     -+'
     -+
     -+test_expect_success 'multiple signatures' '
     -+
     -+	>file5 &&
     -+	git add file5 &&
     -+	git commit --helped-by="foo <bar@frotz>" \
     -+	--reviewed-by="foo2 <bar2@frotz>" \
     -+	--mentored-by="foo3 <bar3@frotz>" \
     -+	--reported-by="foo4 <bar4@frotz>" -s -m "thank you" &&
     ++	git commit -s --trailer "Signed-off-by:C O Mitter1 <committer1@example.com>" \
     ++	--trailer "Helped-by:C O Mitter2 <committer2@example.com>"  \
     ++	--trailer "Reported-by:C O Mitter3 <committer3@example.com>" \
     ++	--trailer "Mentored-by:C O Mitter4 <committer4@example.com>" \
     ++	-m "hello" &&
      +	git cat-file commit HEAD >commit.msg &&
      +	sed -e "1,7d" commit.msg >actual &&
      +	cat >expected <<-\EOF &&
      +	Signed-off-by: C O Mitter <committer@example.com>
     -+	Helped-by: foo <bar@frotz>
     -+	Reviewed-by: foo2 <bar2@frotz>
     -+	Reported-by: foo4 <bar4@frotz>
     -+	Mentored-by: foo3 <bar3@frotz>
     ++	Signed-off-by: C O Mitter1 <committer1@example.com>
     ++	Helped-by: C O Mitter2 <committer2@example.com>
     ++	Reported-by: C O Mitter3 <committer3@example.com>
     ++	Mentored-by: C O Mitter4 <committer4@example.com>
      +	EOF
      +	test_cmp expected actual
     -+
     -+'
     -+
     -+test_expect_success 'multiple signatures (use abbreviations)' '
     -+
     -+	>file6 &&
     -+	git add file6 &&
     -+	git commit -H "foo <bar@frotz>" \
     -+	-R "foo2 <bar2@frotz>" \
     -+	-M "foo3 <bar3@frotz>" \
     -+	-r "foo4 <bar4@frotz>" -s -m "thank you" &&
     -+	git cat-file commit HEAD >commit.msg &&
     -+	sed -e "1,7d" commit.msg >actual &&
     -+	cat >expected <<-\EOF &&
     -+	Signed-off-by: C O Mitter <committer@example.com>
     -+	Helped-by: foo <bar@frotz>
     -+	Reviewed-by: foo2 <bar2@frotz>
     -+	Reported-by: foo4 <bar4@frotz>
     -+	Mentored-by: foo3 <bar3@frotz>
     -+	EOF
     -+	test_cmp expected actual
     -+
      +'
      +
       test_expect_success 'multiple -m' '


 Documentation/git-commit.txt |  8 +++++++-
 builtin/commit.c             | 18 ++++++++++++++++++
 t/t7502-commit-porcelain.sh  | 20 ++++++++++++++++++++
 3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 17150fa7eabe..764513a3f287 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -14,7 +14,7 @@ SYNOPSIS
 	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
 	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
 	   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
-	   [-S[<keyid>]] [--] [<pathspec>...]
+	   [-S[<keyid>]] [--] [<pathspec>...] [(--trailer <token>[(=|:)<value>])...]
 
 DESCRIPTION
 -----------
@@ -166,6 +166,12 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 
 include::signoff-option.txt[]
 
+--trailer <token>[(=|:)<value>]::
+	Specify a (<token>, <value>) pair that should be applied as a
+	trailer. (e.g.  `git commit --trailer "Signed-off-by:C O Mitter <committer@example.com>" \
+	--trailer "Helped-by:C O Mitter <committer@example.com>"`will add the "Signed-off" trailer
+	and the "Helped-by" trailer in the commit message.)
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin/commit.c b/builtin/commit.c
index 739110c5a7f6..abbd136b27f0 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -113,6 +113,8 @@ static int config_commit_verbose = -1; /* unspecified */
 static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
 static char *sign_commit, *pathspec_from_file;
+struct child_process run_trailer = CHILD_PROCESS_INIT;
+static const char *trailer;
 
 /*
  * The default commit message cleanup mode will remove the lines
@@ -131,6 +133,17 @@ static struct strbuf message = STRBUF_INIT;
 
 static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
 
+static int opt_pass_trailer(const struct option *opt, const char *arg, int unset)
+{
+	if (unset) {
+		strvec_clear(&run_trailer.args);
+		return -1;
+	}
+	run_trailer.git_cmd = 1;
+	strvec_pushl(&run_trailer.args, "--trailer", arg, NULL);
+	return 0;
+}
+
 static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
 {
 	enum wt_status_format *value = (enum wt_status_format *)opt->value;
@@ -958,6 +971,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 
 	fclose(s->fp);
 
+	run_command(&run_trailer);
+
 	/*
 	 * Reject an attempt to record a non-merge empty commit without
 	 * explicit --allow-empty. In the cherry-pick case, it may be
@@ -1507,6 +1522,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
 		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+		OPT_CALLBACK(0, "trailer", &trailer, N_("trailer"), N_("trailer(s) to add"), opt_pass_trailer),
 		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
@@ -1577,6 +1593,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 			die(_("could not parse HEAD commit"));
 	}
 	verbose = -1; /* unspecified */
+	strvec_pushl(&run_trailer.args, "interpret-trailers",
+		"--in-place", "--where=end", git_path_commit_editmsg(), NULL);
 	argc = parse_and_validate_options(argc, argv, builtin_commit_options,
 					  builtin_commit_usage,
 					  prefix, current_head, &s);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index 6396897cc818..4b9ac4587d17 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -154,6 +154,26 @@ test_expect_success 'sign off' '
 
 '
 
+test_expect_success 'trailer' '
+	>file1 &&
+	git add file1 &&
+	git commit -s --trailer "Signed-off-by:C O Mitter1 <committer1@example.com>" \
+	--trailer "Helped-by:C O Mitter2 <committer2@example.com>"  \
+	--trailer "Reported-by:C O Mitter3 <committer3@example.com>" \
+	--trailer "Mentored-by:C O Mitter4 <committer4@example.com>" \
+	-m "hello" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -e "1,7d" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	Signed-off-by: C O Mitter <committer@example.com>
+	Signed-off-by: C O Mitter1 <committer1@example.com>
+	Helped-by: C O Mitter2 <committer2@example.com>
+	Reported-by: C O Mitter3 <committer3@example.com>
+	Mentored-by: C O Mitter4 <committer4@example.com>
+	EOF
+	test_cmp expected actual
+'
+
 test_expect_success 'multiple -m' '
 
 	>negative &&

base-commit: 13d7ab6b5d7929825b626f050b62a11241ea4945
-- 
gitgitgadget

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH] [GSOC] commit: provides multiple common signatures
  2021-03-11 15:03  0% ` Shourya Shukla
@ 2021-03-12 11:41  0%   ` ZheNing Hu
  0 siblings, 0 replies; 171+ results
From: ZheNing Hu @ 2021-03-12 11:41 UTC (permalink / raw)
  To: Shourya Shukla; +Cc: ZheNing Hu via GitGitGadget, Git List

Shourya Shukla <periperidip@gmail.com> 于2021年3月11日周四 下午11:05写道:
>
> Hey!
>

Hi!

> The idea seems very useful to me though I am not sure what others feel
> about this and whether Git is ready for such a thing or not. Keeping
> this concern aside, I will still review the patch due to my own interest
> in it as well.
>

haha, thank you! I'm glad that my whims can be recognized by you and help
git itself.

> On 11/03 07:16, ZheNing Hu via GitGitGadget wrote:
> > From: ZheNing Hu <adlternative@gmail.com>
> >
> > Similar to "Helped-by", "Reported-by", "Reviewed-by", "Mentored-by"
> > these signatures are often seen in git commit messages. After
>
> I think it will be better to rephrase the line so that it is easier to
> understand. It took me a couple of reads to figure out what you meant.
>
> Something like:
>
> Similar to "Signed-off-by", trailers such as "Reported-by", "Helped-by"
> and "Mentored-by" are also seen in Git commits.
>

It's exactly what you said.
My lack of English sometimes limits my expression.

> > referring to the simple implementation of `commit --signoff`
> > and `send-email -cc=" commiter <email>"`, I am considering
> > whether to provide multiple signature parameters from the
> > command line. I think this might help maintainers and
> > developers directly uses the shell to provide these signatures
> > instead of multiple times repetitive writing those trailers
> > each time.
>
> The above para is more appropriate for a cover letter than a commit
> message. Your thought process for the patch you sent is equally valuable
> but this does not belong in the commit message. Commit messages are more
> about what you did and any nuances that follow. You get me?
>
> Use 'git format-patch --cover-letter <...>' to create a cover letter for
> your patch.
>

I understand it now, because I use GGG, I will put this content into the
GGG conversation.

> > To achieve this goal, i refactored the `append_signoff` design and
> > provided `append_message` and `append_message_string_list` interfaces,
> > providing new ways to generate those various signatures.
>
> s/i/I
>
> Also, commit messages are generally written in the imperative tense when
> desciribing what you have done in the commit.
>

You're right.

> > Users now can use `commit -H "helper <eamil>"` to generate "Helped-by" trailer,
> > `commit -R "reviewer <eamil>"` to generate "Reviewed-by" trailer,
> > `commit -r "reporter <eamil> "`to generate "Reported-by" trailer,
> > `commit -M "mentor <eamil>"` to generate "Mentored-by" trailer.
>
> Multiple typos.
>
> > Signed-off-by: ZheNing Hu <adlternative@gmail.com>
>
> So, an improved commit message could be:
>
> -----8<-----
> commit: support multiple trailers from the command line
>
> Historically, Git has supported the 'Signed-off-by' commit trailer
> using the '--signoff' and the '-s' option from the command line. Extend
> this list to include other commonly used trailers viz., "Helped-by",
> "Reviewed-by", "Reported-by" and "Mentored-by". Introduce options '-H',
> '-R', '-r' and '-M' corresponding to the aforementioned trailers.
>
> While at it, add tests in the script 't7502-commit-porcelain.sh' and add
> information regarding these options in the Documentation of 'git
> commit'.

I think this paragraph may not be needed. Junio said in reply to one
of my previous patches that we may not need to add instructions about test
files and documents, because `git log -p --stat` can clearly see that what we
have done in testing and documentation.

> ----->8-----
>
> >     [GSOC] commit: provides multiple signatures from command line
> >
> >     I don’t know if my idea will satisfy everyone, I'm also thinking about
> >     whether we can provide a more generalized version (I think this idea can
> >     be extended: because users and developers have other signature methods
> >     that they want, such as "Based-on-patch-by") I hope someone can give me
> >     pointers (on the correctness of ideas or codes)
>
> It will be great if we let the user add customised options for the
> respective trailers but I think that trying to cater to such a large
> audience will only complicate the whole process and decrease the support
> avialable for the options/command. Apart from this, I think that the
> trailer "Reviewed-by" may not be that widely used and it would be better
> if we remove it from this patch.

Okay, I will delete it.

>
> >  Documentation/git-commit.txt |  24 +++++++-
> >  builtin/commit.c             |  63 +++++++++++++++++++++
> >  sequencer.c                  |  40 +++++++++----
> >  sequencer.h                  |   4 ++
> >  t/t7502-commit-porcelain.sh  | 106 +++++++++++++++++++++++++++++++++++
> >  5 files changed, 226 insertions(+), 11 deletions(-)
> >
> > diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> > index 17150fa7eabe..e1b528d70c1a 100644
> > --- a/Documentation/git-commit.txt
> > +++ b/Documentation/git-commit.txt
> > @@ -14,7 +14,9 @@ SYNOPSIS
> >          [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
> >          [--date=<date>] [--cleanup=<mode>] [--[no-]status]
> >          [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
> > -        [-S[<keyid>]] [--] [<pathspec>...]
> > +        [-S[<keyid>]] [--] [<pathspec>...] [(-H|--helped-by)=<address>...]
> > +        [(-R|--reviewed-by)=<address>...] [(-r|--reported-by)=<address>...]
> > +        [(-M|--mentored)=<address>...]
> >
> >  DESCRIPTION
> >  -----------
> > @@ -166,6 +168,26 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
> >
> >  include::signoff-option.txt[]
> >
> > +-H=<address>...::
> > +--helped-by=<address>...::
> > +     Add one or more `Helped-by` trailer by the committer at the end of the commit
> > +     log message.
> > +
> > +-R=<address>...::
> > +--reviewed-by=<address>...::
> > +     Add one or more `Reviewed-by` trailer by the committer at the end of the commit
> > +     log message.
> > +
> > +-r=<address>...::
> > +--reported-by=<address>...::
> > +     Add one or more `Reported-by` trailer by the committer at the end of the commit
> > +     log message.
> > +
> > +-M=<address>...::
> > +--mentored-by=<address>...::
> > +     Add one or more `Mentored-by` trailer by the committer at the end of the commit
> > +     log message.
>
> Oh! I did not think you had added long forms of these options and was
> about to comment on that. Good that you added. Do talk about them as
> well in the commit message.
>

Yes, I forgot to mention these long formats in the commit message.

> >  -n::
> >  --no-verify::
> >       This option bypasses the pre-commit and commit-msg hooks.
> > diff --git a/builtin/commit.c b/builtin/commit.c
> > index 739110c5a7f6..4b312af03181 100644
> > --- a/builtin/commit.c
> > +++ b/builtin/commit.c
> > @@ -113,6 +113,10 @@ static int config_commit_verbose = -1; /* unspecified */
> >  static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
> >  static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
> >  static char *sign_commit, *pathspec_from_file;
> > +static struct string_list helped_by = STRING_LIST_INIT_NODUP;
> > +static struct string_list mentored_by = STRING_LIST_INIT_NODUP;
> > +static struct string_list reviewed_by = STRING_LIST_INIT_NODUP;
> > +static struct string_list reported_by = STRING_LIST_INIT_NODUP;
>
> Good that you kept the variables as 'string_list's instead of a usual
> 'char*'.
>
> >  /*
> >   * The default commit message cleanup mode will remove the lines
> > @@ -829,6 +833,20 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
> >       if (signoff)
> >               append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
> >
> > +     if(helped_by.items)
> > +             append_message_string_list(&sb, "Helped-by: ", &helped_by, ignore_non_trailer(sb.buf, sb.len), 0);
> > +     if(reviewed_by.items)
> > +             append_message_string_list(&sb, "Reviewed-by: ", &reviewed_by, ignore_non_trailer(sb.buf, sb.len), 0);
> > +     if(reported_by.items)
> > +             append_message_string_list(&sb, "Reported-by: ", &reported_by, ignore_non_trailer(sb.buf, sb.len), 0);
> > +     if(mentored_by.items)
> > +             append_message_string_list(&sb, "Mentored-by: ", &mentored_by, ignore_non_trailer(sb.buf, sb.len), 0);
>
> I think this part will look prettier if you wrap around the text. For
> code segments, the wrap around limit is 80 chars. For commit messages
> its 72 chars. Wrap around means that as soon as you hit N number of
> characters, you proceed to the next(new) line.
>

Fine.

> > +     string_list_clear(&helped_by, 0);
> > +     string_list_clear(&reviewed_by, 0);
> > +     string_list_clear(&reported_by, 0);
> > +     string_list_clear(&mentored_by, 0);
> > +
> >       if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
> >               die_errno(_("could not write commit template"));
> >
> > @@ -1490,6 +1508,42 @@ static int git_commit_config(const char *k, const char *v, void *cb)
> >       return git_status_config(k, v, s);
> >  }
> >
> > +static int help_callback(const struct option *opt, const char *arg, int unset)
> > +{
> > +     if (unset)
> > +             string_list_clear(&helped_by, 0);
> > +     else
> > +             string_list_append(&helped_by, arg);
> > +     return 0;
> > +}
> > +
> > +static int review_callback(const struct option *opt, const char *arg, int unset)
> > +{
> > +     if (unset)
> > +             string_list_clear(&reviewed_by, 0);
> > +     else
> > +             string_list_append(&reviewed_by, arg);
> > +     return 0;
> > +}
> > +
> > +static int report_callback(const struct option *opt, const char *arg, int unset)
> > +{
> > +     if (unset)
> > +             string_list_clear(&reported_by, 0);
> > +     else
> > +             string_list_append(&reported_by, arg);
> > +     return 0;
> > +}
> > +
> > +static int mentor_callback(const struct option *opt, const char *arg, int unset)
> > +{
> > +     if (unset)
> > +             string_list_clear(&mentored_by, 0);
> > +     else
> > +             string_list_append(&mentored_by, arg);
> > +     return 0;
> > +}
> >  int cmd_commit(int argc, const char **argv, const char *prefix)
> >  {
> >       static struct wt_status s;
> > @@ -1507,6 +1561,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
> >               OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
> >               OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
> >               OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
> > +             OPT_CALLBACK('H', "helped-by", NULL, N_("email"), N_("add a Helped-by trailer"), help_callback),
> > +             OPT_CALLBACK('r', "reported-by", NULL, N_("email"), N_("add a Reported-by trailer"), report_callback),
> > +             OPT_CALLBACK('R', "reviewed-by", NULL, N_("email"), N_("add a Reviewed-by trailer"), review_callback),
> > +             OPT_CALLBACK('M', "mentored-by", NULL, N_("email"), N_("add a Mentored-by trailer"), mentor_callback),
>
> It would be lovely if you could line wrap these above additions too!
>
> >               OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
> >               OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
> >               OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
> > @@ -1561,6 +1619,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
> >       struct commit_extra_header *extra = NULL;
> >       struct strbuf err = STRBUF_INIT;
> >
> > +     helped_by.strdup_strings = 1;
> > +     reviewed_by.strdup_strings = 1;
> > +     reported_by.strdup_strings = 1;
> > +     mentored_by.strdup_strings = 1;
> > +
> >       if (argc == 2 && !strcmp(argv[1], "-h"))
> >               usage_with_options(builtin_commit_usage, builtin_commit_options);
> >
> > diff --git a/sequencer.c b/sequencer.c
> > index d2332d3e1787..528daf9df252 100644
> > --- a/sequencer.c
> > +++ b/sequencer.c
> > @@ -4668,16 +4668,12 @@ int sequencer_pick_revisions(struct repository *r,
> >       return res;
> >  }
> >
> > -void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> > +void append_message(struct strbuf *msgbuf, struct strbuf *sob,
> > +                     size_t ignore_footer, unsigned flag)
>
> Its nice to see that you generalised the pre-exisiting function instead
> of creating a new one(s) for the new trailers. Good.
>
> It will be better to name 'struct strbuf *sob' to something more
> generic, maybe 'struct strbuf *trailer' since 'sob' stands for
> 'Signed-off-by' and since the function is becoming more generic, its
> contents should too.
>
When I wrote it, I didn’t realize that sob refers to the abbreviation of
'Signed-off-by', I will change it.
> >  {
> >       unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
> > -     struct strbuf sob = STRBUF_INIT;
> >       int has_footer;
> >
> > -     strbuf_addstr(&sob, sign_off_header);
> > -     strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
> > -     strbuf_addch(&sob, '\n');
> > -
> >       if (!ignore_footer)
> >               strbuf_complete_line(msgbuf);
> >
> > @@ -4685,11 +4681,11 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> >        * If the whole message buffer is equal to the sob, pretend that we
> >        * found a conforming footer with a matching sob
> >        */
> > -     if (msgbuf->len - ignore_footer == sob.len &&
> > -         !strncmp(msgbuf->buf, sob.buf, sob.len))
> > +     if (msgbuf->len - ignore_footer == sob->len &&
> > +         !strncmp(msgbuf->buf, sob->buf, sob->len))
> >               has_footer = 3;
> >       else
> > -             has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
> > +             has_footer = has_conforming_footer(msgbuf, sob, ignore_footer);
>
> Again, rename the variables.
>
> >       if (!has_footer) {
> >               const char *append_newlines = NULL;
> > @@ -4723,8 +4719,32 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> >
> >       if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
> >               strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
> > -                             sob.buf, sob.len);
> > +                             sob->buf, sob->len);
> > +}
> > +void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> > +{
> > +     struct strbuf sob = STRBUF_INIT;
> > +     strbuf_addstr(&sob, sign_off_header);
> > +     strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
> > +     strbuf_addch(&sob, '\n');
> > +     append_message(msgbuf, &sob, ignore_footer, flag);
> > +     strbuf_release(&sob);
> > +}
>
> I think it will be nice if you could use a flag to denote whether the
> entity to be appended is a 'sign-off' or not. This way when say the
> variable 'int signoff' is 1, then use the above part in the
> 'append_message()' function otherwise go with the flow that exists.
>
> > +void append_message_string_list(struct strbuf *msgbuf, const char *header,
> > +             struct string_list *sobs, size_t ignore_footer, unsigned flag) {
> > +     int i;
> > +     struct strbuf sob = STRBUF_INIT;
> > +
> > +     for ( i = 0; i < sobs->nr; i++)
> > +     {
> > +             strbuf_addstr(&sob, header);
> > +             strbuf_addstr(&sob, sobs->items[i].string);
> > +             strbuf_addch(&sob, '\n');
> > +             append_message(msgbuf, &sob, ignore_footer, flag);
> > +             strbuf_reset(&sob);
> > +     }
> >       strbuf_release(&sob);
> >  }
>
> Similarly, here, if 'signoff = 0' then the above part goes on. Or
> another alternative can be to create a 'append_message_helper()' and
> shift the current contents of 'append_message()' into that and use the
> above function to work as per the value of signoff.
>
> So a possible flow can be:
>
> void append_message_string_list(...params...) {
>
>         if (signoff) {
>                 ..excecute the necessary segments and call the
>                 'append_message_helper()' function...
>         } else {
>                 ..similarly here..
>         }
> }
>
> This way we save ourselves some extra functions.

May some thing like this:

if (signoff)
        append_message_string_list(&sb, "Signed-off-by: ", NULL,
                   ignore_non_trailer(sb.buf, sb.len), 0);

And then we could judge in `append_message_string_list`
if the arguement `string_list *trailers` set to NULL. If so,
we do something similar to `append_signoff`, otherwise,
we carry out other situations.

So that we can delete the `append_signoff` and user can only
need to call  `append_message_string_list` in any where, I don't
 know if it is better.

>
> > diff --git a/sequencer.h b/sequencer.h
> > index f8b2e4ab8527..b24e274f4c62 100644
> > --- a/sequencer.h
> > +++ b/sequencer.h
> > @@ -174,6 +174,10 @@ int todo_list_rearrange_squash(struct todo_list *todo_list);
> >   * and the new signoff will be spliced into the buffer before those bytes.
> >   */
> >  void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
> > +void append_message(struct strbuf *msgbuf, struct strbuf *sob,
> > +             size_t ignore_footer, unsigned flag);
> > +void append_message_string_list(struct strbuf *msgbuf, const char*header,
> > +             struct string_list *sobs, size_t ignore_footer, unsigned flag);
> >
> >  void append_conflicts_hint(struct index_state *istate,
> >               struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);
>
> Then, these would have to be corrected too.
>
> > diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
> > index 6396897cc818..40823152a51c 100755
> > --- a/t/t7502-commit-porcelain.sh
> > +++ b/t/t7502-commit-porcelain.sh
> > @@ -154,6 +154,112 @@ test_expect_success 'sign off' '
> >
> >  '
>
> I feel that the tests deserve a commit of their own. A follow-up commit
> in this patch.
>
> > +test_expect_success 'helped-by' '
> > +
> > +     >file1 &&
> > +     git add file1 &&
> > +     git commit --helped-by="foo <bar@frotz>" \
> > +     --helped-by="foo2 <bar2@frotz>" -m "thank you" &&
> > +     git cat-file commit HEAD >commit.msg &&
> > +     sed -ne "s/Helped-by: //p" commit.msg >actual &&
> > +     cat >expected <<-\EOF &&
> > +     foo <bar@frotz>
> > +     foo2 <bar2@frotz>
> > +     EOF
> > +     test_cmp expected actual
> > +
>
> Was this extra line feed intentional? It looks odd here and other test
> (scripts) don't have this. Though, this test script seems to have many
> tests which have an extra line feed. My suggestion would be to eliminate
> it. Maybe this script is old and hasn't been reviewed for a cleanup in
> a long time.
>

I might want to keep the same format with the last "sign off" test. Now it
seems that this is not necessary.

> > +'
> > +
> > +test_expect_success 'reported-by' '
> > +
> > +     >file2 &&
> > +     git add file2 &&
> > +     git commit --reported-by="foo <bar@frotz>" \
> > +     --reported-by="foo2 <bar2@frotz>" -m "thank you" &&
> > +     git cat-file commit HEAD >commit.msg &&
> > +     sed -ne "s/Reported-by: //p" commit.msg >actual &&
> > +     cat >expected <<-\EOF &&
> > +     foo <bar@frotz>
> > +     foo2 <bar2@frotz>
> > +     EOF
> > +     test_cmp expected actual
> > +
>
> Similarly here and in the parts that follow.
>
> <...>
>
> This seems like a good patch to me but more experienced members will be
> able to comment better I think. Good job anyways.
>

Your comments and encouragement are of great help to me :)

> Regards,
> Shourya Shukla
>

Regards,
ZheNing Hu

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] [GSOC] commit: provides multiple common signatures
  2021-03-11  7:16  2% [PATCH] [GSOC] commit: provides multiple common signatures ZheNing Hu via GitGitGadget
  2021-03-11 15:03  0% ` Shourya Shukla
@ 2021-03-11 17:28  0% ` Junio C Hamano
  2021-03-12 15:54  5% ` [PATCH v2] [GSOC] commit: add trailer command ZheNing Hu via GitGitGadget
  2 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2021-03-11 17:28 UTC (permalink / raw)
  To: ZheNing Hu via GitGitGadget
  Cc: git, Bradley M. Kuhn, Brandon Casey, ZheNing Hu

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

> From: ZheNing Hu <adlternative@gmail.com>
>
> Similar to "Helped-by", "Reported-by", "Reviewed-by", "Mentored-by"
> these signatures are often seen in git commit messages. After
> referring to the simple implementation of `commit --signoff`
> and `send-email -cc=" commiter <email>"`, I am considering
> whether to provide multiple signature parameters from the
> command line.
> + ...
> +	>file6 &&
> +	git add file6 &&
> +	git commit -H "foo <bar@frotz>" \
> +	-R "foo2 <bar2@frotz>" \
> +	-M "foo3 <bar3@frotz>" \
> +	-r "foo4 <bar4@frotz>" -s -m "thank you" &&

Firm NAK.

Especially, not in this form that squats on short-and-sweet single
letter option names only to support the convention of this single
project (namely, Git).

cf. https://lore.kernel.org/git/20200824061156.1929850-1-espeer@gmail.com/

Thanks.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] [GSOC] commit: provides multiple common signatures
  2021-03-11  7:16  2% [PATCH] [GSOC] commit: provides multiple common signatures ZheNing Hu via GitGitGadget
@ 2021-03-11 15:03  0% ` Shourya Shukla
  2021-03-12 11:41  0%   ` ZheNing Hu
  2021-03-11 17:28  0% ` Junio C Hamano
  2021-03-12 15:54  5% ` [PATCH v2] [GSOC] commit: add trailer command ZheNing Hu via GitGitGadget
  2 siblings, 1 reply; 171+ results
From: Shourya Shukla @ 2021-03-11 15:03 UTC (permalink / raw)
  To: ZheNing Hu via GitGitGadget; +Cc: git

Hey!

The idea seems very useful to me though I am not sure what others feel
about this and whether Git is ready for such a thing or not. Keeping
this concern aside, I will still review the patch due to my own interest
in it as well.

On 11/03 07:16, ZheNing Hu via GitGitGadget wrote:
> From: ZheNing Hu <adlternative@gmail.com>
> 
> Similar to "Helped-by", "Reported-by", "Reviewed-by", "Mentored-by"
> these signatures are often seen in git commit messages. After

I think it will be better to rephrase the line so that it is easier to
understand. It took me a couple of reads to figure out what you meant.

Something like:

Similar to "Signed-off-by", trailers such as "Reported-by", "Helped-by"
and "Mentored-by" are also seen in Git commits.

> referring to the simple implementation of `commit --signoff`
> and `send-email -cc=" commiter <email>"`, I am considering
> whether to provide multiple signature parameters from the
> command line. I think this might help maintainers and
> developers directly uses the shell to provide these signatures
> instead of multiple times repetitive writing those trailers
> each time.

The above para is more appropriate for a cover letter than a commit
message. Your thought process for the patch you sent is equally valuable
but this does not belong in the commit message. Commit messages are more
about what you did and any nuances that follow. You get me?

Use 'git format-patch --cover-letter <...>' to create a cover letter for
your patch.

> To achieve this goal, i refactored the `append_signoff` design and
> provided `append_message` and `append_message_string_list` interfaces,
> providing new ways to generate those various signatures.

s/i/I

Also, commit messages are generally written in the imperative tense when
desciribing what you have done in the commit.

> Users now can use `commit -H "helper <eamil>"` to generate "Helped-by" trailer,
> `commit -R "reviewer <eamil>"` to generate "Reviewed-by" trailer,
> `commit -r "reporter <eamil> "`to generate "Reported-by" trailer,
> `commit -M "mentor <eamil>"` to generate "Mentored-by" trailer.

Multiple typos.

> Signed-off-by: ZheNing Hu <adlternative@gmail.com>

So, an improved commit message could be:

-----8<-----
commit: support multiple trailers from the command line

Historically, Git has supported the 'Signed-off-by' commit trailer
using the '--signoff' and the '-s' option from the command line. Extend
this list to include other commonly used trailers viz., "Helped-by",
"Reviewed-by", "Reported-by" and "Mentored-by". Introduce options '-H',
'-R', '-r' and '-M' corresponding to the aforementioned trailers.

While at it, add tests in the script 't7502-commit-porcelain.sh' and add
information regarding these options in the Documentation of 'git
commit'.
----->8-----

>     [GSOC] commit: provides multiple signatures from command line
>     
>     I don’t know if my idea will satisfy everyone, I'm also thinking about
>     whether we can provide a more generalized version (I think this idea can
>     be extended: because users and developers have other signature methods
>     that they want, such as "Based-on-patch-by") I hope someone can give me
>     pointers (on the correctness of ideas or codes)

It will be great if we let the user add customised options for the
respective trailers but I think that trying to cater to such a large
audience will only complicate the whole process and decrease the support
avialable for the options/command. Apart from this, I think that the
trailer "Reviewed-by" may not be that widely used and it would be better
if we remove it from this patch.

>  Documentation/git-commit.txt |  24 +++++++-
>  builtin/commit.c             |  63 +++++++++++++++++++++
>  sequencer.c                  |  40 +++++++++----
>  sequencer.h                  |   4 ++
>  t/t7502-commit-porcelain.sh  | 106 +++++++++++++++++++++++++++++++++++
>  5 files changed, 226 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> index 17150fa7eabe..e1b528d70c1a 100644
> --- a/Documentation/git-commit.txt
> +++ b/Documentation/git-commit.txt
> @@ -14,7 +14,9 @@ SYNOPSIS
>  	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
>  	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
>  	   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
> -	   [-S[<keyid>]] [--] [<pathspec>...]
> +	   [-S[<keyid>]] [--] [<pathspec>...] [(-H|--helped-by)=<address>...]
> +	   [(-R|--reviewed-by)=<address>...] [(-r|--reported-by)=<address>...]
> +	   [(-M|--mentored)=<address>...]
>  
>  DESCRIPTION
>  -----------
> @@ -166,6 +168,26 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
>  
>  include::signoff-option.txt[]
>  
> +-H=<address>...::
> +--helped-by=<address>...::
> +	Add one or more `Helped-by` trailer by the committer at the end of the commit
> +	log message.
> +
> +-R=<address>...::
> +--reviewed-by=<address>...::
> +	Add one or more `Reviewed-by` trailer by the committer at the end of the commit
> +	log message.
> +
> +-r=<address>...::
> +--reported-by=<address>...::
> +	Add one or more `Reported-by` trailer by the committer at the end of the commit
> +	log message.
> +
> +-M=<address>...::
> +--mentored-by=<address>...::
> +	Add one or more `Mentored-by` trailer by the committer at the end of the commit
> +	log message.

Oh! I did not think you had added long forms of these options and was
about to comment on that. Good that you added. Do talk about them as
well in the commit message.

>  -n::
>  --no-verify::
>  	This option bypasses the pre-commit and commit-msg hooks.
> diff --git a/builtin/commit.c b/builtin/commit.c
> index 739110c5a7f6..4b312af03181 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -113,6 +113,10 @@ static int config_commit_verbose = -1; /* unspecified */
>  static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
>  static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
>  static char *sign_commit, *pathspec_from_file;
> +static struct string_list helped_by = STRING_LIST_INIT_NODUP;
> +static struct string_list mentored_by = STRING_LIST_INIT_NODUP;
> +static struct string_list reviewed_by = STRING_LIST_INIT_NODUP;
> +static struct string_list reported_by = STRING_LIST_INIT_NODUP;

Good that you kept the variables as 'string_list's instead of a usual
'char*'.

>  /*
>   * The default commit message cleanup mode will remove the lines
> @@ -829,6 +833,20 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
>  	if (signoff)
>  		append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
>  
> +	if(helped_by.items)
> +		append_message_string_list(&sb, "Helped-by: ", &helped_by, ignore_non_trailer(sb.buf, sb.len), 0);
> +	if(reviewed_by.items)
> +		append_message_string_list(&sb, "Reviewed-by: ", &reviewed_by, ignore_non_trailer(sb.buf, sb.len), 0);
> +	if(reported_by.items)
> +		append_message_string_list(&sb, "Reported-by: ", &reported_by, ignore_non_trailer(sb.buf, sb.len), 0);
> +	if(mentored_by.items)
> +		append_message_string_list(&sb, "Mentored-by: ", &mentored_by, ignore_non_trailer(sb.buf, sb.len), 0);

I think this part will look prettier if you wrap around the text. For
code segments, the wrap around limit is 80 chars. For commit messages
its 72 chars. Wrap around means that as soon as you hit N number of
characters, you proceed to the next(new) line.

> +	string_list_clear(&helped_by, 0);
> +	string_list_clear(&reviewed_by, 0);
> +	string_list_clear(&reported_by, 0);
> +	string_list_clear(&mentored_by, 0);
> +
>  	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
>  		die_errno(_("could not write commit template"));
>  
> @@ -1490,6 +1508,42 @@ static int git_commit_config(const char *k, const char *v, void *cb)
>  	return git_status_config(k, v, s);
>  }
>  
> +static int help_callback(const struct option *opt, const char *arg, int unset)
> +{
> +	if (unset)
> +		string_list_clear(&helped_by, 0);
> +	else
> +		string_list_append(&helped_by, arg);
> +	return 0;
> +}
> +
> +static int review_callback(const struct option *opt, const char *arg, int unset)
> +{
> +	if (unset)
> +		string_list_clear(&reviewed_by, 0);
> +	else
> +		string_list_append(&reviewed_by, arg);
> +	return 0;
> +}
> +
> +static int report_callback(const struct option *opt, const char *arg, int unset)
> +{
> +	if (unset)
> +		string_list_clear(&reported_by, 0);
> +	else
> +		string_list_append(&reported_by, arg);
> +	return 0;
> +}
> +
> +static int mentor_callback(const struct option *opt, const char *arg, int unset)
> +{
> +	if (unset)
> +		string_list_clear(&mentored_by, 0);
> +	else
> +		string_list_append(&mentored_by, arg);
> +	return 0;
> +}
>  int cmd_commit(int argc, const char **argv, const char *prefix)
>  {
>  	static struct wt_status s;
> @@ -1507,6 +1561,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
>  		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
>  		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
>  		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
> +		OPT_CALLBACK('H', "helped-by", NULL, N_("email"), N_("add a Helped-by trailer"), help_callback),
> +		OPT_CALLBACK('r', "reported-by", NULL, N_("email"), N_("add a Reported-by trailer"), report_callback),
> +		OPT_CALLBACK('R', "reviewed-by", NULL, N_("email"), N_("add a Reviewed-by trailer"), review_callback),
> +		OPT_CALLBACK('M', "mentored-by", NULL, N_("email"), N_("add a Mentored-by trailer"), mentor_callback),

It would be lovely if you could line wrap these above additions too!

>  		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
>  		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
>  		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
> @@ -1561,6 +1619,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
>  	struct commit_extra_header *extra = NULL;
>  	struct strbuf err = STRBUF_INIT;
>  
> +	helped_by.strdup_strings = 1;
> +	reviewed_by.strdup_strings = 1;
> +	reported_by.strdup_strings = 1;
> +	mentored_by.strdup_strings = 1;
> +
>  	if (argc == 2 && !strcmp(argv[1], "-h"))
>  		usage_with_options(builtin_commit_usage, builtin_commit_options);
>  
> diff --git a/sequencer.c b/sequencer.c
> index d2332d3e1787..528daf9df252 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -4668,16 +4668,12 @@ int sequencer_pick_revisions(struct repository *r,
>  	return res;
>  }
>  
> -void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> +void append_message(struct strbuf *msgbuf, struct strbuf *sob,
> +			size_t ignore_footer, unsigned flag)

Its nice to see that you generalised the pre-exisiting function instead
of creating a new one(s) for the new trailers. Good.

It will be better to name 'struct strbuf *sob' to something more
generic, maybe 'struct strbuf *trailer' since 'sob' stands for
'Signed-off-by' and since the function is becoming more generic, its
contents should too.

>  {
>  	unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
> -	struct strbuf sob = STRBUF_INIT;
>  	int has_footer;
>  
> -	strbuf_addstr(&sob, sign_off_header);
> -	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
> -	strbuf_addch(&sob, '\n');
> -
>  	if (!ignore_footer)
>  		strbuf_complete_line(msgbuf);
>  
> @@ -4685,11 +4681,11 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
>  	 * If the whole message buffer is equal to the sob, pretend that we
>  	 * found a conforming footer with a matching sob
>  	 */
> -	if (msgbuf->len - ignore_footer == sob.len &&
> -	    !strncmp(msgbuf->buf, sob.buf, sob.len))
> +	if (msgbuf->len - ignore_footer == sob->len &&
> +	    !strncmp(msgbuf->buf, sob->buf, sob->len))
>  		has_footer = 3;
>  	else
> -		has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
> +		has_footer = has_conforming_footer(msgbuf, sob, ignore_footer);

Again, rename the variables.

>  	if (!has_footer) {
>  		const char *append_newlines = NULL;
> @@ -4723,8 +4719,32 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
>  
>  	if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
>  		strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
> -				sob.buf, sob.len);
> +				sob->buf, sob->len);
> +}
> +void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
> +{
> +	struct strbuf sob = STRBUF_INIT;
> +	strbuf_addstr(&sob, sign_off_header);
> +	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
> +	strbuf_addch(&sob, '\n');
> +	append_message(msgbuf, &sob, ignore_footer, flag);
> +	strbuf_release(&sob);
> +}

I think it will be nice if you could use a flag to denote whether the
entity to be appended is a 'sign-off' or not. This way when say the
variable 'int signoff' is 1, then use the above part in the
'append_message()' function otherwise go with the flow that exists.

> +void append_message_string_list(struct strbuf *msgbuf, const char *header,
> +		struct string_list *sobs, size_t ignore_footer, unsigned flag) {
> +	int i;
> +	struct strbuf sob = STRBUF_INIT;
> +
> +	for ( i = 0; i < sobs->nr; i++)
> +	{
> +		strbuf_addstr(&sob, header);
> +		strbuf_addstr(&sob, sobs->items[i].string);
> +		strbuf_addch(&sob, '\n');
> +		append_message(msgbuf, &sob, ignore_footer, flag);
> +		strbuf_reset(&sob);
> +	}
>  	strbuf_release(&sob);
>  }

Similarly, here, if 'signoff = 0' then the above part goes on. Or
another alternative can be to create a 'append_message_helper()' and
shift the current contents of 'append_message()' into that and use the
above function to work as per the value of signoff.

So a possible flow can be:

void append_message_string_list(...params...) {

	if (signoff) {
		..excecute the necessary segments and call the
		'append_message_helper()' function...
	} else {
		..similarly here..
	}
}

This way we save ourselves some extra functions.

> diff --git a/sequencer.h b/sequencer.h
> index f8b2e4ab8527..b24e274f4c62 100644
> --- a/sequencer.h
> +++ b/sequencer.h
> @@ -174,6 +174,10 @@ int todo_list_rearrange_squash(struct todo_list *todo_list);
>   * and the new signoff will be spliced into the buffer before those bytes.
>   */
>  void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
> +void append_message(struct strbuf *msgbuf, struct strbuf *sob,
> +		size_t ignore_footer, unsigned flag);
> +void append_message_string_list(struct strbuf *msgbuf, const char*header,
> +		struct string_list *sobs, size_t ignore_footer, unsigned flag);
>  
>  void append_conflicts_hint(struct index_state *istate,
>  		struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);

Then, these would have to be corrected too.

> diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
> index 6396897cc818..40823152a51c 100755
> --- a/t/t7502-commit-porcelain.sh
> +++ b/t/t7502-commit-porcelain.sh
> @@ -154,6 +154,112 @@ test_expect_success 'sign off' '
>  
>  '

I feel that the tests deserve a commit of their own. A follow-up commit
in this patch.

> +test_expect_success 'helped-by' '
> +
> +	>file1 &&
> +	git add file1 &&
> +	git commit --helped-by="foo <bar@frotz>" \
> +	--helped-by="foo2 <bar2@frotz>" -m "thank you" &&
> +	git cat-file commit HEAD >commit.msg &&
> +	sed -ne "s/Helped-by: //p" commit.msg >actual &&
> +	cat >expected <<-\EOF &&
> +	foo <bar@frotz>
> +	foo2 <bar2@frotz>
> +	EOF
> +	test_cmp expected actual
> +

Was this extra line feed intentional? It looks odd here and other test
(scripts) don't have this. Though, this test script seems to have many
tests which have an extra line feed. My suggestion would be to eliminate
it. Maybe this script is old and hasn't been reviewed for a cleanup in
a long time.

> +'
> +
> +test_expect_success 'reported-by' '
> +
> +	>file2 &&
> +	git add file2 &&
> +	git commit --reported-by="foo <bar@frotz>" \
> +	--reported-by="foo2 <bar2@frotz>" -m "thank you" &&
> +	git cat-file commit HEAD >commit.msg &&
> +	sed -ne "s/Reported-by: //p" commit.msg >actual &&
> +	cat >expected <<-\EOF &&
> +	foo <bar@frotz>
> +	foo2 <bar2@frotz>
> +	EOF
> +	test_cmp expected actual
> +

Similarly here and in the parts that follow.

<...>

This seems like a good patch to me but more experienced members will be
able to comment better I think. Good job anyways.

Regards,
Shourya Shukla


^ permalink raw reply	[relevance 0%]

* [PATCH] [GSOC] commit: provides multiple common signatures
@ 2021-03-11  7:16  2% ZheNing Hu via GitGitGadget
  2021-03-11 15:03  0% ` Shourya Shukla
                   ` (2 more replies)
  0 siblings, 3 replies; 171+ results
From: ZheNing Hu via GitGitGadget @ 2021-03-11  7:16 UTC (permalink / raw)
  To: git; +Cc: Bradley M. Kuhn, Junio C Hamano, Brandon Casey, ZheNing Hu,
	ZheNing Hu

From: ZheNing Hu <adlternative@gmail.com>

Similar to "Helped-by", "Reported-by", "Reviewed-by", "Mentored-by"
these signatures are often seen in git commit messages. After
referring to the simple implementation of `commit --signoff`
and `send-email -cc=" commiter <email>"`, I am considering
whether to provide multiple signature parameters from the
command line. I think this might help maintainers and
developers directly uses the shell to provide these signatures
instead of multiple times repetitive writing those trailers
each time.

To achieve this goal, i refactored the `append_signoff` design and
provided `append_message` and `append_message_string_list` interfaces,
providing new ways to generate those various signatures.

Users now can use `commit -H "helper <eamil>"` to generate "Helped-by" trailer,
`commit -R "reviewer <eamil>"` to generate "Reviewed-by" trailer,
`commit -r "reporter <eamil> "`to generate "Reported-by" trailer,
`commit -M "mentor <eamil>"` to generate "Mentored-by" trailer.

Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
    [GSOC] commit: provides multiple signatures from command line
    
    I don’t know if my idea will satisfy everyone, I'm also thinking about
    whether we can provide a more generalized version (I think this idea can
    be extended: because users and developers have other signature methods
    that they want, such as "Based-on-patch-by") I hope someone can give me
    pointers (on the correctness of ideas or codes)

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-901%2Fadlternative%2Fcommit-with-multiple-signatures-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-901/adlternative/commit-with-multiple-signatures-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/901

 Documentation/git-commit.txt |  24 +++++++-
 builtin/commit.c             |  63 +++++++++++++++++++++
 sequencer.c                  |  40 +++++++++----
 sequencer.h                  |   4 ++
 t/t7502-commit-porcelain.sh  | 106 +++++++++++++++++++++++++++++++++++
 5 files changed, 226 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 17150fa7eabe..e1b528d70c1a 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -14,7 +14,9 @@ SYNOPSIS
 	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
 	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
 	   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
-	   [-S[<keyid>]] [--] [<pathspec>...]
+	   [-S[<keyid>]] [--] [<pathspec>...] [(-H|--helped-by)=<address>...]
+	   [(-R|--reviewed-by)=<address>...] [(-r|--reported-by)=<address>...]
+	   [(-M|--mentored)=<address>...]
 
 DESCRIPTION
 -----------
@@ -166,6 +168,26 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 
 include::signoff-option.txt[]
 
+-H=<address>...::
+--helped-by=<address>...::
+	Add one or more `Helped-by` trailer by the committer at the end of the commit
+	log message.
+
+-R=<address>...::
+--reviewed-by=<address>...::
+	Add one or more `Reviewed-by` trailer by the committer at the end of the commit
+	log message.
+
+-r=<address>...::
+--reported-by=<address>...::
+	Add one or more `Reported-by` trailer by the committer at the end of the commit
+	log message.
+
+-M=<address>...::
+--mentored-by=<address>...::
+	Add one or more `Mentored-by` trailer by the committer at the end of the commit
+	log message.
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin/commit.c b/builtin/commit.c
index 739110c5a7f6..4b312af03181 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -113,6 +113,10 @@ static int config_commit_verbose = -1; /* unspecified */
 static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
 static char *sign_commit, *pathspec_from_file;
+static struct string_list helped_by = STRING_LIST_INIT_NODUP;
+static struct string_list mentored_by = STRING_LIST_INIT_NODUP;
+static struct string_list reviewed_by = STRING_LIST_INIT_NODUP;
+static struct string_list reported_by = STRING_LIST_INIT_NODUP;
 
 /*
  * The default commit message cleanup mode will remove the lines
@@ -829,6 +833,20 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	if (signoff)
 		append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
 
+	if(helped_by.items)
+		append_message_string_list(&sb, "Helped-by: ", &helped_by, ignore_non_trailer(sb.buf, sb.len), 0);
+	if(reviewed_by.items)
+		append_message_string_list(&sb, "Reviewed-by: ", &reviewed_by, ignore_non_trailer(sb.buf, sb.len), 0);
+	if(reported_by.items)
+		append_message_string_list(&sb, "Reported-by: ", &reported_by, ignore_non_trailer(sb.buf, sb.len), 0);
+	if(mentored_by.items)
+		append_message_string_list(&sb, "Mentored-by: ", &mentored_by, ignore_non_trailer(sb.buf, sb.len), 0);
+
+	string_list_clear(&helped_by, 0);
+	string_list_clear(&reviewed_by, 0);
+	string_list_clear(&reported_by, 0);
+	string_list_clear(&mentored_by, 0);
+
 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
 		die_errno(_("could not write commit template"));
 
@@ -1490,6 +1508,42 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 	return git_status_config(k, v, s);
 }
 
+static int help_callback(const struct option *opt, const char *arg, int unset)
+{
+	if (unset)
+		string_list_clear(&helped_by, 0);
+	else
+		string_list_append(&helped_by, arg);
+	return 0;
+}
+
+static int review_callback(const struct option *opt, const char *arg, int unset)
+{
+	if (unset)
+		string_list_clear(&reviewed_by, 0);
+	else
+		string_list_append(&reviewed_by, arg);
+	return 0;
+}
+
+static int report_callback(const struct option *opt, const char *arg, int unset)
+{
+	if (unset)
+		string_list_clear(&reported_by, 0);
+	else
+		string_list_append(&reported_by, arg);
+	return 0;
+}
+
+static int mentor_callback(const struct option *opt, const char *arg, int unset)
+{
+	if (unset)
+		string_list_clear(&mentored_by, 0);
+	else
+		string_list_append(&mentored_by, arg);
+	return 0;
+}
+
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
 	static struct wt_status s;
@@ -1507,6 +1561,10 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
 		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+		OPT_CALLBACK('H', "helped-by", NULL, N_("email"), N_("add a Helped-by trailer"), help_callback),
+		OPT_CALLBACK('r', "reported-by", NULL, N_("email"), N_("add a Reported-by trailer"), report_callback),
+		OPT_CALLBACK('R', "reviewed-by", NULL, N_("email"), N_("add a Reviewed-by trailer"), review_callback),
+		OPT_CALLBACK('M', "mentored-by", NULL, N_("email"), N_("add a Mentored-by trailer"), mentor_callback),
 		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
@@ -1561,6 +1619,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 	struct commit_extra_header *extra = NULL;
 	struct strbuf err = STRBUF_INIT;
 
+	helped_by.strdup_strings = 1;
+	reviewed_by.strdup_strings = 1;
+	reported_by.strdup_strings = 1;
+	mentored_by.strdup_strings = 1;
+
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_commit_usage, builtin_commit_options);
 
diff --git a/sequencer.c b/sequencer.c
index d2332d3e1787..528daf9df252 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -4668,16 +4668,12 @@ int sequencer_pick_revisions(struct repository *r,
 	return res;
 }
 
-void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
+void append_message(struct strbuf *msgbuf, struct strbuf *sob,
+			size_t ignore_footer, unsigned flag)
 {
 	unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
-	struct strbuf sob = STRBUF_INIT;
 	int has_footer;
 
-	strbuf_addstr(&sob, sign_off_header);
-	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
-	strbuf_addch(&sob, '\n');
-
 	if (!ignore_footer)
 		strbuf_complete_line(msgbuf);
 
@@ -4685,11 +4681,11 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
 	 * If the whole message buffer is equal to the sob, pretend that we
 	 * found a conforming footer with a matching sob
 	 */
-	if (msgbuf->len - ignore_footer == sob.len &&
-	    !strncmp(msgbuf->buf, sob.buf, sob.len))
+	if (msgbuf->len - ignore_footer == sob->len &&
+	    !strncmp(msgbuf->buf, sob->buf, sob->len))
 		has_footer = 3;
 	else
-		has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
+		has_footer = has_conforming_footer(msgbuf, sob, ignore_footer);
 
 	if (!has_footer) {
 		const char *append_newlines = NULL;
@@ -4723,8 +4719,32 @@ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
 
 	if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
 		strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
-				sob.buf, sob.len);
+				sob->buf, sob->len);
+}
+
+void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag)
+{
+	struct strbuf sob = STRBUF_INIT;
+	strbuf_addstr(&sob, sign_off_header);
+	strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
+	strbuf_addch(&sob, '\n');
+	append_message(msgbuf, &sob, ignore_footer, flag);
+	strbuf_release(&sob);
+}
 
+void append_message_string_list(struct strbuf *msgbuf, const char *header,
+		struct string_list *sobs, size_t ignore_footer, unsigned flag) {
+	int i;
+	struct strbuf sob = STRBUF_INIT;
+
+	for ( i = 0; i < sobs->nr; i++)
+	{
+		strbuf_addstr(&sob, header);
+		strbuf_addstr(&sob, sobs->items[i].string);
+		strbuf_addch(&sob, '\n');
+		append_message(msgbuf, &sob, ignore_footer, flag);
+		strbuf_reset(&sob);
+	}
 	strbuf_release(&sob);
 }
 
diff --git a/sequencer.h b/sequencer.h
index f8b2e4ab8527..b24e274f4c62 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -174,6 +174,10 @@ int todo_list_rearrange_squash(struct todo_list *todo_list);
  * and the new signoff will be spliced into the buffer before those bytes.
  */
 void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
+void append_message(struct strbuf *msgbuf, struct strbuf *sob,
+		size_t ignore_footer, unsigned flag);
+void append_message_string_list(struct strbuf *msgbuf, const char*header,
+		struct string_list *sobs, size_t ignore_footer, unsigned flag);
 
 void append_conflicts_hint(struct index_state *istate,
 		struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index 6396897cc818..40823152a51c 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -154,6 +154,112 @@ test_expect_success 'sign off' '
 
 '
 
+test_expect_success 'helped-by' '
+
+	>file1 &&
+	git add file1 &&
+	git commit --helped-by="foo <bar@frotz>" \
+	--helped-by="foo2 <bar2@frotz>" -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Helped-by: //p" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	foo <bar@frotz>
+	foo2 <bar2@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
+test_expect_success 'reported-by' '
+
+	>file2 &&
+	git add file2 &&
+	git commit --reported-by="foo <bar@frotz>" \
+	--reported-by="foo2 <bar2@frotz>" -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Reported-by: //p" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	foo <bar@frotz>
+	foo2 <bar2@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
+test_expect_success 'reviewed-by' '
+
+	>file3 &&
+	git add file3 &&
+	git commit --reviewed-by="foo <bar@frotz>" \
+	--reviewed-by="foo2 <bar2@frotz>" -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Reviewed-by: //p" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	foo <bar@frotz>
+	foo2 <bar2@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
+test_expect_success 'mentored-by' '
+
+	>file4 &&
+	git add file4 &&
+	git commit --mentored-by="foo <bar@frotz>" \
+	--mentored-by="foo2 <bar2@frotz>" -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Mentored-by: //p" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	foo <bar@frotz>
+	foo2 <bar2@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
+test_expect_success 'multiple signatures' '
+
+	>file5 &&
+	git add file5 &&
+	git commit --helped-by="foo <bar@frotz>" \
+	--reviewed-by="foo2 <bar2@frotz>" \
+	--mentored-by="foo3 <bar3@frotz>" \
+	--reported-by="foo4 <bar4@frotz>" -s -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -e "1,7d" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	Signed-off-by: C O Mitter <committer@example.com>
+	Helped-by: foo <bar@frotz>
+	Reviewed-by: foo2 <bar2@frotz>
+	Reported-by: foo4 <bar4@frotz>
+	Mentored-by: foo3 <bar3@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
+test_expect_success 'multiple signatures (use abbreviations)' '
+
+	>file6 &&
+	git add file6 &&
+	git commit -H "foo <bar@frotz>" \
+	-R "foo2 <bar2@frotz>" \
+	-M "foo3 <bar3@frotz>" \
+	-r "foo4 <bar4@frotz>" -s -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -e "1,7d" commit.msg >actual &&
+	cat >expected <<-\EOF &&
+	Signed-off-by: C O Mitter <committer@example.com>
+	Helped-by: foo <bar@frotz>
+	Reviewed-by: foo2 <bar2@frotz>
+	Reported-by: foo4 <bar4@frotz>
+	Mentored-by: foo3 <bar3@frotz>
+	EOF
+	test_cmp expected actual
+
+'
+
 test_expect_success 'multiple -m' '
 
 	>negative &&

base-commit: 13d7ab6b5d7929825b626f050b62a11241ea4945
-- 
gitgitgadget

^ permalink raw reply related	[relevance 2%]

* Re: [PATCH 14/22] test-lib functions: add --author support to test_commit
  2021-01-12 20:17  6% ` [PATCH 14/22] test-lib functions: add --author support to test_commit Ævar Arnfjörð Bjarmason
@ 2021-01-14  7:40  0%   ` Denton Liu
  0 siblings, 0 replies; 171+ results
From: Denton Liu @ 2021-01-14  7:40 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, Johannes Sixt, Johannes Schindelin,
	brian m . carlson

Hi Ævar,

On Tue, Jan 12, 2021 at 09:17:58PM +0100, Ævar Arnfjörð Bjarmason wrote:
> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
> index 194b601bc0..529f6264fe 100644
> --- a/t/test-lib-functions.sh
> +++ b/t/test-lib-functions.sh
> @@ -185,6 +185,8 @@ debug () {
>  #	Do not call test_tick before making a commit
>  #   --signoff
>  #	Invoke "git commit" with --signoff
> +#   --author=<author>

The usage shows that you have to specify the author argument with an
equal sign...

> +#	Invoke "git commit" with --author=<author>
>  #
>  # This will commit a file with the given contents and the given commit
>  # message, and tag the resulting commit with the given tag name.
> @@ -193,6 +195,7 @@ debug () {
>  
>  test_commit () {
>  	notick= &&
> +	author= &&
>  	signoff= &&
>  	indir= &&
>  	while test $# != 0
> @@ -201,6 +204,10 @@ test_commit () {
>  		--notick)
>  			notick=yes
>  			;;
> +		--author)
> +			author="$2"

but over here, it's only parsed if they're presented as two separate
tokens. We should correct the usage text accordingly.

Thanks,
Denton

> +			shift
> +			;;
>  		--signoff)
>  			signoff="$1"
>  			;;

^ permalink raw reply	[relevance 0%]

* [PATCH 14/22] test-lib functions: add --author support to test_commit
  @ 2021-01-12 20:17  6% ` Ævar Arnfjörð Bjarmason
  2021-01-14  7:40  0%   ` Denton Liu
  0 siblings, 1 reply; 171+ results
From: Ævar Arnfjörð Bjarmason @ 2021-01-12 20:17 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Johannes Sixt, Johannes Schindelin,
	brian m . carlson, Ævar Arnfjörð Bjarmason

Add support for --author to "test_commit". This will simplify some
current and future tests, one of those is being changed here.

Let's also line-wrap the "git commit" command invocation to make diffs
that add subsequent options easier to add, as they'll only need to add
a new option line.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t7509-commit-authorship.sh |  7 ++-----
 t/test-lib-functions.sh      | 11 ++++++++++-
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh
index 500ab2fe72..ee6c47416e 100755
--- a/t/t7509-commit-authorship.sh
+++ b/t/t7509-commit-authorship.sh
@@ -18,11 +18,8 @@ message_body () {
 }
 
 test_expect_success '-C option copies authorship and message' '
-	echo "Initial" >foo &&
-	git add foo &&
-	test_tick &&
-	git commit -m "Initial Commit" --author Frigate\ \<flying@over.world\> &&
-	git tag Initial &&
+	test_commit --author Frigate\ \<flying@over.world\> \
+		"Initial Commit" foo Initial Initial &&
 	echo "Test 1" >>foo &&
 	test_tick &&
 	git commit -a -C Initial &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 194b601bc0..529f6264fe 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -185,6 +185,8 @@ debug () {
 #	Do not call test_tick before making a commit
 #   --signoff
 #	Invoke "git commit" with --signoff
+#   --author=<author>
+#	Invoke "git commit" with --author=<author>
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
@@ -193,6 +195,7 @@ debug () {
 
 test_commit () {
 	notick= &&
+	author= &&
 	signoff= &&
 	indir= &&
 	while test $# != 0
@@ -201,6 +204,10 @@ test_commit () {
 		--notick)
 			notick=yes
 			;;
+		--author)
+			author="$2"
+			shift
+			;;
 		--signoff)
 			signoff="$1"
 			;;
@@ -222,7 +229,9 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} commit \
+	    ${author:+ --author "$author"} \
+	    $signoff -m "$1" &&
 	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply related	[relevance 6%]

* [PATCH v6 1/3] test: add helper functions for git-bundle
  2021-01-11 20:09  0%   ` Junio C Hamano
  2021-01-12  2:27  3%     ` [PATCH v6 0/3] improvements " Jiang Xin
@ 2021-01-12  2:27  6%     ` Jiang Xin
  1 sibling, 0 replies; 171+ results
From: Jiang Xin @ 2021-01-12  2:27 UTC (permalink / raw)
  To: Junio C Hamano, Git List,
	Đoàn Trần Công Danh, Jonathan Nieder
  Cc: Jiang Xin

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

Move git-bundle related functions from t5510 to a library, and this lib
will be shared with a new testcase t6020 which finds a known breakage of
"git-bundle".

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 t/t5510-fetch.sh           |  26 +--
 t/t6020-bundle-misc.sh     | 394 +++++++++++++++++++++++++++++++++++++
 t/test-bundle-functions.sh |  42 ++++
 3 files changed, 440 insertions(+), 22 deletions(-)
 create mode 100755 t/t6020-bundle-misc.sh
 create mode 100644 t/test-bundle-functions.sh

diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 2013051a64..1e398380eb 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -6,22 +6,10 @@ test_description='Per branch config variables affects "git fetch".
 '
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/test-bundle-functions.sh
 
 D=$(pwd)
 
-test_bundle_object_count () {
-	git verify-pack -v "$1" >verify.out &&
-	test "$2" = $(grep "^$OID_REGEX " verify.out | wc -l)
-}
-
-convert_bundle_to_pack () {
-	while read x && test -n "$x"
-	do
-		:;
-	done
-	cat
-}
-
 test_expect_success setup '
 	echo >file original &&
 	git add file &&
@@ -312,9 +300,7 @@ test_expect_success 'unbundle 1' '
 
 test_expect_success 'bundle 1 has only 3 files ' '
 	cd "$D" &&
-	convert_bundle_to_pack <bundle1 >bundle.pack &&
-	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle1 3
 '
 
 test_expect_success 'unbundle 2' '
@@ -329,9 +315,7 @@ test_expect_success 'bundle does not prerequisite objects' '
 	git add file2 &&
 	git commit -m add.file2 file2 &&
 	git bundle create bundle3 -1 HEAD &&
-	convert_bundle_to_pack <bundle3 >bundle.pack &&
-	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle3 3
 '
 
 test_expect_success 'bundle should be able to create a full history' '
@@ -884,9 +868,7 @@ test_expect_success 'all boundary commits are excluded' '
 	git merge otherside &&
 	ad=$(git log --no-walk --format=%ad HEAD) &&
 	git bundle create twoside-boundary.bdl main --since="$ad" &&
-	convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
-	pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
-	test_bundle_object_count .git/objects/pack/pack-${pack##pack	}.pack 3
+	test_bundle_object_count --thin twoside-boundary.bdl 3
 '
 
 test_expect_success 'fetch --prune prints the remotes url' '
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
new file mode 100755
index 0000000000..201f34b5c3
--- /dev/null
+++ b/t/t6020-bundle-misc.sh
@@ -0,0 +1,394 @@
+#!/bin/sh
+#
+# Copyright (c) 2021 Jiang Xin
+#
+
+test_description='Test git-bundle'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/test-bundle-functions.sh
+
+# Create a commit or tag and set the variable with the object ID.
+test_commit_setvar () {
+	notick=
+	signoff=
+	indir=
+	merge=
+	tag=
+	var=
+
+	while test $# != 0
+	do
+		case "$1" in
+		--merge)
+			merge=t
+			;;
+		--tag)
+			tag=t
+			;;
+		--notick)
+			notick=t
+			;;
+		--signoff)
+			signoff="$1"
+			;;
+		-C)
+			shift
+			indir="$1"
+			;;
+		-*)
+			echo >&2 "error: unknown option $1"
+			return 1
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+	if test $# -lt 2
+	then
+		echo >&2 "error: test_commit_setvar must have at least 2 arguments"
+		return 1
+	fi
+	var=$1
+	shift
+	indir=${indir:+"$indir"/}
+	if test -z "$notick"
+	then
+		test_tick
+	fi &&
+	if test -n "$merge"
+	then
+		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
+			${2:+-m "$2"} "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	elif test -n "$tag"
+	then
+		git ${indir:+ -C "$indir"} tag -m "$1" "$1" "${2:-HEAD}" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
+	else
+		file=${2:-"$1.t"} &&
+		echo "${3-$1}" >"$indir$file" &&
+		git ${indir:+ -C "$indir"} add "$file" &&
+		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	fi &&
+	eval $var=$oid
+}
+
+# Format the output of git commands to make a user-friendly and stable
+# text.  We can easily prepare the expect text without having to worry
+# about future changes of the commit ID and spaces of the output.
+make_user_friendly_and_stable_output () {
+	sed \
+		-e "s/${A%${A#???????}}[0-9a-f]*/<COMMIT-A>/g" \
+		-e "s/${B%${B#???????}}[0-9a-f]*/<COMMIT-B>/g" \
+		-e "s/${C%${C#???????}}[0-9a-f]*/<COMMIT-C>/g" \
+		-e "s/${D%${D#???????}}[0-9a-f]*/<COMMIT-D>/g" \
+		-e "s/${E%${E#???????}}[0-9a-f]*/<COMMIT-E>/g" \
+		-e "s/${F%${F#???????}}[0-9a-f]*/<COMMIT-F>/g" \
+		-e "s/${G%${G#???????}}[0-9a-f]*/<COMMIT-G>/g" \
+		-e "s/${H%${H#???????}}[0-9a-f]*/<COMMIT-H>/g" \
+		-e "s/${I%${I#???????}}[0-9a-f]*/<COMMIT-I>/g" \
+		-e "s/${J%${J#???????}}[0-9a-f]*/<COMMIT-J>/g" \
+		-e "s/${K%${K#???????}}[0-9a-f]*/<COMMIT-K>/g" \
+		-e "s/${L%${L#???????}}[0-9a-f]*/<COMMIT-L>/g" \
+		-e "s/${M%${M#???????}}[0-9a-f]*/<COMMIT-M>/g" \
+		-e "s/${N%${N#???????}}[0-9a-f]*/<COMMIT-N>/g" \
+		-e "s/${O%${O#???????}}[0-9a-f]*/<COMMIT-O>/g" \
+		-e "s/${P%${P#???????}}[0-9a-f]*/<COMMIT-P>/g" \
+		-e "s/${TAG1%${TAG1#???????}}[0-9a-f]*/<TAG-1>/g" \
+		-e "s/${TAG2%${TAG2#???????}}[0-9a-f]*/<TAG-2>/g" \
+		-e "s/${TAG3%${TAG3#???????}}[0-9a-f]*/<TAG-3>/g" \
+		-e "s/ *\$//"
+}
+
+#            (C)   (D, pull/1/head, topic/1)
+#             o --- o
+#            /       \                              (L)
+#           /         \        o (H, topic/2)             (M, tag:v2)
+#          /    (F)    \      /                                 (N, tag:v3)
+#         /      o --------- o (G, pull/2/head)      o --- o --- o (release)
+#        /      /        \    \                      /       \
+#  o --- o --- o -------- o -- o ------------------ o ------- o --- o (main)
+# (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
+#
+test_expect_success 'setup' '
+	# Try to make a stable fixed width for abbreviated commit ID,
+	# this fixed-width oid will be replaced with "<OID>".
+	git config core.abbrev 7 &&
+
+	# branch main: commit A & B
+	test_commit_setvar A "Commit A" main.txt &&
+	test_commit_setvar B "Commit B" main.txt &&
+
+	# branch topic/1: commit C & D, refs/pull/1/head
+	git checkout -b topic/1 &&
+	test_commit_setvar C "Commit C" topic-1.txt &&
+	test_commit_setvar D "Commit D" topic-1.txt &&
+	git update-ref refs/pull/1/head HEAD &&
+
+	# branch topic/1: commit E, tag v1
+	git checkout main &&
+	test_commit_setvar E "Commit E" main.txt &&
+	test_commit_setvar --tag TAG1 v1 &&
+
+	# branch topic/2: commit F & G, refs/pull/2/head
+	git checkout -b topic/2 &&
+	test_commit_setvar F "Commit F" topic-2.txt &&
+	test_commit_setvar G "Commit G" topic-2.txt &&
+	git update-ref refs/pull/2/head HEAD &&
+	test_commit_setvar H "Commit H" topic-2.txt &&
+
+	# branch main: merge commit I & J
+	git checkout main &&
+	test_commit_setvar --merge I topic/1 "Merge commit I" &&
+	test_commit_setvar --merge J refs/pull/2/head "Merge commit J" &&
+
+	# branch main: commit K
+	git checkout main &&
+	test_commit_setvar K "Commit K" main.txt &&
+
+	# branch release:
+	git checkout -b release &&
+	test_commit_setvar L "Commit L" release.txt &&
+	test_commit_setvar M "Commit M" release.txt &&
+	test_commit_setvar --tag TAG2 v2 &&
+	test_commit_setvar N "Commit N" release.txt &&
+	test_commit_setvar --tag TAG3 v3 &&
+
+	# branch main: merge commit O, commit P
+	git checkout main &&
+	test_commit_setvar --merge O tags/v2 "Merge commit O" &&
+	test_commit_setvar P "Commit P" main.txt
+'
+
+test_expect_failure 'create bundle from special rev: main^!' '
+	git bundle create special-rev.bdl "main^!" &&
+
+	git bundle list-heads special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	EOF
+	test_i18ncmp expect actual &&
+
+	git bundle verify special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains this ref:
+	<COMMIT-P> refs/heads/main
+	The bundle requires this ref:
+	<COMMIT-O>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count special-rev.bdl 3
+'
+
+test_expect_success 'create bundle with --max-count option' '
+	git bundle create max-count.bdl --max-count 1 \
+		main \
+		"^release" \
+		refs/tags/v1 \
+		refs/pull/1/head \
+		refs/pull/2/head &&
+
+	git bundle verify max-count.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-P> refs/heads/main
+	<TAG-1> refs/tags/v1
+	The bundle requires this ref:
+	<COMMIT-O>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count max-count.bdl 4
+'
+
+test_expect_success 'create bundle with --since option' '
+	git log -1 --pretty="%ad" $M >actual &&
+	cat >expect <<-\EOF &&
+	Thu Apr 7 15:26:13 2005 -0700
+	EOF
+	test_cmp expect actual &&
+
+	git bundle create since.bdl \
+		--since "Thu Apr 7 15:27:00 2005 -0700" \
+		--all &&
+
+	git bundle verify since.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains these 5 refs:
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	<COMMIT-P> HEAD
+	The bundle requires these 2 refs:
+	<COMMIT-M>
+	<COMMIT-K>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count --thin since.bdl 13
+'
+
+test_expect_success 'create bundle 1 - no prerequisites' '
+	git bundle create 1.bdl topic/1 topic/2 &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	The bundle records a complete history.
+	EOF
+
+	# verify bundle, which has no prerequisites
+	git bundle verify 1.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 1.bdl 24
+'
+
+test_expect_success 'create bundle 2 - has prerequisites' '
+	git bundle create 2.bdl \
+		--ignore-missing \
+		^topic/deleted \
+		^$D \
+		^topic/2 \
+		release &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains this ref:
+	<COMMIT-N> refs/heads/release
+	The bundle requires these 3 refs:
+	<COMMIT-D>
+	<COMMIT-E>
+	<COMMIT-G>
+	EOF
+
+	git bundle verify 2.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 2.bdl 16
+'
+
+test_expect_success 'fail to verify bundle without prerequisites' '
+	git init --bare test1.git &&
+
+	cat >expect <<-\EOF &&
+	error: Repository lacks these prerequisite commits:
+	error: <COMMIT-D>
+	error: <COMMIT-E>
+	error: <COMMIT-G>
+	EOF
+
+	test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'create bundle 3 - two refs, same object' '
+	git bundle create --version=3 3.bdl \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		main \
+		HEAD &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-P> refs/heads/main
+	<COMMIT-P> HEAD
+	The bundle requires these 2 refs:
+	<COMMIT-M>
+	<COMMIT-K>
+	EOF
+
+	git bundle verify 3.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 3.bdl 4
+'
+
+test_expect_success 'create bundle 4 - with tags' '
+	git bundle create 4.bdl \
+		^main \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		--all &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 3 refs:
+	<TAG-1> refs/tags/v1
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	The bundle records a complete history.
+	EOF
+
+	git bundle verify 4.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 4.bdl 3
+'
+
+test_expect_success 'clone from bundle' '
+	git clone --mirror 1.bdl mirror.git &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	<TAG-1> refs/tags/v1
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/test-bundle-functions.sh b/t/test-bundle-functions.sh
new file mode 100644
index 0000000000..cf7ed818b2
--- /dev/null
+++ b/t/test-bundle-functions.sh
@@ -0,0 +1,42 @@
+# Library of git-bundle related functions.
+
+# Display the pack data contained in the bundle file, bypassing the
+# header that contains the signature, prerequisites and references.
+convert_bundle_to_pack () {
+	while read x && test -n "$x"
+	do
+		:;
+	done
+	cat
+}
+
+# Check count of objects in a bundle file.
+# We can use "--thin" opiton to check thin pack, which must be fixed by
+# command `git-index-pack --fix-thin --stdin`.
+test_bundle_object_count () {
+	thin=
+	if test "$1" = "--thin"
+	then
+		thin=t
+		shift
+	fi
+	if test $# -ne 2
+	then
+		echo >&2 "args should be: <bundle> <count>"
+		return 1
+	fi
+	bundle=$1
+	pack=$bundle.pack
+	convert_bundle_to_pack <"$bundle" >"$pack" &&
+	if test -n "$thin"
+	then
+		mv "$pack" "$bundle.thin.pack" &&
+		git index-pack --stdin --fix-thin "$pack" <"$bundle.thin.pack"
+	else
+		git index-pack "$pack"
+	fi || return 1
+	count=$(git show-index <"${pack%pack}idx" | wc -l) &&
+	test $2 = $count && return 0
+	echo >&2 "error: object count for $bundle is $count, not $2"
+	return 1
+}
-- 
2.28.0.15.gba9e81f0bd


^ permalink raw reply related	[relevance 6%]

* [PATCH v6 0/3] improvements for git-bundle
  2021-01-11 20:09  0%   ` Junio C Hamano
@ 2021-01-12  2:27  3%     ` Jiang Xin
  2021-01-12  2:27  6%     ` [PATCH v6 1/3] test: add helper functions " Jiang Xin
  1 sibling, 0 replies; 171+ results
From: Jiang Xin @ 2021-01-12  2:27 UTC (permalink / raw)
  To: Junio C Hamano, Git List,
	Đoàn Trần Công Danh, Jonathan Nieder
  Cc: Jiang Xin

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

Introduce two improvements for git-bundle

+ Commit "bundle: lost objects when removing duplicate pendings",
  which fixes command like:

        $ git bundle create <file> 'master^!'

+ Commits "bundle: arguments can be read from stdin",
  which add "--stdin" option support for git-bundle, like:

        $ git bundle create <file> <input


## Changes since v5:

Junio C Hamano <gitster@pobox.com> writes:
>
> Jiang Xin <worldhello.net@gmail.com> writes:
>
> > +     var=$1
> > +     shift
> > +     if test -z "$var"
> > +     then
> > +             echo >&2 "error: var is not defined"
> > +             return 1
> > +     fi
>
> We need to check $# immediately after the loop to ensure that we can
> carve out $var and at least another arg.  [*Nit 1*]
>
> The previous round required the command line to have at least one
> after the loop (including parsing of $var) parsed it, but now we
> fall through from here when a command line were:
>
>     test_commit_setvar --merge -C there VAR
>
> and because "$1" does not exist, such an error is propagated down to
> "git merge" not getting the side branch, "git tag" not getting the
> object to tag, etc.

range-diff v5...v6 (part-1):

    @@ t/t6020-bundle-misc.sh (new)
     +		esac
     +		shift
     +	done
    -+
    -+	var=$1
    -+	shift
    -+	if test -z "$var"
    ++	if test $# -lt 2
     +	then
    -+		echo >&2 "error: var is not defined"
    ++		echo >&2 "error: test_commit_setvar must have at least 2 arguments"
     +		return 1
     +	fi
    ++	var=$1
    ++	shift
     +	indir=${indir:+"$indir"/}
     +	if test -z "$notick"
     +	then

> > +     else
> > +             file=${2:-"$1.t"} &&
> > +             echo "${3-$1}" > "$indir$file" &&
>
> Style?  [*Nit 2*]

range-diff v5...v6 (part-2):

* Add new arg "${2:-HEAD}" for `git tag`.
* Fix [*Nit 2*].

    @@ t/t6020-bundle-misc.sh (new)
     +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
     +	elif test -n "$tag"
     +	then
    -+		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
    ++		git ${indir:+ -C "$indir"} tag -m "$1" "$1" "${2:-HEAD}" &&
     +		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
     +	else
     +		file=${2:-"$1.t"} &&
    -+		echo "${3-$1}" > "$indir$file" &&
    ++		echo "${3-$1}" >"$indir$file" &&
     +		git ${indir:+ -C "$indir"} add "$file" &&
     +		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
     +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)

> > +# Format the output of git commands to make a user-friendly and stable
> > +# text.  We can easily prepare the expect text without having to worry
> > +# about future changes of the commit ID and spaces of the output.
> > +make_user_friendly_and_stable_output () {
> > +     sed \
> > +             -e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<COMMIT-A>/g" \
>
> Is "$(echo $A | cut -c1-7)" the same as "${A%${A#???????}}"?  If so,
> the latter may be a bit shorter.


range-diff v5...v6 (part-3):

    @@ t/t6020-bundle-misc.sh (new)
     +	eval $var=$oid
     +}
     +
    -+
     +# Format the output of git commands to make a user-friendly and stable
     +# text.  We can easily prepare the expect text without having to worry
     +# about future changes of the commit ID and spaces of the output.
     +make_user_friendly_and_stable_output () {
     +	sed \
    -+		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<COMMIT-A>/g" \
    -+		-e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<COMMIT-B>/g" \
    -+		-e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<COMMIT-C>/g" \
    -+		-e "s/$(echo $D | cut -c1-7)[0-9a-f]*/<COMMIT-D>/g" \
    -+		-e "s/$(echo $E | cut -c1-7)[0-9a-f]*/<COMMIT-E>/g" \
    -+		-e "s/$(echo $F | cut -c1-7)[0-9a-f]*/<COMMIT-F>/g" \
    -+		-e "s/$(echo $G | cut -c1-7)[0-9a-f]*/<COMMIT-G>/g" \
    -+		-e "s/$(echo $H | cut -c1-7)[0-9a-f]*/<COMMIT-H>/g" \
    -+		-e "s/$(echo $I | cut -c1-7)[0-9a-f]*/<COMMIT-I>/g" \
    -+		-e "s/$(echo $J | cut -c1-7)[0-9a-f]*/<COMMIT-J>/g" \
    -+		-e "s/$(echo $K | cut -c1-7)[0-9a-f]*/<COMMIT-K>/g" \
    -+		-e "s/$(echo $L | cut -c1-7)[0-9a-f]*/<COMMIT-L>/g" \
    -+		-e "s/$(echo $M | cut -c1-7)[0-9a-f]*/<COMMIT-M>/g" \
    -+		-e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<COMMIT-N>/g" \
    -+		-e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<COMMIT-O>/g" \
    -+		-e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<COMMIT-P>/g" \
    -+		-e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<TAG-1>/g" \
    -+		-e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<TAG-2>/g" \
    -+		-e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<TAG-3>/g" \
    ++		-e "s/${A%${A#???????}}[0-9a-f]*/<COMMIT-A>/g" \
    ++		-e "s/${B%${B#???????}}[0-9a-f]*/<COMMIT-B>/g" \
    ++		-e "s/${C%${C#???????}}[0-9a-f]*/<COMMIT-C>/g" \
    ++		-e "s/${D%${D#???????}}[0-9a-f]*/<COMMIT-D>/g" \
    ++		-e "s/${E%${E#???????}}[0-9a-f]*/<COMMIT-E>/g" \
    ++		-e "s/${F%${F#???????}}[0-9a-f]*/<COMMIT-F>/g" \
    ++		-e "s/${G%${G#???????}}[0-9a-f]*/<COMMIT-G>/g" \
    ++		-e "s/${H%${H#???????}}[0-9a-f]*/<COMMIT-H>/g" \
    ++		-e "s/${I%${I#???????}}[0-9a-f]*/<COMMIT-I>/g" \
    ++		-e "s/${J%${J#???????}}[0-9a-f]*/<COMMIT-J>/g" \
    ++		-e "s/${K%${K#???????}}[0-9a-f]*/<COMMIT-K>/g" \
    ++		-e "s/${L%${L#???????}}[0-9a-f]*/<COMMIT-L>/g" \
    ++		-e "s/${M%${M#???????}}[0-9a-f]*/<COMMIT-M>/g" \
    ++		-e "s/${N%${N#???????}}[0-9a-f]*/<COMMIT-N>/g" \
    ++		-e "s/${O%${O#???????}}[0-9a-f]*/<COMMIT-O>/g" \
    ++		-e "s/${P%${P#???????}}[0-9a-f]*/<COMMIT-P>/g" \
    ++		-e "s/${TAG1%${TAG1#???????}}[0-9a-f]*/<TAG-1>/g" \
    ++		-e "s/${TAG2%${TAG2#???????}}[0-9a-f]*/<TAG-2>/g" \
    ++		-e "s/${TAG3%${TAG3#???????}}[0-9a-f]*/<TAG-3>/g" \
     +		-e "s/ *\$//"
     +}
     +

> Do we even need the "error" message?  "git index-pack" would have
> already given some error message to its standard error stream, no?
> If so
>
>         if test -n "$thin"
>         then
>                 ...
>         fi || return 1
>
> would be sufficient, I guess.

range-diff v5...v6 (part-4):

1:  fa7516b2ec ! 1:  900bb16178 test: add helper functions for git-bundle
    @@ t/test-bundle-functions.sh (new)
     +		git index-pack --stdin --fix-thin "$pack" <"$bundle.thin.pack"
     +	else
     +		git index-pack "$pack"
    -+	fi
    -+	if test $? -ne 0
    -+	then
    -+		echo >&2 "error: fail to convert $bundle or index-pack"
    -+		return 1
    -+	fi
    ++	fi || return 1
     +	count=$(git show-index <"${pack%pack}idx" | wc -l) &&
     +	test $2 = $count && return 0
     +	echo >&2 "error: object count for $bundle is $count, not $2"
2:  ea543de111 = 2:  1bbf0ab213 bundle: lost objects when removing duplicate pendings
3:  18f0d48814 = 3:  7ac0751821 bundle: arguments can be read from stdin

--

Jiang Xin (3):
  test: add helper functions for git-bundle
  bundle: lost objects when removing duplicate pendings
  bundle: arguments can be read from stdin

 bundle.c                   | 109 +++++----
 object.c                   |  10 +-
 t/t5510-fetch.sh           |  26 +--
 t/t5607-clone-bundle.sh    |   4 +-
 t/t6020-bundle-misc.sh     | 463 +++++++++++++++++++++++++++++++++++++
 t/test-bundle-functions.sh |  42 ++++
 6 files changed, 576 insertions(+), 78 deletions(-)
 create mode 100755 t/t6020-bundle-misc.sh
 create mode 100644 t/test-bundle-functions.sh

-- 
2.28.0.15.gba9e81f0bd

^ permalink raw reply	[relevance 3%]

* Re: [PATCH v5 1/3] test: add helper functions for git-bundle
  2021-01-10 14:30  6% ` [PATCH v5 1/3] test: add helper functions for git-bundle Jiang Xin
@ 2021-01-11 20:09  0%   ` Junio C Hamano
  2021-01-12  2:27  3%     ` [PATCH v6 0/3] improvements " Jiang Xin
  2021-01-12  2:27  6%     ` [PATCH v6 1/3] test: add helper functions " Jiang Xin
  0 siblings, 2 replies; 171+ results
From: Junio C Hamano @ 2021-01-11 20:09 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Git List, Đoàn Trần Công Danh,
	Jonathan Nieder, Jiang Xin

Jiang Xin <worldhello.net@gmail.com> writes:

> +# Create a commit or tag and set the variable with the object ID.
> +test_commit_setvar () {
> +	notick=
> +	signoff=
> +	indir=
> +	merge=
> +	tag=
> +	var=
> +
> +	while test $# != 0
> +	do
> +		case "$1" in
> +		--merge)
> +			merge=t
> +			;;
> +		--tag)
> +			tag=t
> +			;;
> +		--notick)
> +			notick=t
> +			;;
> +		--signoff)
> +			signoff="$1"
> +			;;
> +		-C)
> +			shift
> +			indir="$1"
> +			;;
> +		-*)
> +			echo >&2 "error: unknown option $1"
> +			return 1
> +			;;
> +		*)
> +			break
> +			;;
> +		esac
> +		shift
> +	done
> +
> +	var=$1
> +	shift
> +	if test -z "$var"
> +	then
> +		echo >&2 "error: var is not defined"
> +		return 1
> +	fi

We need to check $# immediately after the loop to ensure that we can
carve out $var and at least another arg.  [*Nit 1*]

The previous round required the command line to have at least one
after the loop (including parsing of $var) parsed it, but now we
fall through from here when a command line were:

    test_commit_setvar --merge -C there VAR

and because "$1" does not exist, such an error is propagated down to
"git merge" not getting the side branch, "git tag" not getting the
object to tag, etc.

> +	indir=${indir:+"$indir"/}
> +	if test -z "$notick"
> +	then
> +		test_tick
> +	fi &&
> +	if test -n "$merge"
> +	then
> +		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
> +			${2:+-m "$2"} "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> +	elif test -n "$tag"
> +	then
> +		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
> +	else
> +		file=${2:-"$1.t"} &&
> +		echo "${3-$1}" > "$indir$file" &&

Style?  [*Nit 2*]

> +		git ${indir:+ -C "$indir"} add "$file" &&
> +		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> +	fi &&
> +	eval $var=$oid
> +}


> +
> +
> +# Format the output of git commands to make a user-friendly and stable
> +# text.  We can easily prepare the expect text without having to worry
> +# about future changes of the commit ID and spaces of the output.
> +make_user_friendly_and_stable_output () {
> +	sed \
> +		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<COMMIT-A>/g" \

Is "$(echo $A | cut -c1-7)" the same as "${A%${A#???????}}"?  If so,
the latter may be a bit shorter.

> diff --git a/t/test-bundle-functions.sh b/t/test-bundle-functions.sh
> new file mode 100644
> index 0000000000..0853eb1eca
> --- /dev/null
> +++ b/t/test-bundle-functions.sh
> @@ -0,0 +1,47 @@
> +# Library of git-bundle related functions.
> +
> +# Display the pack data contained in the bundle file, bypassing the
> +# header that contains the signature, prerequisites and references.
> +convert_bundle_to_pack () {
> +	while read x && test -n "$x"
> +	do
> +		:;
> +	done
> +	cat
> +}
> +
> +# Check count of objects in a bundle file.
> +# We can use "--thin" opiton to check thin pack, which must be fixed by
> +# command `git-index-pack --fix-thin --stdin`.
> +test_bundle_object_count () {
> +	thin=
> +	if test "$1" = "--thin"
> +	then
> +		thin=t
> +		shift
> +	fi
> +	if test $# -ne 2
> +	then
> +		echo >&2 "args should be: <bundle> <count>"
> +		return 1
> +	fi
> +	bundle=$1
> +	pack=$bundle.pack
> +	convert_bundle_to_pack <"$bundle" >"$pack" &&
> +	if test -n "$thin"
> +	then
> +		mv "$pack" "$bundle.thin.pack" &&
> +		git index-pack --stdin --fix-thin "$pack" <"$bundle.thin.pack"
> +	else
> +		git index-pack "$pack"
> +	fi

I wonder why we shouldn't always do "--fix-thin", so that the caller
does not even have to bother passing the "--thin" option.

Is this to protect us from "git bundle" creating a bundle that
contains a thin pack when it should not?  A caller that knows it is
storing a fully connected history can deliberately omit "--thin"
from the command line and make sure "index-pack" that is not asked
to do "--fix-thin" indeed finds the pack data fully self-contained,
so it may be a good idea to have these two separate codepaths after
all.  OK.

> +	if test $? -ne 0
> +	then
> +		echo >&2 "error: fail to convert $bundle or index-pack"
> +		return 1
> +	fi

Do we even need the "error" message?  "git index-pack" would have
already given some error message to its standard error stream, no?
If so

	if test -n "$thin"
	then
		...
	fi || return 1

would be sufficient, I guess.

> +	count=$(git show-index <"${pack%pack}idx" | wc -l) &&
> +	test $2 = $count && return 0
> +	echo >&2 "error: object count for $bundle is $count, not $2"
> +	return 1
> +}

Looking good except for a few minor nits I mentioned above.

Thanks.

^ permalink raw reply	[relevance 0%]

* [PATCH v5 1/3] test: add helper functions for git-bundle
  @ 2021-01-10 14:30  6% ` Jiang Xin
  2021-01-11 20:09  0%   ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Jiang Xin @ 2021-01-10 14:30 UTC (permalink / raw)
  To: Junio C Hamano, Git List,
	Đoàn Trần Công Danh, Jonathan Nieder
  Cc: Jiang Xin

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

Move git-bundle related functions from t5510 to a library, and this lib
will be shared with a new testcase t6020 which finds a known breakage of
"git-bundle".

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 t/t5510-fetch.sh           |  26 +--
 t/t6020-bundle-misc.sh     | 396 +++++++++++++++++++++++++++++++++++++
 t/test-bundle-functions.sh |  47 +++++
 3 files changed, 447 insertions(+), 22 deletions(-)
 create mode 100755 t/t6020-bundle-misc.sh
 create mode 100644 t/test-bundle-functions.sh

diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 2013051a64..1e398380eb 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -6,22 +6,10 @@ test_description='Per branch config variables affects "git fetch".
 '
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/test-bundle-functions.sh
 
 D=$(pwd)
 
-test_bundle_object_count () {
-	git verify-pack -v "$1" >verify.out &&
-	test "$2" = $(grep "^$OID_REGEX " verify.out | wc -l)
-}
-
-convert_bundle_to_pack () {
-	while read x && test -n "$x"
-	do
-		:;
-	done
-	cat
-}
-
 test_expect_success setup '
 	echo >file original &&
 	git add file &&
@@ -312,9 +300,7 @@ test_expect_success 'unbundle 1' '
 
 test_expect_success 'bundle 1 has only 3 files ' '
 	cd "$D" &&
-	convert_bundle_to_pack <bundle1 >bundle.pack &&
-	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle1 3
 '
 
 test_expect_success 'unbundle 2' '
@@ -329,9 +315,7 @@ test_expect_success 'bundle does not prerequisite objects' '
 	git add file2 &&
 	git commit -m add.file2 file2 &&
 	git bundle create bundle3 -1 HEAD &&
-	convert_bundle_to_pack <bundle3 >bundle.pack &&
-	git index-pack bundle.pack &&
-	test_bundle_object_count bundle.pack 3
+	test_bundle_object_count bundle3 3
 '
 
 test_expect_success 'bundle should be able to create a full history' '
@@ -884,9 +868,7 @@ test_expect_success 'all boundary commits are excluded' '
 	git merge otherside &&
 	ad=$(git log --no-walk --format=%ad HEAD) &&
 	git bundle create twoside-boundary.bdl main --since="$ad" &&
-	convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
-	pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
-	test_bundle_object_count .git/objects/pack/pack-${pack##pack	}.pack 3
+	test_bundle_object_count --thin twoside-boundary.bdl 3
 '
 
 test_expect_success 'fetch --prune prints the remotes url' '
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
new file mode 100755
index 0000000000..637cdb5a8e
--- /dev/null
+++ b/t/t6020-bundle-misc.sh
@@ -0,0 +1,396 @@
+#!/bin/sh
+#
+# Copyright (c) 2021 Jiang Xin
+#
+
+test_description='Test git-bundle'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/test-bundle-functions.sh
+
+# Create a commit or tag and set the variable with the object ID.
+test_commit_setvar () {
+	notick=
+	signoff=
+	indir=
+	merge=
+	tag=
+	var=
+
+	while test $# != 0
+	do
+		case "$1" in
+		--merge)
+			merge=t
+			;;
+		--tag)
+			tag=t
+			;;
+		--notick)
+			notick=t
+			;;
+		--signoff)
+			signoff="$1"
+			;;
+		-C)
+			shift
+			indir="$1"
+			;;
+		-*)
+			echo >&2 "error: unknown option $1"
+			return 1
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
+	var=$1
+	shift
+	if test -z "$var"
+	then
+		echo >&2 "error: var is not defined"
+		return 1
+	fi
+	indir=${indir:+"$indir"/}
+	if test -z "$notick"
+	then
+		test_tick
+	fi &&
+	if test -n "$merge"
+	then
+		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
+			${2:+-m "$2"} "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	elif test -n "$tag"
+	then
+		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
+	else
+		file=${2:-"$1.t"} &&
+		echo "${3-$1}" > "$indir$file" &&
+		git ${indir:+ -C "$indir"} add "$file" &&
+		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	fi &&
+	eval $var=$oid
+}
+
+
+# Format the output of git commands to make a user-friendly and stable
+# text.  We can easily prepare the expect text without having to worry
+# about future changes of the commit ID and spaces of the output.
+make_user_friendly_and_stable_output () {
+	sed \
+		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<COMMIT-A>/g" \
+		-e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<COMMIT-B>/g" \
+		-e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<COMMIT-C>/g" \
+		-e "s/$(echo $D | cut -c1-7)[0-9a-f]*/<COMMIT-D>/g" \
+		-e "s/$(echo $E | cut -c1-7)[0-9a-f]*/<COMMIT-E>/g" \
+		-e "s/$(echo $F | cut -c1-7)[0-9a-f]*/<COMMIT-F>/g" \
+		-e "s/$(echo $G | cut -c1-7)[0-9a-f]*/<COMMIT-G>/g" \
+		-e "s/$(echo $H | cut -c1-7)[0-9a-f]*/<COMMIT-H>/g" \
+		-e "s/$(echo $I | cut -c1-7)[0-9a-f]*/<COMMIT-I>/g" \
+		-e "s/$(echo $J | cut -c1-7)[0-9a-f]*/<COMMIT-J>/g" \
+		-e "s/$(echo $K | cut -c1-7)[0-9a-f]*/<COMMIT-K>/g" \
+		-e "s/$(echo $L | cut -c1-7)[0-9a-f]*/<COMMIT-L>/g" \
+		-e "s/$(echo $M | cut -c1-7)[0-9a-f]*/<COMMIT-M>/g" \
+		-e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<COMMIT-N>/g" \
+		-e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<COMMIT-O>/g" \
+		-e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<COMMIT-P>/g" \
+		-e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<TAG-1>/g" \
+		-e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<TAG-2>/g" \
+		-e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<TAG-3>/g" \
+		-e "s/ *\$//"
+}
+
+#            (C)   (D, pull/1/head, topic/1)
+#             o --- o
+#            /       \                              (L)
+#           /         \        o (H, topic/2)             (M, tag:v2)
+#          /    (F)    \      /                                 (N, tag:v3)
+#         /      o --------- o (G, pull/2/head)      o --- o --- o (release)
+#        /      /        \    \                      /       \
+#  o --- o --- o -------- o -- o ------------------ o ------- o --- o (main)
+# (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
+#
+test_expect_success 'setup' '
+	# Try to make a stable fixed width for abbreviated commit ID,
+	# this fixed-width oid will be replaced with "<OID>".
+	git config core.abbrev 7 &&
+
+	# branch main: commit A & B
+	test_commit_setvar A "Commit A" main.txt &&
+	test_commit_setvar B "Commit B" main.txt &&
+
+	# branch topic/1: commit C & D, refs/pull/1/head
+	git checkout -b topic/1 &&
+	test_commit_setvar C "Commit C" topic-1.txt &&
+	test_commit_setvar D "Commit D" topic-1.txt &&
+	git update-ref refs/pull/1/head HEAD &&
+
+	# branch topic/1: commit E, tag v1
+	git checkout main &&
+	test_commit_setvar E "Commit E" main.txt &&
+	test_commit_setvar --tag TAG1 v1 &&
+
+	# branch topic/2: commit F & G, refs/pull/2/head
+	git checkout -b topic/2 &&
+	test_commit_setvar F "Commit F" topic-2.txt &&
+	test_commit_setvar G "Commit G" topic-2.txt &&
+	git update-ref refs/pull/2/head HEAD &&
+	test_commit_setvar H "Commit H" topic-2.txt &&
+
+	# branch main: merge commit I & J
+	git checkout main &&
+	test_commit_setvar --merge I topic/1 "Merge commit I" &&
+	test_commit_setvar --merge J refs/pull/2/head "Merge commit J" &&
+
+	# branch main: commit K
+	git checkout main &&
+	test_commit_setvar K "Commit K" main.txt &&
+
+	# branch release:
+	git checkout -b release &&
+	test_commit_setvar L "Commit L" release.txt &&
+	test_commit_setvar M "Commit M" release.txt &&
+	test_commit_setvar --tag TAG2 v2 &&
+	test_commit_setvar N "Commit N" release.txt &&
+	test_commit_setvar --tag TAG3 v3 &&
+
+	# branch main: merge commit O, commit P
+	git checkout main &&
+	test_commit_setvar --merge O tags/v2 "Merge commit O" &&
+	test_commit_setvar P "Commit P" main.txt
+'
+
+test_expect_failure 'create bundle from special rev: main^!' '
+	git bundle create special-rev.bdl "main^!" &&
+
+	git bundle list-heads special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	EOF
+	test_i18ncmp expect actual &&
+
+	git bundle verify special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains this ref:
+	<COMMIT-P> refs/heads/main
+	The bundle requires this ref:
+	<COMMIT-O>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count special-rev.bdl 3
+'
+
+test_expect_success 'create bundle with --max-count option' '
+	git bundle create max-count.bdl --max-count 1 \
+		main \
+		"^release" \
+		refs/tags/v1 \
+		refs/pull/1/head \
+		refs/pull/2/head &&
+
+	git bundle verify max-count.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-P> refs/heads/main
+	<TAG-1> refs/tags/v1
+	The bundle requires this ref:
+	<COMMIT-O>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count max-count.bdl 4
+'
+
+test_expect_success 'create bundle with --since option' '
+	git log -1 --pretty="%ad" $M >actual &&
+	cat >expect <<-\EOF &&
+	Thu Apr 7 15:26:13 2005 -0700
+	EOF
+	test_cmp expect actual &&
+
+	git bundle create since.bdl \
+		--since "Thu Apr 7 15:27:00 2005 -0700" \
+		--all &&
+
+	git bundle verify since.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	The bundle contains these 5 refs:
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	<COMMIT-P> HEAD
+	The bundle requires these 2 refs:
+	<COMMIT-M>
+	<COMMIT-K>
+	EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count --thin since.bdl 13
+'
+
+test_expect_success 'create bundle 1 - no prerequisites' '
+	git bundle create 1.bdl topic/1 topic/2 &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	The bundle records a complete history.
+	EOF
+
+	# verify bundle, which has no prerequisites
+	git bundle verify 1.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 1.bdl 24
+'
+
+test_expect_success 'create bundle 2 - has prerequisites' '
+	git bundle create 2.bdl \
+		--ignore-missing \
+		^topic/deleted \
+		^$D \
+		^topic/2 \
+		release &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains this ref:
+	<COMMIT-N> refs/heads/release
+	The bundle requires these 3 refs:
+	<COMMIT-D>
+	<COMMIT-E>
+	<COMMIT-G>
+	EOF
+
+	git bundle verify 2.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 2.bdl 16
+'
+
+test_expect_success 'fail to verify bundle without prerequisites' '
+	git init --bare test1.git &&
+
+	cat >expect <<-\EOF &&
+	error: Repository lacks these prerequisite commits:
+	error: <COMMIT-D>
+	error: <COMMIT-E>
+	error: <COMMIT-G>
+	EOF
+
+	test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'create bundle 3 - two refs, same object' '
+	git bundle create --version=3 3.bdl \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		main \
+		HEAD &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 2 refs:
+	<COMMIT-P> refs/heads/main
+	<COMMIT-P> HEAD
+	The bundle requires these 2 refs:
+	<COMMIT-M>
+	<COMMIT-K>
+	EOF
+
+	git bundle verify 3.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 3.bdl 4
+'
+
+test_expect_success 'create bundle 4 - with tags' '
+	git bundle create 4.bdl \
+		^main \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		--all &&
+
+	cat >expect <<-\EOF &&
+	The bundle contains these 3 refs:
+	<TAG-1> refs/tags/v1
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	The bundle records a complete history.
+	EOF
+
+	git bundle verify 4.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 4.bdl 3
+'
+
+test_expect_success 'clone from bundle' '
+	git clone --mirror 1.bdl mirror.git &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-\EOF &&
+	<COMMIT-P> refs/heads/main
+	<COMMIT-N> refs/heads/release
+	<COMMIT-D> refs/heads/topic/1
+	<COMMIT-H> refs/heads/topic/2
+	<TAG-1> refs/tags/v1
+	<TAG-2> refs/tags/v2
+	<TAG-3> refs/tags/v3
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/test-bundle-functions.sh b/t/test-bundle-functions.sh
new file mode 100644
index 0000000000..0853eb1eca
--- /dev/null
+++ b/t/test-bundle-functions.sh
@@ -0,0 +1,47 @@
+# Library of git-bundle related functions.
+
+# Display the pack data contained in the bundle file, bypassing the
+# header that contains the signature, prerequisites and references.
+convert_bundle_to_pack () {
+	while read x && test -n "$x"
+	do
+		:;
+	done
+	cat
+}
+
+# Check count of objects in a bundle file.
+# We can use "--thin" opiton to check thin pack, which must be fixed by
+# command `git-index-pack --fix-thin --stdin`.
+test_bundle_object_count () {
+	thin=
+	if test "$1" = "--thin"
+	then
+		thin=t
+		shift
+	fi
+	if test $# -ne 2
+	then
+		echo >&2 "args should be: <bundle> <count>"
+		return 1
+	fi
+	bundle=$1
+	pack=$bundle.pack
+	convert_bundle_to_pack <"$bundle" >"$pack" &&
+	if test -n "$thin"
+	then
+		mv "$pack" "$bundle.thin.pack" &&
+		git index-pack --stdin --fix-thin "$pack" <"$bundle.thin.pack"
+	else
+		git index-pack "$pack"
+	fi
+	if test $? -ne 0
+	then
+		echo >&2 "error: fail to convert $bundle or index-pack"
+		return 1
+	fi
+	count=$(git show-index <"${pack%pack}idx" | wc -l) &&
+	test $2 = $count && return 0
+	echo >&2 "error: object count for $bundle is $count, not $2"
+	return 1
+}
-- 
2.30.0.2.g06d2f50715


^ permalink raw reply related	[relevance 6%]

* Re: [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings
  2021-01-09  2:10  0%   ` Junio C Hamano
@ 2021-01-09 13:32  0%     ` Jiang Xin
  0 siblings, 0 replies; 171+ results
From: Jiang Xin @ 2021-01-09 13:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Đoàn Trần Công Danh, Jiang Xin

Junio C Hamano <gitster@pobox.com> 于2021年1月9日周六 上午10:11写道:
>
> Jiang Xin <worldhello.net@gmail.com> writes:
>
> > diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
> > new file mode 100755
> > index 0000000000..c4447ca88f
> > --- /dev/null
> > +++ b/t/t6020-bundle-misc.sh
> > @@ -0,0 +1,477 @@
> > +#!/bin/sh
> > +#
> > +# Copyright (c) 2021 Jiang Xin
> > +#
> > +
> > +test_description='Test git-bundle'
> > +
> > +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> > +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> > +
> > +. ./test-lib.sh
> > +
> > +# Check count of objects in a bundle file.
> > +# We can use "--thin" opiton to check thin pack, which must be fixed by
> > +# command `git-index-pack --fix-thin --stdin`.
> > +test_bundle_object_count () {
> > +     thin= &&
> > +     if test "$1" = "--thin"
> > +     then
> > +             thin=yes
> > +             shift
> > +     fi &&
> > +     if test $# -ne 2
> > +     then
> > +             echo >&2 "args should be: <bundle> <count>"
> > +             return 1
> > +     fi
> > +     bundle=$1 &&
> > +     pack=${bundle%.bdl}.pack &&
> > +     convert_bundle_to_pack <"$bundle" >"$pack" &&
> > +     if test -n "$thin"
> > +     then
> > +             test_must_fail git index-pack "$pack" &&
>
> This is overly strict, isn't it?

I want to make sure that the created bundle file which contains a thin
pack is not changed, but now I think this check is not necessary,
testing the count of objects is enough.

> Imagine a case where the objects newer revisions introduce have *no*
> resemblance to the objects in the prerequisites' trees---the
> resulting pack will have no object that is expressed as a delta
> against anything outside the pack, and the above "index-pack" would
> succeed.
>
> Besides, "git pack-objects --thin" is *not* obligated to create a
> pack that lacks one or more objects.  The "--thin" option merely
> *allows* pack-objects to omit base objects if it is convenient to do
> so.
>
> > +             mv "$pack" "$pack"-thin &&
> > +             cat "$pack"-thin |
> > +                     git index-pack --stdin --fix-thin "$pack"
>
> This side is good, but do not cat a single file into a pipe.
> The whole "then" clause would become
>
>         then
>                 mv "$pack" "$pack-thin" &&
>                 git index-pack --stdin --fix-thin "$pack" <"$pack-thin"
>         else
>
> I would think.

That's better.

> > +     else
> > +             git index-pack "$pack"
> > +     fi &&
> > +     git verify-pack -v "$pack" >verify.out
> > +     if test $? -ne 0
> > +     then
> > +             echo >&2 "error: fail to convert $bundle to $pack"
> > +             return 1
> > +     fi
>
> At this point, we are not testing the bundle subcommand, but is
> testing "git index-pack --fix-thin" that we run ourselves.  Is it
> essential to ensure $pack is sane here?  I doubt it.

If not check the return error code of `git index-pack`, the report
message will be "error: object count for $bundle is , not $2". I want
to give a specific error message for developer.

> > +     count=$(grep -c "^$OID_REGEX " verify.out) &&
>
> And if there is no need to run verify-pack, then we can do
> count=$(git show-index "${pack%pack}idx" | wc -l) instead, perhaps?

Will do.

> > +     test $2 = $count && return 0
> > +     echo >&2 "error: object count for $bundle is $count, not $2"
> > +     return 1
> > +}
> > +
> > +# Display the pack data contained in the bundle file, bypassing the
> > +# header that contains the signature, prerequisites and references.
> > +convert_bundle_to_pack () {
> > +     while read x && test -n "$x"
> > +     do
> > +             :;
> > +     done
> > +     cat
> > +}
>
> This looks somewhat familiar.  Perhaps extract out necessary helpers
> including this one into t/test-bundle-lib or something similar in a
> preparatory step before this patch?
>
> > +# Create a commit or tag and set the variable with the object ID.
> > +test_commit_setvar () {
> > +     notick= &&
> > +     signoff= &&
> > +     indir= &&
> > +     merge= &&
> > +     tag= &&
> > +     var= &&
> > +     while test $# != 0
> > +     do
> > +             case "$1" in
> > +             --merge)
> > +                     merge=yes
> > +                     ;;
> > +             --tag)
> > +                     tag=yes
> > +                     ;;
> > +             --notick)
> > +                     notick=yes
> > +                     ;;
> > +             --signoff)
> > +                     signoff="$1"
> > +                     ;;
> > +             -C)
> > +                     indir="$2"
> > +                     shift
> > +                     ;;
> > +             -*)
> > +                     echo >&2 "error: unknown option $1"
> > +                     return 1
> > +                     ;;
> > +             *)
> > +                     test -n "$var" && break
> > +                     var=$1

The loop ends only if $var has been assigned a value, or no other
args.  Will report error if no other args later.

> > +                     ;;
> > +             esac
> > +             shift
> > +     done &&
>
> At this point, if $var is still empty, the caller is buggy, and ...

See the above note.

> > +     indir=${indir:+"$indir"/} &&
> > +     if test $# -eq 0
> > +     then
> > +             echo >&2 "no args provided"
> > +             return 1
> > +     fi &&
> > +     if test -z "$notick"
> > +     then
> > +             test_tick
> > +     fi &&
> > +     if test -n "$merge"
> > +     then
> > +             git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
> > +                     ${2:+-m "$2"} "$1" &&
> > +             oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> > +     elif test -n "$tag"
> > +     then
> > +             git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
> > +             oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
> > +     else
> > +             file=${2:-"$1.t"} &&
> > +             echo "${3-$1}" > "$indir$file" &&
> > +             git ${indir:+ -C "$indir"} add "$file" &&
> > +             git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
> > +             oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> > +     fi &&
> > +     eval $var=$oid
> > +}
>
> ... it will cause a failure in 'eval' we have here.  Not good.
>
> > +# Format the output of git commands to make a user-friendly and stable
> > +# text.  We can easily prepare the expect text without having to worry
> > +# about future changes of the commit ID and spaces of the output.
>
> Hmph.  This relies on 7 hexdigits being sufficient to uniquely
> identify all objects involved in the test?  It should be OK in
> practice.
>
> Is there a point in having both <COMMIT-A> and <OID-A>?  I would
> have expected that all these "full object name" conversions are
> unneeded.

Will do.

> > +make_user_friendly_and_stable_output () {
> > +     sed \
> > +             -e "s/$A/<COMMIT-A>/" \
> > +             -e "s/$B/<COMMIT-B>/" \
> > +             -e "s/$C/<COMMIT-C>/" \
> > +             -e "s/$D/<COMMIT-D>/" \
> > +             -e "s/$E/<COMMIT-E>/" \
> > +             -e "s/$F/<COMMIT-F>/" \
> > +             -e "s/$G/<COMMIT-G>/" \
> > +             -e "s/$H/<COMMIT-H>/" \
> > +             -e "s/$I/<COMMIT-I>/" \
> > +             -e "s/$J/<COMMIT-J>/" \
> > +             -e "s/$K/<COMMIT-K>/" \
> > +             -e "s/$L/<COMMIT-L>/" \
> > +             -e "s/$M/<COMMIT-M>/" \
> > +             -e "s/$N/<COMMIT-N>/" \
> > +             -e "s/$O/<COMMIT-O>/" \
> > +             -e "s/$P/<COMMIT-P>/" \
> > +             -e "s/$TAG1/<TAG-1>/" \
> > +             -e "s/$TAG2/<TAG-2>/" \
> > +             -e "s/$TAG3/<TAG-3>/" \
> > +             -e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \
> > +             -e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \
> > +             -e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<OID-C>/g" \
> > +             -e "s/$(echo $D | cut -c1-7)[0-9a-f]*/<OID-D>/g" \
> > +             -e "s/$(echo $E | cut -c1-7)[0-9a-f]*/<OID-E>/g" \
> > +             -e "s/$(echo $F | cut -c1-7)[0-9a-f]*/<OID-F>/g" \
> > +             -e "s/$(echo $G | cut -c1-7)[0-9a-f]*/<OID-G>/g" \
> > +             -e "s/$(echo $H | cut -c1-7)[0-9a-f]*/<OID-H>/g" \
> > +             -e "s/$(echo $I | cut -c1-7)[0-9a-f]*/<OID-I>/g" \
> > +             -e "s/$(echo $J | cut -c1-7)[0-9a-f]*/<OID-J>/g" \
> > +             -e "s/$(echo $K | cut -c1-7)[0-9a-f]*/<OID-K>/g" \
> > +             -e "s/$(echo $L | cut -c1-7)[0-9a-f]*/<OID-L>/g" \
> > +             -e "s/$(echo $M | cut -c1-7)[0-9a-f]*/<OID-M>/g" \
> > +             -e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<OID-N>/g" \
> > +             -e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<OID-O>/g" \
> > +             -e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<OID-P>/g" \
> > +             -e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<OID-TAG-1>/g" \
> > +             -e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<OID-TAG-2>/g" \
> > +             -e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<OID-TAG-3>/g" \
> > +             -e "s/ *\$//"
> > +}
> > ...
> > +test_expect_success 'create bundle from special rev: main^!' '
> > +     git bundle create special-rev.bdl "main^!" &&
> > +
> > +     git bundle list-heads special-rev.bdl |
> > +             make_user_friendly_and_stable_output >actual &&
> > +     cat >expect <<-EOF &&
> > +             <COMMIT-P> refs/heads/main
> > +             EOF
>
> We prefer to indent these more like so:
>
>         cat >expect <<-\EOF &&
>         <COMMIT-P> refs/heads/main
>         EOF
>
> i.e. the indent of the line with <<EOF on it and the indent of the
> line with the matching EOF are the same.  Also, quote EOF to signal
> that the body of the here text should be taken as-is without $var
> substitution.
>

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings
  2021-01-08 14:45  6% ` [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings Jiang Xin
@ 2021-01-09  2:10  0%   ` Junio C Hamano
  2021-01-09 13:32  0%     ` Jiang Xin
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2021-01-09  2:10 UTC (permalink / raw)
  To: Jiang Xin; +Cc: Git List, Đoàn Trần Công Danh, Jiang Xin

Jiang Xin <worldhello.net@gmail.com> writes:

> diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
> new file mode 100755
> index 0000000000..c4447ca88f
> --- /dev/null
> +++ b/t/t6020-bundle-misc.sh
> @@ -0,0 +1,477 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2021 Jiang Xin
> +#
> +
> +test_description='Test git-bundle'
> +
> +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
> +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
> +
> +. ./test-lib.sh
> +
> +# Check count of objects in a bundle file.
> +# We can use "--thin" opiton to check thin pack, which must be fixed by
> +# command `git-index-pack --fix-thin --stdin`.
> +test_bundle_object_count () {
> +	thin= &&
> +	if test "$1" = "--thin"
> +	then
> +		thin=yes
> +		shift
> +	fi &&
> +	if test $# -ne 2
> +	then
> +		echo >&2 "args should be: <bundle> <count>"
> +		return 1
> +	fi
> +	bundle=$1 &&
> +	pack=${bundle%.bdl}.pack &&
> +	convert_bundle_to_pack <"$bundle" >"$pack" &&
> +	if test -n "$thin"
> +	then
> +		test_must_fail git index-pack "$pack" &&

This is overly strict, isn't it?  

Imagine a case where the objects newer revisions introduce have *no*
resemblance to the objects in the prerequisites' trees---the
resulting pack will have no object that is expressed as a delta
against anything outside the pack, and the above "index-pack" would
succeed.

Besides, "git pack-objects --thin" is *not* obligated to create a
pack that lacks one or more objects.  The "--thin" option merely
*allows* pack-objects to omit base objects if it is convenient to do
so.

> +		mv "$pack" "$pack"-thin &&
> +		cat "$pack"-thin |
> +			git index-pack --stdin --fix-thin "$pack"

This side is good, but do not cat a single file into a pipe.
The whole "then" clause would become

	then
		mv "$pack" "$pack-thin" &&
		git index-pack --stdin --fix-thin "$pack" <"$pack-thin"
	else

I would think.

> +	else
> +		git index-pack "$pack"
> +	fi &&
> +	git verify-pack -v "$pack" >verify.out
> +	if test $? -ne 0
> +	then
> +		echo >&2 "error: fail to convert $bundle to $pack"
> +		return 1
> +	fi

At this point, we are not testing the bundle subcommand, but is
testing "git index-pack --fix-thin" that we run ourselves.  Is it
essential to ensure $pack is sane here?  I doubt it.

> +	count=$(grep -c "^$OID_REGEX " verify.out) &&

And if there is no need to run verify-pack, then we can do
count=$(git show-index "${pack%pack}idx" | wc -l) instead, perhaps?

> +	test $2 = $count && return 0
> +	echo >&2 "error: object count for $bundle is $count, not $2"
> +	return 1
> +}
> +
> +# Display the pack data contained in the bundle file, bypassing the
> +# header that contains the signature, prerequisites and references.
> +convert_bundle_to_pack () {
> +	while read x && test -n "$x"
> +	do
> +		:;
> +	done
> +	cat
> +}

This looks somewhat familiar.  Perhaps extract out necessary helpers
including this one into t/test-bundle-lib or something similar in a
preparatory step before this patch?

> +# Create a commit or tag and set the variable with the object ID.
> +test_commit_setvar () {
> +	notick= &&
> +	signoff= &&
> +	indir= &&
> +	merge= &&
> +	tag= &&
> +	var= &&
> +	while test $# != 0
> +	do
> +		case "$1" in
> +		--merge)
> +			merge=yes
> +			;;
> +		--tag)
> +			tag=yes
> +			;;
> +		--notick)
> +			notick=yes
> +			;;
> +		--signoff)
> +			signoff="$1"
> +			;;
> +		-C)
> +			indir="$2"
> +			shift
> +			;;
> +		-*)
> +			echo >&2 "error: unknown option $1"
> +			return 1
> +			;;
> +		*)
> +			test -n "$var" && break
> +			var=$1
> +			;;
> +		esac
> +		shift
> +	done &&

At this point, if $var is still empty, the caller is buggy, and ...

> +	indir=${indir:+"$indir"/} &&
> +	if test $# -eq 0
> +	then
> +		echo >&2 "no args provided"
> +		return 1
> +	fi &&
> +	if test -z "$notick"
> +	then
> +		test_tick
> +	fi &&
> +	if test -n "$merge"
> +	then
> +		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
> +			${2:+-m "$2"} "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> +	elif test -n "$tag"
> +	then
> +		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
> +	else
> +		file=${2:-"$1.t"} &&
> +		echo "${3-$1}" > "$indir$file" &&
> +		git ${indir:+ -C "$indir"} add "$file" &&
> +		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
> +		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
> +	fi &&
> +	eval $var=$oid
> +}

... it will cause a failure in 'eval' we have here.  Not good.

> +# Format the output of git commands to make a user-friendly and stable
> +# text.  We can easily prepare the expect text without having to worry
> +# about future changes of the commit ID and spaces of the output.

Hmph.  This relies on 7 hexdigits being sufficient to uniquely
identify all objects involved in the test?  It should be OK in
practice.

Is there a point in having both <COMMIT-A> and <OID-A>?  I would
have expected that all these "full object name" conversions are
unneeded.

> +make_user_friendly_and_stable_output () {
> +	sed \
> +		-e "s/$A/<COMMIT-A>/" \
> +		-e "s/$B/<COMMIT-B>/" \
> +		-e "s/$C/<COMMIT-C>/" \
> +		-e "s/$D/<COMMIT-D>/" \
> +		-e "s/$E/<COMMIT-E>/" \
> +		-e "s/$F/<COMMIT-F>/" \
> +		-e "s/$G/<COMMIT-G>/" \
> +		-e "s/$H/<COMMIT-H>/" \
> +		-e "s/$I/<COMMIT-I>/" \
> +		-e "s/$J/<COMMIT-J>/" \
> +		-e "s/$K/<COMMIT-K>/" \
> +		-e "s/$L/<COMMIT-L>/" \
> +		-e "s/$M/<COMMIT-M>/" \
> +		-e "s/$N/<COMMIT-N>/" \
> +		-e "s/$O/<COMMIT-O>/" \
> +		-e "s/$P/<COMMIT-P>/" \
> +		-e "s/$TAG1/<TAG-1>/" \
> +		-e "s/$TAG2/<TAG-2>/" \
> +		-e "s/$TAG3/<TAG-3>/" \
> +		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \
> +		-e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \
> +		-e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<OID-C>/g" \
> +		-e "s/$(echo $D | cut -c1-7)[0-9a-f]*/<OID-D>/g" \
> +		-e "s/$(echo $E | cut -c1-7)[0-9a-f]*/<OID-E>/g" \
> +		-e "s/$(echo $F | cut -c1-7)[0-9a-f]*/<OID-F>/g" \
> +		-e "s/$(echo $G | cut -c1-7)[0-9a-f]*/<OID-G>/g" \
> +		-e "s/$(echo $H | cut -c1-7)[0-9a-f]*/<OID-H>/g" \
> +		-e "s/$(echo $I | cut -c1-7)[0-9a-f]*/<OID-I>/g" \
> +		-e "s/$(echo $J | cut -c1-7)[0-9a-f]*/<OID-J>/g" \
> +		-e "s/$(echo $K | cut -c1-7)[0-9a-f]*/<OID-K>/g" \
> +		-e "s/$(echo $L | cut -c1-7)[0-9a-f]*/<OID-L>/g" \
> +		-e "s/$(echo $M | cut -c1-7)[0-9a-f]*/<OID-M>/g" \
> +		-e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<OID-N>/g" \
> +		-e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<OID-O>/g" \
> +		-e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<OID-P>/g" \
> +		-e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<OID-TAG-1>/g" \
> +		-e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<OID-TAG-2>/g" \
> +		-e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<OID-TAG-3>/g" \
> +		-e "s/ *\$//"
> +}
> ...
> +test_expect_success 'create bundle from special rev: main^!' '
> +	git bundle create special-rev.bdl "main^!" &&
> +
> +	git bundle list-heads special-rev.bdl |
> +		make_user_friendly_and_stable_output >actual &&
> +	cat >expect <<-EOF &&
> +		<COMMIT-P> refs/heads/main
> +		EOF

We prefer to indent these more like so:

	cat >expect <<-\EOF &&
	<COMMIT-P> refs/heads/main
	EOF

i.e. the indent of the line with <<EOF on it and the indent of the
line with the matching EOF are the same.  Also, quote EOF to signal
that the body of the here text should be taken as-is without $var
substitution.


^ permalink raw reply	[relevance 0%]

* [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings
    2021-01-08 14:45  5% ` [PATCH v4 0/2] Improvements for git-bundle Jiang Xin
@ 2021-01-08 14:45  6% ` Jiang Xin
  2021-01-09  2:10  0%   ` Junio C Hamano
  1 sibling, 1 reply; 171+ results
From: Jiang Xin @ 2021-01-08 14:45 UTC (permalink / raw)
  To: Junio C Hamano, Git List,
	Đoàn Trần Công Danh
  Cc: Jiang Xin

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

`git rev-list` will list one commit for the following command:

    $ git rev-list 'main^!'
    <tip-commit-of-main-branch>

But providing the same rev-list args to `git bundle`, fail to create
a bundle file.

    $ git bundle create - 'main^!'
    # v2 git bundle
    -<OID> <one-line-message>

    fatal: Refusing to create empty bundle.

This is because when removing duplicate objects in function
`object_array_remove_duplicates()`, one unique pending object which has
the same name is deleted by mistake.  The revision arg 'main^!' in the
above example is parsed by `handle_revision_arg()`, and at lease two
different objects will be appended to `revs.pending`, one points to the
parent commit of the "main" branch, and the other points to the tip
commit of the "main" branch.  These two objects have the same name
"main".  Only one object is left with the name "main" after calling the
function `object_array_remove_duplicates()`.

And what's worse, when adding boundary commits into pending list, we use
one-line commit message as names, and the arbitory names may surprise
git-bundle.

Only comparing objects themselves (".item") is also not good enough,
because user may want to create a bundle with two identical objects but
with different reference names, such as: "HEAD" and "refs/heads/main".

Add new function `contains_object()` which compare both the address and
the name of the object.

Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com>
---
 object.c               |  10 +-
 t/t6020-bundle-misc.sh | 477 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 483 insertions(+), 4 deletions(-)
 create mode 100755 t/t6020-bundle-misc.sh

diff --git a/object.c b/object.c
index 68f80b0b3d..98017bed8e 100644
--- a/object.c
+++ b/object.c
@@ -412,15 +412,16 @@ void object_array_clear(struct object_array *array)
 }
 
 /*
- * Return true iff array already contains an entry with name.
+ * Return true if array already contains an entry.
  */
-static int contains_name(struct object_array *array, const char *name)
+static int contains_object(struct object_array *array,
+			   const struct object *item, const char *name)
 {
 	unsigned nr = array->nr, i;
 	struct object_array_entry *object = array->objects;
 
 	for (i = 0; i < nr; i++, object++)
-		if (!strcmp(object->name, name))
+		if (item == object->item && !strcmp(object->name, name))
 			return 1;
 	return 0;
 }
@@ -432,7 +433,8 @@ void object_array_remove_duplicates(struct object_array *array)
 
 	array->nr = 0;
 	for (src = 0; src < nr; src++) {
-		if (!contains_name(array, objects[src].name)) {
+		if (!contains_object(array, objects[src].item,
+				     objects[src].name)) {
 			if (src != array->nr)
 				objects[array->nr] = objects[src];
 			array->nr++;
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
new file mode 100755
index 0000000000..c4447ca88f
--- /dev/null
+++ b/t/t6020-bundle-misc.sh
@@ -0,0 +1,477 @@
+#!/bin/sh
+#
+# Copyright (c) 2021 Jiang Xin
+#
+
+test_description='Test git-bundle'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+# Check count of objects in a bundle file.
+# We can use "--thin" opiton to check thin pack, which must be fixed by
+# command `git-index-pack --fix-thin --stdin`.
+test_bundle_object_count () {
+	thin= &&
+	if test "$1" = "--thin"
+	then
+		thin=yes
+		shift
+	fi &&
+	if test $# -ne 2
+	then
+		echo >&2 "args should be: <bundle> <count>"
+		return 1
+	fi
+	bundle=$1 &&
+	pack=${bundle%.bdl}.pack &&
+	convert_bundle_to_pack <"$bundle" >"$pack" &&
+	if test -n "$thin"
+	then
+		test_must_fail git index-pack "$pack" &&
+		mv "$pack" "$pack"-thin &&
+		cat "$pack"-thin |
+			git index-pack --stdin --fix-thin "$pack"
+	else
+		git index-pack "$pack"
+	fi &&
+	git verify-pack -v "$pack" >verify.out
+	if test $? -ne 0
+	then
+		echo >&2 "error: fail to convert $bundle to $pack"
+		return 1
+	fi
+	count=$(grep -c "^$OID_REGEX " verify.out) &&
+	test $2 = $count && return 0
+	echo >&2 "error: object count for $bundle is $count, not $2"
+	return 1
+}
+
+# Display the pack data contained in the bundle file, bypassing the
+# header that contains the signature, prerequisites and references.
+convert_bundle_to_pack () {
+	while read x && test -n "$x"
+	do
+		:;
+	done
+	cat
+}
+
+# Create a commit or tag and set the variable with the object ID.
+test_commit_setvar () {
+	notick= &&
+	signoff= &&
+	indir= &&
+	merge= &&
+	tag= &&
+	var= &&
+	while test $# != 0
+	do
+		case "$1" in
+		--merge)
+			merge=yes
+			;;
+		--tag)
+			tag=yes
+			;;
+		--notick)
+			notick=yes
+			;;
+		--signoff)
+			signoff="$1"
+			;;
+		-C)
+			indir="$2"
+			shift
+			;;
+		-*)
+			echo >&2 "error: unknown option $1"
+			return 1
+			;;
+		*)
+			test -n "$var" && break
+			var=$1
+			;;
+		esac
+		shift
+	done &&
+	indir=${indir:+"$indir"/} &&
+	if test $# -eq 0
+	then
+		echo >&2 "no args provided"
+		return 1
+	fi &&
+	if test -z "$notick"
+	then
+		test_tick
+	fi &&
+	if test -n "$merge"
+	then
+		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
+			${2:+-m "$2"} "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	elif test -n "$tag"
+	then
+		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
+	else
+		file=${2:-"$1.t"} &&
+		echo "${3-$1}" > "$indir$file" &&
+		git ${indir:+ -C "$indir"} add "$file" &&
+		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
+	fi &&
+	eval $var=$oid
+}
+
+
+# Format the output of git commands to make a user-friendly and stable
+# text.  We can easily prepare the expect text without having to worry
+# about future changes of the commit ID and spaces of the output.
+make_user_friendly_and_stable_output () {
+	sed \
+		-e "s/$A/<COMMIT-A>/" \
+		-e "s/$B/<COMMIT-B>/" \
+		-e "s/$C/<COMMIT-C>/" \
+		-e "s/$D/<COMMIT-D>/" \
+		-e "s/$E/<COMMIT-E>/" \
+		-e "s/$F/<COMMIT-F>/" \
+		-e "s/$G/<COMMIT-G>/" \
+		-e "s/$H/<COMMIT-H>/" \
+		-e "s/$I/<COMMIT-I>/" \
+		-e "s/$J/<COMMIT-J>/" \
+		-e "s/$K/<COMMIT-K>/" \
+		-e "s/$L/<COMMIT-L>/" \
+		-e "s/$M/<COMMIT-M>/" \
+		-e "s/$N/<COMMIT-N>/" \
+		-e "s/$O/<COMMIT-O>/" \
+		-e "s/$P/<COMMIT-P>/" \
+		-e "s/$TAG1/<TAG-1>/" \
+		-e "s/$TAG2/<TAG-2>/" \
+		-e "s/$TAG3/<TAG-3>/" \
+		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \
+		-e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \
+		-e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<OID-C>/g" \
+		-e "s/$(echo $D | cut -c1-7)[0-9a-f]*/<OID-D>/g" \
+		-e "s/$(echo $E | cut -c1-7)[0-9a-f]*/<OID-E>/g" \
+		-e "s/$(echo $F | cut -c1-7)[0-9a-f]*/<OID-F>/g" \
+		-e "s/$(echo $G | cut -c1-7)[0-9a-f]*/<OID-G>/g" \
+		-e "s/$(echo $H | cut -c1-7)[0-9a-f]*/<OID-H>/g" \
+		-e "s/$(echo $I | cut -c1-7)[0-9a-f]*/<OID-I>/g" \
+		-e "s/$(echo $J | cut -c1-7)[0-9a-f]*/<OID-J>/g" \
+		-e "s/$(echo $K | cut -c1-7)[0-9a-f]*/<OID-K>/g" \
+		-e "s/$(echo $L | cut -c1-7)[0-9a-f]*/<OID-L>/g" \
+		-e "s/$(echo $M | cut -c1-7)[0-9a-f]*/<OID-M>/g" \
+		-e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<OID-N>/g" \
+		-e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<OID-O>/g" \
+		-e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<OID-P>/g" \
+		-e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<OID-TAG-1>/g" \
+		-e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<OID-TAG-2>/g" \
+		-e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<OID-TAG-3>/g" \
+		-e "s/ *\$//"
+}
+
+#            (C)   (D, pull/1/head, topic/1)
+#             o --- o
+#            /       \                              (L)
+#           /         \        o (H, topic/2)             (M, tag:v2)
+#          /    (F)    \      /                                 (N, tag:v3)
+#         /      o --------- o (G, pull/2/head)      o --- o --- o (release)
+#        /      /        \    \                      /       \
+#  o --- o --- o -------- o -- o ------------------ o ------- o --- o (main)
+# (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
+#
+test_expect_success 'setup' '
+	# Try to make a stable fixed width for abbreviated commit ID,
+	# this fixed-width oid will be replaced with "<OID>".
+	git config core.abbrev 7 &&
+
+	# branch main: commit A & B
+	test_commit_setvar A "Commit A" main.txt &&
+	test_commit_setvar B "Commit B" main.txt &&
+
+	# branch topic/1: commit C & D, refs/pull/1/head
+	git checkout -b topic/1 &&
+	test_commit_setvar C "Commit C" topic-1.txt &&
+	test_commit_setvar D "Commit D" topic-1.txt &&
+	git update-ref refs/pull/1/head HEAD &&
+
+	# branch topic/1: commit E, tag v1
+	git checkout main &&
+	test_commit_setvar E "Commit E" main.txt &&
+	test_commit_setvar TAG1 --tag v1 &&
+
+	# branch topic/2: commit F & G, refs/pull/2/head
+	git checkout -b topic/2 &&
+	test_commit_setvar F "Commit F" topic-2.txt &&
+	test_commit_setvar G "Commit G" topic-2.txt &&
+	git update-ref refs/pull/2/head HEAD &&
+	test_commit_setvar H "Commit H" topic-2.txt &&
+
+	# branch main: merge commit I & J
+	git checkout main &&
+	test_commit_setvar I --merge topic/1 "Merge commit I" &&
+	test_commit_setvar J --merge refs/pull/2/head "Merge commit J" &&
+
+	# branch main: commit K
+	git checkout main &&
+	test_commit_setvar K "Commit K" main.txt &&
+
+	# branch release:
+	git checkout -b release &&
+	test_commit_setvar L "Commit L" release.txt &&
+	test_commit_setvar M "Commit M" release.txt &&
+	test_commit_setvar TAG2 --tag v2 &&
+	test_commit_setvar N "Commit N" release.txt &&
+	test_commit_setvar TAG3 --tag v3 &&
+
+	# branch main: merge commit O, commit P
+	git checkout main &&
+	test_commit_setvar O --merge tags/v2 "Merge commit O" &&
+	test_commit_setvar P "Commit P" main.txt
+'
+
+test_expect_success 'create bundle from special rev: main^!' '
+	git bundle create special-rev.bdl "main^!" &&
+
+	git bundle list-heads special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-P> refs/heads/main
+		EOF
+	test_i18ncmp expect actual &&
+
+	git bundle verify special-rev.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		The bundle contains this ref:
+		<COMMIT-P> refs/heads/main
+		The bundle requires this ref:
+		<COMMIT-O>
+		EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count special-rev.bdl 3
+'
+
+test_expect_success 'create bundle with --max-count option' '
+	git bundle create max-count.bdl --max-count 1 \
+		main \
+		"^release" \
+		refs/tags/v1 \
+		refs/pull/1/head \
+		refs/pull/2/head &&
+
+	git bundle list-heads max-count.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-P> refs/heads/main
+		<TAG-1> refs/tags/v1
+		EOF
+	test_i18ncmp expect actual &&
+
+	git bundle verify max-count.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		The bundle contains these 2 refs:
+		<COMMIT-P> refs/heads/main
+		<TAG-1> refs/tags/v1
+		The bundle requires this ref:
+		<COMMIT-O>
+		EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count max-count.bdl 4
+'
+
+test_expect_success 'create bundle with --since option' '
+	since="Thu Apr 7 15:26:13 2005 -0700" &&
+	git log -1 --pretty="%ad" $M >actual &&
+	echo "$since" >expect &&
+	test_cmp expect actual &&
+
+	git bundle create since.bdl \
+		--since "$since" --all &&
+
+	git bundle list-heads since.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-P> refs/heads/main
+		<COMMIT-N> refs/heads/release
+		<TAG-2> refs/tags/v2
+		<TAG-3> refs/tags/v3
+		<COMMIT-P> HEAD
+		EOF
+	test_i18ncmp expect actual &&
+
+	git bundle verify since.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		The bundle contains these 5 refs:
+		<COMMIT-P> refs/heads/main
+		<COMMIT-N> refs/heads/release
+		<TAG-2> refs/tags/v2
+		<TAG-3> refs/tags/v3
+		<COMMIT-P> HEAD
+		The bundle requires these 2 refs:
+		<COMMIT-L>
+		<COMMIT-K>
+		EOF
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count --thin since.bdl 16
+'
+
+test_expect_success 'create bundle 1 - no prerequisites' '
+	git bundle create 1.bdl topic/1 topic/2 &&
+
+	cat >expect <<-EOF &&
+		The bundle contains these 2 refs:
+		<COMMIT-D> refs/heads/topic/1
+		<COMMIT-H> refs/heads/topic/2
+		The bundle records a complete history.
+		EOF
+
+	# verify bundle, which has no prerequisites
+	git bundle verify 1.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 1.bdl 24
+'
+
+test_expect_success 'create bundle 2 - has prerequisites' '
+	git bundle create 2.bdl \
+		--ignore-missing \
+		^topic/deleted \
+		^$D \
+		^topic/2 \
+		release &&
+
+	cat >expect <<-EOF &&
+		The bundle contains this ref:
+		<COMMIT-N> refs/heads/release
+		The bundle requires these 3 refs:
+		<COMMIT-D>
+		<COMMIT-E>
+		<COMMIT-G>
+		EOF
+
+	git bundle verify 2.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 2.bdl 16
+'
+
+test_expect_success 'fail to verify bundle without prerequisites' '
+	git init --bare test1.git &&
+
+	cat >expect <<-EOF &&
+		error: Repository lacks these prerequisite commits:
+		error: <COMMIT-D>
+		error: <COMMIT-E>
+		error: <COMMIT-G>
+		EOF
+
+	test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'create bundle 3 - two refs, same object' '
+	git bundle create --version=3 3.bdl \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		main \
+		HEAD &&
+
+	cat >expect <<-EOF &&
+		The bundle contains these 2 refs:
+		<COMMIT-P> refs/heads/main
+		<COMMIT-P> HEAD
+		The bundle requires these 2 refs:
+		<COMMIT-M>
+		<COMMIT-K>
+		EOF
+
+	git bundle verify 3.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 3.bdl 4
+'
+
+test_expect_success 'create bundle 4 - with tags' '
+	git bundle create 4.bdl \
+		^main \
+		^release \
+		^topic/1 \
+		^topic/2 \
+		--all &&
+
+	cat >expect <<-EOF &&
+		The bundle contains these 3 refs:
+		<TAG-1> refs/tags/v1
+		<TAG-2> refs/tags/v2
+		<TAG-3> refs/tags/v3
+		The bundle records a complete history.
+		EOF
+
+	git bundle verify 4.bdl |
+		make_user_friendly_and_stable_output >actual &&
+	test_i18ncmp expect actual &&
+
+	test_bundle_object_count 4.bdl 3
+'
+
+test_expect_success 'clone from bundle' '
+	git clone --mirror 1.bdl mirror.git &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-D> refs/heads/topic/1
+		<COMMIT-H> refs/heads/topic/2
+		EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-N> refs/heads/release
+		<COMMIT-D> refs/heads/topic/1
+		<COMMIT-H> refs/heads/topic/2
+		EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-P> refs/heads/main
+		<COMMIT-N> refs/heads/release
+		<COMMIT-D> refs/heads/topic/1
+		<COMMIT-H> refs/heads/topic/2
+		EOF
+	test_cmp expect actual &&
+
+	git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" &&
+	git -C mirror.git show-ref |
+		make_user_friendly_and_stable_output >actual &&
+	cat >expect <<-EOF &&
+		<COMMIT-P> refs/heads/main
+		<COMMIT-N> refs/heads/release
+		<COMMIT-D> refs/heads/topic/1
+		<COMMIT-H> refs/heads/topic/2
+		<TAG-1> refs/tags/v1
+		<TAG-2> refs/tags/v2
+		<TAG-3> refs/tags/v3
+		EOF
+	test_cmp expect actual
+'
+
+test_done
-- 
2.30.0.2.g06d2f50715


^ permalink raw reply related	[relevance 6%]

* [PATCH v4 0/2] Improvements for git-bundle
  @ 2021-01-08 14:45  5% ` Jiang Xin
  2021-01-08 14:45  6% ` [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings Jiang Xin
  1 sibling, 0 replies; 171+ results
From: Jiang Xin @ 2021-01-08 14:45 UTC (permalink / raw)
  To: Junio C Hamano, Git List,
	Đoàn Trần Công Danh
  Cc: Jiang Xin

From: Jiang Xin <zhiyou.jx@alibaba-inc.com>

## Two improvements for git-bundle

1. Commit "bundle: lost objects when removing duplicate pendings",
   which fixes command like:

        $ git bundle create <file> 'master^!'
  
2. Commits "bundle: arguments can be read from stdin",
   which add "--stdin" option support for git-bundle, like:

        $ git bundle create <file> <input


## Changes of v4

+ Refactor t6020.


## Range diff of v3...v4

1:  9df48434f3 ! 1:  0abad6486a bundle: lost objects when removing duplicate pendings
    @@ t/t6020-bundle-misc.sh (new)
     +
     +. ./test-lib.sh
     +
    ++# Check count of objects in a bundle file.
    ++# We can use "--thin" opiton to check thin pack, which must be fixed by
    ++# command `git-index-pack --fix-thin --stdin`.
     +test_bundle_object_count () {
    ++	thin= &&
    ++	if test "$1" = "--thin"
    ++	then
    ++		thin=yes
    ++		shift
    ++	fi &&
    ++	if test $# -ne 2
    ++	then
    ++		echo >&2 "args should be: <bundle> <count>"
    ++		return 1
    ++	fi
     +	bundle=$1 &&
     +	pack=${bundle%.bdl}.pack &&
     +	convert_bundle_to_pack <"$bundle" >"$pack" &&
    -+	git index-pack "$pack" &&
    -+	git verify-pack -v "$pack" >verify.out &&
    -+	count=$(grep "^$OID_REGEX " verify.out | wc -l) &&
    ++	if test -n "$thin"
    ++	then
    ++		test_must_fail git index-pack "$pack" &&
    ++		mv "$pack" "$pack"-thin &&
    ++		cat "$pack"-thin |
    ++			git index-pack --stdin --fix-thin "$pack"
    ++	else
    ++		git index-pack "$pack"
    ++	fi &&
    ++	git verify-pack -v "$pack" >verify.out
    ++	if test $? -ne 0
    ++	then
    ++		echo >&2 "error: fail to convert $bundle to $pack"
    ++		return 1
    ++	fi
    ++	count=$(grep -c "^$OID_REGEX " verify.out) &&
     +	test $2 = $count && return 0
    -+	echo object count for $bundle is $count, not $2
    -+	return 1
    -+}
    -+
    -+
    -+test_thin_bundle_object_count () {
    -+	bundle=$1 &&
    -+	pack=${bundle%.bdl}.pack &&
    -+	convert_bundle_to_pack <"$bundle" |
    -+		test_must_fail git index-pack --stdin "$pack" &&
    -+	rm -f "$pack" &&
    -+	convert_bundle_to_pack <"$bundle" |
    -+		git index-pack --stdin --fix-thin "$pack" &&
    -+	git verify-pack -v "$pack" >verify.out &&
    -+	count=$(grep "^$OID_REGEX " verify.out | wc -l) &&
    -+	test $2 = $count && return 0
    -+	echo object count for $bundle is $count, not $2
    ++	echo >&2 "error: object count for $bundle is $count, not $2"
     +	return 1
     +}
     +
    ++# Display the pack data contained in the bundle file, bypassing the
    ++# header that contains the signature, prerequisites and references.
     +convert_bundle_to_pack () {
     +	while read x && test -n "$x"
     +	do
    @@ t/t6020-bundle-misc.sh (new)
     +	cat
     +}
     +
    ++# Create a commit or tag and set the variable with the object ID.
    ++test_commit_setvar () {
    ++	notick= &&
    ++	signoff= &&
    ++	indir= &&
    ++	merge= &&
    ++	tag= &&
    ++	var= &&
    ++	while test $# != 0
    ++	do
    ++		case "$1" in
    ++		--merge)
    ++			merge=yes
    ++			;;
    ++		--tag)
    ++			tag=yes
    ++			;;
    ++		--notick)
    ++			notick=yes
    ++			;;
    ++		--signoff)
    ++			signoff="$1"
    ++			;;
    ++		-C)
    ++			indir="$2"
    ++			shift
    ++			;;
    ++		-*)
    ++			echo >&2 "error: unknown option $1"
    ++			return 1
    ++			;;
    ++		*)
    ++			test -n "$var" && break
    ++			var=$1
    ++			;;
    ++		esac
    ++		shift
    ++	done &&
    ++	indir=${indir:+"$indir"/} &&
    ++	if test $# -eq 0
    ++	then
    ++		echo >&2 "no args provided"
    ++		return 1
    ++	fi &&
    ++	if test -z "$notick"
    ++	then
    ++		test_tick
    ++	fi &&
    ++	if test -n "$merge"
    ++	then
    ++		git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
    ++			${2:+-m "$2"} "$1" &&
    ++		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
    ++	elif test -n "$tag"
    ++	then
    ++		git ${indir:+ -C "$indir"} tag -m "$1" "$1" &&
    ++		oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
    ++	else
    ++		file=${2:-"$1.t"} &&
    ++		echo "${3-$1}" > "$indir$file" &&
    ++		git ${indir:+ -C "$indir"} add "$file" &&
    ++		git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
    ++		oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
    ++	fi &&
    ++	eval $var=$oid
    ++}
    ++
    ++
     +# Format the output of git commands to make a user-friendly and stable
     +# text.  We can easily prepare the expect text without having to worry
     +# about future changes of the commit ID and spaces of the output.
     +make_user_friendly_and_stable_output () {
     +	sed \
    -+		-e "s/ *\$//" \
    -+		-e "s/$A/<COMMIT-A>/g" \
    -+		-e "s/$B/<COMMIT-B>/g" \
    -+		-e "s/$C/<COMMIT-C>/g" \
    -+		-e "s/$D/<COMMIT-D>/g" \
    -+		-e "s/$E/<COMMIT-E>/g" \
    -+		-e "s/$F/<COMMIT-F>/g" \
    -+		-e "s/$G/<COMMIT-G>/g" \
    -+		-e "s/$H/<COMMIT-H>/g" \
    -+		-e "s/$I/<COMMIT-I>/g" \
    -+		-e "s/$J/<COMMIT-J>/g" \
    -+		-e "s/$K/<COMMIT-K>/g" \
    -+		-e "s/$L/<COMMIT-L>/g" \
    -+		-e "s/$M/<COMMIT-M>/g" \
    -+		-e "s/$N/<COMMIT-N>/g" \
    -+		-e "s/$O/<COMMIT-O>/g" \
    -+		-e "s/$P/<COMMIT-P>/g" \
    ++		-e "s/$A/<COMMIT-A>/" \
    ++		-e "s/$B/<COMMIT-B>/" \
    ++		-e "s/$C/<COMMIT-C>/" \
    ++		-e "s/$D/<COMMIT-D>/" \
    ++		-e "s/$E/<COMMIT-E>/" \
    ++		-e "s/$F/<COMMIT-F>/" \
    ++		-e "s/$G/<COMMIT-G>/" \
    ++		-e "s/$H/<COMMIT-H>/" \
    ++		-e "s/$I/<COMMIT-I>/" \
    ++		-e "s/$J/<COMMIT-J>/" \
    ++		-e "s/$K/<COMMIT-K>/" \
    ++		-e "s/$L/<COMMIT-L>/" \
    ++		-e "s/$M/<COMMIT-M>/" \
    ++		-e "s/$N/<COMMIT-N>/" \
    ++		-e "s/$O/<COMMIT-O>/" \
    ++		-e "s/$P/<COMMIT-P>/" \
    ++		-e "s/$TAG1/<TAG-1>/" \
    ++		-e "s/$TAG2/<TAG-2>/" \
    ++		-e "s/$TAG3/<TAG-3>/" \
     +		-e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \
     +		-e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \
     +		-e "s/$(echo $C | cut -c1-7)[0-9a-f]*/<OID-C>/g" \
    @@ t/t6020-bundle-misc.sh (new)
     +		-e "s/$(echo $N | cut -c1-7)[0-9a-f]*/<OID-N>/g" \
     +		-e "s/$(echo $O | cut -c1-7)[0-9a-f]*/<OID-O>/g" \
     +		-e "s/$(echo $P | cut -c1-7)[0-9a-f]*/<OID-P>/g" \
    -+		-e "s/$TAG1/<TAG-1>/g" \
    -+		-e "s/$TAG2/<TAG-2>/g" \
    -+		-e "s/$TAG3/<TAG-3>/g" \
     +		-e "s/$(echo $TAG1 | cut -c1-7)[0-9a-f]*/<OID-TAG-1>/g" \
     +		-e "s/$(echo $TAG2 | cut -c1-7)[0-9a-f]*/<OID-TAG-2>/g" \
     +		-e "s/$(echo $TAG3 | cut -c1-7)[0-9a-f]*/<OID-TAG-3>/g" \
    -+		-e "s/$ZERO_OID/<ZERO-OID>/g"
    ++		-e "s/ *\$//"
     +}
     +
     +#            (C)   (D, pull/1/head, topic/1)
    @@ t/t6020-bundle-misc.sh (new)
     +# (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
     +#
     +test_expect_success 'setup' '
    -+	# commit A & B
    -+	cat >main.txt <<-EOF &&
    -+		Commit A
    -+		EOF
    -+	git add main.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit A" &&
    ++	# Try to make a stable fixed width for abbreviated commit ID,
    ++	# this fixed-width oid will be replaced with "<OID>".
    ++	git config core.abbrev 7 &&
     +
    -+	cat >main.txt <<-EOF &&
    -+		Commit B
    -+		EOF
    -+	git add main.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit B" &&
    -+	A=$(git rev-parse HEAD~) &&
    -+	B=$(git rev-parse HEAD) &&
    ++	# branch main: commit A & B
    ++	test_commit_setvar A "Commit A" main.txt &&
    ++	test_commit_setvar B "Commit B" main.txt &&
     +
    -+	# branch topic/1
    ++	# branch topic/1: commit C & D, refs/pull/1/head
     +	git checkout -b topic/1 &&
    -+	cat >topic-1.txt <<-EOF &&
    -+		Commit C
    -+		EOF
    -+	git add topic-1.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit C" &&
    -+
    -+	cat >topic-1.txt <<-EOF &&
    -+		Commit D
    -+		EOF
    -+	git add -u &&
    -+	test_tick &&
    -+	git commit -m "Commit D" &&
    ++	test_commit_setvar C "Commit C" topic-1.txt &&
    ++	test_commit_setvar D "Commit D" topic-1.txt &&
     +	git update-ref refs/pull/1/head HEAD &&
    -+	C=$(git rev-parse topic/1~) &&
    -+	D=$(git rev-parse topic/1) &&
     +
    -+	# commit E
    ++	# branch topic/1: commit E, tag v1
     +	git checkout main &&
    -+	cat >main.txt <<-EOF &&
    -+		Commit E
    -+		EOF
    -+	git add main.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit E" &&
    -+	E=$(git rev-parse HEAD) &&
    -+	test_tick &&
    -+	git tag -m "v1" v1 HEAD &&
    -+	TAG1=$(git rev-parse refs/tags/v1) &&
    -+
    -+	# branch topic/2
    -+	git checkout -b topic/2 &&
    -+	cat >topic-2.txt <<-EOF &&
    -+		Commit F
    -+		EOF
    -+	git add topic-2.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit F" &&
    ++	test_commit_setvar E "Commit E" main.txt &&
    ++	test_commit_setvar TAG1 --tag v1 &&
     +
    -+	cat >topic-2.txt <<-EOF &&
    -+		Commit G
    -+		EOF
    -+	git add -u &&
    -+	test_tick &&
    -+	git commit -m "Commit G" &&
    ++	# branch topic/2: commit F & G, refs/pull/2/head
    ++	git checkout -b topic/2 &&
    ++	test_commit_setvar F "Commit F" topic-2.txt &&
    ++	test_commit_setvar G "Commit G" topic-2.txt &&
     +	git update-ref refs/pull/2/head HEAD &&
    ++	test_commit_setvar H "Commit H" topic-2.txt &&
     +
    -+	cat >topic-2.txt <<-EOF &&
    -+		Commit H
    -+		EOF
    -+	git add -u &&
    -+	test_tick &&
    -+	git commit -m "Commit H" &&
    -+	F=$(git rev-parse topic/2~2) &&
    -+	G=$(git rev-parse topic/2~) &&
    -+	H=$(git rev-parse topic/2) &&
    -+
    -+	# merge commit I & J
    ++	# branch main: merge commit I & J
     +	git checkout main &&
    -+	test_tick &&
    -+	git merge --no-ff --no-edit topic/1 &&
    -+	test_tick &&
    -+	git merge --no-ff --no-edit refs/pull/2/head &&
    -+	I=$(git rev-parse HEAD~) &&
    -+	J=$(git rev-parse HEAD) &&
    -+
    -+	# commit K
    ++	test_commit_setvar I --merge topic/1 "Merge commit I" &&
    ++	test_commit_setvar J --merge refs/pull/2/head "Merge commit J" &&
    ++
    ++	# branch main: commit K
     +	git checkout main &&
    -+	cat >main.txt <<-EOF &&
    -+		Commit K
    -+		EOF
    -+	git add main.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit K" &&
    -+	K=$(git rev-parse HEAD) &&
    ++	test_commit_setvar K "Commit K" main.txt &&
     +
    -+	# branch release
    ++	# branch release:
     +	git checkout -b release &&
    -+	cat >release.txt <<-EOF &&
    -+		Commit L
    -+		EOF
    -+	git add release.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit L" &&
    ++	test_commit_setvar L "Commit L" release.txt &&
    ++	test_commit_setvar M "Commit M" release.txt &&
    ++	test_commit_setvar TAG2 --tag v2 &&
    ++	test_commit_setvar N "Commit N" release.txt &&
    ++	test_commit_setvar TAG3 --tag v3 &&
     +
    -+	cat >release.txt <<-EOF &&
    -+		Commit M
    -+		EOF
    -+	git add -u &&
    -+	test_tick &&
    -+	git commit -m "Commit M" &&
    -+	test_tick &&
    -+	git tag -m "v2" v2 HEAD &&
    -+
    -+	cat >release.txt <<-EOF &&
    -+		Commit N
    -+		EOF
    -+	git add -u &&
    -+	test_tick &&
    -+	git commit -m "Commit N" &&
    -+	test_tick &&
    -+	git tag -m "v3" v3 HEAD &&
    -+	L=$(git rev-parse HEAD~2) &&
    -+	M=$(git rev-parse HEAD~) &&
    -+	N=$(git rev-parse HEAD) &&
    -+	TAG2=$(git rev-parse refs/tags/v2) &&
    -+	TAG3=$(git rev-parse refs/tags/v3) &&
    -+
    -+	# merge commit O
    -+	git checkout main &&
    -+	test_tick &&
    -+	git merge --no-ff --no-edit tags/v2 &&
    -+	O=$(git rev-parse HEAD) &&
    -+
    -+	# commit P
    ++	# branch main: merge commit O, commit P
     +	git checkout main &&
    -+	cat >main.txt <<-EOF &&
    -+		Commit P
    -+		EOF
    -+	git add main.txt &&
    -+	test_tick &&
    -+	git commit -m "Commit P" &&
    -+	P=$(git rev-parse HEAD)
    ++	test_commit_setvar O --merge tags/v2 "Merge commit O" &&
    ++	test_commit_setvar P "Commit P" main.txt
     +'
     +
     +test_expect_success 'create bundle from special rev: main^!' '
    @@ t/t6020-bundle-misc.sh (new)
     +'
     +
     +test_expect_success 'create bundle with --since option' '
    ++	since="Thu Apr 7 15:26:13 2005 -0700" &&
    ++	git log -1 --pretty="%ad" $M >actual &&
    ++	echo "$since" >expect &&
    ++	test_cmp expect actual &&
    ++
     +	git bundle create since.bdl \
    -+		--since "Thu Apr 7 15:26:13 2005 -0700" \
    -+		--all &&
    ++		--since "$since" --all &&
     +
     +	git bundle list-heads since.bdl |
     +		make_user_friendly_and_stable_output >actual &&
    @@ t/t6020-bundle-misc.sh (new)
     +		EOF
     +	test_i18ncmp expect actual &&
     +
    -+	test_thin_bundle_object_count since.bdl 16
    ++	test_bundle_object_count --thin since.bdl 16
     +'
     +
     +test_expect_success 'create bundle 1 - no prerequisites' '
2:  86ad41e4d4 = 2:  48ef4aa44e bundle: arguments can be read from stdin

--
Jiang Xin (2):
  bundle: lost objects when removing duplicate pendings
  bundle: arguments can be read from stdin

 bundle.c                | 111 ++++----
 object.c                |  10 +-
 t/t5607-clone-bundle.sh |   4 +-
 t/t6020-bundle-misc.sh  | 546 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 614 insertions(+), 57 deletions(-)
 create mode 100755 t/t6020-bundle-misc.sh

-- 
2.30.0.2.g06d2f50715


^ permalink raw reply	[relevance 5%]

* Re: [PATCH 1/1] commit: make the sign-off trailer configurable
  @ 2020-01-06 20:31  4%         ` Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2020-01-06 20:31 UTC (permalink / raw)
  To: Derrick Stolee; +Cc: Hans Jerry Illikainen, git

Derrick Stolee <stolee@gmail.com> writes:

> Since I started the line of "this isn't a bad idea" I'll follow up with
> the historical search. Here are previous attempts from 2018 [1], 2015 [2],
> 2010 [3].
>
> Thanks,
> -Stolee
>
> [1] https://lore.kernel.org/git/20180204020318.4363-1-chenjingpiao@gmail.com/
> [2] https://lore.kernel.org/git/1435217454-5718-1-git-send-email-cmarcelo@gmail.com/
> [3] https://lore.kernel.org/git/alpine.LNX.2.00.1001131635510.16395@vqena.qenxr.bet.am/

Thanks.  In an earlier thread, we did

https://lore.kernel.org/git/20090401175153.GA90421@macbook.lan/

to which I said "... the wording we can update if somebody can come
up with a better one" in its follow-up.  Perhaps it's time for us to
be that somebody to help everybody to be on the same page.

Here is my attempt, starting from what I wrote in

https://lore.kernel.org/git/xmqqtw9m5s5m.fsf@gitster.mtv.corp.google.com/

-- >8 --
Subject: commit -s: document why commit.signoff option will not be added


Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 As I said in https://lore.kernel.org/git/7veiw69p26.fsf@gitster.siamese.dyndns.org/
 I have a mixed feeling about this.  To projects that use the same
 definition of what SoB means, not adding the configuration ever is
 the right thing to do, but Git is to be used by other projects, and
 some of them may use SoB with a completely different meaning that
 has no legal weight---and to them, lack of such an automation may
 be a bug.  So ...

 Documentation/git-commit.txt | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index ced5a9beab..1909551087 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -171,6 +171,13 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 	the rights to submit this work under the same license and
 	agrees to a Developer Certificate of Origin
 	(see http://developercertificate.org/ for more information).
++
+As it makes it harder to argue against one who tells the court "that
+log message ends with a SoB by person X but it is very plausible
+that it was done by inertia without person X really intending to
+certify what DCO says, and the SoB is meaningless." to more
+publicized ways to add SoB automatically, Git does not (and will not)
+have a configuration variable to enable it by default.
 
 -n::
 --no-verify::


^ permalink raw reply related	[relevance 4%]

* Re: [PATCH 1/1] commit: make the sign-off trailer configurable
  2020-01-05 17:41 15% ` [PATCH 1/1] " Hans Jerry Illikainen
@ 2020-01-06 13:38  6%   ` Derrick Stolee
    0 siblings, 1 reply; 171+ results
From: Derrick Stolee @ 2020-01-06 13:38 UTC (permalink / raw)
  To: Hans Jerry Illikainen, git

On 1/5/2020 12:41 PM, Hans Jerry Illikainen wrote:
> The commit builtin did not previously have a configuration option to
> enable the 'Signed-off-by' trailer by default.
> 
> For some use-cases (namely, when the user doesn't always have the right
> to contribute patches to a project) it makes sense to make it a
> conscientious decision to add the signoff trailer.  However, others'
> might always have the right to ship patches -- in which case it makes
> sense to have an option to add the trailer by default for projects that
> require it.

My initial thought was that the sign-off was supposed to be a purposeful
decision, but then I also realized that I never do anything in the Git
codebase that I _can't_ put online under the GPL. (It may not make it
upstream, but it will always be put online somewhere.)

> This patch introduces a commit.signOff configuration option that
> determine whether the trailer should be added for commits.  It can be
> overridden with the --(no-)signoff command-line option.

With that in mind, I think this is a valuable feature.
 
> Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com>

Did you generate this with your config option? ;)

> +commit.signOff::
> +	A boolean to specify whether commits should enable the
> +	`-s/--signoff` option by default.  *Note:* Adding the
> +	Signed-off-by: line to a commit message should be a conscious
> +	act and means that you certify you have the rights to submit the
> +	work under the same open source license.  Please see the
> +	'SubmittingPatches' document for further discussion.
> +

I wonder about the language of "should be a conscious act" here. It's
as if you are trying to convince someone to not use this feature. Perhaps
switch it to "is a deliberate act" and add something such as "Enable this
value only in repos where you are the only user and always have these
rights."

The multi-user scenario may be worth clarifying explicitly here. If there
is any chance that another user will join the machine and use that same
repo, then they would have a different user.name and user.email in their
global config (probably) but this as a local setting would provide their
sign-off.

> diff --git a/builtin/commit.c b/builtin/commit.c
> index c70ad01cc9..497e29c58c 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1474,6 +1474,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
>  		sign_commit = git_config_bool(k, v) ? "" : NULL;
>  		return 0;
>  	}
> +	if (!strcmp(k, "commit.signoff")) {
> +		signoff = git_config_bool(k, v);
> +		return 0;
> +	}

Since we are directly modifying the same global used by the --[no-]signoff
option, I verified that the config options are checked before the arguments
are parsed. Thus, --no-signoff will override commit.signOff=true...

> +test_expect_success 'commit.signOff=true' '
> +	test_config commit.signOff true &&
> +	echo 1 >>positive &&
> +	git add positive &&
> +	git commit -m "thank you" &&
> +	git cat-file commit HEAD >commit.msg &&
> +	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
> +	git var GIT_COMMITTER_IDENT >ident &&
> +	sed -e "s/>.*/>/" ident >expected &&
> +	test_cmp expected actual
> +'
> +
> +test_expect_success 'commit.signOff=true and --no-signoff' '
> +	test_config commit.signOff true &&
> +	echo 2 >>positive &&
> +	git add positive &&
> +	git commit --no-signoff -m "thank you" &&
> +	git cat-file commit HEAD >commit.msg &&
> +	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
> +	git var GIT_COMMITTER_IDENT >ident &&
> +	sed -e "s/>.*/>/" ident >expected &&
> +	! test_cmp expected actual
> +'

...which you test here, too. Excellent.

> +test_expect_success 'commit.signOff=false and --signoff' '
> +	test_config commit.signOff false &&
> +	echo 1 >>positive &&
> +	git add positive &&
> +	git commit --signoff -m "thank you" &&

Perhaps it is worth adding an explicit "-c commit.signOff=false" here?

> +	git cat-file commit HEAD >commit.msg &&
> +	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
> +	git var GIT_COMMITTER_IDENT >ident &&
> +	sed -e "s/>.*/>/" ident >expected &&
> +	test_cmp expected actual
> +'
> +

I wonder if the boilerplate for these tests could be simplified or
shared across the tests?

For example: could we not just use test_i18ngrep to see if commit.msg
contains (or does not contain) the string "Signed-off-by"?

I believe this patch delivers the stated feature well. Hopefully others
can add commentary on its usefulness or possible issues in using it.

Thanks,
-Stolee

^ permalink raw reply	[relevance 6%]

* [PATCH 1/1] commit: make the sign-off trailer configurable
  2020-01-05 17:41  5% [PATCH 0/1] commit: make the sign-off trailer configurable Hans Jerry Illikainen
@ 2020-01-05 17:41 15% ` Hans Jerry Illikainen
  2020-01-06 13:38  6%   ` Derrick Stolee
  0 siblings, 1 reply; 171+ results
From: Hans Jerry Illikainen @ 2020-01-05 17:41 UTC (permalink / raw)
  To: git; +Cc: Hans Jerry Illikainen

The commit builtin did not previously have a configuration option to
enable the 'Signed-off-by' trailer by default.

For some use-cases (namely, when the user doesn't always have the right
to contribute patches to a project) it makes sense to make it a
conscientious decision to add the signoff trailer.  However, others'
might always have the right to ship patches -- in which case it makes
sense to have an option to add the trailer by default for projects that
require it.

This patch introduces a commit.signOff configuration option that
determine whether the trailer should be added for commits.  It can be
overridden with the --(no-)signoff command-line option.

Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com>
---
 Documentation/config/commit.txt |  8 ++++++++
 Documentation/git-commit.txt    |  4 ++++
 builtin/commit.c                |  4 ++++
 t/t7502-commit-porcelain.sh     | 36 +++++++++++++++++++++++++++++++++
 4 files changed, 52 insertions(+)

diff --git a/Documentation/config/commit.txt b/Documentation/config/commit.txt
index 2c95573930..6ebfe384ac 100644
--- a/Documentation/config/commit.txt
+++ b/Documentation/config/commit.txt
@@ -15,6 +15,14 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signOff::
+	A boolean to specify whether commits should enable the
+	`-s/--signoff` option by default.  *Note:* Adding the
+	Signed-off-by: line to a commit message should be a conscious
+	act and means that you certify you have the rights to submit the
+	work under the same open source license.  Please see the
+	'SubmittingPatches' document for further discussion.
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index ced5a9beab..61a362770d 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -165,12 +165,16 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 
 -s::
 --signoff::
+--no-signoff::
 	Add Signed-off-by line by the committer at the end of the commit
 	log message.  The meaning of a signoff depends on the project,
 	but it typically certifies that committer has
 	the rights to submit this work under the same license and
 	agrees to a Developer Certificate of Origin
 	(see http://developercertificate.org/ for more information).
+	This option can be enabled by default with the `commit.signOff`
+	configuration option, in which case it can be disabled
+	temporarily with `--no-signoff`.
 
 -n::
 --no-verify::
diff --git a/builtin/commit.c b/builtin/commit.c
index c70ad01cc9..497e29c58c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1474,6 +1474,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 	if (!strcmp(k, "commit.verbose")) {
 		int is_bool;
 		config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index 14c92e4c25..7510325698 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -151,6 +151,42 @@ test_expect_success 'sign off' '
 
 '
 
+test_expect_success 'commit.signOff=true' '
+	test_config commit.signOff true &&
+	echo 1 >>positive &&
+	git add positive &&
+	git commit -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
+	git var GIT_COMMITTER_IDENT >ident &&
+	sed -e "s/>.*/>/" ident >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'commit.signOff=true and --no-signoff' '
+	test_config commit.signOff true &&
+	echo 2 >>positive &&
+	git add positive &&
+	git commit --no-signoff -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
+	git var GIT_COMMITTER_IDENT >ident &&
+	sed -e "s/>.*/>/" ident >expected &&
+	! test_cmp expected actual
+'
+
+test_expect_success 'commit.signOff=false and --signoff' '
+	test_config commit.signOff false &&
+	echo 1 >>positive &&
+	git add positive &&
+	git commit --signoff -m "thank you" &&
+	git cat-file commit HEAD >commit.msg &&
+	sed -ne "s/Signed-off-by: //p" commit.msg >actual &&
+	git var GIT_COMMITTER_IDENT >ident &&
+	sed -e "s/>.*/>/" ident >expected &&
+	test_cmp expected actual
+'
+
 test_expect_success 'multiple -m' '
 
 	>negative &&
-- 
2.25.0.rc1.298.g45d5f025e1


^ permalink raw reply related	[relevance 15%]

* [PATCH 0/1] commit: make the sign-off trailer configurable
@ 2020-01-05 17:41  5% Hans Jerry Illikainen
  2020-01-05 17:41 15% ` [PATCH 1/1] " Hans Jerry Illikainen
  0 siblings, 1 reply; 171+ results
From: Hans Jerry Illikainen @ 2020-01-05 17:41 UTC (permalink / raw)
  To: git; +Cc: Hans Jerry Illikainen

This patch that adds commit.signOff as a configuration option.  The
config/commit.txt documentation where the significance of the
signed-off-by trailer is highlighted is copy-pasted from
config/format.txt.

Even with the note in config/{commit,format}.txt, I still think it's
worthwhile to have the trailer as a configuration option for
contributors that always have the rights to send patches.

Hans Jerry Illikainen (1):
  commit: make the sign-off trailer configurable

 Documentation/config/commit.txt |  8 ++++++++
 Documentation/git-commit.txt    |  4 ++++
 builtin/commit.c                |  4 ++++
 t/t7502-commit-porcelain.sh     | 36 +++++++++++++++++++++++++++++++++
 4 files changed, 52 insertions(+)

--
2.25.0.rc1.298.g45d5f025e1

^ permalink raw reply	[relevance 5%]

* Re: [PATCH 1/1] commit: add support to provide --coauthor
  @ 2019-10-08 12:04  7%   ` Phillip Wood
  0 siblings, 0 replies; 171+ results
From: Phillip Wood @ 2019-10-08 12:04 UTC (permalink / raw)
  To: Toon Claes, git; +Cc: Zeger-Jan van de Weg, Denton Liu

On 08/10/2019 11:11, Phillip Wood wrote:
> Hi Toon & Zeger-Jan
> 
> On 08/10/2019 08:49, Toon Claes wrote:
>> Add support to provide the Co-author when committing. For each
>> co-author provided with --coauthor=<coauthor>, a line is added at the
>> bottom of the commit message, like this:
>>
>>      Co-authored-by: <coauthor>
>>
>> It's a common practice use when pairing up with other people and both
>> authors want to in the commit message.
> 
> Thanks for the patch, it's looking good. I can see this being useful to
> some people - I like the way the patch itself is co-authored.
> [...]
>> @@ -803,6 +805,10 @@ static int prepare_to_commit(const char
>> *index_file, const char *prefix,
>>       if (clean_message_contents)
>>           strbuf_stripspace(&sb, 0);
>>
>> +    for (i = 0; i < coauthors.nr; i++) {
>> +        append_coauthor(&sb, coauthors.items[i].string);
> 
> If you look at the existing code that's calling append_signoff() it does
>   append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0)
> The purpose of ignore_non_trailer is to ignore comment and conflicts
> messages at the end of the commit message (there's more detail in a
> comment above it's definition in builtin/commit.c). I think we need to
> pass this offset when adding co-authors as well.
> 
> One question - what is the desired de-duplication behavior of
> Co-authored-by:? What happens if there is already a matching
> Co-authored-by: footer? (It is also possible for the trailers code to
> only ignore an existing footer if it's the last one.) What happens if
> the same Co-authored-by: is duplicated on the command line? It would be
> nice to have this defined and tests to check it's enforced.

I should give a bit more detail here. git-interpret-trailers gives more
control over handling of duplicates that is configurable via 'git
config' than 'commit --signoff' does. The reason for this is that
'commit --signoff' predates the interpret-trailers stuff. As we're
adding a new footer command we should decide if we want it to act like
--signoff or give the user the ability to configure the de-duplication
behavior by using the interpret-trailers code path instead. (I think
format-patch --signoff respects the interpret-trailers config variables
but 'am --signoff' and 'cherry-pick --signoff' do not.

> 
> Another useful addition would be to check that the footer value looks
> sane but that could come later

Looking at the way commit handles --author (grep for force_author in
builtin/commit.c) it should be simple to add these checks - just call
split_ident() and check it returns zero. --author also checks if the
string contains '<' and if it doesn't it uses the string given on the
command line to lookup a matching author in the commit log - that could
be a nice feature to use here too (see the code that calls
find_author_by_nickname()).

Best Wishes

Phillip

 - I don't think we do that for any other
> footers at the moment (though I haven't checked to see if that's really
> true)
> 
>> +    }
>> +
>>       if (signoff)
>>           append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
>>
>> @@ -1504,6 +1510,7 @@ int cmd_commit(int argc, const char **argv,
>> const char *prefix)
>>           OPT_STRING(0, "squash", &squash_message, N_("commit"),
>> N_("use autosquash formatted message to squash specified commit")),
>>           OPT_BOOL(0, "reset-author", &renew_authorship, N_("the
>> commit is authored by me now (used with -C/-c/--amend)")),
>>           OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
>> +        OPT_STRING_LIST(0, "coauthor", &coauthors, N_("co-author"),
>> N_("add Co-authored-by:")),
>>           OPT_FILENAME('t', "template", &template_file, N_("use
>> specified template file")),
>>           OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
>>           OPT_CLEANUP(&cleanup_arg),
>> diff --git a/sequencer.c b/sequencer.c
>> index d648aaf416..8958a22470 100644
>> --- a/sequencer.c
>> +++ b/sequencer.c
>> @@ -36,6 +36,7 @@
>>   #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
>>
>>   static const char sign_off_header[] = "Signed-off-by: ";
>> +static const char coauthor_header[] = "Co-authored-by: ";
>>   static const char cherry_picked_prefix[] = "(cherry picked from
>> commit ";
>>
>>   GIT_PATH_FUNC(git_path_commit_editmsg, "COMMIT_EDITMSG")
>> @@ -4385,15 +4386,9 @@ int sequencer_pick_revisions(struct repository *r,
>>       return res;
>>   }
>>
>> -void append_signoff(struct strbuf *msgbuf, size_t ignore_footer,
>> unsigned flag)
>> +static void append_footer(struct strbuf *msgbuf, struct strbuf* sob,
>> size_t ignore_footer, size_t no_dup_sob)
>>   {
>> -    unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
>> -    struct strbuf sob = STRBUF_INIT;
>> -    int has_footer;
>> -
>> -    strbuf_addstr(&sob, sign_off_header);
>> -    strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
>> -    strbuf_addch(&sob, '\n');
>> +    size_t has_footer;
>>
>>       if (!ignore_footer)
>>           strbuf_complete_line(msgbuf);
>> @@ -4402,11 +4397,11 @@ void append_signoff(struct strbuf *msgbuf,
>> size_t ignore_footer, unsigned flag)
>>        * If the whole message buffer is equal to the sob, pretend that we
>>        * found a conforming footer with a matching sob
>>        */
>> -    if (msgbuf->len - ignore_footer == sob.len &&
>> -        !strncmp(msgbuf->buf, sob.buf, sob.len))
>> +    if (msgbuf->len - ignore_footer == sob->len &&
>> +        !strncmp(msgbuf->buf, sob->buf, sob->len))
>>           has_footer = 3;
>>       else
>> -        has_footer = has_conforming_footer(msgbuf, &sob, ignore_footer);
>> +        has_footer = has_conforming_footer(msgbuf, sob, ignore_footer);
>>
>>       if (!has_footer) {
>>           const char *append_newlines = NULL;
>> @@ -4440,7 +4435,32 @@ void append_signoff(struct strbuf *msgbuf,
>> size_t ignore_footer, unsigned flag)
>>
>>       if (has_footer != 3 && (!no_dup_sob || has_footer != 2))
>>           strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0,
>> -                sob.buf, sob.len);
>> +                sob->buf, sob->len);
>> +}
>> +
>> +void append_signoff(struct strbuf *msgbuf, size_t ignore_footer,
>> unsigned flag)
>> +{
>> +    unsigned no_dup_sob = flag & APPEND_SIGNOFF_DEDUP;
>> +    struct strbuf sob = STRBUF_INIT;
>> +
>> +    strbuf_addstr(&sob, sign_off_header);
>> +    strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
>> +    strbuf_addch(&sob, '\n');
>> +
>> +    append_footer(msgbuf, &sob, ignore_footer, no_dup_sob);
>> +
>> +    strbuf_release(&sob);
>> +}
>> +
>> +void append_coauthor(struct strbuf *msgbuf, const char *coauthor)
>> +{
>> +    struct strbuf sob = STRBUF_INIT;
>> +
>> +    strbuf_addstr(&sob, coauthor_header);
>> +    strbuf_addstr(&sob, coauthor);
>> +    strbuf_addch(&sob, '\n');
>> +
>> +    append_footer(msgbuf, &sob, 0, 1);
> 
> As we have a constant for APPEND_SIGNOFF_DEDUP can we use it here please
> rather than '1' which does not covey the same meaning to the author.
> Also as I said above I think you want to pass in a real value for
> ignore_footer not zero
> 
>>
>>       strbuf_release(&sob);
>>   }
>> diff --git a/sequencer.h b/sequencer.h
>> index 574260f621..e36489fce7 100644
>> --- a/sequencer.h
>> +++ b/sequencer.h
>> @@ -170,6 +170,8 @@ int todo_list_rearrange_squash(struct todo_list
>> *todo_list);
>>    */
>>   void append_signoff(struct strbuf *msgbuf, size_t ignore_footer,
>> unsigned flag);
>>
>> +void append_coauthor(struct strbuf *msgbuf, const char* co_author);
>> +
>>   void append_conflicts_hint(struct index_state *istate,
>>           struct strbuf *msgbuf, enum commit_msg_cleanup_mode
>> cleanup_mode);
>>   enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg,
>> diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
>> index 14c92e4c25..5ed6735cf4 100755
>> --- a/t/t7502-commit-porcelain.sh
>> +++ b/t/t7502-commit-porcelain.sh
>> @@ -138,6 +138,17 @@ test_expect_success 'partial removal' '
>>
>>   '
>>
>> +test_expect_success 'co-author' '
>> +
>> +    >coauthor &&
>> +    git add coauthor &&
>> +    git commit -m "thank you" --co-author="Author
>> <author@example.com>" &&
>> +    git cat-file commit HEAD >commit.msg &&
>> +    sed -ne "s/Co-authored-by: //p" commit.msg >actual &&
>> +    echo "Author <author@example.com>" >expected &&
>> +    test_cmp expected actual
>> +'
> 
> This is fine as far as it goes but it would be nice to test the
> de-duplication behavior once that's defined
> 
> Best Wishes
> 
> Phillip
> 
>>   test_expect_success 'sign off' '
>>
>>       >positive &&
>> -- 
>> 2.22.0.rc3
>>


^ permalink raw reply	[relevance 7%]

* Re: Git does not recognise directory named '${sys:DATA_ROOT_DIR}'
  2019-09-03 13:34  0% ` Taylor Blau
@ 2019-09-03 14:11  0%   ` Σταύρος Ντέντος
  0 siblings, 0 replies; 171+ results
From: Σταύρος Ντέντος @ 2019-09-03 14:11 UTC (permalink / raw)
  To: Taylor Blau; +Cc: git

Hey Taylor,

This was happening on a (much) more massive repository; I simply tried
to dumb down the example.

The original folder did had a folder structure 3 levels deep.
Unfortunately, I don't remember if the leaves were files (or
directories themselves). However, since I "replicated" it, I went
ahead and cleaned up my main repo (sigh).

Thank you for reminding me of the empty-tree case :-)

(Reply-all missed the list)
-- 
Until next time,
Ντέντος Σταύρος

On Tue, Sep 3, 2019 at 4:34 PM Taylor Blau <me@ttaylorr.com> wrote:
>
> Hi,
>
> On Tue, Sep 03, 2019 at 03:44:14PM +0300, Σταύρος Ντέντος wrote:
> > Hello there,
> >
> > While the name is obviously a mistake, git refuses to even acknowledge
> > the directory.
> >
> > ```
> > u@h:~/$ mkdir init-test
> > u@h:~/$ cd init-test
> > u@h:~/init-test$ git init
> > Initialized empty Git repository in /home/u/init-test/.git/
> > u@h:~/init-test$ (master #) mkdir \$\{sys\:DATA_ROOT_DIR\}/
> > u@h:~/init-test$ (master #) git status
> > On branch master
> >
> > No commits yet
> >
> > nothing to commit (create/copy files and use "git add" to track)
> > u@h:~/init-test$ (master #) git add
> > .git/                    ${sys:DATA_ROOT_DIR}/
> > u@h:~/init-test$ (master #) git add \$\{sys\:DATA_ROOT_DIR\}/
> > u@h:~/init-test$ (master #) git commit --signoff -m'a'
> > On branch master
> >
> > Initial commit
> >
> > nothing to commit
> > u@h:~/init-test$ (master #)
> > ```
> >
> > Is that expected?
>
> Git does not track empty trees; that is to say 'git add' on an empty
> directory does not change the status of the index.
>
> Try for example:
>
>   $ git init repo && cd repo
>   $ mkdir -p dir
>   $ git add dir
>   $ git status
>
> And note that 'git status' says there are no changes.
>
> On the other hand, 'git add' performs fine even in a directory named
> '${sys:DATA_ROOT_DIR}'; simply create a file (even an empty one) within
> that directory and then run 'git add'. It will stage your "changes" as
> expected.
>
> If you wish to keep this directory "empty", but stored in Git, a common
> convention is to create an empty '.gitkeep' file in the directory. This
> file is not special in any way to Git, rather it serves as _a_ file to
> keep the directory non-empty.
>
> Hope this helps.
>
> > Ντέντος Σταύρος
>
> Thanks,
> Taylor

^ permalink raw reply	[relevance 0%]

* Re: Git does not recognise directory named '${sys:DATA_ROOT_DIR}'
  2019-09-03 12:44  5% Git does not recognise directory named '${sys:DATA_ROOT_DIR}' Σταύρος Ντέντος
@ 2019-09-03 13:34  0% ` Taylor Blau
  2019-09-03 14:11  0%   ` Σταύρος Ντέντος
  0 siblings, 1 reply; 171+ results
From: Taylor Blau @ 2019-09-03 13:34 UTC (permalink / raw)
  To: Σταύρος Ντέντος
  Cc: git

Hi,

On Tue, Sep 03, 2019 at 03:44:14PM +0300, Σταύρος Ντέντος wrote:
> Hello there,
>
> While the name is obviously a mistake, git refuses to even acknowledge
> the directory.
>
> ```
> u@h:~/$ mkdir init-test
> u@h:~/$ cd init-test
> u@h:~/init-test$ git init
> Initialized empty Git repository in /home/u/init-test/.git/
> u@h:~/init-test$ (master #) mkdir \$\{sys\:DATA_ROOT_DIR\}/
> u@h:~/init-test$ (master #) git status
> On branch master
>
> No commits yet
>
> nothing to commit (create/copy files and use "git add" to track)
> u@h:~/init-test$ (master #) git add
> .git/                    ${sys:DATA_ROOT_DIR}/
> u@h:~/init-test$ (master #) git add \$\{sys\:DATA_ROOT_DIR\}/
> u@h:~/init-test$ (master #) git commit --signoff -m'a'
> On branch master
>
> Initial commit
>
> nothing to commit
> u@h:~/init-test$ (master #)
> ```
>
> Is that expected?

Git does not track empty trees; that is to say 'git add' on an empty
directory does not change the status of the index.

Try for example:

  $ git init repo && cd repo
  $ mkdir -p dir
  $ git add dir
  $ git status

And note that 'git status' says there are no changes.

On the other hand, 'git add' performs fine even in a directory named
'${sys:DATA_ROOT_DIR}'; simply create a file (even an empty one) within
that directory and then run 'git add'. It will stage your "changes" as
expected.

If you wish to keep this directory "empty", but stored in Git, a common
convention is to create an empty '.gitkeep' file in the directory. This
file is not special in any way to Git, rather it serves as _a_ file to
keep the directory non-empty.

Hope this helps.

> Ντέντος Σταύρος

Thanks,
Taylor

^ permalink raw reply	[relevance 0%]

* Git does not recognise directory named '${sys:DATA_ROOT_DIR}'
@ 2019-09-03 12:44  5% Σταύρος Ντέντος
  2019-09-03 13:34  0% ` Taylor Blau
  0 siblings, 1 reply; 171+ results
From: Σταύρος Ντέντος @ 2019-09-03 12:44 UTC (permalink / raw)
  To: git

Hello there,

While the name is obviously a mistake, git refuses to even acknowledge
the directory.

```
u@h:~/$ mkdir init-test
u@h:~/$ cd init-test
u@h:~/init-test$ git init
Initialized empty Git repository in /home/u/init-test/.git/
u@h:~/init-test$ (master #) mkdir \$\{sys\:DATA_ROOT_DIR\}/
u@h:~/init-test$ (master #) git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
u@h:~/init-test$ (master #) git add
.git/                    ${sys:DATA_ROOT_DIR}/
u@h:~/init-test$ (master #) git add \$\{sys\:DATA_ROOT_DIR\}/
u@h:~/init-test$ (master #) git commit --signoff -m'a'
On branch master

Initial commit

nothing to commit
u@h:~/init-test$ (master #)
```

Is that expected?

Ντέντος Σταύρος

^ permalink raw reply	[relevance 5%]

* Re: [PATCH 1/1] commit: add signoff config variable
  2019-08-03 21:11  4% ` brian m. carlson
@ 2019-08-03 21:23  0%   ` Liam Beguin
  0 siblings, 0 replies; 171+ results
From: Liam Beguin @ 2019-08-03 21:23 UTC (permalink / raw)
  To: brian m. carlson, Liam Beguin, Git mailing list

Hi,

Sorry for sending this without checking the archives before...
I understand why this would not be such a good idea given the legal
meaning attached to it.
Thanks,

Liam

On Sat, Aug 3, 2019 at 5:12 PM brian m. carlson
<sandals@crustytoothpaste.net> wrote:
>
> On 2019-08-03 at 19:34:36, Liam Beguin wrote:
> > Add a configuration variable, based on format.signoff, to automatically
> > signoff commit messages.
> >
> > Signed-off-by: Liam Beguin <liambeguin@gmail.com>
>
> This has been proposed several times. It may be interesting to look
> through the history of the list and examine why it hasn't been accepted
> as a feature. A few attempts are chronicled here:
> https://public-inbox.org/git/?q=commit.signoff
>
> This is, however, achievable with a commit-msg hook or using "git
> interpret-trailers" if you are certain this is what you want to do.
> --
> brian m. carlson: Houston, Texas, US
> OpenPGP: https://keybase.io/bk2204

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 1/1] commit: add signoff config variable
  2019-08-03 19:34  8% [PATCH 1/1] commit: add signoff " Liam Beguin
@ 2019-08-03 21:11  4% ` brian m. carlson
  2019-08-03 21:23  0%   ` Liam Beguin
  0 siblings, 1 reply; 171+ results
From: brian m. carlson @ 2019-08-03 21:11 UTC (permalink / raw)
  To: Liam Beguin; +Cc: git

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

On 2019-08-03 at 19:34:36, Liam Beguin wrote:
> Add a configuration variable, based on format.signoff, to automatically
> signoff commit messages.
> 
> Signed-off-by: Liam Beguin <liambeguin@gmail.com>

This has been proposed several times. It may be interesting to look
through the history of the list and examine why it hasn't been accepted
as a feature. A few attempts are chronicled here:
https://public-inbox.org/git/?q=commit.signoff

This is, however, achievable with a commit-msg hook or using "git
interpret-trailers" if you are certain this is what you want to do.
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204

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

^ permalink raw reply	[relevance 4%]

* [PATCH 1/1] commit: add signoff config variable
@ 2019-08-03 19:34  8% Liam Beguin
  2019-08-03 21:11  4% ` brian m. carlson
  0 siblings, 1 reply; 171+ results
From: Liam Beguin @ 2019-08-03 19:34 UTC (permalink / raw)
  To: git; +Cc: Liam Beguin

Add a configuration variable, based on format.signoff, to automatically
signoff commit messages.

Signed-off-by: Liam Beguin <liambeguin@gmail.com>
---
 Documentation/config/commit.txt | 7 +++++++
 builtin/commit.c                | 4 ++++
 2 files changed, 11 insertions(+)

diff --git a/Documentation/config/commit.txt b/Documentation/config/commit.txt
index 2c95573930be..62aaacb0dc74 100644
--- a/Documentation/config/commit.txt
+++ b/Documentation/config/commit.txt
@@ -27,3 +27,10 @@ commit.template::
 commit.verbose::
 	A boolean or int to specify the level of verbose with `git commit`.
 	See linkgit:git-commit[1].
+
+commit.signOff::
+	A boolean value which lets you enable the `-s/--signoff` option of
+	`git commit` by default. *Note:* Adding the Signed-off-by: line to a
+	patch should be a conscious act and means that you certify you have
+	the rights to submit this work under the same open source license.
+	Please see the 'SubmittingPatches' document for further discussion.
diff --git a/builtin/commit.c b/builtin/commit.c
index ae7aaf6dc683..36d70396ace7 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1456,6 +1456,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 
 	status = git_gpg_config(k, v, NULL);
 	if (status)
-- 
2.21.0.777.g83232e38648b


^ permalink raw reply related	[relevance 8%]

* [PATCH v3 36/42] completion: use __gitcomp_builtin in _git_revert
    2018-02-09 11:01  6%   ` [PATCH v3 10/42] completion: use __gitcomp_builtin in _git_cherry_pick Nguyễn Thái Ngọc Duy
@ 2018-02-09 11:02  6%   ` Nguyễn Thái Ngọc Duy
  1 sibling, 0 replies; 171+ results
From: Nguyễn Thái Ngọc Duy @ 2018-02-09 11:02 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Ævar Arnfjörð Bjarmason,
	Eric Sunshine, SZEDER Gábor,
	Nguyễn Thái Ngọc Duy

The new completable option is --gpg-sign

In-progress options like --continue will be part of --git-completion-helper
then filtered out by _git_revert() unless the operation is in
progress. This helps keep marking of these operations in just one place.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 contrib/completion/git-completion.bash | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9aca05d01e..e63f2f2741 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2692,19 +2692,19 @@ _git_reset ()
 	__git_complete_refs
 }
 
+__git_revert_inprogress_options="--continue --quit --abort"
+
 _git_revert ()
 {
 	__git_find_repo_path
 	if [ -f "$__git_repo_path"/REVERT_HEAD ]; then
-		__gitcomp "--continue --quit --abort"
+		__gitcomp "$__git_revert_inprogress_options"
 		return
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--edit --mainline --no-edit --no-commit --signoff
-			--strategy= --strategy-option=
-			"
+		__gitcomp_builtin revert "--no-edit" \
+			"$__git_revert_inprogress_options"
 		return
 		;;
 	esac
-- 
2.16.1.207.gedba492059


^ permalink raw reply related	[relevance 6%]

* [PATCH v3 10/42] completion: use __gitcomp_builtin in _git_cherry_pick
  @ 2018-02-09 11:01  6%   ` Nguyễn Thái Ngọc Duy
  2018-02-09 11:02  6%   ` [PATCH v3 36/42] completion: use __gitcomp_builtin in _git_revert Nguyễn Thái Ngọc Duy
  1 sibling, 0 replies; 171+ results
From: Nguyễn Thái Ngọc Duy @ 2018-02-09 11:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Ævar Arnfjörð Bjarmason,
	Eric Sunshine, SZEDER Gábor,
	Nguyễn Thái Ngọc Duy

The new completable options are:

--allow-empty
--allow-empty-message
--ff
--gpg-sign
--keep-redundant-commits
--strategy-option

In-progress options like --continue will be part of --git-completion-helper
then filtered out by _git_cherry_pick() unless the operation is in
progress. This helps keep marking of these operations in just one place.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 contrib/completion/git-completion.bash | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 7e312f95e9..068def9f6b 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1283,16 +1283,19 @@ _git_cherry ()
 	__git_complete_refs
 }
 
+__git_cherry_pick_inprogress_options="--continue --quit --abort"
+
 _git_cherry_pick ()
 {
 	__git_find_repo_path
 	if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then
-		__gitcomp "--continue --quit --abort"
+		__gitcomp "$__git_cherry_pick_inprogress_options"
 		return
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
+		__gitcomp_builtin cherry-pick "" \
+			"$__git_cherry_pick_inprogress_options"
 		;;
 	*)
 		__git_complete_refs
-- 
2.16.1.207.gedba492059


^ permalink raw reply related	[relevance 6%]

* Re: [GSoC][PATCH] commit: add a commit.signOff config variable
  2018-02-05 21:50  6% ` Stefan Beller
@ 2018-02-06  7:01  6%   ` Chen Jingpiao
  0 siblings, 0 replies; 171+ results
From: Chen Jingpiao @ 2018-02-06  7:01 UTC (permalink / raw)
  To: Stefan Beller; +Cc: git

On 02/05 01:50, Stefan Beller wrote:
> On Sat, Feb 3, 2018 at 6:03 PM, Chen Jingpiao <chenjingpiao@gmail.com> wrote:
> > Add the commit.signOff configuration variable to use the -s or --signoff
> > option of git commit by default.
> >
> > Signed-off-by: Chen Jingpiao <chenjingpiao@gmail.com>
> > ---
> 
> Welcome to the Git community!
> 
> >
> > Though we can configure signoff using format.signOff variable. Someone like to
> > add Signed-off-by line by the committer.
> 
> There is more discussion about this at
> https://public-inbox.org/git/1482946838-28779-1-git-send-email-ehabkost@redhat.com/
> specifically
> https://public-inbox.org/git/xmqqtw9m5s5m.fsf@gitster.mtv.corp.google.com/
> 
> Not sure if there was any other reasons and discussions brought up
> since then, but that discussion seems to not favor patches that
> add .signoff options.

Thank you.

I agree with Johannes Schindelin once said "a signoff _has_ to be a conscious
act, or else  it will lose its meaning."
I think I shouldn't add this configuration variable.

When add configuration variable for sign-off to format-patch have some discussion:
	https://public-inbox.org/git/20090331204338.GA88381@macbook.lan/
	https://public-inbox.org/git/20090401102610.GC26181@coredump.intra.peff.net/
	https://public-inbox.org/git/7veiw69p26.fsf@gitster.siamese.dyndns.org/

--
Chen Jingpiao

^ permalink raw reply	[relevance 6%]

* Re: [GSoC][PATCH v2] commit: add a commit.signOff config variable
  2018-02-05 19:22  6% ` Junio C Hamano
@ 2018-02-06  4:37  6%   ` Chen Jingpiao
  0 siblings, 0 replies; 171+ results
From: Chen Jingpiao @ 2018-02-06  4:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, sunshine

On 02/05 11:22, Junio C Hamano wrote:
> Chen Jingpiao <chenjingpiao@gmail.com> writes:
> 
> > Add the commit.signOff configuration variable to use the -s or --signoff
> > option of git commit by default.
> 
> This is a rather old topic.  Here is one from 2006:
> 
>     https://public-inbox.org/git/Pine.LNX.4.63.0611281426311.30004@wbgn013.biozentrum.uni-wuerzburg.de/
> 
> which was referred to in another discussion in late 2008:
> 
>     https://public-inbox.org/git/20081227070228.6117@nanako3.lavabit.com/
>     https://public-inbox.org/git/7vabaijvxl.fsf@gitster.siamese.dyndns.org/
> 
> I am not sure if the reasons why the last effort was retracted still
> apply to this round (the world certainly has changed in the past 10
> years); it would be good to explain why this time it is different
> ;-).
> 
> Assuming that the new configuration variable is a desirable thing to
> add, the change to the code looks OK.  Documentation updates may
> need more thought in the light of past discussions, though.
> 
> Thanks.

I agree with Johannes Schindelin once said "a signoff _has_ to be a
conscious act, or else  it will lose its meaning."
I think I shouldn't add this configuration variable. Thank you.

--
Chen Jingpiao

^ permalink raw reply	[relevance 6%]

* Re: [GSoC][PATCH] commit: add a commit.signOff config variable
  2018-02-04  2:03 21% [GSoC][PATCH] commit: add a commit.signOff config variable Chen Jingpiao
  2018-02-04 11:31 13% ` Eric Sunshine
@ 2018-02-05 21:50  6% ` Stefan Beller
  2018-02-06  7:01  6%   ` Chen Jingpiao
  1 sibling, 1 reply; 171+ results
From: Stefan Beller @ 2018-02-05 21:50 UTC (permalink / raw)
  To: Chen Jingpiao; +Cc: git

On Sat, Feb 3, 2018 at 6:03 PM, Chen Jingpiao <chenjingpiao@gmail.com> wrote:
> Add the commit.signOff configuration variable to use the -s or --signoff
> option of git commit by default.
>
> Signed-off-by: Chen Jingpiao <chenjingpiao@gmail.com>
> ---

Welcome to the Git community!

>
> Though we can configure signoff using format.signOff variable. Someone like to
> add Signed-off-by line by the committer.

There is more discussion about this at
https://public-inbox.org/git/1482946838-28779-1-git-send-email-ehabkost@redhat.com/
specifically
https://public-inbox.org/git/xmqqtw9m5s5m.fsf@gitster.mtv.corp.google.com/

Not sure if there was any other reasons and discussions brought up
since then, but that discussion seems to not favor patches that
add .signoff options.

Thanks,
Stefan

>
>  Documentation/config.txt     |  4 +++
>  Documentation/git-commit.txt |  2 ++
>  builtin/commit.c             |  4 +++
>  t/t7501-commit.sh            | 69 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 79 insertions(+)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 0e25b2c92..5dec3f0cb 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -1303,6 +1303,10 @@ commit.gpgSign::
>         convenient to use an agent to avoid typing your GPG passphrase
>         several times.
>
> +commit.signOff::
> +       A boolean value which lets you enable the `-s/--signoff` option of
> +       `git commit` by default. See linkgit:git-commit[1].
> +
>  commit.status::
>         A boolean to enable/disable inclusion of status information in the
>         commit message template when using an editor to prepare the commit
> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> index f970a4342..7a28ea765 100644
> --- a/Documentation/git-commit.txt
> +++ b/Documentation/git-commit.txt
> @@ -166,6 +166,8 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
>         the rights to submit this work under the same license and
>         agrees to a Developer Certificate of Origin
>         (see http://developercertificate.org/ for more information).
> +       See the `commit.signOff` configuration variable in
> +       linkgit:git-config[1].
>
>  -n::
>  --no-verify::
> diff --git a/builtin/commit.c b/builtin/commit.c
> index 4610e3d8e..324213254 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1548,6 +1548,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
>                 sign_commit = git_config_bool(k, v) ? "" : NULL;
>                 return 0;
>         }
> +       if (!strcmp(k, "commit.signoff")) {
> +               signoff = git_config_bool(k, v);
> +               return 0;
> +       }
>         if (!strcmp(k, "commit.verbose")) {
>                 int is_bool;
>                 config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
> diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
> index fa61b1a4e..46733ed2a 100755
> --- a/t/t7501-commit.sh
> +++ b/t/t7501-commit.sh
> @@ -505,6 +505,75 @@ Myfooter: x" &&
>         test_cmp expected actual
>  '
>
> +test_expect_success "commit.signoff=true and --signoff omitted" '
> +       echo 7 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=true commit -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       (
> +               echo thank you
> +               echo
> +               git var GIT_COMMITTER_IDENT |
> +               sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +       ) >expected &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=true and --signoff" '
> +       echo 8 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=true commit --signoff -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       (
> +               echo thank you
> +               echo
> +               git var GIT_COMMITTER_IDENT |
> +               sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +       ) >expected &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=true and --no-signoff" '
> +       echo 9 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=true commit --no-signoff -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       echo thank you >expected &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --signoff omitted" '
> +       echo 10 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=false commit -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       echo thank you >expected &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --signoff" '
> +       echo 11 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=false commit --signoff -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       (
> +               echo thank you
> +               echo
> +               git var GIT_COMMITTER_IDENT |
> +               sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +       ) >expected &&
> +       test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --no-signoff" '
> +       echo 12 >positive &&
> +       git add positive &&
> +       git -c commit.signoff=false commit --no-signoff -m "thank you" &&
> +       git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +       echo thank you >expected &&
> +       test_cmp expected actual
> +'
> +
>  test_expect_success 'multiple -m' '
>
>         >negative &&
> --
> 2.16.1.70.g5ccd54536
>

^ permalink raw reply	[relevance 6%]

* Re: [GSoC][PATCH v2] commit: add a commit.signOff config variable
  2018-02-05 10:40 21% [GSoC][PATCH v2] " Chen Jingpiao
@ 2018-02-05 19:22  6% ` Junio C Hamano
  2018-02-06  4:37  6%   ` Chen Jingpiao
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2018-02-05 19:22 UTC (permalink / raw)
  To: Chen Jingpiao; +Cc: git, sunshine

Chen Jingpiao <chenjingpiao@gmail.com> writes:

> Add the commit.signOff configuration variable to use the -s or --signoff
> option of git commit by default.

This is a rather old topic.  Here is one from 2006:

    https://public-inbox.org/git/Pine.LNX.4.63.0611281426311.30004@wbgn013.biozentrum.uni-wuerzburg.de/

which was referred to in another discussion in late 2008:

    https://public-inbox.org/git/20081227070228.6117@nanako3.lavabit.com/
    https://public-inbox.org/git/7vabaijvxl.fsf@gitster.siamese.dyndns.org/

I am not sure if the reasons why the last effort was retracted still
apply to this round (the world certainly has changed in the past 10
years); it would be good to explain why this time it is different
;-).

Assuming that the new configuration variable is a desirable thing to
add, the change to the code looks OK.  Documentation updates may
need more thought in the light of past discussions, though.

Thanks.

^ permalink raw reply	[relevance 6%]

* [GSoC][PATCH v2] commit: add a commit.signOff config variable
@ 2018-02-05 10:40 21% Chen Jingpiao
  2018-02-05 19:22  6% ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Chen Jingpiao @ 2018-02-05 10:40 UTC (permalink / raw)
  To: git; +Cc: sunshine, Chen Jingpiao

Add the commit.signOff configuration variable to use the -s or --signoff
option of git commit by default.

Convenience for those who prefer to add Signed-off-by line by the committer
instead of using format.signOff variable.

Signed-off-by: Chen Jingpiao <chenjingpiao@gmail.com>
---

Previous version of the patch:
[v1]: https://public-inbox.org/git/20180204020318.4363-1-chenjingpiao@gmail.com/

Changes in v2:
	* Update commit message: Move commentary explains to commit message.
	* Update test: Just test two combinations.
	Suggested-by: Eric Sunshine <sunshine@sunshineco.com>

 Documentation/config.txt     |  4 ++++
 Documentation/git-commit.txt |  2 ++
 builtin/commit.c             |  4 ++++
 t/t7501-commit.sh            | 10 ++++++++++
 4 files changed, 20 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0e25b2c92..5dec3f0cb 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1303,6 +1303,10 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signOff::
+	A boolean value which lets you enable the `-s/--signoff` option of
+	`git commit` by default. See linkgit:git-commit[1].
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index f970a4342..7a28ea765 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -166,6 +166,8 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 	the rights to submit this work under the same license and
 	agrees to a Developer Certificate of Origin
 	(see http://developercertificate.org/ for more information).
+	See the `commit.signOff` configuration variable in
+	linkgit:git-config[1].
 
 -n::
 --no-verify::
diff --git a/builtin/commit.c b/builtin/commit.c
index 4610e3d8e..324213254 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1548,6 +1548,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 	if (!strcmp(k, "commit.verbose")) {
 		int is_bool;
 		config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index fa61b1a4e..adaaeea5b 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -505,6 +505,16 @@ Myfooter: x" &&
 	test_cmp expected actual
 '
 
+test_expect_success 'commit.signoff=true & --signoff omitted' '
+	git -c commit.signoff=true commit --allow-empty -m x &&
+	git log -1 --format=%B | grep ^Signed-off-by:
+'
+
+test_expect_success 'commit.signoff=true & --no-signoff' '
+	git -c commit.signoff=true commit --allow-empty -m x --no-signoff &&
+	! git log -1 --format=%B | grep ^Signed-off-by:
+'
+
 test_expect_success 'multiple -m' '
 
 	>negative &&
-- 
2.16.1.70.g5ccd54536


^ permalink raw reply related	[relevance 21%]

* Re: [GSoC][PATCH] commit: add a commit.signOff config variable
  2018-02-04 11:31 13% ` Eric Sunshine
@ 2018-02-04 18:59  6%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 171+ results
From: Ævar Arnfjörð Bjarmason @ 2018-02-04 18:59 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Chen Jingpiao, git


On Sun, Feb 04 2018, Eric Sunshine jotted:

> --- >8 ---
> for cfg in true false
> do
>     for opt in '' --signoff --no-signoff
>     do
>         case "$opt:$cfg" in
>         --signoff:*|:true) expect= ;;
>         --no-signoff:*|:false) expect=! ;;
>         esac
>         test_expect_success "commit.signoff=$cfg & ${opt:---signoff omitted}" '
>             git -c commit.signoff=$cfg commit --allow-empty -m x $opt &&
>             eval "$expect git log -1 --format=%B | grep ^Signed-off-by:"
>         '
>     done
> done
> --- >8 ---
>
> A final consideration is that tests run slowly on Windows, and although
> it's nice to be thorough by testing all six combinations, you can
> probably exercise the new code sufficiently by instead testing just two
> combinations. For instance, instead of all six combinations, test just
> these two:
>
> --- >8 ---
> test_expect_success 'commit.signoff=true & --signoff omitted' '
>     git -c commit.signoff=true commit --allow-empty -m x &&
>     git log -1 --format=%B | grep ^Signed-off-by:
> '
>
> test_expect_success 'commit.signoff=true & --no-signoff' '
>     git -c commit.signoff=true commit --allow-empty -m x --no-signoff &&
>     ! git log -1 --format=%B | grep ^Signed-off-by:
> '
> --- >8 ---

I just skimmed this, but just to this question. I don't think we need to
worry about 2 v.s. 6 tests having an impact on Windows performance, it's
just massive amounts of tests like my in-flight wildmatch test series
that really matter.

But if we are worring about 2 v.s. 6 there's always my in-flight
EXPENSIVE_ON_WINDOWS prereq :)

^ permalink raw reply	[relevance 6%]

* Re: [GSoC][PATCH] commit: add a commit.signOff config variable
  2018-02-04  2:03 21% [GSoC][PATCH] commit: add a commit.signOff config variable Chen Jingpiao
@ 2018-02-04 11:31 13% ` Eric Sunshine
  2018-02-04 18:59  6%   ` Ævar Arnfjörð Bjarmason
  2018-02-05 21:50  6% ` Stefan Beller
  1 sibling, 1 reply; 171+ results
From: Eric Sunshine @ 2018-02-04 11:31 UTC (permalink / raw)
  To: Chen Jingpiao; +Cc: git

On Sun, Feb 04, 2018 at 10:03:18AM +0800, Chen Jingpiao wrote:
> Add the commit.signOff configuration variable to use the -s or --signoff
> option of git commit by default.
> 
> Signed-off-by: Chen Jingpiao <chenjingpiao@gmail.com>
> ---
> 
> Though we can configure signoff using format.signOff variable. Someone like to
> add Signed-off-by line by the committer.

This commentary explains why this feature is desirable, therefore it
would be a good idea to include this in the commit message itself.

> diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
> @@ -505,6 +505,75 @@ Myfooter: x" &&
> +test_expect_success "commit.signoff=true and --signoff omitted" '
> +	echo 7 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=true commit -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	(
> +		echo thank you
> +		echo
> +		git var GIT_COMMITTER_IDENT |
> +		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +	) >expected &&
> +	test_cmp expected actual
> +'

The bodies of these test are quite noisy, doing a lot of work that isn't
really necessary, which makes it difficult to figure out what is really
being tested. Other tests in this script already check that the commit
message is properly formatted when Signed-off-by: is inserted so you
don't need to repeat all that boilerplate here.

Instead, you are interested only in whether or not Signed-off-by: has
been added to the message. For that purpose, you can use a simple 'grep'
expression.

The amount of copy/paste code in these six tests is also unfortunate.
Rather than merely repeating the same code over and over, you could
instead parameterize the test. For instance, you could run all six tests
via a simple for-loop:

--- >8 ---
for cfg in true false
do
    for opt in '' --signoff --no-signoff
    do
        case "$opt:$cfg" in
        --signoff:*|:true) expect= ;;
        --no-signoff:*|:false) expect=! ;;
        esac
        test_expect_success "commit.signoff=$cfg & ${opt:---signoff omitted}" '
            git -c commit.signoff=$cfg commit --allow-empty -m x $opt &&
            eval "$expect git log -1 --format=%B | grep ^Signed-off-by:"
        '
    done
done
--- >8 ---

A final consideration is that tests run slowly on Windows, and although
it's nice to be thorough by testing all six combinations, you can
probably exercise the new code sufficiently by instead testing just two
combinations. For instance, instead of all six combinations, test just
these two:

--- >8 ---
test_expect_success 'commit.signoff=true & --signoff omitted' '
    git -c commit.signoff=true commit --allow-empty -m x &&
    git log -1 --format=%B | grep ^Signed-off-by:
'

test_expect_success 'commit.signoff=true & --no-signoff' '
    git -c commit.signoff=true commit --allow-empty -m x --no-signoff &&
    ! git log -1 --format=%B | grep ^Signed-off-by:
'
--- >8 ---

> +test_expect_success "commit.signoff=true and --signoff" '
> +	echo 8 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=true commit --signoff -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	(
> +		echo thank you
> +		echo
> +		git var GIT_COMMITTER_IDENT |
> +		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +	) >expected &&
> +	test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=true and --no-signoff" '
> +	echo 9 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=true commit --no-signoff -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	echo thank you >expected &&
> +	test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --signoff omitted" '
> +	echo 10 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=false commit -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	echo thank you >expected &&
> +	test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --signoff" '
> +	echo 11 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=false commit --signoff -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	(
> +		echo thank you
> +		echo
> +		git var GIT_COMMITTER_IDENT |
> +		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
> +	) >expected &&
> +	test_cmp expected actual
> +'
> +
> +test_expect_success "commit.signoff=false and --no-signoff" '
> +	echo 12 >positive &&
> +	git add positive &&
> +	git -c commit.signoff=false commit --no-signoff -m "thank you" &&
> +	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
> +	echo thank you >expected &&
> +	test_cmp expected actual
> +'

^ permalink raw reply	[relevance 13%]

* [GSoC][PATCH] commit: add a commit.signOff config variable
@ 2018-02-04  2:03 21% Chen Jingpiao
  2018-02-04 11:31 13% ` Eric Sunshine
  2018-02-05 21:50  6% ` Stefan Beller
  0 siblings, 2 replies; 171+ results
From: Chen Jingpiao @ 2018-02-04  2:03 UTC (permalink / raw)
  To: git; +Cc: Chen Jingpiao

Add the commit.signOff configuration variable to use the -s or --signoff
option of git commit by default.

Signed-off-by: Chen Jingpiao <chenjingpiao@gmail.com>
---

Though we can configure signoff using format.signOff variable. Someone like to
add Signed-off-by line by the committer.

 Documentation/config.txt     |  4 +++
 Documentation/git-commit.txt |  2 ++
 builtin/commit.c             |  4 +++
 t/t7501-commit.sh            | 69 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 79 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0e25b2c92..5dec3f0cb 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1303,6 +1303,10 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signOff::
+	A boolean value which lets you enable the `-s/--signoff` option of
+	`git commit` by default. See linkgit:git-commit[1].
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index f970a4342..7a28ea765 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -166,6 +166,8 @@ The `-m` option is mutually exclusive with `-c`, `-C`, and `-F`.
 	the rights to submit this work under the same license and
 	agrees to a Developer Certificate of Origin
 	(see http://developercertificate.org/ for more information).
+	See the `commit.signOff` configuration variable in
+	linkgit:git-config[1].
 
 -n::
 --no-verify::
diff --git a/builtin/commit.c b/builtin/commit.c
index 4610e3d8e..324213254 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1548,6 +1548,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 	if (!strcmp(k, "commit.verbose")) {
 		int is_bool;
 		config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index fa61b1a4e..46733ed2a 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -505,6 +505,75 @@ Myfooter: x" &&
 	test_cmp expected actual
 '
 
+test_expect_success "commit.signoff=true and --signoff omitted" '
+	echo 7 >positive &&
+	git add positive &&
+	git -c commit.signoff=true commit -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	(
+		echo thank you
+		echo
+		git var GIT_COMMITTER_IDENT |
+		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+	) >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success "commit.signoff=true and --signoff" '
+	echo 8 >positive &&
+	git add positive &&
+	git -c commit.signoff=true commit --signoff -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	(
+		echo thank you
+		echo
+		git var GIT_COMMITTER_IDENT |
+		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+	) >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success "commit.signoff=true and --no-signoff" '
+	echo 9 >positive &&
+	git add positive &&
+	git -c commit.signoff=true commit --no-signoff -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	echo thank you >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success "commit.signoff=false and --signoff omitted" '
+	echo 10 >positive &&
+	git add positive &&
+	git -c commit.signoff=false commit -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	echo thank you >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success "commit.signoff=false and --signoff" '
+	echo 11 >positive &&
+	git add positive &&
+	git -c commit.signoff=false commit --signoff -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	(
+		echo thank you
+		echo
+		git var GIT_COMMITTER_IDENT |
+		sed -e "s/>.*/>/" -e "s/^/Signed-off-by: /"
+	) >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success "commit.signoff=false and --no-signoff" '
+	echo 12 >positive &&
+	git add positive &&
+	git -c commit.signoff=false commit --no-signoff -m "thank you" &&
+	git cat-file commit HEAD | sed -e "1,/^\$/d" >actual &&
+	echo thank you >expected &&
+	test_cmp expected actual
+'
+
 test_expect_success 'multiple -m' '
 
 	>negative &&
-- 
2.16.1.70.g5ccd54536


^ permalink raw reply related	[relevance 21%]

* [PATCH v2 36/41] completion: use __gitcomp_builtin in _git_revert
    2018-01-31 11:05  6% ` [PATCH v2 10/41] completion: use __gitcomp_builtin in _git_cherry_pick Nguyễn Thái Ngọc Duy
@ 2018-01-31 11:05  6% ` Nguyễn Thái Ngọc Duy
    2 siblings, 0 replies; 171+ results
From: Nguyễn Thái Ngọc Duy @ 2018-01-31 11:05 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

The new completable option is --gpg-sign

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/revert.c                       | 12 +++++++++---
 contrib/completion/git-completion.bash |  5 +----
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/builtin/revert.c b/builtin/revert.c
index b9d927eb09..c8e045911b 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -96,9 +96,15 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
 	const char *me = action_name(opts);
 	int cmd = 0;
 	struct option base_options[] = {
-		OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
-		OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
-		OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
+		OPT_CMDMODE_F(0, "quit", &cmd,
+			      N_("end revert or cherry-pick sequence"),
+			      'q', PARSE_OPT_NOCOMPLETE),
+		OPT_CMDMODE_F(0, "continue", &cmd,
+			      N_("resume revert or cherry-pick sequence"),
+			      'c', PARSE_OPT_NOCOMPLETE),
+		OPT_CMDMODE_F(0, "abort", &cmd,
+			      N_("cancel revert or cherry-pick sequence"),
+			      'a', PARSE_OPT_NOCOMPLETE),
 		OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
 		OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
 		OPT_NOOP_NOARG('r', NULL),
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a830c9c854..d6215c494e 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2687,10 +2687,7 @@ _git_revert ()
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--edit --mainline --no-edit --no-commit --signoff
-			--strategy= --strategy-option=
-			"
+		__gitcomp_builtin revert "--no-edit"
 		return
 		;;
 	esac
-- 
2.16.1.205.g271f633410


^ permalink raw reply related	[relevance 6%]

* [PATCH v2 10/41] completion: use __gitcomp_builtin in _git_cherry_pick
  @ 2018-01-31 11:05  6% ` Nguyễn Thái Ngọc Duy
  2018-01-31 11:05  6% ` [PATCH v2 36/41] completion: use __gitcomp_builtin in _git_revert Nguyễn Thái Ngọc Duy
    2 siblings, 0 replies; 171+ results
From: Nguyễn Thái Ngọc Duy @ 2018-01-31 11:05 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

The new completable options are:

--allow-empty
--allow-empty-message
--ff
--gpg-sign
--keep-redundant-commits
--strategy-option

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 contrib/completion/git-completion.bash | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 61880275ed..1b2e510cf6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1281,7 +1281,7 @@ _git_cherry_pick ()
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
+		__gitcomp_builtin cherry-pick
 		;;
 	*)
 		__git_complete_refs
-- 
2.16.1.205.g271f633410


^ permalink raw reply related	[relevance 6%]

* Re: [PATCH] fixup! log: add exhaustive tests for pattern style options & config
  @ 2017-05-16  6:15  5%         ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 171+ results
From: Ævar Arnfjörð Bjarmason @ 2017-05-16  6:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, Git Mailing List

On Tue, May 16, 2017 at 2:46 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
>> On Mon, 15 May 2017, Junio C Hamano wrote:
>>
>>> My knee-jerk reaction matched Dscho's, but grep is about contents,
>>> and we should be able to test this if we used a sensible tagnames or
>>> didn't use any.  Glad to see somebody can step back and think ;-)
>>
>> Maybe somebody should step back even further and think even more, as we
>> could adjust test_commit to mangle the argument into a tag name that is
>> legal even with a refs backend relying on NTFS.
>
> Perhaps, but I am not sure if that is needed.
>
> The point of the helper is to serve as a simple "we are building a
> toy sample history by only adding a one-liner new file" convenience
> helper, and I think it is sensible to keep its definition simple.
> The callers (like the ones being added in the rerolled patch under
> discussion) with special needs can supply tagname when the default
> one is not suitable.
>
> In hindsight, perhaps it would have been better if the default for
> the helper were _not_ to create any tag (and callers who care about
> tags can optionally tell it to add tag, or tag the resulting commit
> themselves), but that is lamenting water under the bridge.

This works, but I wonder if it's worth it to solve this one-off issue:

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 5ee124332a..4cab67c410 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -195,7 +195,15 @@ test_commit () {
                test_tick
        fi &&
        git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
-       git ${indir:+ -C "$indir"} tag "${4:-$1}"
+       if test -n "$4"
+       then
+               git ${indir:+ -C "$indir"} tag "$4"
+       elif test -n "$(echo $1 | tr -d A-Za-z0-9/~_.#-)"
+       then
+               error "Implicitly created tag '$1' looks unusual,
probably fails outside *nix"
+       else
+               git ${indir:+ -C "$indir"} tag "$1"
+       fi
 }

 # Call test_merge with the arguments "<message> <commit>", where <commit>

^ permalink raw reply related	[relevance 5%]

* Re: [PATCH v4 03/12] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  2013-02-12 10:17  6% ` [PATCH v4 03/12] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
@ 2017-05-13 17:41  0%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 171+ results
From: Ævar Arnfjörð Bjarmason @ 2017-05-13 17:41 UTC (permalink / raw)
  To: Brandon Casey
  Cc: Git Mailing List, Junio C Hamano,
	Nguyễn Thái Ngọc Duy, Jonathan Nieder,
	Brandon Casey

On Tue, Feb 12, 2013 at 11:17 AM, Brandon Casey <drafnel@gmail.com> wrote:
> The <message> part of test_commit() may not be appropriate for a tag name.
> So let's allow test_commit to accept a fourth argument to specify the tag
> name.

[Kind of late to notice, I know]

I see nobody spotted in four rounds of reviews that this commit didn't
update the corresponding t/README docs for test_commit.

> Signed-off-by: Brandon Casey <bcasey@nvidia.com>
> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
> ---
>  t/test-lib-functions.sh | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
> index fa62d01..61d0804 100644
> --- a/t/test-lib-functions.sh
> +++ b/t/test-lib-functions.sh
> @@ -135,12 +135,12 @@ test_pause () {
>         fi
>  }
>
> -# Call test_commit with the arguments "<message> [<file> [<contents>]]"
> +# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
>  #
>  # This will commit a file with the given contents and the given commit
> -# message.  It will also add a tag with <message> as name.
> +# message, and tag the resulting commit with the given tag name.
>  #
> -# Both <file> and <contents> default to <message>.
> +# <file>, <contents>, and <tag> all default to <message>.
>
>  test_commit () {
>         notick= &&
> @@ -168,7 +168,7 @@ test_commit () {
>                 test_tick
>         fi &&
>         git commit $signoff -m "$1" &&
> -       git tag "$1"
> +       git tag "${4:-$1}"
>  }
>
>  # Call test_merge with the arguments "<message> <commit>", where <commit>
> --
> 1.8.1.3.579.gd9af3b6
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[relevance 0%]

* [PATCHv2 02/14] completion: wrap __git_refs() for better option parsing
  @ 2017-03-23 15:29  2% ` SZEDER Gábor
  0 siblings, 0 replies; 171+ results
From: SZEDER Gábor @ 2017-03-23 15:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, SZEDER Gábor

__git_refs() currently accepts two optional positional parameters: a
remote and a flag for 'git checkout's tracking DWIMery.  To fix a
minor bug, and, more importantly, for faster refs completion, this
series will add three more parameters: a prefix, the current word to
be completed and a suffix, i.e. the options accepted by __gitcomp() &
friends, and will change __git_refs() to list only refs matching that
given current word and to add that given prefix and suffix to the
listed refs.

However, __git_refs() is the helper function that is most likely used
in users' custom completion scriptlets for their own git commands, and
we don't want to break those, so

  - we can't change __git_refs()'s default output format, i.e. we
    can't by default append a trailing space to every listed ref,
    meaning that the suffix parameter containing the default trailing
    space would have to be specified on every invocation, and

  - we can't change the position of existing positional parameters
    either, so there would have to be plenty of set-but-empty
    placeholder positional parameters all over the completion script.

Furthermore, with five positional parameters it would be really hard
to remember which position means what.

To keep callsites simple, add the new wrapper function
__git_complete_refs() around __git_refs(), which:

  - instead of positional parameters accepts real '--opt=val'-style
    options and with minimalistic option parsing translates them to
    __git_refs()'s and __gitcomp_nl()'s positional parameters, and

  - includes the '__gitcomp_nl "$(__git_refs ...)" ...' command
    substitution to make its behavior match its name and the behavior
    of other __git_complete_* functions, and to limit future changes
    in this series to __git_refs() and this new wrapper function.

Call this wrapper function instead of __git_refs() wherever possible
throughout the completion script, i.e. when __git_refs()'s output is
fed to __gitcomp_nl() right away without further processing, which
means all callsites except a single one in the __git_refs2() helper.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
---
 contrib/completion/git-completion.bash | 102 ++++++++++++++++++++-----------
 t/t9902-completion.sh                  | 106 +++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+), 35 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 91fda7ffb..0b90cfa54 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -354,6 +354,8 @@ __git_tags ()
 #    Can be the name of a configured remote, a path, or a URL.
 # 2: In addition to local refs, list unique branches from refs/remotes/ for
 #    'git checkout's tracking DWIMery (optional; ignored, if set but empty).
+#
+# Use __git_complete_refs() instead.
 __git_refs ()
 {
 	local i hash dir track="${2-}"
@@ -446,6 +448,36 @@ __git_refs ()
 	esac
 }
 
+# Completes refs, short and long, local and remote, symbolic and pseudo.
+#
+# Usage: __git_complete_refs [<option>]...
+# --remote=<remote>: The remote to list refs from, can be the name of a
+#                    configured remote, a path, or a URL.
+# --track: List unique remote branches for 'git checkout's tracking DWIMery.
+# --pfx=<prefix>: A prefix to be added to each ref.
+# --cur=<word>: The current ref to be completed.  Defaults to the current
+#               word to be completed.
+# --sfx=<suffix>: A suffix to be appended to each ref instead of the default
+#                 space.
+__git_complete_refs ()
+{
+	local remote track pfx cur_="$cur" sfx=" "
+
+	while test $# != 0; do
+		case "$1" in
+		--remote=*)	remote="${1##--remote=}" ;;
+		--track)	track="yes" ;;
+		--pfx=*)	pfx="${1##--pfx=}" ;;
+		--cur=*)	cur_="${1##--cur=}" ;;
+		--sfx=*)	sfx="${1##--sfx=}" ;;
+		*)		return 1 ;;
+		esac
+		shift
+	done
+
+	__gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx"
+}
+
 # __git_refs2 requires 1 argument (to pass to __git_refs)
 __git_refs2 ()
 {
@@ -554,15 +586,15 @@ __git_complete_revlist_file ()
 	*...*)
 		pfx="${cur_%...*}..."
 		cur_="${cur_#*...}"
-		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		;;
 	*..*)
 		pfx="${cur_%..*}.."
 		cur_="${cur_#*..}"
-		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 }
@@ -649,21 +681,21 @@ __git_complete_remote_or_refspec ()
 		if [ $lhs = 1 ]; then
 			__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
 		else
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	pull|remote)
 		if [ $lhs = 1 ]; then
-			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
 		else
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	push)
 		if [ $lhs = 1 ]; then
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		else
-			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	esac
@@ -1061,7 +1093,7 @@ _git_bisect ()
 
 	case "$subcommand" in
 	bad|good|reset|skip|start)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	*)
 		;;
@@ -1083,7 +1115,7 @@ _git_branch ()
 
 	case "$cur" in
 	--set-upstream-to=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
+		__git_complete_refs --cur="${cur##--set-upstream-to=}"
 		;;
 	--*)
 		__gitcomp "
@@ -1097,7 +1129,7 @@ _git_branch ()
 		if [ $only_local_ref = "y" -a $has_r = "n" ]; then
 			__gitcomp_nl "$(__git_heads)"
 		else
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 		fi
 		;;
 	esac
@@ -1140,18 +1172,18 @@ _git_checkout ()
 	*)
 		# check if --track, --no-track, or --no-guess was specified
 		# if so, disable DWIM mode
-		local flags="--track --no-track --no-guess" track=1
+		local flags="--track --no-track --no-guess" track_opt="--track"
 		if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-			track=''
+			track_opt=''
 		fi
-		__gitcomp_nl "$(__git_refs '' $track)"
+		__git_complete_refs $track_opt
 		;;
 	esac
 }
 
 _git_cherry ()
 {
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_cherry_pick ()
@@ -1166,7 +1198,7 @@ _git_cherry_pick ()
 		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 }
@@ -1216,7 +1248,7 @@ _git_commit ()
 {
 	case "$prev" in
 	-c|-C)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		return
 		;;
 	esac
@@ -1229,7 +1261,7 @@ _git_commit ()
 		;;
 	--reuse-message=*|--reedit-message=*|\
 	--fixup=*|--squash=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		__git_complete_refs --cur="${cur#*=}"
 		return
 		;;
 	--untracked-files=*)
@@ -1267,7 +1299,7 @@ _git_describe ()
 			"
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 __git_diff_algorithms="myers minimal patience histogram"
@@ -1453,7 +1485,7 @@ _git_grep ()
 		;;
 	esac
 
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_help ()
@@ -1621,7 +1653,7 @@ _git_merge ()
 			--rerere-autoupdate --no-rerere-autoupdate --abort --continue"
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_mergetool ()
@@ -1646,7 +1678,7 @@ _git_merge_base ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_mv ()
@@ -1684,7 +1716,7 @@ _git_notes ()
 	,*)
 		case "$prev" in
 		--ref)
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 			;;
 		*)
 			__gitcomp "$subcommands --ref"
@@ -1693,7 +1725,7 @@ _git_notes ()
 		;;
 	add,--reuse-message=*|append,--reuse-message=*|\
 	add,--reedit-message=*|append,--reedit-message=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		__git_complete_refs --cur="${cur#*=}"
 		;;
 	add,--*|append,--*)
 		__gitcomp '--file= --message= --reedit-message=
@@ -1712,7 +1744,7 @@ _git_notes ()
 		-m|-F)
 			;;
 		*)
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 			;;
 		esac
 		;;
@@ -1750,10 +1782,10 @@ __git_complete_force_with_lease ()
 	--*=)
 		;;
 	*:*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur_#*:}"
+		__git_complete_refs --cur="${cur_#*:}"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)" "" "$cur_"
+		__git_complete_refs --cur="$cur_"
 		;;
 	esac
 }
@@ -1829,7 +1861,7 @@ _git_rebase ()
 
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_reflog ()
@@ -1840,7 +1872,7 @@ _git_reflog ()
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
 	else
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 	fi
 }
 
@@ -1986,7 +2018,7 @@ _git_config ()
 		return
 		;;
 	branch.*.merge)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		return
 		;;
 	branch.*.rebase)
@@ -2460,7 +2492,7 @@ _git_remote ()
 
 _git_replace ()
 {
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_reset ()
@@ -2473,7 +2505,7 @@ _git_reset ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_revert ()
@@ -2489,7 +2521,7 @@ _git_revert ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_rm ()
@@ -2597,7 +2629,7 @@ _git_stash ()
 			;;
 		branch,*)
 			if [ $cword -eq 3 ]; then
-				__gitcomp_nl "$(__git_refs)";
+				__git_complete_refs
 			else
 				__gitcomp_nl "$(__git stash list \
 						| sed -n -e 's/:.*//p')"
@@ -2755,7 +2787,7 @@ _git_tag ()
 		fi
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d711bef24..4e7f3076f 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -775,6 +775,112 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer
 	test_cmp expected "$actual"
 '
 
+test_expect_success '__git_complete_refs - simple' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	HEAD Z
+	master Z
+	matching-branch Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	matching-tag Z
+	EOF
+	(
+		cur= &&
+		__git_complete_refs &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - matching' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	matching-branch Z
+	matching-tag Z
+	EOF
+	(
+		cur=mat &&
+		__git_complete_refs &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - remote' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	HEAD Z
+	branch-in-other Z
+	master-in-other Z
+	EOF
+	(
+		cur=
+		__git_complete_refs --remote=other &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - track' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	HEAD Z
+	master Z
+	matching-branch Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	matching-tag Z
+	branch-in-other Z
+	master-in-other Z
+	EOF
+	(
+		cur=
+		__git_complete_refs --track &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - current word' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	matching-branch Z
+	matching-tag Z
+	EOF
+	(
+		cur="--option=mat" &&
+		__git_complete_refs --cur="${cur#*=}" &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - prefix' '
+	sed -e "s/Z$//" >expected <<-EOF &&
+	v1.0..matching-branch Z
+	v1.0..matching-tag Z
+	EOF
+	(
+		cur=v1.0..mat &&
+		__git_complete_refs --pfx=v1.0.. --cur=mat &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - suffix' '
+	cat >expected <<-EOF &&
+	HEAD.
+	master.
+	matching-branch.
+	other/branch-in-other.
+	other/master-in-other.
+	matching-tag.
+	EOF
+	(
+		cur= &&
+		__git_complete_refs --sfx=. &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
 test_expect_success 'teardown after ref completion' '
 	git branch -d matching-branch &&
 	git tag -d matching-tag &&
-- 
2.12.1.485.g1616aa492


^ permalink raw reply related	[relevance 2%]

* [PATCH v2 7/7] completion: recognize more long-options
  @ 2017-02-03 11:01  9% ` cornelius.weig
  0 siblings, 0 replies; 171+ results
From: cornelius.weig @ 2017-02-03 11:01 UTC (permalink / raw)
  To: git; +Cc: szeder.dev, j6t, Cornelius Weig

From: Cornelius Weig <cornelius.weig@tngtech.com>

Command completion only recognizes a subset of the available options for
the various git commands. The set of recognized options needs to balance
between having all useful options and to not clutter the terminal.

This commit adds all long-options that are mentioned in the man-page
synopsis of the respective git command. Possibly dangerous options are
not included in this set, to avoid accidental data loss. The added
options are:

 - apply: --recount --directory=
 - archive: --output
 - branch: --column --no-column --sort= --points-at
 - clone: --no-single-branch --shallow-submodules
 - commit: --patch --short --date --allow-empty
 - describe: --first-parent
 - fetch, pull: --unshallow --update-shallow
 - fsck: --name-objects
 - grep: --break --heading --show-function --function-context
         --untracked --no-index
 - mergetool: --prompt --no-prompt
 - reset: --keep
 - revert: --strategy= --strategy-option=
 - shortlog: --email
 - tag: --merged --no-merged --create-reflog

Signed-off-by: Cornelius Weig <cornelius.weig@tngtech.com>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Reviewed-by: SZEDER Gábor <szeder.dev@gmail.com>
---
 contrib/completion/git-completion.bash | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d8960cf..3545f6a 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -936,6 +936,7 @@ _git_apply ()
 			--apply --no-add --exclude=
 			--ignore-whitespace --ignore-space-change
 			--whitespace= --inaccurate-eof --verbose
+			--recount --directory=
 			"
 		return
 	esac
@@ -974,7 +975,7 @@ _git_archive ()
 	--*)
 		__gitcomp "
 			--format= --list --verbose
-			--prefix= --remote= --exec=
+			--prefix= --remote= --exec= --output
 			"
 		return
 		;;
@@ -1029,6 +1030,7 @@ _git_branch ()
 			--track --no-track --contains --merged --no-merged
 			--set-upstream-to= --edit-description --list
 			--unset-upstream --delete --move --remotes
+			--column --no-column --sort= --points-at
 			"
 		;;
 	*)
@@ -1142,6 +1144,8 @@ _git_clone ()
 			--single-branch
 			--branch
 			--recurse-submodules
+			--no-single-branch
+			--shallow-submodules
 			"
 		return
 		;;
@@ -1183,6 +1187,7 @@ _git_commit ()
 			--reset-author --file= --message= --template=
 			--cleanup= --untracked-files --untracked-files=
 			--verbose --quiet --fixup= --squash=
+			--patch --short --date --allow-empty
 			"
 		return
 	esac
@@ -1201,7 +1206,7 @@ _git_describe ()
 	--*)
 		__gitcomp "
 			--all --tags --contains --abbrev= --candidates=
-			--exact-match --debug --long --match --always
+			--exact-match --debug --long --match --always --first-parent
 			"
 		return
 	esac
@@ -1284,6 +1289,7 @@ __git_fetch_recurse_submodules="yes on-demand no"
 __git_fetch_options="
 	--quiet --verbose --append --upload-pack --force --keep --depth=
 	--tags --no-tags --all --prune --dry-run --recurse-submodules=
+	--unshallow --update-shallow
 "
 
 _git_fetch ()
@@ -1333,7 +1339,7 @@ _git_fsck ()
 	--*)
 		__gitcomp "
 			--tags --root --unreachable --cache --no-reflogs --full
-			--strict --verbose --lost-found
+			--strict --verbose --lost-found --name-objects
 			"
 		return
 		;;
@@ -1377,6 +1383,8 @@ _git_grep ()
 			--max-depth
 			--count
 			--and --or --not --all-match
+			--break --heading --show-function --function-context
+			--untracked --no-index
 			"
 		return
 		;;
@@ -1576,7 +1584,7 @@ _git_mergetool ()
 		return
 		;;
 	--*)
-		__gitcomp "--tool="
+		__gitcomp "--tool= --prompt --no-prompt"
 		return
 		;;
 	esac
@@ -2465,7 +2473,7 @@ _git_reset ()
 
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft --patch"
+		__gitcomp "--merge --mixed --hard --soft --patch --keep"
 		return
 		;;
 	esac
@@ -2481,7 +2489,10 @@ _git_revert ()
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		__gitcomp "
+			--edit --mainline --no-edit --no-commit --signoff
+			--strategy= --strategy-option=
+			"
 		return
 		;;
 	esac
@@ -2509,7 +2520,7 @@ _git_shortlog ()
 		__gitcomp "
 			$__git_log_common_options
 			$__git_log_shortlog_options
-			--numbered --summary
+			--numbered --summary --email
 			"
 		return
 		;;
@@ -2787,8 +2798,8 @@ _git_tag ()
 	--*)
 		__gitcomp "
 			--list --delete --verify --annotate --message --file
-			--sign --cleanup --local-user --force --column --sort
-			--contains --points-at
+			--sign --cleanup --local-user --force --column --sort=
+			--contains --points-at --merged --no-merged --create-reflog
 			"
 		;;
 	esac
-- 
2.10.2


^ permalink raw reply related	[relevance 9%]

* [PATCH 02/12] completion: wrap __git_refs() for better option parsing
  @ 2017-02-03  2:53  2% ` SZEDER Gábor
  0 siblings, 0 replies; 171+ results
From: SZEDER Gábor @ 2017-02-03  2:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, SZEDER Gábor

__git_refs() currently accepts two optional positional parameters: a
remote and a flag for 'git checkout's tracking DWIMery.  To fix a
minor bug, and, more importantly, for faster refs completion, this
series will add three more parameters: a prefix, the current word to
be completed and a suffix, i.e. the options accepted by __gitcomp() &
friends, and will change __git_refs() to list only refs matching that
given current word and to add that given prefix and suffix to the
listed refs.

However, __git_refs() is the helper function that is most likely used
in users' custom completion scriptlets for their own git commands, and
we don't want to break those, so

  - we can't change __git_refs()'s default output format, i.e. we
    can't by default append a trailing space to every listed ref,
    meaning that the suffix parameter containing the default trailing
    space would have to be specified on every invocation, and

  - we can't change the position of existing positional parameters
    either, so there would have to be plenty of set-but-empty
    placeholder positional parameters all over the completion script.

Furthermore, with five positional parameters it would be really hard
to remember which position means what.

To keep callsites simple, add the new wrapper function
__git_complete_refs() around __git_refs(), which:

  - instead of positional parameters accepts real '--opt=val'-style
    options and with minimalistic option parsing translates them to
    __git_refs()'s and __gitcomp_nl()'s positional parameters, and

  - includes the '__gitcomp_nl "$(__git_refs ...)" ...' command
    substitution to make its behavior match its name and the behavior
    of other __git_complete_* functions, and to limit future changes
    in this series to __git_refs() and this new wrapper function.

Call this wrapper function instead of __git_refs() wherever possible
throughout the completion script, i.e. when __git_refs()'s output is
fed to __gitcomp_nl() right away without further processing, which
means all callsites except a single one in the __git_refs2() helper.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
---
 contrib/completion/git-completion.bash | 102 ++++++++++++++++++++-----------
 t/t9902-completion.sh                  | 106 +++++++++++++++++++++++++++++++++
 2 files changed, 173 insertions(+), 35 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index f20d4600c..7f19e2a4f 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -354,6 +354,8 @@ __git_tags ()
 #    Can be the name of a configured remote, a path, or a URL.
 # 2: In addition to local refs, list unique branches from refs/remotes/ for
 #    'git checkout's tracking DWIMery (optional; ignored, if set but empty).
+#
+# Use __git_complete_refs() instead.
 __git_refs ()
 {
 	local i hash dir track="${2-}"
@@ -446,6 +448,36 @@ __git_refs ()
 	esac
 }
 
+# Completes refs, short and long, local and remote, symbolic and pseudo.
+#
+# Usage: __git_complete_refs [<option>]...
+# --remote=<remote>: The remote to list refs from, can be the name of a
+#                    configured remote, a path, or a URL.
+# --track: List unique remote branches for 'git checkout's tracking DWIMery.
+# --pfx=<prefix>: A prefix to be added to each ref.
+# --cur=<word>: The current ref to be completed.  Defaults to the current
+#               word to be completed.
+# --sfx=<suffix>: A suffix to be appended to each ref instead of the default
+#                 space.
+__git_complete_refs ()
+{
+	local remote track pfx cur_="$cur" sfx=" "
+
+	while test $# != 0; do
+		case "$1" in
+		--remote=*)	remote="${1##--remote=}" ;;
+		--track)	track="yes" ;;
+		--pfx=*)	pfx="${1##--pfx=}" ;;
+		--cur=*)	cur_="${1##--cur=}" ;;
+		--sfx=*)	sfx="${1##--sfx=}" ;;
+		*)		return 1 ;;
+		esac
+		shift
+	done
+
+	__gitcomp_nl "$(__git_refs "$remote" "$track")" "$pfx" "$cur_" "$sfx"
+}
+
 # __git_refs2 requires 1 argument (to pass to __git_refs)
 __git_refs2 ()
 {
@@ -554,15 +586,15 @@ __git_complete_revlist_file ()
 	*...*)
 		pfx="${cur_%...*}..."
 		cur_="${cur_#*...}"
-		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		;;
 	*..*)
 		pfx="${cur_%..*}.."
 		cur_="${cur_#*..}"
-		__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+		__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 }
@@ -649,21 +681,21 @@ __git_complete_remote_or_refspec ()
 		if [ $lhs = 1 ]; then
 			__gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
 		else
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	pull|remote)
 		if [ $lhs = 1 ]; then
-			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
 		else
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	push)
 		if [ $lhs = 1 ]; then
-			__gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+			__git_complete_refs --pfx="$pfx" --cur="$cur_"
 		else
-			__gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+			__git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_"
 		fi
 		;;
 	esac
@@ -1061,7 +1093,7 @@ _git_bisect ()
 
 	case "$subcommand" in
 	bad|good|reset|skip|start)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	*)
 		;;
@@ -1083,7 +1115,7 @@ _git_branch ()
 
 	case "$cur" in
 	--set-upstream-to=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}"
+		__git_complete_refs --cur="${cur##--set-upstream-to=}"
 		;;
 	--*)
 		__gitcomp "
@@ -1097,7 +1129,7 @@ _git_branch ()
 		if [ $only_local_ref = "y" -a $has_r = "n" ]; then
 			__gitcomp_nl "$(__git_heads)"
 		else
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 		fi
 		;;
 	esac
@@ -1140,18 +1172,18 @@ _git_checkout ()
 	*)
 		# check if --track, --no-track, or --no-guess was specified
 		# if so, disable DWIM mode
-		local flags="--track --no-track --no-guess" track=1
+		local flags="--track --no-track --no-guess" track_opt="--track"
 		if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-			track=''
+			track_opt=''
 		fi
-		__gitcomp_nl "$(__git_refs '' $track)"
+		__git_complete_refs $track_opt
 		;;
 	esac
 }
 
 _git_cherry ()
 {
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_cherry_pick ()
@@ -1166,7 +1198,7 @@ _git_cherry_pick ()
 		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 }
@@ -1216,7 +1248,7 @@ _git_commit ()
 {
 	case "$prev" in
 	-c|-C)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		return
 		;;
 	esac
@@ -1229,7 +1261,7 @@ _git_commit ()
 		;;
 	--reuse-message=*|--reedit-message=*|\
 	--fixup=*|--squash=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		__git_complete_refs --cur="${cur#*=}"
 		return
 		;;
 	--untracked-files=*)
@@ -1267,7 +1299,7 @@ _git_describe ()
 			"
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 __git_diff_algorithms="myers minimal patience histogram"
@@ -1453,7 +1485,7 @@ _git_grep ()
 		;;
 	esac
 
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_help ()
@@ -1621,7 +1653,7 @@ _git_merge ()
 			--rerere-autoupdate --no-rerere-autoupdate --abort --continue"
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_mergetool ()
@@ -1646,7 +1678,7 @@ _git_merge_base ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_mv ()
@@ -1684,7 +1716,7 @@ _git_notes ()
 	,*)
 		case "$prev" in
 		--ref)
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 			;;
 		*)
 			__gitcomp "$subcommands --ref"
@@ -1693,7 +1725,7 @@ _git_notes ()
 		;;
 	add,--reuse-message=*|append,--reuse-message=*|\
 	add,--reedit-message=*|append,--reedit-message=*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+		__git_complete_refs --cur="${cur#*=}"
 		;;
 	add,--*|append,--*)
 		__gitcomp '--file= --message= --reedit-message=
@@ -1712,7 +1744,7 @@ _git_notes ()
 		-m|-F)
 			;;
 		*)
-			__gitcomp_nl "$(__git_refs)"
+			__git_complete_refs
 			;;
 		esac
 		;;
@@ -1750,10 +1782,10 @@ __git_complete_force_with_lease ()
 	--*=)
 		;;
 	*:*)
-		__gitcomp_nl "$(__git_refs)" "" "${cur_#*:}"
+		__git_complete_refs --cur="${cur_#*:}"
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)" "" "$cur_"
+		__git_complete_refs --cur="$cur_"
 		;;
 	esac
 }
@@ -1829,7 +1861,7 @@ _git_rebase ()
 
 		return
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_reflog ()
@@ -1840,7 +1872,7 @@ _git_reflog ()
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
 	else
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 	fi
 }
 
@@ -1986,7 +2018,7 @@ _git_config ()
 		return
 		;;
 	branch.*.merge)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		return
 		;;
 	branch.*.rebase)
@@ -2460,7 +2492,7 @@ _git_remote ()
 
 _git_replace ()
 {
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_reset ()
@@ -2473,7 +2505,7 @@ _git_reset ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_revert ()
@@ -2489,7 +2521,7 @@ _git_revert ()
 		return
 		;;
 	esac
-	__gitcomp_nl "$(__git_refs)"
+	__git_complete_refs
 }
 
 _git_rm ()
@@ -2597,7 +2629,7 @@ _git_stash ()
 			;;
 		branch,*)
 			if [ $cword -eq 3 ]; then
-				__gitcomp_nl "$(__git_refs)";
+				__git_complete_refs
 			else
 				__gitcomp_nl "$(__git stash list \
 						| sed -n -e 's/:.*//p')"
@@ -2755,7 +2787,7 @@ _git_tag ()
 		fi
 		;;
 	*)
-		__gitcomp_nl "$(__git_refs)"
+		__git_complete_refs
 		;;
 	esac
 
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d711bef24..50c534072 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -775,6 +775,112 @@ test_expect_success '__git_refs - unique remote branches for git checkout DWIMer
 	test_cmp expected "$actual"
 '
 
+test_expect_success '__git_complete_refs - simple' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	HEAD Z
+	master Z
+	matching-branch Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	matching-tag Z
+	EOF
+	(
+		cur= &&
+		__git_complete_refs &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - matching' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	matching-branch Z
+	matching-tag Z
+	EOF
+	(
+		cur=mat &&
+		__git_complete_refs &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - remote' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	HEAD Z
+	branch-in-other Z
+	master-in-other Z
+	EOF
+	(
+		cur=
+		__git_complete_refs --remote=other &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - track' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	HEAD Z
+	master Z
+	matching-branch Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	matching-tag Z
+	branch-in-other Z
+	master-in-other Z
+	EOF
+	(
+		cur=
+		__git_complete_refs --track &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - current word' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	matching-branch Z
+	matching-tag Z
+	EOF
+	(
+		cur="--option=mat" &&
+		__git_complete_refs --cur="${cur#*=}" &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - prefix' '
+	sed -e "s/Z$//g" >expected <<-EOF &&
+	v1.0..matching-branch Z
+	v1.0..matching-tag Z
+	EOF
+	(
+		cur=v1.0..mat &&
+		__git_complete_refs --pfx=v1.0.. --cur=mat &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
+test_expect_success '__git_complete_refs - suffix' '
+	cat >expected <<-EOF &&
+	HEAD.
+	master.
+	matching-branch.
+	other/branch-in-other.
+	other/master-in-other.
+	matching-tag.
+	EOF
+	(
+		cur= &&
+		__git_complete_refs --sfx=. &&
+		print_comp
+	) &&
+	test_cmp expected out
+'
+
 test_expect_success 'teardown after ref completion' '
 	git branch -d matching-branch &&
 	git tag -d matching-tag &&
-- 
2.11.0.555.g967c1bcb3


^ permalink raw reply related	[relevance 2%]

* Re: [PATCH v2 7/7] completion: recognize more long-options
  2017-01-27 21:17  9%   ` [PATCH v2 7/7] " cornelius.weig
@ 2017-01-31 22:17  0%     ` SZEDER Gábor
  0 siblings, 0 replies; 171+ results
From: SZEDER Gábor @ 2017-01-31 22:17 UTC (permalink / raw)
  To: Cornelius Weig; +Cc: j6t, spearce, git

On Fri, Jan 27, 2017 at 10:17 PM,  <cornelius.weig@tngtech.com> wrote:
> From: Cornelius Weig <cornelius.weig@tngtech.com>
>
> Recognize several new long-options for bash completion in the following
> commands:

Adding more long options that git commands learn along the way is
always an improvement.  However, seeing "_several_ new long options"
(or "some long options" in one of the other patches in the series)
makes the reader wonder: are these the only new long options missing
or are there more?  If there are more, why only these are added?  If
there aren't any more missing long options left, then please say so,
e.g. "Add all missing long options, except the potentially
desctructive ones, for the following commands: ...."


>  - apply: --recount --directory=
>  - archive: --output
>  - branch: --column --no-column --sort= --points-at
>  - clone: --no-single-branch --shallow-submodules
>  - commit: --patch --short --date --allow-empty
>  - describe: --first-parent
>  - fetch, pull: --unshallow --update-shallow
>  - fsck: --name-objects
>  - grep: --break --heading --show-function --function-context
>          --untracked --no-index
>  - mergetool: --prompt --no-prompt
>  - reset: --keep
>  - revert: --strategy= --strategy-option=
>  - rm: --force

'--force' is a potentially destructive option, too.

>  - shortlog: --email
>  - tag: --merged --no-merged --create-reflog
>
> Signed-off-by: Cornelius Weig <cornelius.weig@tngtech.com>
> Helped-by: Johannes Sixt <j6t@kdbg.org>
> ---
>  contrib/completion/git-completion.bash | 31 +++++++++++++++++++++----------
>  1 file changed, 21 insertions(+), 10 deletions(-)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 0e09519..933bb6e 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -936,6 +936,7 @@ _git_apply ()
>                         --apply --no-add --exclude=
>                         --ignore-whitespace --ignore-space-change
>                         --whitespace= --inaccurate-eof --verbose
> +                       --recount --directory=
>                         "
>                 return
>         esac
> @@ -974,7 +975,7 @@ _git_archive ()
>         --*)
>                 __gitcomp "
>                         --format= --list --verbose
> -                       --prefix= --remote= --exec=
> +                       --prefix= --remote= --exec= --output
>                         "
>                 return
>                 ;;
> @@ -1029,6 +1030,7 @@ _git_branch ()
>                         --track --no-track --contains --merged --no-merged
>                         --set-upstream-to= --edit-description --list
>                         --unset-upstream --delete --move --remotes
> +                       --column --no-column --sort= --points-at
>                         "
>                 ;;
>         *)
> @@ -1142,6 +1144,8 @@ _git_clone ()
>                         --single-branch
>                         --branch
>                         --recurse-submodules
> +                       --no-single-branch
> +                       --shallow-submodules
>                         "
>                 return
>                 ;;
> @@ -1183,6 +1187,7 @@ _git_commit ()
>                         --reset-author --file= --message= --template=
>                         --cleanup= --untracked-files --untracked-files=
>                         --verbose --quiet --fixup= --squash=
> +                       --patch --short --date --allow-empty
>                         "
>                 return
>         esac
> @@ -1201,7 +1206,7 @@ _git_describe ()
>         --*)
>                 __gitcomp "
>                         --all --tags --contains --abbrev= --candidates=
> -                       --exact-match --debug --long --match --always
> +                       --exact-match --debug --long --match --always --first-parent
>                         "
>                 return
>         esac
> @@ -1284,6 +1289,7 @@ __git_fetch_recurse_submodules="yes on-demand no"
>  __git_fetch_options="
>         --quiet --verbose --append --upload-pack --force --keep --depth=
>         --tags --no-tags --all --prune --dry-run --recurse-submodules=
> +       --unshallow --update-shallow
>  "
>
>  _git_fetch ()
> @@ -1333,7 +1339,7 @@ _git_fsck ()
>         --*)
>                 __gitcomp "
>                         --tags --root --unreachable --cache --no-reflogs --full
> -                       --strict --verbose --lost-found
> +                       --strict --verbose --lost-found --name-objects
>                         "
>                 return
>                 ;;
> @@ -1377,6 +1383,8 @@ _git_grep ()
>                         --max-depth
>                         --count
>                         --and --or --not --all-match
> +                       --break --heading --show-function --function-context
> +                       --untracked --no-index
>                         "
>                 return
>                 ;;
> @@ -1576,7 +1584,7 @@ _git_mergetool ()
>                 return
>                 ;;
>         --*)
> -               __gitcomp "--tool="
> +               __gitcomp "--tool= --prompt --no-prompt"
>                 return
>                 ;;
>         esac
> @@ -2456,7 +2464,7 @@ _git_reset ()
>
>         case "$cur" in
>         --*)
> -               __gitcomp "--merge --mixed --hard --soft --patch"
> +               __gitcomp "--merge --mixed --hard --soft --patch --keep"
>                 return
>                 ;;
>         esac
> @@ -2472,7 +2480,10 @@ _git_revert ()
>         fi
>         case "$cur" in
>         --*)
> -               __gitcomp "--edit --mainline --no-edit --no-commit --signoff"
> +               __gitcomp "
> +                       --edit --mainline --no-edit --no-commit --signoff
> +                       --strategy= --strategy-option=
> +                       "
>                 return
>                 ;;
>         esac
> @@ -2483,7 +2494,7 @@ _git_rm ()
>  {
>         case "$cur" in
>         --*)
> -               __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
> +               __gitcomp "--cached --dry-run --ignore-unmatch --quiet --force"
>                 return
>                 ;;
>         esac
> @@ -2500,7 +2511,7 @@ _git_shortlog ()
>                 __gitcomp "
>                         $__git_log_common_options
>                         $__git_log_shortlog_options
> -                       --numbered --summary
> +                       --numbered --summary --email
>                         "
>                 return
>                 ;;
> @@ -2778,8 +2789,8 @@ _git_tag ()
>         --*)
>                 __gitcomp "
>                         --list --delete --verify --annotate --message --file
> -                       --sign --cleanup --local-user --force --column --sort
> -                       --contains --points-at
> +                       --sign --cleanup --local-user --force --column --sort=
> +                       --contains --points-at --merged --no-merged --create-reflog
>                         "
>                 ;;
>         esac
> --
> 2.10.2
>

^ permalink raw reply	[relevance 0%]

* [PATCH v2 7/7] completion: recognize more long-options
  @ 2017-01-27 21:17  9%   ` cornelius.weig
  2017-01-31 22:17  0%     ` SZEDER Gábor
  0 siblings, 1 reply; 171+ results
From: cornelius.weig @ 2017-01-27 21:17 UTC (permalink / raw)
  To: j6t; +Cc: szeder.dev, spearce, git, Cornelius Weig

From: Cornelius Weig <cornelius.weig@tngtech.com>

Recognize several new long-options for bash completion in the following
commands:

 - apply: --recount --directory=
 - archive: --output
 - branch: --column --no-column --sort= --points-at
 - clone: --no-single-branch --shallow-submodules
 - commit: --patch --short --date --allow-empty
 - describe: --first-parent
 - fetch, pull: --unshallow --update-shallow
 - fsck: --name-objects
 - grep: --break --heading --show-function --function-context
         --untracked --no-index
 - mergetool: --prompt --no-prompt
 - reset: --keep
 - revert: --strategy= --strategy-option=
 - rm: --force
 - shortlog: --email
 - tag: --merged --no-merged --create-reflog

Signed-off-by: Cornelius Weig <cornelius.weig@tngtech.com>
Helped-by: Johannes Sixt <j6t@kdbg.org>
---
 contrib/completion/git-completion.bash | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0e09519..933bb6e 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -936,6 +936,7 @@ _git_apply ()
 			--apply --no-add --exclude=
 			--ignore-whitespace --ignore-space-change
 			--whitespace= --inaccurate-eof --verbose
+			--recount --directory=
 			"
 		return
 	esac
@@ -974,7 +975,7 @@ _git_archive ()
 	--*)
 		__gitcomp "
 			--format= --list --verbose
-			--prefix= --remote= --exec=
+			--prefix= --remote= --exec= --output
 			"
 		return
 		;;
@@ -1029,6 +1030,7 @@ _git_branch ()
 			--track --no-track --contains --merged --no-merged
 			--set-upstream-to= --edit-description --list
 			--unset-upstream --delete --move --remotes
+			--column --no-column --sort= --points-at
 			"
 		;;
 	*)
@@ -1142,6 +1144,8 @@ _git_clone ()
 			--single-branch
 			--branch
 			--recurse-submodules
+			--no-single-branch
+			--shallow-submodules
 			"
 		return
 		;;
@@ -1183,6 +1187,7 @@ _git_commit ()
 			--reset-author --file= --message= --template=
 			--cleanup= --untracked-files --untracked-files=
 			--verbose --quiet --fixup= --squash=
+			--patch --short --date --allow-empty
 			"
 		return
 	esac
@@ -1201,7 +1206,7 @@ _git_describe ()
 	--*)
 		__gitcomp "
 			--all --tags --contains --abbrev= --candidates=
-			--exact-match --debug --long --match --always
+			--exact-match --debug --long --match --always --first-parent
 			"
 		return
 	esac
@@ -1284,6 +1289,7 @@ __git_fetch_recurse_submodules="yes on-demand no"
 __git_fetch_options="
 	--quiet --verbose --append --upload-pack --force --keep --depth=
 	--tags --no-tags --all --prune --dry-run --recurse-submodules=
+	--unshallow --update-shallow
 "
 
 _git_fetch ()
@@ -1333,7 +1339,7 @@ _git_fsck ()
 	--*)
 		__gitcomp "
 			--tags --root --unreachable --cache --no-reflogs --full
-			--strict --verbose --lost-found
+			--strict --verbose --lost-found --name-objects
 			"
 		return
 		;;
@@ -1377,6 +1383,8 @@ _git_grep ()
 			--max-depth
 			--count
 			--and --or --not --all-match
+			--break --heading --show-function --function-context
+			--untracked --no-index
 			"
 		return
 		;;
@@ -1576,7 +1584,7 @@ _git_mergetool ()
 		return
 		;;
 	--*)
-		__gitcomp "--tool="
+		__gitcomp "--tool= --prompt --no-prompt"
 		return
 		;;
 	esac
@@ -2456,7 +2464,7 @@ _git_reset ()
 
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft --patch"
+		__gitcomp "--merge --mixed --hard --soft --patch --keep"
 		return
 		;;
 	esac
@@ -2472,7 +2480,10 @@ _git_revert ()
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		__gitcomp "
+			--edit --mainline --no-edit --no-commit --signoff
+			--strategy= --strategy-option=
+			"
 		return
 		;;
 	esac
@@ -2483,7 +2494,7 @@ _git_rm ()
 {
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+		__gitcomp "--cached --dry-run --ignore-unmatch --quiet --force"
 		return
 		;;
 	esac
@@ -2500,7 +2511,7 @@ _git_shortlog ()
 		__gitcomp "
 			$__git_log_common_options
 			$__git_log_shortlog_options
-			--numbered --summary
+			--numbered --summary --email
 			"
 		return
 		;;
@@ -2778,8 +2789,8 @@ _git_tag ()
 	--*)
 		__gitcomp "
 			--list --delete --verify --annotate --message --file
-			--sign --cleanup --local-user --force --column --sort
-			--contains --points-at
+			--sign --cleanup --local-user --force --column --sort=
+			--contains --points-at --merged --no-merged --create-reflog
 			"
 		;;
 	esac
-- 
2.10.2


^ permalink raw reply related	[relevance 9%]

* [PATCH 7/7] completion: recognize more long-options
  @ 2017-01-22 22:57  9% ` bitte.keine.werbung.einwerfen
  0 siblings, 0 replies; 171+ results
From: bitte.keine.werbung.einwerfen @ 2017-01-22 22:57 UTC (permalink / raw)
  To: git; +Cc: thomas.braun, szeder, john, Cornelius Weig

From: Cornelius Weig <cornelius.weig@tngtech.com>

Recognize several new long-options for bash completion in the following
commands:

 - apply: --recount --directory= --unsafe-paths
 - archive: --prefix= --remote= --exec= --output
 - branch: --column --no-column --sort= --points-at
 - clone: --no-single-branch --shallow-submodules
 - commit: --patch --short --date --allow-empty
 - describe: --first-parent
 - fetch, pull: --unshallow --update-shallow
 - fsck: --name-objects
 - grep: --break --heading --show-function --function-context
         --untracked --no-index
 - mergetool: --prompt --no-prompt
 - reset: --merge --mixed --hard --soft --patch --keep
 - revert: --strategy= --strategy-option=
 - rm: --force
 - shortlog: --email
 - tag: --merged --no-merged --create-reflog
---
 contrib/completion/git-completion.bash | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0e09519..87d3d2c 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -936,6 +936,7 @@ _git_apply ()
 			--apply --no-add --exclude=
 			--ignore-whitespace --ignore-space-change
 			--whitespace= --inaccurate-eof --verbose
+			--recount --directory= --unsafe-paths
 			"
 		return
 	esac
@@ -974,7 +975,7 @@ _git_archive ()
 	--*)
 		__gitcomp "
 			--format= --list --verbose
-			--prefix= --remote= --exec=
+			--prefix= --remote= --exec= --output
 			"
 		return
 		;;
@@ -1029,6 +1030,7 @@ _git_branch ()
 			--track --no-track --contains --merged --no-merged
 			--set-upstream-to= --edit-description --list
 			--unset-upstream --delete --move --remotes
+			--column --no-column --sort= --points-at
 			"
 		;;
 	*)
@@ -1142,6 +1144,8 @@ _git_clone ()
 			--single-branch
 			--branch
 			--recurse-submodules
+			--no-single-branch
+			--shallow-submodules
 			"
 		return
 		;;
@@ -1183,6 +1187,7 @@ _git_commit ()
 			--reset-author --file= --message= --template=
 			--cleanup= --untracked-files --untracked-files=
 			--verbose --quiet --fixup= --squash=
+			--patch --short --date --allow-empty
 			"
 		return
 	esac
@@ -1201,7 +1206,7 @@ _git_describe ()
 	--*)
 		__gitcomp "
 			--all --tags --contains --abbrev= --candidates=
-			--exact-match --debug --long --match --always
+			--exact-match --debug --long --match --always --first-parent
 			"
 		return
 	esac
@@ -1284,6 +1289,7 @@ __git_fetch_recurse_submodules="yes on-demand no"
 __git_fetch_options="
 	--quiet --verbose --append --upload-pack --force --keep --depth=
 	--tags --no-tags --all --prune --dry-run --recurse-submodules=
+	--unshallow --update-shallow
 "
 
 _git_fetch ()
@@ -1333,7 +1339,7 @@ _git_fsck ()
 	--*)
 		__gitcomp "
 			--tags --root --unreachable --cache --no-reflogs --full
-			--strict --verbose --lost-found
+			--strict --verbose --lost-found --name-objects
 			"
 		return
 		;;
@@ -1377,6 +1383,8 @@ _git_grep ()
 			--max-depth
 			--count
 			--and --or --not --all-match
+			--break --heading --show-function --function-context
+			--untracked --no-index
 			"
 		return
 		;;
@@ -1576,7 +1584,7 @@ _git_mergetool ()
 		return
 		;;
 	--*)
-		__gitcomp "--tool="
+		__gitcomp "--tool= --prompt --no-prompt"
 		return
 		;;
 	esac
@@ -2456,7 +2464,7 @@ _git_reset ()
 
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft --patch"
+		__gitcomp "--merge --mixed --hard --soft --patch --keep"
 		return
 		;;
 	esac
@@ -2472,7 +2480,10 @@ _git_revert ()
 	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		__gitcomp "
+			--edit --mainline --no-edit --no-commit --signoff
+			--strategy= --strategy-option=
+			"
 		return
 		;;
 	esac
@@ -2483,7 +2494,7 @@ _git_rm ()
 {
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+		__gitcomp "--cached --dry-run --ignore-unmatch --quiet --force"
 		return
 		;;
 	esac
@@ -2500,7 +2511,7 @@ _git_shortlog ()
 		__gitcomp "
 			$__git_log_common_options
 			$__git_log_shortlog_options
-			--numbered --summary
+			--numbered --summary --email
 			"
 		return
 		;;
@@ -2778,8 +2789,8 @@ _git_tag ()
 	--*)
 		__gitcomp "
 			--list --delete --verify --annotate --message --file
-			--sign --cleanup --local-user --force --column --sort
-			--contains --points-at
+			--sign --cleanup --local-user --force --column --sort=
+			--contains --points-at --merged --no-merged --create-reflog
 			"
 		;;
 	esac
-- 
2.10.2


^ permalink raw reply related	[relevance 9%]

* [PATCHv8 3/6] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-12 19:04 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-12 19:04 UTC (permalink / raw)
  To: gitster; +Cc: git, bmwill, pclouds, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.49.ge1f3b0c.dirty


^ permalink raw reply related	[relevance 11%]

* [PATCHv7 3/6] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-08 21:03 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-08 21:03 UTC (permalink / raw)
  To: bmwill; +Cc: git, pclouds, gitster, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.29.g7c00390.dirty


^ permalink raw reply related	[relevance 11%]

* [PATCHv6 3/7] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-08  1:46 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-08  1:46 UTC (permalink / raw)
  To: bmwill; +Cc: git, pclouds, gitster, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.30.gc512cbd.dirty


^ permalink raw reply related	[relevance 11%]

* [PATCHv5 3/5] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-07 21:01 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-07 21:01 UTC (permalink / raw)
  To: bmwill; +Cc: git, pclouds, gitster, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.28.g2af45f1.dirty


^ permalink raw reply related	[relevance 11%]

* [PATCHv4 3/5] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-02 23:42 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-02 23:42 UTC (permalink / raw)
  To: pclouds, bmwill, gitster; +Cc: git, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.28.g2673dad


^ permalink raw reply related	[relevance 11%]

* [PATCHv3 3/5] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-12-01 20:25 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-12-01 20:25 UTC (permalink / raw)
  To: pclouds; +Cc: git, bmwill, gitster, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.10.2.613.g22f2156


^ permalink raw reply related	[relevance 11%]

* [PATCHv2 3/4] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-11-22 19:22 11% ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2016-11-22 19:22 UTC (permalink / raw)
  To: bmwill, gitster; +Cc: git, jrnieder, Jens.Lehmann, hvoigt, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.4.g3396b6f.dirty


^ permalink raw reply related	[relevance 11%]

* Re: [PATCH 2/3] test-lib-functions.sh: teach test_commit -C <dir>
  2016-11-21 20:41 11% ` [PATCH 2/3] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
@ 2016-11-21 21:04  0%   ` Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2016-11-21 21:04 UTC (permalink / raw)
  To: Stefan Beller; +Cc: bmwill, jrnieder, git, Jens.Lehmann, hvoigt

Stefan Beller <sbeller@google.com> writes:

> Specifically when setting up submodule tests, it comes in handy if
> we can create commits in repositories that are not at the root of
> the tested trash dir. Add "-C <dir>" similar to gits -C parameter
> that will perform the operation in the given directory.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---

Looks useful.

>  t/test-lib-functions.sh | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
> index fdaeb3a96b..579e812506 100644
> --- a/t/test-lib-functions.sh
> +++ b/t/test-lib-functions.sh
> @@ -157,16 +157,21 @@ debug () {
>  	 GIT_TEST_GDB=1 "$@"
>  }
>  
> -# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
> +# Call test_commit with the arguments
> +# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
>  #
>  # This will commit a file with the given contents and the given commit
>  # message, and tag the resulting commit with the given tag name.
>  #
>  # <file>, <contents>, and <tag> all default to <message>.
> +#
> +# If the first argument is "-C", the second argument is used as a path for
> +# the git invocations.
>  
>  test_commit () {
>  	notick= &&
>  	signoff= &&
> +	indir= &&
>  	while test $# != 0
>  	do
>  		case "$1" in
> @@ -176,21 +181,26 @@ test_commit () {
>  		--signoff)
>  			signoff="$1"
>  			;;
> +		-C)
> +			indir="$2"
> +			shift
> +			;;
>  		*)
>  			break
>  			;;
>  		esac
>  		shift
>  	done &&
> +	indir=${indir:+"$indir"/} &&
>  	file=${2:-"$1.t"} &&
> -	echo "${3-$1}" > "$file" &&
> -	git add "$file" &&
> +	echo "${3-$1}" > "$indir$file" &&
> +	git ${indir:+ -C "$indir"} add "$file" &&
>  	if test -z "$notick"
>  	then
>  		test_tick
>  	fi &&
> -	git commit $signoff -m "$1" &&
> -	git tag "${4:-$1}"
> +	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
> +	git ${indir:+ -C "$indir"} tag "${4:-$1}"
>  }
>  
>  # Call test_merge with the arguments "<message> <commit>", where <commit>

^ permalink raw reply	[relevance 0%]

* [PATCH 2/3] test-lib-functions.sh: teach test_commit -C <dir>
  @ 2016-11-21 20:41 11% ` Stefan Beller
  2016-11-21 21:04  0%   ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Stefan Beller @ 2016-11-21 20:41 UTC (permalink / raw)
  To: bmwill, jrnieder; +Cc: git, gitster, Jens.Lehmann, hvoigt, Stefan Beller

Specifically when setting up submodule tests, it comes in handy if
we can create commits in repositories that are not at the root of
the tested trash dir. Add "-C <dir>" similar to gits -C parameter
that will perform the operation in the given directory.

Signed-off-by: Stefan Beller <sbeller@google.com>
---
 t/test-lib-functions.sh | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fdaeb3a96b..579e812506 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -157,16 +157,21 @@ debug () {
 	 GIT_TEST_GDB=1 "$@"
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
+# Call test_commit with the arguments
+# [-C <directory>] <message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
 # message, and tag the resulting commit with the given tag name.
 #
 # <file>, <contents>, and <tag> all default to <message>.
+#
+# If the first argument is "-C", the second argument is used as a path for
+# the git invocations.
 
 test_commit () {
 	notick= &&
 	signoff= &&
+	indir= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -176,21 +181,26 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		-C)
+			indir="$2"
+			shift
+			;;
 		*)
 			break
 			;;
 		esac
 		shift
 	done &&
+	indir=${indir:+"$indir"/} &&
 	file=${2:-"$1.t"} &&
-	echo "${3-$1}" > "$file" &&
-	git add "$file" &&
+	echo "${3-$1}" > "$indir$file" &&
+	git ${indir:+ -C "$indir"} add "$file" &&
 	if test -z "$notick"
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
+	git ${indir:+ -C "$indir"} tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.11.0.rc2.18.g0126045.dirty


^ permalink raw reply related	[relevance 11%]

* [PATCH v14 13/21] unpack-trees: preserve index extensions
  @ 2016-07-03  7:58  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-07-03  7:58 UTC (permalink / raw)
  To: git, pclouds, kmaggg; +Cc: David Turner, Junio C Hamano

From: David Turner <dturner@twopensource.com>

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 633e1dd..1b372ed 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state *istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 8521e85..bc3c989 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2777,3 +2777,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
1.9.1


^ permalink raw reply related	[relevance 4%]

* [PATCH v13 13/20] unpack-trees: preserve index extensions
  @ 2016-06-26  4:14  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-06-26  4:14 UTC (permalink / raw)
  To: git, pclouds, kamggg; +Cc: David Turner, Junio C Hamano

From: David Turner <dturner@twopensource.com>

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 633e1dd..1b372ed 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state *istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 8521e85..bc3c989 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2777,3 +2777,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
1.9.1


^ permalink raw reply related	[relevance 4%]

* [PATCH v12 13/20] unpack-trees: preserve index extensions
  @ 2016-05-19 21:45  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-05-19 21:45 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 633e1dd..1b372ed 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state *istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 8ec4be3..82d4446 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2767,3 +2767,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v10 13/20] unpack-trees: preserve index extensions
  @ 2016-05-12 20:20  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-05-12 20:20 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 633e1dd..1b372ed 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state *istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 8f6b956..75a1b05 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2771,3 +2771,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v9 12/19] unpack-trees: preserve index extensions
  @ 2016-05-09 20:48  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-05-09 20:48 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 633e1dd..1b372ed 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state *istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index b4ed18e..76b65c2 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2769,3 +2769,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v8 12/19] unpack-trees: preserve index extensions
  @ 2016-05-05 21:47  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-05-05 21:47 UTC (permalink / raw)
  To: git, pclouds, Ramsay Jones; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index a167920..e65234d 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index b44b18b..4ad2c19 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2770,3 +2770,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v7 12/19] unpack-trees: preserve index extensions
  @ 2016-04-30  1:02  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-04-30  1:02 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index a167920..e65234d 100644
--- a/cache.h
+++ b/cache.h
@@ -580,6 +580,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index e3f3a1a..1779fa2 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2767,3 +2767,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v6 12/19] unpack-trees: preserve index extensions
  @ 2016-04-27 20:04  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-04-27 20:04 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 4cc89bb..49fa128 100644
--- a/cache.h
+++ b/cache.h
@@ -571,6 +571,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index a57f605..470a27d 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2768,3 +2768,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v5 11/15] unpack-trees: preserve index extensions
  @ 2016-04-19 23:28  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-04-19 23:28 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index 4cc89bb..49fa128 100644
--- a/cache.h
+++ b/cache.h
@@ -571,6 +571,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index fb0168e..65f22f9 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2745,3 +2745,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v4 11/16] unpack-trees: preserve index extensions
  @ 2016-04-13  0:33  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-04-13  0:33 UTC (permalink / raw)
  To: git, pclouds, Ævar Arnfjörð Bjarmason,
	Ramsay Jones
  Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index e43a6e1..5713835 100644
--- a/cache.h
+++ b/cache.h
@@ -571,6 +571,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 89c4356..264a25b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2807,3 +2807,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v3 11/16] unpack-trees: preserve index extensions
  @ 2016-04-06 22:11  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-04-06 22:11 UTC (permalink / raw)
  To: git, pclouds, aevarb, jeffhost; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 22 ++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 36 insertions(+)

diff --git a/cache.h b/cache.h
index e43a6e1..5713835 100644
--- a/cache.h
+++ b/cache.h
@@ -571,6 +571,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define CLOSE_LOCK		(1 << 1)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index b6e9244..470cd7b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2725,3 +2725,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..083516d 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,26 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH v2 12/17] unpack-trees: preserve index extensions
  @ 2016-03-19  1:04  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-03-19  1:04 UTC (permalink / raw)
  To: git, pclouds, Johannes Schindelin; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 23 +++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 37 insertions(+)

diff --git a/cache.h b/cache.h
index 9fa339a..4ae7dd0 100644
--- a/cache.h
+++ b/cache.h
@@ -572,6 +572,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define REFRESH_DAEMON		(1 << 2)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 8e886d1..c141fec 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2742,3 +2742,11 @@ void stat_validity_update(struct stat_validity *sv, int fd)
 		fill_stat_data(sv->sd, &st);
 	}
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..a2c8535 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,27 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* [PATCH 15/19] unpack-trees: preserve index extensions
  @ 2016-03-09 18:36  4% ` David Turner
  0 siblings, 0 replies; 171+ results
From: David Turner @ 2016-03-09 18:36 UTC (permalink / raw)
  To: git, pclouds; +Cc: David Turner

Make git checkout (and other unpack_tree operations) preserve the
untracked cache and watchman status. This is valuable for two reasons:

1. Often, an unpack_tree operation will not touch large parts of the
working tree, and thus most of the untracked cache will continue to be
valid.

2. Even if the untracked cache were entirely invalidated by such an
operation, the user has signaled their intention to have such a cache,
and we don't want to throw it away.

The same logic applies to the watchman state.

Signed-off-by: David Turner <dturner@twopensource.com>
---
 cache.h                           |  1 +
 read-cache.c                      |  8 ++++++++
 t/t7063-status-untracked-cache.sh | 23 +++++++++++++++++++++++
 t/test-lib-functions.sh           |  4 ++++
 unpack-trees.c                    |  1 +
 5 files changed, 37 insertions(+)

diff --git a/cache.h b/cache.h
index 272c928..03c34f1 100644
--- a/cache.h
+++ b/cache.h
@@ -572,6 +572,7 @@ extern void write_watchman_ext(struct strbuf *sb, struct index_state* istate);
 #define REFRESH_DAEMON		(1 << 2)
 extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
 extern int discard_index(struct index_state *);
+extern void move_index_extensions(struct index_state *dst, struct index_state *src);
 extern int unmerged_index(const struct index_state *);
 extern int verify_path(const char *path);
 extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
diff --git a/read-cache.c b/read-cache.c
index 78f5f0e..40d789a 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2591,3 +2591,11 @@ void report_index_stats(struct trace_key *key)
 			 "index stats: file writes       = %10u\n",
 			 nr_read_index, nr_read_shm_index, nr_write_index);
 }
+
+void move_index_extensions(struct index_state *dst, struct index_state *src)
+{
+	dst->untracked = src->untracked;
+	src->untracked = NULL;
+	dst->last_update = src->last_update;
+	src->last_update = NULL;
+}
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index a971884..a2c8535 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -646,4 +646,27 @@ test_expect_success 'test ident field is working' '
 	test_cmp ../expect ../err
 '
 
+test_expect_success 'untracked cache survives a checkout' '
+	git commit --allow-empty -m empty &&
+	test-dump-untracked-cache >../before &&
+	test_when_finished  "git checkout master" &&
+	git checkout -b other_branch &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after &&
+	test_commit test &&
+	test-dump-untracked-cache >../before &&
+	git checkout master &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
+
+test_expect_success 'untracked cache survives a commit' '
+	test-dump-untracked-cache >../before &&
+	git add done/two &&
+	git commit -m commit &&
+	test-dump-untracked-cache >../after &&
+	test_cmp ../before ../after
+'
+
 test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d99eb3..e974b5b 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -186,6 +186,10 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
+	if [ "$(git config core.bare)" = false ]
+	then
+	    git update-index --force-untracked-cache
+	fi
 	git tag "${4:-$1}"
 }
 
diff --git a/unpack-trees.c b/unpack-trees.c
index 9f55cc2..fc90eb3 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1215,6 +1215,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 						  WRITE_TREE_SILENT |
 						  WRITE_TREE_REPAIR);
 		}
+		move_index_extensions(&o->result, o->dst_index);
 		discard_index(o->dst_index);
 		*o->dst_index = o->result;
 	} else {
-- 
2.4.2.767.g62658d5-twtrsrc

^ permalink raw reply related	[relevance 4%]

* Re: [RFC/PATCH] log: add log.firstparent option
  2015-07-25  1:47  6%         ` Jeff King
@ 2015-07-25 17:18  0%           ` Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2015-07-25 17:18 UTC (permalink / raw)
  To: Jeff King; +Cc: Stefan Beller, git@vger.kernel.org, Josh Bleecher Snyder

Jeff King <peff@peff.net> writes:

> This works for "format-patch -s". But I guess that leaves open the
> question of "commit --signoff". It should not matter when making a
> commit new (after all, you have not yet had a chance to put the "---"
> in). But something like "git commit --amend --signoff" might want to
> handle it. Of course we have no idea if any "---" we find there is meant
> to be an email notes-separator by the user, or if they happened to use
> "---" for something else[1] (which is a bad idea if you have an emailed
> patches workflow, but many people do not). So it's a bit riskier.
>
> -Peff
>
> [1] While reading the old "git commit --notes" thread recently, Johan
>     Herland gave a plausible confusing example:
>
>     ...
>       Why
>       ---
>
>       To show that "---" can be part of a commit message. :)

That is all true, but such a commit already is problematic when used
as an input to "am", regardless of where the sign-off goes.  With or
without our change, the intended explanation of "why" part will be
missing from the resulting commit at the receiving end.  The only
difference your change makes is that the resulting truncated log
message at least will have a sign-off, albeit at a place that the
user did not intend to put it.

We could invent a new and more prominent delimiter, teach
"format-patch" to add that between the log and patch if and only if
the log has a three-dashes line in it (with an option to override
that "if and only if" default), and teach "mailsplit" to pay
attention to it.  People who are relying on the fact that a
three-dashes line in the local log message will be stripped off at
the receiving end have to pass that "The commit has three-dash in it
as a cut-mark on purpose; don't add that prominent delimiter" option
when formatting their patches out for submission.

But I somehow think it is not worth the effort.  It is fairly well
established that three-dash lines are cut marks and Johan's example
log message above deliberately violates only to spite itself.  My
knee-jerk advice is that people can just rephrase s/Why/Reason/ and
be done with it.

I dunno.

^ permalink raw reply	[relevance 0%]

* Re: [RFC/PATCH] log: add log.firstparent option
  @ 2015-07-25  1:47  6%         ` Jeff King
  2015-07-25 17:18  0%           ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Jeff King @ 2015-07-25  1:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Stefan Beller, git@vger.kernel.org, Josh Bleecher Snyder

On Fri, Jul 24, 2015 at 06:36:34PM -0700, Jeff King wrote:

> > I think in the cycle we merged Couder's trailer stuff we updated the
> > helper functions to locate where the S-o-b should go in an existing
> > message and consolidated (or, at least "talked about consolidating")
> > them into a single helper.  I do not think we wrote any special case
> > for "a line with three-dashes and nothing else on it" when we did
> > so, but that function would be the logical place to do so.
> 
> Yeah, it nicely has the concept of "ignore this footer". But we would
> want it only to kick in when doing emails (where the "---" is
> syntactically significant), I would think. So something like the patch
> below (no commit message because I'm in an airport right now; I'll add
> tests and repost in the next day or two).

This works for "format-patch -s". But I guess that leaves open the
question of "commit --signoff". It should not matter when making a
commit new (after all, you have not yet had a chance to put the "---"
in). But something like "git commit --amend --signoff" might want to
handle it. Of course we have no idea if any "---" we find there is meant
to be an email notes-separator by the user, or if they happened to use
"---" for something else[1] (which is a bad idea if you have an emailed
patches workflow, but many people do not). So it's a bit riskier.

-Peff

[1] While reading the old "git commit --notes" thread recently, Johan
    Herland gave a plausible confusing example:

      What
      ----

      A commit message using markdown-like formatting conventions.

      Why
      ---

      To show that "---" can be part of a commit message. :)

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 16:01 11%     ` Junio C Hamano
@ 2015-06-25 18:56  6%       ` Matthieu Moy
  0 siblings, 0 replies; 171+ results
From: Matthieu Moy @ 2015-06-25 18:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Caio Marcelo de Oliveira Filho, git

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

> [commit]
>     signoff = "I certify that all my work is licenseable under DCO"

I like this one.

The paranoid version would be

    signoff = "I certify that all my work in /home/my/projects/foo are ..."

to avoid mistakenly have the config option applied to the wrong repo.
But that's probably overkill.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 14:50 20% [PATCH v2] " Caio Marcelo de Oliveira Filho
  2015-06-25 14:55  6% ` Junio C Hamano
@ 2015-06-25 16:36  6% ` Torsten Bögershausen
  1 sibling, 0 replies; 171+ results
From: Torsten Bögershausen @ 2015-06-25 16:36 UTC (permalink / raw)
  To: Caio Marcelo de Oliveira Filho, git

On 2015-06-25 16.50, Caio Marcelo de Oliveira Filho wrote:

> +test_expect_success 'commit.signoff config option' '
> +	test_config commit.signoff true &&
> +	echo "yet another content *narf*" >> foo &&

Minor nit:
The > or >> should be written without a space, like this:
>>foo

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 15:19  6%   ` Caio Marcelo de Oliveira Filho
@ 2015-06-25 16:01 11%     ` Junio C Hamano
  2015-06-25 18:56  6%       ` Matthieu Moy
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2015-06-25 16:01 UTC (permalink / raw)
  To: Caio Marcelo de Oliveira Filho; +Cc: git

Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com> writes:

> A similar concern probably applies to format.signOff option. Would
> be sufficient to add a note about conscious act (like
> format.signOff has) to the config description?

I am generally in negative on automating this.  This is not just you
but makes everybody else's S-o-b less and less meaningful ("Their
tool have ways to add that string randomly, and many of these ways
the user ends up adding that string without even conciously thinking
what they are doing.  Does that string even mean anything anymore?").

One solution might be to make this not a straight-forward boolean,
but an option that superficially takes a string and treats one
specific value as "true" and everything else as "false", e.g.

[commit]
    signoff = "I certify that all my work is licenseable under DCO"

I dunno.

^ permalink raw reply	[relevance 11%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 14:55  6% ` Junio C Hamano
  2015-06-25 15:08  6%   ` Johannes Löthberg
@ 2015-06-25 15:19  6%   ` Caio Marcelo de Oliveira Filho
  2015-06-25 16:01 11%     ` Junio C Hamano
  1 sibling, 1 reply; 171+ results
From: Caio Marcelo de Oliveira Filho @ 2015-06-25 15:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Hi,

> Hmm, I do not recall seeing v1 but that is OK.

http://thread.gmane.org/gmane.comp.version-control.git/272635
http://thread.gmane.org/gmane.comp.version-control.git/272636


> The following immediately comes to mind.
>
> http://thread.gmane.org/gmane.comp.version-control.git/51754/focus=51780

Thanks for the reference, amazed that I ended up using the same title!
From the thread:

> Even though these lines are not digitally signed,
> the intent of adding a Signed-off-by: line with your name is
> that you are certifying its origin, according to the definition
> of DCO (see Documentation/SubmittingPatches).  This should be a
> conscious act from the signer's part, and making it automatic
> with a config variable that you set once and forget makes it
> much less meaningful.

This is a fair point. However I've seen that in practice, in some
cases it's easier
to consider the DCO as the rules for contributing to the entire
project. In those
cases people tend to use commit templates or aliases or hooks, which in practice
automate the signing off act anyway.

A similar concern probably applies to format.signOff option. Would be sufficient
to add a note about conscious act (like format.signOff has) to the
config description?


-- 
Caio Marcelo de Oliveira Filho

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 14:55  6% ` Junio C Hamano
@ 2015-06-25 15:08  6%   ` Johannes Löthberg
  2015-06-25 15:19  6%   ` Caio Marcelo de Oliveira Filho
  1 sibling, 0 replies; 171+ results
From: Johannes Löthberg @ 2015-06-25 15:08 UTC (permalink / raw)
  To: git

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

On 25/06, Junio C Hamano wrote:
>Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com> writes:
>Hmm, I do not recall seeing v1 but that is OK.
>
>The following immediately comes to mind.
>
>http://thread.gmane.org/gmane.comp.version-control.git/51754/focus=51780

To be honest I'm not sure I buy that since we have `git commit -s`, 
which is just as easily added as a really simple git alias.

-- 
Sincerely,
  Johannes Löthberg
  PGP Key ID: 0x50FB9B273A9D0BB5
  https://theos.kyriasis.com/~kyrias/

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

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] commit: add commit.signoff config option
  2015-06-25  8:32 12%   ` Remi Galan Alfonso
@ 2015-06-25 14:57  6%     ` Caio Marcelo de Oliveira Filho
  0 siblings, 0 replies; 171+ results
From: Caio Marcelo de Oliveira Filho @ 2015-06-25 14:57 UTC (permalink / raw)
  To: Remi Galan Alfonso; +Cc: git

> In both tests, you should probably use 'test_config' instead of 'git
> config [...] git config --unset', it takes care of it for you (also
> should prevent the case where the config is not unset when your test
> fails in the middle).

Posted a v2 with this improvement and the bash completion.
Thanks for the review.


-- 
Caio Marcelo de Oliveira Filho

^ permalink raw reply	[relevance 6%]

* Re: [PATCH v2] commit: add commit.signoff config option
  2015-06-25 14:50 20% [PATCH v2] " Caio Marcelo de Oliveira Filho
@ 2015-06-25 14:55  6% ` Junio C Hamano
  2015-06-25 15:08  6%   ` Johannes Löthberg
  2015-06-25 15:19  6%   ` Caio Marcelo de Oliveira Filho
  2015-06-25 16:36  6% ` Torsten Bögershausen
  1 sibling, 2 replies; 171+ results
From: Junio C Hamano @ 2015-06-25 14:55 UTC (permalink / raw)
  To: Caio Marcelo de Oliveira Filho; +Cc: git

Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com> writes:

> In projects that use Signed-off-by, it's convenient to include that line
> in the commit message by default. The commit.signoff config option

Hmm, I do not recall seeing v1 but that is OK.

The following immediately comes to mind.

http://thread.gmane.org/gmane.comp.version-control.git/51754/focus=51780

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] commit: add commit.signoff config option
  2015-06-25  8:43  6% ` Christian Couder
@ 2015-06-25 14:55  6%   ` Caio Marcelo de Oliveira Filho
  0 siblings, 0 replies; 171+ results
From: Caio Marcelo de Oliveira Filho @ 2015-06-25 14:55 UTC (permalink / raw)
  To: Christian Couder; +Cc: git

On Thu, Jun 25, 2015 at 5:43 AM, Christian Couder
<christian.couder@gmail.com> wrote:
> You can use a commit template.
>
> Or you can use the "commit-msg" hook. For example with commands like:
>
> grep "^Signed-off-by:" "$1" ||
> echo "Signed-off-by: $(git config user.name) <$(git config user.email)>" >>"$1"
>
> If you have more complex needs, there is also "git interpret-trailers"
> (see the examples in the man page).

Thanks for the references. I was initially using a commit template to solve
the problem. But I've considered that since we already handle
"Signed-off-by" somewhat specially (e.g. "commit -s"), and how common this
case is, it was worth adding a config option.


-- 
Caio Marcelo de Oliveira Filho

^ permalink raw reply	[relevance 6%]

* [PATCH v2] commit: add commit.signoff config option
@ 2015-06-25 14:50 20% Caio Marcelo de Oliveira Filho
  2015-06-25 14:55  6% ` Junio C Hamano
  2015-06-25 16:36  6% ` Torsten Bögershausen
  0 siblings, 2 replies; 171+ results
From: Caio Marcelo de Oliveira Filho @ 2015-06-25 14:50 UTC (permalink / raw)
  To: git; +Cc: Caio Marcelo de Oliveira Filho

In projects that use Signed-off-by, it's convenient to include that line
in the commit message by default. The commit.signoff config option
allows to add that line in all commits automatically.

Document that this config option can be overriden by using
--no-signoff.

Signed-off-by: Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com>
---

Differences from v1:
* Use test_config helper in the test
* Add bash completion for commit and config

 Documentation/config.txt               |  6 ++++++
 Documentation/git-commit.txt           |  5 +++++
 builtin/commit.c                       |  4 ++++
 contrib/completion/git-completion.bash |  4 +++-
 t/t7500-commit.sh                      | 20 ++++++++++++++++++++
 5 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3e37b93..e019f62 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1089,6 +1089,12 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signoff::
+
+	A boolean to enable/disable whether Signed-off-by line by the
+	committer should be added to all commits at the end of the
+	commit log messages.  Defaults to false.
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 904dafa..7546c7a 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -156,6 +156,11 @@ OPTIONS
 	Add Signed-off-by line by the committer at the end of the commit
 	log message.
 
+--no-signoff::
+	Countermand `commit.signoff` configuration, preventing a
+	Signed-off-by line to be added at the end of the commit log
+	message.
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin/commit.c b/builtin/commit.c
index 254477f..5cfbe57 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1505,6 +1505,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 
 	status = git_gpg_config(k, v, NULL);
 	if (status)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index c97c648..7a79a89 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1123,7 +1123,8 @@ _git_commit ()
 		;;
 	--*)
 		__gitcomp "
-			--all --author= --signoff --verify --no-verify
+			--all --author=
+			--signoff --no-signoff --verify --no-verify
 			--edit --no-edit
 			--amend --include --only --interactive
 			--dry-run --reuse-message= --reedit-message=
@@ -2009,6 +2010,7 @@ _git_config ()
 		color.status.untracked
 		color.status.updated
 		color.ui
+		commit.signoff
 		commit.status
 		commit.template
 		core.abbrev
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 116885a..949272d 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -179,6 +179,26 @@ test_expect_success '--signoff' '
 	test_cmp expect output
 '
 
+test_expect_success 'commit.signoff config option' '
+	test_config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "zort" | git commit -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	test_cmp expect output
+'
+
+cat > expect <<EOF
+no signed off by here
+EOF
+
+test_expect_success '--no-signoff' '
+	test_config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "no signed off by here" | git commit --no-signoff -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	test_cmp expect output
+'
+
 test_expect_success 'commit message from file (1)' '
 	mkdir subdir &&
 	echo "Log in top directory" >log &&
-- 
2.4.4.489.g5bc41de

^ permalink raw reply related	[relevance 20%]

* Re: [PATCH] commit: add commit.signoff config option
  2015-06-25  7:32 20% Caio Marcelo de Oliveira Filho
@ 2015-06-25  8:43  6% ` Christian Couder
  2015-06-25 14:55  6%   ` Caio Marcelo de Oliveira Filho
  0 siblings, 1 reply; 171+ results
From: Christian Couder @ 2015-06-25  8:43 UTC (permalink / raw)
  To: Caio Marcelo de Oliveira Filho; +Cc: git

On Thu, Jun 25, 2015 at 9:32 AM, Caio Marcelo de Oliveira Filho
<cmarcelo@gmail.com> wrote:
> In projects that use Signed-off-by, it's convenient to include that line
> in the commit by default. The commit.signoff config option allows to add
> that line in all commits automatically.

You can use a commit template.

Or you can use the "commit-msg" hook. For example with commands like:

grep "^Signed-off-by:" "$1" ||
echo "Signed-off-by: $(git config user.name) <$(git config user.email)>" >>"$1"

If you have more complex needs, there is also "git interpret-trailers"
(see the examples in the man page).

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] commit: add commit.signoff config option
  2015-06-25  8:21  6% ` Alexander Kuleshov
@ 2015-06-25  8:32 12%   ` Remi Galan Alfonso
  2015-06-25 14:57  6%     ` Caio Marcelo de Oliveira Filho
  0 siblings, 1 reply; 171+ results
From: Remi Galan Alfonso @ 2015-06-25  8:32 UTC (permalink / raw)
  To: cmarcelo; +Cc: git

Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com> writes:
> +test_expect_success 'commit.signoff config option' '
> +        git config commit.signoff true &&
> +        echo "yet another content *narf*" >> foo &&
> +        echo "zort" | git commit -F - foo &&
> +        git cat-file commit HEAD | sed "1,/^\$/d" > output &&
> +        git config --unset commit.signoff &&
> +        test_cmp expect output
> +'
> +
> +cat > expect <<EOF
> +no signed off by here
> +EOF
> +
> +test_expect_success '--no-signoff' '
> +        git config commit.signoff true &&
> +        echo "yet another content *narf*" >> foo &&
> +        echo "no signed off by here" | git commit --no-signoff -F - foo &&
> +        git cat-file commit HEAD | sed "1,/^\$/d" > output &&
> +        git config --unset commit.signoff &&
> +        test_cmp expect output
> +'
> +

In both tests, you should probably use 'test_config' instead of 'git
config [...] git config --unset', it takes care of it for you (also
should prevent the case where the config is not unset when your test
fails in the middle).

For example, the first test would be:
test_expect_success 'commit.signoff config option' '
	test_config commit.signoff true &&
	echo "yet another content *narf*" >> foo &&
	echo "zort" | git commit -F - foo &&
	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
	test_cmp expect output
'

Rémi

^ permalink raw reply	[relevance 12%]

* Re: [PATCH] commit: add commit.signoff config option
  2015-06-25  7:30 20% [PATCH] commit: add commit.signoff config option cmarcelo
@ 2015-06-25  8:21  6% ` Alexander Kuleshov
  2015-06-25  8:32 12%   ` Remi Galan Alfonso
  0 siblings, 1 reply; 171+ results
From: Alexander Kuleshov @ 2015-06-25  8:21 UTC (permalink / raw)
  To: cmarcelo; +Cc: git

On 06/25, cmarcelo@gmail.com wrote:
> From: Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com>
> 
> In projects that use Signed-off-by, it's convenient to include that line
> in the commit by default. The commit.signoff config option allows to add
> that line in all commits automatically.
> 
> Document that this config option can be overriden by using
> --no-signoff.
> 

Hello, also would be great to have bash completion for the --no-signoff

Thank you.

^ permalink raw reply	[relevance 6%]

* [PATCH] commit: add commit.signoff config option
@ 2015-06-25  7:32 20% Caio Marcelo de Oliveira Filho
  2015-06-25  8:43  6% ` Christian Couder
  0 siblings, 1 reply; 171+ results
From: Caio Marcelo de Oliveira Filho @ 2015-06-25  7:32 UTC (permalink / raw)
  To: git; +Cc: Caio Marcelo de Oliveira Filho

In projects that use Signed-off-by, it's convenient to include that line
in the commit by default. The commit.signoff config option allows to add
that line in all commits automatically.

Document that this config option can be overriden by using
--no-signoff.

Signed-off-by: Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com>
---
 Documentation/config.txt     |  6 ++++++
 Documentation/git-commit.txt |  5 +++++
 builtin/commit.c             |  4 ++++
 t/t7500-commit.sh            | 22 ++++++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3e37b93..e019f62 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1089,6 +1089,12 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signoff::
+
+	A boolean to enable/disable whether Signed-off-by line by the
+	committer should be added to all commits at the end of the
+	commit log messages.  Defaults to false.
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 904dafa..7546c7a 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -156,6 +156,11 @@ OPTIONS
 	Add Signed-off-by line by the committer at the end of the commit
 	log message.
 
+--no-signoff::
+	Countermand `commit.signoff` configuration, preventing a
+	Signed-off-by line to be added at the end of the commit log
+	message.
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin/commit.c b/builtin/commit.c
index 254477f..5cfbe57 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1505,6 +1505,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 
 	status = git_gpg_config(k, v, NULL);
 	if (status)
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 116885a..fcb39b4 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -179,6 +179,28 @@ test_expect_success '--signoff' '
 	test_cmp expect output
 '
 
+test_expect_success 'commit.signoff config option' '
+	git config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "zort" | git commit -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	git config --unset commit.signoff &&
+	test_cmp expect output
+'
+
+cat > expect <<EOF
+no signed off by here
+EOF
+
+test_expect_success '--no-signoff' '
+	git config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "no signed off by here" | git commit --no-signoff -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	git config --unset commit.signoff &&
+	test_cmp expect output
+'
+
 test_expect_success 'commit message from file (1)' '
 	mkdir subdir &&
 	echo "Log in top directory" >log &&
-- 
2.4.4.489.gc2a2b54.dirty

^ permalink raw reply related	[relevance 20%]

* [PATCH] commit: add commit.signoff config option
@ 2015-06-25  7:30 20% cmarcelo
  2015-06-25  8:21  6% ` Alexander Kuleshov
  0 siblings, 1 reply; 171+ results
From: cmarcelo @ 2015-06-25  7:30 UTC (permalink / raw)
  To: git; +Cc: Caio Marcelo de Oliveira Filho

From: Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com>

In projects that use Signed-off-by, it's convenient to include that line
in the commit by default. The commit.signoff config option allows to add
that line in all commits automatically.

Document that this config option can be overriden by using
--no-signoff.

Signed-off-by: Caio Marcelo de Oliveira Filho <cmarcelo@gmail.com>
---
 Documentation/config.txt     |  6 ++++++
 Documentation/git-commit.txt |  5 +++++
 builtin/commit.c             |  4 ++++
 t/t7500-commit.sh            | 22 ++++++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3e37b93..e019f62 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1089,6 +1089,12 @@ commit.gpgSign::
 	convenient to use an agent to avoid typing your GPG passphrase
 	several times.
 
+commit.signoff::
+
+	A boolean to enable/disable whether Signed-off-by line by the
+	committer should be added to all commits at the end of the
+	commit log messages.  Defaults to false.
+
 commit.status::
 	A boolean to enable/disable inclusion of status information in the
 	commit message template when using an editor to prepare the commit
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 904dafa..7546c7a 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -156,6 +156,11 @@ OPTIONS
 	Add Signed-off-by line by the committer at the end of the commit
 	log message.
 
+--no-signoff::
+	Countermand `commit.signoff` configuration, preventing a
+	Signed-off-by line to be added at the end of the commit log
+	message.
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin/commit.c b/builtin/commit.c
index 254477f..5cfbe57 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1505,6 +1505,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
 	}
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 
 	status = git_gpg_config(k, v, NULL);
 	if (status)
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 116885a..fcb39b4 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -179,6 +179,28 @@ test_expect_success '--signoff' '
 	test_cmp expect output
 '
 
+test_expect_success 'commit.signoff config option' '
+	git config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "zort" | git commit -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	git config --unset commit.signoff &&
+	test_cmp expect output
+'
+
+cat > expect <<EOF
+no signed off by here
+EOF
+
+test_expect_success '--no-signoff' '
+	git config commit.signoff true &&
+	echo "yet another content *narf*" >> foo &&
+	echo "no signed off by here" | git commit --no-signoff -F - foo &&
+	git cat-file commit HEAD | sed "1,/^\$/d" > output &&
+	git config --unset commit.signoff &&
+	test_cmp expect output
+'
+
 test_expect_success 'commit message from file (1)' '
 	mkdir subdir &&
 	echo "Log in top directory" >log &&
-- 
2.4.4.489.gc2a2b54.dirty

^ permalink raw reply related	[relevance 20%]

* Re: [PATCH v2 1/2] completion: Add sequencer function
  2015-05-30 16:01  5%     ` [PATCH v2 1/2] completion: Add sequencer function Thomas Braun
@ 2015-05-30 19:01  0%       ` SZEDER Gábor
  0 siblings, 0 replies; 171+ results
From: SZEDER Gábor @ 2015-05-30 19:01 UTC (permalink / raw)
  To: Thomas Braun; +Cc: git, Ramkumar Ramachandra, Junio C Hamano, John Keeping


Quoting Thomas Braun <thomas.braun@virtuell-zuhause.de>:

> Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
> ---
>  contrib/completion/git-completion.bash | 48  
> +++++++++++++++++++++++-----------
>  1 file changed, 33 insertions(+), 15 deletions(-)

I don't see the benefits of this change.  This patch adds more than  
twice as many lines as it removes, and patch 2/2 adds 8 new lines  
although it could get away with only 5 without this function.  To  
offer sequencer options we currently go through a single if statement,  
with this patch we'd go through a case statement, an if statement and  
finally an &&.

Gábor


> diff --git a/contrib/completion/git-completion.bash  
> b/contrib/completion/git-completion.bash
> index bfc74e9..f6e5bf6 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -851,15 +851,40 @@ __git_count_arguments ()
>  	printf "%d" $c
>  }
>
> +__git_complete_sequencer ()
> +{
> +	local dir="$(__gitdir)"
> +
> +	case "$1" in
> +	am)
> +		if [ -d "$dir"/rebase-apply ]; then
> +			__gitcomp "--skip --continue --resolved --abort"
> +			return 0
> +		fi
> +		;;
> +	cherry-pick)
> +		if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
> +			__gitcomp "--continue --quit --abort"
> +			return 0
> +		fi
> +		;;
> +	rebase)
> +		if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
> +			__gitcomp "--continue --skip --abort"
> +			return 0
> +		fi
> +		;;
> +	esac
> +
> +	return 1
> +}
> +
>  __git_whitespacelist="nowarn warn error error-all fix"
>
>  _git_am ()
>  {
> -	local dir="$(__gitdir)"
> -	if [ -d "$dir"/rebase-apply ]; then
> -		__gitcomp "--skip --continue --resolved --abort"
> -		return
> -	fi
> +	__git_complete_sequencer "am" && return
> +
>  	case "$cur" in
>  	--whitespace=*)
>  		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
> @@ -1044,11 +1069,8 @@ _git_cherry ()
>
>  _git_cherry_pick ()
>  {
> -	local dir="$(__gitdir)"
> -	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
> -		__gitcomp "--continue --quit --abort"
> -		return
> -	fi
> +	__git_complete_sequencer "cherry-pick" && return
> +
>  	case "$cur" in
>  	--*)
>  		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
> @@ -1666,11 +1688,7 @@ _git_push ()
>
>  _git_rebase ()
>  {
> -	local dir="$(__gitdir)"
> -	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
> -		__gitcomp "--continue --skip --abort"
> -		return
> -	fi
> +	__git_complete_sequencer "rebase" && return
>  	__git_complete_strategy && return
>  	case "$cur" in
>  	--whitespace=*)

^ permalink raw reply	[relevance 0%]

* [PATCH v2 1/2] completion: Add sequencer function
  2015-05-29 23:13  0%   ` Ramkumar Ramachandra
                       ` (2 preceding siblings ...)
  2015-05-30 16:01  5%     ` [PATCH v2 1/2] completion: Add sequencer function Thomas Braun
@ 2015-05-30 16:02  5%     ` Thomas Braun
  3 siblings, 0 replies; 171+ results
From: Thomas Braun @ 2015-05-30 16:02 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Junio C Hamano, John Keeping,
	SZEDER Gábor

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
---
 contrib/completion/git-completion.bash | 48 +++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index bfc74e9..f6e5bf6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -851,15 +851,40 @@ __git_count_arguments ()
 	printf "%d" $c
 }
 
+__git_complete_sequencer ()
+{
+	local dir="$(__gitdir)"
+
+	case "$1" in
+	am)
+		if [ -d "$dir"/rebase-apply ]; then
+			__gitcomp "--skip --continue --resolved --abort"
+			return 0
+		fi
+		;;
+	cherry-pick)
+		if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
+			__gitcomp "--continue --quit --abort"
+			return 0
+		fi
+		;;
+	rebase)
+		if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
+			__gitcomp "--continue --skip --abort"
+			return 0
+		fi
+		;;
+	esac
+
+	return 1
+}
+
 __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local dir="$(__gitdir)"
-	if [ -d "$dir"/rebase-apply ]; then
-		__gitcomp "--skip --continue --resolved --abort"
-		return
-	fi
+	__git_complete_sequencer "am" && return
+
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1044,11 +1069,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local dir="$(__gitdir)"
-	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
-		__gitcomp "--continue --quit --abort"
-		return
-	fi
+	__git_complete_sequencer "cherry-pick" && return
+
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
@@ -1666,11 +1688,7 @@ _git_push ()
 
 _git_rebase ()
 {
-	local dir="$(__gitdir)"
-	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
-		__gitcomp "--continue --skip --abort"
-		return
-	fi
+	__git_complete_sequencer "rebase" && return
 	__git_complete_strategy && return
 	case "$cur" in
 	--whitespace=*)

^ permalink raw reply related	[relevance 5%]

* [PATCH v2 1/2] completion: Add sequencer function
  2015-05-29 23:13  0%   ` Ramkumar Ramachandra
  2015-05-30 15:57  0%     ` [PATCH v2 0/2] completion: sequencer commands Thomas Braun
  2015-05-30 16:01  5%     ` [PATCH v2 2/2] completion: suggest sequencer commands for revert Thomas Braun
@ 2015-05-30 16:01  5%     ` Thomas Braun
  2015-05-30 19:01  0%       ` SZEDER Gábor
  2015-05-30 16:02  5%     ` Thomas Braun
  3 siblings, 1 reply; 171+ results
From: Thomas Braun @ 2015-05-30 16:01 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Junio C Hamano, John Keeping,
	SZEDER Gábor

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
---
 contrib/completion/git-completion.bash | 48 +++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index bfc74e9..f6e5bf6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -851,15 +851,40 @@ __git_count_arguments ()
 	printf "%d" $c
 }
 
+__git_complete_sequencer ()
+{
+	local dir="$(__gitdir)"
+
+	case "$1" in
+	am)
+		if [ -d "$dir"/rebase-apply ]; then
+			__gitcomp "--skip --continue --resolved --abort"
+			return 0
+		fi
+		;;
+	cherry-pick)
+		if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
+			__gitcomp "--continue --quit --abort"
+			return 0
+		fi
+		;;
+	rebase)
+		if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
+			__gitcomp "--continue --skip --abort"
+			return 0
+		fi
+		;;
+	esac
+
+	return 1
+}
+
 __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local dir="$(__gitdir)"
-	if [ -d "$dir"/rebase-apply ]; then
-		__gitcomp "--skip --continue --resolved --abort"
-		return
-	fi
+	__git_complete_sequencer "am" && return
+
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1044,11 +1069,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local dir="$(__gitdir)"
-	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
-		__gitcomp "--continue --quit --abort"
-		return
-	fi
+	__git_complete_sequencer "cherry-pick" && return
+
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
@@ -1666,11 +1688,7 @@ _git_push ()
 
 _git_rebase ()
 {
-	local dir="$(__gitdir)"
-	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
-		__gitcomp "--continue --skip --abort"
-		return
-	fi
+	__git_complete_sequencer "rebase" && return
 	__git_complete_strategy && return
 	case "$cur" in
 	--whitespace=*)

^ permalink raw reply related	[relevance 5%]

* [PATCH v2 2/2] completion: suggest sequencer commands for revert
  2015-05-29 23:13  0%   ` Ramkumar Ramachandra
  2015-05-30 15:57  0%     ` [PATCH v2 0/2] completion: sequencer commands Thomas Braun
@ 2015-05-30 16:01  5%     ` Thomas Braun
  2015-05-30 16:01  5%     ` [PATCH v2 1/2] completion: Add sequencer function Thomas Braun
  2015-05-30 16:02  5%     ` Thomas Braun
  3 siblings, 0 replies; 171+ results
From: Thomas Braun @ 2015-05-30 16:01 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Junio C Hamano, John Keeping,
	SZEDER Gábor

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
---
 contrib/completion/git-completion.bash | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index f6e5bf6..486c61b 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -868,6 +868,12 @@ __git_complete_sequencer ()
 			return 0
 		fi
 		;;
+	revert)
+		if [ -f "$dir"/REVERT_HEAD ]; then
+			__gitcomp "--continue --quit --abort"
+			return 0
+		fi
+		;;
 	rebase)
 		if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 			__gitcomp "--continue --skip --abort"
@@ -2300,6 +2306,8 @@ _git_reset ()
 
 _git_revert ()
 {
+	__git_complete_sequencer "revert" && return
+
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"

^ permalink raw reply related	[relevance 5%]

* [PATCH v2 0/2] completion: sequencer commands
  2015-05-29 23:13  0%   ` Ramkumar Ramachandra
@ 2015-05-30 15:57  0%     ` Thomas Braun
  2015-05-30 16:01  5%     ` [PATCH v2 2/2] completion: suggest sequencer commands for revert Thomas Braun
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 171+ results
From: Thomas Braun @ 2015-05-30 15:57 UTC (permalink / raw)
  To: git; +Cc: Ramkumar Ramachandra, Junio C Hamano, John Keeping,
	SZEDER Gábor

Ramkumar Ramachandra wrote:
> Junio C Hamano wrote:
> >
> > >  contrib/completion/git-completion.bash | 5 +++++
> > >  1 file changed, 5 insertions(+)
> > >
> > > diff --git a/contrib/completion/git-completion.bash
> b/contrib/completion/git-completion.bash
> > > index bfc74e9..3c00acd 100644
> > > --- a/contrib/completion/git-completion.bash
> > > +++ b/contrib/completion/git-completion.bash
> > > @@ -2282,6 +2282,11 @@ _git_reset ()
> > >
> > >  _git_revert ()
> > >  {
> > > +     local dir="$(__gitdir)"
> > > +     if [ -f "$dir"/REVERT_HEAD ]; then
> > > +             __gitcomp "--continue --quit --abort"
> > > +             return
> > > +     fi
> > >       case "$cur" in
> > >       --*)
> > >               __gitcomp "--edit --mainline --no-edit --no-commit
> --signoff"
>
> This corresponds exactly to what we do for git-cherry-pick:
>
> local dir="$(__gitdir)"
> if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
> __gitcomp "--continue --quit --abort"
> return
> fi
>
> Perhaps _git_revert() and _git_cherry_pick() should call into the same
> function with different arguments.

Good idea.
I created a new function __git_complete_sequencer which is now used to complete
all commands with active sequencer.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] completion: suggest sequencer commands for revert
  2015-05-29 19:50  0% ` Junio C Hamano
@ 2015-05-29 23:13  0%   ` Ramkumar Ramachandra
  2015-05-30 15:57  0%     ` [PATCH v2 0/2] completion: sequencer commands Thomas Braun
                       ` (3 more replies)
  0 siblings, 4 replies; 171+ results
From: Ramkumar Ramachandra @ 2015-05-29 23:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: John Keeping, SZEDER Gábor, Git List, Thomas Braun

Junio C Hamano wrote:
>
> >  contrib/completion/git-completion.bash | 5 +++++
> >  1 file changed, 5 insertions(+)
> >
> > diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> > index bfc74e9..3c00acd 100644
> > --- a/contrib/completion/git-completion.bash
> > +++ b/contrib/completion/git-completion.bash
> > @@ -2282,6 +2282,11 @@ _git_reset ()
> >
> >  _git_revert ()
> >  {
> > +     local dir="$(__gitdir)"
> > +     if [ -f "$dir"/REVERT_HEAD ]; then
> > +             __gitcomp "--continue --quit --abort"
> > +             return
> > +     fi
> >       case "$cur" in
> >       --*)
> >               __gitcomp "--edit --mainline --no-edit --no-commit --signoff"

This corresponds exactly to what we do for git-cherry-pick:

local dir="$(__gitdir)"
if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
__gitcomp "--continue --quit --abort"
return
fi

Perhaps _git_revert() and _git_cherry_pick() should call into the same
function with different arguments.

This looks fine though.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH] completion: suggest sequencer commands for revert
  2015-05-25  9:59  5% [PATCH] completion: suggest sequencer commands for revert Thomas Braun
@ 2015-05-29 19:50  0% ` Junio C Hamano
  2015-05-29 23:13  0%   ` Ramkumar Ramachandra
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2015-05-29 19:50 UTC (permalink / raw)
  To: John Keeping, SZEDER Gábor, Ramkumar Ramachandra; +Cc: git, Thomas Braun

Thomas Braun <thomas.braun@virtuell-zuhause.de> writes:

> Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
> ---
>
> Hi,
>
> I added the sequencer commands for git revert. These are handy in case a git
> revert needs manual intervention.

This looks OK from a cursory read to me; asking opinions from those
who have touched the file in the recent past (Ram also happens to be
one of the people who were heavily involved in sequencer work).

Thanks.

>
> Thanks,
> Thomas
>
>  contrib/completion/git-completion.bash | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index bfc74e9..3c00acd 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -2282,6 +2282,11 @@ _git_reset ()
>  
>  _git_revert ()
>  {
> +	local dir="$(__gitdir)"
> +	if [ -f "$dir"/REVERT_HEAD ]; then
> +		__gitcomp "--continue --quit --abort"
> +		return
> +	fi
>  	case "$cur" in
>  	--*)
>  		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"

^ permalink raw reply	[relevance 0%]

* [PATCH] completion: suggest sequencer commands for revert
@ 2015-05-25  9:59  5% Thomas Braun
  2015-05-29 19:50  0% ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Thomas Braun @ 2015-05-25  9:59 UTC (permalink / raw)
  To: git

Signed-off-by: Thomas Braun <thomas.braun@virtuell-zuhause.de>
---

Hi,

I added the sequencer commands for git revert. These are handy in case a git
revert needs manual intervention.

Thanks,
Thomas

 contrib/completion/git-completion.bash | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index bfc74e9..3c00acd 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2282,6 +2282,11 @@ _git_reset ()
 
 _git_revert ()
 {
+	local dir="$(__gitdir)"
+	if [ -f "$dir"/REVERT_HEAD ]; then
+		__gitcomp "--continue --quit --abort"
+		return
+	fi
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"

^ permalink raw reply related	[relevance 5%]

* [PATCH v3 07/27] commit: allow disabling pre-commit and commit-msg separately
  @ 2014-08-18 21:22  7%   ` Fabian Ruch
  0 siblings, 0 replies; 171+ results
From: Fabian Ruch @ 2014-08-18 21:22 UTC (permalink / raw)
  To: git; +Cc: Michael Haggerty, Thomas Rast, Jeff King

Introduce the git-commit command line options `--no-pre-commit` and
`--no-commit-msg` to disable the pre-commit and commit-msg hooks,
respectively. Make `--no-verify` a synonym for specifying both at the
same time.

This change is motivated by an internal usage of git-commit in
git-rebase--interactive to disable pre-commit while keeping
commit-msg enabled when rewording a commit.

Make `test_commit` forward unknown options to git-commit instead of
teaching it all possible options. In order to support leading double
dashes in `<message>`, stop interpreting `test_commit` arguments
following a `--` argument as options. This wasn't a problem before
because the first unknown option would be used as `<message>`.

Allow disabling tag creation to avoid name clashes when using
`test_commit` with the same arguments several times from the same
test suite. By default, `test_commit` tags successful commits using
git-tag for easy reference. The `--notag` option skips this step.

Add tests.

Signed-off-by: Fabian Ruch <bafain@gmail.com>
---
 Documentation/git-commit.txt |  8 ++++-
 builtin/commit.c             | 32 ++++++++++++++---
 t/t7503-pre-commit-hook.sh   | 65 ++++++++++++++++++++++++++++-----
 t/t7504-commit-msg-hook.sh   | 85 ++++++++++++++++++++++++++++++++++----------
 t/test-lib-functions.sh      | 23 ++++++++----
 5 files changed, 176 insertions(+), 37 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 0bbc8f5..28a2c5c 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -158,7 +158,7 @@ OPTIONS
 
 -n::
 --no-verify::
-	This option bypasses the pre-commit and commit-msg hooks.
+	A synonym for `--no-pre-commit --no-commit-msg`.
 	See also linkgit:githooks[5].
 
 --allow-empty::
@@ -238,6 +238,12 @@ You should understand the implications of rewriting history if you
 amend a commit that has already been published.  (See the "RECOVERING
 FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
 
+--no-pre-commit::
+	This option bypasses the pre-commit hook.
+
+--no-commit-msg::
+	This option bypasses the commit-msg hook.
+
 --no-post-rewrite::
 	Bypass the post-rewrite hook.
 
diff --git a/builtin/commit.c b/builtin/commit.c
index 5ed6036..dfd354e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -98,12 +98,27 @@ static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
 static int all, also, interactive, patch_interactive, only, amend, signoff;
 static int edit_flag = -1; /* unspecified */
-static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
+static int quiet, verbose, allow_empty, dry_run, renew_authorship;
 static int no_post_rewrite, allow_empty_message;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
 static char *sign_commit;
 
 /*
+ * The verify variable is interpreted as a bitmap of enabled commit
+ * verification hooks according to the legend below.
+ *
+ * By default, the pre-commit and commit-msg hooks are enabled. This
+ * is represented by both the PRE_COMMIT and COMMIT_MSG bits being
+ * set.
+ *
+ * The bitmap is changed through the command line options
+ * --no-verify, --no-pre-commit and --no-commit-msg.
+ */
+#define PRE_COMMIT (1<<0)
+#define COMMIT_MSG (1<<1)
+static int verify = PRE_COMMIT | COMMIT_MSG;
+
+/*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
  * whitespaces (empty lines or containing only whitespaces)
@@ -661,7 +676,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	/* This checks and barfs if author is badly specified */
 	determine_author_info(author_ident);
 
-	if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
+	if (verify & PRE_COMMIT &&
+	    run_commit_hook(use_editor, index_file, "pre-commit", NULL))
 		return 0;
 
 	if (squash_message) {
@@ -962,7 +978,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		}
 	}
 
-	if (!no_verify &&
+	if (verify & COMMIT_MSG &&
 	    run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
 		return 0;
 	}
@@ -1590,7 +1606,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
 		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
 		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
-		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+		OPT_NEGBIT('n', "no-verify", &verify,
+			   N_("synonym for --no-pre-commit --no-commit-msg"),
+			   PRE_COMMIT | COMMIT_MSG),
 		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
 		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
 			    STATUS_FORMAT_SHORT),
@@ -1603,6 +1621,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_BOOL('z', "null", &s.null_termination,
 			 N_("terminate entries with NUL")),
 		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+		OPT_NEGBIT(0, "no-pre-commit", &verify,
+			   N_("bypass pre-commit hook"),
+			   PRE_COMMIT),
+		OPT_NEGBIT(0, "no-commit-msg", &verify,
+			   N_("bypass commit-msg hook"),
+			   COMMIT_MSG),
 		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 		/* end commit contents options */
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index 984889b..db5de1c 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -12,11 +12,11 @@ test_expect_success 'with no hook' '
 
 '
 
-test_expect_success '--no-verify with no hook' '
+test_expect_success '--no-pre-commit with no hook' '
 
 	echo "bar" > file &&
 	git add file &&
-	git commit --no-verify -m "bar"
+	git commit --no-pre-commit -m "bar"
 
 '
 
@@ -38,11 +38,11 @@ test_expect_success 'with succeeding hook' '
 
 '
 
-test_expect_success '--no-verify with succeeding hook' '
+test_expect_success '--no-pre-commit with succeeding hook' '
 
 	echo "even more" >> file &&
 	git add file &&
-	git commit --no-verify -m "even more"
+	git commit --no-pre-commit -m "even more"
 
 '
 
@@ -60,11 +60,11 @@ test_expect_success 'with failing hook' '
 
 '
 
-test_expect_success '--no-verify with failing hook' '
+test_expect_success '--no-pre-commit with failing hook' '
 
 	echo "stuff" >> file &&
 	git add file &&
-	git commit --no-verify -m "stuff"
+	git commit --no-pre-commit -m "stuff"
 
 '
 
@@ -77,15 +77,64 @@ test_expect_success POSIXPERM 'with non-executable hook' '
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-pre-commit with non-executable hook' '
 
 	echo "more content" >> file &&
 	git add file &&
-	git commit --no-verify -m "more content"
+	git commit --no-pre-commit -m "more content"
 
 '
 chmod +x "$HOOK"
 
+test_hook_enabled () {
+	git checkout --detach master &&
+	output="running failing pre-commit hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	echo "$output" >expected.output &&
+	test_must_fail test_commit $* file &&
+	test_cmp expected.output actual.output
+}
+
+test_hook_disabled () {
+	git checkout --detach master &&
+	output="running failing pre-commit hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	test_commit --notag $* file &&
+	test_must_be_empty actual.output
+}
+
+test_expect_success 'command line options combinations' '
+	test_hook_enabled &&
+	test_hook_enabled --pre-commit &&
+	test_hook_enabled --no-pre-commit --pre-commit &&
+	test_hook_enabled --no-verify --pre-commit &&
+	test_hook_enabled --verify &&
+	test_hook_enabled --no-pre-commit --verify &&
+	test_hook_enabled --no-verify --verify &&
+	test_hook_enabled --verify --no-commit-msg &&
+	test_hook_enabled --verify --commit-msg &&
+	test_hook_disabled --no-pre-commit &&
+	test_hook_disabled --pre-commit --no-pre-commit &&
+	test_hook_disabled --pre-commit --no-verify &&
+	test_hook_disabled --no-verify &&
+	test_hook_disabled --verify --no-pre-commit &&
+	test_hook_disabled --verify --no-verify &&
+	test_hook_disabled --no-verify --no-commit-msg &&
+	test_hook_disabled --no-verify --commit-msg
+'
+
 # a hook that checks $GIT_PREFIX and succeeds inside the
 # success/ subdirectory only
 cat > "$HOOK" <<EOF
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 1f53ea8..59642a3 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -34,20 +34,20 @@ test_expect_success 'with no hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with no hook' '
+test_expect_success '--no-commit-msg with no hook' '
 
 	echo "bar" > file &&
 	git add file &&
-	git commit --no-verify -m "bar"
+	git commit --no-commit-msg -m "bar"
 
 '
 
-test_expect_success '--no-verify with no hook (editor)' '
+test_expect_success '--no-commit-msg with no hook (editor)' '
 
 	echo "more bar" > file &&
 	git add file &&
 	echo "more bar" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -78,20 +78,20 @@ test_expect_success 'with succeeding hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with succeeding hook' '
+test_expect_success '--no-commit-msg with succeeding hook' '
 
 	echo "even more" >> file &&
 	git add file &&
-	git commit --no-verify -m "even more"
+	git commit --no-commit-msg -m "even more"
 
 '
 
-test_expect_success '--no-verify with succeeding hook (editor)' '
+test_expect_success '--no-commit-msg with succeeding hook (editor)' '
 
 	echo "even more more" >> file &&
 	git add file &&
 	echo "even more more" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -118,20 +118,20 @@ test_expect_success 'with failing hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with failing hook' '
+test_expect_success '--no-commit-msg with failing hook' '
 
 	echo "stuff" >> file &&
 	git add file &&
-	git commit --no-verify -m "stuff"
+	git commit --no-commit-msg -m "stuff"
 
 '
 
-test_expect_success '--no-verify with failing hook (editor)' '
+test_expect_success '--no-commit-msg with failing hook (editor)' '
 
 	echo "more stuff" >> file &&
 	git add file &&
 	echo "more stuff" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -153,23 +153,72 @@ test_expect_success POSIXPERM 'with non-executable hook (editor)' '
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-commit-msg with non-executable hook' '
 
 	echo "more content" >> file &&
 	git add file &&
-	git commit --no-verify -m "more content"
+	git commit --no-commit-msg -m "more content"
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' '
+test_expect_success POSIXPERM '--no-commit-msg with non-executable hook (editor)' '
 
 	echo "even more content" >> file &&
 	git add file &&
 	echo "even more content" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
+test_hook_enabled () {
+	git checkout --detach master &&
+	output="running failing commit-msg hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	echo "$output" >expected.output &&
+	test_must_fail test_commit $* file &&
+	test_cmp expected.output actual.output
+}
+
+test_hook_disabled () {
+	git checkout --detach master &&
+	output="running failing commit-msg hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	test_commit --notag $* file &&
+	test_must_be_empty actual.output
+}
+
+test_expect_success 'command line options combinations' '
+	test_hook_enabled &&
+	test_hook_enabled --commit-msg &&
+	test_hook_enabled --no-commit-msg --commit-msg &&
+	test_hook_enabled --no-verify --commit-msg &&
+	test_hook_enabled --verify &&
+	test_hook_enabled --no-commit-msg --verify &&
+	test_hook_enabled --no-verify --verify &&
+	test_hook_enabled --verify --no-pre-commit &&
+	test_hook_enabled --verify --pre-commit &&
+	test_hook_disabled --no-commit-msg &&
+	test_hook_disabled --commit-msg --no-commit-msg &&
+	test_hook_disabled --commit-msg --no-verify &&
+	test_hook_disabled --no-verify &&
+	test_hook_disabled --verify --no-commit-msg &&
+	test_hook_disabled --verify --no-verify &&
+	test_hook_disabled --no-verify --no-pre-commit &&
+	test_hook_disabled --no-verify --pre-commit
+'
+
 # now a hook that edits the commit message
 cat > "$HOOK" <<'EOF'
 #!/bin/sh
@@ -205,7 +254,7 @@ test_expect_success "hook doesn't edit commit message" '
 
 	echo "plus" >> file &&
 	git add file &&
-	git commit --no-verify -m "plus" &&
+	git commit --no-commit-msg -m "plus" &&
 	commit_msg_is "plus"
 
 '
@@ -215,7 +264,7 @@ test_expect_success "hook doesn't edit commit message (editor)" '
 	echo "more plus" >> file &&
 	git add file &&
 	echo "more plus" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify &&
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg &&
 	commit_msg_is "more plus"
 
 '
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index dafd6ad..a107073 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -154,20 +154,28 @@ test_pause () {
 
 test_commit () {
 	notick= &&
-	signoff= &&
+	notag= &&
+	commit_opts= &&
 	while test $# != 0
 	do
 		case "$1" in
 		--notick)
 			notick=yes
 			;;
-		--signoff)
-			signoff="$1"
+		--notag)
+			notag=yes
+			;;
+		--)
+			shift &&
+			break
+			;;
+		-*)
+			commit_opts="$commit_opts $1"
 			;;
 		*)
 			break
 			;;
-		esac
+		esac &&
 		shift
 	done &&
 	file=${2:-"$1.t"} &&
@@ -177,8 +185,11 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git commit $commit_opts -m "$1" &&
+	if test -z "$notag"
+	then
+		git tag "${4:-$1}"
+	fi
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.0.1

^ permalink raw reply related	[relevance 7%]

* [PATCH v2 06/23] commit: allow disabling pre-commit and commit-msg separately
  @ 2014-08-06 23:59  7%   ` Fabian Ruch
  0 siblings, 0 replies; 171+ results
From: Fabian Ruch @ 2014-08-06 23:59 UTC (permalink / raw)
  To: git; +Cc: Michael Haggerty, Thomas Rast, Jeff King

Introduce the git-commit command line options `--no-pre-commit` and
`--no-commit-msg` to disable the pre-commit and commit-msg hooks,
respectively. Make `--no-verify` a synonym for specifying both at the
same time.

This change is motivated by an internal usage of git-commit in
git-rebase--interactive to disable pre-commit while keeping
commit-msg enabled when rewording a commit.

Make `test_commit` forward unknown options to git-commit instead of
teaching it all possible options. In order to support leading double
dashes in `<message>`, stop interpreting `test_commit` arguments
following a `--` argument as options. This wasn't a problem before
because the first unknown option would be used as `<message>`.

Allow disabling tag creation to avoid name clashes when using
`test_commit` with the same arguments several times from the same
test suite. By default, `test_commit` tags successful commits using
git-tag for easy reference. The `--notag` option skips this step.

Add tests.

Signed-off-by: Fabian Ruch <bafain@gmail.com>
---
 Documentation/git-commit.txt |  8 ++++-
 builtin/commit.c             | 32 ++++++++++++++---
 t/t7503-pre-commit-hook.sh   | 65 ++++++++++++++++++++++++++++-----
 t/t7504-commit-msg-hook.sh   | 85 ++++++++++++++++++++++++++++++++++----------
 t/test-lib-functions.sh      | 23 ++++++++----
 5 files changed, 176 insertions(+), 37 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 0bbc8f5..28a2c5c 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -158,7 +158,7 @@ OPTIONS
 
 -n::
 --no-verify::
-	This option bypasses the pre-commit and commit-msg hooks.
+	A synonym for `--no-pre-commit --no-commit-msg`.
 	See also linkgit:githooks[5].
 
 --allow-empty::
@@ -238,6 +238,12 @@ You should understand the implications of rewriting history if you
 amend a commit that has already been published.  (See the "RECOVERING
 FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
 
+--no-pre-commit::
+	This option bypasses the pre-commit hook.
+
+--no-commit-msg::
+	This option bypasses the commit-msg hook.
+
 --no-post-rewrite::
 	Bypass the post-rewrite hook.
 
diff --git a/builtin/commit.c b/builtin/commit.c
index 5ed6036..dfd354e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -98,12 +98,27 @@ static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
 static int all, also, interactive, patch_interactive, only, amend, signoff;
 static int edit_flag = -1; /* unspecified */
-static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
+static int quiet, verbose, allow_empty, dry_run, renew_authorship;
 static int no_post_rewrite, allow_empty_message;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
 static char *sign_commit;
 
 /*
+ * The verify variable is interpreted as a bitmap of enabled commit
+ * verification hooks according to the legend below.
+ *
+ * By default, the pre-commit and commit-msg hooks are enabled. This
+ * is represented by both the PRE_COMMIT and COMMIT_MSG bits being
+ * set.
+ *
+ * The bitmap is changed through the command line options
+ * --no-verify, --no-pre-commit and --no-commit-msg.
+ */
+#define PRE_COMMIT (1<<0)
+#define COMMIT_MSG (1<<1)
+static int verify = PRE_COMMIT | COMMIT_MSG;
+
+/*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
  * whitespaces (empty lines or containing only whitespaces)
@@ -661,7 +676,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	/* This checks and barfs if author is badly specified */
 	determine_author_info(author_ident);
 
-	if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
+	if (verify & PRE_COMMIT &&
+	    run_commit_hook(use_editor, index_file, "pre-commit", NULL))
 		return 0;
 
 	if (squash_message) {
@@ -962,7 +978,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		}
 	}
 
-	if (!no_verify &&
+	if (verify & COMMIT_MSG &&
 	    run_commit_hook(use_editor, index_file, "commit-msg", git_path(commit_editmsg), NULL)) {
 		return 0;
 	}
@@ -1590,7 +1606,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
 		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
 		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
-		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+		OPT_NEGBIT('n', "no-verify", &verify,
+			   N_("synonym for --no-pre-commit --no-commit-msg"),
+			   PRE_COMMIT | COMMIT_MSG),
 		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
 		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
 			    STATUS_FORMAT_SHORT),
@@ -1603,6 +1621,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_BOOL('z', "null", &s.null_termination,
 			 N_("terminate entries with NUL")),
 		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+		OPT_NEGBIT(0, "no-pre-commit", &verify,
+			   N_("bypass pre-commit hook"),
+			   PRE_COMMIT),
+		OPT_NEGBIT(0, "no-commit-msg", &verify,
+			   N_("bypass commit-msg hook"),
+			   COMMIT_MSG),
 		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 		/* end commit contents options */
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index 984889b..db5de1c 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -12,11 +12,11 @@ test_expect_success 'with no hook' '
 
 '
 
-test_expect_success '--no-verify with no hook' '
+test_expect_success '--no-pre-commit with no hook' '
 
 	echo "bar" > file &&
 	git add file &&
-	git commit --no-verify -m "bar"
+	git commit --no-pre-commit -m "bar"
 
 '
 
@@ -38,11 +38,11 @@ test_expect_success 'with succeeding hook' '
 
 '
 
-test_expect_success '--no-verify with succeeding hook' '
+test_expect_success '--no-pre-commit with succeeding hook' '
 
 	echo "even more" >> file &&
 	git add file &&
-	git commit --no-verify -m "even more"
+	git commit --no-pre-commit -m "even more"
 
 '
 
@@ -60,11 +60,11 @@ test_expect_success 'with failing hook' '
 
 '
 
-test_expect_success '--no-verify with failing hook' '
+test_expect_success '--no-pre-commit with failing hook' '
 
 	echo "stuff" >> file &&
 	git add file &&
-	git commit --no-verify -m "stuff"
+	git commit --no-pre-commit -m "stuff"
 
 '
 
@@ -77,15 +77,64 @@ test_expect_success POSIXPERM 'with non-executable hook' '
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-pre-commit with non-executable hook' '
 
 	echo "more content" >> file &&
 	git add file &&
-	git commit --no-verify -m "more content"
+	git commit --no-pre-commit -m "more content"
 
 '
 chmod +x "$HOOK"
 
+test_hook_enabled () {
+	git checkout --detach master &&
+	output="running failing pre-commit hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	echo "$output" >expected.output &&
+	test_must_fail test_commit $* file &&
+	test_cmp expected.output actual.output
+}
+
+test_hook_disabled () {
+	git checkout --detach master &&
+	output="running failing pre-commit hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	test_commit --notag $* file &&
+	test_must_be_empty actual.output
+}
+
+test_expect_success 'command line options combinations' '
+	test_hook_enabled &&
+	test_hook_enabled --pre-commit &&
+	test_hook_enabled --no-pre-commit --pre-commit &&
+	test_hook_enabled --no-verify --pre-commit &&
+	test_hook_enabled --verify &&
+	test_hook_enabled --no-pre-commit --verify &&
+	test_hook_enabled --no-verify --verify &&
+	test_hook_enabled --verify --no-commit-msg &&
+	test_hook_enabled --verify --commit-msg &&
+	test_hook_disabled --no-pre-commit &&
+	test_hook_disabled --pre-commit --no-pre-commit &&
+	test_hook_disabled --pre-commit --no-verify &&
+	test_hook_disabled --no-verify &&
+	test_hook_disabled --verify --no-pre-commit &&
+	test_hook_disabled --verify --no-verify &&
+	test_hook_disabled --no-verify --no-commit-msg &&
+	test_hook_disabled --no-verify --commit-msg
+'
+
 # a hook that checks $GIT_PREFIX and succeeds inside the
 # success/ subdirectory only
 cat > "$HOOK" <<EOF
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 1f53ea8..59642a3 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -34,20 +34,20 @@ test_expect_success 'with no hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with no hook' '
+test_expect_success '--no-commit-msg with no hook' '
 
 	echo "bar" > file &&
 	git add file &&
-	git commit --no-verify -m "bar"
+	git commit --no-commit-msg -m "bar"
 
 '
 
-test_expect_success '--no-verify with no hook (editor)' '
+test_expect_success '--no-commit-msg with no hook (editor)' '
 
 	echo "more bar" > file &&
 	git add file &&
 	echo "more bar" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -78,20 +78,20 @@ test_expect_success 'with succeeding hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with succeeding hook' '
+test_expect_success '--no-commit-msg with succeeding hook' '
 
 	echo "even more" >> file &&
 	git add file &&
-	git commit --no-verify -m "even more"
+	git commit --no-commit-msg -m "even more"
 
 '
 
-test_expect_success '--no-verify with succeeding hook (editor)' '
+test_expect_success '--no-commit-msg with succeeding hook (editor)' '
 
 	echo "even more more" >> file &&
 	git add file &&
 	echo "even more more" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -118,20 +118,20 @@ test_expect_success 'with failing hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with failing hook' '
+test_expect_success '--no-commit-msg with failing hook' '
 
 	echo "stuff" >> file &&
 	git add file &&
-	git commit --no-verify -m "stuff"
+	git commit --no-commit-msg -m "stuff"
 
 '
 
-test_expect_success '--no-verify with failing hook (editor)' '
+test_expect_success '--no-commit-msg with failing hook (editor)' '
 
 	echo "more stuff" >> file &&
 	git add file &&
 	echo "more stuff" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
@@ -153,23 +153,72 @@ test_expect_success POSIXPERM 'with non-executable hook (editor)' '
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-commit-msg with non-executable hook' '
 
 	echo "more content" >> file &&
 	git add file &&
-	git commit --no-verify -m "more content"
+	git commit --no-commit-msg -m "more content"
 
 '
 
-test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' '
+test_expect_success POSIXPERM '--no-commit-msg with non-executable hook (editor)' '
 
 	echo "even more content" >> file &&
 	git add file &&
 	echo "even more content" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg
 
 '
 
+test_hook_enabled () {
+	git checkout --detach master &&
+	output="running failing commit-msg hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	echo "$output" >expected.output &&
+	test_must_fail test_commit $* file &&
+	test_cmp expected.output actual.output
+}
+
+test_hook_disabled () {
+	git checkout --detach master &&
+	output="running failing commit-msg hook with ${*:-(none)}..." &&
+	>actual.output &&
+	cat >"$HOOK" <<-EOF &&
+	#!/bin/sh
+	echo "$output" >>actual.output
+	exit 1
+	EOF
+	chmod +x "$HOOK" &&
+	test_commit --notag $* file &&
+	test_must_be_empty actual.output
+}
+
+test_expect_success 'command line options combinations' '
+	test_hook_enabled &&
+	test_hook_enabled --commit-msg &&
+	test_hook_enabled --no-commit-msg --commit-msg &&
+	test_hook_enabled --no-verify --commit-msg &&
+	test_hook_enabled --verify &&
+	test_hook_enabled --no-commit-msg --verify &&
+	test_hook_enabled --no-verify --verify &&
+	test_hook_enabled --verify --no-pre-commit &&
+	test_hook_enabled --verify --pre-commit &&
+	test_hook_disabled --no-commit-msg &&
+	test_hook_disabled --commit-msg --no-commit-msg &&
+	test_hook_disabled --commit-msg --no-verify &&
+	test_hook_disabled --no-verify &&
+	test_hook_disabled --verify --no-commit-msg &&
+	test_hook_disabled --verify --no-verify &&
+	test_hook_disabled --no-verify --no-pre-commit &&
+	test_hook_disabled --no-verify --pre-commit
+'
+
 # now a hook that edits the commit message
 cat > "$HOOK" <<'EOF'
 #!/bin/sh
@@ -205,7 +254,7 @@ test_expect_success "hook doesn't edit commit message" '
 
 	echo "plus" >> file &&
 	git add file &&
-	git commit --no-verify -m "plus" &&
+	git commit --no-commit-msg -m "plus" &&
 	commit_msg_is "plus"
 
 '
@@ -215,7 +264,7 @@ test_expect_success "hook doesn't edit commit message (editor)" '
 	echo "more plus" >> file &&
 	git add file &&
 	echo "more plus" > FAKE_MSG &&
-	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify &&
+	GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-commit-msg &&
 	commit_msg_is "more plus"
 
 '
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index dafd6ad..a107073 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -154,20 +154,28 @@ test_pause () {
 
 test_commit () {
 	notick= &&
-	signoff= &&
+	notag= &&
+	commit_opts= &&
 	while test $# != 0
 	do
 		case "$1" in
 		--notick)
 			notick=yes
 			;;
-		--signoff)
-			signoff="$1"
+		--notag)
+			notag=yes
+			;;
+		--)
+			shift &&
+			break
+			;;
+		-*)
+			commit_opts="$commit_opts $1"
 			;;
 		*)
 			break
 			;;
-		esac
+		esac &&
 		shift
 	done &&
 	file=${2:-"$1.t"} &&
@@ -177,8 +185,11 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
-	git tag "${4:-$1}"
+	git commit $commit_opts -m "$1" &&
+	if test -z "$notag"
+	then
+		git tag "${4:-$1}"
+	fi
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
2.0.1

^ permalink raw reply related	[relevance 7%]

* [PATCH v1 03/19] rebase -i: reword executes pre-commit hook on interim commit
  @ 2014-07-28 23:18 11%   ` Fabian Ruch
  0 siblings, 0 replies; 171+ results
From: Fabian Ruch @ 2014-07-28 23:18 UTC (permalink / raw)
  To: git; +Cc: Michael Haggerty, Thomas Rast, Jeff King

The to-do list command `reword` replays a commit like `pick` but lets
the user also edit the commit's log message. This happens in two
steps. Firstly, the named commit is cherry-picked. Secondly, the
commit created in the first step is amended using an unchanged index
to edit the log message. The pre-commit hook is meant to verify the
changes introduced by a commit (for instance, catching inserted
trailing white space). Since the committed tree is not changed
between the two steps and we do not verify rebased patches, do not
execute the pre-commit hook in the second step.

Specify the git-commit option `--no-verify` to disable the pre-commit
hook when editing the log message. Because `--no-verify` also skips
the commit-msg hook, execute the hook from within
git-rebase--interactive after the commit is created. Fortunately, the
commit message is still available in `$GIT_DIR/COMMIT_EDITMSG` after
git-commit terminates. Caveat: In case the commit-msg hook finds the
new log message ill-formatted, the user is only notified of the
failed commit-msg hook but the log message is used for the commit
anyway. git-commit ought to offer more fine-grained control over
which hooks are executed.

Teach `test_commit` the `--no-verify` option and add test.

Signed-off-by: Fabian Ruch <bafain@gmail.com>
---
 git-rebase--interactive.sh    | 17 +++++++++++++----
 t/t3404-rebase-interactive.sh | 38 ++++++++++++++++++++++++++++++++++++++
 t/test-lib-functions.sh       |  6 +++++-
 3 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 689400e..b50770d 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -504,10 +504,19 @@ do_next () {
 
 		mark_action_done
 		do_pick $sha1 "$rest"
-		git commit --allow-empty --amend --no-post-rewrite ${gpg_sign_opt:+"$gpg_sign_opt"} || {
-			warn "Could not amend commit after successfully picking $sha1... $rest"
-			exit_with_patch $sha1 1
-		}
+		# TODO: Work around the fact that git-commit lets us
+		# disable either both the pre-commit and the commit-msg
+		# hook or none. Disable the pre-commit hook because the
+		# tree is left unchanged but run the commit-msg hook
+		# from here because the log message is altered.
+		git commit --allow-empty --amend --no-post-rewrite -n ${gpg_sign_opt:+"$gpg_sign_opt"} &&
+			if test -x "$GIT_DIR"/hooks/commit-msg
+			then
+				"$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG
+			fi || {
+				warn "Could not amend commit after successfully picking $sha1... $rest"
+				exit_with_patch $sha1 1
+			}
 		record_in_rewritten $sha1
 		;;
 	edit|e)
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 9931143..2da4b9c 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -577,6 +577,44 @@ test_expect_success 'rebase a commit violating pre-commit' '
 
 '
 
+test_expect_success 'reword a commit violating pre-commit' '
+	test_when_finished rm -r .git/hooks &&
+	mkdir -p .git/hooks &&
+	PRE_COMMIT=.git/hooks/pre-commit &&
+	cat >"$PRE_COMMIT" <<EOF
+#!/bin/sh
+echo running pre-commit: exit 1
+exit 1
+EOF
+	chmod +x "$PRE_COMMIT" &&
+	test_must_fail test_commit pre-commit-violated &&
+	test_commit --no-verify pre-commit-violated &&
+	test_when_finished reset_rebase &&
+	set_fake_editor &&
+	FAKE_LINES="pick 1" git rebase -i HEAD^ &&
+	FAKE_LINES="pick 1" git rebase -i --no-ff HEAD^ &&
+	FAKE_LINES="reword 1" git rebase -i HEAD^
+'
+
+test_expect_success 'reword a commit violating commit-msg' '
+	test_when_finished rm -r .git/hooks &&
+	mkdir -p .git/hooks &&
+	COMMIT_MSG=.git/hooks/commit-msg &&
+	cat >"$COMMIT_MSG" <<EOF
+#!/bin/sh
+echo running commit-msg: exit 1
+exit 1
+EOF
+	chmod +x "$COMMIT_MSG" &&
+	test_must_fail test_commit commit-msg-violated &&
+	test_commit --no-verify commit-msg-violated &&
+	test_when_finished reset_rebase &&
+	set_fake_editor &&
+	FAKE_LINES="pick 1" git rebase -i HEAD^ &&
+	FAKE_LINES="pick 1" git rebase -i --no-ff HEAD^ &&
+	test_must_fail env FAKE_LINES="reword 1" git rebase -i HEAD^
+'
+
 test_expect_success 'rebase with a file named HEAD in worktree' '
 
 	rm -fr .git/hooks &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 0377d3e..db65653 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -155,6 +155,7 @@ test_pause () {
 test_commit () {
 	notick= &&
 	signoff= &&
+	noverify= &&
 	while test $# != 0
 	do
 		case "$1" in
@@ -164,6 +165,9 @@ test_commit () {
 		--signoff)
 			signoff="$1"
 			;;
+		--no-verify)
+			noverify="$1"
+			;;
 		*)
 			break
 			;;
@@ -177,7 +181,7 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit $signoff -m "$1" &&
+	git commit $signoff $noverify -m "$1" &&
 	git tag "${4:-$1}"
 }
 
-- 
2.0.1

^ permalink raw reply related	[relevance 11%]

* Re: [PATCH] Documentation: add a script to generate a (long/short) options overview
  @ 2013-10-31 23:09  7%   ` Stefan Beller
  0 siblings, 0 replies; 171+ results
From: Stefan Beller @ 2013-10-31 23:09 UTC (permalink / raw)
  To: Stefan Beller, tr, mhagger, git

On 11/01/2013 12:04 AM, Stefan Beller wrote:
> Recently a discussion started on the mailing list, which short option
> shall be best for a long option. (-f being always --force and therefore
> should not be reassigned another meaning in one particular command)
> See http://www.mail-archive.com/git@vger.kernel.org/msg38456.html
> 
> For discussions as these we need a script to easily generate an
> overview of all available one letter options, and their long option
> equivalents.
> 
> As the list of options was not retrieved fully automated,
> there might be minor errors or missing items.
> 
> Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
> ---
>  Documentation/generateShortOptions.py | 460 ++++++++++++++++++++++++++++++++++
>  1 file changed, 460 insertions(+)
>  create mode 100644 Documentation/generateShortOptions.py
> 

When trying to send a follow-up patch with the table itself, I got:
fatal: /tmp/wHpJlnf1r5/0002-Documentation-add-table-viewing-short-long-options-f.patch: 19: patch contains a line longer than 998 characters
warning: no patches were sent

Is this an artifical limitation or something that actually makes sense?

Anyway here is the table, updated to carry more commands and sorted:

>From 7d2ba0af3500f1629783dfc80aafe218dee8618c Mon Sep 17 00:00:00 2001
From: Stefan Beller <stefanbeller@googlemail.com>
Date: Fri, 1 Nov 2013 00:01:21 +0100
Subject: [PATCH 2/2] Documentation: add table viewing (short/long) options for
 all commands

Signed-off-by: Stefan Beller <stefanbeller@googlemail.com>
---
 Documentation/ShortOptions.txt | 73 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/ShortOptions.txt

diff --git a/Documentation/ShortOptions.txt b/Documentation/ShortOptions.txt
new file mode 100644
index 0000000..dd76512
--- /dev/null
+++ b/Documentation/ShortOptions.txt
@@ -0,0 +1,73 @@
+         Name\short |      q |             v |             n |          s |      f |         m |                u |         a |              p |        e |                   l |                X |            i |              n |                p |            d |                  u |                 o |             f |              F |               c |         t |     z |       a |                    b |      q |              A |              N |             k |                   i |               s |       3 |              C |         S |       b |       g |        r |            w |               B |            C |                    D |             M |        U |                 W |              c |           e |     k |            m |       r |        v |                 w |     2 |  
              B |                E |             G |               H |                    L |                    O |            P |        R |                 W |        x |     3 |                E |
              F |         N |      d |             g |      h |      l |     t |     x
+                add |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          add
+                 am |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |               utf8 |                   |               |                |                 |           |       |         |                      |  quiet |                |                |               |         interactive |         signoff |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |  3way |                  |
                |           |        |               |        |        |       |          am
+           annotate |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |        porcelain |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          annotate
+              apply |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |    3way |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |  reverse |                   |          |       |                  |
                |           |        |               |        |        |       |          apply
+            archive |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |            output |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          archive
+              blame |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |    show-number |        porcelain |              |                    |                   |     show-name |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |  show-email |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          blame
+             branch |  quiet |       verbose |               |            |  force |      move |  set-upstream-to |       all |                |          |       create-reflog |                  |              |                |                  |       delete |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          branch
+         check-attr |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          check-attr
+       check-ignore |  quiet |       verbose |  non-matching |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          check-ignore
+           checkout |  quiet |               |               |            |  force |     merge |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |     track |       |         |                      |        |                |                |               |                     |                 |  theirs |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |  ours |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          checkout
+     checkout-index |  quiet |               |     no-create |            |  force |           |            index |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          checkout-index
+             cherry |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          cherry
+        cherry-pick |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          cherry-pick
+              clean |  quiet |               |       dry-run |            |  force |           |                  |           |                |  exclude |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          clean
+              clone |  quiet |       verbose |   no-checkout |     shared |        |           |      upload-pack |           |                |          |               local |                  |              |                |                  |              |                    |            origin |               |                |          config |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          clone
+             commit |  quiet |       verbose |     no-verify |    signoff |        |   message |  untracked-files |       all |          patch |     edit |                     |                  |      include |                |                  |              |                    |              only |               |           file |  reedit-message |  template |  null |         |                      |        |                |                |               |                     |                 |         |  reuse-message |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          commit
+             config |        |               |               |            |   file |           |                  |           |                |     edit |                list |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          config
+      count-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |  human-readable |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          count-objects
+               diff |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |                |             |       |              |         |          |  ignore-all-space |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          diff
+         diff-files |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |              patch |                   |               |                |                 |           |       |    text |  ignore-space-change |        |                |                |               |                     |                 |         |                |           |         |         |          |              |  break-rewrites |  find-copies |  irreversible-delete |  find-renames |  unified |  function-context |             cc |             |       |              |         |          |  ignore-all-space |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          diff-files
+              fetch |  quiet |       verbose |               |            |  force |  multiple |   update-head-ok |    append |          prune |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |      tags |       |         |                      |        |                |                |          keep |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fetch
+      filter-branch |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |         force |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          filter-branch
+      fmt-merge-msg |        |               |               |            |        |   message |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fmt-merge-msg
+       for-each-ref |        |               |               |      shell |        |           |                  |           |           perl |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          for-each-ref
+       format-patch |  quiet |  reroll-count |      numbered |    signoff |        |           |                  |           |        no-stat |          |                     |                  |              |                |                  |              |                    |  output-directory |               |                |                 |           |       |         |                      |        |                |    no-numbered |  keep-subject |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          format-patch
+               fsck |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fsck
+       fsck-objects |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          fsck-objects
+                 gc |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          gc
+               grep |  quiet |  invert-match |   line-number |            |        |           |                  |      text |  show-function |          |  files-with-matches |                  |  ignore-case |                |                  |              |                    |                   |               |  fixed-strings |           count |           |  null |         |                      |        |  after-context |                |               |                     |                 |         |        context |           |         |         |          |  word-regexp |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
 before-context |  extended-regexp |  basic-regexp |                 |  files-without-match |  open-files-in-pager |  perl-regexp |          |  function-context |          |       |                  |
                |           |        |               |        |        |       |          grep
+               help |        |               |               |            |        |       man |                  |       all |                |          |                     |                  |         info |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  guides |          |          web |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          help
+               init |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          init
+            init-db |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          init-db
+          insta-web |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |             port |              |                    |                   |               |                |                 |           |       |         |              browser |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |  module-path |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |  httpd |               |        |  local |       |          insta-web
+                log |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          log
+           ls-files |        |               |               |      stage |        |  modified |         unmerged |           |                |          |                     |     exclude-from |      ignored |                |                  |      deleted |                    |            others |               |                |          cached |           |       |         |                      |        |                |                |        killed |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |  exclude |       |                  |
                |           |        |               |        |        |       |          ls-files
+         ls-remotes |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |        upload-pack |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |  heads |        |  tags |          ls-remotes
+            ls-tree |        |               |               |            |        |           |                  |           |                |          |                long |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          ls-tree
+              merge |  quiet |       verbose |       no-stat |   strategy |        |   message |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |  gpg-sign |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge
+         merge-base |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge-base
+         merge-file |  quiet |               |               |            |        |           |                  |           |         stdout |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          merge-file
+                 mv |        |       verbose |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          mv
+       pack-objects |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          pack-objects
+              prune |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          prune
+       prune-packed |  quiet |               |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          prune-packed
+               pull |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |                  |              |     update-head-ok |                   |         force |                |                 |           |       |  append |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |  keep |              |  rebase |  verbose |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          pull
+               push |  quiet |       verbose |       dry-run |            |  force |           |     set-upstream |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          push
+       quilt-import |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |        dry-run |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          quilt-import
+          read-tree |        |       verbose |       dry-run |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          read-tree
+             rebase |        |               |               |   strategy |        |           |                  |           |                |          |                     |  strategy-option |              |        no-stat |  preserve-merges |              |                    |                   |  force-rebase |                |                 |           |       |         |                      |        |                |                |               |         interactive |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |        merge |  rebase |  verbose |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |  exec    rebase
+             reflog |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          reflog
+             remote |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          remote
+             repack |  quiet |               |               |            |        |           |                  |           |                |          |               local |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          repack
+            replace |        |               |               |            |  force |           |                  |           |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          replace
+              reset |  quiet |               |               |            |        |           |                  |           |          patch |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          reset
+           rev-list |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |      max-count |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |  regexp-ignore-case |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |  extended-regexp |
  fixed-strings |           |        |  walk-reflogs |        |        |       |          rev-list
+             revert |        |               |     no-commit |    signoff |        |  mainline |                  |           |                |     edit |                     |  strategy-option |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          revert
+                 rm |  quiet |               |       dry-run |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          rm
+           shortlog |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |       numbered |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |         summary |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |       email |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          shortlog
+               show |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show
+        show-branch |        |               |               |            |        |           |                  |       all |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |  reflog |  remotes |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show-branch
+           show-ref |  quiet |               |               |       hash |        |           |                  |           |                |          |                     |                  |              |                |                  |  dereference |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          show-ref
+              stage |        |       verbose |       dry-run |            |  force |           |           update |           |          patch |     edit |                     |                  |  interactive |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |            all |  intent-to-add |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stage
+              stash |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |            patch |              |  include-untracked |                   |               |                |                 |           |       |     all |                      |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stash
+             status |        |       verbose |               |      short |        |           |  untracked-files |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |  null |         |                      |        |                |                |               |                     |                 |         |                |           |  branch |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          status
+         stripspace |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |  strip-comments |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |  comment-lines |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          stripspace
+          submodule |        |               |               |            |        |           |                  |           |                |          |                     |                  |              |  summary-limit |                  |              |                    |                   |         force |                |                 |           |       |         |               branch |  quiet |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |  no-fetch |        |               |        |        |       |          submodule
+       symbolic-ref |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |       delete |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          symbolic-ref
+                tag |        |        verify |               |       sign |  force |   message |       local-user |  annotate |                |          |                list |                  |              |                |                  |       delete |                    |                   |               |           file |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          tag
+ update-server-info |        |               |               |            |  force |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          update-server-info
+        verify-pack |        |       verbose |               |  stat-only |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          verify-pack
+         verify-tag |        |       verbose |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          verify-tag
+        whatchanged |  quiet |               |               |            |        |           |                  |           |                |          |                     |                  |              |                |                  |              |                    |                   |               |                |                 |           |       |         |                      |        |                |                |               |                     |                 |         |                |           |         |         |          |              |                 |              |                      |               |          |                   |                |             |       |              |         |          |                   |       |  
                |                  |               |                 |                      |                      |              |          |                   |          |       |                  |
                |           |        |               |        |        |       |          whatchanged
-- 
1.8.4.1.605.g23c6912

^ permalink raw reply related	[relevance 7%]

* [PATCH] completion: add more cherry-pick options
@ 2013-04-10  9:08  6% Felipe Contreras
  0 siblings, 0 replies; 171+ results
From: Felipe Contreras @ 2013-04-10  9:08 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, SZEDER Gábor, Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 contrib/completion/git-completion.bash | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 93eba46..d257b90 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1124,9 +1124,14 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
+	local dir="$(__gitdir)"
+	if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
+		__gitcomp "--continue --quit --abort"
+		return
+	fi
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --no-commit"
+		__gitcomp "--edit --no-commit --signoff --strategy= --mainline"
 		;;
 	*)
 		__gitcomp_nl "$(__git_refs)"
-- 
1.8.2.1

^ permalink raw reply related	[relevance 6%]

* [PATCH v4 03/12] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  @ 2013-02-12 10:17  6% ` Brandon Casey
  2017-05-13 17:41  0%   ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 171+ results
From: Brandon Casey @ 2013-02-12 10:17 UTC (permalink / raw)
  To: git; +Cc: gitster, pclouds, jrnieder, Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
---
 t/test-lib-functions.sh | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fa62d01..61d0804 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,12 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message, and tag the resulting commit with the given tag name.
 #
-# Both <file> and <contents> default to <message>.
+# <file>, <contents>, and <tag> all default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +168,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.1.3.579.gd9af3b6

^ permalink raw reply related	[relevance 6%]

* [PATCH v3 03/11] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  @ 2013-01-28  1:11  6% ` Brandon Casey
  0 siblings, 0 replies; 171+ results
From: Brandon Casey @ 2013-01-28  1:11 UTC (permalink / raw)
  To: git; +Cc: jrnieder, pclouds, gitster, Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
---
 t/test-lib-functions.sh | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fa62d01..61d0804 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,12 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message, and tag the resulting commit with the given tag name.
 #
-# Both <file> and <contents> default to <message>.
+# <file>, <contents>, and <tag> all default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +168,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.1.1.450.g0327af3

^ permalink raw reply related	[relevance 6%]

* [PATCH v2 02/10] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  @ 2013-01-21  8:40  6% ` Brandon Casey
  0 siblings, 0 replies; 171+ results
From: Brandon Casey @ 2013-01-21  8:40 UTC (permalink / raw)
  To: gitster; +Cc: pclouds, git, Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
---
 t/test-lib-functions.sh | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index fa62d01..c601918 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,13 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message.  It will also add a tag with <message> as name unless <tag> is
+# given.
 #
-# Both <file> and <contents> default to <message>.
+# <file>, <contents>, and <tag> all default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +169,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.1.1.252.gdb33759

^ permalink raw reply related	[relevance 6%]

* Re: [PATCH] Alphabetize the fast-import options, following a suggestion on the list.
  @ 2013-01-05 23:11  5% ` Jonathan Nieder
  0 siblings, 0 replies; 171+ results
From: Jonathan Nieder @ 2013-01-05 23:11 UTC (permalink / raw)
  To: Eric S. Raymond; +Cc: git, David Michael Barr, Pete Wyckoff

Eric S. Raymond wrote:

> ---

Missing sign-off.  Depending on when you prefer to add the sign-off, something
like

	echo '[alias] c = commit --signoff' >>~/.gitconfig

or

	echo '[alias] f = format-patch --signoff' >>~/.gitconfig

might be useful for the future, assuming you already look over what
you are sending out in a mail client to avoid mistakes.

> Documentation/git-fast-import.txt | 94 +++++++++++++++++++--------------------
> 1 file changed, 45 insertions(+), 49 deletions(-)

My knee-jerk response was "If the options are currently organized logically,
wouldn't it be more appropriate to add a sub-heading for each group of options
and alphabetize only within the subgroups?"

But in fact the current options list doesn't seem to be well organized at all.
What do you think would be a logical way to group these?

 Features of input syntax

	--date-format
	--done

 Verbosity

	--quiet
	--stats

 Marks handling (checkpoint/restore)

	--import-marks
	--import-marks-if-exists
	--export-marks
	--relative-marks

 Semantics of execution

	--dry-run
	--force
	--cat-blob-fd
	--export-pack-edges

 Tuning

	--active-branches
	--max-pack-size
	--big-file-threshold
	--depth

^ permalink raw reply	[relevance 5%]

* [PATCH 02/11] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  @ 2012-11-26  1:45  6% ` Brandon Casey
  0 siblings, 0 replies; 171+ results
From: Brandon Casey @ 2012-11-26  1:45 UTC (permalink / raw)
  To: git; +Cc: pclouds, gitster, Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
---
 t/test-lib-functions.sh | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8889ba5..9e2b8b8 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,13 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message.  It will also add a tag with <message> as name unless <tag> is
+# given.
 #
-# Both <file> and <contents> default to <message>.
+# <file>, <contents>, and <tag> all default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +169,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.0.284.g959048a

^ permalink raw reply related	[relevance 6%]

* [PATCH 1/5 v2] t/test-lib-functions.sh: allow to specify the tag name to test_commit
  @ 2012-11-15  5:49  6% ` Brandon Casey
  0 siblings, 0 replies; 171+ results
From: Brandon Casey @ 2012-11-15  5:49 UTC (permalink / raw)
  To: kraai; +Cc: git, Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
---
 t/test-lib-functions.sh | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8889ba5..9e2b8b8 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,13 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message.  It will also add a tag with <message> as name unless <tag> is
+# given.
 #
-# Both <file> and <contents> default to <message>.
+# <file>, <contents>, and <tag> all default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +169,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.0

^ permalink raw reply related	[relevance 6%]

* [PATCH 1/5] t/test-lib-functions.sh: allow to specify the tag name to test_commit
@ 2012-11-15  1:37  6% Brandon Casey
  0 siblings, 0 replies; 171+ results
From: Brandon Casey @ 2012-11-15  1:37 UTC (permalink / raw)
  To: git; +Cc: Brandon Casey, Brandon Casey

The <message> part of test_commit() may not be appropriate for a tag name.
So let's allow test_commit to accept a fourth argument to specify the tag
name.

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
---
 t/test-lib-functions.sh | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8889ba5..4d6057e 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -135,12 +135,13 @@ test_pause () {
 	fi
 }
 
-# Call test_commit with the arguments "<message> [<file> [<contents>]]"
+# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]"
 #
 # This will commit a file with the given contents and the given commit
-# message.  It will also add a tag with <message> as name.
+# message.  It will also add a tag with <message> as name unless <tag> is
+# given.
 #
-# Both <file> and <contents> default to <message>.
+# Both <file> <contents> and <tag> default to <message>.
 
 test_commit () {
 	notick= &&
@@ -168,7 +169,7 @@ test_commit () {
 		test_tick
 	fi &&
 	git commit $signoff -m "$1" &&
-	git tag "$1"
+	git tag "${4:-$1}"
 }
 
 # Call test_merge with the arguments "<message> <commit>", where <commit>
-- 
1.8.0

^ permalink raw reply related	[relevance 6%]

* Re: How to create the " [PATCH 0/5]" first email?
  @ 2012-09-18 20:16  5%                   ` Jeff King
  0 siblings, 0 replies; 171+ results
From: Jeff King @ 2012-09-18 20:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Philip Oakley, Git List

On Tue, Sep 18, 2012 at 12:47:36PM -0700, Junio C Hamano wrote:

> >> Jeff King <peff@peff.net> writes:
> >> 
> >> > But even without that, I still think format-patch is a reasonable time
> >> > to do it. It is the time when I proof-read my commit message and patch
> >> > in its final form, and think "do I really want to send this?".
> >> 
> >> But it is not like "I cannot sign off because I think it is still
> >> iffy".
> >
> > No, that is not the particular reason in my case, but I think I
> > explained other reasons why "format-patch -s" is not a wrong workflow.
> 
> Then I didn't read it.  What does "do I really want to send this?"
> have anything to do with DCO in any case?

Because it is an excellent time to think about "am I willing and able to
agree to the DCO?" As I said, for me personally working on git.git, that
is not generally an issue. But I think it is perfectly reasonable for
somebody to work and commit in isolation, and then only decide on the
DCO during the sending phase (perhaps because they need to clear it with
their company's legal department or some such). In other words, "it is
iffy at the time of commit" might be exactly the reason for some people.

If you are responding to my "that is not the particular reason in my
case", I will paraphrase the reason I gave earlier: I find it annoying
and pointless to type "-s" on every commit. We do not have
commit.signoff, but we do have format.signoff.

-Peff

^ permalink raw reply	[relevance 5%]

* [PATCH v4] cherry-pick: don't forget -s on failure
  @ 2012-09-14  6:52  7%             ` Miklos Vajna
  0 siblings, 0 replies; 171+ results
From: Miklos Vajna @ 2012-09-14  6:52 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Robin Stocker

In case 'git cherry-pick -s <commit>' failed, the user had to use 'git
commit -s' (i.e. state the -s option again), which is easy to forget
about.  Instead, write the signed-off-by line early, so plain 'git
commit' will have the same result.

Also update 'git commit -s', so that in case there is already a relevant
Signed-off-by line before the Conflicts: line, it won't add one more at
the end of the message. If there is no such line, then add it before the
the Conflicts: line.

Signed-off-by: Miklos Vajna <vmiklos@suse.cz>
---

On Thu, Sep 13, 2012 at 02:13:46PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
> That's decl-after-stmt.

Sorry, added -Wdeclaration-after-statement to CFLAGS now.

> I would have expected that you can just do strbuf_splice() to add
> the &sob into &msgbuf with the original code structure, without a
> substantial rewrite of the function like this.  Perhaps I am missing
> something?

I forgot about strbuf_splice(). ;-) Here is a version with it -- it's 
indeed shorter, even if ends_rfc2822_footer() now has to be aware of a 
possible footer.

 builtin/commit.c                |   79 +++++++++++---------------------------
 sequencer.c                     |   65 ++++++++++++++++++++++++++++++++
 sequencer.h                     |    4 ++
 t/t3507-cherry-pick-conflict.sh |   32 ++++++++++++++++
 t/t3510-cherry-pick-sequence.sh |    6 +-
 t/test-lib-functions.sh         |   20 +++++++--
 6 files changed, 142 insertions(+), 64 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 778cf16..4d50484 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -28,6 +28,7 @@
 #include "submodule.h"
 #include "gpg-interface.h"
 #include "column.h"
+#include "sequencer.h"
 
 static const char * const builtin_commit_usage[] = {
 	N_("git commit [options] [--] <filepattern>..."),
@@ -466,8 +467,6 @@ static int is_a_merge(const struct commit *current_head)
 	return !!(current_head->parents && current_head->parents->next);
 }
 
-static const char sign_off_header[] = "Signed-off-by: ";
-
 static void export_one(const char *var, const char *s, const char *e, int hack)
 {
 	struct strbuf buf = STRBUF_INIT;
@@ -552,47 +551,6 @@ static void determine_author_info(struct strbuf *author_ident)
 	}
 }
 
-static int ends_rfc2822_footer(struct strbuf *sb)
-{
-	int ch;
-	int hit = 0;
-	int i, j, k;
-	int len = sb->len;
-	int first = 1;
-	const char *buf = sb->buf;
-
-	for (i = len - 1; i > 0; i--) {
-		if (hit && buf[i] == '\n')
-			break;
-		hit = (buf[i] == '\n');
-	}
-
-	while (i < len - 1 && buf[i] == '\n')
-		i++;
-
-	for (; i < len; i = k) {
-		for (k = i; k < len && buf[k] != '\n'; k++)
-			; /* do nothing */
-		k++;
-
-		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
-			continue;
-
-		first = 0;
-
-		for (j = 0; i + j < len; j++) {
-			ch = buf[i + j];
-			if (ch == ':')
-				break;
-			if (isalnum(ch) ||
-			    (ch == '-'))
-				continue;
-			return 0;
-		}
-	}
-	return 1;
-}
-
 static char *cut_ident_timestamp_part(char *string)
 {
 	char *ket = strrchr(string, '>');
@@ -717,21 +675,30 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		stripspace(&sb, 0);
 
 	if (signoff) {
-		struct strbuf sob = STRBUF_INIT;
-		int i;
+		/*
+		 * See if we have a Conflicts: block at the end. If yes, count
+		 * its size, so we can ignore it.
+		 */
+		int ignore_footer = 0;
+		int i, eol, previous = 0;
+		const char *nl;
 
-		strbuf_addstr(&sob, sign_off_header);
-		strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
-					     getenv("GIT_COMMITTER_EMAIL")));
-		strbuf_addch(&sob, '\n');
-		for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
-			; /* do nothing */
-		if (prefixcmp(sb.buf + i, sob.buf)) {
-			if (!i || !ends_rfc2822_footer(&sb))
-				strbuf_addch(&sb, '\n');
-			strbuf_addbuf(&sb, &sob);
+		for (i = 0; i < sb.len; i++) {
+			nl = memchr(sb.buf + i, '\n', sb.len - i);
+			if (nl)
+				eol = nl - sb.buf;
+			else
+				eol = sb.len;
+			if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) {
+				ignore_footer = sb.len - previous;
+				break;
+			}
+			while (i < eol)
+				i++;
+			previous = eol;
 		}
-		strbuf_release(&sob);
+
+		append_signoff(&sb, ignore_footer);
 	}
 
 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
diff --git a/sequencer.c b/sequencer.c
index f86f116..dbef5ce 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -17,6 +17,8 @@
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
+const char sign_off_header[] = "Signed-off-by: ";
+
 void remove_sequencer_state(void)
 {
 	struct strbuf seq_dir = STRBUF_INIT;
@@ -233,6 +235,9 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
 		die(_("%s: Unable to write new index file"), action_name(opts));
 	rollback_lock_file(&index_lock);
 
+	if (opts->signoff)
+		append_signoff(msgbuf, 0);
+
 	if (!clean) {
 		int i;
 		strbuf_addstr(msgbuf, "\nConflicts:\n");
@@ -1011,3 +1016,63 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 	save_opts(opts);
 	return pick_commits(todo_list, opts);
 }
+
+static int ends_rfc2822_footer(struct strbuf *sb, int ignore_footer)
+{
+	int ch;
+	int hit = 0;
+	int i, j, k;
+	int len = sb->len - ignore_footer;
+	int first = 1;
+	const char *buf = sb->buf;
+
+	for (i = len - 1; i > 0; i--) {
+		if (hit && buf[i] == '\n')
+			break;
+		hit = (buf[i] == '\n');
+	}
+
+	while (i < len - 1 && buf[i] == '\n')
+		i++;
+
+	for (; i < len; i = k) {
+		for (k = i; k < len && buf[k] != '\n'; k++)
+			; /* do nothing */
+		k++;
+
+		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
+			continue;
+
+		first = 0;
+
+		for (j = 0; i + j < len; j++) {
+			ch = buf[i + j];
+			if (ch == ':')
+				break;
+			if (isalnum(ch) ||
+			    (ch == '-'))
+				continue;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer)
+{
+	struct strbuf sob = STRBUF_INIT;
+	int i;
+
+	strbuf_addstr(&sob, sign_off_header);
+	strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
+				getenv("GIT_COMMITTER_EMAIL")));
+	strbuf_addch(&sob, '\n');
+	for (i = msgbuf->len - 1 - ignore_footer; i > 0 && msgbuf->buf[i - 1] != '\n'; i--)
+		; /* do nothing */
+	if (prefixcmp(msgbuf->buf + i, sob.buf)) {
+		if (!i || !ends_rfc2822_footer(msgbuf, ignore_footer))
+			strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0, "\n", 1);
+		strbuf_splice(msgbuf, msgbuf->len - ignore_footer, 0, sob.buf, sob.len);
+	}
+	strbuf_release(&sob);
+}
diff --git a/sequencer.h b/sequencer.h
index d849420..60287b8 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -49,4 +49,8 @@ extern void remove_sequencer_state(void);
 
 int sequencer_pick_revisions(struct replay_opts *opts);
 
+extern const char sign_off_header[];
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer);
+
 #endif
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 0c81b3c..c82f721 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -30,6 +30,7 @@ test_expect_success setup '
 	test_commit initial foo a &&
 	test_commit base foo b &&
 	test_commit picked foo c &&
+	test_commit --signoff picked-signed foo d &&
 	git config advice.detachedhead false
 
 '
@@ -340,4 +341,35 @@ test_expect_success 'revert conflict, diff3 -m style' '
 	test_cmp expected actual
 '
 
+test_expect_success 'failed cherry-pick does not forget -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked &&
+	test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
+'
+
+test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked-signed &&
+	git commit -a -s &&
+	test $(git show -s |grep -c "Signed-off-by") = 1
+'
+
+test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick picked &&
+	git commit -a -s &&
+	pwd &&
+	cat <<EOF > expected &&
+picked
+
+Signed-off-by: C O Mitter <committer@example.com>
+
+Conflicts:
+	foo
+EOF
+
+	git show -s --pretty=format:%B > actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index f4e6450..b5fb527 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -410,7 +410,7 @@ test_expect_success '--continue respects -x in first commit in multi-pick' '
 	grep "cherry picked from.*$picked" msg
 '
 
-test_expect_success '--signoff is not automatically propagated to resolved conflict' '
+test_expect_failure '--signoff is automatically propagated to resolved conflict' '
 	pristine_detach initial &&
 	test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
 	echo "c" >foo &&
@@ -428,7 +428,7 @@ test_expect_success '--signoff is not automatically propagated to resolved confl
 	grep "Signed-off-by:" anotherpick_msg
 '
 
-test_expect_success '--signoff dropped for implicit commit of resolution, multi-pick case' '
+test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked anotherpick &&
 	echo c >foo &&
@@ -441,7 +441,7 @@ test_expect_success '--signoff dropped for implicit commit of resolution, multi-
 	! grep Signed-off-by: msg
 '
 
-test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
+test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked &&
 	echo c >foo &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 9bc57d2..0802da5 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -144,11 +144,21 @@ test_pause () {
 
 test_commit () {
 	notick= &&
-	if test "z$1" = "z--notick"
-	then
-		notick=yes
+	signoff= &&
+	while test $# != 0; do
+		case "$1" in
+		--notick)
+			notick=yes
+			;;
+		--signoff)
+			signoff="$1"
+			;;
+		*)
+			break
+			;;
+		esac
 		shift
-	fi &&
+	done &&
 	file=${2:-"$1.t"} &&
 	echo "${3-$1}" > "$file" &&
 	git add "$file" &&
@@ -156,7 +166,7 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit -m "$1" &&
+	git commit $signoff -m "$1" &&
 	git tag "$1"
 }
 
-- 
1.7.7

^ permalink raw reply related	[relevance 7%]

* [PATCH v3] cherry-pick: don't forget -s on failure
  @ 2012-09-13 20:27  7%         ` Miklos Vajna
    0 siblings, 1 reply; 171+ results
From: Miklos Vajna @ 2012-09-13 20:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Robin Stocker

In case 'git cherry-pick -s <commit>' failed, the user had to use 'git
commit -s' (i.e. state the -s option again), which is easy to forget
about.  Instead, write the signed-off-by line early, so plain 'git
commit' will have the same result.

Also update 'git commit -s', so that in case there is already a relevant
Signed-off-by line before the Conflicts: line, it won't add one more at
the end of the message. If there is no such line, then add it before the
the Conflicts: line.

Signed-off-by: Miklos Vajna <vmiklos@suse.cz>
---

> This is somewhat iffy.  Shouldn't "test_commit --signoff --notick"
> work?

Indeed, fixed now.

> Hrm, what is this thing trying to do?  It does start scanning from
> the end (ignoring the "Conflicts:" thing) to see who the last person
> that signed it off was, but once it decides that it needs to add a
> new sign-off, it still adds it at the very end anyway.

Ah, I did not handle that, as the original git commit -s didn't do it 
either -- and originally I just wanted to touch git cherry-pick. 
Implemented now.

 builtin/commit.c                |   79 +++++++++++---------------------------
 sequencer.c                     |   72 +++++++++++++++++++++++++++++++++++
 sequencer.h                     |    4 ++
 t/t3507-cherry-pick-conflict.sh |   32 ++++++++++++++++
 t/t3510-cherry-pick-sequence.sh |    6 +-
 t/test-lib-functions.sh         |   20 +++++++--
 6 files changed, 149 insertions(+), 64 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 778cf16..4d50484 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -28,6 +28,7 @@
 #include "submodule.h"
 #include "gpg-interface.h"
 #include "column.h"
+#include "sequencer.h"
 
 static const char * const builtin_commit_usage[] = {
 	N_("git commit [options] [--] <filepattern>..."),
@@ -466,8 +467,6 @@ static int is_a_merge(const struct commit *current_head)
 	return !!(current_head->parents && current_head->parents->next);
 }
 
-static const char sign_off_header[] = "Signed-off-by: ";
-
 static void export_one(const char *var, const char *s, const char *e, int hack)
 {
 	struct strbuf buf = STRBUF_INIT;
@@ -552,47 +551,6 @@ static void determine_author_info(struct strbuf *author_ident)
 	}
 }
 
-static int ends_rfc2822_footer(struct strbuf *sb)
-{
-	int ch;
-	int hit = 0;
-	int i, j, k;
-	int len = sb->len;
-	int first = 1;
-	const char *buf = sb->buf;
-
-	for (i = len - 1; i > 0; i--) {
-		if (hit && buf[i] == '\n')
-			break;
-		hit = (buf[i] == '\n');
-	}
-
-	while (i < len - 1 && buf[i] == '\n')
-		i++;
-
-	for (; i < len; i = k) {
-		for (k = i; k < len && buf[k] != '\n'; k++)
-			; /* do nothing */
-		k++;
-
-		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
-			continue;
-
-		first = 0;
-
-		for (j = 0; i + j < len; j++) {
-			ch = buf[i + j];
-			if (ch == ':')
-				break;
-			if (isalnum(ch) ||
-			    (ch == '-'))
-				continue;
-			return 0;
-		}
-	}
-	return 1;
-}
-
 static char *cut_ident_timestamp_part(char *string)
 {
 	char *ket = strrchr(string, '>');
@@ -717,21 +675,30 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		stripspace(&sb, 0);
 
 	if (signoff) {
-		struct strbuf sob = STRBUF_INIT;
-		int i;
+		/*
+		 * See if we have a Conflicts: block at the end. If yes, count
+		 * its size, so we can ignore it.
+		 */
+		int ignore_footer = 0;
+		int i, eol, previous = 0;
+		const char *nl;
 
-		strbuf_addstr(&sob, sign_off_header);
-		strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
-					     getenv("GIT_COMMITTER_EMAIL")));
-		strbuf_addch(&sob, '\n');
-		for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
-			; /* do nothing */
-		if (prefixcmp(sb.buf + i, sob.buf)) {
-			if (!i || !ends_rfc2822_footer(&sb))
-				strbuf_addch(&sb, '\n');
-			strbuf_addbuf(&sb, &sob);
+		for (i = 0; i < sb.len; i++) {
+			nl = memchr(sb.buf + i, '\n', sb.len - i);
+			if (nl)
+				eol = nl - sb.buf;
+			else
+				eol = sb.len;
+			if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) {
+				ignore_footer = sb.len - previous;
+				break;
+			}
+			while (i < eol)
+				i++;
+			previous = eol;
 		}
-		strbuf_release(&sob);
+
+		append_signoff(&sb, ignore_footer);
 	}
 
 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
diff --git a/sequencer.c b/sequencer.c
index f86f116..4420807 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -17,6 +17,8 @@
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
+const char sign_off_header[] = "Signed-off-by: ";
+
 void remove_sequencer_state(void)
 {
 	struct strbuf seq_dir = STRBUF_INIT;
@@ -233,6 +235,9 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
 		die(_("%s: Unable to write new index file"), action_name(opts));
 	rollback_lock_file(&index_lock);
 
+	if (opts->signoff)
+		append_signoff(msgbuf, 0);
+
 	if (!clean) {
 		int i;
 		strbuf_addstr(msgbuf, "\nConflicts:\n");
@@ -1011,3 +1016,70 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 	save_opts(opts);
 	return pick_commits(todo_list, opts);
 }
+
+static int ends_rfc2822_footer(struct strbuf *sb)
+{
+	int ch;
+	int hit = 0;
+	int i, j, k;
+	int len = sb->len;
+	int first = 1;
+	const char *buf = sb->buf;
+
+	for (i = len - 1; i > 0; i--) {
+		if (hit && buf[i] == '\n')
+			break;
+		hit = (buf[i] == '\n');
+	}
+
+	while (i < len - 1 && buf[i] == '\n')
+		i++;
+
+	for (; i < len; i = k) {
+		for (k = i; k < len && buf[k] != '\n'; k++)
+			; /* do nothing */
+		k++;
+
+		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
+			continue;
+
+		first = 0;
+
+		for (j = 0; i + j < len; j++) {
+			ch = buf[i + j];
+			if (ch == ':')
+				break;
+			if (isalnum(ch) ||
+			    (ch == '-'))
+				continue;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer)
+{
+	struct strbuf sob = STRBUF_INIT;
+	int i;
+
+	strbuf_addstr(&sob, sign_off_header);
+	strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
+				getenv("GIT_COMMITTER_EMAIL")));
+	strbuf_addch(&sob, '\n');
+	for (i = msgbuf->len - 1 - ignore_footer; i > 0 && msgbuf->buf[i - 1] != '\n'; i--)
+		; /* do nothing */
+	struct strbuf footer = STRBUF_INIT;
+	if (ignore_footer > 0) {
+		strbuf_addstr(&footer, msgbuf->buf + msgbuf->len - ignore_footer);
+		strbuf_setlen(msgbuf, msgbuf->len - ignore_footer);
+	}
+	if (prefixcmp(msgbuf->buf + i, sob.buf)) {
+		if (!i || !ends_rfc2822_footer(msgbuf))
+			strbuf_addch(msgbuf, '\n');
+		strbuf_addbuf(msgbuf, &sob);
+	}
+	strbuf_release(&sob);
+	strbuf_addbuf(msgbuf, &footer);
+	strbuf_release(&footer);
+}
diff --git a/sequencer.h b/sequencer.h
index d849420..60287b8 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -49,4 +49,8 @@ extern void remove_sequencer_state(void);
 
 int sequencer_pick_revisions(struct replay_opts *opts);
 
+extern const char sign_off_header[];
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer);
+
 #endif
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 0c81b3c..c82f721 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -30,6 +30,7 @@ test_expect_success setup '
 	test_commit initial foo a &&
 	test_commit base foo b &&
 	test_commit picked foo c &&
+	test_commit --signoff picked-signed foo d &&
 	git config advice.detachedhead false
 
 '
@@ -340,4 +341,35 @@ test_expect_success 'revert conflict, diff3 -m style' '
 	test_cmp expected actual
 '
 
+test_expect_success 'failed cherry-pick does not forget -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked &&
+	test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
+'
+
+test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked-signed &&
+	git commit -a -s &&
+	test $(git show -s |grep -c "Signed-off-by") = 1
+'
+
+test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick picked &&
+	git commit -a -s &&
+	pwd &&
+	cat <<EOF > expected &&
+picked
+
+Signed-off-by: C O Mitter <committer@example.com>
+
+Conflicts:
+	foo
+EOF
+
+	git show -s --pretty=format:%B > actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index f4e6450..b5fb527 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -410,7 +410,7 @@ test_expect_success '--continue respects -x in first commit in multi-pick' '
 	grep "cherry picked from.*$picked" msg
 '
 
-test_expect_success '--signoff is not automatically propagated to resolved conflict' '
+test_expect_failure '--signoff is automatically propagated to resolved conflict' '
 	pristine_detach initial &&
 	test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
 	echo "c" >foo &&
@@ -428,7 +428,7 @@ test_expect_success '--signoff is not automatically propagated to resolved confl
 	grep "Signed-off-by:" anotherpick_msg
 '
 
-test_expect_success '--signoff dropped for implicit commit of resolution, multi-pick case' '
+test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked anotherpick &&
 	echo c >foo &&
@@ -441,7 +441,7 @@ test_expect_success '--signoff dropped for implicit commit of resolution, multi-
 	! grep Signed-off-by: msg
 '
 
-test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
+test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked &&
 	echo c >foo &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 9bc57d2..0802da5 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -144,11 +144,21 @@ test_pause () {
 
 test_commit () {
 	notick= &&
-	if test "z$1" = "z--notick"
-	then
-		notick=yes
+	signoff= &&
+	while test $# != 0; do
+		case "$1" in
+		--notick)
+			notick=yes
+			;;
+		--signoff)
+			signoff="$1"
+			;;
+		*)
+			break
+			;;
+		esac
 		shift
-	fi &&
+	done &&
 	file=${2:-"$1.t"} &&
 	echo "${3-$1}" > "$file" &&
 	git add "$file" &&
@@ -156,7 +166,7 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit -m "$1" &&
+	git commit $signoff -m "$1" &&
 	git tag "$1"
 }
 
-- 
1.7.7

^ permalink raw reply related	[relevance 7%]

* Re: [PATCH v2] cherry-pick: don't forget -s on failure
  2012-09-13  7:33  7%     ` [PATCH v2] " Miklos Vajna
@ 2012-09-13 17:04  0%       ` Junio C Hamano
    1 sibling, 0 replies; 171+ results
From: Junio C Hamano @ 2012-09-13 17:04 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: git, Robin Stocker

Miklos Vajna <vmiklos@suse.cz> writes:

> In case 'git cherry-pick -s <commit>' failed, the user had to use 'git
> commit -s' (i.e. state the -s option again), which is easy to forget
> about.  Instead, write the signed-off-by line early, so plain 'git
> commit' will have the same result.
>
> Also update 'git commit -s', so that in case there is already a relevant
> Signed-off-by line before the Conflicts: line, it won't add one more at
> the end of the message.
>
> Signed-off-by: Miklos Vajna <vmiklos@suse.cz>
> ---
>
> On Wed, Sep 12, 2012 at 03:45:10PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
>>  - The additional S-o-b should come immediately after the existing
>>    block of footers.
>
> This was trivial to fix.

Indeed.  Just inserting before starting to add "Oh, there were
conflicts, and add the info on them" before doing it at the end is
all it takes.  Simple and straightforward---I like it.

> --- a/t/test-lib-functions.sh
> +++ b/t/test-lib-functions.sh
> @@ -149,6 +149,12 @@ test_commit () {
>  		notick=yes
>  		shift
>  	fi &&
> +	signoff= &&
> +	if test "z$1" = "z--signoff"
> +	then
> +		signoff="$1"
> +		shift
> +	fi &&
>  	file=${2:-"$1.t"} &&
>  	echo "${3-$1}" > "$file" &&
>  	git add "$file" &&

This is somewhat iffy.  Shouldn't "test_commit --signoff --notick" work?

> @@ -156,7 +162,7 @@ test_commit () {
>  	then
>  		test_tick
>  	fi &&
> -	git commit -m "$1" &&
> +	git commit $signoff -m "$1" &&
>  	git tag "$1"
>  }

Thanks.

^ permalink raw reply	[relevance 0%]

* [PATCH v2] cherry-pick: don't forget -s on failure
  @ 2012-09-13  7:33  7%     ` Miklos Vajna
  2012-09-13 17:04  0%       ` Junio C Hamano
    0 siblings, 2 replies; 171+ results
From: Miklos Vajna @ 2012-09-13  7:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Robin Stocker

In case 'git cherry-pick -s <commit>' failed, the user had to use 'git
commit -s' (i.e. state the -s option again), which is easy to forget
about.  Instead, write the signed-off-by line early, so plain 'git
commit' will have the same result.

Also update 'git commit -s', so that in case there is already a relevant
Signed-off-by line before the Conflicts: line, it won't add one more at
the end of the message.

Signed-off-by: Miklos Vajna <vmiklos@suse.cz>
---

On Wed, Sep 12, 2012 at 03:45:10PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
>  - The additional S-o-b should come immediately after the existing
>    block of footers.

This was trivial to fix.

>  - And the last entry in the existing footer block is already mine,
>    so there shouldn't have been a new and duplicated one added.
> 
> 
> I am not sure how reusable the moved function is without
> enhancements for your purpose.  The logic to identify the footer
> needs to be enhanced so that an "end" pointer to point at the byte
> before the caller added "Conflicts: " can be given, and pretend as
> if it is the end of the buffer, unlike in the fresh commit case
> where it can consider the real end of the buffer as such.

Below is what I came up with. It simply ignores anything after the 
Conclicts: line, when checking for the last Signed-off-by line.

An other thing: I forgot to run 'make test' for the initial patch, it 
seems t3510-cherry-pick-sequence.sh has 3 tests that basically ensures 
the opposite of what my patch does. Given that there are already 
testcases for the new behaviour, can they be just removed? For now, I 
just disabled them.

 builtin/commit.c                |   79 +++++++++++---------------------------
 sequencer.c                     |   65 ++++++++++++++++++++++++++++++++
 sequencer.h                     |    4 ++
 t/t3507-cherry-pick-conflict.sh |   14 +++++++
 t/t3510-cherry-pick-sequence.sh |    6 +-
 t/test-lib-functions.sh         |    8 +++-
 6 files changed, 116 insertions(+), 60 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 778cf16..4d50484 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -28,6 +28,7 @@
 #include "submodule.h"
 #include "gpg-interface.h"
 #include "column.h"
+#include "sequencer.h"
 
 static const char * const builtin_commit_usage[] = {
 	N_("git commit [options] [--] <filepattern>..."),
@@ -466,8 +467,6 @@ static int is_a_merge(const struct commit *current_head)
 	return !!(current_head->parents && current_head->parents->next);
 }
 
-static const char sign_off_header[] = "Signed-off-by: ";
-
 static void export_one(const char *var, const char *s, const char *e, int hack)
 {
 	struct strbuf buf = STRBUF_INIT;
@@ -552,47 +551,6 @@ static void determine_author_info(struct strbuf *author_ident)
 	}
 }
 
-static int ends_rfc2822_footer(struct strbuf *sb)
-{
-	int ch;
-	int hit = 0;
-	int i, j, k;
-	int len = sb->len;
-	int first = 1;
-	const char *buf = sb->buf;
-
-	for (i = len - 1; i > 0; i--) {
-		if (hit && buf[i] == '\n')
-			break;
-		hit = (buf[i] == '\n');
-	}
-
-	while (i < len - 1 && buf[i] == '\n')
-		i++;
-
-	for (; i < len; i = k) {
-		for (k = i; k < len && buf[k] != '\n'; k++)
-			; /* do nothing */
-		k++;
-
-		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
-			continue;
-
-		first = 0;
-
-		for (j = 0; i + j < len; j++) {
-			ch = buf[i + j];
-			if (ch == ':')
-				break;
-			if (isalnum(ch) ||
-			    (ch == '-'))
-				continue;
-			return 0;
-		}
-	}
-	return 1;
-}
-
 static char *cut_ident_timestamp_part(char *string)
 {
 	char *ket = strrchr(string, '>');
@@ -717,21 +675,30 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		stripspace(&sb, 0);
 
 	if (signoff) {
-		struct strbuf sob = STRBUF_INIT;
-		int i;
+		/*
+		 * See if we have a Conflicts: block at the end. If yes, count
+		 * its size, so we can ignore it.
+		 */
+		int ignore_footer = 0;
+		int i, eol, previous = 0;
+		const char *nl;
 
-		strbuf_addstr(&sob, sign_off_header);
-		strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
-					     getenv("GIT_COMMITTER_EMAIL")));
-		strbuf_addch(&sob, '\n');
-		for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
-			; /* do nothing */
-		if (prefixcmp(sb.buf + i, sob.buf)) {
-			if (!i || !ends_rfc2822_footer(&sb))
-				strbuf_addch(&sb, '\n');
-			strbuf_addbuf(&sb, &sob);
+		for (i = 0; i < sb.len; i++) {
+			nl = memchr(sb.buf + i, '\n', sb.len - i);
+			if (nl)
+				eol = nl - sb.buf;
+			else
+				eol = sb.len;
+			if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) {
+				ignore_footer = sb.len - previous;
+				break;
+			}
+			while (i < eol)
+				i++;
+			previous = eol;
 		}
-		strbuf_release(&sob);
+
+		append_signoff(&sb, ignore_footer);
 	}
 
 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
diff --git a/sequencer.c b/sequencer.c
index f86f116..e691b08 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -17,6 +17,8 @@
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
+const char sign_off_header[] = "Signed-off-by: ";
+
 void remove_sequencer_state(void)
 {
 	struct strbuf seq_dir = STRBUF_INIT;
@@ -233,6 +235,9 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
 		die(_("%s: Unable to write new index file"), action_name(opts));
 	rollback_lock_file(&index_lock);
 
+	if (opts->signoff)
+		append_signoff(msgbuf, 0);
+
 	if (!clean) {
 		int i;
 		strbuf_addstr(msgbuf, "\nConflicts:\n");
@@ -1011,3 +1016,63 @@ int sequencer_pick_revisions(struct replay_opts *opts)
 	save_opts(opts);
 	return pick_commits(todo_list, opts);
 }
+
+static int ends_rfc2822_footer(struct strbuf *sb)
+{
+	int ch;
+	int hit = 0;
+	int i, j, k;
+	int len = sb->len;
+	int first = 1;
+	const char *buf = sb->buf;
+
+	for (i = len - 1; i > 0; i--) {
+		if (hit && buf[i] == '\n')
+			break;
+		hit = (buf[i] == '\n');
+	}
+
+	while (i < len - 1 && buf[i] == '\n')
+		i++;
+
+	for (; i < len; i = k) {
+		for (k = i; k < len && buf[k] != '\n'; k++)
+			; /* do nothing */
+		k++;
+
+		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
+			continue;
+
+		first = 0;
+
+		for (j = 0; i + j < len; j++) {
+			ch = buf[i + j];
+			if (ch == ':')
+				break;
+			if (isalnum(ch) ||
+			    (ch == '-'))
+				continue;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer)
+{
+	struct strbuf sob = STRBUF_INIT;
+	int i;
+
+	strbuf_addstr(&sob, sign_off_header);
+	strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
+				getenv("GIT_COMMITTER_EMAIL")));
+	strbuf_addch(&sob, '\n');
+	for (i = msgbuf->len - 1 - ignore_footer; i > 0 && msgbuf->buf[i - 1] != '\n'; i--)
+		; /* do nothing */
+	if (prefixcmp(msgbuf->buf + i, sob.buf)) {
+		if (!i || !ends_rfc2822_footer(msgbuf))
+			strbuf_addch(msgbuf, '\n');
+		strbuf_addbuf(msgbuf, &sob);
+	}
+	strbuf_release(&sob);
+}
diff --git a/sequencer.h b/sequencer.h
index d849420..60287b8 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -49,4 +49,8 @@ extern void remove_sequencer_state(void);
 
 int sequencer_pick_revisions(struct replay_opts *opts);
 
+extern const char sign_off_header[];
+
+void append_signoff(struct strbuf *msgbuf, int ignore_footer);
+
 #endif
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 0c81b3c..b67756f 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -30,6 +30,7 @@ test_expect_success setup '
 	test_commit initial foo a &&
 	test_commit base foo b &&
 	test_commit picked foo c &&
+	test_commit --signoff picked-signed foo d &&
 	git config advice.detachedhead false
 
 '
@@ -340,4 +341,17 @@ test_expect_success 'revert conflict, diff3 -m style' '
 	test_cmp expected actual
 '
 
+test_expect_success 'failed cherry-pick does not forget -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked &&
+	test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
+'
+
+test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick -s picked-signed &&
+	git commit -a -s &&
+	test $(git show -s |grep -c "Signed-off-by") = 1
+'
+
 test_done
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index f4e6450..b5fb527 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -410,7 +410,7 @@ test_expect_success '--continue respects -x in first commit in multi-pick' '
 	grep "cherry picked from.*$picked" msg
 '
 
-test_expect_success '--signoff is not automatically propagated to resolved conflict' '
+test_expect_failure '--signoff is automatically propagated to resolved conflict' '
 	pristine_detach initial &&
 	test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
 	echo "c" >foo &&
@@ -428,7 +428,7 @@ test_expect_success '--signoff is not automatically propagated to resolved confl
 	grep "Signed-off-by:" anotherpick_msg
 '
 
-test_expect_success '--signoff dropped for implicit commit of resolution, multi-pick case' '
+test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked anotherpick &&
 	echo c >foo &&
@@ -441,7 +441,7 @@ test_expect_success '--signoff dropped for implicit commit of resolution, multi-
 	! grep Signed-off-by: msg
 '
 
-test_expect_success 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
+test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
 	pristine_detach initial &&
 	test_must_fail git cherry-pick -s picked &&
 	echo c >foo &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 9bc57d2..bbb7b7d 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -149,6 +149,12 @@ test_commit () {
 		notick=yes
 		shift
 	fi &&
+	signoff= &&
+	if test "z$1" = "z--signoff"
+	then
+		signoff="$1"
+		shift
+	fi &&
 	file=${2:-"$1.t"} &&
 	echo "${3-$1}" > "$file" &&
 	git add "$file" &&
@@ -156,7 +162,7 @@ test_commit () {
 	then
 		test_tick
 	fi &&
-	git commit -m "$1" &&
+	git commit $signoff -m "$1" &&
 	git tag "$1"
 }
 
-- 
1.7.7

^ permalink raw reply related	[relevance 7%]

* [PATCH 2/2] completion: Use parse-options raw output for simple long options
  @ 2012-04-11 10:29  7% ` Stephen Boyd
  0 siblings, 0 replies; 171+ results
From: Stephen Boyd @ 2012-04-11 10:29 UTC (permalink / raw)
  To: git; +Cc: spearce, szeder, felipe.contreras, jrnieder

Now that parse-options supports generating lists of long options for any
parse-optified git program we can remove the hand-coded lists in the
completion script. Replace these lists with code to generate the lists
lazily when a user tab completes that specific command. Unforunately,
doing lazy evalution takes more lines than before, but the benefit is we
reduce the amount of trivial patches to update the script for new and/or
removed options. It also mildly encourages the migration of git commands
to the parse-options API.

Signed-off-by: Stephen Boyd <bebarino@gmail.com>
---

Is there some way to compute these lists with some magical function instead
of duplicating that logic over and over?

 contrib/completion/git-completion.bash |  298 +++++++++++++++++++-------------
 1 file changed, 176 insertions(+), 122 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 31f714d..69abbe5 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -917,6 +917,11 @@ __git_list_porcelain_commands ()
 	done
 }
 
+__git_list_command_options ()
+{
+	git $@ --dump-raw-long-options
+}
+
 __git_porcelain_commands=
 __git_compute_porcelain_commands ()
 {
@@ -1027,43 +1032,45 @@ _git_am ()
 	COMPREPLY=()
 }
 
+__git_apply_options=
 _git_apply ()
 {
+	test -n "$__git_apply_options" ||
+	__git_apply_options=$(__git_list_command_options apply)
+
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
 		return
 		;;
 	--*)
-		__gitcomp "
-			--stat --numstat --summary --check --index
-			--cached --index-info --reverse --reject --unidiff-zero
-			--apply --no-add --exclude=
-			--ignore-whitespace --ignore-space-change
-			--whitespace= --inaccurate-eof --verbose
-			"
+		__gitcomp "$__git_apply_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_add_options=
 _git_add ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_add_options" ||
+	__git_add_options=$(__git_list_command_options add)
 
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--interactive --refresh --patch --update --dry-run
-			--ignore-errors --intent-to-add
-			"
+		__gitcomp "$__git_add_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_archive_options=
 _git_archive ()
 {
+	test -n "$__git_archive_options" ||
+	__git_archive_options=$(__git_list_command_options archive)
+
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1074,10 +1081,7 @@ _git_archive ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--format= --list --verbose
-			--prefix= --remote= --exec=
-			"
+		__gitcomp "$__git_archive_options"
 		return
 		;;
 	esac
@@ -1109,6 +1113,7 @@ _git_bisect ()
 	esac
 }
 
+__git_branch_options=
 _git_branch ()
 {
 	local i c=1 only_local_ref="n" has_r="n"
@@ -1122,13 +1127,12 @@ _git_branch ()
 		((c++))
 	done
 
+	test -n "$__git_branch_options" ||
+	__git_branch_options=$(__git_list_command_options branch)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--color --no-color --verbose --abbrev= --no-abbrev
-			--track --no-track --contains --merged --no-merged
-			--set-upstream --edit-description --list
-			"
+		__gitcomp "$__git_branch_options"
 		;;
 	*)
 		if [ $only_local_ref = "y" -a $has_r = "n" ]; then
@@ -1160,19 +1164,19 @@ _git_bundle ()
 	esac
 }
 
+__git_checkout_options=
 _git_checkout ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_checkout_options" ||
+	__git_checkout_options=$(__git_list_command_options checkout)
 
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
 		;;
 	--*)
-		__gitcomp "
-			--quiet --ours --theirs --track --no-track --merge
-			--conflict= --orphan --patch
-			"
+		__gitcomp "$__git_checkout_options"
 		;;
 	*)
 		# check if --track, --no-track, or --no-guess was specified
@@ -1191,11 +1195,15 @@ _git_cherry ()
 	__gitcomp "$(__git_refs)"
 }
 
+__git_cherry_pick_options=
 _git_cherry_pick ()
 {
+	test -n "$__git_cherry_pick_options" ||
+	__git_cherry_pick_options=$(__git_list_command_options cherry-pick)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --no-commit"
+		__gitcomp "$__git_cherry_pick_options"
 		;;
 	*)
 		__gitcomp_nl "$(__git_refs)"
@@ -1203,46 +1211,44 @@ _git_cherry_pick ()
 	esac
 }
 
+__git_clean_options=
 _git_clean ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_clean_options" ||
+	__git_clean_options=$(__git_list_command_options clean)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--dry-run --quiet"
+		__gitcomp "$__git_clean_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_clone_options=
 _git_clone ()
 {
+	test -n "$__git_clone_options" ||
+	__git_clone_options=$(__git_list_command_options clone)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--local
-			--no-hardlinks
-			--shared
-			--reference
-			--quiet
-			--no-checkout
-			--bare
-			--mirror
-			--origin
-			--upload-pack
-			--template=
-			--depth
-			"
+		__gitcomp "$__git_clone_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_commit_options=
 _git_commit ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_commit_options" ||
+	__git_commit_options=$(__git_list_command_options commit)
 
 	case "$cur" in
 	--cleanup=*)
@@ -1260,27 +1266,21 @@ _git_commit ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--all --author= --signoff --verify --no-verify
-			--edit --amend --include --only --interactive
-			--dry-run --reuse-message= --reedit-message=
-			--reset-author --file= --message= --template=
-			--cleanup= --untracked-files --untracked-files=
-			--verbose --quiet --fixup= --squash=
-			"
+		__gitcomp "$__git_commit_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_describe_options=
 _git_describe ()
 {
+	test -n "$__git_describe_options" ||
+	__git_describe_options=$(__git_list_command_options describe)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--all --tags --contains --abbrev= --candidates=
-			--exact-match --debug --long --match --always
-			"
+		__gitcomp "$__git_describe_options"
 		return
 	esac
 	__gitcomp_nl "$(__git_refs)"
@@ -1343,13 +1343,16 @@ _git_difftool ()
 	__git_complete_file
 }
 
-__git_fetch_options="
-	--quiet --verbose --append --upload-pack --force --keep --depth=
-	--tags --no-tags --all --prune --dry-run
-"
+__git_fetch_options=
+__git_compute_fetch_options ()
+{
+	test -n "$__git_fetch_options" ||
+	__git_fetch_options=$(__git_list_command_options fetch)
+}
 
 _git_fetch ()
 {
+	__git_compute_fetch_options
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1359,8 +1362,12 @@ _git_fetch ()
 	__git_complete_remote_or_refspec
 }
 
+__git_format_patch_options=
 _git_format_patch ()
 {
+	test -n "$__git_format_patch_options" ||
+	__git_format_patch_options=$(__git_list_command_options format-patch)
+
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1369,46 +1376,37 @@ _git_format_patch ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--stdout --attach --no-attach --thread --thread=
-			--output-directory
-			--numbered --start-number
-			--numbered-files
-			--keep-subject
-			--signoff --signature --no-signature
-			--in-reply-to= --cc=
-			--full-index --binary
-			--not --all
-			--cover-letter
-			--no-prefix --src-prefix= --dst-prefix=
-			--inline --suffix= --ignore-if-in-upstream
-			--subject-prefix=
-			"
+		__gitcomp "$__git_format_patch_options"
 		return
 		;;
 	esac
 	__git_complete_revlist
 }
 
+__git_fsck_options=
 _git_fsck ()
 {
+	test -n "$__git_fsck_options" ||
+	__git_fsck_options=$(__git_list_command_options fsck)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--tags --root --unreachable --cache --no-reflogs --full
-			--strict --verbose --lost-found
-			"
+		__gitcomp "$__git_fsck_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_gc_options=
 _git_gc ()
 {
+	test -n "$__git_gc_options" ||
+	__git_gc_options=$(__git_list_command_options gc)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--prune --aggressive"
+		__gitcomp "$__git_gc_options"
 		return
 		;;
 	esac
@@ -1424,24 +1422,17 @@ __git_match_ctag() {
 	awk "/^${1////\\/}/ { print \$1 }" "$2"
 }
 
+__git_grep_options=
 _git_grep ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_grep_options" ||
+	__git_grep_options=$(__git_list_command_options grep)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--cached
-			--text --ignore-case --word-regexp --invert-match
-			--full-name --line-number
-			--extended-regexp --basic-regexp --fixed-strings
-			--perl-regexp
-			--files-with-matches --name-only
-			--files-without-match
-			--max-depth
-			--count
-			--and --or --not --all-match
-			"
+		__gitcomp "$__git_grep_options"
 		return
 		;;
 	esac
@@ -1458,11 +1449,15 @@ _git_grep ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_help_options=
 _git_help ()
 {
+	test -n "$__git_help_options" ||
+	__git_help_options=$(__git_list_command_options help)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--all --info --man --web"
+		__gitcomp "$__git_help_options"
 		return
 		;;
 	esac
@@ -1475,8 +1470,12 @@ _git_help ()
 		"
 }
 
+__git_init_options=
 _git_init ()
 {
+	test -n "$__git_init_options" ||
+	__git_init_options=$(__git_list_command_options init)
+
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1485,26 +1484,24 @@ _git_init ()
 		return
 		;;
 	--*)
-		__gitcomp "--quiet --bare --template= --shared --shared="
+		__gitcomp "$__git_init_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_ls_files_options=
 _git_ls_files ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_ls_files_options" ||
+	__git_ls_files_options=$(__git_list_command_options ls-files)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --deleted --modified --others --ignored
-			--stage --directory --no-empty-directory --unmerged
-			--killed --exclude= --exclude-from=
-			--exclude-per-directory= --exclude-standard
-			--error-unmatch --with-tree= --full-name
-			--abbrev --ignored --exclude-per-directory
-			"
+		__gitcomp "$__git_ls_files_options"
 		return
 		;;
 	esac
@@ -1516,8 +1513,18 @@ _git_ls_remote ()
 	__gitcomp_nl "$(__git_remotes)"
 }
 
+__git_ls_tree_options=
 _git_ls_tree ()
 {
+	test -n "$__git_ls_tree_options" ||
+	__git_ls_tree_options=$(__git_list_command_options ls-tree)
+
+	case "$cur" in
+	--*)
+		__gitcomp "$__git_ls_tree_options"
+		return
+		;;
+	esac
 	__git_complete_file
 }
 
@@ -1595,14 +1602,17 @@ _git_log ()
 	__git_complete_revlist
 }
 
-__git_merge_options="
-	--no-commit --no-stat --log --no-log --squash --strategy
-	--commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit
-"
+__git_merge_options=
+__git_compute_merge_options ()
+{
+	test -n "$__git_merge_options" ||
+	__git_merge_options=$(__git_list_command_options merge)
+}
 
 _git_merge ()
 {
 	__git_complete_strategy && return
+	__git_compute_merge_options
 
 	case "$cur" in
 	--*)
@@ -1632,30 +1642,50 @@ _git_merge_base ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_mv_options=
 _git_mv ()
 {
+	test -n "$__git_mv_options" ||
+	__git_mv_options=$(__git_list_command_options mv)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--dry-run"
+		__gitcomp "$__git_mv_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_name_rev_options=
 _git_name_rev ()
 {
-	__gitcomp "--tags --all --stdin"
+	test -n "$__git_name_rev_options" ||
+	__git_name_rev_options=$(__git_list_command_options name-rev)
+
+	case "$cur" in
+	--*)
+		__gitcomp "$__git_name_rev_options"
+		return
+		;;
+	esac
 }
 
+__git_notes_options=
+__git_notes_add_options=
+__git_notes_copy_options=
+__git_notes_prune_options=
 _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 
+	test -n "$__git_notes_options" ||
+	__git_notes_options=$(__git_list_command_options notes)
+
 	case "$subcommand,$cur" in
 	,--*)
-		__gitcomp '--ref'
+		__gitcomp "$__git_notes_options"
 		;;
 	,*)
 		case "${words[cword-1]}" in
@@ -1672,14 +1702,19 @@ _git_notes ()
 		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
 		;;
 	add,--*|append,--*)
-		__gitcomp '--file= --message= --reedit-message=
-				--reuse-message='
+		test -n "$__git_notes_add_options" ||
+		__git_notes_add_options=$(__git_list_command_options notes add)
+		__gitcomp "$__git_notes_add_options"
 		;;
 	copy,--*)
-		__gitcomp '--stdin'
+		test -n "$__git_notes_copy_options" ||
+		__git_notes_copy_options=$(__git_list_command_options notes copy)
+		__gitcomp "$__git_notes_copy_options"
 		;;
 	prune,--*)
-		__gitcomp '--dry-run --verbose'
+		test -n "$__git_notes_prune_options" ||
+		__git_notes_prune_options=$(__git_list_command_options notes prune)
+		__gitcomp "$__git_notes_prune_options"
 		;;
 	prune,*)
 		;;
@@ -1699,6 +1734,9 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
+	__git_compute_merge_options
+	__git_compute_fetch_options
+
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1712,8 +1750,12 @@ _git_pull ()
 	__git_complete_remote_or_refspec
 }
 
+__git_push_options=
 _git_push ()
 {
+	test -n "$__git_push_options" ||
+	__git_push_options=$(__git_list_command_options push)
+
 	case "$prev" in
 	--repo)
 		__gitcomp_nl "$(__git_remotes)"
@@ -1725,10 +1767,7 @@ _git_push ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--all --mirror --tags --dry-run --force --verbose
-			--receive-pack= --repo= --set-upstream
-		"
+		__gitcomp "$__git_push_options"
 		return
 		;;
 	esac
@@ -2313,37 +2352,49 @@ _git_replace ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_reset_options=
 _git_reset ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_reset_options" ||
+	__git_reset_options=$(__git_list_command_options reset)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft --patch"
+		__gitcomp "$__git_reset_options"
 		return
 		;;
 	esac
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_revert_options=
 _git_revert ()
 {
+	test -n "$__git_revert_options" ||
+	__git_revert_options=$(__git_list_command_options revert)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		__gitcomp "$__git_revert_options"
 		return
 		;;
 	esac
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_rm_options=
 _git_rm ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_rm_options" ||
+	__git_rm_options=$(__git_list_command_options rm)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+		__gitcomp "$__git_rm_options"
 		return
 		;;
 	esac
@@ -2367,10 +2418,14 @@ _git_shortlog ()
 	__git_complete_revlist
 }
 
+__git_show_options=
 _git_show ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_show_options" ||
+	__git_show_options=$(__git_list_command_options show)
+
 	case "$cur" in
 	--pretty=*|--format=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -2378,7 +2433,7 @@ _git_show ()
 		return
 		;;
 	--*)
-		__gitcomp "--pretty= --format= --abbrev-commit --oneline
+		__gitcomp "$__git_show_options
 			$__git_diff_common_options
 			"
 		return
@@ -2387,16 +2442,15 @@ _git_show ()
 	__git_complete_file
 }
 
+__git_show_branch_options=
 _git_show_branch ()
 {
+	test -n "$__git_show_branch_options" ||
+	__git_show_branch_options=$(__git_list_command_options show-branch)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--all --remotes --topo-order --current --more=
-			--list --independent --merge-base --no-name
-			--color --no-color
-			--sha1-name --sparse --topics --reflog
-			"
+		__gitcomp "$__git_show_branch_options"
 		return
 		;;
 	esac
-- 
1.7.10.128.g7945c.dirty

^ permalink raw reply related	[relevance 7%]

* Re: [PATCH 00/18] GSoC update: Sequencer for inclusion v3
  2011-07-28 16:32  4%     ` Ramkumar Ramachandra
@ 2011-07-28 16:39  0%       ` Jonathan Nieder
  0 siblings, 0 replies; 171+ results
From: Jonathan Nieder @ 2011-07-28 16:39 UTC (permalink / raw)
  To: Ramkumar Ramachandra
  Cc: Junio C Hamano, Git List, Christian Couder, Daniel Barkalow,
	Jeff King

Ramkumar Ramachandra wrote:

> Um, one more thing.  I've also decided to let Jonathan's commit
> signoff-factoring patch [1] wait until the next series.
>
> [1]: https://github.com/artagnon/git/commit/0494a

Sure, I don't think it belongs in the series at all fwiw --- it can
migrate to master independently.  It was mostly a way to deter a
non-sequitor in the commit message. :)

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 00/18] GSoC update: Sequencer for inclusion v3
  @ 2011-07-28 16:32  4%     ` Ramkumar Ramachandra
  2011-07-28 16:39  0%       ` Jonathan Nieder
  0 siblings, 1 reply; 171+ results
From: Ramkumar Ramachandra @ 2011-07-28 16:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Jonathan Nieder, Christian Couder, Daniel Barkalow,
	Jeff King

Hi again,

Ramkumar Ramachandra writes:
> Do you think the series is alright otherwise?  I'll post another
> iteration of the sequencer momentarily.

Um, one more thing.  I've also decided to let Jonathan's commit
signoff-factoring patch [1] wait until the next series.

[1]: https://github.com/artagnon/git/commit/0494a

Thanks.

-- Ram

^ permalink raw reply	[relevance 4%]

* [PATCH 2/3] bash: remove unnecessary _get_comp_words_by_ref() invocations
  @ 2011-04-28 16:01  3%   ` SZEDER Gábor
  0 siblings, 0 replies; 171+ results
From: SZEDER Gábor @ 2011-04-28 16:01 UTC (permalink / raw)
  To: Jonathan Nieder, Junio C Hamano
  Cc: Felipe Contreras, git, Stefan Haller, Mark Lodato,
	SZEDER Gábor

In v1.7.4-rc0~11^2~2 (bash: get --pretty=m<tab> completion to work
with bash v4, 2010-12-02) we started to use _get_comp_words_by_ref()
to access completion-related variables.  That was large change, and to
make it easily reviewable, we invoked _get_comp_words_by_ref() in each
completion function and systematically replaced every occurance of
bash's completion-related variables ($COMP_WORDS and $COMP_CWORD) with
variables set by _get_comp_words_by_ref().

This has the downside that _get_comp_words_by_ref() is invoked several
times during a single completion.  The worst offender is perhaps 'git
log mas<TAB>': during the completion of 'master'
_get_comp_words_by_ref() is invoked no less than six times.

However, the variables $prev, $cword, and $words provided by
_get_comp_words_by_ref() are not modified in any of the completion
functions, and the previous commit ensures that the $cur variable is
not modified as well.  This makes it possible to invoke
_get_comp_words_by_ref() to get those variables only once in our
toplevel completion functions _git() and _gitk(), and all other
completion functions will inherit them.

Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-completion.bash |  116 +++-----------------------------
 1 files changed, 11 insertions(+), 105 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a594b40..862b840 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -489,8 +489,6 @@ fi
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	local cur_="$cur"
 
 	if [ $# -gt 2 ]; then
@@ -553,8 +551,7 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
-	local cur format refs
-	_get_comp_words_by_ref -n =: cur
+	local format refs
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -668,9 +665,7 @@ __git_compute_merge_strategies ()
 
 __git_complete_revlist_file ()
 {
-	local pfx ls ref cur
-	_get_comp_words_by_ref -n =: cur
-	local cur_="$cur"
+	local pfx ls ref cur_="$cur"
 	case "$cur_" in
 	*..?*:*)
 		return
@@ -742,8 +737,6 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
 	local cur_="$cur" cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
 	while [ $c -lt $cword ]; do
@@ -815,8 +808,6 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
-	local cur prev
-	_get_comp_words_by_ref -n =: cur prev
 	__git_compute_merge_strategies
 	case "$prev" in
 	-s|--strategy)
@@ -994,8 +985,7 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1 words cword
-	_get_comp_words_by_ref -n =: words cword
+	local word subcommand c=1
 	while [ $c -lt $cword ]; do
 		word="${words[c]}"
 		for subcommand in $1; do
@@ -1010,8 +1000,7 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1 words cword
-	_get_comp_words_by_ref -n =: words cword
+	local c=1
 	while [ $c -lt $cword ]; do
 		if [ "--" = "${words[c]}" ]; then
 			return 0
@@ -1025,8 +1014,7 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur dir="$(__gitdir)"
-	_get_comp_words_by_ref -n =: cur
+	local dir="$(__gitdir)"
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -1050,8 +1038,6 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1074,8 +1060,6 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1089,8 +1073,6 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1138,9 +1120,8 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	local i c=1 only_local_ref="n" has_r="n"
 
-	_get_comp_words_by_ref -n =: cur words cword
 	while [ $c -lt $cword ]; do
 		i="${words[c]}"
 		case "$i" in
@@ -1170,8 +1151,6 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local words cword
-	_get_comp_words_by_ref -n =: words cword
 	local cmd="${words[2]}"
 	case "$cword" in
 	2)
@@ -1194,8 +1173,6 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1225,8 +1202,6 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1241,8 +1216,6 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1254,8 +1227,6 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1282,8 +1253,6 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1318,8 +1287,6 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1351,8 +1318,6 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1373,8 +1338,6 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1399,8 +1362,6 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1412,8 +1373,6 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1445,8 +1404,6 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1461,8 +1418,6 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1481,8 +1436,6 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1505,8 +1458,6 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1524,8 +1475,6 @@ _git_help ()
 
 _git_init ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1545,8 +1494,6 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1607,8 +1554,6 @@ _git_log ()
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -1662,8 +1607,6 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1674,8 +1617,6 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1696,8 +1637,6 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1716,8 +1655,6 @@ _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
 
 	case "$subcommand,$cur" in
 	,--*)
@@ -1767,8 +1704,6 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1784,8 +1719,6 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur prev
-	_get_comp_words_by_ref -n =: cur prev
 	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
@@ -1810,8 +1743,6 @@ _git_push ()
 _git_rebase ()
 {
 	local dir="$(__gitdir)"
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1853,8 +1784,6 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1896,8 +1825,6 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local words cword
-	_get_comp_words_by_ref -n =: words cword
 	local prevword word config_file= c=$cword
 	while [ $c -gt 1 ]; do
 		word="${words[c]}"
@@ -1928,8 +1855,6 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur prev
-	_get_comp_words_by_ref -n =: cur prev
 	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
@@ -2389,8 +2314,6 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2402,8 +2325,6 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2417,8 +2338,6 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2432,8 +2351,6 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2451,8 +2368,6 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -2476,8 +2391,6 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2494,8 +2407,6 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur
-	_get_comp_words_by_ref -n =: cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
@@ -2540,8 +2451,6 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur
-		_get_comp_words_by_ref -n =: cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2585,8 +2494,6 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur
-		_get_comp_words_by_ref -n =: cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2658,8 +2565,6 @@ _git_svn ()
 _git_tag ()
 {
 	local i c=1 f=0
-	local words cword prev
-	_get_comp_words_by_ref -n =: words cword prev
 	while [ $c -lt $cword ]; do
 		i="${words[c]}"
 		case "$i" in
@@ -2705,8 +2610,8 @@ _git ()
 		setopt KSH_TYPESET
 	fi
 
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
+	local cur words cword prev
+	_get_comp_words_by_ref -n =: cur words cword prev
 	while [ $c -lt $cword ]; do
 		i="${words[c]}"
 		case "$i" in
@@ -2756,15 +2661,16 @@ _gitk ()
 		setopt KSH_TYPESET
 	fi
 
+	local cur words cword prev
+	_get_comp_words_by_ref -n =: cur words cword prev
+
 	__git_has_doubledash && return
 
-	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
-	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
-- 
1.7.5.86.g799a6

^ permalink raw reply related	[relevance 3%]

* [PATCH 1/3] bash: get --pretty=m<tab> completion to work with bash v4
  @ 2010-12-15  6:26  2%               ` Jonathan Nieder
  0 siblings, 0 replies; 171+ results
From: Jonathan Nieder @ 2010-12-15  6:26 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: SZEDER Gábor, Peter van der Does, Shawn O. Pearce, git,
	Marc Branchaud, Brian Gernhardt, Kevin Ballard, Mathias Lafeldt,
	Stephen Boyd

From: Peter van der Does <peter@avirtualhome.com>

Bash's programmable completion provides the COMP_WORDS array variable,
which holds the individual words in the current command line.  In bash
versions prior to v4 "words are split on shell metacharacters as the
shell parser would separate them" (quote from bash v3.2.48's man
page).  This behavior has changed with bash v4, and the command line
"is split into words as readline would split it, using COMP_WORDBREAKS
as" "the set of characters that the readline library treats as word
separators" (quote from bash v4's man page).

Since COMP_WORDBREAKS contains the characters : and = by default, this
behavior change in bash affects git's completion script.  For example,
before bash 4, running

	$ git log --pretty=m <tab><tab>

would give a list of pretty-printing formats starting with 'm' but now
it completes on branch names.

It would be possible to work around this by removing '=' and ':' from
COMP_WORDBREAKS, but as noticed in v1.5.6.4~9^2 (bash completion:
Resolve git show ref:path<tab> losing ref: portion, 2008-07-15), that
would break *other* completion scripts.  The bash-completion library
includes a better workaround: the _get_comp_words_by_ref function
re-assembles a copy of COMP_WORDS, excluding a collection of word
separators of the caller's choice.  Use it.

As a bonus, this improves behavior when tab is pressed with the cursor
in the middle of a word if the bash-completion lib is loaded.

To avoid breaking setups with the bash-completion library not already
loaded, if the _get_comp_words_by_ref function is not defined then use
a shim that just reads COMP_WORDS instead (no change from the current
behavior in that case).

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Explained-by: SZEDER Gábor <szeder@ira.uka.de>
---
 contrib/completion/git-completion.bash |  236 +++++++++++++++++++++----------
 1 files changed, 160 insertions(+), 76 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 82e6609..68b68d0 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -321,11 +321,39 @@ __gitcomp_1 ()
 	done
 }
 
+if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
+_get_comp_words_by_ref ()
+{
+	while [ $# -gt 0 ]; do
+		case "$1" in
+		cur)
+			cur=${COMP_WORDS[COMP_CWORD]}
+			;;
+		prev)
+			prev=${COMP_WORDS[COMP_CWORD-1]}
+			;;
+		words)
+			words=("${COMP_WORDS[@]}")
+			;;
+		cword)
+			cword=$COMP_CWORD
+			;;
+		-n)
+			# assume COMP_WORDBREAKS is already set sanely
+			shift
+			;;
+		esac
+		shift
+	done
+}
+fi
+
 # __gitcomp accepts 1, 2, 3, or 4 arguments
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -384,7 +412,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -482,7 +511,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -530,7 +560,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -550,11 +581,12 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n =: cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -622,13 +654,14 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "$prev" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -788,10 +821,10 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
-
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	local word subcommand c=1 words cword
+	_get_comp_words_by_ref -n =: words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -804,9 +837,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1 words cword
+	_get_comp_words_by_ref -n =: words cword
+	while [ $c -lt $cword ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -818,7 +852,8 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -842,7 +877,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -865,7 +901,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -879,7 +916,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -923,10 +961,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n =: cur words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -934,7 +973,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -954,8 +993,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -976,7 +1017,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1000,7 +1042,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1015,7 +1058,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1027,7 +1071,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1054,7 +1099,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1089,7 +1135,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1121,7 +1168,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1142,7 +1190,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1167,7 +1216,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1179,7 +1229,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1211,7 +1262,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1226,7 +1278,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1245,7 +1298,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1268,7 +1322,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1286,7 +1341,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1306,7 +1362,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1360,12 +1417,13 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -1419,7 +1477,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1430,7 +1489,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1451,7 +1511,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1469,12 +1530,14 @@ _git_name_rev ()
 _git_notes ()
 {
 	local subcommands="edit show"
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
 		__gitcomp "$subcommands"
 		return
 	fi
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${words[cword-1]}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -1488,7 +1551,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1504,8 +1568,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1528,7 +1593,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local dir="$(__gitdir)"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1558,7 +1625,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1600,9 +1668,11 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
+	local prevword word config_file= c=$cword
 	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+		word="${words[c]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1630,9 +1700,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1642,13 +1712,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2039,7 +2109,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2051,7 +2122,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2065,7 +2137,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2079,7 +2152,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2097,7 +2171,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2121,7 +2196,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2138,7 +2214,8 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
@@ -2183,7 +2260,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref -n =: cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2227,7 +2305,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref -n =: cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2299,8 +2378,10 @@ _git_svn ()
 _git_tag ()
 {
 	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local words cword prev
+	_get_comp_words_by_ref -n =: words cword prev
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2313,7 +2394,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "$prev" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2339,8 +2420,10 @@ _git ()
 {
 	local i c=1 command __git_dir
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local cur words cword
+	_get_comp_words_by_ref -n =: cur words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2352,7 +2435,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "$cur" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2385,12 +2468,13 @@ _gitk ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
-- 
1.7.3.3.573.g0bcfc

^ permalink raw reply related	[relevance 2%]

* Re: [PATCH v4 0/2] Make git-completion Bash 4 compatible
    2010-12-01 20:49  2% ` [PATCH v4 2/2] Use the new functions to get the current cword Peter van der Does
@ 2010-12-02  9:16  2% ` Jonathan Nieder
    1 sibling, 1 reply; 171+ results
From: Jonathan Nieder @ 2010-12-02  9:16 UTC (permalink / raw)
  To: Peter van der Does
  Cc: Shawn O. Pearce, git, SZEDER Gábor, Marc Branchaud,
	Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

Hi again,

Peter van der Does wrote:

> Make git-completion Bash 4 compatible.

Thanks again for this work and sorry for all the fuss.

> Peter van der Does (2):
>   Introduce functions from bash-completion project.

This patch introduces a minor regression in that it breaks the
(already somewhat incomplete) zsh support.  Should be fixable by
falling back to using COMP_WORDS on zsh.

>   Use the new functions to get the current cword.

This one introduces some subtle differences between commands and imho
does more than it set out to do, by differentiating word splitting
behavior between commands.  bash 3 was not splitting COMP_WORDS at
equal signs or colons, ever.  Maybe we can start with that and then
make refinements on top later.

While trying that out, I had an idea.  The patch depends on
understanding the bash-completion library function introduced by patch
1, but I think we can avoid that by rearranging the patch series like
this:

 1. If _get_comp_words_by_ref is already defined, use it to fetch
    completion words.  Otherwise, just use COMP_WORDS (using a stub
    _get_comp_words_by_ref), maintaining the current behavior.
    [shown below]

 2. Import the definition of _get_comp_words_by_ref from the
    bash-completion lib and use it if ZSH_VERSION is unset.

 3. Further refinements, if needed.

What do you think?

-- 8< --
From: Peter van der Does <peter@avirtualhome.com>
Subject: bash: work around bash 4.0 change in COMP_WORDS semantics

Before bash 4, running

	$ git log --pretty=m <tab><tab>

would give a list of pretty formats starting with 'm', but now it
completes on ordinary files instead.  It seems that as part of a
rework of completion word splitting, bash 4.0 changed the semantics of
the COMP_WORDS array: previously, --pretty=m was treated as one word,
but now it breaks on '=' if COMP_WORDBREAKS contains an equal sign.

It would be possible to work around that by removing '=' and ':' from
COMP_WORDBREAKS, but as noticed in v1.5.6.4~9^2 (bash completion:
Resolve git show ref:path<tab> losing ref: portion, 2008-07-15), doing
so is likely to break *other* completion scripts.  Luckily, the
bash-completion library includes a better workaround --- a
_get_comp_words_by_ref function to retrieve an array somewhat like
COMP_WORDS but:

 * excluding some word break characters of your choice
 * returning correct results even when the cursor is in the middle of
   a word.

Use it.  To avoid breaking setups where the bash-completion library is
not already loaded, if that function is not defined then a shim
replacement that just reads COMP_WORDS will be used instead.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 contrib/completion/git-completion.bash |  236 +++++++++++++++++++++----------
 1 files changed, 160 insertions(+), 76 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index feab651..0b0eb45 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -327,11 +327,39 @@ __gitcomp_1 ()
 	done
 }
 
+if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
+_get_comp_words_by_ref ()
+{
+	while [ $# -gt 0 ]; do
+		case "$1" in
+		cur)
+			cur=${COMP_WORDS[COMP_CWORD]}
+			;;
+		prev)
+			prev=${COMP_WORDS[COMP_CWORD-1]}
+			;;
+		words)
+			words=("${COMP_WORDS[@]}")
+			;;
+		cword)
+			cword=$COMP_CWORD
+			;;
+		-n)
+			# assume COMP_WORDBREAKS is already set sanely
+			shift
+			;;
+		esac
+		shift
+	done
+}
+fi
+
 # __gitcomp accepts 1, 2, 3, or 4 arguments
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -390,7 +418,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -488,7 +517,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -536,7 +566,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -556,11 +587,12 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n =: cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -628,13 +660,14 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "$prev" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -794,10 +827,10 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
-
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	local word subcommand c=1 words cword
+	_get_comp_words_by_ref -n =: words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -810,9 +843,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1 words cword
+	_get_comp_words_by_ref -n =: words cword
+	while [ $c -lt $cword ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -824,7 +858,8 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -848,7 +883,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -871,7 +907,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -885,7 +922,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -929,10 +967,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n =: cur words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -940,7 +979,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -960,8 +999,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -982,7 +1023,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1006,7 +1048,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1021,7 +1064,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1033,7 +1077,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1060,7 +1105,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1095,7 +1141,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1127,7 +1174,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1148,7 +1196,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1173,7 +1222,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1185,7 +1235,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1217,7 +1268,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1232,7 +1284,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1251,7 +1304,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1274,7 +1328,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1292,7 +1347,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1312,7 +1368,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1366,12 +1423,13 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -1425,7 +1483,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1436,7 +1495,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1457,7 +1517,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1475,12 +1536,14 @@ _git_name_rev ()
 _git_notes ()
 {
 	local subcommands="edit show"
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
 		__gitcomp "$subcommands"
 		return
 	fi
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${words[cword-1]}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -1494,7 +1557,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1510,8 +1574,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1534,7 +1599,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local dir="$(__gitdir)"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1564,7 +1631,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1606,9 +1674,11 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
+	local words cword
+	_get_comp_words_by_ref -n =: words cword
+	local prevword word config_file= c=$cword
 	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+		word="${words[c]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1636,9 +1706,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref -n =: cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1648,13 +1718,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2045,7 +2115,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2057,7 +2128,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2071,7 +2143,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2085,7 +2158,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2103,7 +2177,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2127,7 +2202,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2144,7 +2220,8 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n =: cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
@@ -2189,7 +2266,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref -n =: cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2233,7 +2311,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref -n =: cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2305,8 +2384,10 @@ _git_svn ()
 _git_tag ()
 {
 	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local words cword prev
+	_get_comp_words_by_ref -n =: words cword prev
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2319,7 +2400,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "$prev" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2350,8 +2431,10 @@ _git ()
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local cur words cword
+	_get_comp_words_by_ref -n =: cur words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2363,7 +2446,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "$cur" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2401,12 +2484,13 @@ _gitk ()
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref -n =: cur
 	case "$cur" in
 	--*)
 		__gitcomp "
-- 
1.7.2.3

^ permalink raw reply related	[relevance 2%]

* [PATCH v5 2/2] Use the new functions to get the current cword.
  @ 2010-12-02  0:40  2% ` Peter van der Does
  0 siblings, 0 replies; 171+ results
From: Peter van der Does @ 2010-12-02  0:40 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Peter van der Does, git, Jonathan Nieder

Change the completion functions to use the newly introduced functions to
get the current and/or previous cword and to reassemble the COMP_CWORDS,
making sure the options are correctly split.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  223 ++++++++++++++++++++------------
 1 files changed, 140 insertions(+), 83 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0036e8b..f915e1f 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -554,7 +554,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -615,7 +616,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -729,7 +731,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -777,7 +780,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -797,11 +801,13 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n ":" cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -869,13 +875,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -1048,10 +1056,11 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
+	local word subcommand c=1 words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -1064,9 +1073,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1, words cword
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cwords ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -1078,7 +1088,9 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -1102,7 +1114,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1125,7 +1138,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1139,7 +1153,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1187,10 +1202,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	_get_comp_words_by_ref cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -1198,7 +1214,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -1218,8 +1234,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -1240,7 +1258,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1270,7 +1289,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1285,7 +1305,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1297,7 +1318,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1324,7 +1346,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1359,7 +1382,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1391,7 +1415,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1412,7 +1437,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1437,7 +1463,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1449,7 +1476,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1481,7 +1509,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1496,7 +1525,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1515,7 +1545,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1538,7 +1569,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1556,7 +1588,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1576,7 +1609,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1630,7 +1664,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1689,7 +1724,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1700,7 +1736,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1721,7 +1758,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1740,7 +1778,8 @@ _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 
 	case "$subcommand,$cur" in
 	,--*)
@@ -1775,7 +1814,7 @@ _git_notes ()
 	prune,*)
 		;;
 	*)
-		case "${COMP_WORDS[COMP_CWORD-1]}" in
+		case "${prev}" in
 		-m|-F)
 			;;
 		*)
@@ -1790,7 +1829,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1806,8 +1846,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1830,7 +1871,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1860,7 +1903,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1902,9 +1946,10 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
-	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+	local prevword word config_file= words cword
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $cword -gt 1 ]; do
+		word="${words[cword]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1916,7 +1961,7 @@ __git_config_get_set_variables ()
 			;;
 		esac
 		prevword=$word
-		c=$((--c))
+		cword=$((--cword))
 	done
 
 	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
@@ -1932,9 +1977,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1944,13 +1989,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2341,7 +2386,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2353,7 +2399,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2367,7 +2414,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2381,7 +2429,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2399,7 +2448,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -2423,7 +2473,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2440,10 +2491,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2485,7 +2537,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2529,7 +2582,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2600,9 +2654,10 @@ _git_svn ()
 
 _git_tag ()
 {
-	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local i c=1 f=0 words cword prev
+	_get_comp_words_by_ref prev words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2615,7 +2670,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2639,15 +2694,16 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir words cword
 
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2659,7 +2715,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${words[cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2690,19 +2746,20 @@ _git ()
 
 _gitk ()
 {
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2730,7 +2787,7 @@ complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
 	|| complete -o default -o nospace -F _git git.exe
 fi
 
-if [[ -n ${ZSH_VERSION-} ]]; then
+if [[ -n $ZSH_VERSION ]]; then
 	shopt () {
 		local option
 		if [ $# -ne 2 ]; then
-- 
1.7.3.2

^ permalink raw reply related	[relevance 2%]

* [PATCH v4 2/2] Use the new functions to get the current cword.
  @ 2010-12-01 20:49  2% ` Peter van der Does
  2010-12-02  9:16  2% ` [PATCH v4 0/2] Make git-completion Bash 4 compatible Jonathan Nieder
  1 sibling, 0 replies; 171+ results
From: Peter van der Does @ 2010-12-01 20:49 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Peter van der Does, git, Jonathan Nieder

Change the completion functions to use the newly introduced functions to
get the current and/or previous cword and to reassemble the COMP_CWORDS,
making sure the options are correctly split.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  223 ++++++++++++++++++++------------
 1 files changed, 140 insertions(+), 83 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0036e8b..f915e1f 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -554,7 +554,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -615,7 +616,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")" track="${2-}"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -729,7 +731,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -777,7 +780,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -797,11 +801,13 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n ":" cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -869,13 +875,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -1048,10 +1056,11 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
+	local word subcommand c=1 words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -1064,9 +1073,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1, words cword
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cwords ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -1078,7 +1088,9 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -1102,7 +1114,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1125,7 +1138,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1139,7 +1153,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1187,10 +1202,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	_get_comp_words_by_ref cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -1198,7 +1214,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -1218,8 +1234,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -1240,7 +1258,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1270,7 +1289,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1285,7 +1305,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1297,7 +1318,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1324,7 +1346,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1359,7 +1382,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1391,7 +1415,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1412,7 +1437,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1437,7 +1463,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1449,7 +1476,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1481,7 +1509,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1496,7 +1525,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1515,7 +1545,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1538,7 +1569,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1556,7 +1588,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1576,7 +1609,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1630,7 +1664,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1689,7 +1724,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1700,7 +1736,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1721,7 +1758,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1740,7 +1778,8 @@ _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 
 	case "$subcommand,$cur" in
 	,--*)
@@ -1775,7 +1814,7 @@ _git_notes ()
 	prune,*)
 		;;
 	*)
-		case "${COMP_WORDS[COMP_CWORD-1]}" in
+		case "${prev}" in
 		-m|-F)
 			;;
 		*)
@@ -1790,7 +1829,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1806,8 +1846,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1830,7 +1871,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1860,7 +1903,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1902,9 +1946,10 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
-	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+	local prevword word config_file= words cword
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $cword -gt 1 ]; do
+		word="${words[cword]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1916,7 +1961,7 @@ __git_config_get_set_variables ()
 			;;
 		esac
 		prevword=$word
-		c=$((--c))
+		cword=$((--cword))
 	done
 
 	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
@@ -1932,9 +1977,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1944,13 +1989,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2341,7 +2386,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2353,7 +2399,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2367,7 +2414,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2381,7 +2429,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2399,7 +2448,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -2423,7 +2473,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2440,10 +2491,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2485,7 +2537,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2529,7 +2582,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2600,9 +2654,10 @@ _git_svn ()
 
 _git_tag ()
 {
-	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local i c=1 f=0 words cword prev
+	_get_comp_words_by_ref prev words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2615,7 +2670,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2639,15 +2694,16 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir words cword
 
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2659,7 +2715,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${words[cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2690,19 +2746,20 @@ _git ()
 
 _gitk ()
 {
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2730,7 +2787,7 @@ complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
 	|| complete -o default -o nospace -F _git git.exe
 fi
 
-if [[ -n ${ZSH_VERSION-} ]]; then
+if [[ -n $ZSH_VERSION ]]; then
 	shopt () {
 		local option
 		if [ $# -ne 2 ]; then
-- 
1.7.3.2

^ permalink raw reply related	[relevance 2%]

* [PATCH] commit -s: allow "(cherry picked " lines in sign-off section
  @ 2010-11-16 20:25  4%   ` Jonathan Nieder
  0 siblings, 0 replies; 171+ results
From: Jonathan Nieder @ 2010-11-16 20:25 UTC (permalink / raw)
  To: Jeff King; +Cc: Michael J Gruber, git, Martin Svensson, Junio C Hamano

Using cherry-pick -x -s to backport a public commit results in
an unsightly gap in the sign-off chain:

	Reported-by: Jarek Poplawski <jarkao2@gmail.com>
	Tested-by: Jarek Poplawski <jarkao2@gmail.com>
	Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
	Cc: Jeff Mahoney <jeffm@suse.com>
	Cc: All since 2.6.32 <stable@kernel.org>
	Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
	Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
	(cherry picked from commit 9d8117e72bf453dd9d85e0cd322ce4a0f8bccbc0)

	Signed-off-by: Back Porter <backporter@example.com>

The cherry-pick is a step in the line of a patch like any other,
so one might prefer to lose the extra newline.

	...
	Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
	(cherry picked from commit 9d8117e72bf453dd9d85e0cd322ce4a0f8bccbc0)
	Signed-off-by: Back Porter <backporter@example.com>

This commit teaches "git commit --signoff", and thus cherry-pick -s,
to do exactly that.  It works by treating the "(cherry picked" line as
just another line in the signoff chain, except as the first line (that
last exception is to avoid false positives).

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Jeff King wrote:

> Even better, I wonder if it should actually be:
> 
>   message subject
> 
>   Message body.
> 
>   Signed-off-by: Jeff King <peff@peff.net>
>   Cherry-picked-from: ...

Here's something like that.  I use "git cherry-pick -x -s" to
backport patches from a public upstream.  Now you can, too.

Ideally inline notes like

	 [akpm@linux-foundation.org: coding-style fixes]

also ought to be tolerated.

 builtin/commit.c               |   20 +++++++
 t/t3510-cherry-pick-message.sh |  112 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+), 0 deletions(-)
 create mode 100755 t/t3510-cherry-pick-message.sh

diff --git a/builtin/commit.c b/builtin/commit.c
index 66fdd22..71dd52b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -528,6 +528,8 @@ static int ends_rfc2822_footer(struct strbuf *sb)
 		i++;
 
 	for (; i < len; i = k) {
+		static const char cherry_pick[] = "(cherry picked from commit ";
+
 		for (k = i; k < len && buf[k] != '\n'; k++)
 			; /* do nothing */
 		k++;
@@ -535,6 +537,20 @@ static int ends_rfc2822_footer(struct strbuf *sb)
 		if ((buf[k] == ' ' || buf[k] == '\t') && !first)
 			continue;
 
+		if (!first && buf[k] == '(' && k + strlen(cherry_pick) < len) {
+			/* Might be a cherry-pick notice. */
+			const char *p = buf + k;
+			if (!memcmp(p, cherry_pick, strlen(cherry_pick))) {
+				p = memchr(buf + k, '\n', len - k);
+				if (!p)
+					return 0;
+				if (p + 1 == buf + len)
+					return 1;
+				k = p - buf;
+				continue;
+			}
+		}
+
 		first = 0;
 
 		for (j = 0; i + j < len; j++) {
@@ -625,6 +641,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 		for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
 			; /* do nothing */
 		if (prefixcmp(sb.buf + i, sob.buf)) {
+			/*
+			 * Only insert an extra newline if the previous line
+			 * is not part of a Signed-off-by:/Acked-by:/etc chain.
+			 */
 			if (!i || !ends_rfc2822_footer(&sb))
 				strbuf_addch(&sb, '\n');
 			strbuf_addbuf(&sb, &sob);
diff --git a/t/t3510-cherry-pick-message.sh b/t/t3510-cherry-pick-message.sh
new file mode 100755
index 0000000..83e50a3
--- /dev/null
+++ b/t/t3510-cherry-pick-message.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+
+test_description='tests for the log messages cherry-pick produces
+
+  ----
+  +      cherry-pick of branch
+     +   signoff
+    +    basic
+  ++     mainline
+  +++    initial
+'
+. ./test-lib.sh
+
+prepare_commit () {
+	git checkout initial &&
+	test_commit "$1" &&
+	test_tick &&
+	git commit --amend --allow-empty-message -F "$1.message" &&
+	git tag -d "$1" &&
+	git tag "$1"
+}
+
+test_cmp_message () {
+	expect=$1 &&
+	shift &&
+	git log -1 --pretty=format:%B "$@" >actual &&
+	test_cmp "$expect" actual
+}
+
+cat >basic.message <<\EOF
+ A branch
+
+Here comes the lovely description of a change to pick up.
+Contributions come from many people:
+EOF
+
+{
+	cat basic.message
+	cat <<-\EOF
+
+	Signed-off-by: Foo <foo@example.com>
+	Signed-off-by: Bar <bar@example.com>
+	Tested-by: Baz <baz@example.com>
+	EOF
+} >signoff.message
+
+test_expect_success 'setup' '
+	test_commit initial &&
+	prepare_commit basic &&
+	prepare_commit signoff
+'
+
+test_expect_success 'cherry-pick preserves message' '
+	cat basic.message >expect &&
+	git checkout initial &&
+	git cherry-pick basic &&
+	test_cmp_message expect
+'
+
+test_expect_success 'cherry-pick -s adds signoff' '
+	{
+		cat basic.message &&
+		echo &&
+		echo "Signed-off-by: C O Mitter <committer@example.com>"
+	} >expect &&
+	git checkout initial &&
+	git cherry-pick -s basic &&
+	test_cmp_message expect HEAD
+'
+
+test_expect_success 'cherry-pick -s integrates into existing signoff chain' '
+	{
+		cat signoff.message &&
+		echo "Signed-off-by: C O Mitter <committer@example.com>"
+	} >expect &&
+	git checkout initial &&
+	git cherry-pick -s signoff &&
+	test_cmp_message expect HEAD
+'
+
+test_expect_success 'cherry-pick -x adds old commit id' '
+	{
+		cat basic.message &&
+		echo "(cherry picked from commit $(git rev-parse basic^0))"
+	} >expect &&
+	git checkout initial &&
+	git cherry-pick -x basic &&
+	test_cmp_message expect HEAD
+'
+
+test_expect_success 'cherry-pick -x integrates into signoff chain' '
+	{
+		cat signoff.message &&
+		echo "(cherry picked from commit $(git rev-parse signoff^0))"
+	} >expect &&
+	git checkout initial &&
+	git cherry-pick -x signoff &&
+	test_cmp_message expect HEAD
+'
+
+test_expect_success 'cherry-pick -x -s' '
+	{
+		cat signoff.message &&
+		echo "(cherry picked from commit $(git rev-parse signoff^0))"
+		echo "Signed-off-by: C O Mitter <committer@example.com>"
+	} >expect &&
+	git checkout initial &&
+	git cherry-pick -x -s signoff &&
+	test_cmp_message expect HEAD
+'
+
+test_done
-- 
1.7.2.3.551.g13682.dirty

^ permalink raw reply related	[relevance 4%]

* [PATCH v3/RFC 2/2] Use the new functions to get the current cword.
  @ 2010-10-30 20:42  2% ` Peter van der Does
  0 siblings, 0 replies; 171+ results
From: Peter van der Does @ 2010-10-30 20:42 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Peter van der Does, git, SZEDER Gábor, Jonathan Nieder,
	Marc Branchaud, Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

Change the completion functions to use the newly introduced functions to
get the current and/or previous cword and to reassemble the COMP_CWORDS,
making sure the options are correctly split.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  223 ++++++++++++++++++++------------
 1 files changed, 140 insertions(+), 83 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index e0f5893..3115377 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -554,7 +554,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -613,7 +614,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -711,7 +713,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -759,7 +762,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -779,11 +783,13 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n ":" cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -851,13 +857,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -1017,10 +1025,11 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
+	local word subcommand c=1 words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -1033,9 +1042,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1, words cword
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cwords ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -1047,7 +1057,9 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -1071,7 +1083,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1094,7 +1107,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1108,7 +1122,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1152,10 +1167,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	_get_comp_words_by_ref cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -1163,7 +1179,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -1183,8 +1199,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -1205,7 +1223,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1229,7 +1248,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1244,7 +1264,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1256,7 +1277,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1283,7 +1305,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1318,7 +1341,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1350,7 +1374,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1371,7 +1396,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1396,7 +1422,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1408,7 +1435,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1440,7 +1468,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1455,7 +1484,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1474,7 +1504,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1497,7 +1528,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1515,7 +1547,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1535,7 +1568,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1589,7 +1623,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1648,7 +1683,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1659,7 +1695,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1680,7 +1717,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1697,13 +1735,14 @@ _git_name_rev ()
 
 _git_notes ()
 {
-	local subcommands="edit show"
+	local subcommands="edit show" prev
+	_get_comp_words_by_ref prev
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
 		__gitcomp "$subcommands"
 		return
 	fi
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -1717,7 +1756,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1733,8 +1773,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1757,7 +1798,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1787,7 +1830,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1829,9 +1873,10 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
-	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+	local prevword word config_file= words cword
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $cword -gt 1 ]; do
+		word="${words[cword]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1843,7 +1888,7 @@ __git_config_get_set_variables ()
 			;;
 		esac
 		prevword=$word
-		c=$((--c))
+		cword=$((--cword))
 	done
 
 	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
@@ -1859,9 +1904,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1871,13 +1916,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2268,7 +2313,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2280,7 +2326,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2294,7 +2341,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2308,7 +2356,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2326,7 +2375,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2350,7 +2400,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2367,10 +2418,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2412,7 +2464,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2456,7 +2509,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2527,9 +2581,10 @@ _git_svn ()
 
 _git_tag ()
 {
-	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local i c=1 f=0 words cword prev
+	_get_comp_words_by_ref prev words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2542,7 +2597,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2566,15 +2621,16 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir words cword
 
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2586,7 +2642,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${words[cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2617,19 +2673,20 @@ _git ()
 
 _gitk ()
 {
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2657,7 +2714,7 @@ complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
 	|| complete -o default -o nospace -F _git git.exe
 fi
 
-if [[ -n ${ZSH_VERSION-} ]]; then
+if [[ -n $ZSH_VERSION ]]; then
 	shopt () {
 		local option
 		if [ $# -ne 2 ]; then
-- 
1.7.3.2

^ permalink raw reply related	[relevance 2%]

* [PATCH v2/RFC] Make git-completion Bash 4 compatible.
@ 2010-10-27 17:15  2% Peter van der Does
  0 siblings, 0 replies; 171+ results
From: Peter van der Does @ 2010-10-27 17:15 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: git, SZEDER Gábor, Jonathan Nieder, Marc Branchaud,
	Brian Gernhardt, Kevin Ballard, Mathias Lafeldt


The completion script does not work as expected under Bash 4.
Bash: 3
output:
$ git log --pretty=<tab><tab>
email     full      medium    raw
format:   fuller    oneline   short

Bash: 4
output:
$ git log --pretty=<tab><tab>
.bash_logout         .local/
.bash_profile        Music/
--More--

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
Updated patch to play along with latest maint branch. It broke after the patch 
ml/completion-zsh was implemented.
Removed some debugging code from the patch.

 contrib/completion/git-completion.bash |  417 +++++++++++++++++++++++++++-----
 1 files changed, 355 insertions(+), 62 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 64341d5..85fb0f1 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -76,12 +76,251 @@
 #
 #       git@vger.kernel.org
 #
+# Updated for Bash 4.0
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
 *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
 esac
 
+# If the function _get_comp_words_by_ref does not exists, we can assume the
+# bash_completion 1.2 script isn't loaded and therefor we're defining the
+# necessary functions ourselves.
+if ! type _get_comp_words_by_ref &> /dev/null ; then
+	# Assign variable one scope above the caller
+	# Usage: local "$1" && _upvar $1 "value(s)"
+	# Param: $1  Variable name to assign value to
+	# Param: $*  Value(s) to assign.  If multiple values, an array is
+	#            assigned, otherwise a single value is assigned.
+	# NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
+	#       use multiple '_upvar' calls, since one '_upvar' call might
+	#       reassign a variable to be used by another '_upvar' call.
+	# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+	_upvar() {
+		if unset -v "$1"; then           # Unset & validate varname
+	        if (( $# == 2 )); then
+	            eval $1=\"\$2\"          # Return single value
+	        else
+	            eval $1=\(\"\${@:2}\"\)  # Return array
+	        fi
+	    fi
+	}
+
+
+	# Assign variables one scope above the caller
+	# Usage: local varname [varname ...] &&
+	#        _upvars [-v varname value] | [-aN varname [value ...]] ...
+	# Available OPTIONS:
+	#     -aN  Assign next N values to varname as array
+	#     -v   Assign single value to varname
+	# Return: 1 if error occurs
+	# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+	_upvars() {
+	    if ! (( $# )); then
+	        echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
+	            "value] | [-aN varname [value ...]] ..." 1>&2
+	        return 2
+	    fi
+	    while (( $# )); do
+	        case $1 in
+	            -a*)
+	                # Error checking
+	                [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
+	                    "number specifier" 1>&2; return 1; }
+	                printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
+	                    "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
+	                    return 1; }
+	                # Assign array of -aN elements
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
+	                shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
+	                    "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
+	                ;;
+	            -v)
+	                # Assign single value
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
+	                shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
+	                "argument(s)" 1>&2; return 1; }
+	                ;;
+	            *)
+	                echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
+	                return 1 ;;
+	        esac
+	    done
+	}
+
+
+	# Reassemble command line words, excluding specified characters from the
+	# list of word completion separators (COMP_WORDBREAKS).
+	# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
+	#     NOT be considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 here.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	#
+	__reassemble_comp_words_by_ref() {
+	    local exclude i j ref
+	    # Exclude word separator characters?
+	    if [[ $1 ]]; then
+	        # Yes, exclude word separator characters;
+	        # Exclude only those characters, which were really included
+	        exclude="${1//[^$COMP_WORDBREAKS]}"
+	    fi
+
+	    # Default to cword unchanged
+	    eval $3=$COMP_CWORD
+	    # Are characters excluded which were former included?
+	    if [[ $exclude ]]; then
+	        # Yes, list of word completion separators has shrunk;
+	        # Re-assemble words to complete
+	        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+	            # Is current word not word 0 (the command itself) and is word not
+	            # empty and is word made up of just word separator characters to be
+	            # excluded?
+	            while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
+	                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
+	            ]]; do
+	                [ $j -ge 2 ] && ((j--))
+	                # Append word separator to current word
+	                ref="$2[$j]"
+	                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	                # Indicate new cword
+	                [ $i = $COMP_CWORD ] && eval $3=$j
+	                # Indicate next word if available, else end *both* while and for loop
+	                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
+	            done
+	            # Append word to current word
+	            ref="$2[$j]"
+	            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	            # Indicate new cword
+	            [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j
+	        done
+	    else
+	        # No, list of word completions separators hasn't changed;
+	        eval $2=\( \"\${COMP_WORDS[@]}\" \)
+	    fi
+	} # __reassemble_comp_words_by_ref()
+
+	# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
+	#     considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
+	#     ensures we get the same word on both bash-3 and bash-4.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	# @param $4 cur  Name of variable to return current word to complete to
+	# @see ___get_cword_at_cursor_by_ref()
+	__get_cword_at_cursor_by_ref() {
+	    local cword words=()
+	    __reassemble_comp_words_by_ref "$1" words cword
+
+	    local i cur2
+	    local cur="$COMP_LINE"
+	    local index="$COMP_POINT"
+	    for (( i = 0; i <= cword; ++i )); do
+	        while [[
+	            # Current word fits in $cur?
+	            "${#cur}" -ge ${#words[i]} &&
+	            # $cur doesn't match cword?
+	            "${cur:0:${#words[i]}}" != "${words[i]}"
+	        ]]; do
+	            # Strip first character
+	            cur="${cur:1}"
+	            # Decrease cursor position
+	            ((index--))
+	        done
+
+	        # Does found word matches cword?
+	        if [[ "$i" -lt "$cword" ]]; then
+	            # No, cword lies further;
+	            local old_size="${#cur}"
+	            cur="${cur#${words[i]}}"
+	            local new_size="${#cur}"
+	            index=$(( index - old_size + new_size ))
+	        fi
+	    done
+
+	    if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
+	        # We messed up. At least return the whole word so things keep working
+	        cur2=${words[cword]}
+	    else
+	        cur2=${cur:0:$index}
+	    fi
+
+	    local "$2" "$3" "$4" &&
+	        _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
+	}
+
+
+	# Get the word to complete and optional previous words.
+	# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
+	# where the user is completing in the middle of a word.
+	# (For example, if the line is "ls foobar",
+	# and the cursor is here -------->   ^
+	# Also one is able to cross over possible wordbreak characters.
+	# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
+	# Available VARNAMES:
+	#     cur         Return cur via $cur
+	#     prev        Return prev via $prev
+	#     words       Return words via $words
+	#     cword       Return cword via $cword
+	#
+	# Available OPTIONS:
+	#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be
+	#                 considered word breaks. This is useful for things like scp
+	#                 where we want to return host:path and not only path, so we
+	#                 would pass the colon (:) as -n option in this case.  Bash-3
+	#                 doesn't do word splitting, so this ensures we get the same
+	#                 word on both bash-3 and bash-4.
+	#     -c VARNAME  Return cur via $VARNAME
+	#     -p VARNAME  Return prev via $VARNAME
+	#     -w VARNAME  Return words via $VARNAME
+	#     -i VARNAME  Return cword via $VARNAME
+	#
+	# Example usage:
+	#
+	#    $ _get_comp_words_by_ref -n : cur prev
+	#
+	_get_comp_words_by_ref()
+	{
+	    local exclude flag i OPTIND=1
+	    local cur cword words=()
+	    local upargs=() upvars=() vcur vcword vprev vwords
+
+	    while getopts "c:i:n:p:w:" flag "$@"; do
+	        case $flag in
+	            c) vcur=$OPTARG ;;
+	            i) vcword=$OPTARG ;;
+	            n) exclude=$OPTARG ;;
+	            p) vprev=$OPTARG ;;
+	            w) vwords=$OPTARG ;;
+	        esac
+	    done
+	    while [[ $# -ge $OPTIND ]]; do
+	        case ${!OPTIND} in
+	            cur)   vcur=cur ;;
+	            prev)  vprev=prev ;;
+	            cword) vcword=cword ;;
+	            words) vwords=words ;;
+	            *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
+	                1>&2; return 1
+	        esac
+	        let "OPTIND += 1"
+	    done
+
+	    __get_cword_at_cursor_by_ref "$exclude" words cword cur
+
+	    [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
+	    [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
+	    [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
+	        "${words[cword - 1]}"); }
+	    [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
+	        "${words[@]}"); }
+
+	    (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
+	}
+fi
+
 # __gitdir accepts 0 or 1 arguments (i.e., location)
 # returns location of .git repo
 __gitdir ()
@@ -331,7 +570,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -390,7 +630,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -488,7 +729,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -536,7 +778,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -556,11 +799,14 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local git_comp_words git_comp_cword
+	__reassemble_comp_words_by_ref : git_comp_words git_comp_cword
+	local cmd="${git_comp_words[1]}"
+	local cur
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n ":" cur
+	while [ $c -lt $git_comp_cword ]; do
+		i="${git_comp_words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -628,13 +874,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -824,7 +1072,10 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -848,7 +1099,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -871,7 +1123,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -885,7 +1138,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -929,7 +1183,8 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n", cur
+	_get_comp_words_by_ref cur
 
 	while [ $c -lt $COMP_CWORD ]; do
 		i="${COMP_WORDS[c]}"
@@ -940,7 +1195,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -982,7 +1237,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1006,7 +1262,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1021,7 +1278,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1033,7 +1291,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1060,7 +1319,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1095,7 +1355,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1127,7 +1388,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1148,7 +1410,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1173,7 +1436,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1185,7 +1449,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1217,7 +1482,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1232,7 +1498,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1251,7 +1518,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1274,7 +1542,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1292,7 +1561,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1312,7 +1582,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1366,7 +1637,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1425,7 +1697,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1436,7 +1709,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1457,7 +1731,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1494,7 +1769,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1510,8 +1786,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1534,7 +1811,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1564,7 +1843,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1606,9 +1886,11 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
+	local prevword word config_file= c
+	local git_comp_words
+	__reassemble_comp_words_by_ref = git_comp_words c
 	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+		word="${git_comp_words[c]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1636,9 +1918,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1648,13 +1930,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2045,7 +2327,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2057,7 +2340,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2071,7 +2355,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2085,7 +2370,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2103,7 +2389,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2127,7 +2414,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2144,10 +2432,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2189,7 +2478,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2233,7 +2523,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2343,15 +2634,16 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir git_comp_words git_comp_cword
 
 	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	__reassemble_comp_words_by_ref = git_comp_words git_comp_cword
+	while [ $c -lt $git_comp_cword ]; do
+		i="${git_comp_words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2363,7 +2655,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${git_comp_words[git_comp_cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2401,12 +2693,13 @@ _gitk ()
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
-- 
1.7.3.2


-- 
Peter van der Does

GPG key: E77E8E98

IRC: Ganseki on irc.freenode.net
Twitter: @petervanderdoes

^ permalink raw reply related	[relevance 2%]

* [PATCH/RFC] Make git-completion Bash 4 compatible.
@ 2010-10-26 13:53  2% Peter van der Does
  0 siblings, 0 replies; 171+ results
From: Peter van der Does @ 2010-10-26 13:53 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: git, SZEDER Gábor, Jonathan Nieder, Marc Branchaud,
	Brian Gernhardt, Kevin Ballard, Mathias Lafeldt


The completion script does not work as expected under Bash 4.
Bash: 3
output:
$ git log --pretty=<tab><tab>
email     full      medium    raw
format:   fuller    oneline   short

Bash: 4
output:
$ git log --pretty=<tab><tab>
.bash_logout         .local/
.bash_profile        Music/
--More--

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  419 +++++++++++++++++++++++++++-----
 1 files changed, 357 insertions(+), 62 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index f83f019..becabd0 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -71,12 +71,251 @@
 #
 #       git@vger.kernel.org
 #
+# Updated for Bash 4.0
 
 case "$COMP_WORDBREAKS" in
 *:*) : great ;;
 *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
 esac
 
+# If the function _get_comp_words_by_ref does not exists, we can assume the
+# bash_completion 1.2 script isn't loaded and therefor we're defining the
+# necessary functions ourselves.
+if ! type _get_comp_words_by_ref &> /dev/null ; then
+	# Assign variable one scope above the caller
+	# Usage: local "$1" && _upvar $1 "value(s)"
+	# Param: $1  Variable name to assign value to
+	# Param: $*  Value(s) to assign.  If multiple values, an array is
+	#            assigned, otherwise a single value is assigned.
+	# NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
+	#       use multiple '_upvar' calls, since one '_upvar' call might
+	#       reassign a variable to be used by another '_upvar' call.
+	# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+	_upvar() {
+		if unset -v "$1"; then           # Unset & validate varname
+	        if (( $# == 2 )); then
+	            eval $1=\"\$2\"          # Return single value
+	        else
+	            eval $1=\(\"\${@:2}\"\)  # Return array
+	        fi
+	    fi
+	}
+
+
+	# Assign variables one scope above the caller
+	# Usage: local varname [varname ...] &&
+	#        _upvars [-v varname value] | [-aN varname [value ...]] ...
+	# Available OPTIONS:
+	#     -aN  Assign next N values to varname as array
+	#     -v   Assign single value to varname
+	# Return: 1 if error occurs
+	# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+	_upvars() {
+	    if ! (( $# )); then
+	        echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
+	            "value] | [-aN varname [value ...]] ..." 1>&2
+	        return 2
+	    fi
+	    while (( $# )); do
+	        case $1 in
+	            -a*)
+	                # Error checking
+	                [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
+	                    "number specifier" 1>&2; return 1; }
+	                printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
+	                    "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
+	                    return 1; }
+	                # Assign array of -aN elements
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
+	                shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
+	                    "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
+	                ;;
+	            -v)
+	                # Assign single value
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
+	                shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
+	                "argument(s)" 1>&2; return 1; }
+	                ;;
+	            *)
+	                echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
+	                return 1 ;;
+	        esac
+	    done
+	}
+
+
+	# Reassemble command line words, excluding specified characters from the
+	# list of word completion separators (COMP_WORDBREAKS).
+	# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
+	#     NOT be considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 here.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	#
+	__reassemble_comp_words_by_ref() {
+	    local exclude i j ref
+	    # Exclude word separator characters?
+	    if [[ $1 ]]; then
+	        # Yes, exclude word separator characters;
+	        # Exclude only those characters, which were really included
+	        exclude="${1//[^$COMP_WORDBREAKS]}"
+	    fi
+
+	    # Default to cword unchanged
+	    eval $3=$COMP_CWORD
+	    # Are characters excluded which were former included?
+	    if [[ $exclude ]]; then
+	        # Yes, list of word completion separators has shrunk;
+	        # Re-assemble words to complete
+	        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+	            # Is current word not word 0 (the command itself) and is word not
+	            # empty and is word made up of just word separator characters to be
+	            # excluded?
+	            while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
+	                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
+	            ]]; do
+	                [ $j -ge 2 ] && ((j--))
+	                # Append word separator to current word
+	                ref="$2[$j]"
+	                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	                # Indicate new cword
+	                [ $i = $COMP_CWORD ] && eval $3=$j
+	                # Indicate next word if available, else end *both* while and for loop
+	                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
+	            done
+	            # Append word to current word
+	            ref="$2[$j]"
+	            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	            # Indicate new cword
+	            [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j
+	        done
+	    else
+	        # No, list of word completions separators hasn't changed;
+	        eval $2=\( \"\${COMP_WORDS[@]}\" \)
+	    fi
+	} # __reassemble_comp_words_by_ref()
+
+	# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
+	#     considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
+	#     ensures we get the same word on both bash-3 and bash-4.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	# @param $4 cur  Name of variable to return current word to complete to
+	# @see ___get_cword_at_cursor_by_ref()
+	__get_cword_at_cursor_by_ref() {
+	    local cword words=()
+	    __reassemble_comp_words_by_ref "$1" words cword
+
+	    local i cur2
+	    local cur="$COMP_LINE"
+	    local index="$COMP_POINT"
+	    for (( i = 0; i <= cword; ++i )); do
+	        while [[
+	            # Current word fits in $cur?
+	            "${#cur}" -ge ${#words[i]} &&
+	            # $cur doesn't match cword?
+	            "${cur:0:${#words[i]}}" != "${words[i]}"
+	        ]]; do
+	            # Strip first character
+	            cur="${cur:1}"
+	            # Decrease cursor position
+	            ((index--))
+	        done
+
+	        # Does found word matches cword?
+	        if [[ "$i" -lt "$cword" ]]; then
+	            # No, cword lies further;
+	            local old_size="${#cur}"
+	            cur="${cur#${words[i]}}"
+	            local new_size="${#cur}"
+	            index=$(( index - old_size + new_size ))
+	        fi
+	    done
+
+	    if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
+	        # We messed up. At least return the whole word so things keep working
+	        cur2=${words[cword]}
+	    else
+	        cur2=${cur:0:$index}
+	    fi
+
+	    local "$2" "$3" "$4" &&
+	        _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
+	}
+
+
+	# Get the word to complete and optional previous words.
+	# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
+	# where the user is completing in the middle of a word.
+	# (For example, if the line is "ls foobar",
+	# and the cursor is here -------->   ^
+	# Also one is able to cross over possible wordbreak characters.
+	# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
+	# Available VARNAMES:
+	#     cur         Return cur via $cur
+	#     prev        Return prev via $prev
+	#     words       Return words via $words
+	#     cword       Return cword via $cword
+	#
+	# Available OPTIONS:
+	#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be
+	#                 considered word breaks. This is useful for things like scp
+	#                 where we want to return host:path and not only path, so we
+	#                 would pass the colon (:) as -n option in this case.  Bash-3
+	#                 doesn't do word splitting, so this ensures we get the same
+	#                 word on both bash-3 and bash-4.
+	#     -c VARNAME  Return cur via $VARNAME
+	#     -p VARNAME  Return prev via $VARNAME
+	#     -w VARNAME  Return words via $VARNAME
+	#     -i VARNAME  Return cword via $VARNAME
+	#
+	# Example usage:
+	#
+	#    $ _get_comp_words_by_ref -n : cur prev
+	#
+	_get_comp_words_by_ref()
+	{
+	    local exclude flag i OPTIND=1
+	    local cur cword words=()
+	    local upargs=() upvars=() vcur vcword vprev vwords
+
+	    while getopts "c:i:n:p:w:" flag "$@"; do
+	        case $flag in
+	            c) vcur=$OPTARG ;;
+	            i) vcword=$OPTARG ;;
+	            n) exclude=$OPTARG ;;
+	            p) vprev=$OPTARG ;;
+	            w) vwords=$OPTARG ;;
+	        esac
+	    done
+	    while [[ $# -ge $OPTIND ]]; do
+	        case ${!OPTIND} in
+	            cur)   vcur=cur ;;
+	            prev)  vprev=prev ;;
+	            cword) vcword=cword ;;
+	            words) vwords=words ;;
+	            *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
+	                1>&2; return 1
+	        esac
+	        let "OPTIND += 1"
+	    done
+
+	    __get_cword_at_cursor_by_ref "$exclude" words cword cur
+
+	    [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
+	    [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
+	    [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
+	        "${words[cword - 1]}"); }
+	    [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
+	        "${words[@]}"); }
+
+	    (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
+	}
+fi
+
 # __gitdir accepts 0 or 1 arguments (i.e., location)
 # returns location of .git repo
 __gitdir ()
@@ -325,7 +564,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -384,7 +624,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -482,7 +723,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -530,7 +772,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -550,11 +793,14 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local git_comp_words git_comp_cword
+	__reassemble_comp_words_by_ref : git_comp_words git_comp_cword
+	local cmd="${git_comp_words[1]}"
+	local cur
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n ":" cur
+	while [ $c -lt $git_comp_cword ]; do
+		i="${git_comp_words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -622,13 +868,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -818,7 +1066,12 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
+	echo "$cur"
+	echo "$prev"
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -842,7 +1095,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -865,7 +1119,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -879,7 +1134,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -923,7 +1179,8 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n", cur
+	_get_comp_words_by_ref cur
 
 	while [ $c -lt $COMP_CWORD ]; do
 		i="${COMP_WORDS[c]}"
@@ -934,7 +1191,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -976,7 +1233,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1000,7 +1258,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1015,7 +1274,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1027,7 +1287,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1054,7 +1315,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1089,7 +1351,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1121,7 +1384,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1142,7 +1406,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1167,7 +1432,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1179,7 +1445,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1211,7 +1478,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1226,7 +1494,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1245,7 +1514,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1268,7 +1538,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1286,7 +1557,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1306,7 +1578,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1360,7 +1633,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1419,7 +1693,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1430,7 +1705,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1451,7 +1727,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1488,7 +1765,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1504,8 +1782,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1528,7 +1807,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1558,7 +1839,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1600,9 +1882,11 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
+	local prevword word config_file= c
+	local git_comp_words
+	__reassemble_comp_words_by_ref = git_comp_words c
 	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+		word="${git_comp_words[c]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1630,9 +1914,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1642,13 +1926,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2039,7 +2323,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2051,7 +2336,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2065,7 +2351,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2079,7 +2366,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2097,7 +2385,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2121,7 +2410,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2138,10 +2428,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2183,7 +2474,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2227,7 +2519,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2337,10 +2630,11 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir git_comp_words git_comp_cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	__reassemble_comp_words_by_ref = git_comp_words git_comp_cword
+	while [ $c -lt $git_comp_cword ]; do
+		i="${git_comp_words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2352,7 +2646,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${git_comp_words[git_comp_cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2385,12 +2679,13 @@ _gitk ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
-- 
1.7.3.1


-- 
Peter van der Does

GPG key: E77E8E98

IRC: Ganseki on irc.freenode.net
Twitter: @petervanderdoes

^ permalink raw reply related	[relevance 2%]

* Re: [PATCH] Add `commit.signoff` configuration variable.
  2010-01-13  3:36 14% [PATCH] Add `commit.signoff` configuration variable Steven Drake
  2010-01-13  4:36 11% ` Steven Drake
@ 2010-01-13  8:30  6% ` Junio C Hamano
  1 sibling, 0 replies; 171+ results
From: Junio C Hamano @ 2010-01-13  8:30 UTC (permalink / raw)
  To: Steven Drake; +Cc: git

You need to defend this one better, in fact a *lot* better, than other
ones.  See

  http://thread.gmane.org/gmane.comp.version-control.git/32503/focus=32522
  http://thread.gmane.org/gmane.comp.version-control.git/103939/focus=104207

for starters.  Your justifications should address all the points raised in
previous threads.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] Add `commit.signoff` configuration variable.
  2010-01-13  3:36 14% [PATCH] Add `commit.signoff` configuration variable Steven Drake
@ 2010-01-13  4:36 11% ` Steven Drake
  2010-01-13  8:30  6% ` Junio C Hamano
  1 sibling, 0 replies; 171+ results
From: Steven Drake @ 2010-01-13  4:36 UTC (permalink / raw)
  To: git

On Wed, 13 Jan 2010, Steven Drake wrote:
> Signed-off-by: Steven Drake <sdrake@xnet.co.nz>

I ment to make a note with that patch that the commit message Signed-off-by
was added using using the `commit.signoff` feature.

-- 
Steven
  1: Linux - will work for fish.
  2: The Linux penguin - looks stuffed to the brim with herring.
  ( make your own conclusions )

^ permalink raw reply	[relevance 11%]

* [PATCH] Add 'git commit --no-signoff' option.
@ 2010-01-13  3:36 21% Steven Drake
  0 siblings, 0 replies; 171+ results
From: Steven Drake @ 2010-01-13  3:36 UTC (permalink / raw)
  To: git

Do not add a signed-off-by line. This overrides both the `--signoff`
option and the `commit.signoff` configuration variable.

Signed-off-by: Steven Drake <sdrake@xnet.co.nz>
---
 Documentation/git-commit.txt |    4 ++++
 builtin-commit.c             |    5 ++++-
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 5a977b6..2dfc989 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -116,6 +116,10 @@ OPTIONS
 	Add Signed-off-by line by the committer at the end of the commit
 	log message. This overrides the `commit.signoff` configuration variable.
 
+--no-signoff::
+	Do not add igned-off-by line. This overrides both the `--signoff`
+	option and the `commit.signoff` configuration variable.
+
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin-commit.c b/builtin-commit.c
index db90e7a..f236068 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -51,7 +51,7 @@ static const char *logfile, *force_author;
 static const char *template_file;
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
-static int all, edit_flag, also, interactive, only, amend, signoff;
+static int all, edit_flag, also, interactive, only, amend, signoff, no_signoff;
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static char *untracked_files_arg;
 /*
@@ -103,6 +103,7 @@ static struct option builtin_commit_options[] = {
 	OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
 	OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
 	OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
+	OPT_BOOLEAN(0, "no-signoff", &no_signoff, "Do not add Signed-off-by:"),
 	OPT_FILENAME('t', "template", &template_file, "use specified template file"),
 	OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
 	OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
@@ -797,6 +798,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (force_author && renew_authorship)
 		die("Using both --reset-author and --author does not make sense");
 
+	signoff = no_signoff ? 0 : signoff;
+
 	if (logfile || message.len || use_message)
 		use_editor = 0;
 	if (edit_flag)
-- 
1.6.4

^ permalink raw reply related	[relevance 21%]

* [PATCH] Add `commit.signoff` configuration variable.
@ 2010-01-13  3:36 14% Steven Drake
  2010-01-13  4:36 11% ` Steven Drake
  2010-01-13  8:30  6% ` Junio C Hamano
  0 siblings, 2 replies; 171+ results
From: Steven Drake @ 2010-01-13  3:36 UTC (permalink / raw)
  To: git

Signed-off-by: Steven Drake <sdrake@xnet.co.nz>
---
 Documentation/config.txt     |    4 ++++
 Documentation/git-commit.txt |    2 +-
 builtin-commit.c             |    4 ++++
 3 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 23a965e..dd261cf 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -712,6 +712,10 @@ color.ui::
 	terminal. When more specific variables of color.* are set, they always
 	take precedence over this setting. Defaults to false.
 
+commit.signoff::
+	Add Signed-off-by line by the committer at the end of the commit
+	log message.
+
 commit.template::
 	Specify a file to use as the template for new commit messages.
 	"{tilde}/" is expanded to the value of `$HOME` and "{tilde}user/" to the
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index c97c151..5a977b6 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -114,7 +114,7 @@ OPTIONS
 -s::
 --signoff::
 	Add Signed-off-by line by the committer at the end of the commit
-	log message.
+	log message. This overrides the `commit.signoff` configuration variable.
 
 -n::
 --no-verify::
diff --git a/builtin-commit.c b/builtin-commit.c
index 3dfcd77..db90e7a 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -1093,6 +1093,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 
 	if (!strcmp(k, "commit.template"))
 		return git_config_pathname(&template_file, k, v);
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
 
 	return git_status_config(k, v, s);
 }
-- 
1.6.4

^ permalink raw reply related	[relevance 14%]

* What's cooking in git.git (Jan 2009, #02; Sun, 11)
@ 2009-01-11  9:51  4% Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2009-01-11  9:51 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'.  The ones marked with '.' do not appear in any of the branches,
but I am still holding onto them.

The topics list the commits in reverse chronological order.  The topics
meant to be merged to the maintenance series have "maint-" in their names.

----------------------------------------------------------------
[New Topics]

* rs/fgrep (Sat Jan 10 00:18:34 2009 +0100) 2 commits
 + grep: don't call regexec() for fixed strings
 + grep -w: forward to next possible position after rejected match

* lt/zlib-wrap-xprm (Wed Jan 7 19:54:47 2009 -0800) 1 commit
 - Wrap inflateInit to retry allocation after releasing pack memory

Need to clean up the log message, perhaps rebase it to maint-1.6.0 and
start cooking in 'next'.

* jc/maint-format-patch (Sat Jan 10 12:41:33 2009 -0800) 1 commit
 + format-patch: show patch text for the root commit

* tr/maint-no-index-fixes (Wed Jan 7 12:15:30 2009 +0100) 3 commits
 + diff --no-index -q: fix endless loop
 + diff --no-index: test for pager after option parsing
 + diff: accept -- when using --no-index

* gb/gitweb-opml (Fri Jan 2 13:49:30 2009 +0100) 2 commits
 - gitweb: suggest name for OPML view
 - gitweb: don't use pathinfo for global actions

* mh/maint-commit-color-status (Thu Jan 8 19:53:05 2009 +0100) 2 commits
 - git-status -v: color diff output when color.ui is set
 - git-commit: color status output when color.ui is set

* ks/maint-mailinfo-folded (Thu Jan 8 01:43:42 2009 +0300) 1 commit
 - mailinfo: correctly handle multiline 'Subject:' header

* js/patience-diff (Thu Jan 1 17:39:37 2009 +0100) 3 commits
 - bash completions: Add the --patience option
 - Introduce the diff option '--patience'
 - Implement the patience diff algorithm

All of the above 'pu' topics are ready for 'next'.

* ap/clone-into-empty (Fri Jan 9 02:24:23 2009 +0300) 2 commits
 - Use is_pseudo_dir_name everywhere
 - Allow cloning to an existing empty directory

There is an updated patch that only refactors the repeated code to check
if a dirent is dot or dot-dot posted, which I should have picked up to
replace these but I haven't yet (the "clone into empty" can and should
build on top of it).

----------------------------------------------------------------
[Stalled and may need help and prodding to go forward]

* ds/uintmax-config (Mon Nov 3 09:14:28 2008 -0900) 1 commit
 - autoconf: Enable threaded delta search when pthreads are supported

This automatically enables threaded delta search code when autoconf
detects pthreads are usable.  I haven't heard neither positive nor
negative comments from minority platforms that might be harmed, but
this feels like the right thing to do, so perhaps the best course of
action is to merge this down to 'master' and see if anybody screams.

* jc/blame (Wed Jun 4 22:58:40 2008 -0700) 2 commits
 + blame: show "previous" information in --porcelain/--incremental
   format
 + git-blame: refactor code to emit "porcelain format" output

This gives Porcelains (like gitweb) the information on the commit _before_
the one that the final blame is laid on, which should save them one
rev-parse to dig further.  The line number in the "previous" information
may need refining, and sanity checking code for reference counting may
need to be resurrected before this can move forward.

----------------------------------------------------------------
[Actively cooking]

* mv/apply-parse-opt (Fri Jan 9 22:21:36 2009 -0800) 2 commits
 + Resurrect "git apply --flags -" to read from the standard input
 + parse-opt: migrate builtin-apply.

* rs/maint-shortlog-foldline (Tue Jan 6 21:41:06 2009 +0100) 1 commit
 + shortlog: handle multi-line subjects like log --pretty=oneline et.
   al. do

* tr/rebase-root (Fri Jan 2 23:28:29 2009 +0100) 4 commits
 - rebase: update documentation for --root
 - rebase -i: learn to rebase root commit
 - rebase: learn to rebase root commit
 - rebase -i: execute hook only after argument checking

I should be able to find time to read this over again and merge to
'next' sometime this week.

* as/autocorrect-alias (Sun Jan 4 18:16:01 2009 +0100) 1 commit
 + git.c: make autocorrected aliases work

* js/notes (Sat Dec 20 13:06:03 2008 +0100) 4 commits
 - Add an expensive test for git-notes
 - Speed up git notes lookup
 - Add a script to edit/inspect notes
 - Introduce commit notes

* sc/gitweb-category (Fri Dec 12 00:45:12 2008 +0100) 3 commits
 - gitweb: Optional grouping of projects by category
 - gitweb: Split git_project_list_body in two functions
 - gitweb: Modularized git_get_project_description to be more generic

* gb/gitweb-patch (Thu Dec 18 08:13:19 2008 +0100) 4 commits
 - gitweb: link to patch(es) view in commit(diff) and (short)log view
 - gitweb: add patches view
 - gitweb: change call pattern for git_commitdiff
 - gitweb: add patch view

----------------------------------------------------------------
[Graduated to "master"]

* mh/maint-sendmail-cc-doc (Mon Dec 29 00:37:25 2008 +0100) 1 commit
 + doc/git-send-email: mention sendemail.cc config variable

* rs/diff-ihc (Sun Dec 28 19:45:32 2008 +0100) 1 commit
 + diff: add option to show context between close hunks

* js/maint-merge-recursive-r-d-conflict (Mon Dec 22 23:10:20 2008 +0100) 1 commit
 + merge-recursive: mark rename/delete conflict as unmerged

* mk/gitweb-feature (Mon Dec 15 22:16:19 2008 -0800) 1 commit
 + gitweb: unify boolean feature subroutines

* cb/merge-recursive-fix (Mon Dec 15 02:41:24 2008 -0800) 3 commits
 + Merge branch 'cb/maint-merge-recursive-fix' into cb/merge-
   recursive-fix
 + merge-recursive: do not clobber untracked working tree garbage
 + modify/delete conflict resolution overwrites untracked file

* cb/maint-merge-recursive-fix (Sun Dec 14 19:40:09 2008 -0800) 2 commits
 + merge-recursive: do not clobber untracked working tree garbage
 + modify/delete conflict resolution overwrites untracked file

* wp/add-p-goto (Thu Dec 4 10:22:40 2008 +0000) 2 commits
 + Add 'g' command to go to a hunk
 + Add subroutine to display one-line summary of hunks

* jn/gitweb-blame (Thu Dec 11 01:33:29 2008 +0100) 3 commits
 + gitweb: cache $parent_commit info in git_blame()
 + gitweb: A bit of code cleanup in git_blame()
 + gitweb: Move 'lineno' id from link to row element in git_blame

* mv/um-pdf (Wed Dec 10 23:44:50 2008 +0100) 1 commit
 + Add support for a pdf version of the user manual

* kk/maint-http-push (Tue Dec 23 11:31:15 2008 +0300) 1 commit
 + http-push: support full URI in handle_remote_ls_ctx()

----------------------------------------------------------------
[Will merge to "master" soon]

* nd/grep-assume-unchanged (Sat Dec 27 15:21:03 2008 +0700) 2 commits
 + grep: grep cache entries if they are "assume unchanged"
 + grep: support --no-ext-grep to test builtin grep

* as/maint-shortlog-cleanup (Tue Dec 30 22:01:44 2008 +0100) 1 commit
 + builtin-shortlog.c: use string_list_append(), and don't strdup
   unnecessarily

* jc/maint-ls-tree (Wed Dec 31 19:00:50 2008 +0900) 2 commits
 + Document git-ls-tree --full-tree
 + ls-tree: add --full-tree option

* js/bundle-tags (Fri Jan 2 19:08:46 2009 +0100) 1 commit
 + bundle: allow rev-list options to exclude annotated tags

* js/add-not-submodule (Fri Jan 2 19:08:40 2009 +0100) 1 commit
 + git add: do not add files from a submodule

* pb/maint-git-pm-false-dir (Mon Dec 29 01:25:00 2008 +0100) 1 commit
 + Git.pm: correctly handle directory name that evaluates to "false"

* pj/maint-ldflags (Sun Jan 4 21:27:41 2009 -0500) 1 commit
 + configure clobbers LDFLAGS

* fe/cvsserver (Fri Jan 2 16:40:14 2009 +0100) 2 commits
 + cvsserver: change generation of CVS author names
 + cvsserver: add option to configure commit message

* js/maint-bisect-gitk (Fri Jan 2 19:08:00 2009 +0100) 1 commit
 + bisect view: call gitk if Cygwin's SESSIONNAME variable is set

* np/no-loosen-prune-expire-now (Tue Dec 30 14:45:11 2008 -0500) 1 commit
 + objects to be pruned immediately don't have to be loosened

* cb/maint-unpack-trees-absense (Thu Jan 1 21:54:33 2009 +0100) 3 commits
 + unpack-trees: remove redundant path search in verify_absent
 + unpack-trees: fix path search bug in verify_absent
 + unpack-trees: handle failure in verify_absent

* mc/cd-p-pwd (Tue Dec 30 07:10:24 2008 -0800) 1 commit
 + git-sh-setup: Fix scripts whose PWD is a symlink to a work-dir on
   OS X

* mh/cherry-default (Thu Jan 1 22:56:29 2009 +0100) 2 commits
 + Documentation: clarify which parameters are optional to git-cherry
 + git-cherry: make <upstream> parameter optional

----------------------------------------------------------------
[Will drop]

* as/commit-signoff (Mon Dec 29 12:16:45 2008 +0100) 1 commit
 - [WIP] Add a commit.signoff configuration option to always use --
   signoff in commit

The semantics when "git commit" was used as a backend for other actions
such as rebase and cherry-pick was unclear.

----------------------------------------------------------------
[On Hold]

* jk/renamelimit (Sat May 3 13:58:42 2008 -0700) 1 commit
 - diff: enable "too large a rename" warning when -M/-C is explicitly
   asked for

This would be the right thing to do for command line use,
but gitk will be hit due to tcl/tk's limitation, so I am holding
this back for now.

* jc/stripspace (Sun Mar 9 00:30:35 2008 -0800) 6 commits
 - git-am --forge: add Signed-off-by: line for the author
 - git-am: clean-up Signed-off-by: lines
 - stripspace: add --log-clean option to clean up signed-off-by:
   lines
 - stripspace: use parse_options()
 - Add "git am -s" test
 - git-am: refactor code to add signed-off-by line for the committer

^ permalink raw reply	[relevance 4%]

* What's cooking in git.git (Jan 2009, #01; Mon, 05)
@ 2009-01-06  6:33  4% Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2009-01-06  6:33 UTC (permalink / raw)
  To: git

What's cooking in git.git (Jan 2009, #01; Mon, 05)
--------------------------------------------------

Here are the topics that have been cooking.  Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'.  The ones marked with '.' do not appear in any of the branches,
but I am still holding onto them.

The topics list the commits in reverse chronological order.  The topics
meant to be merged to the maintenance series have "maint-" in their names.

Sorry to have been lagging a bit.  There are a few patches I am interested
in but haven't studied yet nor mentioned here.  I've been swamped outside
git lately for the past few days, but hopefully I can get to them shortly.

----------------------------------------------------------------
[New Topics]

* js/bundle-tags (Fri Jan 2 19:08:46 2009 +0100) 1 commit
 + bundle: allow rev-list options to exclude annotated tags

* js/add-not-submodule (Fri Jan 2 19:08:40 2009 +0100) 1 commit
 + git add: do not add files from a submodule

* pb/maint-git-pm-false-dir (Mon Dec 29 01:25:00 2008 +0100) 1 commit
 + Git.pm: correctly handle directory name that evaluates to "false"

* pj/maint-ldflags (Sun Jan 4 21:27:41 2009 -0500) 1 commit
 + configure clobbers LDFLAGS

* fe/cvsserver (Fri Jan 2 16:40:14 2009 +0100) 2 commits
 + cvsserver: change generation of CVS author names
 + cvsserver: add option to configure commit message

* js/maint-bisect-gitk (Fri Jan 2 19:08:00 2009 +0100) 1 commit
 + bisect view: call gitk if Cygwin's SESSIONNAME variable is set

* np/no-loosen-prune-expire-now (Tue Dec 30 14:45:11 2008 -0500) 1 commit
 + objects to be pruned immediately don't have to be loosened

* cb/maint-unpack-trees-absense (Thu Jan 1 21:54:33 2009 +0100) 3 commits
 + unpack-trees: remove redundant path search in verify_absent
 + unpack-trees: fix path search bug in verify_absent
 + unpack-trees: handle failure in verify_absent

* mc/cd-p-pwd (Tue Dec 30 07:10:24 2008 -0800) 1 commit
 + git-sh-setup: Fix scripts whose PWD is a symlink to a work-dir on
   OS X

All of the above are good fixes and clean-ups; will be fast-tracked to
'master' and maintenance branches as appropriate.

* mv/apply-parse-opt (Sun Dec 28 00:03:57 2008 +0100) 1 commit
 + parse-opt: migrate builtin-apply.

* mh/cherry-default (Thu Jan 1 22:56:29 2009 +0100) 2 commits
 + Documentation: clarify which parameters are optional to git-cherry
 + git-cherry: make <upstream> parameter optional

* rs/maint-shortlog-foldline (Mon Dec 29 23:15:50 2008 +0100) 1 commit
 - [Need tidying up the log] pretty: support multiline subjects with
   format:

* tr/rebase-root (Fri Jan 2 23:28:29 2009 +0100) 4 commits
 - rebase: update documentation for --root
 - rebase -i: learn to rebase root commit
 - rebase: learn to rebase root commit
 - rebase -i: execute hook only after argument checking

I should be able to find time to read this over again and merge to
'next' sometime this week.

* as/autocorrect-alias (Sun Jan 4 18:16:01 2009 +0100) 1 commit
 + git.c: make autocorrected aliases work

* as/commit-signoff (Mon Dec 29 12:16:45 2008 +0100) 1 commit
 - [WIP] Add a commit.signoff configuration option to always use --
   signoff in commit

----------------------------------------------------------------
[Stalled and may need help and prodding to go forward]

* wp/add-patch-find (Thu Nov 27 04:08:03 2008 +0000) 3 commits
 . In add --patch, Handle K,k,J,j slightly more gracefully.
 . Add / command in add --patch
 . git-add -i/-p: Change prompt separater from slash to comma

Will discard and wait for a resubmit.

* kb/am-directory (Fri Aug 29 15:27:50 2008 -0700) 1 commit
 . git-am: Pass the --directory option through to git-apply

A reroll of this by Simon Schubert triggered a series to fix a parameter
propagation bug, and another reroll to add "git am --directory=path/"
should be much easier now.  I am not likely to use the feature myself, so
it is up to intrested volunteers to carry it forward.

* ds/uintmax-config (Mon Nov 3 09:14:28 2008 -0900) 1 commit
 - autoconf: Enable threaded delta search when pthreads are supported

This automatically enables threaded delta search code when autoconf
detects pthreads are usable.  I haven't heard neither positive nor
negative comments from minority platforms that might be harmed, but
this feels like the right thing to do, so perhaps the best course of
action is to merge this down to 'master' and see if anybody screams.

* jc/blame (Wed Jun 4 22:58:40 2008 -0700) 2 commits
 + blame: show "previous" information in --porcelain/--incremental
   format
 + git-blame: refactor code to emit "porcelain format" output

This gives Porcelains (like gitweb) the information on the commit _before_
the one that the final blame is laid on, which should save them one
rev-parse to dig further.  The line number in the "previous" information
may need refining, and sanity checking code for reference counting may
need to be resurrected before this can move forward.

----------------------------------------------------------------
[Actively cooking]

* nd/grep-assume-unchanged (Sat Dec 27 15:21:03 2008 +0700) 2 commits
 + grep: grep cache entries if they are "assume unchanged"
 + grep: support --no-ext-grep to test builtin grep

* as/maint-shortlog-cleanup (Tue Dec 30 22:01:44 2008 +0100) 1 commit
 + builtin-shortlog.c: use string_list_append(), and don't strdup
   unnecessarily

* jc/maint-ls-tree (Wed Dec 31 19:00:50 2008 +0900) 2 commits
 + Document git-ls-tree --full-tree
 + ls-tree: add --full-tree option

* js/notes (Sat Dec 20 13:06:03 2008 +0100) 4 commits
 - Add an expensive test for git-notes
 - Speed up git notes lookup
 - Add a script to edit/inspect notes
 - Introduce commit notes

* sc/gitweb-category (Fri Dec 12 00:45:12 2008 +0100) 3 commits
 - gitweb: Optional grouping of projects by category
 - gitweb: Split git_project_list_body in two functions
 - gitweb: Modularized git_get_project_description to be more generic

* gb/gitweb-patch (Thu Dec 18 08:13:19 2008 +0100) 4 commits
 - gitweb: link to patch(es) view in commit(diff) and (short)log view
 - gitweb: add patches view
 - gitweb: change call pattern for git_commitdiff
 - gitweb: add patch view

----------------------------------------------------------------
[Graduated to "master"]

* cb/mergetool (Fri Dec 12 21:48:41 2008 +0000) 4 commits
 + mergetool: Don't keep temporary merge files unless told to
 + mergetool: Add prompt to continue after failing to merge a file
 + Add -y/--no-prompt option to mergetool
 + Fix some tab/space inconsistencies in git-mergetool.sh

----------------------------------------------------------------
[Will merge to "master" soon]

* mh/maint-sendmail-cc-doc (Mon Dec 29 00:37:25 2008 +0100) 1 commit
 + doc/git-send-email: mention sendemail.cc config variable

* rs/diff-ihc (Sun Dec 28 19:45:32 2008 +0100) 1 commit
 + diff: add option to show context between close hunks

* js/maint-merge-recursive-r-d-conflict (Mon Dec 22 23:10:20 2008 +0100) 1 commit
 + merge-recursive: mark rename/delete conflict as unmerged

* mk/gitweb-feature (Mon Dec 15 22:16:19 2008 -0800) 1 commit
 + gitweb: unify boolean feature subroutines

* cb/merge-recursive-fix (Mon Dec 15 02:41:24 2008 -0800) 3 commits
 + Merge branch 'cb/maint-merge-recursive-fix' into cb/merge-
   recursive-fix
 + merge-recursive: do not clobber untracked working tree garbage
 + modify/delete conflict resolution overwrites untracked file

* cb/maint-merge-recursive-fix (Sun Dec 14 19:40:09 2008 -0800) 2 commits
 + merge-recursive: do not clobber untracked working tree garbage
 + modify/delete conflict resolution overwrites untracked file

* wp/add-p-goto (Thu Dec 4 10:22:40 2008 +0000) 2 commits
 + Add 'g' command to go to a hunk
 + Add subroutine to display one-line summary of hunks

* jn/gitweb-blame (Thu Dec 11 01:33:29 2008 +0100) 3 commits
 + gitweb: cache $parent_commit info in git_blame()
 + gitweb: A bit of code cleanup in git_blame()
 + gitweb: Move 'lineno' id from link to row element in git_blame

* mv/um-pdf (Wed Dec 10 23:44:50 2008 +0100) 1 commit
 + Add support for a pdf version of the user manual

* kk/maint-http-push (Tue Dec 23 11:31:15 2008 +0300) 1 commit
 + http-push: support full URI in handle_remote_ls_ctx()

----------------------------------------------------------------
[On Hold]

* nd/narrow (Sun Nov 30 17:54:38 2008 +0700) 17 commits
 - wt-status: show sparse checkout info
 - Introduce default sparse patterns (core.defaultsparse)
 - checkout: add new options to support sparse checkout
 - clone: support sparse checkout with --sparse-checkout option
 - unpack_trees(): add support for sparse checkout
 - unpack_trees(): keep track of unmerged entries
 - Introduce "sparse patterns"
 - Merge branch 'master' into nd/narrow
 - t2104: touch portability fix
 - grep: skip files outside sparse checkout area
 - checkout_entry(): CE_NO_CHECKOUT on checked out entries.
 - Prevent diff machinery from examining worktree outside sparse
   checkout
 - ls-files: Add tests for --sparse and friends
 - update-index: add --checkout/--no-checkout to update
   CE_NO_CHECKOUT bit
 - update-index: refactor mark_valid() in preparation for new options
 - ls-files: add options to support sparse checkout
 - Introduce CE_NO_CHECKOUT bit

Will drop shortly, but there may be some other fixes to CE_VALID, like
nd/grep-assume-unchanged topic above, that we may want to resurrect.

* jc/clone-symref-2 (Sat Nov 29 23:38:21 2008 -0800) 7 commits
 - clone: test the new HEAD detection logic
 - Merge commit 'HEAD@{2}' into HEAD
 - upload-pack: send the HEAD information
 - clone: find the current branch more explicitly
 - connect.c::read_extra_info(): find where HEAD points at
 - connect.c::read_extra_info(): prepare to receive more than server
   capabilities
 - get_remote_heads(): refactor code to read "server capabilities"

An attempt to extend the fetch protocol to make the logic to detect where
HEAD on the origin site points to more robust.  Will drop shortly as the
protocol extension was not very popular.

* cc/bisect-replace (Mon Nov 24 22:20:30 2008 +0100) 9 commits
 - bisect: add "--no-replace" option to bisect without using replace
   refs
 - rev-list: make it possible to disable replacing using "--no-
   bisect-replace"
 - bisect: use "--bisect-replace" options when checking merge bases
 - merge-base: add "--bisect-replace" option to use fixed up revs
 - commit: add "bisect_replace_all" prototype to "commit.h"
 - rev-list: add "--bisect-replace" to list revisions with fixed up
   history
 - Documentation: add "git bisect replace" documentation
 - bisect: add test cases for "git bisect replace"
 - bisect: add "git bisect replace" subcommand

Will drop and replace it with the resubmitted series when it comes.

* jc/send-pack-tell-me-more (Thu Mar 20 00:44:11 2008 -0700) 1 commit
 - "git push": tellme-more protocol extension

This seems to have a deadlock during communication between the peers.
Will drop shortly.

* jk/renamelimit (Sat May 3 13:58:42 2008 -0700) 1 commit
 - diff: enable "too large a rename" warning when -M/-C is explicitly
   asked for

This would be the right thing to do for command line use,
but gitk will be hit due to tcl/tk's limitation, so I am holding
this back for now.

* jc/stripspace (Sun Mar 9 00:30:35 2008 -0800) 6 commits
 - git-am --forge: add Signed-off-by: line for the author
 - git-am: clean-up Signed-off-by: lines
 - stripspace: add --log-clean option to clean up signed-off-by:
   lines
 - stripspace: use parse_options()
 - Add "git am -s" test
 - git-am: refactor code to add signed-off-by line for the committer

^ permalink raw reply	[relevance 4%]

* Re: [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
  2009-01-01 22:18  8%                     ` Adeodato Simó
@ 2009-01-02 12:46  8%                       ` Adeodato Simó
  0 siblings, 0 replies; 171+ results
From: Adeodato Simó @ 2009-01-02 12:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

* Adeodato Simó [Thu, 01 Jan 2009 23:18:17 +0100]:

> * Junio C Hamano [Tue, 30 Dec 2008 13:04:13 -0800]:

> > They actually started making me think
> > that commmit.signoff might be more trouble than it is worth.

> I am beginning to think the same myself, and I'm okay with letting go.
> If somebody has a sensible plan, I can invest some time on implementing
> it, but I'll reckon it all tastes too messy at the moment.

> Thanks for your time.

Oh, I see you merged the last version into pu. I don't know if that
means it'd be bad for me to abandon now, but as said, if somebody helps
me figure out things, I'm open to continue working on it.

I just don't want to be pushing for inclusion of something of
sub-standard (UI) quality.

Cheers,

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
Will you just stand still?
                -- Luke Danes

^ permalink raw reply	[relevance 8%]

* Re: [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
  2008-12-30 21:04 14%                   ` Junio C Hamano
@ 2009-01-01 22:18  8%                     ` Adeodato Simó
  2009-01-02 12:46  8%                       ` Adeodato Simó
  0 siblings, 1 reply; 171+ results
From: Adeodato Simó @ 2009-01-01 22:18 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

* Junio C Hamano [Tue, 30 Dec 2008 13:04:13 -0800]:

> They actually started making me think
> that commmit.signoff might be more trouble than it is worth.

I am beginning to think the same myself, and I'm okay with letting go.
If somebody has a sensible plan, I can invest some time on implementing
it, but I'll reckon it all tastes too messy at the moment.

Thanks for your time.

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
                                     Listening to: Vanessa-Mae - Leyenda

^ permalink raw reply	[relevance 8%]

* Re: [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
  2008-12-29 11:16 21%                 ` [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit Adeodato Simó
  2008-12-29 11:18  8%                   ` Adeodato Simó
@ 2008-12-30 21:04 14%                   ` Junio C Hamano
  2009-01-01 22:18  8%                     ` Adeodato Simó
  1 sibling, 1 reply; 171+ results
From: Junio C Hamano @ 2008-12-30 21:04 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git

Adeodato Simó <dato@net.com.org.es> writes:

> diff --git a/builtin-revert.c b/builtin-revert.c
> index d48313c..395c7a5 100644
> --- a/builtin-revert.c
> +++ b/builtin-revert.c
> @@ -429,6 +429,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
>  		args[i++] = "-n";
>  		if (signoff)
>  			args[i++] = "-s";
> +		else
> +			args[i++] = "--no-signoff";
>  		if (!edit) {
>  			args[i++] = "-F";
>  			args[i++] = defmsg;

Introduction of --no-commit to "git commit" is absolutely necessary for
interactive users if we were to introduce commit.signoff, but I am not
sure about this change and similar ones given to the other Porcelain
commands that use "git commit".  They actually started making me think
that commmit.signoff might be more trouble than it is worth.

It is plausible that your workflow is to have others push to your 'mob'
branch and integrating good bits from there by cherry-picking, sort of
like using the 'mob' branch as if they are e-mailed patches.  In such a
setup, if you are so forgetful to type "-s" for your commit that you would
want commit.signoff configuration, you would likely to be equally
forgetful to type "-s" for your cherry-pick, and would want to have some
configuration affect how this part of the code works.

I however moderately doubt if the complexity and flexibility of having
rebase.signoff, revert.signoff, and cherry-pick.signoff as independent
options is worth it.  I am inclined to think that is too many knobs to
tweak, and it is far simpler to understand and easier to explain if the
single configuration, commit.signoff, applied to every Porcelain that
creates commits.

If we were to go that route, instead of passing --no-signoff when they
invoke "git commit", these commands need to take their own --no-signoff
option instead, and when neither --signoff nor --no-signoff is given, they
just should just invoke "git commit" and let it use the config (if set).

^ permalink raw reply	[relevance 14%]

* Re: [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
  2008-12-29 11:16 21%                 ` [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit Adeodato Simó
@ 2008-12-29 11:18  8%                   ` Adeodato Simó
  2008-12-30 21:04 14%                   ` Junio C Hamano
  1 sibling, 0 replies; 171+ results
From: Adeodato Simó @ 2008-12-29 11:18 UTC (permalink / raw)
  To: git, gitster

>  Changes since v2:

(Updating git-rebase--interactive.sh is still missing, I know.)

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
He who has not a good memory should never take upon himself the trade of lying.
                -- Michel de Montaigne

^ permalink raw reply	[relevance 8%]

* [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
  2008-12-27 12:01  7%               ` Adeodato Simó
@ 2008-12-29 11:16 21%                 ` Adeodato Simó
  2008-12-29 11:18  8%                   ` Adeodato Simó
  2008-12-30 21:04 14%                   ` Junio C Hamano
  0 siblings, 2 replies; 171+ results
From: Adeodato Simó @ 2008-12-29 11:16 UTC (permalink / raw)
  To: git, gitster; +Cc: Adeodato Simó

The intent is that it only applies when the user runs `git commit`
themselves, hence a number of commands (rebase and revert/cherry-pick)
have started passing --no-signoff when invoking commit.

Signed-off-by: Adeodato Simó <dato@net.com.org.es>
---

Hello, I've worked a bit more on this patch, and I'd like to know if
it's going in a good direction or not. Changes since v2:

 t/t7500-commit.sh        |   22 ++++++++++++++++++++++

   * add tests to check that commit.signoff works correctly, and that 
     is overriden by --no-signoff

 git-rebase.sh            |    2 +-
 t/t3402-rebase-merge.sh  |    6 +++++-

   * make git-rebase pass --no-signoff when invoking `git commit`, and
     add a test for it
   
 builtin-revert.c         |    2 ++

   * make revert/cherry-pick pass --no-signoff unless -s was given by
     the user (missing test)
   
 Documentation/config.txt |    4 ++--

   * improve config.txt wording as per <20081227120128.GA11322@chistera.yi.org>

(I don't know if it's customary to send a diff from v2 to v3, if it is
please let me know.)

Thanks,

 Documentation/config.txt     |    9 +++++++++
 Documentation/git-commit.txt |    3 ++-
 builtin-commit.c             |    5 +++++
 builtin-revert.c             |    2 ++
 git-rebase.sh                |    2 +-
 t/t3402-rebase-merge.sh      |    6 +++++-
 t/t7500-commit.sh            |   22 ++++++++++++++++++++++
 7 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 52786c7..13f2200 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -591,6 +591,15 @@ color.ui::
 commit.template::
 	Specify a file to use as the template for new commit messages.
 
+commit.signoff::
+	If set, 'git commit' will behave as if '-s' option was given.
+	Please use this option with care: by enabling it globally, you'd
+	be stating that all your commits will invariably meet the S-o-b
+	requirements for any project you send patches to. It's probably
+	best to only use it from your private repositories' .git/config
+	file, and only for projects who require a S-o-b as proof of
+	provenance of the patch, and not of its correctness or quality.
+
 diff.autorefreshindex::
 	When using 'git-diff' to compare with work tree
 	files, do not consider stat-only change as changed.
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index b5d81be..abab839 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -96,7 +96,8 @@ OPTIONS
 -s::
 --signoff::
 	Add Signed-off-by line by the committer at the end of the commit
-	log message.
+	log message. This overrides the `commit.signoff` configuration
+	variable.
 
 -n::
 --no-verify::
diff --git a/builtin-commit.c b/builtin-commit.c
index e88b78f..fc09539 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -929,6 +929,11 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 	if (!strcmp(k, "commit.template"))
 		return git_config_string(&template_file, k, v);
 
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
+
 	return git_status_config(k, v, cb);
 }
 
diff --git a/builtin-revert.c b/builtin-revert.c
index d48313c..395c7a5 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -429,6 +429,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 		args[i++] = "-n";
 		if (signoff)
 			args[i++] = "-s";
+		else
+			args[i++] = "--no-signoff";
 		if (!edit) {
 			args[i++] = "-F";
 			args[i++] = defmsg;
diff --git a/git-rebase.sh b/git-rebase.sh
index ebd4df3..bf520d0 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -63,7 +63,7 @@ continue_merge () {
 	cmt=`cat "$dotest/current"`
 	if ! git diff-index --quiet --ignore-submodules HEAD --
 	then
-		if ! git commit --no-verify -C "$cmt"
+		if ! git commit --no-verify --no-signoff -C "$cmt"
 		then
 			echo "Commit failed, please do not call \"git commit\""
 			echo "directly, but instead do one of the following: "
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index 7b7d072..bd2d08c 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -41,7 +41,8 @@ test_expect_success setup '
 	git branch test-rebase side &&
 	git branch test-rebase-pick side &&
 	git branch test-reference-pick side &&
-	git checkout -b test-merge side
+	git checkout -b test-merge side &&
+	git config commit.signoff true
 '
 
 test_expect_success 'reference merge' '
@@ -54,6 +55,9 @@ test_expect_success rebase '
 	GIT_TRACE=1 git rebase --merge master
 '
 
+test_expect_success 'rebase uses --no-signoff' '
+	!(git log | grep -q Signed-off-by)'
+
 test_expect_success 'test-rebase@{1} is pre rebase' '
 	test $PRE_REBASE = $(git rev-parse test-rebase@{1})
 '
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 6e18a96..c7deb3e 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -147,6 +147,10 @@ zort
 Signed-off-by: C O Mitter <committer@example.com>
 EOF
 
+cat > expect_no_signoff << EOF
+zort
+EOF
+
 test_expect_success '--signoff' '
 	echo "yet another content *narf*" >> foo &&
 	echo "zort" | (
@@ -157,6 +161,24 @@ test_expect_success '--signoff' '
 	test_cmp expect output
 '
 
+test_expect_success 'commit.signoff' '
+	echo "and more content" >> foo &&
+	git config commit.signoff true &&
+	echo "zort" | git commit -F - foo &&
+	git config --unset commit.signoff &&
+	git cat-file commit HEAD | sed "1,/^$/d" > output &&
+	test_cmp expect output
+'
+
+test_expect_success '--no-signoff trumps commit.signoff' '
+	echo "and even more" >> foo &&
+	git config commit.signoff true &&
+	echo "zort" | git commit --no-signoff -F - foo &&
+	git config --unset commit.signoff &&
+	git cat-file commit HEAD | sed "1,/^$/d" > output &&
+	test_cmp expect_no_signoff output
+'
+
 test_expect_success 'commit message from file (1)' '
 	mkdir subdir &&
 	echo "Log in top directory" >log &&
-- 
1.6.1.307.g07803

^ permalink raw reply related	[relevance 21%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-27 18:40  7%   ` Adeodato Simó
@ 2008-12-27 19:15  7%     ` Jan Krüger
  0 siblings, 0 replies; 171+ results
From: Jan Krüger @ 2008-12-27 19:15 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, gitster

Hi,

On Sat, 27 Dec 2008 19:40:01 +0100
"Adeodato Simó" <dato@net.com.org.es> wrote:

> > I think it might be a good idea to allow overriding the config
> > variable in the other direction, i.e. a --no-signoff option to
> > commit. [...]
> 
> Good catch.
> 
> --no-signoff exists already, so maybe git-rebase should just use it?

Oh, yeah, I didn't notice the option mechanism worked this way and the
options got parsed after processing the config variables. I guess
rebase and rebase--interactive should use it, then, and perhaps there
are other commands that should that I just don't know about (a grep
across all commands implemented in shell script didn't find anything
else, though).

-Jan

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-27 18:08  7% ` [PATCH] Add a commit.signoff configuration variable to always use --signoff Jan Krüger
@ 2008-12-27 18:40  7%   ` Adeodato Simó
  2008-12-27 19:15  7%     ` Jan Krüger
  0 siblings, 1 reply; 171+ results
From: Adeodato Simó @ 2008-12-27 18:40 UTC (permalink / raw)
  To: Jan Krüger; +Cc: git, gitster

* Jan Krüger [Sat, 27 Dec 2008 19:08:19 +0100]:

> I think it might be a good idea to allow overriding the config variable
> in the other direction, i.e. a --no-signoff option to commit. Otherwise,
> for example, rebase would have no way of suppressing the S-o-b lines in
> rebased commits (and you might want to not automatically sign off
> commits you rebase).

Good catch.

--no-signoff exists already, so maybe git-rebase should just use it?

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
Man is certainly stark mad; he cannot make a flea, yet he makes gods by the
dozens.
                -- Michel de Montaigne

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-26 12:56 15% [PATCH] Add a commit.signoff configuration variable to always use --signoff Adeodato Simó
  2008-12-26 22:02  7% ` Nanako Shiraishi
@ 2008-12-27 18:08  7% ` Jan Krüger
  2008-12-27 18:40  7%   ` Adeodato Simó
  1 sibling, 1 reply; 171+ results
From: Jan Krüger @ 2008-12-27 18:08 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, gitster

Hi,

On Fri, 26 Dec 2008 13:56:59 +0100
"Adeodato Simó" <dato@net.com.org.es> wrote:

> > Has there even been talk of a commit.signoff configuration variable
> > to always add a S-o-b line? This could allow to enable it on a
> > per-project basis, which would be cool.
> 
> Well, it seemed easy enough to do, so I went ahead. Comments would be
> welcome.

I think it might be a good idea to allow overriding the config variable
in the other direction, i.e. a --no-signoff option to commit. Otherwise,
for example, rebase would have no way of suppressing the S-o-b lines in
rebased commits (and you might want to not automatically sign off
commits you rebase).

-Jan

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff
  2008-12-27 11:53  7%             ` Junio C Hamano
@ 2008-12-27 12:01  7%               ` Adeodato Simó
  2008-12-29 11:16 21%                 ` [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit Adeodato Simó
  0 siblings, 1 reply; 171+ results
From: Adeodato Simó @ 2008-12-27 12:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

* Junio C Hamano [Sat, 27 Dec 2008 03:53:47 -0800]:

> Adeodato Simó <dato@net.com.org.es> writes:

> > +commit.signoff::
> > +	If set, 'git commit' will behave as if '-s' option was given.
> > +	Please use this option with care: by enabling it, you're stating
> > +	that all your commits will invariably meet the S-o-b
> > +	requirements for any project you send patches to. It's probably

> This is true only if you set it in your global configuration.  A more sane
> usage would be to have it per repository as you recommend in a later
> sentence, and "for any project" part is untrue when the reader does so.

How about:

  Please use this option with care: by enabling it globally, you'd be
  stating...

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
                              Listening to: Niza - Solsticio de invierno

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff
  2008-12-27  9:03 14%           ` Adeodato Simó
  2008-12-27 11:04  7%             ` Thomas Rast
@ 2008-12-27 11:53  7%             ` Junio C Hamano
  2008-12-27 12:01  7%               ` Adeodato Simó
  1 sibling, 1 reply; 171+ results
From: Junio C Hamano @ 2008-12-27 11:53 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git

Adeodato Simó <dato@net.com.org.es> writes:

> +commit.signoff::
> +	If set, 'git commit' will behave as if '-s' option was given.
> +	Please use this option with care: by enabling it, you're stating
> +	that all your commits will invariably meet the S-o-b
> +	requirements for any project you send patches to. It's probably

This is true only if you set it in your global configuration.  A more sane
usage would be to have it per repository as you recommend in a later
sentence, and "for any project" part is untrue when the reader does so.

> diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
> index b5d81be..abab839 100644
> --- a/Documentation/git-commit.txt
> +++ b/Documentation/git-commit.txt
> @@ -96,7 +96,8 @@ OPTIONS
>  -s::
>  --signoff::
>  	Add Signed-off-by line by the committer at the end of the commit
> -	log message.
> +	log message. This overrides the `commit.signoff` configuration
> +	variable.

Good and careful thinking.  I like it.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff
  2008-12-27 11:04  7%             ` Thomas Rast
@ 2008-12-27 11:05  7%               ` Adeodato Simó
  0 siblings, 0 replies; 171+ results
From: Adeodato Simó @ 2008-12-27 11:05 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, gitster

* Thomas Rast [Sat, 27 Dec 2008 12:04:11 +0100]:

> Adeodato Simó wrote:
> > +commit.signoff::
> > +	If set, 'git commit' will behave as if '-s' option was given.
> > +	Please use this option with care: by enabling it, you're stating
> > +	that all your commits will invariably meet the S-o-b
> > +	requirements for any project you send patches to. It's probably
> > +	best to only use it from your private repositories' .git/config
> > +	file, and only for projects who require a S-o-b as proof of
>                            ^^^^^^^^^^^^

> "projects which ..." or "projects that ...".  "Who" can only stand for
> people, not objects.

Good catch, thank you. Hopefully Junio can amend.

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
                                   Listening to: Miguel Bosé - Puede que

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff
  2008-12-27  9:03 14%           ` Adeodato Simó
@ 2008-12-27 11:04  7%             ` Thomas Rast
  2008-12-27 11:05  7%               ` Adeodato Simó
  2008-12-27 11:53  7%             ` Junio C Hamano
  1 sibling, 1 reply; 171+ results
From: Thomas Rast @ 2008-12-27 11:04 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, gitster

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

Adeodato Simó wrote:
> +commit.signoff::
> +	If set, 'git commit' will behave as if '-s' option was given.
> +	Please use this option with care: by enabling it, you're stating
> +	that all your commits will invariably meet the S-o-b
> +	requirements for any project you send patches to. It's probably
> +	best to only use it from your private repositories' .git/config
> +	file, and only for projects who require a S-o-b as proof of
                           ^^^^^^^^^^^^

"projects which ..." or "projects that ...".  "Who" can only stand for
people, not objects.

> +	provenance of the patch, and not of its correctness or quality.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch






[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[relevance 7%]

* [PATCH] Add a commit.signoff configuration variable to always use --signoff
  2008-12-27  8:44  7%         ` Junio C Hamano
@ 2008-12-27  9:03 14%           ` Adeodato Simó
  2008-12-27 11:04  7%             ` Thomas Rast
  2008-12-27 11:53  7%             ` Junio C Hamano
  0 siblings, 2 replies; 171+ results
From: Adeodato Simó @ 2008-12-27  9:03 UTC (permalink / raw)
  To: git, gitster; +Cc: Adeodato Simó

Signed-off-by: Adeodato Simó <dato@net.com.org.es>
---

* Junio C Hamano [Sat, 27 Dec 2008 00:44:59 -0800]:

> > +commit.signoff::
> > +       If set, 'git-commit' will always add a Signed-off-by line.

> It is not a big deal, but my first reaction to the above was "S-o-b by
> whom?  It misses details and does not say where to find them".

> How about "if set, 'git commit' will behave as if '-s' option was given",
> so that we can leave the details of whose S-o-b line to generate and such
> to the description of "git commit -s" manual page?

Changed.

> > I'll send an amended patch (or should I send an incremental/extra
> > one instead?)

I didn't get an answer to this, so I'm sending an amended one, hoping
that's the correct thing to do in this land.

> Another problem that you seem to have missed about M-F-T is that while you
> solicited responses from general public by CC'ing the list (which allowed
> me to respond to you), by forcing the response go only to the list, you
> excluded people on the To: and Cc: list of your original message from my
> response.  You required them to be subscribed to the list, if they want to
> be kept in the loop.

No, not really, because Mutt will add to the M-F-T header all addresses
that appear on the To or Cc headers.

 Documentation/config.txt     |    9 +++++++++
 Documentation/git-commit.txt |    3 ++-
 builtin-commit.c             |    5 +++++
 3 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 52786c7..4d0a79b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -591,6 +591,15 @@ color.ui::
 commit.template::
 	Specify a file to use as the template for new commit messages.
 
+commit.signoff::
+	If set, 'git commit' will behave as if '-s' option was given.
+	Please use this option with care: by enabling it, you're stating
+	that all your commits will invariably meet the S-o-b
+	requirements for any project you send patches to. It's probably
+	best to only use it from your private repositories' .git/config
+	file, and only for projects who require a S-o-b as proof of
+	provenance of the patch, and not of its correctness or quality.
+
 diff.autorefreshindex::
 	When using 'git-diff' to compare with work tree
 	files, do not consider stat-only change as changed.
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index b5d81be..abab839 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -96,7 +96,8 @@ OPTIONS
 -s::
 --signoff::
 	Add Signed-off-by line by the committer at the end of the commit
-	log message.
+	log message. This overrides the `commit.signoff` configuration
+	variable.
 
 -n::
 --no-verify::
diff --git a/builtin-commit.c b/builtin-commit.c
index e88b78f..fc09539 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -929,6 +929,11 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 	if (!strcmp(k, "commit.template"))
 		return git_config_string(&template_file, k, v);
 
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
+
 	return git_status_config(k, v, cb);
 }
 
-- 
1.6.1.307.g07803

^ permalink raw reply related	[relevance 14%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-27  8:26 11%       ` Adeodato Simó
@ 2008-12-27  8:44  7%         ` Junio C Hamano
  2008-12-27  9:03 14%           ` Adeodato Simó
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2008-12-27  8:44 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, Johannes Schindelin

Adeodato Simó <dato@net.com.org.es> writes:

> Does this sound good? If so, I'll send an amended patch (or should I send an
> incremental/extra one instead?):
>
> +commit.signoff::
> +       If set, 'git-commit' will always add a Signed-off-by line.

It is not a big deal, but my first reaction to the above was "S-o-b by
whom?  It misses details and does not say where to find them".

How about "if set, 'git commit' will behave as if '-s' option was given",
so that we can leave the details of whose S-o-b line to generate and such
to the description of "git commit -s" manual page?

> +       Please use this option with care: by enabling it, you're stating
> +       that all your commits will invariably meet the S-o-b
> +       requirements for any project you send patches to. It's probably
> +       best to only use it from your private repositories' .git/config
> +       file, and only for projects who require a S-o-b as proof of
> +       provenance of the patch, and not of its correctness or quality.

Yeah, many projects do not even have S-o-b convention.

>> By the way, please do not deflect away responses meant to you by using a
>> Mail-Followup-To header that points at the git mailing list.  It is rude.
>
> I set a M-F-T header because I prefer not to be CC'ed. I have other
> mechanisms in place that prevent me from missing replies to my messages
> (based on In-Reply-To/References headers).
>
> Nevertheless, if the list normally operates CC-based, I can see how pressing
> Reply-to-all and not seing the original autor in the recipient list can be
> offputting, so I'll stop setting M-F-T in my messages to git@. (Hopefully
> starting with this message already.)

Thanks.

Another problem that you seem to have missed about M-F-T is that while you
solicited responses from general public by CC'ing the list (which allowed
me to respond to you), by forcing the response go only to the list, you
excluded people on the To: and Cc: list of your original message from my
response.  You required them to be subscribed to the list, if they want to
be kept in the loop.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-27  0:36  7%     ` Junio C Hamano
@ 2008-12-27  8:26 11%       ` Adeodato Simó
  2008-12-27  8:44  7%         ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Adeodato Simó @ 2008-12-27  8:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes Schindelin

* Junio C Hamano [Fri, 26 Dec 2008 16:36:38 -0800]:

> Adeodato Simó <dato@net.com.org.es> writes:

> > ... I'd
> > still like to hear if my patch would be suitable for inclusion, because
> > it's much more straightforward to use (and to discover).

> But "straightforward to discover" is not an advantage in this case.

> As long as it comes with documentation that clearly explains why this
> feature should not be used blindly in order to avoid diluting the value of
> S-o-b, I think the feature itself is not a harmful thing to have.  Dscho's
> argument in the quoted thread that says it should be a conscious act to
> add S-o-b (except for the part he misunderstands what S-o-b attests), is a
> good one and still is valid.

Does this sound good? If so, I'll send an amended patch (or should I send an
incremental/extra one instead?):

+commit.signoff::
+       If set, 'git-commit' will always add a Signed-off-by line.
+       Please use this option with care: by enabling it, you're stating
+       that all your commits will invariably meet the S-o-b
+       requirements for any project you send patches to. It's probably
+       best to only use it from your private repositories' .git/config
+       file, and only for projects who require a S-o-b as proof of
+       provenance of the patch, and not of its correctness or quality.

> By the way, please do not deflect away responses meant to you by using a
> Mail-Followup-To header that points at the git mailing list.  It is rude.

I set a M-F-T header because I prefer not to be CC'ed. I have other
mechanisms in place that prevent me from missing replies to my messages
(based on In-Reply-To/References headers).

Nevertheless, if the list normally operates CC-based, I can see how pressing
Reply-to-all and not seing the original autor in the recipient list can be
offputting, so I'll stop setting M-F-T in my messages to git@. (Hopefully
starting with this message already.)

I didn't mean for it to be rude in any way.

Thanks,

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
A conference is a gathering of important people who singly can do nothing
but together can decide that nothing can be done.
                -- Fred Allen

^ permalink raw reply	[relevance 11%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-26 22:10  7%   ` Adeodato Simó
@ 2008-12-27  0:36  7%     ` Junio C Hamano
  2008-12-27  8:26 11%       ` Adeodato Simó
  0 siblings, 1 reply; 171+ results
From: Junio C Hamano @ 2008-12-27  0:36 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git, Johannes Schindelin

Adeodato Simó <dato@net.com.org.es> writes:

> ... I'd
> still like to hear if my patch would be suitable for inclusion, because
> it's much more straightforward to use (and to discover).

But "straightforward to discover" is not an advantage in this case.

As long as it comes with documentation that clearly explains why this
feature should not be used blindly in order to avoid diluting the value of
S-o-b, I think the feature itself is not a harmful thing to have.  Dscho's
argument in the quoted thread that says it should be a conscious act to
add S-o-b (except for the part he misunderstands what S-o-b attests), is a
good one and still is valid.

By the way, please do not deflect away responses meant to you by using a
Mail-Followup-To header that points at the git mailing list.  It is rude.

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-26 22:02  7% ` Nanako Shiraishi
@ 2008-12-26 22:10  7%   ` Adeodato Simó
  2008-12-27  0:36  7%     ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Adeodato Simó @ 2008-12-26 22:10 UTC (permalink / raw)
  To: git

* Nanako Shiraishi [Sat, 27 Dec 2008 07:02:28 +0900]:

> There was a discussion in
> "http://thread.gmane.org/gmane.comp.version-control.git/32503/focus=32522"
> about automatically adding S-o-b line.

Ah, thanks for the pointer.

> Even though Junio said in his response "it certainly is a
> possibility", another solution that he referred to as "cleaner and
> more useful" in his message was made available in version 1.5.3 after
> this discussion.

Oh, a template file? I certainly hadn't thought of that, though I'd
still like to hear if my patch would be suitable for inclusion, because
it's much more straightforward to use (and to discover).

Thanks,

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
- I love you, Shirley, I'm not ashamed to say.
- If you love me, then you'll want me to be happy. Even if I'm not with you.
- I don't love you that much.
                -- Denny Crane and Shirley Schmidt

^ permalink raw reply	[relevance 7%]

* Re: [PATCH] Add a commit.signoff configuration variable to always use --signoff.
  2008-12-26 12:56 15% [PATCH] Add a commit.signoff configuration variable to always use --signoff Adeodato Simó
@ 2008-12-26 22:02  7% ` Nanako Shiraishi
  2008-12-26 22:10  7%   ` Adeodato Simó
  2008-12-27 18:08  7% ` [PATCH] Add a commit.signoff configuration variable to always use --signoff Jan Krüger
  1 sibling, 1 reply; 171+ results
From: Nanako Shiraishi @ 2008-12-26 22:02 UTC (permalink / raw)
  To: Adeodato Simó; +Cc: git

Quoting Adeodato Simó <dato@net.com.org.es>:

> I wrote:
>> Has there even been talk of a commit.signoff configuration variable
>> to always add a S-o-b line? This could allow to enable it on a
>> per-project basis, which would be cool.

There was a discussion in "http://thread.gmane.org/gmane.comp.version-control.git/32503/focus=32522" about automatically adding S-o-b line.

Even though Junio said in his response "it certainly is a possibility", another solution that he referred to as "cleaner and more useful" in his message was made available in version 1.5.3 after this discussion.

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

^ permalink raw reply	[relevance 7%]

* [PATCH] Add a commit.signoff configuration variable to always use --signoff.
@ 2008-12-26 12:56 15% Adeodato Simó
  2008-12-26 22:02  7% ` Nanako Shiraishi
  2008-12-27 18:08  7% ` [PATCH] Add a commit.signoff configuration variable to always use --signoff Jan Krüger
  0 siblings, 2 replies; 171+ results
From: Adeodato Simó @ 2008-12-26 12:56 UTC (permalink / raw)
  To: git, gitster

Signed-off-by: Adeodato Simó <dato@net.com.org.es>
---
I wrote:
> Has there even been talk of a commit.signoff configuration variable
> to always add a S-o-b line? This could allow to enable it on a
> per-project basis, which would be cool.

Well, it seemed easy enough to do, so I went ahead. Comments would be
welcome.

 Documentation/config.txt     |    6 ++++++
 Documentation/git-commit.txt |    3 ++-
 builtin-commit.c             |    5 +++++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 52786c7..6d195a3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -591,6 +591,12 @@ color.ui::
 commit.template::
 	Specify a file to use as the template for new commit messages.
 
+commit.signoff::
+	If set, 'git-commit' will always add a Signed-off-by line. If
+	you don't want it always active, you can still set it in the
+	repository specific configuration file for projects that require
+	a Signed-off-by line for all commits.
+
 diff.autorefreshindex::
 	When using 'git-diff' to compare with work tree
 	files, do not consider stat-only change as changed.
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index b5d81be..abab839 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -96,7 +96,8 @@ OPTIONS
 -s::
 --signoff::
 	Add Signed-off-by line by the committer at the end of the commit
-	log message.
+	log message. This overrides the `commit.signoff` configuration
+	variable.
 
 -n::
 --no-verify::
diff --git a/builtin-commit.c b/builtin-commit.c
index e88b78f..fc09539 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -929,6 +929,11 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 	if (!strcmp(k, "commit.template"))
 		return git_config_string(&template_file, k, v);
 
+	if (!strcmp(k, "commit.signoff")) {
+		signoff = git_config_bool(k, v);
+		return 0;
+	}
+
 	return git_status_config(k, v, cb);
 }
 
-- 
1.6.1.307.g07803

^ permalink raw reply related	[relevance 15%]

* [PATCH] git-shortlog.txt: improve documentation about .mailmap files
  @ 2008-12-26 11:55  3% ` Adeodato Simó
  0 siblings, 0 replies; 171+ results
From: Adeodato Simó @ 2008-12-26 11:55 UTC (permalink / raw)
  To: git, gitster

The previous .mailmap example made it seem like .mailmap files are only
useful for commits with a wrong address for an author, when they are about
fixing the real name. Explained this better in the text, and replaced the
existing example with a new one that hopefully makes things clearer.

Signed-off-by: Adeodato Simó <dato@net.com.org.es>
---

    Now with a Signed-off-by line. Has there even been talk of a 
    commit.signoff configuration variable to always add a S-o-b line? 
    This could allow to enable it on a per-project basis, which would be
    cool.

 Documentation/git-shortlog.txt |   31 ++++++++++++++++++++++++-------
 1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 7ccf31c..69e10a4 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -48,15 +48,32 @@ OPTIONS
 FILES
 -----
 
-If the file `.mailmap` exists, it will be used for mapping author
-email addresses to a real author name. One mapping per line, first
-the author name followed by the email address enclosed by
-'<' and '>'. Use hash '#' for comments. Example:
+If a file `.mailmap` exists in the toplevel directory of the repository,
+it will be used for mapping author email addresses to a canonical real
+name. This can be used to coalesce together commits by the same person
+where their name was spelled differently (whether with the same email
+address or not).
+
+The format of the file is one mapping per line, first the desired author
+name followed by the email address enclosed by '<' and '>'. Use hash '#'
+for comments. For example, if your history contains commits by these
+committers:
+
+------------
+Author: Joe Developer <joe@random.com>
+Author: Joe R. Developer <joe@random.com>
+Author: Jane Doe <jane@the-does.name>
+Author: Jane Doe <jane@laptop.(none)>
+Author: Jane D. <jane@desktop.(none)>
+------------
+
+Then a proper `.mailmap` file would be:
 
 ------------
-# Keep alphabetized
-Adam Morrow <adam@localhost.localdomain>
-Eve Jones <eve@laptop.(none)>
+# Note how we don't need an entry for <jane@laptop.(none)>, because the
+# real name of that author is correct already, and coalesced directly.
+Jane Doe <jane@desktop.(none)>
+Joe R. Developer <joe@random.com>
 ------------
 
 Author
-- 
1.6.1

^ permalink raw reply related	[relevance 3%]

* [PATCH 4/8] bash completion: Add completion for 'git revert'
  @ 2008-08-05  5:50 10%       ` Lee Marlow
  0 siblings, 0 replies; 171+ results
From: Lee Marlow @ 2008-08-05  5:50 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git, Lee Marlow

Added completions for all long options specified in the docs
        --edit --mainline --no-edit --no-commit --signoff

Signed-off-by: Lee Marlow <lee.marlow@gmail.com>
---
 contrib/completion/git-completion.bash |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index c7a6d92..6a5c4cd 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1264,6 +1264,18 @@ _git_reset ()
 	__gitcomp "$(__git_refs)"
 }
 
+_git_revert ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_rm ()
 {
 	__git_has_doubledash && return
@@ -1554,6 +1566,7 @@ _git ()
 	rebase)      _git_rebase ;;
 	remote)      _git_remote ;;
 	reset)       _git_reset ;;
+	revert)      _git_revert ;;
 	rm)          _git_rm ;;
 	send-email)  _git_send_email ;;
 	shortlog)    _git_shortlog ;;
-- 
1.6.0.rc1.48.g2b6032

^ permalink raw reply related	[relevance 10%]

* Re: [PATCH] git-gui: Allow users to set commit.signoff from options.
  2007-07-08 21:48 12% ` Shawn O. Pearce
@ 2007-07-09  7:43  6%   ` Gerrit Pape
  0 siblings, 0 replies; 171+ results
From: Gerrit Pape @ 2007-07-09  7:43 UTC (permalink / raw)
  To: Shawn O. Pearce, git

On Sun, Jul 08, 2007 at 05:48:32PM -0400, Shawn O. Pearce wrote:
> Gerrit Pape <pape@smarden.org> wrote:
> > Users may want to automatically sign-off any commit for a specific
> > repository.  If they are mostly a git-gui user they should be able to
> > view/set this option from within the git-gui environment, rather than
> > needing to edit a raw text file on their local filesystem.
> 
> Sure.  But your patch to git-gui actually just lets the user set
> the flag, but doesn't make git-gui honor it.  So the user can set
> "Automatically Sign-Off" through git-gui but it will have no effect
> within git-gui (git-gui doesn't use git-commit.sh, it has its own
> pure-Tcl implementation).

Ups, sorry.

> I'm not applying this to git-gui, for the very same reason that
> Junio already gave as to why he won't apply the git-commit.sh patch.
> 
> Within git-gui adding a signoff is either one mouse click (the
> button on the toolbar), a single keystroke (Ctrl-S) or a menu action
> (Commit->Signoff).  Three easy ways to insert the signoff line.
> But it still needs to be a choice from the user, every time they
> make a commit.

Yes, thanks, Gerrit.

^ permalink raw reply	[relevance 6%]

* Re: [PATCH] git-gui: Allow users to set commit.signoff from options.
  2007-07-06 14:46 13% [PATCH] git-gui: Allow users to set commit.signoff from options Gerrit Pape
@ 2007-07-08 21:48 12% ` Shawn O. Pearce
  2007-07-09  7:43  6%   ` Gerrit Pape
  0 siblings, 1 reply; 171+ results
From: Shawn O. Pearce @ 2007-07-08 21:48 UTC (permalink / raw)
  To: Gerrit Pape; +Cc: git

Gerrit Pape <pape@smarden.org> wrote:
> Users may want to automatically sign-off any commit for a specific
> repository.  If they are mostly a git-gui user they should be able to
> view/set this option from within the git-gui environment, rather than
> needing to edit a raw text file on their local filesystem.

Sure.  But your patch to git-gui actually just lets the user set
the flag, but doesn't make git-gui honor it.  So the user can set
"Automatically Sign-Off" through git-gui but it will have no effect
within git-gui (git-gui doesn't use git-commit.sh, it has its own
pure-Tcl implementation).

I'm not applying this to git-gui, for the very same reason that
Junio already gave as to why he won't apply the git-commit.sh patch.

Within git-gui adding a signoff is either one mouse click (the
button on the toolbar), a single keystroke (Ctrl-S) or a menu action
(Commit->Signoff).  Three easy ways to insert the signoff line.
But it still needs to be a choice from the user, every time they
make a commit.
 
-- 
Shawn.

^ permalink raw reply	[relevance 12%]

* [PATCH] git-gui: Allow users to set commit.signoff from options.
@ 2007-07-06 14:46 13% Gerrit Pape
  2007-07-08 21:48 12% ` Shawn O. Pearce
  0 siblings, 1 reply; 171+ results
From: Gerrit Pape @ 2007-07-06 14:46 UTC (permalink / raw)
  To: Shawn O. Pearce, git

Users may want to automatically sign-off any commit for a specific
repository.  If they are mostly a git-gui user they should be able to
view/set this option from within the git-gui environment, rather than
needing to edit a raw text file on their local filesystem.

This was noticed and requested by Josh Triplett through
 http://bugs.debian.org/412776

Signed-off-by: Gerrit Pape <pape@smarden.org>
---
 git-gui.sh     |    1 +
 lib/option.tcl |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/git-gui.sh b/git-gui.sh
index 0096f49..5ded736 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1295,6 +1295,7 @@ set default_config(merge.summary) false
 set default_config(merge.verbosity) 2
 set default_config(user.name) {}
 set default_config(user.email) {}
+set default_config(commit.signoff) false
 
 set default_config(gui.pruneduringfetch) false
 set default_config(gui.trustmtime) false
diff --git a/lib/option.tcl b/lib/option.tcl
index ae19a8f..28208ce 100644
--- a/lib/option.tcl
+++ b/lib/option.tcl
@@ -188,6 +188,7 @@ proc do_options {} {
 		{b merge.summary {Summarize Merge Commits}}
 		{i-1..5 merge.verbosity {Merge Verbosity}}
 		{b merge.diffstat {Show Diffstat After Merge}}
+		{b commit.signoff {Automatically Sign-off}}
 
 		{b gui.trustmtime  {Trust File Modification Timestamps}}
 		{b gui.pruneduringfetch {Prune Tracking Branches During Fetch}}
-- 
1.5.2.1

^ permalink raw reply related	[relevance 13%]

* [PATCH] git-commit: add commit.signoff config option
  @ 2007-07-06 14:45 19% ` Gerrit Pape
  0 siblings, 0 replies; 171+ results
From: Gerrit Pape @ 2007-07-06 14:45 UTC (permalink / raw)
  To: Junio C Hamano, git

Have the commit.signoff boolean config option automatically add a
Signed-off-by: by git-commit, without giving the -s switch explicitly.

Signed-off-by: Gerrit Pape <pape@smarden.org>
---
 git-commit.sh |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/git-commit.sh b/git-commit.sh
index 7a7d19a..b493820 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -275,6 +275,7 @@ $1"
 	esac
 done
 case "$edit_flag" in t) no_edit= ;; esac
+test "$(git config --bool commit.signoff)" != true || signoff=t
 
 ################################################################
 # Sanity check options
-- 
1.5.2.1

^ permalink raw reply related	[relevance 19%]

* Re: [PATCH] Add support for commit.signoff config option
  2006-11-28 12:02 19% [PATCH] Add support for commit.signoff config option Andy Parkins
@ 2006-11-28 20:17  6% ` Junio C Hamano
  0 siblings, 0 replies; 171+ results
From: Junio C Hamano @ 2006-11-28 20:17 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git

Andy Parkins <andyparkins@gmail.com> writes:

> Whether patches require signing off or not is probably a per-project
> setting rather than a per-commit setting.  Therefore as a convenience to
> the user, the commit.signoff setting will automtically add --signoff to
> commits.
>
> Signed-off-by: Andy Parkins <andyparkins@gmail.com>

I muttered something about commit templates which would make
this change a moot point, but independent of that...

> +# Config
> +case "$(git-repo-config --get commit.signoff)" in
> +1|on|yes|true)
> +	signoff=t
> +	;;
> +esac

this is ugly; please use --bool and check only for 'true'.



^ permalink raw reply	[relevance 6%]

* [PATCH] Add support for commit.signoff config option
@ 2006-11-28 12:02 19% Andy Parkins
  2006-11-28 20:17  6% ` Junio C Hamano
  0 siblings, 1 reply; 171+ results
From: Andy Parkins @ 2006-11-28 12:02 UTC (permalink / raw)
  To: git

Whether patches require signing off or not is probably a per-project
setting rather than a per-commit setting.  Therefore as a convenience to
the user, the commit.signoff setting will automtically add --signoff to
commits.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---

 git-commit.sh |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/git-commit.sh b/git-commit.sh
index 81c3a0c..c45af10 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -66,9 +66,7 @@ trap '
 	rm -f "$NEXT_INDEX"
 ' 0
 
-################################################################
-# Command line argument parsing and sanity checking
-
+# Init
 all=
 also=
 only=
@@ -85,6 +83,17 @@ signoff=
 force_author=
 only_include_assumed=
 untracked_files=
+
+# Config
+case "$(git-repo-config --get commit.signoff)" in
+1|on|yes|true)
+	signoff=t
+	;;
+esac
+
+################################################################
+# Command line argument parsing and sanity checking
+
 while case "$#" in 0) break;; esac
 do
 	case "$1" in
-- 
1.4.3.GIT-dirty

^ permalink raw reply related	[relevance 19%]

* [ANNOUNCE] Cogito-0.17.1
@ 2006-03-26 17:56  3% Petr Baudis
  0 siblings, 0 replies; 171+ results
From: Petr Baudis @ 2006-03-26 17:56 UTC (permalink / raw)
  To: git; +Cc: linux-kernel

  Hello,

  cogito-0.17.1 was just released, the next release on the latest stable
line of the Cogito user-friendly Git user interface. Note that the
stable stuff is now happening on the v0.17 branch, just like we did in
the 0.16 times. In addition to that, however, an auto-built
documentation in the man, txt and html format is available in the

	http://www.kernel.org/pub/scm/cogito/cogito-doc.git/

repository. It has the same branch structure as the cogito.git
repository and should also have the same tags if my scripts work
properly. Thanks to Junio for the base version of the script maintaining
this repository.

  So, what's new?

  * Fixed several minor relative path related cg-add and cg-status bugs
  * Fixed cg-add -r not readding cg-rm'd files
  * Fixed support for branch names containing slashes

  * cg-admin-rewritehist - the universal history rewriting tool
  * cg-commit --author
  * cg-commit -p alias for cg-commit --review
  * cg-status -S will show the full contents of the untracked
    directories instead of just the directory name
  * $CG_NORC will make Cogito ignore ~/.cgrc
  * https:// URLs are supported now

  * Several small speed-ups (especially --topo-order in cg-mkpatch)
  * Random documentation updates (most notably cg-ref quick reference)
  * The tutorial script updated


  Who did what:

Dennis Stosberg:
      Cogito: Allow https:// URLs

Jonas Fonseca:
      cg-export: document the -r option
      [PATCH 1/4] Simplify wildcards for match files to be ignored
      [PATCH 2/4] Encode the manpage section in the file name
      [PATCH 3/4] Generate PDF documents using docbook2pdf
      [PATCH 4/4] Add quick reference (cg-ref) to the documentation suite
      Fix multi-paragraph list items in OPTIONS section

Pavel Roskin:
      Use Cogito when possible in the "tutorial" test.
      [PATCH 3/3] Allow the tutorial script to be run by "make test"
      [PATCH 1/3] cg-mv doesn't work with bash 3.1.7 due to excessive quotes
      Clean up after failed "git merge" in the tutorial script

Petr Baudis:
      Refer to cg-branch-add in cg-clone docs and clarify stuff
      Add example usage to cg-clone per jbl's request
      Easier cut'n'paste
      --merge-order is too slow, always use --topo-order
      TODO: branches/with/slashes and cg-clone -a
      Add cg-commit --author, consolidate author documentation
      Update for the modern conflicts handling
      Improve cg-switch -r shortdesc
      Expand the git-mv workarounds description
      cg-merge: Do not fast-forward when doing an octopus
      Fix some relpath-related cg-add and cg-status bugs
      Make cg-commit -p synonymous with --review
      TODO: cg-shelf - shelve changes temporarily
      Generalize the tac stub (cg-mkpatch -> cg-Xlib)
      Generalize pick_author() to pick_id()
      cg-admin-rewritehist - history rewriting swiss knife
      Update the example usage
      Hopefully fix cg-admin-rewritehist -r
      Umm, update year in the (c) notice ;)
      Properly support multiple -r arguments
      Make the main cycle more efficient
      Another optimization - retrieve the commit object only once
      Accept subsections inside the OPTIONS section
      Do not load ~/.cgrc if $CG_NORC is set
      Remove bogus information from cg-patch docs
      Properly document cg-commit --signoff=STRING
      cg-admin-rewritehist --parent-filter for rewriting parent string
      cg-admin-rewritehist --commit-filter for omitting commits
      Reference cg-ref(7) from cogito(7)
      A quick docs pointer and Getting help section update
      cg-status -S will turn dirsquashing off
      Fix cg-add -r not readding removed files
      Use the new ref format when resetting the HEAD file
      Fix support for branch names containing slashes


P.S.: See us at #git @ FreeNode!

  Happy hacking,

-- 
				Petr "Pasky the lousy poet" Baudis
Stuff: http://pasky.or.cz/
Of the 3 great composers Mozart tells us what it's like to be human,
Beethoven tells us what it's like to be Beethoven and Bach tells us
what it's like to be the universe.  -- Douglas Adams

^ permalink raw reply	[relevance 3%]

* [ANNOUNCE] Cogito-0.17
@ 2006-02-27  1:16  4% Petr Baudis
  0 siblings, 0 replies; 171+ results
From: Petr Baudis @ 2006-02-27  1:16 UTC (permalink / raw)
  To: git; +Cc: linux-kernel


		The last winter snow
		leaves but Cogito comes in
		its place, snow-white 0.17
				(*)


  After some random bugfixes I got no more bugreports so this feels
stable enough for a release. The rest of this mail will mostly be
a rehash of the 0.17rc1 announcement; the rc2-to-0.17 bugfixes were
rather dull.

  Huge amount of new features and cool stuff. The highlight is cg-switch
for switching between local branches and massive cg-patch improvements,
but there is plenty of other stuff as well. Read on for more details.

  The notable new stuff includes:

  * cg-switch - Cogito finally gives you the full convenience of
    multiple local branches in a single repository ;)
  * cg-patch -c, -C, -d - Cogito now supports cherrypicking, easy commit
    reverts and automatic committing of applied patches
  * Resumable cg-clone - if cg-clone fails in the middle of the initial
    fetch, the directory is not deleted and you do not have to start all
    over again - just cd inside and run cg-fetch and it will DTRT

  * Support for tracking rebasing branches; as long as you use cg-update
    (NOT cg-fetch + cg-merge) and won't commit local changes, Cogito
    will correctly update the branch even if it got rebased in the
    meanwhile
  * Quoting fixes - this means that Cogito should be now theoretically
    100% resilient to whitespaces and metacharacters in filenames etc.
    Note that filenames containing newlines still aren't supported and
    aren't likely to ever be. You are a loonie. Go away.
  * Radically improved cg-fetch progressbar; it still doesn't quite work
    with rsync (use cg-fetch -v -v), but I don't think that can be
    helped. The main advantage is that it will show HTTP fetch progress
    even when fetching large files (especially packs).
  * Much more sensible behaviour for cg-clean wrt. untracked directories
    (do not erase their content).

  * Significant merges speedup (but still quite some potential for
    improvement)
  * cg-* --help now by default shows only short help; use --long-help
    to see the full manual
  * cg-commit --signoff
  * cg-commit --review to review and even modify the patch you are
    committing
  * cg-commit -M to take the commit message from a file
  * bash commandline autocompletion files in contrib/
  * cg-fetch -v, cg-fetch -v -v, cg-merge -v, cg-update -v
  * cg-push -r to push a different branch (or even a specific commit)
    instead of your current branch
  * cg-rm -r for recursive directories removal
  * cg-mv trivial wrapper for git-mv
  * cg-push over HTTP
  * cg-patch -u for applying non-git patches while autoadding/removing
    files, cg-patch -pN with obvious meaning
  * cg-object-id -d for short human-readable commit string id
    (just wraps git-describe)

  * Too many minor new features to list here

  * Incompatible change - cg-log -d renamed to cg-log -D
  * Incompatible change - the post-commit hook won't be ran for all the
    merged commits anymore when you commit a merge; you can reenable
    that in .git/config, see the cg-commit documentation for details


P.S.: See us at #git @ FreeNode!
P.P.S.: (*) That means bug-free, if it wasn't obvious!
P.P.P.S.: Yes, it just occurred to me that I've forgot about the
pre-built documentation, but it's too late in the night by now. Sorry,
the next time.

  Happy hacking,

-- 
				Petr "Pasky the lousy poet" Baudis
Stuff: http://pasky.or.cz/
Of the 3 great composers Mozart tells us what it's like to be human,
Beethoven tells us what it's like to be Beethoven and Bach tells us
what it's like to be the universe.  -- Douglas Adams

^ permalink raw reply	[relevance 4%]

* [ANNOUNCE] Cogito-0.17rc1
@ 2006-02-12 17:11  4% Petr Baudis
  0 siblings, 0 replies; 171+ results
From: Petr Baudis @ 2006-02-12 17:11 UTC (permalink / raw)
  To: git

  Hello,

  I'm announcing the release of Cogito version 0.17rc1, the human-friendly
version control UI for Linus' GIT tool. Share and enjoy at:

	http://www.kernel.org/pub/software/scm/cogito/

  This isn't as heavy on bugfixes as 0.16rc1 was, since most of the
bugfixes already went to 0.16 minor releases. This worked out pretty
well and 0.16.4 is really quite stable; so I will do the same thing for
0.17 as well.

  Still, there is a huge amount of new features and cool stuff. The
highlight is cg-switch for switching between local branches and massive
cg-patch improvements, but there is plenty of other stuff as well. Read
on for more details.

  Note that there is a lot of new stuff inside and some of it went in
quite lately so it didn't have a lot of time to get tested by the
bleeding edge users. Therefore take care, bugs might be lurking around.

  The notable new stuff includes:

  * cg-switch - Cogito finally gives you the full convenience of
    multiple local branches in a single repository ;)
  * cg-patch -c, -C, -d - Cogito now supports cherrypicking, easy commit
    reverts and automatic committing of applied patches
  * Resumable cg-clone - if cg-clone fails in the middle of the initial
    fetch, the directory is not deleted and you do not have to start all
    over again - just cd inside and run cg-fetch and it will DTRT

  * Support for tracking rebasing branches; as long as you use cg-update
    (NOT cg-fetch + cg-merge) and won't commit local changes, Cogito
    will correctly update the branch even if it got rebased in the
    meanwhile
  * Quoting fixes - this means that Cogito should be now theoretically
    100% resilient to whitespaces and metacharacters in filenames etc.
    Note that filenames containing newlines still aren't supported and
    aren't likely to ever be. You are a loonie. Go away.
  * Radically improved cg-fetch progressbar; it still doesn't quite work
    with rsync (use cg-fetch -v -v), but I don't think that can be
    helped. The main advantage is that it will show HTTP fetch progress
    even when fetching large files (especially packs).

  * Significant merges speedup (but still quite some potential for
    improvement)
  * cg-* --help now by default shows only short help; use --long-help
    to see the full manual
  * cg-commit --signoff
  * cg-commit --review to review and even modify the patch you are
    committing
  * bash commandline autocompletion files in contrib/
  * cg-fetch -v, cg-fetch -v -v, cg-merge -v, cg-update -v
  * cg-push -r to push a different branch (or even a specific commit)
    instead of your current branch
  * cg-rm -r for recursive directories removal
  * cg-mv trivial wrapper for git-mv
  * cg-push over HTTP
  * cg-patch -u for applying non-git patches while autoadding/removing
    files, cg-patch -pN with obvious meaning
  * cg-object-id -d for short human-readable commit string id
    (just wraps git-describe)

  * Too many minor new features to list here

  * Incompatible change - the post-commit hook won't be ran for all the
    merged commits anymore when you commit a merge; you can reenable
    that in .git/config, see the cg-commit documentation for details


P.S.: See us at #git @ FreeNode!

  Happy hacking,

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
VI has two modes: the one in which it beeps and the one in which

^ permalink raw reply	[relevance 4%]

* [PATCH] cg-commit: append sign off line when passed -s or --signoff
@ 2005-11-29 23:58  4% Jonas Fonseca
  0 siblings, 0 replies; 171+ results
From: Jonas Fonseca @ 2005-11-29 23:58 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git

No sign off line is appended if it already is signed off. By default the
identity reported by 'git-var GIT_AUTHOR_IDENT' is used for signing off.
Optionally, specify the name and email to sign off with by doing:

	cg-commit --signoff='Author Name <user@example.com>

If the commit message specified on the command line already contains
signed off lines no empty line is inserted between the message and the
sign off line.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

---
commit dd872816a04f6462686e282b00d3e1523e3ecf4c
tree a8487566085727636a5782e2edb270190b9f3916
parent c0a9b8feb79d72f7c02f37392da840dbad446dbd
author Jonas Fonseca <fonseca@diku.dk> Mon, 28 Nov 2005 04:42:05 +0100
committer Jonas Fonseca <fonseca@antimatter.localdomain> Mon, 28 Nov 2005 04:42:05 +0100

 TODO      |    2 --
 cg-commit |   17 ++++++++++++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/TODO b/TODO
index 5193d08..777c728 100644
--- a/TODO
+++ b/TODO
@@ -79,8 +79,6 @@ cg-*patch should be pre-1.0.)
 		  whitespace errors and stuff; hooks are good for this too,
 		  but I think it's good to have internal support for the
 		  basic stuff.
-		* -s,--signoff to automatically append a signoff line of
-		  yours to the patch.
 	-- post 1.0 --
 	* Patch-altering cg-commit
 		You can already alter the list of files to be committed,
diff --git a/cg-commit b/cg-commit
index d084c24..9f8d5d5 100755
--- a/cg-commit
+++ b/cg-commit
@@ -58,6 +58,11 @@
 #	Be quiet in case there's "nothing to commit", and silently exit
 #	returning success. In a sense, this is the opposite to '-f'.
 #
+# -s, --signoff:: Automatically append a sign off line
+#	Add Signed-off-by line at the end of the commit message.
+#	Optionally, specify the exact name and email to sign off with by
+#	passing: `--signoff="Author Name <user@example.com>"`.
+#
 # FILES
 # -----
 # $GIT_DIR/author::
@@ -119,7 +124,7 @@
 # EDITOR::
 #	The editor used for entering revision log information.
 
-USAGE="cg-commit [-m MESSAGE]... [-C] [-e | -E] [-c COMMIT_ID] [FILE]... [< MESSAGE]"
+USAGE="cg-commit [-m MESSAGE]... [-C] [-e | -E] [-s | --signoff] [-c COMMIT_ID] [FILE]... [< MESSAGE]"
 
 . ${COGITO_LIB}cg-Xlib || exit 1
 
@@ -148,6 +153,7 @@ ignorecache=
 infoonly=
 commitalways=
 missingok=
+signoff=
 copy_commit=
 msgs=()
 quiet=
@@ -166,6 +172,10 @@ while optparse; do
 		force=1
 	elif optparse -q; then
 		quiet=1
+	elif optparse -s || optparse --signoff; then
+		[ "$signoff" ] || signoff="$(git-var GIT_AUTHOR_IDENT | sed 's/> .*/>/')"
+	elif optparse --signoff=; then
+		signoff="$OPTARG"
 	elif optparse -m=; then
 		msgs[${#msgs[@]}]="$OPTARG"
 	elif optparse -c=; then
@@ -292,6 +302,11 @@ fi >> $LOGMSG
 # the poor people whose text editor has no 'O' command.
 [ "$written" ] || echo >>$LOGMSG
 
+if [ "$signoff" ] && ! grep -q -i "signed-off-by: $signoff" $LOGMSG; then
+	grep -q -i sign-off-by $LOGMSG || echo
+	echo "Signed-off-by: $signoff"
+fi >> $LOGMSG
+
 if [ -e "$_git/commit-template" ]; then
 	cat $_git/commit-template >>$LOGMSG
 else

-- 
Jonas Fonseca

^ permalink raw reply related	[relevance 4%]

Results 1-171 of 171 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2005-11-29 23:58  4% [PATCH] cg-commit: append sign off line when passed -s or --signoff Jonas Fonseca
2006-02-12 17:11  4% [ANNOUNCE] Cogito-0.17rc1 Petr Baudis
2006-02-27  1:16  4% [ANNOUNCE] Cogito-0.17 Petr Baudis
2006-03-26 17:56  3% [ANNOUNCE] Cogito-0.17.1 Petr Baudis
2006-11-28 12:02 19% [PATCH] Add support for commit.signoff config option Andy Parkins
2006-11-28 20:17  6% ` Junio C Hamano
2007-07-06 14:42     [PATCH] git-commit: don't add multiple Signed-off-by: from the same identity Gerrit Pape
2007-07-06 14:45 19% ` [PATCH] git-commit: add commit.signoff config option Gerrit Pape
2007-07-06 14:46 13% [PATCH] git-gui: Allow users to set commit.signoff from options Gerrit Pape
2007-07-08 21:48 12% ` Shawn O. Pearce
2007-07-09  7:43  6%   ` Gerrit Pape
2008-08-05  5:50     [PATCH 0/8] bash completion: more porcelain completions Lee Marlow
2008-08-05  5:50     ` [PATCH 1/8] bash completion: Add completion for 'git clone' Lee Marlow
2008-08-05  5:50       ` [PATCH 2/8] bash completion: Add completion for 'git clean' Lee Marlow
2008-08-05  5:50         ` [PATCH 3/8] bash completion: Add completion for 'git init' Lee Marlow
2008-08-05  5:50 10%       ` [PATCH 4/8] bash completion: Add completion for 'git revert' Lee Marlow
2008-12-26 11:18     [PATCH] git-shortlog.txt: improve documentation about .mailmap files Adeodato Simó
2008-12-26 11:55  3% ` Adeodato Simó
2008-12-26 12:56 15% [PATCH] Add a commit.signoff configuration variable to always use --signoff Adeodato Simó
2008-12-26 22:02  7% ` Nanako Shiraishi
2008-12-26 22:10  7%   ` Adeodato Simó
2008-12-27  0:36  7%     ` Junio C Hamano
2008-12-27  8:26 11%       ` Adeodato Simó
2008-12-27  8:44  7%         ` Junio C Hamano
2008-12-27  9:03 14%           ` Adeodato Simó
2008-12-27 11:04  7%             ` Thomas Rast
2008-12-27 11:05  7%               ` Adeodato Simó
2008-12-27 11:53  7%             ` Junio C Hamano
2008-12-27 12:01  7%               ` Adeodato Simó
2008-12-29 11:16 21%                 ` [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit Adeodato Simó
2008-12-29 11:18  8%                   ` Adeodato Simó
2008-12-30 21:04 14%                   ` Junio C Hamano
2009-01-01 22:18  8%                     ` Adeodato Simó
2009-01-02 12:46  8%                       ` Adeodato Simó
2008-12-27 18:08  7% ` [PATCH] Add a commit.signoff configuration variable to always use --signoff Jan Krüger
2008-12-27 18:40  7%   ` Adeodato Simó
2008-12-27 19:15  7%     ` Jan Krüger
2009-01-06  6:33  4% What's cooking in git.git (Jan 2009, #01; Mon, 05) Junio C Hamano
2009-01-11  9:51  4% What's cooking in git.git (Jan 2009, #02; Sun, 11) Junio C Hamano
2010-01-13  3:36 14% [PATCH] Add `commit.signoff` configuration variable Steven Drake
2010-01-13  4:36 11% ` Steven Drake
2010-01-13  8:30  6% ` Junio C Hamano
2010-01-13  3:36 21% [PATCH] Add 'git commit --no-signoff' option Steven Drake
2010-10-26 13:53  2% [PATCH/RFC] Make git-completion Bash 4 compatible Peter van der Does
2010-10-27 17:15  2% [PATCH v2/RFC] " Peter van der Does
2010-10-30 20:42     [PATCH v3/RFC 0/2] " Peter van der Does
2010-10-30 20:42  2% ` [PATCH v3/RFC 2/2] Use the new functions to get the current cword Peter van der Does
2010-11-16 15:11     [PATCH] cherry-pick -x: add newline before pick note Michael J Gruber
2010-11-16 19:30     ` Jeff King
2010-11-16 20:25  4%   ` [PATCH] commit -s: allow "(cherry picked " lines in sign-off section Jonathan Nieder
2010-12-01 20:49     [PATCH v4 0/2] *** SUBJECT HERE *** Peter van der Does
2010-12-01 20:49  2% ` [PATCH v4 2/2] Use the new functions to get the current cword Peter van der Does
2010-12-02  9:16  2% ` [PATCH v4 0/2] Make git-completion Bash 4 compatible Jonathan Nieder
2010-12-02 14:16       ` Peter van der Does
2010-12-02 21:02         ` [RFC/PATCH 2/1] bash: eliminate dependency on bash_completion lib Jonathan Nieder
2010-12-07 16:07           ` SZEDER Gábor
2010-12-07 19:49             ` Jonathan Nieder
2010-12-07 21:03               ` Junio C Hamano
2010-12-15  6:24                 ` [PATCH v5.1 0/3] Make git-completion Bash 4 compatible Jonathan Nieder
2010-12-15  6:26  2%               ` [PATCH 1/3] bash: get --pretty=m<tab> completion to work with bash v4 Jonathan Nieder
2010-12-02  0:40     [PATCH v5 0/2] Make git-completion Bash 4 compatible Peter van der Does
2010-12-02  0:40  2% ` [PATCH v5 2/2] Use the new functions to get the current cword Peter van der Does
2011-04-28 16:01     [RFC/PATCH] completion: avoid "words" as variable name for zsh portability SZEDER Gábor
2011-04-28 16:01     ` [PATCH 1/3] bash: don't modify the $cur variable in completion functions SZEDER Gábor
2011-04-28 16:01  3%   ` [PATCH 2/3] bash: remove unnecessary _get_comp_words_by_ref() invocations SZEDER Gábor
2011-07-27  3:18     [PATCH 00/18] GSoC update: Sequencer for inclusion v3 Ramkumar Ramachandra
2011-07-27 22:59     ` Junio C Hamano
2011-07-28 16:26       ` Ramkumar Ramachandra
2011-07-28 16:32  4%     ` Ramkumar Ramachandra
2011-07-28 16:39  0%       ` Jonathan Nieder
2012-04-11 10:29     [PATCH 0/2] Dynamic long options for bash completion Stephen Boyd
2012-04-11 10:29  7% ` [PATCH 2/2] completion: Use parse-options raw output for simple long options Stephen Boyd
2012-09-12 19:57     [PATCH] cherry-pick: don't forget -s on failure Miklos Vajna
2012-09-12 22:32     ` Junio C Hamano
2012-09-12 22:45       ` Junio C Hamano
2012-09-13  7:33  7%     ` [PATCH v2] " Miklos Vajna
2012-09-13 17:04  0%       ` Junio C Hamano
2012-09-13 17:23           ` Junio C Hamano
2012-09-13 20:27  7%         ` [PATCH v3] " Miklos Vajna
2012-09-13 21:13               ` Junio C Hamano
2012-09-14  6:52  7%             ` [PATCH v4] " Miklos Vajna
2012-09-15 14:27     How to create the " [PATCH 0/5]" first email? Philip Oakley
2012-09-15 17:08     ` Junio C Hamano
2012-09-17 22:55       ` Philip Oakley
2012-09-17 23:49         ` Junio C Hamano
2012-09-18  0:15           ` Jeff King
2012-09-18  0:36             ` Junio C Hamano
2012-09-18 18:55               ` Jeff King
2012-09-18 19:11                 ` Junio C Hamano
2012-09-18 19:16                   ` Jeff King
2012-09-18 19:47                     ` Junio C Hamano
2012-09-18 20:16  5%                   ` Jeff King
2012-11-15  1:37  6% [PATCH 1/5] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
2012-11-15  3:20     Matt Kraai
2012-11-15  5:49  6% ` [PATCH 1/5 v2] " Brandon Casey
2012-11-26  1:45     [PATCH 00/11] alternative unify appending of sob Brandon Casey
2012-11-26  1:45  6% ` [PATCH 02/11] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
2013-01-05 16:44     [PATCH] Alphabetize the fast-import options, following a suggestion on the list Eric S. Raymond
2013-01-05 23:11  5% ` Jonathan Nieder
2013-01-21  8:40     [PATCH v2 00/10] unify appending of sob Brandon Casey
2013-01-21  8:40  6% ` [PATCH v2 02/10] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
2013-01-28  1:11     [PATCH v3 00/11] unify appending of sob Brandon Casey
2013-01-28  1:11  6% ` [PATCH v3 03/11] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
2013-02-12 10:17     [PATCH v4 00/12] unify appending of sob Brandon Casey
2013-02-12 10:17  6% ` [PATCH v4 03/12] t/test-lib-functions.sh: allow to specify the tag name to test_commit Brandon Casey
2017-05-13 17:41  0%   ` Ævar Arnfjörð Bjarmason
2013-04-10  9:08  6% [PATCH] completion: add more cherry-pick options Felipe Contreras
2013-10-31 23:03     [PATCH] commit: Add -f, --fixes <commit> option to add Fixes: line Stefan Beller
2013-10-31 23:04     ` [PATCH] Documentation: add a script to generate a (long/short) options overview Stefan Beller
2013-10-31 23:09  7%   ` Stefan Beller
2014-06-19  3:28     [RFC PATCH 0/7] rebase -i: Implement `reword` and `squash` in terms of `do_pick` Fabian Ruch
2014-07-28 23:18     ` [PATCH v1 00/19] Enable options --signoff, --reset-author for pick, reword Fabian Ruch
2014-07-28 23:18 11%   ` [PATCH v1 03/19] rebase -i: reword executes pre-commit hook on interim commit Fabian Ruch
2014-08-06 23:59     ` [PATCH v2 00/23] Enable options --signoff, --reset-author for pick, reword Fabian Ruch
2014-08-06 23:59  7%   ` [PATCH v2 06/23] commit: allow disabling pre-commit and commit-msg separately Fabian Ruch
2014-08-18 21:22     ` [PATCH v3 00/27] Enable options --signoff, --reset-author for pick, reword, edit Fabian Ruch
2014-08-18 21:22  7%   ` [PATCH v3 07/27] commit: allow disabling pre-commit and commit-msg separately Fabian Ruch
2015-05-25  9:59  5% [PATCH] completion: suggest sequencer commands for revert Thomas Braun
2015-05-29 19:50  0% ` Junio C Hamano
2015-05-29 23:13  0%   ` Ramkumar Ramachandra
2015-05-30 15:57  0%     ` [PATCH v2 0/2] completion: sequencer commands Thomas Braun
2015-05-30 16:01  5%     ` [PATCH v2 2/2] completion: suggest sequencer commands for revert Thomas Braun
2015-05-30 16:01  5%     ` [PATCH v2 1/2] completion: Add sequencer function Thomas Braun
2015-05-30 19:01  0%       ` SZEDER Gábor
2015-05-30 16:02  5%     ` Thomas Braun
2015-06-25  7:30 20% [PATCH] commit: add commit.signoff config option cmarcelo
2015-06-25  8:21  6% ` Alexander Kuleshov
2015-06-25  8:32 12%   ` Remi Galan Alfonso
2015-06-25 14:57  6%     ` Caio Marcelo de Oliveira Filho
2015-06-25  7:32 20% Caio Marcelo de Oliveira Filho
2015-06-25  8:43  6% ` Christian Couder
2015-06-25 14:55  6%   ` Caio Marcelo de Oliveira Filho
2015-06-25 14:50 20% [PATCH v2] " Caio Marcelo de Oliveira Filho
2015-06-25 14:55  6% ` Junio C Hamano
2015-06-25 15:08  6%   ` Johannes Löthberg
2015-06-25 15:19  6%   ` Caio Marcelo de Oliveira Filho
2015-06-25 16:01 11%     ` Junio C Hamano
2015-06-25 18:56  6%       ` Matthieu Moy
2015-06-25 16:36  6% ` Torsten Bögershausen
2015-07-23  1:23     [RFC/PATCH] log: add log.firstparent option Jeff King
2015-07-23 22:14     ` Stefan Beller
2015-07-24  7:40       ` Jeff King
2015-07-24 15:31         ` Junio C Hamano
2015-07-25  1:36           ` Jeff King
2015-07-25  1:47  6%         ` Jeff King
2015-07-25 17:18  0%           ` Junio C Hamano
2016-03-09 18:36     [PATCH 00/19] index-helper, watchman David Turner
2016-03-09 18:36  4% ` [PATCH 15/19] unpack-trees: preserve index extensions David Turner
2016-03-19  1:04     [PATCH v2 00/15] index-helper, watchman David Turner
2016-03-19  1:04  4% ` [PATCH v2 12/17] unpack-trees: preserve index extensions David Turner
2016-04-06 22:11     [PATCH v3 00/16] index-helper, watchman David Turner
2016-04-06 22:11  4% ` [PATCH v3 11/16] unpack-trees: preserve index extensions David Turner
2016-04-13  0:32     [PATCH v4 00/16] index-helper, watchman David Turner
2016-04-13  0:33  4% ` [PATCH v4 11/16] unpack-trees: preserve index extensions David Turner
2016-04-19 23:27     [PATCH v5 00/15] index-helper/watchman David Turner
2016-04-19 23:28  4% ` [PATCH v5 11/15] unpack-trees: preserve index extensions David Turner
2016-04-27 20:04     [PATCH v6 00/19] index-helper/watchman David Turner
2016-04-27 20:04  4% ` [PATCH v6 12/19] unpack-trees: preserve index extensions David Turner
2016-04-30  1:01     [PATCH v7 00/19] index-helper/watchman David Turner
2016-04-30  1:02  4% ` [PATCH v7 12/19] unpack-trees: preserve index extensions David Turner
2016-05-05 21:46     [PATCH v8 00/19] index-helper/watchman David Turner
2016-05-05 21:47  4% ` [PATCH v8 12/19] unpack-trees: preserve index extensions David Turner
2016-05-09 20:48     [PATCH v9 00/19] index-helper/watchman David Turner
2016-05-09 20:48  4% ` [PATCH v9 12/19] unpack-trees: preserve index extensions David Turner
2016-05-12 20:19     [PATCH v10 00/20] index-helper/watchman David Turner
2016-05-12 20:20  4% ` [PATCH v10 13/20] unpack-trees: preserve index extensions David Turner
2016-05-19 21:45     [PATCH v12 00/20] index-helper/watchman David Turner
2016-05-19 21:45  4% ` [PATCH v12 13/20] unpack-trees: preserve index extensions David Turner
2016-06-26  4:14     [PATCH v13 01/20] read-cache.c: fix constness of verify_hdr() David Turner
2016-06-26  4:14  4% ` [PATCH v13 13/20] unpack-trees: preserve index extensions David Turner
2016-07-03  7:57     [PATCH v14 00/21] index-helper/watchman David Turner
2016-07-03  7:58  4% ` [PATCH v14 13/21] unpack-trees: preserve index extensions David Turner
2016-11-21 20:41     [PATCH 0/3] Introduce `submodule interngitdirs` Stefan Beller
2016-11-21 20:41 11% ` [PATCH 2/3] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-11-21 21:04  0%   ` Junio C Hamano
2016-11-22 19:22     [PATCHv2 0/4] `submodule embedgitdirs` [was: Introduce `submodule interngitdirs`] Stefan Beller
2016-11-22 19:22 11% ` [PATCHv2 3/4] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-01 20:25     [PATCHv3 0/5] submodule embedgitdirs Stefan Beller
2016-12-01 20:25 11% ` [PATCHv3 3/5] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-02 23:42     [PATCHv4 0/5] submodule embedgitdirs Stefan Beller
2016-12-02 23:42 11% ` [PATCHv4 3/5] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-07 21:01     [PATCHv5 0/5] submodule embedgitdirs Stefan Beller
2016-12-07 21:01 11% ` [PATCHv5 3/5] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-08  1:46     [PATCHv6 0/7] submodule embedgitdirs Stefan Beller
2016-12-08  1:46 11% ` [PATCHv6 3/7] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-08 21:03     [PATCHv7 0/6] submodule absorbgitdirs Stefan Beller
2016-12-08 21:03 11% ` [PATCHv7 3/6] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2016-12-12 19:04     [PATCHv7 0/6] submodule absorbgitdirs Stefan Beller
2016-12-12 19:04 11% ` [PATCHv8 3/6] test-lib-functions.sh: teach test_commit -C <dir> Stefan Beller
2017-01-22 22:57     [PATCH 0/7] completion bash: add more options and commands bitte.keine.werbung.einwerfen
2017-01-22 22:57  9% ` [PATCH 7/7] completion: recognize more long-options bitte.keine.werbung.einwerfen
2017-01-24  7:15     Johannes Sixt
2017-01-27 21:17     ` [PATCH v2 0/7] " cornelius.weig
2017-01-27 21:17  9%   ` [PATCH v2 7/7] " cornelius.weig
2017-01-31 22:17  0%     ` SZEDER Gábor
2017-02-03  2:53     [PATCH 00/12] completion: speed up refs completion SZEDER Gábor
2017-02-03  2:53  2% ` [PATCH 02/12] completion: wrap __git_refs() for better option parsing SZEDER Gábor
2017-02-03 11:01     [PATCH v2 0/7] completion bash: add more options and commands cornelius.weig
2017-02-03 11:01  9% ` [PATCH v2 7/7] completion: recognize more long-options cornelius.weig
2017-03-23 15:29     [PATCHv2 00/14] completion: speed up refs completion SZEDER Gábor
2017-03-23 15:29  2% ` [PATCHv2 02/14] completion: wrap __git_refs() for better option parsing SZEDER Gábor
2017-05-12 10:50     [PATCH] fixup! log: add exhaustive tests for pattern style options & config Johannes Schindelin
2017-05-13 13:20     ` Ævar Arnfjörð Bjarmason
2017-05-15  2:18       ` Junio C Hamano
2017-05-15 12:19         ` Johannes Schindelin
2017-05-16  0:46           ` Junio C Hamano
2017-05-16  6:15  5%         ` Ævar Arnfjörð Bjarmason
2018-01-31 11:05     [PATCH v2 00/41] Automate updating git-completion.bash a bit Nguyễn Thái Ngọc Duy
2018-01-31 11:05  6% ` [PATCH v2 10/41] completion: use __gitcomp_builtin in _git_cherry_pick Nguyễn Thái Ngọc Duy
2018-01-31 11:05  6% ` [PATCH v2 36/41] completion: use __gitcomp_builtin in _git_revert Nguyễn Thái Ngọc Duy
2018-02-09 11:01     ` [PATCH v3 00/42] Automate updating git-completion.bash a bit Nguyễn Thái Ngọc Duy
2018-02-09 11:01  6%   ` [PATCH v3 10/42] completion: use __gitcomp_builtin in _git_cherry_pick Nguyễn Thái Ngọc Duy
2018-02-09 11:02  6%   ` [PATCH v3 36/42] completion: use __gitcomp_builtin in _git_revert Nguyễn Thái Ngọc Duy
2018-02-04  2:03 21% [GSoC][PATCH] commit: add a commit.signOff config variable Chen Jingpiao
2018-02-04 11:31 13% ` Eric Sunshine
2018-02-04 18:59  6%   ` Ævar Arnfjörð Bjarmason
2018-02-05 21:50  6% ` Stefan Beller
2018-02-06  7:01  6%   ` Chen Jingpiao
2018-02-05 10:40 21% [GSoC][PATCH v2] " Chen Jingpiao
2018-02-05 19:22  6% ` Junio C Hamano
2018-02-06  4:37  6%   ` Chen Jingpiao
2019-08-03 19:34  8% [PATCH 1/1] commit: add signoff " Liam Beguin
2019-08-03 21:11  4% ` brian m. carlson
2019-08-03 21:23  0%   ` Liam Beguin
2019-09-03 12:44  5% Git does not recognise directory named '${sys:DATA_ROOT_DIR}' Σταύρος Ντέντος
2019-09-03 13:34  0% ` Taylor Blau
2019-09-03 14:11  0%   ` Σταύρος Ντέντος
2019-10-08  7:49     [PATCH 1/1] commit: add support to provide --coauthor Toon Claes
2019-10-08 10:11     ` Phillip Wood
2019-10-08 12:04  7%   ` Phillip Wood
2020-01-05 17:41  5% [PATCH 0/1] commit: make the sign-off trailer configurable Hans Jerry Illikainen
2020-01-05 17:41 15% ` [PATCH 1/1] " Hans Jerry Illikainen
2020-01-06 13:38  6%   ` Derrick Stolee
2020-01-06 16:53         ` Junio C Hamano
2020-01-06 19:53           ` Derrick Stolee
2020-01-06 20:31  4%         ` Junio C Hamano
2021-01-05 13:03     [PATCH] shortlog: remove unused(?) "repo-abbrev" feature Ævar Arnfjörð Bjarmason
2021-01-12 20:17  6% ` [PATCH 14/22] test-lib functions: add --author support to test_commit Ævar Arnfjörð Bjarmason
2021-01-14  7:40  0%   ` Denton Liu
2021-01-07 15:37     [PATCH v3 1/2] bundle: lost objects when removing duplicate pendings Đoàn Trần Công Danh
2021-01-08 14:45  5% ` [PATCH v4 0/2] Improvements for git-bundle Jiang Xin
2021-01-08 14:45  6% ` [PATCH v4 1/2] bundle: lost objects when removing duplicate pendings Jiang Xin
2021-01-09  2:10  0%   ` Junio C Hamano
2021-01-09 13:32  0%     ` Jiang Xin
2021-01-09 22:02     Junio C Hamano
2021-01-10 14:30  6% ` [PATCH v5 1/3] test: add helper functions for git-bundle Jiang Xin
2021-01-11 20:09  0%   ` Junio C Hamano
2021-01-12  2:27  3%     ` [PATCH v6 0/3] improvements " Jiang Xin
2021-01-12  2:27  6%     ` [PATCH v6 1/3] test: add helper functions " Jiang Xin
2021-03-11  7:16  2% [PATCH] [GSOC] commit: provides multiple common signatures ZheNing Hu via GitGitGadget
2021-03-11 15:03  0% ` Shourya Shukla
2021-03-12 11:41  0%   ` ZheNing Hu
2021-03-11 17:28  0% ` Junio C Hamano
2021-03-12 15:54  5% ` [PATCH v2] [GSOC] commit: add trailer command ZheNing Hu via GitGitGadget
2021-03-19 12:06     [PATCH 0/3] [GSOC] commit: add own-identity option ZheNing Hu via GitGitGadget
2021-03-19 12:06  3% ` [PATCH 2/3] [GSOC] interpret-trailers: " ZheNing Hu via GitGitGadget
2021-04-09 13:37     [PATCH v8 0/2] [GSOC] trailer: add new .cmd config option ZheNing Hu via GitGitGadget
2021-04-12 16:39     ` [PATCH v9 " ZheNing Hu via GitGitGadget
2021-04-12 16:39       ` [PATCH v9 2/2] " ZheNing Hu via GitGitGadget
2021-04-12 20:51         ` Junio C Hamano
2021-04-13  7:33           ` Christian Couder
2021-04-13 12:02             ` ZheNing Hu
2021-04-13 19:18               ` Junio C Hamano
2021-04-14 13:27                 ` ZheNing Hu
2021-04-14 20:33  4%               ` Junio C Hamano
2021-04-15 15:32  0%                 ` ZheNing Hu
2021-06-01 13:20     Runaway sed memory use in test on older sed+glibc (was "Re: [PATCH v6 1/3] test: add helper functions for git-bundle") Jiang Xin
2021-06-01 14:49  4% ` [PATCH 1/2] t6020: fix bash incompatible issue Jiang Xin
2021-08-15 23:07     git format-patch -s enhancement jim.cromie
2021-08-16 16:36  5% ` Jeff King
2021-08-16 21:49  0%   ` jim.cromie
2022-12-06 17:06     Skipping adding Signed-off-by even if it's not the last on git commit David Caro
2022-12-07  1:50  4% ` Taylor Blau
2022-12-07  4:11  0%   ` Junio C Hamano
2022-12-07  8:40  0%     ` David Caro
2022-12-07 22:13  0%       ` Taylor Blau
2022-12-07 23:04  0%         ` Junio C Hamano
2022-12-08  7:27  0%           ` Jeff King
2022-12-16 19:50     Add git config variable for signoff Prajwal S N
2022-12-16 23:03     ` Junio C Hamano
2022-12-19 17:26  6%   ` Prajwal S N

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).