]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-tree: provide a list of which files have conflicts
authorElijah Newren <newren@gmail.com>
Sat, 18 Jun 2022 00:20:52 +0000 (00:20 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 22 Jun 2022 23:10:06 +0000 (16:10 -0700)
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 <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-merge-tree.txt
builtin/merge-tree.c
t/t4301-merge-tree-write-tree.sh

index 25b462be14e6eafc16b7b7ad053b8af4b60b9eb7..68a51c82618c412e5aed96f71202bba4d47e2d22 100644 (file)
@@ -58,6 +58,7 @@ line:
 Whereas for a conflicted merge, the output is by default of the form:
 
        <OID of toplevel tree>
+       <Conflicted file list>
        <Informational messages>
 
 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
 ~~~~~~~~~~~~~~~~~~~~~~
index 831d9c775833d58f591324f84a4895089f293a28..13a9536f7c10b1873f3771153b4bb6293c3fa347 100644 (file)
@@ -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]);
 }
index 719d81e71738c2ecacef37c92652aaff68a4a92f..8e6dba44288720029fc95508c9b31ed85af794b0 100755 (executable)
@@ -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