From: Elijah Newren <newren@xxxxxxxxx> Callers of `git merge-tree --real` might want an easy way to determine which files conflicted. While they could potentially use the --messages option and parse the resulting messages written to that file, those messages are not meant to be machine readable. Provide a simpler mechanism of having the user specify --unmerged-list=$FILENAME, and then write a NUL-separated list of unmerged filenames to the specified file. Signed-off-by: Elijah Newren <newren@xxxxxxxxx> --- Documentation/git-merge-tree.txt | 6 ++++-- builtin/merge-tree.c | 16 ++++++++++++++++ merge-ort.c | 13 +++++++++++++ merge-ort.h | 3 +++ t/t4301-merge-tree-real.sh | 9 +++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt index 4d5857b390b..542cea1a1a8 100644 --- a/Documentation/git-merge-tree.txt +++ b/Documentation/git-merge-tree.txt @@ -9,7 +9,7 @@ git-merge-tree - Perform merge without touching index or working tree SYNOPSIS -------- [verse] -'git merge-tree' --real [--messages=<file>] <branch1> <branch2> +'git merge-tree' --real [--messages=<file>] [--conflicted-list=<file>] <branch1> <branch2> 'git merge-tree' <base-tree> <branch1> <branch2> DESCRIPTION @@ -23,7 +23,9 @@ will be `0`, and if the merge has conflicts, the exit status will be `1`. The output will consist solely of the resulting toplevel tree (which may have files including conflict markers). With `--messages`, it will write any informational messages (such as "Auto-merging -<path>" and conflict notices) to the given file. +<path>" and conflict notices) to the given file. With +`--conflicted-list`, it will write a list of unmerged files, one per +line, to the given file. The second form is meant for backward compatibility and will only do a trival merge. It reads three tree-ish, and outputs trivial merge diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 46b746b6b7c..4ae34da98b1 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -391,6 +391,7 @@ static int trivial_merge(const char *base, struct merge_tree_options { int real; char *messages_file; + char *conflicted_file; }; static int real_merge(struct merge_tree_options *o, @@ -450,6 +451,19 @@ static int real_merge(struct merge_tree_options *o, merge_display_update_messages(&opt, &result, fp); fclose(fp); } + if (o->conflicted_file) { + struct string_list conflicted_files = STRING_LIST_INIT_NODUP; + FILE *fp = xfopen(o->conflicted_file, "w"); + int i; + + merge_get_conflicted_files(&result, &conflicted_files); + for (i = 0; i < conflicted_files.nr; i++) { + fprintf(fp, "%s", conflicted_files.items[i].string); + fputc('\0', fp); + } + fclose(fp); + string_list_clear(&conflicted_files, 0); + } printf("%s\n", oid_to_hex(&result.tree->object.oid)); merge_finalize(&opt, &result); @@ -472,6 +486,8 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix) N_("do a real merge instead of a trivial merge")), OPT_STRING(0, "messages", &o.messages_file, N_("file"), N_("filename to write informational/conflict messages to")), + OPT_STRING(0, "conflicted-list", &o.conflicted_file, N_("file"), + N_("filename to write list of unmerged files")), OPT_END() }; diff --git a/merge-ort.c b/merge-ort.c index 86eebf39166..3d6dd1b234c 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -4234,6 +4234,19 @@ void merge_display_update_messages(struct merge_options *opt, trace2_region_leave("merge", "display messages", opt->repo); } +void merge_get_conflicted_files(struct merge_result *result, + struct string_list *conflicted_files) +{ + struct hashmap_iter iter; + struct strmap_entry *e; + struct merge_options_internal *opti = result->priv; + + strmap_for_each_entry(&opti->conflicted, &iter, e) { + string_list_append(conflicted_files, e->key); + } + string_list_sort(conflicted_files); +} + void merge_switch_to_result(struct merge_options *opt, struct tree *head, struct merge_result *result, diff --git a/merge-ort.h b/merge-ort.h index 55819a57da8..165cef6616f 100644 --- a/merge-ort.h +++ b/merge-ort.h @@ -79,6 +79,9 @@ void merge_display_update_messages(struct merge_options *opt, struct merge_result *result, FILE *stream); +void merge_get_conflicted_files(struct merge_result *result, + struct string_list *conflicted_files); + /* Do needed cleanup when not calling merge_switch_to_result() */ void merge_finalize(struct merge_options *opt, struct merge_result *result); diff --git a/t/t4301-merge-tree-real.sh b/t/t4301-merge-tree-real.sh index 5f3f27f504d..ec7bd8efd06 100755 --- a/t/t4301-merge-tree-real.sh +++ b/t/t4301-merge-tree-real.sh @@ -96,4 +96,13 @@ test_expect_success '--messages gives us the conflict notices and such' ' test_cmp expect MSG_FILE ' +test_expect_success '--messages gives us the conflict notices and such' ' + test_must_fail git merge-tree --real --conflicted-list=UNMERGED side1 side2 && + + cat UNMERGED | tr "\0" "\n" >actual && + test_write_lines greeting whatever~side1 >expect && + + test_cmp expect actual +' + test_done -- gitgitgadget