merge & sequencer: turn "Conflicts:" hint into a comment
authorJunio C Hamano <gitster@pobox.com>
Tue, 28 Oct 2014 20:04:38 +0000 (13:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 Oct 2014 21:04:28 +0000 (14:04 -0700)
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 <gitster@pobox.com>
builtin/commit.c
sequencer.c
t/t3507-cherry-pick-conflict.sh
index cd455aa36b084c1c4d957568941414ff4e5c52ef..0a78e7649b579b3392dcd2958717671d8bf49db4 100644 (file)
@@ -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,
index 0f84bbeac6437a887b19f05515ebb8b1778f78b4..1d97da3ca478f70cee1ccd5a23a0773ca47bec49 100644 (file)
@@ -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++;
index 223b98433c502b03c4ba70550cb32d42a5f6295b..7c5ad086264e3d1c140da7fd996f27c1352a26a9 100755 (executable)
@@ -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 <<EOF > expected &&
-picked
 
-Signed-off-by: C O Mitter <committer@example.com>
+       # Do S-o-b and Conflicts appear in the right order?
+       cat <<-\EOF >expect &&
+       Signed-off-by: C O Mitter <committer@example.com>
+       # 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 <committer@example.com>
+       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 <committer@example.com>
+       Conflicts:
+       EOF
+       grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
+       test_cmp expect actual
+'
+
 test_done