merge-tree.c: allow specifying the merge-base when --stdin is passed
The previous commit added a `--merge-base` option in order to allow using a specified merge-base for the merge. Extend the input accepted by `--stdin` to also allow a specified merge-base with each merge requested. For example: printf "<b3> -- <b1> <b2>" | git merge-tree --stdin does a merge of b1 and b2, and uses b3 as the merge-base. Signed-off-by: Kyle Zhao <kylezhao@tencent.com> Signed-off-by: Taylor Blau <me@ttaylorr.com>
Kyle Zhao committed
Nov 11, 2022 at 23:45 UTC
501e3bab99da75eada3e2d6ef5257a3c44dd1ae4
3 files changed
+67
-3
Documentation/git-merge-tree.txt
+13
-1
@@ -66,7 +66,8 @@ OPTIONS
66
67
--merge-base=<commit>::
68
Instead of finding the merge-bases for <branch1> and <branch2>,
69
- specify a merge-base for the merge.
69
+ specify a merge-base for the merge. This option is incompatible
70
+ with `--stdin`.
71
72
[[OUTPUT]]
73
OUTPUT
@@ -220,6 +221,17 @@ with linkgit:git-merge[1]:
221
* any messages that would have been printed to stdout (the
222
<<IM,Informational messages>>)
223
224
+INPUT FORMAT
225
+------------
226
+'git merge-tree --stdin' input format is fully text based. Each line
227
+has this format:
228
+
229
+ [<base-commit> -- ]<branch1> <branch2>
230
+
231
+If one line is separated by `--`, the string before the separator is
232
+used for specifying a merge-base for the merge and the string after
233
+the separator describes the branches to be merged.
234
+
235
MISTAKES TO AVOID
236
-----------------
237
builtin/merge-tree.c
+19
-2
@@ -557,12 +557,29 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
557
while (strbuf_getline_lf(&buf, stdin) != EOF) {
558
struct strbuf **split;
559
int result;
560
+ const char *input_merge_base = NULL;
561
562
split = strbuf_split(&buf, ' ');
562
- if (!split[0] || !split[1] || split[2])
563
+ if (!split[0] || !split[1])
564
die(_("malformed input line: '%s'."), buf.buf);
565
strbuf_rtrim(split[0]);
565
- result = real_merge(&o, merge_base, split[0]->buf, split[1]->buf, prefix);
566
+ strbuf_rtrim(split[1]);
567
+
568
+ /* parse the merge-base */
569
+ if (!strcmp(split[1]->buf, "--")) {
570
+ input_merge_base = split[0]->buf;
571
+ }
572
+
573
+ if (input_merge_base && split[2] && split[3] && !split[4]) {
574
+ strbuf_rtrim(split[2]);
575
+ strbuf_rtrim(split[3]);
576
+ result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
577
+ } else if (!input_merge_base && !split[2]) {
578
+ result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
579
+ } else {
580
+ die(_("malformed input line: '%s'."), buf.buf);
581
+ }
582
+
583
if (result < 0)
584
die(_("merging cannot continue; got unclean result of %d"), result);
585
strbuf_list_free(split);
t/t4301-merge-tree-write-tree.sh
+35
@@ -860,6 +860,13 @@ test_expect_success '--stdin with both a successful and a conflicted merge' '
860
test_cmp expect actual
861
'
862
863
+
864
+test_expect_success '--merge-base is incompatible with --stdin' '
865
+ test_must_fail git merge-tree --merge-base=side1 --stdin 2>expect &&
866
+
867
+ grep "^fatal: --merge-base is incompatible with --stdin" expect
868
+'
869
+
870
# specify merge-base as parent of branch2
871
# git merge-tree --write-tree --merge-base=c2 c1 c3
872
# Commit c1: add file1
@@ -887,4 +894,32 @@ test_expect_success 'specify merge-base as parent of branch2' '
894
test_cmp expect actual
895
'
896
897
+# Since the earlier tests have verified that individual merge-tree calls
898
+# are doing the right thing, this test case is only used to verify that
899
+# we can also trigger merges via --stdin, and that when we do we get
900
+# the same answer as running a bunch of separate merges.
901
+
902
+test_expect_success 'check the input format when --stdin is passed' '
903
+ test_when_finished "rm -rf repo" &&
904
+ git init repo &&
905
+ test_commit -C repo c1 &&
906
+ test_commit -C repo c2 &&
907
+ test_commit -C repo c3 &&
908
+ printf "c1 c3\nc2 -- c1 c3\nc2 c3" | git -C repo merge-tree --stdin >actual &&
909
+
910
+ printf "1\0" >expect &&
911
+ git -C repo merge-tree --write-tree -z c1 c3 >>expect &&
912
+ printf "\0" >>expect &&
913
+
914
+ printf "1\0" >>expect &&
915
+ git -C repo merge-tree --write-tree -z --merge-base=c2 c1 c3 >>expect &&
916
+ printf "\0" >>expect &&
917
+
918
+ printf "1\0" >>expect &&
919
+ git -C repo merge-tree --write-tree -z c2 c3 >>expect &&
920
+ printf "\0" >>expect &&
921
+
922
+ test_cmp expect actual
923
+'
924
+
925
test_done