Skip to content

Commit

Permalink
Merge branch 'dl/merge-cleanup-scissors-fix'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed May 8, 2019
2 parents f757794 + 1a2b985 commit b877cb4
Show file tree
Hide file tree
Showing 18 changed files with 484 additions and 132 deletions.
7 changes: 7 additions & 0 deletions Documentation/git-cherry-pick.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions Documentation/git-revert.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions Documentation/merge-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 20 additions & 29 deletions builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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"));
Expand Down Expand Up @@ -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
Expand All @@ -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"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) "" },
Expand Down Expand Up @@ -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();
Expand Down
51 changes: 40 additions & 11 deletions builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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")) {
Expand Down Expand Up @@ -800,20 +807,33 @@ 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 *);
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);
Expand All @@ -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);
Expand Down Expand Up @@ -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))
Expand All @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down
12 changes: 12 additions & 0 deletions builtin/pull.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "lockfile.h"
#include "wt-status.h"
#include "commit-reach.h"
#include "sequencer.h"

enum rebase_type {
REBASE_INVALID = -1,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions builtin/revert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions builtin/tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions parse-options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit b877cb4

Please sign in to comment.