@matheusbsbs / matheus-bagliano / commits / 525ab63950
Fork 0

merge-recursive: split low-level merge functions out.

This moves low-level merge functions out of merge-recursive.c and places them in a new separate file, ll-merge.c Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Dec 24, 2007 at 00:36 UTC 525ab63950e324823dd45423104cdcf5e46e2610
4 files changed +408 -369
Makefile
+2 -2
@@ -301,7 +301,7 @@ LIB_H = \
301 run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
302 tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
303 utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
304 - mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
304 + mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h ll-merge.h
305
306 DIFF_OBJS = \
307 diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -324,7 +324,7 @@ LIB_OBJS = \
324 alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
325 color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
326 convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
327 - transport.o bundle.o walker.o parse-options.o ws.o archive.o
327 + transport.o bundle.o walker.o parse-options.o ws.o archive.o ll-merge.o
328
329 BUILTIN_OBJS = \
330 builtin-add.o \
ll-merge.c new
+379
@@ -0,0 +1,379 @@
1 +/*
2 + * Low level 3-way in-core file merge.
3 + *
4 + * Copyright (c) 2007 Junio C Hamano
5 + */
6 +
7 +#include "cache.h"
8 +#include "attr.h"
9 +#include "xdiff-interface.h"
10 +#include "run-command.h"
11 +#include "interpolate.h"
12 +#include "ll-merge.h"
13 +
14 +struct ll_merge_driver;
15 +
16 +typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
17 + mmbuffer_t *result,
18 + const char *path,
19 + mmfile_t *orig,
20 + mmfile_t *src1, const char *name1,
21 + mmfile_t *src2, const char *name2,
22 + int virtual_ancestor);
23 +
24 +struct ll_merge_driver {
25 + const char *name;
26 + const char *description;
27 + ll_merge_fn fn;
28 + const char *recursive;
29 + struct ll_merge_driver *next;
30 + char *cmdline;
31 +};
32 +
33 +/*
34 + * Built-in low-levels
35 + */
36 +static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
37 + mmbuffer_t *result,
38 + const char *path_unused,
39 + mmfile_t *orig,
40 + mmfile_t *src1, const char *name1,
41 + mmfile_t *src2, const char *name2,
42 + int virtual_ancestor)
43 +{
44 + /*
45 + * The tentative merge result is "ours" for the final round,
46 + * or common ancestor for an internal merge. Still return
47 + * "conflicted merge" status.
48 + */
49 + mmfile_t *stolen = virtual_ancestor ? orig : src1;
50 +
51 + result->ptr = stolen->ptr;
52 + result->size = stolen->size;
53 + stolen->ptr = NULL;
54 + return 1;
55 +}
56 +
57 +static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
58 + mmbuffer_t *result,
59 + const char *path_unused,
60 + mmfile_t *orig,
61 + mmfile_t *src1, const char *name1,
62 + mmfile_t *src2, const char *name2,
63 + int virtual_ancestor)
64 +{
65 + xpparam_t xpp;
66 +
67 + if (buffer_is_binary(orig->ptr, orig->size) ||
68 + buffer_is_binary(src1->ptr, src1->size) ||
69 + buffer_is_binary(src2->ptr, src2->size)) {
70 + warning("Cannot merge binary files: %s vs. %s\n",
71 + name1, name2);
72 + return ll_binary_merge(drv_unused, result,
73 + path_unused,
74 + orig, src1, name1,
75 + src2, name2,
76 + virtual_ancestor);
77 + }
78 +
79 + memset(&xpp, 0, sizeof(xpp));
80 + return xdl_merge(orig,
81 + src1, name1,
82 + src2, name2,
83 + &xpp, XDL_MERGE_ZEALOUS,
84 + result);
85 +}
86 +
87 +static int ll_union_merge(const struct ll_merge_driver *drv_unused,
88 + mmbuffer_t *result,
89 + const char *path_unused,
90 + mmfile_t *orig,
91 + mmfile_t *src1, const char *name1,
92 + mmfile_t *src2, const char *name2,
93 + int virtual_ancestor)
94 +{
95 + char *src, *dst;
96 + long size;
97 + const int marker_size = 7;
98 +
99 + int status = ll_xdl_merge(drv_unused, result, path_unused,
100 + orig, src1, NULL, src2, NULL,
101 + virtual_ancestor);
102 + if (status <= 0)
103 + return status;
104 + size = result->size;
105 + src = dst = result->ptr;
106 + while (size) {
107 + char ch;
108 + if ((marker_size < size) &&
109 + (*src == '<' || *src == '=' || *src == '>')) {
110 + int i;
111 + ch = *src;
112 + for (i = 0; i < marker_size; i++)
113 + if (src[i] != ch)
114 + goto not_a_marker;
115 + if (src[marker_size] != '\n')
116 + goto not_a_marker;
117 + src += marker_size + 1;
118 + size -= marker_size + 1;
119 + continue;
120 + }
121 + not_a_marker:
122 + do {
123 + ch = *src++;
124 + *dst++ = ch;
125 + size--;
126 + } while (ch != '\n' && size);
127 + }
128 + result->size = dst - result->ptr;
129 + return 0;
130 +}
131 +
132 +#define LL_BINARY_MERGE 0
133 +#define LL_TEXT_MERGE 1
134 +#define LL_UNION_MERGE 2
135 +static struct ll_merge_driver ll_merge_drv[] = {
136 + { "binary", "built-in binary merge", ll_binary_merge },
137 + { "text", "built-in 3-way text merge", ll_xdl_merge },
138 + { "union", "built-in union merge", ll_union_merge },
139 +};
140 +
141 +static void create_temp(mmfile_t *src, char *path)
142 +{
143 + int fd;
144 +
145 + strcpy(path, ".merge_file_XXXXXX");
146 + fd = xmkstemp(path);
147 + if (write_in_full(fd, src->ptr, src->size) != src->size)
148 + die("unable to write temp-file");
149 + close(fd);
150 +}
151 +
152 +/*
153 + * User defined low-level merge driver support.
154 + */
155 +static int ll_ext_merge(const struct ll_merge_driver *fn,
156 + mmbuffer_t *result,
157 + const char *path,
158 + mmfile_t *orig,
159 + mmfile_t *src1, const char *name1,
160 + mmfile_t *src2, const char *name2,
161 + int virtual_ancestor)
162 +{
163 + char temp[3][50];
164 + char cmdbuf[2048];
165 + struct interp table[] = {
166 + { "%O" },
167 + { "%A" },
168 + { "%B" },
169 + };
170 + struct child_process child;
171 + const char *args[20];
172 + int status, fd, i;
173 + struct stat st;
174 +
175 + if (fn->cmdline == NULL)
176 + die("custom merge driver %s lacks command line.", fn->name);
177 +
178 + result->ptr = NULL;
179 + result->size = 0;
180 + create_temp(orig, temp[0]);
181 + create_temp(src1, temp[1]);
182 + create_temp(src2, temp[2]);
183 +
184 + interp_set_entry(table, 0, temp[0]);
185 + interp_set_entry(table, 1, temp[1]);
186 + interp_set_entry(table, 2, temp[2]);
187 +
188 + interpolate(cmdbuf, sizeof(cmdbuf), fn->cmdline, table, 3);
189 +
190 + memset(&child, 0, sizeof(child));
191 + child.argv = args;
192 + args[0] = "sh";
193 + args[1] = "-c";
194 + args[2] = cmdbuf;
195 + args[3] = NULL;
196 +
197 + status = run_command(&child);
198 + if (status < -ERR_RUN_COMMAND_FORK)
199 + ; /* failure in run-command */
200 + else
201 + status = -status;
202 + fd = open(temp[1], O_RDONLY);
203 + if (fd < 0)
204 + goto bad;
205 + if (fstat(fd, &st))
206 + goto close_bad;
207 + result->size = st.st_size;
208 + result->ptr = xmalloc(result->size + 1);
209 + if (read_in_full(fd, result->ptr, result->size) != result->size) {
210 + free(result->ptr);
211 + result->ptr = NULL;
212 + result->size = 0;
213 + }
214 + close_bad:
215 + close(fd);
216 + bad:
217 + for (i = 0; i < 3; i++)
218 + unlink(temp[i]);
219 + return status;
220 +}
221 +
222 +/*
223 + * merge.default and merge.driver configuration items
224 + */
225 +static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
226 +static const char *default_ll_merge;
227 +
228 +static int read_merge_config(const char *var, const char *value)
229 +{
230 + struct ll_merge_driver *fn;
231 + const char *ep, *name;
232 + int namelen;
233 +
234 + if (!strcmp(var, "merge.default")) {
235 + if (value)
236 + default_ll_merge = strdup(value);
237 + return 0;
238 + }
239 +
240 + /*
241 + * We are not interested in anything but "merge.<name>.variable";
242 + * especially, we do not want to look at variables such as
243 + * "merge.summary", "merge.tool", and "merge.verbosity".
244 + */
245 + if (prefixcmp(var, "merge.") || (ep = strrchr(var, '.')) == var + 5)
246 + return 0;
247 +
248 + /*
249 + * Find existing one as we might be processing merge.<name>.var2
250 + * after seeing merge.<name>.var1.
251 + */
252 + name = var + 6;
253 + namelen = ep - name;
254 + for (fn = ll_user_merge; fn; fn = fn->next)
255 + if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
256 + break;
257 + if (!fn) {
258 + fn = xcalloc(1, sizeof(struct ll_merge_driver));
259 + fn->name = xmemdupz(name, namelen);
260 + fn->fn = ll_ext_merge;
261 + *ll_user_merge_tail = fn;
262 + ll_user_merge_tail = &(fn->next);
263 + }
264 +
265 + ep++;
266 +
267 + if (!strcmp("name", ep)) {
268 + if (!value)
269 + return error("%s: lacks value", var);
270 + fn->description = strdup(value);
271 + return 0;
272 + }
273 +
274 + if (!strcmp("driver", ep)) {
275 + if (!value)
276 + return error("%s: lacks value", var);
277 + /*
278 + * merge.<name>.driver specifies the command line:
279 + *
280 + * command-line
281 + *
282 + * The command-line will be interpolated with the following
283 + * tokens and is given to the shell:
284 + *
285 + * %O - temporary file name for the merge base.
286 + * %A - temporary file name for our version.
287 + * %B - temporary file name for the other branches' version.
288 + *
289 + * The external merge driver should write the results in the
290 + * file named by %A, and signal that it has done with zero exit
291 + * status.
292 + */
293 + fn->cmdline = strdup(value);
294 + return 0;
295 + }
296 +
297 + if (!strcmp("recursive", ep)) {
298 + if (!value)
299 + return error("%s: lacks value", var);
300 + fn->recursive = strdup(value);
301 + return 0;
302 + }
303 +
304 + return 0;
305 +}
306 +
307 +static void initialize_ll_merge(void)
308 +{
309 + if (ll_user_merge_tail)
310 + return;
311 + ll_user_merge_tail = &ll_user_merge;
312 + git_config(read_merge_config);
313 +}
314 +
315 +static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr)
316 +{
317 + struct ll_merge_driver *fn;
318 + const char *name;
319 + int i;
320 +
321 + initialize_ll_merge();
322 +
323 + if (ATTR_TRUE(merge_attr))
324 + return &ll_merge_drv[LL_TEXT_MERGE];
325 + else if (ATTR_FALSE(merge_attr))
326 + return &ll_merge_drv[LL_BINARY_MERGE];
327 + else if (ATTR_UNSET(merge_attr)) {
328 + if (!default_ll_merge)
329 + return &ll_merge_drv[LL_TEXT_MERGE];
330 + else
331 + name = default_ll_merge;
332 + }
333 + else
334 + name = merge_attr;
335 +
336 + for (fn = ll_user_merge; fn; fn = fn->next)
337 + if (!strcmp(fn->name, name))
338 + return fn;
339 +
340 + for (i = 0; i < ARRAY_SIZE(ll_merge_drv); i++)
341 + if (!strcmp(ll_merge_drv[i].name, name))
342 + return &ll_merge_drv[i];
343 +
344 + /* default to the 3-way */
345 + return &ll_merge_drv[LL_TEXT_MERGE];
346 +}
347 +
348 +static const char *git_path_check_merge(const char *path)
349 +{
350 + static struct git_attr_check attr_merge_check;
351 +
352 + if (!attr_merge_check.attr)
353 + attr_merge_check.attr = git_attr("merge", 5);
354 +
355 + if (git_checkattr(path, 1, &attr_merge_check))
356 + return NULL;
357 + return attr_merge_check.value;
358 +}
359 +
360 +int ll_merge(mmbuffer_t *result_buf,
361 + const char *path,
362 + mmfile_t *ancestor,
363 + mmfile_t *ours, const char *our_label,
364 + mmfile_t *theirs, const char *their_label,
365 + int virtual_ancestor)
366 +{
367 + const char *ll_driver_name;
368 + const struct ll_merge_driver *driver;
369 +
370 + ll_driver_name = git_path_check_merge(path);
371 + driver = find_ll_merge_driver(ll_driver_name);
372 +
373 + if (virtual_ancestor && driver->recursive)
374 + driver = find_ll_merge_driver(driver->recursive);
375 + return driver->fn(driver, result_buf, path,
376 + ancestor,
377 + ours, our_label,
378 + theirs, their_label, virtual_ancestor);
379 +}
ll-merge.h new
+15
@@ -0,0 +1,15 @@
1 +/*
2 + * Low level 3-way in-core file merge.
3 + */
4 +
5 +#ifndef LL_MERGE_H
6 +#define LL_MERGE_H
7 +
8 +int ll_merge(mmbuffer_t *result_buf,
9 + const char *path,
10 + mmfile_t *ancestor,
11 + mmfile_t *ours, const char *our_label,
12 + mmfile_t *theirs, const char *their_label,
13 + int virtual_ancestor);
14 +
15 +#endif
merge-recursive.c
+12 -367
@@ -10,13 +10,11 @@
10 #include "tree-walk.h"
11 #include "diff.h"
12 #include "diffcore.h"
13 -#include "run-command.h"
13 #include "tag.h"
14 #include "unpack-trees.h"
15 #include "path-list.h"
16 #include "xdiff-interface.h"
18 -#include "interpolate.h"
19 -#include "attr.h"
17 +#include "ll-merge.h"
18
19 static int subtree_merge;
20
@@ -624,364 +622,16 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm)
622 mm->size = size;
623 }
624
627 -/*
628 - * Customizable low-level merge drivers support.
629 - */
630 -
631 -struct ll_merge_driver;
632 -typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
633 - const char *path,
634 - mmfile_t *orig,
635 - mmfile_t *src1, const char *name1,
636 - mmfile_t *src2, const char *name2,
637 - mmbuffer_t *result);
638 -
639 -struct ll_merge_driver {
640 - const char *name;
641 - const char *description;
642 - ll_merge_fn fn;
643 - const char *recursive;
644 - struct ll_merge_driver *next;
645 - char *cmdline;
646 -};
647 -
648 -/*
649 - * Built-in low-levels
650 - */
651 -static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
652 - const char *path_unused,
653 - mmfile_t *orig,
654 - mmfile_t *src1, const char *name1,
655 - mmfile_t *src2, const char *name2,
656 - mmbuffer_t *result)
657 -{
658 - /*
659 - * The tentative merge result is "ours" for the final round,
660 - * or common ancestor for an internal merge. Still return
661 - * "conflicted merge" status.
662 - */
663 - mmfile_t *stolen = index_only ? orig : src1;
664 -
665 - result->ptr = stolen->ptr;
666 - result->size = stolen->size;
667 - stolen->ptr = NULL;
668 - return 1;
669 -}
670 -
671 -static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
672 - const char *path_unused,
673 - mmfile_t *orig,
674 - mmfile_t *src1, const char *name1,
675 - mmfile_t *src2, const char *name2,
676 - mmbuffer_t *result)
677 -{
678 - xpparam_t xpp;
679 -
680 - if (buffer_is_binary(orig->ptr, orig->size) ||
681 - buffer_is_binary(src1->ptr, src1->size) ||
682 - buffer_is_binary(src2->ptr, src2->size)) {
683 - warning("Cannot merge binary files: %s vs. %s\n",
684 - name1, name2);
685 - return ll_binary_merge(drv_unused, path_unused,
686 - orig, src1, name1,
687 - src2, name2,
688 - result);
689 - }
690 -
691 - memset(&xpp, 0, sizeof(xpp));
692 - return xdl_merge(orig,
693 - src1, name1,
694 - src2, name2,
695 - &xpp, XDL_MERGE_ZEALOUS,
696 - result);
697 -}
698 -
699 -static int ll_union_merge(const struct ll_merge_driver *drv_unused,
700 - const char *path_unused,
701 - mmfile_t *orig,
702 - mmfile_t *src1, const char *name1,
703 - mmfile_t *src2, const char *name2,
704 - mmbuffer_t *result)
705 -{
706 - char *src, *dst;
707 - long size;
708 - const int marker_size = 7;
709 -
710 - int status = ll_xdl_merge(drv_unused, path_unused,
711 - orig, src1, NULL, src2, NULL, result);
712 - if (status <= 0)
713 - return status;
714 - size = result->size;
715 - src = dst = result->ptr;
716 - while (size) {
717 - char ch;
718 - if ((marker_size < size) &&
719 - (*src == '<' || *src == '=' || *src == '>')) {
720 - int i;
721 - ch = *src;
722 - for (i = 0; i < marker_size; i++)
723 - if (src[i] != ch)
724 - goto not_a_marker;
725 - if (src[marker_size] != '\n')
726 - goto not_a_marker;
727 - src += marker_size + 1;
728 - size -= marker_size + 1;
729 - continue;
730 - }
731 - not_a_marker:
732 - do {
733 - ch = *src++;
734 - *dst++ = ch;
735 - size--;
736 - } while (ch != '\n' && size);
737 - }
738 - result->size = dst - result->ptr;
739 - return 0;
740 -}
741 -
742 -#define LL_BINARY_MERGE 0
743 -#define LL_TEXT_MERGE 1
744 -#define LL_UNION_MERGE 2
745 -static struct ll_merge_driver ll_merge_drv[] = {
746 - { "binary", "built-in binary merge", ll_binary_merge },
747 - { "text", "built-in 3-way text merge", ll_xdl_merge },
748 - { "union", "built-in union merge", ll_union_merge },
749 -};
750 -
751 -static void create_temp(mmfile_t *src, char *path)
752 -{
753 - int fd;
754 -
755 - strcpy(path, ".merge_file_XXXXXX");
756 - fd = xmkstemp(path);
757 - if (write_in_full(fd, src->ptr, src->size) != src->size)
758 - die("unable to write temp-file");
759 - close(fd);
760 -}
761 -
762 -/*
763 - * User defined low-level merge driver support.
764 - */
765 -static int ll_ext_merge(const struct ll_merge_driver *fn,
766 - const char *path,
767 - mmfile_t *orig,
768 - mmfile_t *src1, const char *name1,
769 - mmfile_t *src2, const char *name2,
770 - mmbuffer_t *result)
771 -{
772 - char temp[3][50];
773 - char cmdbuf[2048];
774 - struct interp table[] = {
775 - { "%O" },
776 - { "%A" },
777 - { "%B" },
778 - };
779 - struct child_process child;
780 - const char *args[20];
781 - int status, fd, i;
782 - struct stat st;
783 -
784 - if (fn->cmdline == NULL)
785 - die("custom merge driver %s lacks command line.", fn->name);
786 -
787 - result->ptr = NULL;
788 - result->size = 0;
789 - create_temp(orig, temp[0]);
790 - create_temp(src1, temp[1]);
791 - create_temp(src2, temp[2]);
792 -
793 - interp_set_entry(table, 0, temp[0]);
794 - interp_set_entry(table, 1, temp[1]);
795 - interp_set_entry(table, 2, temp[2]);
796 -
797 - output(1, "merging %s using %s", path,
798 - fn->description ? fn->description : fn->name);
799 -
800 - interpolate(cmdbuf, sizeof(cmdbuf), fn->cmdline, table, 3);
801 -
802 - memset(&child, 0, sizeof(child));
803 - child.argv = args;
804 - args[0] = "sh";
805 - args[1] = "-c";
806 - args[2] = cmdbuf;
807 - args[3] = NULL;
808 -
809 - status = run_command(&child);
810 - if (status < -ERR_RUN_COMMAND_FORK)
811 - ; /* failure in run-command */
812 - else
813 - status = -status;
814 - fd = open(temp[1], O_RDONLY);
815 - if (fd < 0)
816 - goto bad;
817 - if (fstat(fd, &st))
818 - goto close_bad;
819 - result->size = st.st_size;
820 - result->ptr = xmalloc(result->size + 1);
821 - if (read_in_full(fd, result->ptr, result->size) != result->size) {
822 - free(result->ptr);
823 - result->ptr = NULL;
824 - result->size = 0;
825 - }
826 - close_bad:
827 - close(fd);
828 - bad:
829 - for (i = 0; i < 3; i++)
830 - unlink(temp[i]);
831 - return status;
832 -}
833 -
834 -/*
835 - * merge.default and merge.driver configuration items
836 - */
837 -static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail;
838 -static const char *default_ll_merge;
839 -
840 -static int read_merge_config(const char *var, const char *value)
841 -{
842 - struct ll_merge_driver *fn;
843 - const char *ep, *name;
844 - int namelen;
845 -
846 - if (!strcmp(var, "merge.default")) {
847 - if (!value)
848 - return config_error_nonbool(var);
849 - default_ll_merge = strdup(value);
850 - return 0;
851 - }
852 -
853 - /*
854 - * We are not interested in anything but "merge.<name>.variable";
855 - * especially, we do not want to look at variables such as
856 - * "merge.summary", "merge.tool", and "merge.verbosity".
857 - */
858 - if (prefixcmp(var, "merge.") || (ep = strrchr(var, '.')) == var + 5)
859 - return 0;
860 -
861 - /*
862 - * Find existing one as we might be processing merge.<name>.var2
863 - * after seeing merge.<name>.var1.
864 - */
865 - name = var + 6;
866 - namelen = ep - name;
867 - for (fn = ll_user_merge; fn; fn = fn->next)
868 - if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
869 - break;
870 - if (!fn) {
871 - fn = xcalloc(1, sizeof(struct ll_merge_driver));
872 - fn->name = xmemdupz(name, namelen);
873 - fn->fn = ll_ext_merge;
874 - *ll_user_merge_tail = fn;
875 - ll_user_merge_tail = &(fn->next);
876 - }
877 -
878 - ep++;
879 -
880 - if (!strcmp("name", ep)) {
881 - if (!value)
882 - return config_error_nonbool(var);
883 - fn->description = strdup(value);
884 - return 0;
885 - }
886 -
887 - if (!strcmp("driver", ep)) {
888 - if (!value)
889 - return config_error_nonbool(var);
890 - /*
891 - * merge.<name>.driver specifies the command line:
892 - *
893 - * command-line
894 - *
895 - * The command-line will be interpolated with the following
896 - * tokens and is given to the shell:
897 - *
898 - * %O - temporary file name for the merge base.
899 - * %A - temporary file name for our version.
900 - * %B - temporary file name for the other branches' version.
901 - *
902 - * The external merge driver should write the results in the
903 - * file named by %A, and signal that it has done with zero exit
904 - * status.
905 - */
906 - fn->cmdline = strdup(value);
907 - return 0;
908 - }
909 -
910 - if (!strcmp("recursive", ep)) {
911 - if (!value)
912 - return config_error_nonbool(var);
913 - fn->recursive = strdup(value);
914 - return 0;
915 - }
916 -
917 - return 0;
918 -}
919 -
920 -static void initialize_ll_merge(void)
921 -{
922 - if (ll_user_merge_tail)
923 - return;
924 - ll_user_merge_tail = &ll_user_merge;
925 - git_config(read_merge_config);
926 -}
927 -
928 -static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr)
929 -{
930 - struct ll_merge_driver *fn;
931 - const char *name;
932 - int i;
933 -
934 - initialize_ll_merge();
935 -
936 - if (ATTR_TRUE(merge_attr))
937 - return &ll_merge_drv[LL_TEXT_MERGE];
938 - else if (ATTR_FALSE(merge_attr))
939 - return &ll_merge_drv[LL_BINARY_MERGE];
940 - else if (ATTR_UNSET(merge_attr)) {
941 - if (!default_ll_merge)
942 - return &ll_merge_drv[LL_TEXT_MERGE];
943 - else
944 - name = default_ll_merge;
945 - }
946 - else
947 - name = merge_attr;
948 -
949 - for (fn = ll_user_merge; fn; fn = fn->next)
950 - if (!strcmp(fn->name, name))
951 - return fn;
952 -
953 - for (i = 0; i < ARRAY_SIZE(ll_merge_drv); i++)
954 - if (!strcmp(ll_merge_drv[i].name, name))
955 - return &ll_merge_drv[i];
956 -
957 - /* default to the 3-way */
958 - return &ll_merge_drv[LL_TEXT_MERGE];
959 -}
960 -
961 -static const char *git_path_check_merge(const char *path)
962 -{
963 - static struct git_attr_check attr_merge_check;
964 -
965 - if (!attr_merge_check.attr)
966 - attr_merge_check.attr = git_attr("merge", 5);
967 -
968 - if (git_checkattr(path, 1, &attr_merge_check))
969 - return NULL;
970 - return attr_merge_check.value;
971 -}
972 -
973 -static int ll_merge(mmbuffer_t *result_buf,
974 - struct diff_filespec *o,
975 - struct diff_filespec *a,
976 - struct diff_filespec *b,
977 - const char *branch1,
978 - const char *branch2)
625 +static int merge_3way(mmbuffer_t *result_buf,
626 + struct diff_filespec *o,
627 + struct diff_filespec *a,
628 + struct diff_filespec *b,
629 + const char *branch1,
630 + const char *branch2)
631 {
632 mmfile_t orig, src1, src2;
633 char *name1, *name2;
634 int merge_status;
983 - const char *ll_driver_name;
984 - const struct ll_merge_driver *driver;
635
636 name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
637 name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
@@ -990,14 +640,9 @@ static int ll_merge(mmbuffer_t *result_buf,
640 fill_mm(a->sha1, &src1);
641 fill_mm(b->sha1, &src2);
642
993 - ll_driver_name = git_path_check_merge(a->path);
994 - driver = find_ll_merge_driver(ll_driver_name);
995 -
996 - if (index_only && driver->recursive)
997 - driver = find_ll_merge_driver(driver->recursive);
998 - merge_status = driver->fn(driver, a->path,
999 - &orig, &src1, name1, &src2, name2,
1000 - result_buf);
643 + merge_status = ll_merge(result_buf, a->path, &orig,
644 + &src1, name1, &src2, name2,
645 + index_only);
646
647 free(name1);
648 free(name2);
@@ -1038,8 +683,8 @@ static struct merge_file_info merge_file(struct diff_filespec *o,
683 mmbuffer_t result_buf;
684 int merge_status;
685
1041 - merge_status = ll_merge(&result_buf, o, a, b,
1042 - branch1, branch2);
686 + merge_status = merge_3way(&result_buf, o, a, b,
687 + branch1, branch2);
688
689 if ((merge_status < 0) || !result_buf.ptr)
690 die("Failed to execute internal merge");