diff options
-rw-r--r-- | Documentation/git-cherry-pick.txt | 7 | ||||
-rw-r--r-- | Documentation/git-revert.txt | 7 | ||||
-rw-r--r-- | Documentation/merge-options.txt | 7 | ||||
-rw-r--r-- | builtin/commit.c | 49 | ||||
-rw-r--r-- | builtin/merge.c | 51 | ||||
-rw-r--r-- | builtin/pull.c | 12 | ||||
-rw-r--r-- | builtin/revert.c | 7 | ||||
-rw-r--r-- | builtin/tag.c | 3 | ||||
-rw-r--r-- | parse-options.h | 1 | ||||
-rw-r--r-- | sequencer.c | 73 | ||||
-rw-r--r-- | sequencer.h | 9 | ||||
-rwxr-xr-x | t/t3507-cherry-pick-conflict.sh | 128 | ||||
-rwxr-xr-x | t/t5521-pull-options.sh | 8 | ||||
-rwxr-xr-x | t/t7502-commit-porcelain.sh | 93 | ||||
-rwxr-xr-x | t/t7600-merge.sh | 73 | ||||
-rwxr-xr-x | t/t7604-merge-custom-message.sh | 75 | ||||
-rw-r--r-- | wt-status.c | 12 | ||||
-rw-r--r-- | wt-status.h | 1 |
18 files changed, 484 insertions, 132 deletions
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index d64e72462f..754b16ce0c 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -57,6 +57,13 @@ OPTIONS With this option, 'git cherry-pick' will let you edit the commit message prior to committing. +--cleanup=<mode>:: + This option determines how the commit message will be cleaned up before + being passed on to the commit machinery. See linkgit:git-commit[1] for more + details. In particular, if the '<mode>' is given a value of `scissors`, + scissors will be appended to `MERGE_MSG` before being passed on in the case + of a conflict. + -x:: When recording the commit, append a line that says "(cherry picked from commit ...)" to the original commit diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 6afccb2f1e..0c82ca5bc0 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -66,6 +66,13 @@ more details. With this option, 'git revert' will not start the commit message editor. +--cleanup=<mode>:: + This option determines how the commit message will be cleaned up before + being passed on to the commit machinery. See linkgit:git-commit[1] for more + details. In particular, if the '<mode>' is given a value of `scissors`, + scissors will be appended to `MERGE_MSG` before being passed on in the case + of a conflict. + -n:: --no-commit:: Usually the command automatically creates some commits with diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 92a7d936c1..61876dbc33 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -32,6 +32,13 @@ they run `git merge`. To make it easier to adjust such scripts to the 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. 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 pointer, without creating a merge commit. This is the default diff --git a/builtin/commit.c b/builtin/commit.c index 833ecb316a..bd4b180c43 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,16 @@ 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 +818,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 +844,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" @@ -1172,24 +1184,7 @@ static int parse_and_validate_options(int argc, const char *argv[], die(_("Only one of --include/--only/--all/--interactive/--patch can be used.")); if (argc == 0 && (also || (only && !amend && !allow_empty))) die(_("No paths with --include/--only does not make sense.")); - if (!cleanup_arg || !strcmp(cleanup_arg, "default")) - cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_ALL : - COMMIT_MSG_CLEANUP_SPACE; - else if (!strcmp(cleanup_arg, "verbatim")) - cleanup_mode = COMMIT_MSG_CLEANUP_NONE; - else if (!strcmp(cleanup_arg, "whitespace")) - cleanup_mode = COMMIT_MSG_CLEANUP_SPACE; - else if (!strcmp(cleanup_arg, "strip")) - cleanup_mode = COMMIT_MSG_CLEANUP_ALL; - else if (!strcmp(cleanup_arg, "scissors")) - cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_SCISSORS : - COMMIT_MSG_CLEANUP_SPACE; - /* - * Please update _git_commit() in git-completion.bash when you - * add new options. - */ - else - die(_("Invalid cleanup mode %s"), cleanup_arg); + cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor); handle_untracked_files_arg(s); @@ -1491,7 +1486,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")), OPT_FILENAME('t', "template", &template_file, N_("use specified template file")), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")), - OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")), + OPT_CLEANUP(&cleanup_arg), OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")), { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, @@ -1627,11 +1622,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) die(_("could not read commit message: %s"), strerror(saved_errno)); } - if (verbose || /* Truncate the message just before the diff, if any. */ - cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) - strbuf_setlen(&sb, wt_status_locate_end(sb.buf, sb.len)); - if (cleanup_mode != COMMIT_MSG_CLEANUP_NONE) - strbuf_stripspace(&sb, cleanup_mode == COMMIT_MSG_CLEANUP_ALL); + cleanup_message(&sb, cleanup_mode, verbose); if (message_is_empty(&sb, cleanup_mode) && !allow_empty_message) { rollback_index_files(); diff --git a/builtin/merge.c b/builtin/merge.c index 5ce8946d39..e96f72af80 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -38,6 +38,7 @@ #include "tag.h" #include "alias.h" #include "commit-reach.h" +#include "wt-status.h" #define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_OCTOPUS (1<<1) @@ -98,6 +99,9 @@ enum ff_type { static enum ff_type fast_forward = FF_ALLOW; +static const char *cleanup_arg; +static enum commit_msg_cleanup_mode cleanup_mode; + static int option_parse_message(const struct option *opt, const char *arg, int unset) { @@ -249,6 +253,7 @@ static struct option builtin_merge_options[] = { N_("perform a commit if the merge succeeds (default)")), OPT_BOOL('e', "edit", &option_edit, N_("edit message before committing")), + OPT_CLEANUP(&cleanup_arg), OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW), OPT_SET_INT_F(0, "ff-only", &fast_forward, N_("abort if fast-forward is not possible"), @@ -612,6 +617,8 @@ static int git_merge_config(const char *k, const char *v, void *cb) return git_config_string(&pull_twohead, k, v); else if (!strcmp(k, "pull.octopus")) return git_config_string(&pull_octopus, k, v); + else if (!strcmp(k, "commit.cleanup")) + return git_config_string(&cleanup_arg, k, v); else if (!strcmp(k, "merge.renormalize")) option_renormalize = git_config_bool(k, v); else if (!strcmp(k, "merge.ff")) { @@ -800,8 +807,13 @@ static void abort_commit(struct commit_list *remoteheads, const char *err_msg) static const char merge_editor_comment[] = N_("Please enter a commit message to explain why this merge is necessary,\n" "especially if it merges an updated upstream into a topic branch.\n" - "\n" - "Lines starting with '%c' will be ignored, and an empty message aborts\n" + "\n"); + +static const char scissors_editor_comment[] = +N_("An empty message aborts the commit.\n"); + +static const char no_scissors_editor_comment[] = +N_("Lines starting with '%c' will be ignored, and an empty message aborts\n" "the commit.\n"); static void write_merge_heads(struct commit_list *); @@ -809,11 +821,19 @@ static void prepare_to_commit(struct commit_list *remoteheads) { struct strbuf msg = STRBUF_INIT; strbuf_addbuf(&msg, &merge_msg); - strbuf_addch(&msg, '\n'); if (squash) BUG("the control must not reach here under --squash"); - if (0 < option_edit) - strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char); + if (0 < option_edit) { + strbuf_addch(&msg, '\n'); + if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { + wt_status_append_cut_line(&msg); + strbuf_commented_addf(&msg, "\n"); + } + strbuf_commented_addf(&msg, _(merge_editor_comment)); + strbuf_commented_addf(&msg, _(cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS ? + scissors_editor_comment : + no_scissors_editor_comment), comment_line_char); + } if (signoff) append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); write_merge_heads(remoteheads); @@ -832,7 +852,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) abort_commit(remoteheads, NULL); read_merge_msg(&msg); - strbuf_stripspace(&msg, 0 < option_edit); + cleanup_message(&msg, cleanup_mode, 0); if (!msg.len) abort_commit(remoteheads, _("Empty commit message.")); strbuf_release(&merge_msg); @@ -880,7 +900,6 @@ static int finish_automerge(struct commit *head, parents = remoteheads; if (!head_subsumed || fast_forward == FF_NO) commit_list_insert(head, &parents); - strbuf_addch(&merge_msg, '\n'); prepare_to_commit(remoteheads); if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents, &result_commit, NULL, sign_commit)) @@ -901,7 +920,15 @@ static int suggest_conflicts(void) filename = git_path_merge_msg(the_repository); fp = xfopen(filename, "a"); - append_conflicts_hint(&the_index, &msgbuf); + /* + * 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. + */ + append_conflicts_hint(&the_index, &msgbuf, + get_cleanup_mode(cleanup_arg, 1)); fputs(msgbuf.buf, fp); strbuf_release(&msgbuf); fclose(fp); @@ -1301,6 +1328,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix) } resolve_undo_clear(); + if (option_edit < 0) + option_edit = default_edit_option(); + + cleanup_mode = get_cleanup_mode(cleanup_arg, 0 < option_edit); + if (verbosity < 0) show_diffstat = 0; @@ -1386,9 +1418,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) fast_forward = FF_NO; } - if (option_edit < 0) - option_edit = default_edit_option(); - if (!use_strategies) { if (!remoteheads) ; /* already up-to-date */ diff --git a/builtin/pull.c b/builtin/pull.c index 9bd6a78081..9dd32a115b 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -24,6 +24,7 @@ #include "lockfile.h" #include "wt-status.h" #include "commit-reach.h" +#include "sequencer.h" enum rebase_type { REBASE_INVALID = -1, @@ -101,6 +102,7 @@ static char *opt_signoff; static char *opt_squash; static char *opt_commit; static char *opt_edit; +static char *cleanup_arg; static char *opt_ff; static char *opt_verify_signatures; static int opt_autostash = -1; @@ -168,6 +170,7 @@ static struct option pull_options[] = { OPT_PASSTHRU(0, "edit", &opt_edit, NULL, N_("edit message before committing"), PARSE_OPT_NOARG), + OPT_CLEANUP(&cleanup_arg), OPT_PASSTHRU(0, "ff", &opt_ff, NULL, N_("allow fast-forward"), PARSE_OPT_NOARG), @@ -645,6 +648,8 @@ static int run_merge(void) argv_array_push(&args, opt_commit); if (opt_edit) argv_array_push(&args, opt_edit); + if (cleanup_arg) + argv_array_pushf(&args, "--cleanup=%s", cleanup_arg); if (opt_ff) argv_array_push(&args, opt_ff); if (opt_verify_signatures) @@ -876,6 +881,13 @@ int cmd_pull(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0); + if (cleanup_arg) + /* + * this only checks the validity of cleanup_arg; we don't need + * a valid value for use_editor + */ + get_cleanup_mode(cleanup_arg, 0); + parse_repo_refspecs(argc, argv, &repo, &refspecs); if (!opt_ff) diff --git a/builtin/revert.c b/builtin/revert.c index a47b53ceaf..d4dcedbdc6 100644 --- a/builtin/revert.c +++ b/builtin/revert.c @@ -96,11 +96,13 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) { const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char *me = action_name(opts); + const char *cleanup_arg = NULL; int cmd = 0; struct option base_options[] = { OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'), OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'), + OPT_CLEANUP(&cleanup_arg), OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")), OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")), OPT_NOOP_NOARG('r', NULL), @@ -137,6 +139,11 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts) if (opts->keep_redundant_commits) opts->allow_empty = 1; + if (cleanup_arg) { + opts->default_msg_cleanup = get_cleanup_mode(cleanup_arg, 1); + opts->explicit_cleanup = 1; + } + /* Check for incompatible command line arguments */ if (cmd) { char *this_operation; diff --git a/builtin/tag.c b/builtin/tag.c index 8399a0ed54..1debd3a11c 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -408,8 +408,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_FILENAME('F', "file", &msgfile, N_("read message from file")), OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")), OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")), - OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"), - N_("how to strip spaces and #comments from message")), + OPT_CLEANUP(&cleanup_arg), OPT_STRING('u', "local-user", &keyid, N_("key-id"), N_("use another key to sign the tag")), OPT__FORCE(&force, N_("replace the tag if exists"), 0), diff --git a/parse-options.h b/parse-options.h index cc9230adac..1dd3523c15 100644 --- a/parse-options.h +++ b/parse-options.h @@ -316,5 +316,6 @@ int parse_opt_passthru_argv(const struct option *, const char *, int); #define OPT_NO_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG) #define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG) #define OPT_WITHOUT(v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG) +#define OPT_CLEANUP(v) OPT_STRING(0, "cleanup", v, N_("mode"), N_("how to strip spaces and #comments from message")) #endif diff --git a/sequencer.c b/sequencer.c index 5da5949962..4407a3f978 100644 --- a/sequencer.c +++ b/sequencer.c @@ -181,7 +181,7 @@ static int git_sequencer_config(const char *k, const char *v, void *cb) opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_ALL; opts->explicit_cleanup = 1; } else if (!strcmp(s, "scissors")) { - opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SPACE; + opts->default_msg_cleanup = COMMIT_MSG_CLEANUP_SCISSORS; opts->explicit_cleanup = 1; } else { warning(_("invalid commit message cleanup mode '%s'"), @@ -515,11 +515,54 @@ static int fast_forward_to(struct repository *r, return 0; } +enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg, + int use_editor) +{ + if (!cleanup_arg || !strcmp(cleanup_arg, "default")) + return use_editor ? COMMIT_MSG_CLEANUP_ALL : + COMMIT_MSG_CLEANUP_SPACE; + else if (!strcmp(cleanup_arg, "verbatim")) + return COMMIT_MSG_CLEANUP_NONE; + else if (!strcmp(cleanup_arg, "whitespace")) + return COMMIT_MSG_CLEANUP_SPACE; + else if (!strcmp(cleanup_arg, "strip")) + return COMMIT_MSG_CLEANUP_ALL; + else if (!strcmp(cleanup_arg, "scissors")) + return use_editor ? COMMIT_MSG_CLEANUP_SCISSORS : + COMMIT_MSG_CLEANUP_SPACE; + else + die(_("Invalid cleanup mode %s"), cleanup_arg); +} + +/* + * NB using int rather than enum cleanup_mode to stop clang's + * -Wtautological-constant-out-of-range-compare complaining that the comparison + * is always true. + */ +static const char *describe_cleanup_mode(int cleanup_mode) +{ + static const char *modes[] = { "whitespace", + "verbatim", + "scissors", + "strip" }; + + if (cleanup_mode < ARRAY_SIZE(modes)) + return modes[cleanup_mode]; + + BUG("invalid cleanup_mode provided (%d)", cleanup_mode); +} + void append_conflicts_hint(struct index_state *istate, - struct strbuf *msgbuf) + struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode) { int i; + if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) { + strbuf_addch(msgbuf, '\n'); + wt_status_append_cut_line(msgbuf); + strbuf_addch(msgbuf, comment_line_char); + } + strbuf_addch(msgbuf, '\n'); strbuf_commented_addf(msgbuf, "Conflicts:\n"); for (i = 0; i < istate->cache_nr;) { @@ -587,7 +630,8 @@ static int do_recursive_merge(struct repository *r, _(action_name(opts))); if (!clean) - append_conflicts_hint(r->index, msgbuf); + append_conflicts_hint(r->index, msgbuf, + opts->default_msg_cleanup); return !clean; } @@ -906,7 +950,6 @@ static int run_git_commit(struct repository *r, unsigned int flags) { struct child_process cmd = CHILD_PROCESS_INIT; - const char *value; if ((flags & CREATE_ROOT_COMMIT) && !(flags & AMEND_MSG)) { struct strbuf msg = STRBUF_INIT, script = STRBUF_INIT; @@ -976,7 +1019,7 @@ static int run_git_commit(struct repository *r, argv_array_push(&cmd.args, "-e"); else if (!(flags & CLEANUP_MSG) && !opts->signoff && !opts->record_origin && - git_config_get_value("commit.cleanup", &value)) + !opts->explicit_cleanup) argv_array_push(&cmd.args, "--cleanup=verbatim"); if ((flags & ALLOW_EMPTY)) @@ -1017,6 +1060,16 @@ static int rest_is_empty(const struct strbuf *sb, int start) return 1; } +void cleanup_message(struct strbuf *msgbuf, + enum commit_msg_cleanup_mode cleanup_mode, int verbose) +{ + if (verbose || /* Truncate the message just before the diff, if any. */ + cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) + strbuf_setlen(msgbuf, wt_status_locate_end(msgbuf->buf, msgbuf->len)); + if (cleanup_mode != COMMIT_MSG_CLEANUP_NONE) + strbuf_stripspace(msgbuf, cleanup_mode == COMMIT_MSG_CLEANUP_ALL); +} + /* * Find out if the message in the strbuf contains only whitespace and * Signed-off-by lines. @@ -2313,7 +2366,10 @@ static int populate_opts_cb(const char *key, const char *value, void *data) opts->allow_rerere_auto = git_config_bool_or_int(key, value, &error_flag) ? RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE; - else + else if (!strcmp(key, "options.default-msg-cleanup")) { + opts->explicit_cleanup = 1; + opts->default_msg_cleanup = get_cleanup_mode(value, 1); + } else return error(_("invalid key: %s"), key); if (!error_flag) @@ -2735,6 +2791,11 @@ static int save_opts(struct replay_opts *opts) "options.allow-rerere-auto", opts->allow_rerere_auto == RERERE_AUTOUPDATE ? "true" : "false"); + + if (opts->explicit_cleanup) + res |= git_config_set_in_file_gently(opts_file, + "options.default-msg-cleanup", + describe_cleanup_mode(opts->default_msg_cleanup)); return res; } diff --git a/sequencer.h b/sequencer.h index b69e7686c9..75e292c03b 100644 --- a/sequencer.h +++ b/sequencer.h @@ -163,7 +163,14 @@ int todo_list_rearrange_squash(struct todo_list *todo_list); */ void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag); -void append_conflicts_hint(struct index_state *istate, struct strbuf *msgbuf); +void append_conflicts_hint(struct index_state *istate, + struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode); +enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg, + int use_editor); + +void cleanup_message(struct strbuf *msgbuf, + enum commit_msg_cleanup_mode cleanup_mode, int verbose); + int message_is_empty(const struct strbuf *sb, enum commit_msg_cleanup_mode cleanup_mode); int template_untouched(const struct strbuf *sb, const char *template_file, diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 1ef8e9d534..1a8818fbe0 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -93,7 +93,7 @@ test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' ' test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' ' pristine_detach initial && - echo foo > foo && + echo foo >foo && test_must_fail git cherry-pick base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' @@ -101,7 +101,7 @@ test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' ' test_expect_success \ 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' ' pristine_detach initial && - echo foo > foo && + echo foo >foo && test_must_fail git cherry-pick --strategy=resolve base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' @@ -180,23 +180,63 @@ test_expect_success 'failed cherry-pick registers participants in index' ' git ls-files --stage foo && git checkout picked -- foo && git ls-files --stage foo - } > stages && + } >stages && sed " 1 s/ 0 / 1 / 2 s/ 0 / 2 / 3 s/ 0 / 3 / - " < stages > expected && + " stages >expected && git read-tree -u --reset HEAD && test_must_fail git cherry-pick picked && - git ls-files --stage --unmerged > actual && + git ls-files --stage --unmerged >actual && test_cmp expected actual ' +test_expect_success \ + 'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' ' + pristine_detach initial && + git config commit.cleanup scissors && + cat <<-EOF >expected && + picked + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git cherry-pick picked && + + test_i18ncmp expected .git/MERGE_MSG +' + +test_expect_success \ + 'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' ' + pristine_detach initial && + git config --unset commit.cleanup && + cat <<-EOF >expected && + picked + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git cherry-pick --cleanup=scissors picked && + + test_i18ncmp expected .git/MERGE_MSG +' + test_expect_success 'failed cherry-pick describes conflict in work tree' ' pristine_detach initial && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ======= @@ -206,14 +246,14 @@ test_expect_success 'failed cherry-pick describes conflict in work tree' ' test_must_fail git cherry-pick picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' test_expect_success 'diff3 -m style' ' pristine_detach initial && git config merge.conflictstyle diff3 && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ||||||| parent of objid picked @@ -225,14 +265,14 @@ test_expect_success 'diff3 -m style' ' test_must_fail git cherry-pick picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' test_expect_success 'revert also handles conflicts sanely' ' git config --unset merge.conflictstyle && pristine_detach initial && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ======= @@ -246,24 +286,24 @@ test_expect_success 'revert also handles conflicts sanely' ' git ls-files --stage foo && git checkout base -- foo && git ls-files --stage foo - } > stages && + } >stages && sed " 1 s/ 0 / 1 / 2 s/ 0 / 2 / 3 s/ 0 / 3 / - " < stages > expected-stages && + " stages >expected-stages && git read-tree -u --reset HEAD && head=$(git rev-parse HEAD) && test_must_fail git revert picked && newhead=$(git rev-parse HEAD) && - git ls-files --stage --unmerged > actual-stages && + git ls-files --stage --unmerged >actual-stages && test "$head" = "$newhead" && test_must_fail git update-index --refresh -q && test_must_fail git diff-index --exit-code HEAD && test_cmp expected-stages actual-stages && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' @@ -289,7 +329,7 @@ test_expect_success 'revert --no-commit sets REVERT_HEAD' ' test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' ' pristine_detach base && - echo foo > foo && + echo foo >foo && test_must_fail git revert base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && test_must_fail git rev-parse --verify REVERT_HEAD @@ -324,7 +364,7 @@ test_expect_success 'failed commit does not clear REVERT_HEAD' ' test_expect_success 'revert conflict, diff3 -m style' ' pristine_detach initial && git config merge.conflictstyle diff3 && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ||||||| objid picked @@ -336,10 +376,56 @@ test_expect_success 'revert conflict, diff3 -m style' ' test_must_fail git revert picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' +test_expect_success \ + 'revert conflict, ensure commit.cleanup = scissors places scissors line properly' ' + pristine_detach initial && + git config commit.cleanup scissors && + cat >expected <<-EOF && + Revert "picked" + + This reverts commit OBJID. + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git revert picked && + + sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual && + test_i18ncmp expected actual +' + +test_expect_success \ + 'revert conflict, ensure cleanup=scissors places scissors line properly' ' + pristine_detach initial && + git config --unset commit.cleanup && + cat >expected <<-EOF && + Revert "picked" + + This reverts commit OBJID. + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git revert --cleanup=scissors picked && + + sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual && + test_i18ncmp expected actual +' + test_expect_success 'failed cherry-pick does not forget -s' ' pristine_detach initial && test_must_fail git cherry-pick -s picked && @@ -350,7 +436,7 @@ test_expect_success 'commit after failed cherry-pick does not add duplicated -s' pristine_detach initial && test_must_fail git cherry-pick -s picked-signed && git commit -a -s && - test $(git show -s |grep -c "Signed-off-by") = 1 + test $(git show -s >tmp && grep -c "Signed-off-by" tmp && rm tmp) = 1 ' test_expect_success 'commit after failed cherry-pick adds -s at the right place' ' @@ -364,7 +450,7 @@ test_expect_success 'commit after failed cherry-pick adds -s at the right place' Signed-off-by: C O Mitter <committer@example.com> # Conflicts: EOF - grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + grep -e "^# Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual && test_cmp expect actual && cat <<-\EOF >expected && @@ -383,7 +469,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' # emulate old-style conflicts block mv .git/MERGE_MSG .git/MERGE_MSG+ && - sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG && + sed -e "/^# Conflicts:/,\$s/^# *//" .git/MERGE_MSG+ >.git/MERGE_MSG && git commit -a && git commit --amend -s && @@ -393,7 +479,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' Signed-off-by: C O Mitter <committer@example.com> Conflicts: EOF - grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + grep -e "^Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual && test_cmp expect actual ' diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index c19d8dbc9d..ccde8ba491 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -77,6 +77,14 @@ test_expect_success 'git pull -q -v' ' test_must_be_empty out && test -s err) ' +test_expect_success 'git pull --cleanup errors early on invalid argument' ' + mkdir clonedcleanup && + (cd clonedcleanup && git init && + test_must_fail git pull --cleanup invalid "../parent" >out 2>err && + test_must_be_empty out && + test -s err) +' + test_expect_success 'git pull --force' ' mkdir clonedoldstyle && diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index ca4a740da0..5733d9cd34 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -16,7 +16,8 @@ commit_msg_is () { # Arguments: [<prefix] [<commit message>] [<commit options>] check_summary_oneline() { test_tick && - git commit ${3+"$3"} -m "$2" | head -1 > act && + git commit ${3+"$3"} -m "$2" >raw && + head -n 1 raw >act && # branch name SUMMARY_PREFIX="$(git name-rev --name-only HEAD)" && @@ -68,7 +69,7 @@ test_expect_success 'output summary format for merges' ' git checkout recursive-a && test_must_fail git merge recursive-b && # resolve the conflict - echo commit-a > file1 && + echo commit-a >file1 && git add file1 && check_summary_oneline "" "Merge" ' @@ -142,9 +143,11 @@ test_expect_success 'sign off' ' >positive && git add positive && git commit -s -m "thank you" && - actual=$(git cat-file commit HEAD | sed -ne "s/Signed-off-by: //p") && - expected=$(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/") && - test "z$actual" = "z$expected" + git cat-file commit HEAD >commit.msg && + sed -ne "s/Signed-off-by: //p" commit.msg >actual && + git var GIT_COMMITTER_IDENT >ident && + sed -e "s/>.*/>/" ident >expected && + test_cmp expected actual ' @@ -153,8 +156,8 @@ test_expect_success 'multiple -m' ' >negative && git add negative && git commit -m "one" -m "two" -m "three" && - actual=$(git cat-file commit HEAD | sed -e "1,/^\$/d") && - expected=$(echo one; echo; echo two; echo; echo three) && + actual=$(git cat-file commit HEAD >tmp && sed -e "1,/^\$/d" tmp && rm tmp) && + expected=$(test_write_lines "one" "" "two" "" "three") && test "z$actual" = "z$expected" ' @@ -163,7 +166,8 @@ test_expect_success 'verbose' ' echo minus >negative && git add negative && - git status -v | sed -ne "/^diff --git /p" >actual && + git status -v >raw && + sed -ne "/^diff --git /p" raw >actual && echo "diff --git a/negative b/negative" >expect && test_cmp expect actual @@ -189,7 +193,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-t)' ' echo >>negative && git commit --cleanup=verbatim --no-status -t expect -a && - git cat-file -p HEAD |sed -e "1,/^\$/d" >actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -198,7 +203,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-F)' ' echo >>negative && git commit --cleanup=verbatim -F expect -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -207,7 +213,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-m)' ' echo >>negative && git commit --cleanup=verbatim -m "$mesg_with_comment_and_newlines" -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -215,10 +222,11 @@ test_expect_success 'cleanup commit messages (verbatim option,-m)' ' test_expect_success 'cleanup commit messages (whitespace option,-F)' ' echo >>negative && - { echo;echo "# text";echo; } >text && + test_write_lines "" "# text" "" >text && echo "# text" >expect && git commit --cleanup=whitespace -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -226,48 +234,51 @@ test_expect_success 'cleanup commit messages (whitespace option,-F)' ' test_expect_success 'cleanup commit messages (scissors option,-F,-e)' ' echo >>negative && - cat >text <<EOF && + cat >text <<-\EOF && -# to be kept + # to be kept - # ------------------------ >8 ------------------------ -# to be kept, too -# ------------------------ >8 ------------------------ -to be removed -# ------------------------ >8 ------------------------ -to be removed, too -EOF + # ------------------------ >8 ------------------------ + # to be kept, too + # ------------------------ >8 ------------------------ + to be removed + # ------------------------ >8 ------------------------ + to be removed, too + EOF - cat >expect <<EOF && -# to be kept + cat >expect <<-\EOF && + # to be kept - # ------------------------ >8 ------------------------ -# to be kept, too -EOF + # ------------------------ >8 ------------------------ + # to be kept, too + EOF git commit --cleanup=scissors -e -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' test_expect_success 'cleanup commit messages (scissors option,-F,-e, scissors on first line)' ' echo >>negative && - cat >text <<EOF && -# ------------------------ >8 ------------------------ -to be removed -EOF + cat >text <<-\EOF && + # ------------------------ >8 ------------------------ + to be removed + EOF git commit --cleanup=scissors -e -F text -a --allow-empty-message && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_must_be_empty actual ' test_expect_success 'cleanup commit messages (strip option,-F)' ' echo >>negative && - { echo;echo "# text";echo sample;echo; } >text && + test_write_lines "" "# text" "sample" "" >text && echo sample >expect && git commit --cleanup=strip -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -275,7 +286,7 @@ test_expect_success 'cleanup commit messages (strip option,-F)' ' test_expect_success 'cleanup commit messages (strip option,-F,-e)' ' echo >>negative && - { echo;echo sample;echo; } >text && + test_write_lines "" "sample" "" >text && git commit -e -F text -a && head -n 4 .git/COMMIT_EDITMSG >actual ' @@ -387,7 +398,7 @@ test_expect_success AUTOIDENT 'message shows committer when it is automatic' ' ' write_script .git/FAKE_EDITOR <<EOF -echo editor started > "$(pwd)/.git/result" +echo editor started >"$(pwd)/.git/result" exit 0 EOF @@ -455,7 +466,7 @@ EOF test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' ' echo >>negative && ! "$SHELL_PATH" -c '\'' - echo kill -TERM $$ >> .git/FAKE_EDITOR + echo kill -TERM $$ >>.git/FAKE_EDITOR GIT_EDITOR=.git/FAKE_EDITOR export GIT_EDITOR exec git commit -a'\'' && @@ -471,7 +482,8 @@ test_expect_success 'Hand committing of a redundant merge removes dups' ' test_must_fail git merge second master && git checkout master g && EDITOR=: git commit -a && - git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual && + git cat-file commit HEAD >raw && + sed -n -e "s/^parent //p" -e "/^$/q" raw >actual && test_cmp expect actual ' @@ -480,7 +492,8 @@ test_expect_success 'A single-liner subject with a token plus colon is not a foo git reset --hard && git commit -s -m "hello: kitty" --allow-empty && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_line_count = 3 actual ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 106148254d..7f9c68cbe7 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -233,20 +233,65 @@ test_expect_success 'merge --squash c3 with c7' ' cat result.9z >file && git commit --no-edit -a && - { - cat <<-EOF - Squashed commit of the following: + cat >expect <<-EOF && + Squashed commit of the following: - $(git show -s c7) + $(git show -s c7) - # Conflicts: - # file - EOF - } >expect && - git cat-file commit HEAD | sed -e '1,/^$/d' >actual && + # Conflicts: + # file + EOF + git cat-file commit HEAD >raw && + sed -e '1,/^$/d' raw >actual && 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' ' @@ -680,10 +725,10 @@ cat >editor <<\EOF ( echo "Merge work done on the side branch c1" echo - cat <"$1" + cat "$1" ) >"$1.tmp" && mv "$1.tmp" "$1" # strip comments and blank lines from end of message -sed -e '/^#/d' < "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' > expected +sed -e '/^#/d' "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' >expected EOF chmod 755 editor @@ -768,14 +813,14 @@ test_expect_success 'set up mod-256 conflict scenario' ' git commit -m base && # one side changes the first line of each to "master" - sed s/-1/-master/ <file >tmp && + sed s/-1/-master/ file >tmp && mv tmp file && git commit -am master && # and the other to "side"; merging the two will # yield 256 separate conflicts git checkout -b side HEAD^ && - sed s/-1/-side/ <file >tmp && + sed s/-1/-side/ file >tmp && mv tmp file && git commit -am side ' @@ -814,7 +859,7 @@ EOF test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' ' git reset --hard c0 && ! "$SHELL_PATH" -c '\'' - echo kill -TERM $$ >> .git/FAKE_EDITOR + echo kill -TERM $$ >>.git/FAKE_EDITOR GIT_EDITOR=.git/FAKE_EDITOR export GIT_EDITOR exec git merge --no-ff --edit c1'\'' && diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh index 89619cf446..cd4f9607dc 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -16,16 +16,16 @@ create_merge_msgs() { } test_expect_success 'setup' ' - echo c0 > c0.c && + echo c0 >c0.c && git add c0.c && git commit -m c0 && git tag c0 && - echo c1 > c1.c && + echo c1 >c1.c && git add c1.c && git commit -m c1 && git tag c1 && git reset --hard c0 && - echo c2 > c2.c && + echo c2 >c2.c && git add c2.c && git commit -m c2 && git tag c2 && @@ -36,15 +36,80 @@ test_expect_success 'setup' ' test_expect_success 'merge c2 with a custom message' ' git reset --hard c1 && git merge -m "$(cat exp.subject)" c2 && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_cmp exp.subject actual ' test_expect_success 'merge --log appends to custom message' ' git reset --hard c1 && git merge --log -m "$(cat exp.subject)" c2 && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_cmp exp.log actual ' +mesg_with_comment_and_newlines=' +# text + +' + +test_expect_success 'prepare file with comment line and trailing newlines' ' + printf "%s" "$mesg_with_comment_and_newlines" >expect +' + +test_expect_success 'cleanup commit messages (verbatim option)' ' + git reset --hard c1 && + git merge --cleanup=verbatim -F expect c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup commit messages (whitespace option)' ' + git reset --hard c1 && + test_write_lines "" "# text" "" >text && + echo "# text" >expect && + git merge --cleanup=whitespace -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup merge messages (scissors option)' ' + git reset --hard c1 && + cat >text <<-\EOF && + + # to be kept + + # ------------------------ >8 ------------------------ + # to be kept, too + # ------------------------ >8 ------------------------ + to be removed + # ------------------------ >8 ------------------------ + to be removed, too + EOF + + cat >expect <<-\EOF && + # to be kept + + # ------------------------ >8 ------------------------ + # to be kept, too + EOF + git merge --cleanup=scissors -e -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup commit messages (strip option)' ' + git reset --hard c1 && + test_write_lines "" "# text" "sample" "" >text && + echo sample >expect && + git merge --cleanup=strip -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + test_done diff --git a/wt-status.c b/wt-status.c index 445a36204a..b81fcd428d 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1006,13 +1006,19 @@ size_t wt_status_locate_end(const char *s, size_t len) return len; } -void wt_status_add_cut_line(FILE *fp) +void wt_status_append_cut_line(struct strbuf *buf) { const char *explanation = _("Do not modify or remove the line above.\nEverything below it will be ignored."); + + strbuf_commented_addf(buf, "%s", cut_line); + strbuf_add_commented_lines(buf, explanation, strlen(explanation)); +} + +void wt_status_add_cut_line(FILE *fp) +{ struct strbuf buf = STRBUF_INIT; - fprintf(fp, "%c %s", comment_line_char, cut_line); - strbuf_add_commented_lines(&buf, explanation, strlen(explanation)); + wt_status_append_cut_line(&buf); fputs(buf.buf, fp); strbuf_release(&buf); } diff --git a/wt-status.h b/wt-status.h index 3a95975032..64f1ddc9fd 100644 --- a/wt-status.h +++ b/wt-status.h @@ -129,6 +129,7 @@ struct wt_status { }; size_t wt_status_locate_end(const char *s, size_t len); +void wt_status_append_cut_line(struct strbuf *buf); void wt_status_add_cut_line(FILE *fp); void wt_status_prepare(struct repository *r, struct wt_status *s); void wt_status_print(struct wt_status *s); |