From 073bd75e177aa9f1fc42b152a38e251c7156dfe0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Oct 2014 12:44:09 -0700 Subject: builtin/commit.c: extract ignore_non_trailer() helper function Extract a helper function from prepare_to_commit() to determine where to place a new Signed-off-by: line, which is essentially the true "end" of the log message, ignoring the trailing "Conflicts:" line and everything below it. The detection _should_ make sure the "Conflicts:" line it finds is truly the conflict hint block by checking everything that follows is a HT indented pathname to avoid false positive, but this logic will be revamped in a later patch to ignore comments and blanks anyway, so it is left as-is in this step. Signed-off-by: Junio C Hamano --- builtin/commit.c | 59 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 26 deletions(-) (limited to 'builtin/commit.c') diff --git a/builtin/commit.c b/builtin/commit.c index fedb45af8c..cd455aa36b 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -593,6 +593,37 @@ static char *cut_ident_timestamp_part(char *string) return ket; } +/* + * Inspect sb and determine the true "end" of the log message, in + * order to find where to put a new Signed-off-by: line. Ignored are + * trailing "Conflict:" block. + * + * Returns the number of bytes from the tail to ignore, to be fed as + * the second parameter to append_signoff(). + */ +static int ignore_non_trailer(struct strbuf *sb) +{ + int ignore_footer = 0; + int i, eol, previous = 0; + const char *nl; + + 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; + } + return ignore_footer; +} + static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *current_head, struct wt_status *s, @@ -718,32 +749,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, if (clean_message_contents) stripspace(&sb, 0); - if (signoff) { - /* - * 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; - - 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; - } - - append_signoff(&sb, ignore_footer, 0); - } + if (signoff) + append_signoff(&sb, ignore_non_trailer(&sb), 0); if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) die_errno(_("could not write commit template")); -- cgit v1.2.3 From 261f315bebfa9af2d09f20211960100ff06f87cb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 28 Oct 2014 13:04:38 -0700 Subject: merge & sequencer: turn "Conflicts:" hint into a comment Just like other hints such as "Changes to be committed" we show in the editor to remind the committer what paths were involved in the resulting commit to help improving their log message, this section is merely a reminder. Traditionally, it was not made into comments primarily because it has to be generated outside the wt-status infrastructure, and also because it was meant as a bit stronger reminder than the others (i.e. explaining how you resolved conflicts is much more important than mentioning what you did to every paths involved in the commit). But that still does not make this hint a part of the log message proper, and not showing it as a comment is inviting mistakes. Note that we still notice "Conflicts:" followed by list of indented pathnames as an old-style cruft and insert a new Signed-off-by: before it. This is so that "commit --amend -s" adds the new S-o-b at the right place when used on an older commit. Signed-off-by: Junio C Hamano --- builtin/commit.c | 47 +++++++++++++++++++++++++++-------------- sequencer.c | 7 +++--- t/t3507-cherry-pick-conflict.sh | 42 +++++++++++++++++++++++++++++------- 3 files changed, 68 insertions(+), 28 deletions(-) (limited to 'builtin/commit.c') diff --git a/builtin/commit.c b/builtin/commit.c index cd455aa36b..0a78e7649b 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -596,32 +596,47 @@ static char *cut_ident_timestamp_part(char *string) /* * Inspect sb and determine the true "end" of the log message, in * order to find where to put a new Signed-off-by: line. Ignored are - * trailing "Conflict:" block. + * trailing comment lines and blank lines, and also the traditional + * "Conflicts:" block that is not commented out, so that we can use + * "git commit -s --amend" on an existing commit that forgot to remove + * it. * * Returns the number of bytes from the tail to ignore, to be fed as * the second parameter to append_signoff(). */ static int ignore_non_trailer(struct strbuf *sb) { - int ignore_footer = 0; - int i, eol, previous = 0; - const char *nl; + int boc = 0; + int bol = 0; + int in_old_conflicts_block = 0; - for (i = 0; i < sb->len; i++) { - nl = memchr(sb->buf + i, '\n', sb->len - i); - if (nl) - eol = nl - sb->buf; + while (bol < sb->len) { + char *next_line; + + if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol))) + next_line = sb->buf + sb->len; else - eol = sb->len; - if (!prefixcmp(sb->buf + previous, "\nConflicts:\n")) { - ignore_footer = sb->len - previous; - break; + next_line++; + + if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') { + /* is this the first of the run of comments? */ + if (!boc) + boc = bol; + /* otherwise, it is just continuing */ + } else if (!prefixcmp(sb->buf + bol, "Conflicts:\n")) { + in_old_conflicts_block = 1; + if (!boc) + boc = bol; + } else if (in_old_conflicts_block && sb->buf[bol] == '\t') { + ; /* a pathname in the conflicts block */ + } else if (boc) { + /* the previous was not trailing comment */ + boc = 0; + in_old_conflicts_block = 0; } - while (i < eol) - i++; - previous = eol; + bol = next_line - sb->buf; } - return ignore_footer; + return boc ? sb->len - boc : 0; } static int prepare_to_commit(const char *index_file, const char *prefix, diff --git a/sequencer.c b/sequencer.c index 0f84bbeac6..1d97da3ca4 100644 --- a/sequencer.c +++ b/sequencer.c @@ -291,13 +291,12 @@ void append_conflicts_hint(struct strbuf *msgbuf) { int i; - strbuf_addstr(msgbuf, "\nConflicts:\n"); + strbuf_addch(msgbuf, '\n'); + strbuf_commented_addf(msgbuf, "Conflicts:\n"); for (i = 0; i < active_nr;) { const struct cache_entry *ce = active_cache[i++]; if (ce_stage(ce)) { - strbuf_addch(msgbuf, '\t'); - strbuf_addstr(msgbuf, ce->name); - strbuf_addch(msgbuf, '\n'); + strbuf_commented_addf(msgbuf, "\t%s\n", ce->name); while (i < active_nr && !strcmp(ce->name, active_cache[i]->name)) i++; diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 223b98433c..7c5ad08626 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -351,19 +351,45 @@ test_expect_success 'commit after failed cherry-pick does not add duplicated -s' 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 < expected && -picked -Signed-off-by: C O Mitter + # Do S-o-b and Conflicts appear in the right order? + cat <<-\EOF >expect && + Signed-off-by: C O Mitter + # Conflicts: + EOF + grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + test_cmp expect actual && + + cat <<-\EOF >expected && + picked -Conflicts: - foo -EOF + Signed-off-by: C O Mitter + EOF - git show -s --pretty=format:%B > actual && + git show -s --pretty=format:%B >actual && test_cmp expected actual ' +test_expect_success 'commit --amend -s places the sign-off at the right place' ' + pristine_detach initial && + test_must_fail git cherry-pick picked && + + # emulate old-style conflicts block + mv .git/MERGE_MSG .git/MERGE_MSG+ && + sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG && + + git commit -a && + git commit --amend -s && + + # Do S-o-b and Conflicts appear in the right order? + cat <<-\EOF >expect && + Signed-off-by: C O Mitter + Conflicts: + EOF + grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + test_cmp expect actual +' + test_done -- cgit v1.2.3 From 8c3845892363abf3fb5cf2fe61bc455554f50c68 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sun, 9 Nov 2014 10:23:41 +0100 Subject: commit: make ignore_non_trailer() non static Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/commit.c | 46 ---------------------------------------------- commit.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ commit.h | 3 +++ 3 files changed, 49 insertions(+), 46 deletions(-) (limited to 'builtin/commit.c') diff --git a/builtin/commit.c b/builtin/commit.c index 80a618fe13..537e228c3a 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -669,52 +669,6 @@ static void adjust_comment_line_char(const struct strbuf *sb) comment_line_char = *p; } -/* - * Inspect sb and determine the true "end" of the log message, in - * order to find where to put a new Signed-off-by: line. Ignored are - * trailing comment lines and blank lines, and also the traditional - * "Conflicts:" block that is not commented out, so that we can use - * "git commit -s --amend" on an existing commit that forgot to remove - * it. - * - * Returns the number of bytes from the tail to ignore, to be fed as - * the second parameter to append_signoff(). - */ -static int ignore_non_trailer(struct strbuf *sb) -{ - int boc = 0; - int bol = 0; - int in_old_conflicts_block = 0; - - while (bol < sb->len) { - char *next_line; - - if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol))) - next_line = sb->buf + sb->len; - else - next_line++; - - if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') { - /* is this the first of the run of comments? */ - if (!boc) - boc = bol; - /* otherwise, it is just continuing */ - } else if (starts_with(sb->buf + bol, "Conflicts:\n")) { - in_old_conflicts_block = 1; - if (!boc) - boc = bol; - } else if (in_old_conflicts_block && sb->buf[bol] == '\t') { - ; /* a pathname in the conflicts block */ - } else if (boc) { - /* the previous was not trailing comment */ - boc = 0; - in_old_conflicts_block = 0; - } - bol = next_line - sb->buf; - } - return boc ? sb->len - boc : 0; -} - static int prepare_to_commit(const char *index_file, const char *prefix, struct commit *current_head, struct wt_status *s, diff --git a/commit.c b/commit.c index ae7f2b10f4..07d2290d0d 100644 --- a/commit.c +++ b/commit.c @@ -1660,3 +1660,49 @@ void print_commit_list(struct commit_list *list, printf(format, sha1_to_hex(list->item->object.sha1)); } } + +/* + * Inspect sb and determine the true "end" of the log message, in + * order to find where to put a new Signed-off-by: line. Ignored are + * trailing comment lines and blank lines, and also the traditional + * "Conflicts:" block that is not commented out, so that we can use + * "git commit -s --amend" on an existing commit that forgot to remove + * it. + * + * Returns the number of bytes from the tail to ignore, to be fed as + * the second parameter to append_signoff(). + */ +int ignore_non_trailer(struct strbuf *sb) +{ + int boc = 0; + int bol = 0; + int in_old_conflicts_block = 0; + + while (bol < sb->len) { + char *next_line; + + if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol))) + next_line = sb->buf + sb->len; + else + next_line++; + + if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') { + /* is this the first of the run of comments? */ + if (!boc) + boc = bol; + /* otherwise, it is just continuing */ + } else if (starts_with(sb->buf + bol, "Conflicts:\n")) { + in_old_conflicts_block = 1; + if (!boc) + boc = bol; + } else if (in_old_conflicts_block && sb->buf[bol] == '\t') { + ; /* a pathname in the conflicts block */ + } else if (boc) { + /* the previous was not trailing comment */ + boc = 0; + in_old_conflicts_block = 0; + } + bol = next_line - sb->buf; + } + return boc ? sb->len - boc : 0; +} diff --git a/commit.h b/commit.h index a401ddfbc4..f87b392506 100644 --- a/commit.h +++ b/commit.h @@ -326,6 +326,9 @@ extern struct commit_extra_header *read_commit_extra_headers(struct commit *, co extern void free_commit_extra_headers(struct commit_extra_header *extra); +/* Find the end of the log message, the right place for a new trailer. */ +extern int ignore_non_trailer(struct strbuf *sb); + typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra, void *cb_data); -- cgit v1.2.3