From 7fa3338870d66dd3946c5c3a0bd09dadb798893d Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sat, 18 Jun 2022 00:20:52 +0000 Subject: merge-tree: provide a list of which files have conflicts Callers of `git merge-tree --write-tree` will often want to know which files had conflicts. While they could potentially attempt to parse the CONFLICT notices printed, those messages are not meant to be machine readable. Provide a simpler mechanism of just printing the files (in the same format as `git ls-files` with quoting, but restricted to unmerged files) in the output before the free-form messages. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 25b462b..68a51c8 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -58,6 +58,7 @@ line: Whereas for a conflicted merge, the output is by default of the form: + These are discussed individually below. @@ -70,6 +71,14 @@ This is a tree object that represents what would be checked out in the working tree at the end of `git merge`. If there were conflicts, then files within this tree may have embedded conflict markers. +[[CFI]] +Conflicted file list +~~~~~~~~~~~~~~~~~~~~ + +This is a sequence of lines containing a filename on each line, quoted +as explained for the configuration variable `core.quotePath` (see +linkgit:git-config[1]). + [[IM]] Informational messages ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 831d9c7..13a9536 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -11,6 +11,9 @@ #include "blob.h" #include "exec-cmd.h" #include "merge-blobs.h" +#include "quote.h" + +static int line_termination = '\n'; struct merge_list { struct merge_list *next; @@ -400,7 +403,8 @@ struct merge_tree_options { }; static int real_merge(struct merge_tree_options *o, - const char *branch1, const char *branch2) + const char *branch1, const char *branch2, + const char *prefix) { struct commit *parent1, *parent2; struct commit_list *merge_bases = NULL; @@ -441,8 +445,24 @@ static int real_merge(struct merge_tree_options *o, o->show_messages = !result.clean; puts(oid_to_hex(&result.tree->object.oid)); + if (!result.clean) { + struct string_list conflicted_files = STRING_LIST_INIT_NODUP; + const char *last = NULL; + int i; + + merge_get_conflicted_files(&result, &conflicted_files); + for (i = 0; i < conflicted_files.nr; i++) { + const char *name = conflicted_files.items[i].string; + if (last && !strcmp(last, name)) + continue; + write_name_quoted_relative( + name, prefix, stdout, line_termination); + last = name; + } + string_list_clear(&conflicted_files, 1); + } if (o->show_messages) { - printf("\n"); + putchar(line_termination); merge_display_update_messages(&opt, &result); } merge_finalize(&opt, &result); @@ -508,7 +528,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) /* Do the relevant type of merge */ if (o.mode == MODE_REAL) - return real_merge(&o, argv[0], argv[1]); + return real_merge(&o, argv[0], argv[1], prefix); else return trivial_merge(argv[0], argv[1], argv[2]); } diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 719d81e..8e6dba4 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -117,6 +117,8 @@ test_expect_success 'test conflict notices and such' ' # "whatever" has *both* a modify/delete and a file/directory conflict cat <<-EOF >expect && HASH + greeting + whatever~side1 Auto-merging greeting CONFLICT (content): Merge conflict in greeting @@ -140,4 +142,13 @@ do ' done +test_expect_success 'Just the conflicted files without the messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + anonymize_hash out >actual && + + test_write_lines HASH greeting whatever~side1 >expect && + + test_cmp expect actual +' + test_done -- cgit v0.10.2-6-g49f6