Start treating the "(cherry picked from" line added by cherry-pick -x the same way that the s-o-b lines are treated. Namely, separate them from the main commit message body with an empty line. Also, introduce tests to test this functionality. Signed-off-by: Brandon Casey <bcasey@xxxxxxxxxx> --- This seems like the right thing to do, but it's more of a change in policy than the others, so I marked it as RFC. Any disagreement here? -Brandon sequencer.c | 110 ++++++++++++++++++++++++----------------------- t/t3511-cherry-pick-x.sh | 77 +++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 54 deletions(-) diff --git a/sequencer.c b/sequencer.c index 27e684c..0da0538 100644 --- a/sequencer.c +++ b/sequencer.c @@ -20,6 +20,60 @@ const char sign_off_header[] = "Signed-off-by: "; const char cherry_picked_prefix[] = "(cherry picked from commit "; +static int is_rfc2822_line(const char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + int ch = buf[i]; + if (ch == ':') + break; + if (isalnum(ch) || (ch == '-')) + continue; + return 0; + } + + return 1; +} + +static int is_cherry_pick_from_line(const char *buf, int len) +{ + return (strlen(cherry_picked_prefix) + 41) <= len && + !prefixcmp(buf, cherry_picked_prefix); +} + +static int ends_rfc2822_footer(struct strbuf *sb, int ignore_footer) +{ + int hit = 0; + int i, k; + int len = sb->len - ignore_footer; + int last_was_rfc2822 = 0; + 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 (last_was_rfc2822 && (buf[i] == ' ' || buf[i] == '\t')) + continue; + + if (!((last_was_rfc2822 = is_rfc2822_line(buf+i, k-i)) || + is_cherry_pick_from_line(buf+i, k-i))) + return 0; + } + return 1; +} + static void remove_sequencer_state(void) { struct strbuf seq_dir = STRBUF_INIT; @@ -493,6 +547,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) } if (opts->record_origin) { + if (!ends_rfc2822_footer(&msgbuf, 0)) + strbuf_addch(&msgbuf, '\n'); strbuf_addstr(&msgbuf, cherry_picked_prefix); strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1)); strbuf_addstr(&msgbuf, ")\n"); @@ -1018,60 +1074,6 @@ int sequencer_pick_revisions(struct replay_opts *opts) return pick_commits(todo_list, opts); } -static int is_rfc2822_line(const char *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - int ch = buf[i]; - if (ch == ':') - break; - if (isalnum(ch) || (ch == '-')) - continue; - return 0; - } - - return 1; -} - -static int is_cherry_pick_from_line(const char *buf, int len) -{ - return (strlen(cherry_picked_prefix) + 41) <= len && - !prefixcmp(buf, cherry_picked_prefix); -} - -static int ends_rfc2822_footer(struct strbuf *sb, int ignore_footer) -{ - int hit = 0; - int i, k; - int len = sb->len - ignore_footer; - int last_was_rfc2822 = 0; - 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 (last_was_rfc2822 && (buf[i] == ' ' || buf[i] == '\t')) - continue; - - if (!((last_was_rfc2822 = is_rfc2822_line(buf+i, k-i)) || - is_cherry_pick_from_line(buf+i, k-i))) - return 0; - } - return 1; -} - void append_signoff(struct strbuf *msgbuf, int ignore_footer) { struct strbuf sob = STRBUF_INIT; diff --git a/t/t3511-cherry-pick-x.sh b/t/t3511-cherry-pick-x.sh index 785486e..af7a87c 100755 --- a/t/t3511-cherry-pick-x.sh +++ b/t/t3511-cherry-pick-x.sh @@ -40,6 +40,19 @@ test_expect_success setup ' test_commit conflicting unrelated ' +test_expect_success 'cherry-pick -x inserts blank line after non-rfc2822 footer' ' + pristine_detach initial && + sha1=`git rev-parse non-rfc2822-base^0` && + git cherry-pick -x non-rfc2822-base && + cat <<-EOF >expect && + $non_rfc2822_mesg + + (cherry picked from commit $sha1) + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + test_expect_success 'cherry-pick -s inserts blank line after non-rfc2822 footer' ' pristine_detach initial && git cherry-pick -s non-rfc2822-base && @@ -52,6 +65,32 @@ test_expect_success 'cherry-pick -s inserts blank line after non-rfc2822 footer' test_cmp expect actual ' +test_expect_success 'cherry-pick -x -s inserts blank line after non-rfc2822 footer' ' + pristine_detach initial && + sha1=`git rev-parse non-rfc2822-base^0` && + git cherry-pick -x -s non-rfc2822-base && + cat <<-EOF >expect && + $non_rfc2822_mesg + + (cherry picked from commit $sha1) + Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + +test_expect_success 'cherry-pick -x not confused by rfc2822 continuation line' ' + pristine_detach initial && + sha1=`git rev-parse rfc2822-base^0` && + git cherry-pick -x rfc2822-base && + cat <<-EOF >expect && + $rfc2822_mesg + (cherry picked from commit $sha1) + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + test_expect_success 'cherry-pick -s not confused by rfc2822 continuation line' ' pristine_detach initial && git cherry-pick -s rfc2822-base && @@ -63,6 +102,31 @@ test_expect_success 'cherry-pick -s not confused by rfc2822 continuation line' ' test_cmp expect actual ' +test_expect_success 'cherry-pick -x -s not confused by rfc2822 continuation line' ' + pristine_detach initial && + sha1=`git rev-parse rfc2822-base^0` && + git cherry-pick -x -s rfc2822-base && + cat <<-EOF >expect && + $rfc2822_mesg + (cherry picked from commit $sha1) + Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + +test_expect_success 'cherry-pick treats -x "(cherry picked from..." line as part of footer' ' + pristine_detach initial && + sha1=`git rev-parse rfc2822-cherry-base^0` && + git cherry-pick -x rfc2822-cherry-base && + cat <<-EOF >expect && + $rfc2822_cherry_mesg + (cherry picked from commit $sha1) + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + test_expect_success 'cherry-pick treats -s "(cherry picked from..." line as part of footer' ' pristine_detach initial && git cherry-pick -s rfc2822-cherry-base && @@ -74,4 +138,17 @@ test_expect_success 'cherry-pick treats -s "(cherry picked from..." line as part test_cmp expect actual ' +test_expect_success 'cherry-pick treats -x -s "(cherry picked from..." line as part of footer' ' + pristine_detach initial && + sha1=`git rev-parse rfc2822-cherry-base^0` && + git cherry-pick -x -s rfc2822-cherry-base && + cat <<-EOF >expect && + $rfc2822_cherry_mesg + (cherry picked from commit $sha1) + Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> + EOF + git log -1 --pretty=format:%B >actual && + test_cmp expect actual +' + test_done -- 1.8.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html