sequencer.c: recognize "(cherry picked from ..." as part of s-o-b footer

When 'cherry-pick -s' is used to append a signed-off-by line to a cherry
picked commit, it does not currently detect the "(cherry picked from..."
that may have been appended by a previous 'cherry-pick -x' as part of the
s-o-b footer and it will insert a blank line before appending a new s-o-b.

Let's detect "(cherry picked from...)" as part of the footer so that we
will produce this:

   Signed-off-by: A U Thor <author@example.com>
   (cherry picked from da39a3ee5e6b4b0d3255bfef95601890afd80709)
   Signed-off-by: C O Mmitter <committer@example.com>

instead of this:

   Signed-off-by: A U Thor <author@example.com>
   (cherry picked from da39a3ee5e6b4b0d3255bfef95601890afd80709)

   Signed-off-by: C O Mmitter <committer@example.com>

[with improvements from Jonathan Nieder]

Signed-off-by: Brandon Casey <bcasey@nvidia.com>
Acked-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Brandon Casey
2013-02-12 02:17:32 -08:00
committed by Junio C Hamano
parent f2b9a7555b
commit cd650a4eee
2 changed files with 92 additions and 14 deletions

View File

@ -18,6 +18,7 @@
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
const char sign_off_header[] = "Signed-off-by: ";
static const char cherry_picked_prefix[] = "(cherry picked from commit ";
static void remove_sequencer_state(void)
{
@ -492,7 +493,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
}
if (opts->record_origin) {
strbuf_addstr(&msgbuf, "(cherry picked from commit ");
strbuf_addstr(&msgbuf, cherry_picked_prefix);
strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
strbuf_addstr(&msgbuf, ")\n");
}
@ -1017,16 +1018,44 @@ int sequencer_pick_revisions(struct replay_opts *opts)
return pick_commits(todo_list, opts);
}
static int ends_rfc2822_footer(struct strbuf *sb, int ignore_footer)
static int is_rfc2822_line(const char *buf, int len)
{
char ch, prev;
int i, j, k;
int i;
for (i = 0; i < len; i++) {
int ch = buf[i];
if (ch == ':')
return 1;
if (!isalnum(ch) && ch != '-')
break;
}
return 0;
}
static int is_cherry_picked_from_line(const char *buf, int len)
{
/*
* We only care that it looks roughly like (cherry picked from ...)
*/
return len > strlen(cherry_picked_prefix) + 1 &&
!prefixcmp(buf, cherry_picked_prefix) && buf[len - 1] == ')';
}
static int has_conforming_footer(struct strbuf *sb, int ignore_footer)
{
char prev;
int i, k;
int len = sb->len - ignore_footer;
const char *buf = sb->buf;
/* footer must end with newline */
if (!len || buf[len - 1] != '\n')
return 0;
prev = '\0';
for (i = len - 1; i > 0; i--) {
ch = buf[i];
char ch = buf[i];
if (prev == '\n' && ch == '\n') /* paragraph break */
break;
prev = ch;
@ -1041,15 +1070,9 @@ static int ends_rfc2822_footer(struct strbuf *sb, int ignore_footer)
; /* do nothing */
k++;
for (j = 0; i + j < len; j++) {
ch = buf[i + j];
if (ch == ':')
break;
if (isalnum(ch) ||
(ch == '-'))
continue;
if (!is_rfc2822_line(buf + i, k - i - 1) &&
!is_cherry_picked_from_line(buf + i, k - i - 1))
return 0;
}
}
return 1;
}
@ -1066,7 +1089,7 @@ void append_signoff(struct strbuf *msgbuf, int ignore_footer)
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))
if (!i || !has_conforming_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);
}