summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2019-05-09 00:37:24 +0900
committerLibravatar Junio C Hamano <gitster@pobox.com>2019-05-09 00:37:24 +0900
commitb877cb4a7ec2fafd03b6a3a70c26370744a32c1b (patch)
tree841a4389aea1aef57d9278bec5f966de5bb1ef7e
parentMerge branch 'pw/sequencer-cleanup-with-signoff-x-fix' (diff)
parentcherry-pick/revert: add scissors line on merge conflict (diff)
downloadtgif-b877cb4a7ec2fafd03b6a3a70c26370744a32c1b.tar.xz
Merge branch 'dl/merge-cleanup-scissors-fix'
The list of conflicted paths shown in the editor while concluding a conflicted merge was shown above the scissors line when the clean-up mode is set to "scissors", even though it was commented out just like the list of updated paths and other information to help the user explain the merge better. * dl/merge-cleanup-scissors-fix: cherry-pick/revert: add scissors line on merge conflict sequencer.c: save and restore cleanup mode merge: add scissors line on merge conflict merge: cleanup messages like commit parse-options.h: extract common --cleanup option commit: extract cleanup_mode functions to sequencer t7502: clean up style t7604: clean up style t3507: clean up style t7600: clean up style
-rw-r--r--Documentation/git-cherry-pick.txt7
-rw-r--r--Documentation/git-revert.txt7
-rw-r--r--Documentation/merge-options.txt7
-rw-r--r--builtin/commit.c49
-rw-r--r--builtin/merge.c51
-rw-r--r--builtin/pull.c12
-rw-r--r--builtin/revert.c7
-rw-r--r--builtin/tag.c3
-rw-r--r--parse-options.h1
-rw-r--r--sequencer.c73
-rw-r--r--sequencer.h9
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh128
-rwxr-xr-xt/t5521-pull-options.sh8
-rwxr-xr-xt/t7502-commit-porcelain.sh93
-rwxr-xr-xt/t7600-merge.sh73
-rwxr-xr-xt/t7604-merge-custom-message.sh75
-rw-r--r--wt-status.c12
-rw-r--r--wt-status.h1
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);