merge-ort: format messages slightly different for use in headers
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>
Elijah Newren committed
Feb 2, 2022 at 02:37 UTC
6054d1aac36d5769461fb73b15326a900e53edb9
3 files changed
+46
-2
merge-ort.c
+40
-2
@@ -634,17 +634,49 @@ static void path_msg(struct merge_options *opt,
634
const char *fmt, ...)
635
{
636
va_list ap;
637
- struct strbuf *sb = strmap_get(&opt->priv->output, path);
637
+ struct strbuf *sb, *dest;
638
+ struct strbuf tmp = STRBUF_INIT;
639
+
640
+ if (opt->record_conflict_msgs_as_headers && omittable_hint)
641
+ return; /* Do not record mere hints in tree */
642
+ sb = strmap_get(&opt->priv->output, path);
643
if (!sb) {
644
sb = xmalloc(sizeof(*sb));
645
strbuf_init(sb, 0);
646
strmap_put(&opt->priv->output, path, sb);
647
}
648
649
+ dest = (opt->record_conflict_msgs_as_headers ? &tmp : sb);
650
+
651
va_start(ap, fmt);
645
- strbuf_vaddf(sb, fmt, ap);
652
+ strbuf_vaddf(dest, fmt, ap);
653
va_end(ap);
654
655
+ if (opt->record_conflict_msgs_as_headers) {
656
+ int i_sb = 0, i_tmp = 0;
657
+
658
+ /* Start with the specified prefix */
659
+ if (opt->msg_header_prefix)
660
+ strbuf_addf(sb, "%s ", opt->msg_header_prefix);
661
+
662
+ /* Copy tmp to sb, adding spaces after newlines */
663
+ strbuf_grow(sb, sb->len + 2*tmp.len); /* more than sufficient */
664
+ for (; i_tmp < tmp.len; i_tmp++, i_sb++) {
665
+ /* Copy next character from tmp to sb */
666
+ sb->buf[sb->len + i_sb] = tmp.buf[i_tmp];
667
+
668
+ /* If we copied a newline, add a space */
669
+ if (tmp.buf[i_tmp] == '\n')
670
+ sb->buf[++i_sb] = ' ';
671
+ }
672
+ /* Update length and ensure it's NUL-terminated */
673
+ sb->len += i_sb;
674
+ sb->buf[sb->len] = '\0';
675
+
676
+ strbuf_release(&tmp);
677
+ }
678
+
679
+ /* Add final newline character to sb */
680
strbuf_addch(sb, '\n');
681
}
682
@@ -4246,6 +4278,9 @@ void merge_switch_to_result(struct merge_options *opt,
4278
struct string_list olist = STRING_LIST_INIT_NODUP;
4279
int i;
4280
4281
+ if (opt->record_conflict_msgs_as_headers)
4282
+ BUG("Either display conflict messages or record them as headers, not both");
4283
+
4284
trace2_region_enter("merge", "display messages", opt->repo);
4285
4286
/* 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)
4382
assert(opt->recursive_variant >= MERGE_VARIANT_NORMAL &&
4383
opt->recursive_variant <= MERGE_VARIANT_THEIRS);
4384
4385
+ if (opt->msg_header_prefix)
4386
+ assert(opt->record_conflict_msgs_as_headers);
4387
+
4388
/*
4389
* detect_renames, verbosity, buffer_output, and obuf are ignored
4390
* fields that were used by "recursive" rather than "ort" -- but
merge-recursive.c
+4
@@ -3714,6 +3714,10 @@ static int merge_start(struct merge_options *opt, struct tree *head)
3714
3715
assert(opt->priv == NULL);
3716
3717
+ /* Not supported; option specific to merge-ort */
3718
+ assert(!opt->record_conflict_msgs_as_headers);
3719
+ assert(!opt->msg_header_prefix);
3720
+
3721
/* Sanity check on repo state; index must match head */
3722
if (repo_index_has_changes(opt->repo, head, &sb)) {
3723
err(opt, _("Your local changes to the following files would be overwritten by merge:\n %s"),
merge-recursive.h
+2
@@ -46,6 +46,8 @@ struct merge_options {
46
/* miscellaneous control options */
47
const char *subtree_shift;
48
unsigned renormalize : 1;
49
+ unsigned record_conflict_msgs_as_headers : 1;
50
+ const char *msg_header_prefix;
51
52
/* internal fields used by the implementation */
53
struct merge_options_internal *priv;