[RFC,2/3] Add merge commit message type autoselect logic
diff mbox series

Message ID 20200209131623.5827-3-darktemplar@dark-templar-archives.net
State New
Headers show
Series
  • git-merge: update default commit message
Related show

Commit Message

i.Dark_Templar Feb. 9, 2020, 1:16 p.m. UTC
Signed-off-by: i.Dark_Templar <darktemplar@dark-templar-archives.net>
---
 Documentation/config/fmt-merge-msg.txt | 17 ++++--
 builtin/fmt-merge-msg.c                | 71 ++++++++++++++++++++++++--
 2 files changed, 78 insertions(+), 10 deletions(-)

Patch
diff mbox series

diff --git a/Documentation/config/fmt-merge-msg.txt b/Documentation/config/fmt-merge-msg.txt
index 8c12540fa7..3829095222 100644
--- a/Documentation/config/fmt-merge-msg.txt
+++ b/Documentation/config/fmt-merge-msg.txt
@@ -9,8 +9,15 @@  merge.log::
 	actual commits that are being merged.  Defaults to false, and
 	true is a synonym for 20.
 
-merge.multilineMessage::
-	Make default merge commit message multiline. Every merged object
-	will be written using new line. This should ensure that
-	commit message wouldn't become one very long line when
-	there are a lot of merged objects.
+merge.messageType::
+	Configure default merge commit message type. `original` is used
+	if no value or an invalid value is set.
+	+
+	* `original` keeps old merge commit message format which takes only one line.
+	* `multiline` switches merge commit message to multiline mode. Every merged object
+	will be written using new line. This should ensure that commit message
+	wouldn't become one very long line when there are a lot of merged objects.
+	* `autoselect`, as it's name implies, selects one of following types
+	using arbitrary logic. Currently it selects `original` mode for merge
+	with only one additional object, otherwise switching to `multiline` mode,
+	but this behaviour may be changed in future without any notice.
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 93d44b59d9..0bc6ce5b05 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -14,13 +14,20 @@ 
 #include "repository.h"
 #include "commit-reach.h"
 
+enum message_format {
+	MESSAGE_FORMAT_ORIGINAL = 0,
+	MESSAGE_FORMAT_MULTILINE = 1,
+	MESSAGE_FORMAT_AUTOSELECT = 2,
+	MESSAGE_FORMAT_DEFAULT = MESSAGE_FORMAT_ORIGINAL
+};
+
 static const char * const fmt_merge_msg_usage[] = {
 	N_("git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"),
 	NULL
 };
 
 static int use_branch_desc;
-static int use_multiline_default_message = 0;
+static enum message_format default_message_format = MESSAGE_FORMAT_DEFAULT;
 
 int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 {
@@ -33,8 +40,16 @@  int fmt_merge_msg_config(const char *key, const char *value, void *cb)
 			merge_log_config = DEFAULT_MERGE_LOG_LEN;
 	} else if (!strcmp(key, "merge.branchdesc")) {
 		use_branch_desc = git_config_bool(key, value);
-	} else if (!strcmp(key, "merge.multilinemessage")) {
-		use_multiline_default_message = git_config_bool(key, value);
+	} else if (!strcmp(key, "merge.messagetype")) {
+		if (!value)
+			return config_error_nonbool(key);
+
+		if (!strcmp(value, "autoselect"))
+			default_message_format = MESSAGE_FORMAT_AUTOSELECT;
+		else if (!strcmp(value, "original"))
+			default_message_format = MESSAGE_FORMAT_ORIGINAL;
+		else if (!strcmp(value, "multiline"))
+			default_message_format = MESSAGE_FORMAT_MULTILINE;
 	} else {
 		return git_default_config(key, value, cb);
 	}
@@ -525,6 +540,43 @@  static void fmt_merge_msg_title_multiline(struct strbuf *out,
 	}
 }
 
+static void fmt_merge_msg_title_autoselect(struct strbuf *out,
+				const char *current_branch)
+{
+	int i = 0;
+	int j = 0;
+	int objects_count = 0;
+
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.items[i].util;
+
+		if (src_data->head_status == 1) {
+			++objects_count;
+			continue;
+		}
+		if (src_data->head_status == 3) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->r_branch.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->tag.nr; j++) {
+			++objects_count;
+		}
+		for (j = 0; j < src_data->generic.nr; j++) {
+			++objects_count;
+		}
+	}
+
+	if (objects_count > 1)
+		fmt_merge_msg_title_multiline(out, current_branch);
+	else
+		fmt_merge_msg_title(out, current_branch);
+}
+
 static void fmt_tag_signature(struct strbuf *tagbuf,
 			      struct strbuf *sig,
 			      const char *buf,
@@ -693,10 +745,19 @@  int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 	}
 
 	if (opts->add_title && srcs.nr) {
-		if (!use_multiline_default_message)
+		switch (default_message_format) {
+		case MESSAGE_FORMAT_ORIGINAL:
 			fmt_merge_msg_title(out, current_branch);
-		else
+			break;
+		case MESSAGE_FORMAT_MULTILINE:
 			fmt_merge_msg_title_multiline(out, current_branch);
+			break;
+		case MESSAGE_FORMAT_AUTOSELECT:
+			fmt_merge_msg_title_autoselect(out, current_branch);
+			break;
+		default:
+			BUG("merge.messagetype value is not properly processed: %d", (int) default_message_format);
+		}
 	}
 
 	if (origins.nr)