threads / discuss / 51559

[PATCHv3] send-email: Ask if a patch should be sent twice

Subject: [PATCHv3] send-email: Ask if a patch should be sent twice

## tl;dr

7 messages between Jul 30, 2019 and Jul 31, 2019.

replies: 6people: 5as markdown or json

Dmitry Safonov· Jul 30, 2019, 20:33 UTC · lore
I was almost certain that git won't let me send the same patch twice,
but today I've managed to double-send a directory by a mistake:
	git send-email --to linux-kernel@vger.kernel.org /tmp/timens/
	    --cc 'Dmitry Safonov <0x7f454c46@gmail.com>' /tmp/timens/`
[I haven't noticed that I put the directory twice ^^]

Prevent this shipwreck from happening again by asking if a patch is sent multiple times on purpose.

link: https://lkml.kernel.org/r/4d53ebc7-d5b2-346e-c383-606401d19d3a@gmail.com
Cc: Andrei Vagin <avagin@openvz.org>
Suggested-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
v3: Use `test_i18ngrep` instead of plain `grep`
v2: Moved the check under --validate,
    fixed tests,
    added a new test,
    updated documentation for --validate
 Documentation/git-send-email.txt |  2 ++
 git-send-email.perl              | 14 ++++++++++++++
 t/t9001-send-email.sh            | 15 +++++++++++++++
 3 files changed, 31 insertions(+)
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index d93e5d0f58f0..0441bb1b5d3b 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -421,6 +421,8 @@ have been specified, in which case default to 'compose'.
 			('auto', 'base64', or 'quoted-printable') is used;
 			this is due to SMTP limits as described by
 			http://www.ietf.org/rfc/rfc5322.txt.
+		*	Ask confirmation before sending patches multiple times
+			if the supplied patches set overlaps.
 --
 +
 Default is the value of `sendemail.validate`; if this is not set,
diff --git a/git-send-email.perl b/git-send-email.perl
index 5f92c89c1c1b..c1638d06f81d 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -688,6 +688,9 @@ sub is_format_patch_arg {
 @files = handle_backup_files(@files);
 
 if ($validate) {
+	my %seen;
+	my @dupes = grep { $seen{$_}++ } @files;
+
 	foreach my $f (@files) {
 		unless (-p $f) {
 			my $error = validate_patch($f, $target_xfer_encoding);
@@ -695,6 +698,17 @@ sub is_format_patch_arg {
 						  $f, $error);
 		}
 	}
+	if (@dupes) {
+		printf(__("Patches specified several times: \n"));
+		printf(__("%s \n" x @dupes), @dupes);
+		$_ = ask(__("Do you want to send those patches several times? Y/n "),
+			default => "y",
+			valid_re => qr/^(?:yes|y|no|n)/i);
+		if (/^n/i) {
+			cleanup_compose_files();
+			exit(0);
+		}
+	}
 }
 
 if (@files) {
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 997f90b42b3e..496005af1763 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -555,6 +555,7 @@ test_expect_success $PREREQ 'In-Reply-To without --chain-reply-to' '
 		--no-chain-reply-to \
 		--in-reply-to="$(cat expect)" \
 		--smtp-server="$(pwd)/fake.sendmail" \
+		--no-validate \
 		$patches $patches $patches \
 		2>errors &&
 	# The first message is a reply to --in-reply-to
@@ -577,6 +578,7 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
 		--chain-reply-to \
 		--in-reply-to="$(cat expect)" \
 		--smtp-server="$(pwd)/fake.sendmail" \
+		--no-validate \
 		$patches $patches $patches \
 		2>errors &&
 	sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual &&
@@ -589,6 +591,19 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
 	test_cmp expect actual
 '
 
+test_expect_success $PREREQ 'ask confirmation for double-send' '
+	clean_fake_sendmail &&
+	echo y | \
+		GIT_SEND_EMAIL_NOTTY=1 \
+		git send-email --from=author@example.com \
+			--to=nobody@example.com \
+			--smtp-server="$(pwd)/fake.sendmail" \
+			--validate \
+			$patches $patches $patches \
+			>stdout &&
+	! test_i18ngrep "Patches specified several times: " stdout
+'
+
 test_expect_success $PREREQ 'setup fake editor' '
 	write_script fake-editor <<-\EOF
 	echo fake edit >>"$1"
-- 
2.22.0
SZEDER Gábor· Jul 30, 2019, 21:10 UTC · re: Dmitry Safonov · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

On Tue, Jul 30, 2019 at 09:33:27PM +0100, Dmitry Safonov wrote:
Show 15 quoted lines
> @@ -589,6 +591,19 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
>  	test_cmp expect actual
>  '
>  
> +test_expect_success $PREREQ 'ask confirmation for double-send' '
> +	clean_fake_sendmail &&
> +	echo y | \
> +		GIT_SEND_EMAIL_NOTTY=1 \
> +		git send-email --from=author@example.com \
> +			--to=nobody@example.com \
> +			--smtp-server="$(pwd)/fake.sendmail" \
> +			--validate \
> +			$patches $patches $patches \
> +			>stdout &&
> +	! test_i18ngrep "Patches specified several times: " stdout

You should write this as 'test_i18ngrep ! <...>'. When running the test with GIT_TEST_GETTEXT_POISON=true, then 'test_i18ngrep' is basically a noop and always returns with success, the leading ! would turn that into a failure, which then would fail the test.

Sorry for not being specific enough.
Dmitry Safonov· Jul 30, 2019, 21:19 UTC · re: SZEDER Gábor · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

On 7/30/19 10:10 PM, SZEDER Gábor wrote:
Show 23 quoted lines
> On Tue, Jul 30, 2019 at 09:33:27PM +0100, Dmitry Safonov wrote:
>> @@ -589,6 +591,19 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
>>  	test_cmp expect actual
>>  '
>>  
>> +test_expect_success $PREREQ 'ask confirmation for double-send' '
>> +	clean_fake_sendmail &&
>> +	echo y | \
>> +		GIT_SEND_EMAIL_NOTTY=1 \
>> +		git send-email --from=author@example.com \
>> +			--to=nobody@example.com \
>> +			--smtp-server="$(pwd)/fake.sendmail" \
>> +			--validate \
>> +			$patches $patches $patches \
>> +			>stdout &&
>> +	! test_i18ngrep "Patches specified several times: " stdout
> 
> You should write this as 'test_i18ngrep ! <...>'.  When running the
> test with GIT_TEST_GETTEXT_POISON=true, then 'test_i18ngrep' is
> basically a noop and always returns with success, the leading ! would
> turn that into a failure, which then would fail the test.
> 
> Sorry for not being specific enough.

No worries, thanks for the review anyway, quite educative - I haven't worked much on i18-related things in other projects, so sorry for not getting it straight away. Will resend shortly..

Thanks,
          Dmtiry
Junio C Hamano· Jul 30, 2019, 22:13 UTC · re: Dmitry Safonov · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

Dmitry Safonov <dima@arista.com> writes:
> I was almost certain that git won't let me send the same patch twice,

Why? And more importantly, does it matter to readers of this message what you thought?

Show 10 quoted lines
> but today I've managed to double-send a directory by a mistake:
> 	git send-email --to linux-kernel@vger.kernel.org /tmp/timens/
> 	    --cc 'Dmitry Safonov <0x7f454c46@gmail.com>' /tmp/timens/`
>
> [I haven't noticed that I put the directory twice ^^]
>
> Prevent this shipwreck from happening again by asking if a patch
> is sent multiple times on purpose.
>
> link: https://lkml.kernel.org/r/4d53ebc7-d5b2-346e-c383-606401d19d3a@gmail.com
What does "link:" mean?
> Cc: Andrei Vagin <avagin@openvz.org>

What's the significance for this project to record that this patch was CCed to Andrei?

> Suggested-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

I think "Helped-by:" is a lot more appropriate, viewing the exchange on v2 from the sideline.

> Signed-off-by: Dmitry Safonov <dima@arista.com>
> ---
Show 30 quoted lines
> diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
> index d93e5d0f58f0..0441bb1b5d3b 100644
> --- a/Documentation/git-send-email.txt
> +++ b/Documentation/git-send-email.txt
> @@ -421,6 +421,8 @@ have been specified, in which case default to 'compose'.
>  			('auto', 'base64', or 'quoted-printable') is used;
>  			this is due to SMTP limits as described by
>  			http://www.ietf.org/rfc/rfc5322.txt.
> +		*	Ask confirmation before sending patches multiple times
> +			if the supplied patches set overlaps.
>  --
>  +
>  Default is the value of `sendemail.validate`; if this is not set,
> diff --git a/git-send-email.perl b/git-send-email.perl
> index 5f92c89c1c1b..c1638d06f81d 100755
> --- a/git-send-email.perl
> +++ b/git-send-email.perl
> @@ -688,6 +688,9 @@ sub is_format_patch_arg {
>  @files = handle_backup_files(@files);
>  
>  if ($validate) {
> +	my %seen;
> +	my @dupes = grep { $seen{$_}++ } @files;
> +
>  	foreach my $f (@files) {
>  		unless (-p $f) {
>  			my $error = validate_patch($f, $target_xfer_encoding);
> @@ -695,6 +698,17 @@ sub is_format_patch_arg {
>  						  $f, $error);
>  		}

This is not a fault of your patch at all, but the two hunks are curious. If "git format-patch" chose to coalesce these two hunks into one, the second hunk header can be replaced by

		$error and die sprintf(__("fatal: ..."),

The end result would be that we will spend the same number of lines and we will see more useful information.

Show 12 quoted lines
>  	}
> +	if (@dupes) {
> +		printf(__("Patches specified several times: \n"));
> +		printf(__("%s \n" x @dupes), @dupes);
> +		$_ = ask(__("Do you want to send those patches several times? Y/n "),
> +			default => "y",
> +			valid_re => qr/^(?:yes|y|no|n)/i);
> +		if (/^n/i) {
> +			cleanup_compose_files();
> +			exit(0);
> +		}
> +	}

Perhaps this should be inserted _before_ the "let's examine each patchfile and complain" loop. Otherwise, you'd see this warning only after seeing the same "the file has too long a line" error on the same patch.

While you are counting with %seen how many times the contents of @files appear, perhaps you can also create a list of unique files, so that you do not have to call validate_patch() more than once for each of them. It would also allow you to offer another choice in the above question "do you want to send them more than once?", which may be much more useful than yes/no: "drop duplicates". If you did so, you do not need to swap the order of the checks. You would first count the occurences of each element in @files, then call validate_patch() on each of them just once, and after you are done, check if the user wants to send duplicates, abort, or dedup.

Perhaps like this:
 if ($validate) {
+	my (@dupes, %seen, @uniq);
+
	foreach my $f (@files) {
+		if ($seen{$f}) {
+			if ($seen{$f} == 1) { push @dupes, $f; }
+			next;
+		}
+		$seen{$f}++;
+		push @uniq, $f;
+	}
+	foreach my $f (@uniq) {	
		unless (-p $f) {
			my $error = validate_patch(...);
		... the existing loop ...
	}
+
+	if (@dupes) {
+		... the new code in your patch ...
Andrey Vagin· Jul 30, 2019, 22:56 UTC · re: Junio C Hamano · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

On Tue, Jul 30, 2019 at 3:13 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 7 quoted lines
>
> Dmitry Safonov <dima@arista.com> writes:
>
> > I was almost certain that git won't let me send the same patch twice,
>
> Why?  And more importantly, does it matter to readers of this
> message what you thought?

Sounds rude. What matter to readers except author's thoughts? I guess you want to say that the comment should be in more neutral technical form without personal pronouns.

Show 118 quoted lines
>
> > but today I've managed to double-send a directory by a mistake:
> >       git send-email --to linux-kernel@vger.kernel.org /tmp/timens/
> >           --cc 'Dmitry Safonov <0x7f454c46@gmail.com>' /tmp/timens/`
> >
> > [I haven't noticed that I put the directory twice ^^]
> >
> > Prevent this shipwreck from happening again by asking if a patch
> > is sent multiple times on purpose.
> >
> > link: https://lkml.kernel.org/r/4d53ebc7-d5b2-346e-c383-606401d19d3a@gmail.com
>
> What does "link:" mean?
>
> > Cc: Andrei Vagin <avagin@openvz.org>
>
> What's the significance for this project to record that this patch
> was CCed to Andrei?
>
> > Suggested-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>
> I think "Helped-by:" is a lot more appropriate, viewing the exchange
> on v2 from the sideline.
>
> > Signed-off-by: Dmitry Safonov <dima@arista.com>
> > ---
>
> > diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
> > index d93e5d0f58f0..0441bb1b5d3b 100644
> > --- a/Documentation/git-send-email.txt
> > +++ b/Documentation/git-send-email.txt
> > @@ -421,6 +421,8 @@ have been specified, in which case default to 'compose'.
> >                       ('auto', 'base64', or 'quoted-printable') is used;
> >                       this is due to SMTP limits as described by
> >                       http://www.ietf.org/rfc/rfc5322.txt.
> > +             *       Ask confirmation before sending patches multiple times
> > +                     if the supplied patches set overlaps.
> >  --
> >  +
> >  Default is the value of `sendemail.validate`; if this is not set,
> > diff --git a/git-send-email.perl b/git-send-email.perl
> > index 5f92c89c1c1b..c1638d06f81d 100755
> > --- a/git-send-email.perl
> > +++ b/git-send-email.perl
> > @@ -688,6 +688,9 @@ sub is_format_patch_arg {
> >  @files = handle_backup_files(@files);
> >
> >  if ($validate) {
> > +     my %seen;
> > +     my @dupes = grep { $seen{$_}++ } @files;
> > +
> >       foreach my $f (@files) {
> >               unless (-p $f) {
> >                       my $error = validate_patch($f, $target_xfer_encoding);
> > @@ -695,6 +698,17 @@ sub is_format_patch_arg {
> >                                                 $f, $error);
> >               }
>
> This is not a fault of your patch at all, but the two hunks are
> curious.  If "git format-patch" chose to coalesce these two hunks
> into one, the second hunk header can be replaced by
>
>                 $error and die sprintf(__("fatal: ..."),
>
> The end result would be that we will spend the same number of lines
> and we will see more useful information.
>
> >       }
> > +     if (@dupes) {
> > +             printf(__("Patches specified several times: \n"));
> > +             printf(__("%s \n" x @dupes), @dupes);
> > +             $_ = ask(__("Do you want to send those patches several times? Y/n "),
> > +                     default => "y",
> > +                     valid_re => qr/^(?:yes|y|no|n)/i);
> > +             if (/^n/i) {
> > +                     cleanup_compose_files();
> > +                     exit(0);
> > +             }
> > +     }
>
> Perhaps this should be inserted _before_ the "let's examine each
> patchfile and complain" loop.  Otherwise, you'd see this warning
> only after seeing the same "the file has too long a line" error
> on the same patch.
>
> While you are counting with %seen how many times the contents of
> @files appear, perhaps you can also create a list of unique files,
> so that you do not have to call validate_patch() more than once
> for each of them.  It would also allow you to offer another choice
> in the above question "do you want to send them more than once?",
> which may be much more useful than yes/no: "drop duplicates".  If
> you did so, you do not need to swap the order of the checks.  You
> would first count the occurences of each element in @files, then
> call validate_patch() on each of them just once, and after you are
> done, check if the user wants to send duplicates, abort, or dedup.
>
> Perhaps like this:
>
>  if ($validate) {
> +       my (@dupes, %seen, @uniq);
> +
>         foreach my $f (@files) {
> +               if ($seen{$f}) {
> +                       if ($seen{$f} == 1) { push @dupes, $f; }
> +                       next;
> +               }
> +               $seen{$f}++;
> +               push @uniq, $f;
> +       }
> +       foreach my $f (@uniq) {
>                 unless (-p $f) {
>                         my $error = validate_patch(...);
>                 ... the existing loop ...
>         }
> +
> +       if (@dupes) {
> +               ... the new code in your patch ...
>
Jeff King· Jul 31, 2019, 01:06 UTC · re: Andrey Vagin · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

On Tue, Jul 30, 2019 at 03:56:43PM -0700, Andrey Vagin wrote:
Show 12 quoted lines
> On Tue, Jul 30, 2019 at 3:13 PM Junio C Hamano <gitster@pobox.com> wrote:
> >
> > Dmitry Safonov <dima@arista.com> writes:
> >
> > > I was almost certain that git won't let me send the same patch twice,
> >
> > Why?  And more importantly, does it matter to readers of this
> > message what you thought?
> 
> Sounds rude. What matter to readers except author's thoughts? I guess you want
> to say that the comment should be in more neutral technical form without
> personal pronouns.

IMHO it's OK to use personal pronouns, but it's good to stick to the facts. It's easy to go off on a tangent about what led you to the patch that ends up making it harder for somebody reading the patch later to get to the point.

In this case, you did the leg-work to advance the story from "I'm confused about it should do..." to "it definitely does X now, and it would be better if it did Y". That's probably the best place for a later reader of the commit message to pick it up.

-Peff
PS I agree that what Junio wrote does sound a bit rude, but I don't
   think that was his intent. It's easy to accidentally be a little too
   curt during reviews (and I'm sure I've done it myself many times).
   Hopefully we can all take this as a reminder to be careful. :)
Dmitry Safonov· Jul 30, 2019, 23:05 UTC · re: Junio C Hamano · lore

Re: [PATCHv3] send-email: Ask if a patch should be sent twice

Hi Junio,
On 7/30/19 11:13 PM, Junio C Hamano wrote:
Show 6 quoted lines
> Dmitry Safonov <dima@arista.com> writes:
> 
>> I was almost certain that git won't let me send the same patch twice,
> 
> Why?  And more importantly, does it matter to readers of this
> message what you thought?

I see the point of putting description in impersonal, technical way. Probably, was irritated after sending 50 patches instead of 37. Also I've seen that in `git log | grep ' I '` over the project, not that it justifies using it in the discussed patch.

Show 13 quoted lines
> 
>> but today I've managed to double-send a directory by a mistake:
>> 	git send-email --to linux-kernel@vger.kernel.org /tmp/timens/
>> 	    --cc 'Dmitry Safonov <0x7f454c46@gmail.com>' /tmp/timens/`
>>
>> [I haven't noticed that I put the directory twice ^^]
>>
>> Prevent this shipwreck from happening again by asking if a patch
>> is sent multiple times on purpose.
>>
>> link: https://lkml.kernel.org/r/4d53ebc7-d5b2-346e-c383-606401d19d3a@gmail.com
> 
> What does "link:" mean?

It's a tag, usually used to point URL for more information. Maybe not that common in git-ml, but often it shows an example of what can go wrong without a patch.

Show 5 quoted lines
> 
>> Cc: Andrei Vagin <avagin@openvz.org>
> 
> What's the significance for this project to record that this patch
> was CCed to Andrei?

I've felt like I need to give credit to my friend with whom I was working on the patches set; which I've failed to send properly. Maybe it's a thing of more opensource-friendly communities like lkml.

Show 7 quoted lines
> 
>> Suggested-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> 
> I think "Helped-by:" is a lot more appropriate, viewing the exchange
> on v2 from the sideline.
> 
>> Signed-off-by: Dmitry Safonov <dima@arista.com>

To be honest, I don't feel like going on with v5. I've underestimate how welcoming some communities are to foreign patches.

If you feel like it's still worth to have the feature, please carry-on
with the tag
Abandoned-by: Dmitry Safonov <dima@arista.com>
and don't drop Cc tag.
[..]
Thanks and sorry for waisted time,
          Dmitry

← back to recent threads