@matheusbsbs / matheus-bagliano / commits / 712516bcac
Fork 0

ll-merge: replace flag argument with options struct

Keeping track of the flag bits is proving more trouble than it's worth. Instead, use a pointer to an options struct like most similar APIs do. Callers with no special requests can pass NULL to request the default options. Cc: Bert Wesarg <bert.wesarg@googlemail.com> Cc: Avery Pennarun <apenwarr@gmail.com> Helped-by: Justin Frankel <justin@cockos.com> Helped-by: Bert Wesarg <bert.wesarg@googlemail.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Nieder committed Aug 26, 2010 at 00:49 UTC 712516bcacacd45b4825ec649f15c3573f6fb42a
7 files changed +104 -66
Documentation/technical/api-merge.txt
+51 -20
@@ -17,6 +17,40 @@ responsible for a few things.
17 path-specific merge drivers (specified in `.gitattributes`)
18 into account.
19
20 +Data structures
21 +---------------
22 +
23 +* `mmbuffer_t`, `mmfile_t`
24 +
25 +These store data usable for use by the xdiff backend, for writing and
26 +for reading, respectively. See `xdiff/xdiff.h` for the definitions
27 +and `diff.c` for examples.
28 +
29 +* `struct ll_merge_options`
30 +
31 +This describes the set of options the calling program wants to affect
32 +the operation of a low-level (single file) merge. Some options:
33 +
34 +`virtual_ancestor`::
35 + Behave as though this were part of a merge between common
36 + ancestors in a recursive merge.
37 + If a helper program is specified by the
38 + `[merge "<driver>"] recursive` configuration, it will
39 + be used (see linkgit:gitattributes[5]).
40 +
41 +`variant`::
42 + Resolve local conflicts automatically in favor
43 + of one side or the other (as in 'git merge-file'
44 + `--ours`/`--theirs`/`--union`). Can be `0`,
45 + `XDL_MERGE_FAVOR_OURS`, `XDL_MERGE_FAVOR_THEIRS`, or
46 + `XDL_MERGE_FAVOR_UNION`.
47 +
48 +`renormalize`::
49 + Resmudge and clean the "base", "theirs" and "ours" files
50 + before merging. Use this when the merge is likely to have
51 + overlapped with a change in smudge/clean or end-of-line
52 + normalization rules.
53 +
54 Low-level (single file) merge
55 -----------------------------
56
@@ -28,15 +62,24 @@ Low-level (single file) merge
62 `.git/info/attributes` into account. Returns 0 for a
63 clean merge.
64
31 -The caller:
65 +Calling sequence:
66
33 -1. allocates an mmbuffer_t variable for the result;
34 -2. allocates and fills variables with the file's original content
35 - and two modified versions (using `read_mmfile`, for example);
36 -3. calls ll_merge();
37 -4. reads the output from result_buf.ptr and result_buf.size;
38 -5. releases buffers when finished (free(ancestor.ptr); free(ours.ptr);
39 - free(theirs.ptr); free(result_buf.ptr);).
67 +* Prepare a `struct ll_merge_options` to record options.
68 + If you have no special requests, skip this and pass `NULL`
69 + as the `opts` parameter to use the default options.
70 +
71 +* Allocate an mmbuffer_t variable for the result.
72 +
73 +* Allocate and fill variables with the file's original content
74 + and two modified versions (using `read_mmfile`, for example).
75 +
76 +* Call `ll_merge()`.
77 +
78 +* Read the merged content from `result_buf.ptr` and `result_buf.size`.
79 +
80 +* Release buffers when finished. A simple
81 + `free(ancestor.ptr); free(ours.ptr); free(theirs.ptr);
82 + free(result_buf.ptr);` will do.
83
84 If the modifications do not merge cleanly, `ll_merge` will return a
85 nonzero value and `result_buf` will generally include a description of
@@ -47,18 +90,6 @@ The `ancestor_label`, `our_label`, and `their_label` parameters are
90 used to label the different sides of a conflict if the merge driver
91 supports this.
92
50 -The `flag` parameter is a bitfield:
51 -
52 - - The `LL_OPT_VIRTUAL_ANCESTOR` bit indicates whether this is an
53 - internal merge to consolidate ancestors for a recursive merge.
54 -
55 - - The `LL_OPT_FAVOR_MASK` bits allow local conflicts to be automatically
56 - resolved in favor of one side or the other (as in 'git merge-file'
57 - `--ours`/`--theirs`/`--union`).
58 - They can be populated by `create_ll_flag`, whose argument can be
59 - `XDL_MERGE_FAVOR_OURS`, `XDL_MERGE_FAVOR_THEIRS`, or
60 - `XDL_MERGE_FAVOR_UNION`.
61 -
93 Everything else
94 ---------------
95
builtin/checkout.c
+1 -1
@@ -155,7 +155,7 @@ static int checkout_merged(int pos, struct checkout *state)
155 * merge.renormalize set, too
156 */
157 status = ll_merge(&result_buf, path, &ancestor, "base",
158 - &ours, "ours", &theirs, "theirs", 0);
158 + &ours, "ours", &theirs, "theirs", NULL);
159 free(ancestor.ptr);
160 free(ours.ptr);
161 free(theirs.ptr);
ll-merge.c
+33 -17
@@ -18,7 +18,7 @@ typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
18 mmfile_t *orig, const char *orig_name,
19 mmfile_t *src1, const char *name1,
20 mmfile_t *src2, const char *name2,
21 - int flag,
21 + const struct ll_merge_options *opts,
22 int marker_size);
23
24 struct ll_merge_driver {
@@ -39,14 +39,18 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
39 mmfile_t *orig, const char *orig_name,
40 mmfile_t *src1, const char *name1,
41 mmfile_t *src2, const char *name2,
42 - int flag, int marker_size)
42 + const struct ll_merge_options *opts,
43 + int marker_size)
44 {
45 + mmfile_t *stolen;
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.
52 */
49 - mmfile_t *stolen = (flag & LL_OPT_VIRTUAL_ANCESTOR) ? orig : src1;
53 + stolen = opts->virtual_ancestor ? orig : src1;
54
55 result->ptr = stolen->ptr;
56 result->size = stolen->size;
@@ -60,9 +64,11 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
64 mmfile_t *orig, const char *orig_name,
65 mmfile_t *src1, const char *name1,
66 mmfile_t *src2, const char *name2,
63 - int flag, int marker_size)
67 + const struct ll_merge_options *opts,
68 + int marker_size)
69 {
70 xmparam_t xmp;
71 + assert(opts);
72
73 if (buffer_is_binary(orig->ptr, orig->size) ||
74 buffer_is_binary(src1->ptr, src1->size) ||
@@ -74,12 +80,12 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
80 orig, orig_name,
81 src1, name1,
82 src2, name2,
77 - flag, marker_size);
83 + opts, marker_size);
84 }
85
86 memset(&xmp, 0, sizeof(xmp));
87 xmp.level = XDL_MERGE_ZEALOUS;
82 - xmp.favor = ll_opt_favor(flag);
88 + xmp.favor = opts->variant;
89 if (git_xmerge_style >= 0)
90 xmp.style = git_xmerge_style;
91 if (marker_size > 0)
@@ -96,15 +102,17 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
102 mmfile_t *orig, const char *orig_name,
103 mmfile_t *src1, const char *name1,
104 mmfile_t *src2, const char *name2,
99 - int flag, int marker_size)
105 + const struct ll_merge_options *opts,
106 + int marker_size)
107 {
108 /* Use union favor */
102 - flag &= ~LL_OPT_FAVOR_MASK;
103 - flag |= create_ll_flag(XDL_MERGE_FAVOR_UNION);
109 + struct ll_merge_options o;
110 + assert(opts);
111 + o = *opts;
112 + o.variant = XDL_MERGE_FAVOR_UNION;
113 return ll_xdl_merge(drv_unused, result, path_unused,
114 orig, NULL, src1, NULL, src2, NULL,
106 - flag, marker_size);
107 - return 0;
115 + &o, marker_size);
116 }
117
118 #define LL_BINARY_MERGE 0
@@ -136,7 +144,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
144 mmfile_t *orig, const char *orig_name,
145 mmfile_t *src1, const char *name1,
146 mmfile_t *src2, const char *name2,
139 - int flag, int marker_size)
147 + const struct ll_merge_options *opts,
148 + int marker_size)
149 {
150 char temp[4][50];
151 struct strbuf cmd = STRBUF_INIT;
@@ -144,6 +153,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
153 const char *args[] = { NULL, NULL };
154 int status, fd, i;
155 struct stat st;
156 + assert(opts);
157
158 dict[0].placeholder = "O"; dict[0].value = temp[0];
159 dict[1].placeholder = "A"; dict[1].value = temp[1];
@@ -337,15 +347,21 @@ int ll_merge(mmbuffer_t *result_buf,
347 mmfile_t *ancestor, const char *ancestor_label,
348 mmfile_t *ours, const char *our_label,
349 mmfile_t *theirs, const char *their_label,
340 - int flag)
350 + const struct ll_merge_options *opts)
351 {
352 static struct git_attr_check check[2];
353 const char *ll_driver_name = NULL;
354 int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
355 const struct ll_merge_driver *driver;
346 - int virtual_ancestor = flag & LL_OPT_VIRTUAL_ANCESTOR;
356
348 - if (flag & LL_OPT_RENORMALIZE) {
357 + if (!opts) {
358 + struct ll_merge_options default_opts = {0};
359 + return ll_merge(result_buf, path, ancestor, ancestor_label,
360 + ours, our_label, theirs, their_label,
361 + &default_opts);
362 + }
363 +
364 + if (opts->renormalize) {
365 normalize_file(ancestor, path);
366 normalize_file(ours, path);
367 normalize_file(theirs, path);
@@ -359,11 +375,11 @@ int ll_merge(mmbuffer_t *result_buf,
375 }
376 }
377 driver = find_ll_merge_driver(ll_driver_name);
362 - if (virtual_ancestor && driver->recursive)
378 + if (opts->virtual_ancestor && driver->recursive)
379 driver = find_ll_merge_driver(driver->recursive);
380 return driver->fn(driver, result_buf, path, ancestor, ancestor_label,
381 ours, our_label, theirs, their_label,
366 - flag, marker_size);
382 + opts, marker_size);
383 }
384
385 int ll_merge_marker_size(const char *path)
ll-merge.h
+6 -15
@@ -5,27 +5,18 @@
5 #ifndef LL_MERGE_H
6 #define LL_MERGE_H
7
8 -#define LL_OPT_VIRTUAL_ANCESTOR (1 << 0)
9 -#define LL_OPT_FAVOR_MASK ((1 << 1) | (1 << 2))
10 -#define LL_OPT_FAVOR_SHIFT 1
11 -#define LL_OPT_RENORMALIZE (1 << 3)
12 -
13 -static inline int ll_opt_favor(int flag)
14 -{
15 - return (flag & LL_OPT_FAVOR_MASK) >> LL_OPT_FAVOR_SHIFT;
16 -}
17 -
18 -static inline int create_ll_flag(int favor)
19 -{
20 - return ((favor << LL_OPT_FAVOR_SHIFT) & LL_OPT_FAVOR_MASK);
21 -}
8 +struct ll_merge_options {
9 + unsigned virtual_ancestor : 1;
10 + unsigned variant : 2; /* favor ours, favor theirs, or union merge */
11 + unsigned renormalize : 1;
12 +};
13
14 int ll_merge(mmbuffer_t *result_buf,
15 const char *path,
16 mmfile_t *ancestor, const char *ancestor_label,
17 mmfile_t *ours, const char *our_label,
18 mmfile_t *theirs, const char *their_label,
28 - int flag);
19 + const struct ll_merge_options *opts);
20
21 int ll_merge_marker_size(const char *path);
22
merge-file.c
+1 -1
@@ -37,7 +37,7 @@ static void *three_way_filemerge(const char *path, mmfile_t *base, mmfile_t *our
37 * common ancestor.
38 */
39 merge_status = ll_merge(&res, path, base, NULL,
40 - our, ".our", their, ".their", 0);
40 + our, ".our", their, ".their", NULL);
41 if (merge_status < 0)
42 return NULL;
43
merge-recursive.c
+11 -11
@@ -608,22 +608,25 @@ static int merge_3way(struct merge_options *o,
608 const char *branch2)
609 {
610 mmfile_t orig, src1, src2;
611 + struct ll_merge_options ll_opts = {0};
612 char *base_name, *name1, *name2;
613 int merge_status;
613 - int favor;
614
615 - if (o->call_depth)
616 - favor = 0;
617 - else {
615 + ll_opts.renormalize = o->renormalize;
616 +
617 + if (o->call_depth) {
618 + ll_opts.virtual_ancestor = 1;
619 + ll_opts.variant = 0;
620 + } else {
621 switch (o->recursive_variant) {
622 case MERGE_RECURSIVE_OURS:
620 - favor = XDL_MERGE_FAVOR_OURS;
623 + ll_opts.variant = XDL_MERGE_FAVOR_OURS;
624 break;
625 case MERGE_RECURSIVE_THEIRS:
623 - favor = XDL_MERGE_FAVOR_THEIRS;
626 + ll_opts.variant = XDL_MERGE_FAVOR_THEIRS;
627 break;
628 default:
626 - favor = 0;
629 + ll_opts.variant = 0;
630 break;
631 }
632 }
@@ -646,10 +649,7 @@ static int merge_3way(struct merge_options *o,
649 read_mmblob(&src2, b->sha1);
650
651 merge_status = ll_merge(result_buf, a->path, &orig, base_name,
649 - &src1, name1, &src2, name2,
650 - ((o->call_depth ? LL_OPT_VIRTUAL_ANCESTOR : 0) |
651 - (o->renormalize ? LL_OPT_RENORMALIZE : 0) |
652 - create_ll_flag(favor)));
652 + &src1, name1, &src2, name2, &ll_opts);
653
654 free(name1);
655 free(name2);
rerere.c
+1 -1
@@ -325,7 +325,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
325 */
326 ll_merge(&result, path, &mmfile[0], NULL,
327 &mmfile[1], "ours",
328 - &mmfile[2], "theirs", 0);
328 + &mmfile[2], "theirs", NULL);
329 for (i = 0; i < 3; i++)
330 free(mmfile[i].ptr);
331