merge: teach -Xours/-Xtheirs to binary ll-merge driver

The (discouraged) -Xours/-Xtheirs modes of merge are supposed to give a quick and dirty way to come up with a random mixture of cleanly merged parts and punted conflict resolution to take contents from one side in conflicting parts. These options however were only passed down to the low level merge driver for text. Teach the built-in binary merge driver to notice them as well. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Sep 8, 2012 at 21:27 UTC a944af1d86e6171d68ed2a3aa67b1d68f00e1fe8
3 files changed +35 -7
Documentation/merge-strategies.txt
+2 -1
@@ -32,13 +32,14 @@ ours;;
32 This option forces conflicting hunks to be auto-resolved cleanly by
33 favoring 'our' version. Changes from the other tree that do not
34 conflict with our side are reflected to the merge result.
35 + For a binary file, the entire contents are taken from our side.
36 +
37 This should not be confused with the 'ours' merge strategy, which does not
38 even look at what the other tree contains at all. It discards everything
39 the other tree did, declaring 'our' history contains all that happened in it.
40
41 theirs;;
41 - This is opposite of 'ours'.
42 + This is the opposite of 'ours'.
43
44 patience;;
45 With this option, 'merge-recursive' spends a little extra time
ll-merge.c
+20 -5
@@ -46,16 +46,31 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
46 assert(opts);
47
48 /*
49 - * The tentative merge result is "ours" for the final round,
50 - * or common ancestor for an internal merge. Still return
51 - * "conflicted merge" status.
49 + * The tentative merge result is the or common ancestor for an internal merge.
50 */
53 - stolen = opts->virtual_ancestor ? orig : src1;
51 + if (opts->virtual_ancestor) {
52 + stolen = orig;
53 + } else {
54 + switch (opts->variant) {
55 + default:
56 + case XDL_MERGE_FAVOR_OURS:
57 + stolen = src1;
58 + break;
59 + case XDL_MERGE_FAVOR_THEIRS:
60 + stolen = src2;
61 + break;
62 + }
63 + }
64
65 result->ptr = stolen->ptr;
66 result->size = stolen->size;
67 stolen->ptr = NULL;
58 - return 1;
68 +
69 + /*
70 + * With -Xtheirs or -Xours, we have cleanly merged;
71 + * otherwise we got a conflict.
72 + */
73 + return (opts->variant ? 0 : 1);
74 }
75
76 static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
t/t6037-merge-ours-theirs.sh
+13 -1
@@ -53,7 +53,19 @@ test_expect_success 'recursive favouring ours' '
53 ! grep 1 file
54 '
55
56 -test_expect_success 'pull with -X' '
56 +test_expect_success 'binary file with -Xours/-Xtheirs' '
57 + echo "file -merge" >.gitattributes &&
58 +
59 + git reset --hard master &&
60 + git merge -s recursive -X theirs side &&
61 + git diff --exit-code side HEAD -- file &&
62 +
63 + git reset --hard master &&
64 + git merge -s recursive -X ours side &&
65 + git diff --exit-code master HEAD -- file
66 +'
67 +
68 +test_expect_success 'pull passes -X to underlying merge' '
69 git reset --hard master && git pull -s recursive -Xours . side &&
70 git reset --hard master && git pull -s recursive -X ours . side &&
71 git reset --hard master && git pull -s recursive -Xtheirs . side &&