[PATCH v5 09/12] merge-tree: provide easy access to `ls-files -u` style info
From: Elijah Newren <newren@gmail.com>
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>
---
Documentation/git-merge-tree.txt | 32 ++++++++++++++++++++++++++------
builtin/merge-tree.c | 11 ++++++++++-
t/t4301-merge-tree-write-tree.sh | 26 ++++++++++++++++++++++++--
3 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index deaeb49ae05..67a135e8f5d 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -50,6 +50,13 @@ discuss the first form.
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
@@ -67,7 +74,7 @@ simply one 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.
@@ -79,18 +86,23 @@ 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.
-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.
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..."
@@ -120,6 +132,14 @@ Thus, it could be 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.
+git-merge-tree was written to provide users with the same information
+that they'd have access to if using `git merge`:
+ * what would be written to the working tree (the <OID of toplevel tree>)
+ * the higher order stages that would be written to the index (the
+ <Conflicted file info>)
+ * any messages that would have been printed to stdout (the <Informational
+ messages>)
+
GIT
---
Part of the linkgit:git[1] suite
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index cb4169d2271..1d4d6637b90 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -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,
@@ -456,7 +457,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);
@@ -491,6 +496,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()
};
diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh
index 8e6dba44288..0ec5f0d3f7e 100755
--- a/t/t4301-merge-tree-write-tree.sh
+++ b/t/t4301-merge-tree-write-tree.sh
@@ -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
--
gitgitgadget