threads / patch / 37039

v2git-am: add option to extract email Message-Id: tag into commit log

Subject: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

## tl;dr

7 messages between Jul 2, 2014 and Jul 3, 2014. Diffs are folded; open one to read it.

replies: 6people: 4as markdown or json

Avi Kivity· Jul 2, 2014, 08:51 UTC · lore

Some workflows prefer to track exactly which email message was used to generate a commit. This can be used, for example, to generate an automated acknowledgement when a patch is committed as a response to the patch email, or as a reference to the thread which introduced the patch.

Support this by adding a --message-id option (abbreviated as -m) to git-am, which will then extract the message ID and append it to the email commit log.

Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
---
v2: adjust to pass test suite (t5100)
 Documentation/git-am.txt |  6 ++++++
 builtin/mailinfo.c       |  2 +-
 git-am.sh                | 10 +++++++++-
 t/t5100/info0004         |  1 +
 t/t5100/info0005         |  1 +
 t/t5100/info0012         |  1 +
 6 files changed, 19 insertions(+), 2 deletions(-)
Show changes to 6 files +19 −2

Documentation/git-am.txt, builtin/mailinfo.c, git-am.sh, t/t5100/info0004, t/t5100/info0005, t/t5100/info0012

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 	 [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
 	 [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
 	 [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
+	 [--message-id]
 	 [(<mbox> | <Maildir>)...]
 'git am' (--continue | --skip | --abort)
 
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
 	user to lie about the author date by using the same
 	value as the committer date.
 
+-m::
+--message-id::
+	Extract the Message-Id: header from the e-mail and
+	append it to the commit message's tag stanza.
+
 --skip::
 	Skip the current patch.  This is only meaningful when
 	restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
 
 static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
-	"From","Subject","Date",
+	"From","Subject","Date","Message-Id"
 };
 
 static inline int cmp_header(const struct strbuf *line, const char *hdr)
diff --git a/git-am.sh b/git-am.sh
index ee61a77..c0e7bdd 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-date    lie about committer date
 ignore-date     use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
 S,gpg-sign?     GPG-sign commits
+m,message-id    copy the Message-Id: header to the commit's tag stanza
 rebasing*       (internal use for git-rebase)"
 
 . git-sh-setup
@@ -371,7 +372,7 @@ split_patches () {
 prec=4
 dotest="$GIT_DIR/rebase-apply"
 sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
 git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore."
 		gpg_sign_opt=-S ;;
 	--gpg-sign=*)
 		gpg_sign_opt="-S${1#--gpg-sign=}" ;;
+	-m|--message-id)
+		message_id=t ;;
 	--)
 		shift; break ;;
 	*)
@@ -565,6 +568,7 @@ Use \"git am --abort\" to remove it.")"
 	echo " $git_apply_opt" >"$dotest/apply-opt"
 	echo "$threeway" >"$dotest/threeway"
 	echo "$sign" >"$dotest/sign"
+	echo "$message_id" > "$dotest/message-id"
 	echo "$utf8" >"$dotest/utf8"
 	echo "$keep" >"$dotest/keep"
 	echo "$scissors" >"$dotest/scissors"
@@ -757,6 +761,10 @@ To restore the original branch and stop patching run \"\$cmdline --abort\"."
 		then
 			cat "$dotest/msg-clean"
 		fi
+		if test 't' == "$message_id"
+		then
+			grep ^Message-Id: "$dotest/info" || true
+		fi
 		if test '' != "$ADD_SIGNOFF"
 		then
 			echo "$ADD_SIGNOFF"
diff --git a/t/t5100/info0004 b/t/t5100/info0004
index 616c309..f7e2983 100644
--- a/t/t5100/info0004
+++ b/t/t5100/info0004
@@ -2,4 +2,5 @@ Author: YOSHIFUJI Hideaki / 吉藤英明
 Email: yoshfuji@linux-ipv6.org
 Subject: GIT: Try all addresses for given remote name
 Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)
+Message-Id: <20050721.091036.01119516.yoshfuji@linux-ipv6.org>
 
diff --git a/t/t5100/info0005 b/t/t5100/info0005
index 46a46fc..592388f 100644
--- a/t/t5100/info0005
+++ b/t/t5100/info0005
@@ -2,4 +2,5 @@ Author: David Kågedal
 Email: davidk@lysator.liu.se
 Subject: Fixed two bugs in git-cvsimport-script.
 Date: Mon, 15 Aug 2005 20:18:25 +0200
+Message-Id: <u5tacjjdpxq.fsf@lysator.liu.se>
 
diff --git a/t/t5100/info0012 b/t/t5100/info0012
index ac1216f..b5d89a1 100644
--- a/t/t5100/info0012
+++ b/t/t5100/info0012
@@ -2,4 +2,5 @@ Author: Dmitriy Blinov
 Email: bda@mnsspb.ru
 Subject: Изменён список пакетов необходимых для сборки
 Date: Wed, 12 Nov 2008 17:54:41 +0300
+Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>
 
-- 
1.9.3
Torsten Bögershausen· Jul 2, 2014, 09:58 UTC · re: Avi Kivity · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

Show 41 quoted lines
> --- a/git-am.sh
> +++ b/git-am.sh
> @@ -39,6 +39,7 @@ committer-date-is-author-date    lie about committer date
>  ignore-date     use current timestamp for author date
>  rerere-autoupdate update the index with reused conflict resolution if possible
>  S,gpg-sign?     GPG-sign commits
> +m,message-id    copy the Message-Id: header to the commit's tag stanza
>  rebasing*       (internal use for git-rebase)"
>  
>  . git-sh-setup
> @@ -371,7 +372,7 @@ split_patches () {
>  prec=4
>  dotest="$GIT_DIR/rebase-apply"
>  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
> -resolvemsg= resume= scissors= no_inbody_headers=
> +resolvemsg= resume= scissors= no_inbody_headers= message_id=
>  git_apply_opt=
>  committer_date_is_author_date=
>  ignore_date=
> @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore."
>  		gpg_sign_opt=-S ;;
>  	--gpg-sign=*)
>  		gpg_sign_opt="-S${1#--gpg-sign=}" ;;
> +	-m|--message-id)
> +		message_id=t ;;
>  	--)
>  		shift; break ;;
>  	*)
> @@ -565,6 +568,7 @@ Use \"git am --abort\" to remove it.")"
>  	echo " $git_apply_opt" >"$dotest/apply-opt"
>  	echo "$threeway" >"$dotest/threeway"
>  	echo "$sign" >"$dotest/sign"
> +	echo "$message_id" > "$dotest/message-id"
>  	echo "$utf8" >"$dotest/utf8"
>  	echo "$keep" >"$dotest/keep"
>  	echo "$scissors" >"$dotest/scissors"
> @@ -757,6 +761,10 @@ To restore the original branch and stop patching run \"\$cmdline --abort\"."
>  		then
>  			cat "$dotest/msg-clean"
>  		fi
> +		if test 't' == "$message_id"
The == is bash special, please use = instead
And the 't' can be written as t, so that the whole line looks like this:
		if test t = "$message_id"
Avi Kivity· Jul 2, 2014, 13:54 UTC · re: Torsten Bögershausen · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

On 07/02/2014 12:58 PM, Torsten Bögershausen wrote:
Show 9 quoted lines
>> @@ -757,6 +761,10 @@ To restore the original branch and stop patching run \"\$cmdline --abort\"."
>>   		then
>>   			cat "$dotest/msg-clean"
>>   		fi
>> +		if test 't' == "$message_id"
> The == is bash special, please use = instead
> And the 't' can be written as t, so that the whole line looks like this:
> 		if test t = "$message_id"
>
Thanks.  v3 posted with these changes.
Fabian Ruch· Jul 2, 2014, 14:18 UTC · re: Avi Kivity · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

Hi Avi,
On 07/02/2014 10:51 AM, Avi Kivity wrote:
Show 87 quoted lines
> Some workflows prefer to track exactly which email message was used to
> generate a commit.  This can be used, for example, to generate an
> automated acknowledgement when a patch is committed as a response to
> the patch email, or as a reference to the thread which introduced the
> patch.
> 
> Support this by adding a --message-id option (abbreviated as -m) to
> git-am, which will then extract the message ID and append it to the
> email commit log.
> 
> Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
> ---
> 
> v2: adjust to pass test suite (t5100)
> 
>  Documentation/git-am.txt |  6 ++++++
>  builtin/mailinfo.c       |  2 +-
>  git-am.sh                | 10 +++++++++-
>  t/t5100/info0004         |  1 +
>  t/t5100/info0005         |  1 +
>  t/t5100/info0012         |  1 +
>  6 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
> index 9adce37..8a251a1 100644
> --- a/Documentation/git-am.txt
> +++ b/Documentation/git-am.txt
> @@ -15,6 +15,7 @@ SYNOPSIS
>  	 [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
>  	 [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
>  	 [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
> +	 [--message-id]
>  	 [(<mbox> | <Maildir>)...]
>  'git am' (--continue | --skip | --abort)
>  
> @@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
>  	user to lie about the author date by using the same
>  	value as the committer date.
>  
> +-m::
> +--message-id::
> +	Extract the Message-Id: header from the e-mail and
> +	append it to the commit message's tag stanza.
> +
>  --skip::
>  	Skip the current patch.  This is only meaningful when
>  	restarting an aborted patch.
> diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
> index cf11c8d..f1e1fed 100644
> --- a/builtin/mailinfo.c
> +++ b/builtin/mailinfo.c
> @@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
>  
>  static void decode_header(struct strbuf *line);
>  static const char *header[MAX_HDR_PARSED] = {
> -	"From","Subject","Date",
> +	"From","Subject","Date","Message-Id"
>  };
>  
>  static inline int cmp_header(const struct strbuf *line, const char *hdr)
> diff --git a/git-am.sh b/git-am.sh
> index ee61a77..c0e7bdd 100755
> --- a/git-am.sh
> +++ b/git-am.sh
> @@ -39,6 +39,7 @@ committer-date-is-author-date    lie about committer date
>  ignore-date     use current timestamp for author date
>  rerere-autoupdate update the index with reused conflict resolution if possible
>  S,gpg-sign?     GPG-sign commits
> +m,message-id    copy the Message-Id: header to the commit's tag stanza
>  rebasing*       (internal use for git-rebase)"
>  
>  . git-sh-setup
> @@ -371,7 +372,7 @@ split_patches () {
>  prec=4
>  dotest="$GIT_DIR/rebase-apply"
>  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
> -resolvemsg= resume= scissors= no_inbody_headers=
> +resolvemsg= resume= scissors= no_inbody_headers= message_id=
>  git_apply_opt=
>  committer_date_is_author_date=
>  ignore_date=
> @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore."
>  		gpg_sign_opt=-S ;;
>  	--gpg-sign=*)
>  		gpg_sign_opt="-S${1#--gpg-sign=}" ;;
> +	-m|--message-id)
> +		message_id=t ;;

Doesn't the message-id line in OPTIONS_SPEC make the negated long option --no-message-id available as well? If that's the case, then the corresponding case arm is missing from here.

Show 8 quoted lines
>  	--)
>  		shift; break ;;
>  	*)
> @@ -565,6 +568,7 @@ Use \"git am --abort\" to remove it.")"
>  	echo " $git_apply_opt" >"$dotest/apply-opt"
>  	echo "$threeway" >"$dotest/threeway"
>  	echo "$sign" >"$dotest/sign"
> +	echo "$message_id" > "$dotest/message-id"

To match the local style conventions, the space character after the redirection operator should be removed.

Also, isn't the patch missing the bits where the state of message-id is read? Like so:

    if test "$(cat "$dotest/message-id")" = t
    then
    	message_id=t
    fi
Show 10 quoted lines
>  	echo "$utf8" >"$dotest/utf8"
>  	echo "$keep" >"$dotest/keep"
>  	echo "$scissors" >"$dotest/scissors"
> @@ -757,6 +761,10 @@ To restore the original branch and stop patching run \"\$cmdline --abort\"."
>  		then
>  			cat "$dotest/msg-clean"
>  		fi
> +		if test 't' == "$message_id"
> +		then
> +			grep ^Message-Id: "$dotest/info" || true

Why is the true guard needed here? The exit status of grep seems to never be checked.

Although I cannot come up with an example where this would matter, you might want to consider using the grep wrapper sane_grep from git-sh-setup.sh instead. It resets the environment variable GREP_OPTIONS before calling grep so that no unexpected user options come into play.

Show 6 quoted lines
> +		fi
>  		if test '' != "$ADD_SIGNOFF"
>  		then
>  			echo "$ADD_SIGNOFF"
> 
> [..]
   Fabian
Avi Kivity· Jul 2, 2014, 14:44 UTC · re: Fabian Ruch · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

On 07/02/2014 05:18 PM, Fabian Ruch wrote:
Show 93 quoted lines
> Hi Avi,
>
> On 07/02/2014 10:51 AM, Avi Kivity wrote:
>> Some workflows prefer to track exactly which email message was used to
>> generate a commit.  This can be used, for example, to generate an
>> automated acknowledgement when a patch is committed as a response to
>> the patch email, or as a reference to the thread which introduced the
>> patch.
>>
>> Support this by adding a --message-id option (abbreviated as -m) to
>> git-am, which will then extract the message ID and append it to the
>> email commit log.
>>
>> Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
>> ---
>>
>> v2: adjust to pass test suite (t5100)
>>
>>   Documentation/git-am.txt |  6 ++++++
>>   builtin/mailinfo.c       |  2 +-
>>   git-am.sh                | 10 +++++++++-
>>   t/t5100/info0004         |  1 +
>>   t/t5100/info0005         |  1 +
>>   t/t5100/info0012         |  1 +
>>   6 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
>> index 9adce37..8a251a1 100644
>> --- a/Documentation/git-am.txt
>> +++ b/Documentation/git-am.txt
>> @@ -15,6 +15,7 @@ SYNOPSIS
>>   	 [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
>>   	 [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
>>   	 [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
>> +	 [--message-id]
>>   	 [(<mbox> | <Maildir>)...]
>>   'git am' (--continue | --skip | --abort)
>>   
>> @@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
>>   	user to lie about the author date by using the same
>>   	value as the committer date.
>>   
>> +-m::
>> +--message-id::
>> +	Extract the Message-Id: header from the e-mail and
>> +	append it to the commit message's tag stanza.
>> +
>>   --skip::
>>   	Skip the current patch.  This is only meaningful when
>>   	restarting an aborted patch.
>> diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
>> index cf11c8d..f1e1fed 100644
>> --- a/builtin/mailinfo.c
>> +++ b/builtin/mailinfo.c
>> @@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
>>   
>>   static void decode_header(struct strbuf *line);
>>   static const char *header[MAX_HDR_PARSED] = {
>> -	"From","Subject","Date",
>> +	"From","Subject","Date","Message-Id"
>>   };
>>   
>>   static inline int cmp_header(const struct strbuf *line, const char *hdr)
>> diff --git a/git-am.sh b/git-am.sh
>> index ee61a77..c0e7bdd 100755
>> --- a/git-am.sh
>> +++ b/git-am.sh
>> @@ -39,6 +39,7 @@ committer-date-is-author-date    lie about committer date
>>   ignore-date     use current timestamp for author date
>>   rerere-autoupdate update the index with reused conflict resolution if possible
>>   S,gpg-sign?     GPG-sign commits
>> +m,message-id    copy the Message-Id: header to the commit's tag stanza
>>   rebasing*       (internal use for git-rebase)"
>>   
>>   . git-sh-setup
>> @@ -371,7 +372,7 @@ split_patches () {
>>   prec=4
>>   dotest="$GIT_DIR/rebase-apply"
>>   sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
>> -resolvemsg= resume= scissors= no_inbody_headers=
>> +resolvemsg= resume= scissors= no_inbody_headers= message_id=
>>   git_apply_opt=
>>   committer_date_is_author_date=
>>   ignore_date=
>> @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore."
>>   		gpg_sign_opt=-S ;;
>>   	--gpg-sign=*)
>>   		gpg_sign_opt="-S${1#--gpg-sign=}" ;;
>> +	-m|--message-id)
>> +		message_id=t ;;
> Doesn't the message-id line in OPTIONS_SPEC make the negated long
> option --no-message-id available as well? If that's the case, then
> the corresponding case arm is missing from here.

I don't know, but some other booleans don't supply negations, for example --reject.

Show 10 quoted lines
>>   	--)
>>   		shift; break ;;
>>   	*)
>> @@ -565,6 +568,7 @@ Use \"git am --abort\" to remove it.")"
>>   	echo " $git_apply_opt" >"$dotest/apply-opt"
>>   	echo "$threeway" >"$dotest/threeway"
>>   	echo "$sign" >"$dotest/sign"
>> +	echo "$message_id" > "$dotest/message-id"
> To match the local style conventions, the space character after the
> redirection operator should be removed.
Sure.
Show 7 quoted lines
> Also, isn't the patch missing the bits where the state of message-id
> is read? Like so:
>
>      if test "$(cat "$dotest/message-id")" = t
>      then
>      	message_id=t
>      fi
Good catch, I guess this fixes a restarted am.
Show 13 quoted lines
>
>>   	echo "$utf8" >"$dotest/utf8"
>>   	echo "$keep" >"$dotest/keep"
>>   	echo "$scissors" >"$dotest/scissors"
>> @@ -757,6 +761,10 @@ To restore the original branch and stop patching run \"\$cmdline --abort\"."
>>   		then
>>   			cat "$dotest/msg-clean"
>>   		fi
>> +		if test 't' == "$message_id"
>> +		then
>> +			grep ^Message-Id: "$dotest/info" || true
> Why is the true guard needed here? The exit status of grep seems to
> never be checked.
I usually code scripts with -e, but here it's unneeded.
Show 6 quoted lines
>
> Although I cannot come up with an example where this would matter,
> you might want to consider using the grep wrapper sane_grep from
> git-sh-setup.sh instead. It resets the environment variable
> GREP_OPTIONS before calling grep so that no unexpected user options
> come into play.
Good idea.  Will post a v4 shortly.
Junio C Hamano· Jul 2, 2014, 17:17 UTC · re: Avi Kivity · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

Avi Kivity <avi@cloudius-systems.com> writes:
Show 7 quoted lines
> +		if test 't' == "$message_id"
> +		then
> +			grep ^Message-Id: "$dotest/info" || true
> +		fi
>  		if test '' != "$ADD_SIGNOFF"
>  		then
>  			echo "$ADD_SIGNOFF"

Seeing how existing code carefully makes sure that ADD_SIGNOFF has an empty line before it when and only when necessary to ensure that there is a blank after the existing log message, I would suspect that this patch that blindly inserts a line is doubly wrong. The output from "grep" may be appended without adding a blank when necessary, and appending of ADD_SIGNOFF may end up adding an extra blank after Message-Id. Am I reading the patch wrong?

Avi Kivity· Jul 3, 2014, 14:08 UTC · re: Junio C Hamano · lore

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

On 07/02/2014 08:17 PM, Junio C Hamano wrote:
Show 16 quoted lines
> Avi Kivity <avi@cloudius-systems.com> writes:
>
>> +		if test 't' == "$message_id"
>> +		then
>> +			grep ^Message-Id: "$dotest/info" || true
>> +		fi
>>   		if test '' != "$ADD_SIGNOFF"
>>   		then
>>   			echo "$ADD_SIGNOFF"
> Seeing how existing code carefully makes sure that ADD_SIGNOFF has
> an empty line before it when and only when necessary to ensure that
> there is a blank after the existing log message, I would suspect
> that this patch that blindly inserts a line is doubly wrong.  The
> output from "grep" may be appended without adding a blank when
> necessary, and appending of ADD_SIGNOFF may end up adding an extra
> blank after Message-Id.  Am I reading the patch wrong?

Yes, you're right. Will have to redo the logic for deciding whether we already have a tag stanza or not.

← back to recent threads