]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-ort: format messages slightly different for use in headers
authorElijah Newren <newren@gmail.com>
Wed, 2 Feb 2022 02:37:33 +0000 (02:37 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Feb 2022 18:02:27 +0000 (10:02 -0800)
When users run
    git show --remerge-diff $MERGE_COMMIT
or
    git log -p --remerge-diff ...
stdout is not an appropriate location to dump conflict messages, but we
do want to provide them to users.  We will include them in the diff
headers instead...but for that to work, we need for any multiline
messages to replace newlines with both a newline and a space.  Add a new
flag to signal when we want these messages modified in such a fashion,
and use it in path_msg() to modify these messages this way.  Also, allow
a special prefix to be specified for these headers.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
merge-ort.c
merge-recursive.c
merge-recursive.h

index 998e92ec593cece2600a805e08f8eb6ebb397eff..481305d2bcf0a21a52f0a051b3a93fa1a7a05be0 100644 (file)
@@ -634,17 +634,49 @@ static void path_msg(struct merge_options *opt,
                     const char *fmt, ...)
 {
        va_list ap;
-       struct strbuf *sb = strmap_get(&opt->priv->output, path);
+       struct strbuf *sb, *dest;
+       struct strbuf tmp = STRBUF_INIT;
+
+       if (opt->record_conflict_msgs_as_headers && omittable_hint)
+               return; /* Do not record mere hints in tree */
+       sb = strmap_get(&opt->priv->output, path);
        if (!sb) {
                sb = xmalloc(sizeof(*sb));
                strbuf_init(sb, 0);
                strmap_put(&opt->priv->output, path, sb);
        }
 
+       dest = (opt->record_conflict_msgs_as_headers ? &tmp : sb);
+
        va_start(ap, fmt);
-       strbuf_vaddf(sb, fmt, ap);
+       strbuf_vaddf(dest, fmt, ap);
        va_end(ap);
 
+       if (opt->record_conflict_msgs_as_headers) {
+               int i_sb = 0, i_tmp = 0;
+
+               /* Start with the specified prefix */
+               if (opt->msg_header_prefix)
+                       strbuf_addf(sb, "%s ", opt->msg_header_prefix);
+
+               /* Copy tmp to sb, adding spaces after newlines */
+               strbuf_grow(sb, sb->len + 2*tmp.len); /* more than sufficient */
+               for (; i_tmp < tmp.len; i_tmp++, i_sb++) {
+                       /* Copy next character from tmp to sb */
+                       sb->buf[sb->len + i_sb] = tmp.buf[i_tmp];
+
+                       /* If we copied a newline, add a space */
+                       if (tmp.buf[i_tmp] == '\n')
+                               sb->buf[++i_sb] = ' ';
+               }
+               /* Update length and ensure it's NUL-terminated */
+               sb->len += i_sb;
+               sb->buf[sb->len] = '\0';
+
+               strbuf_release(&tmp);
+       }
+
+       /* Add final newline character to sb */
        strbuf_addch(sb, '\n');
 }
 
@@ -4246,6 +4278,9 @@ void merge_switch_to_result(struct merge_options *opt,
                struct string_list olist = STRING_LIST_INIT_NODUP;
                int i;
 
+               if (opt->record_conflict_msgs_as_headers)
+                       BUG("Either display conflict messages or record them as headers, not both");
+
                trace2_region_enter("merge", "display messages", opt->repo);
 
                /* Hack to pre-allocate olist to the desired size */
@@ -4347,6 +4382,9 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
        assert(opt->recursive_variant >= MERGE_VARIANT_NORMAL &&
               opt->recursive_variant <= MERGE_VARIANT_THEIRS);
 
+       if (opt->msg_header_prefix)
+               assert(opt->record_conflict_msgs_as_headers);
+
        /*
         * detect_renames, verbosity, buffer_output, and obuf are ignored
         * fields that were used by "recursive" rather than "ort" -- but
index bc73c52dd847801cdbca80558ec4e0016d08813b..9ec1e6d043a2f85f61422138c97b379e1a5b70c9 100644 (file)
@@ -3714,6 +3714,10 @@ static int merge_start(struct merge_options *opt, struct tree *head)
 
        assert(opt->priv == NULL);
 
+       /* Not supported; option specific to merge-ort */
+       assert(!opt->record_conflict_msgs_as_headers);
+       assert(!opt->msg_header_prefix);
+
        /* Sanity check on repo state; index must match head */
        if (repo_index_has_changes(opt->repo, head, &sb)) {
                err(opt, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
index 0795a1d3ec1809ea42fd11c1e3ad35467050d286..b88000e3c25277d07d20b7ba29755b9670cd28ff 100644 (file)
@@ -46,6 +46,8 @@ struct merge_options {
        /* miscellaneous control options */
        const char *subtree_shift;
        unsigned renormalize : 1;
+       unsigned record_conflict_msgs_as_headers : 1;
+       const char *msg_header_prefix;
 
        /* internal fields used by the implementation */
        struct merge_options_internal *priv;