]> git.ipfire.org Git - thirdparty/git.git/commitdiff
merge-tree: provide easy access to `ls-files -u` style info
authorElijah Newren <newren@gmail.com>
Sat, 18 Jun 2022 00:20:53 +0000 (00:20 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 22 Jun 2022 23:10:06 +0000 (16:10 -0700)
Much like `git merge` updates the index with information of the form
    (mode, oid, stage, name)
provide this output for conflicted files for merge-tree as well.
Provide a --name-only option for users to exclude the mode, oid, and
stage and only get the list of conflicted filenames.

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 68a51c82618c412e5aed96f71202bba4d47e2d22..b89aabdb98e69478bca4d43475b5ea7249889fdb 100644 (file)
@@ -40,6 +40,13 @@ After the merge completes, a new toplevel tree object is created.  See
 OPTIONS
 -------
 
+--name-only::
+       In the Conflicted file info section, instead of writing a list
+       of (mode, oid, stage, path) tuples to output for conflicted
+       files, just provide a list of filenames with conflicts (and
+       do not list filenames multiple times if they have multiple
+       conflicting stages).
+
 --[no-]messages::
        Write any informational messages such as "Auto-merging <path>"
        or CONFLICT notices to the end of stdout.  If unspecified, the
@@ -58,7 +65,7 @@ line:
 Whereas for a conflicted merge, the output is by default of the form:
 
        <OID of toplevel tree>
-       <Conflicted file list>
+       <Conflicted file info>
        <Informational messages>
 
 These are discussed individually below.
@@ -72,19 +79,24 @@ 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
+Conflicted file info
 ~~~~~~~~~~~~~~~~~~~~
 
-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]).
+This is a sequence of lines with the format
+
+       <mode> <object> <stage> <filename>
+
+The filename will be quoted as explained for the configuration
+variable `core.quotePath` (see linkgit:git-config[1]).  However, if
+the `--name-only` option is passed, the mode, object, and stage will
+be omitted.
 
 [[IM]]
 Informational messages
 ~~~~~~~~~~~~~~~~~~~~~~
 
 This always starts with a blank line to separate it from the previous
-section, and then has free-form messages about the merge, such as:
+sections, and then has free-form messages about the merge, such as:
 
   * "Auto-merging <file>"
   * "CONFLICT (rename/delete): <oldfile> renamed...but deleted in..."
@@ -116,6 +128,16 @@ used as a part of a series of steps such as:
 Note that when the exit status is non-zero, `NEWTREE` in this sequence
 will contain a lot more output than just a tree.
 
+For conflicts, the output includes the same information that you'd get
+with linkgit:git-merge[1]:
+
+  * what would be written to the working tree (the
+    <<OIDTLT,OID of toplevel tree>>)
+  * the higher order stages that would be written to the index (the
+    <<CFI,Conflicted file info>>)
+  * any messages that would have been printed to stdout (the
+    <<IM,Informational messages>>)
+
 [[DEPMERGE]]
 DEPRECATED DESCRIPTION
 ----------------------
index 13a9536f7c10b1873f3771153b4bb6293c3fa347..c61b5b4a10dcc18951e228603147ebd33c29bcab 100644 (file)
@@ -400,6 +400,7 @@ enum mode {
 struct merge_tree_options {
        int mode;
        int show_messages;
+       int name_only;
 };
 
 static int real_merge(struct merge_tree_options *o,
@@ -453,7 +454,11 @@ static int real_merge(struct merge_tree_options *o,
                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))
+                       struct stage_info *c = conflicted_files.items[i].util;
+                       if (!o->name_only)
+                               printf("%06o %s %d\t",
+                                      c->mode, oid_to_hex(&c->oid), c->stage);
+                       else if (last && !strcmp(last, name))
                                continue;
                        write_name_quoted_relative(
                                name, prefix, stdout, line_termination);
@@ -488,6 +493,10 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
                            N_("do a trivial merge only"), MODE_TRIVIAL),
                OPT_BOOL(0, "messages", &o.show_messages,
                         N_("also show informational/conflict messages")),
+               OPT_BOOL_F(0, "name-only",
+                          &o.name_only,
+                          N_("list filenames without modes/oids/stages"),
+                          PARSE_OPT_NONEG),
                OPT_END()
        };
 
index 8e6dba44288720029fc95508c9b31ed85af794b0..0ec5f0d3f7e8c1f94cd0749d444581351f0db21d 100755 (executable)
@@ -65,6 +65,7 @@ test_expect_success 'Content merge and a few conflicts' '
        expected_tree=$(git rev-parse AUTO_MERGE) &&
 
        # We will redo the merge, while we are still in a conflicted state!
+       git ls-files -u >conflicted-file-info &&
        test_when_finished "git reset --hard" &&
 
        test_expect_code 1 git merge-tree --write-tree side1 side2 >RESULT &&
@@ -108,7 +109,7 @@ anonymize_hash() {
 }
 
 test_expect_success 'test conflict notices and such' '
-       test_expect_code 1 git merge-tree --write-tree side1 side2 >out &&
+       test_expect_code 1 git merge-tree --write-tree --name-only side1 side2 >out &&
        anonymize_hash out >actual &&
 
        # Expected results:
@@ -143,7 +144,7 @@ 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 &&
+       test_expect_code 1 git merge-tree --write-tree --no-messages --name-only side1 side2 >out &&
        anonymize_hash out >actual &&
 
        test_write_lines HASH greeting whatever~side1 >expect &&
@@ -151,4 +152,25 @@ test_expect_success 'Just the conflicted files without the messages' '
        test_cmp expect actual
 '
 
+test_expect_success 'Check conflicted oids and modes without messages' '
+       test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out &&
+       anonymize_hash out >actual &&
+
+       # Compare the basic output format
+       q_to_tab >expect <<-\EOF &&
+       HASH
+       100644 HASH 1Qgreeting
+       100644 HASH 2Qgreeting
+       100644 HASH 3Qgreeting
+       100644 HASH 1Qwhatever~side1
+       100644 HASH 2Qwhatever~side1
+       EOF
+
+       test_cmp expect actual &&
+
+       # Check the actual hashes against the `ls-files -u` output too
+       tail -n +2 out | sed -e s/side1/HEAD/ >actual &&
+       test_cmp conflicted-file-info actual
+'
+
 test_done