This fixes a bug where the scissors line is placed after the Conflicts:
section, in the case where a merge conflict occurs and
commit.cleanup = scissors.

Next, if commit.cleanup = scissors is specified, don't produce a
scissors line in commit if one already exists in the MERGE_MSG file.

Helped-by: Eric Sunshine <sunsh...@sunshineco.com>
Signed-off-by: Denton Liu <liu.den...@gmail.com>
---
 Documentation/merge-options.txt |  7 +++--
 builtin/commit.c                | 20 ++++++++++----
 builtin/merge.c                 | 14 ++++++++++
 t/t7600-merge.sh                | 46 +++++++++++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index bcf0b3e49c..61876dbc33 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -33,8 +33,11 @@ updated behaviour, the environment variable 
`GIT_MERGE_AUTOEDIT` can be
 set to `no` at the beginning of them.
 
 --cleanup=<mode>::
-       This option determines how the merge message will be cleaned up
-       before commiting. See linkgit:git-commit[1] for more details.
+       This option determines how the merge message will be cleaned up before
+       commiting. See linkgit:git-commit[1] for more details. In addition, if
+       the '<mode>' is given a value of `scissors`, scissors will be appended
+       to `MERGE_MSG` before being passed on to the commit machinery in the
+       case of a merge conflict.
 
 --ff::
        When the merge resolves as a fast-forward, only update the branch
diff --git a/builtin/commit.c b/builtin/commit.c
index ba1e6027ba..b9159c2e7b 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -668,6 +668,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
        const char *hook_arg2 = NULL;
        int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE);
        int old_display_comment_prefix;
+       int merge_contains_scissors = 0;
 
        /* This checks and barfs if author is badly specified */
        determine_author_info(author_ident);
@@ -728,6 +729,8 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
                        strbuf_addbuf(&sb, &message);
                hook_arg1 = "message";
        } else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
+               size_t merge_msg_start;
+
                /*
                 * prepend SQUASH_MSG here if it exists and a
                 * "merge --squash" was originally performed
@@ -738,8 +741,14 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
                        hook_arg1 = "squash";
                } else
                        hook_arg1 = "merge";
+
+               merge_msg_start = sb.len;
                if (strbuf_read_file(&sb, git_path_merge_msg(the_repository), 
0) < 0)
                        die_errno(_("could not read MERGE_MSG"));
+
+               if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
+                   wt_status_locate_end(sb.buf + merge_msg_start, sb.len - 
merge_msg_start) < sb.len - merge_msg_start)
+                       merge_contains_scissors = 1;
        } else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
                if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 
0) < 0)
                        die_errno(_("could not read SQUASH_MSG"));
@@ -807,7 +816,8 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
                struct ident_split ci, ai;
 
                if (whence != FROM_COMMIT) {
-                       if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS)
+                       if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
+                               !merge_contains_scissors)
                                wt_status_add_cut_line(s->fp);
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                            whence == FROM_MERGE
@@ -832,10 +842,10 @@ static int prepare_to_commit(const char *index_file, 
const char *prefix,
                                _("Please enter the commit message for your 
changes."
                                  " Lines starting\nwith '%c' will be ignored, 
and an empty"
                                  " message aborts the commit.\n"), 
comment_line_char);
-               else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
-                        whence == FROM_COMMIT)
-                       wt_status_add_cut_line(s->fp);
-               else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
+               else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
+                       if (whence == FROM_COMMIT && !merge_contains_scissors)
+                               wt_status_add_cut_line(s->fp);
+               } else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
                        status_printf(s, GIT_COLOR_NORMAL,
                                _("Please enter the commit message for your 
changes."
                                  " Lines starting\n"
diff --git a/builtin/merge.c b/builtin/merge.c
index f5783a901d..148554f08e 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -920,6 +920,20 @@ static int suggest_conflicts(void)
        filename = git_path_merge_msg(the_repository);
        fp = xfopen(filename, "a");
 
+       /*
+        * We can't use cleanup_mode because if we're not using the editor,
+        * get_cleanup_mode will return COMMIT_MSG_CLEANUP_SPACE instead, even
+        * though the message is meant to be processed later by git-commit.
+        * Thus, we will get the cleanup mode which is returned when we _are_ 
using
+        * an editor.
+        */
+       if (get_cleanup_mode(cleanup_arg, 1, 1) == COMMIT_MSG_CLEANUP_SCISSORS) 
{
+           fputc('\n', fp);
+           wt_status_add_cut_line(fp);
+           /* comments out the newline from append_conflicts_hint */
+           fputc(comment_line_char, fp);
+       }
+
        append_conflicts_hint(&the_index, &msgbuf);
        fputs(msgbuf.buf, fp);
        strbuf_release(&msgbuf);
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2f4c2801fb..7f9c68cbe7 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -246,6 +246,52 @@ test_expect_success 'merge --squash c3 with c7' '
        test_cmp expect actual
 '
 
+test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' '
+       git config commit.cleanup scissors &&
+       git reset --hard c3 &&
+       test_must_fail git merge c7 &&
+       cat result.9z >file &&
+       git commit --no-edit -a &&
+
+       cat >expect <<-\EOF &&
+       Merge tag '"'"'c7'"'"'
+
+       # ------------------------ >8 ------------------------
+       # Do not modify or remove the line above.
+       # Everything below it will be ignored.
+       #
+       # Conflicts:
+       #       file
+       EOF
+       git cat-file commit HEAD >raw &&
+       sed -e '1,/^$/d' raw >actual &&
+       test_i18ncmp expect actual
+'
+
+test_expect_success 'merge c3 with c7 with --squash commit.cleanup = scissors' 
'
+       git config commit.cleanup scissors &&
+       git reset --hard c3 &&
+       test_must_fail git merge --squash c7 &&
+       cat result.9z >file &&
+       git commit --no-edit -a &&
+
+       cat >expect <<-EOF &&
+       Squashed commit of the following:
+
+       $(git show -s c7)
+
+       # ------------------------ >8 ------------------------
+       # Do not modify or remove the line above.
+       # Everything below it will be ignored.
+       #
+       # Conflicts:
+       #       file
+       EOF
+       git cat-file commit HEAD >raw &&
+       sed -e '1,/^$/d' raw >actual &&
+       test_i18ncmp expect actual
+'
+
 test_debug 'git log --graph --decorate --oneline --all'
 
 test_expect_success 'merge c1 with c2 and c3' '
-- 
2.21.0.512.g57bf1b23e1

Reply via email to