merge-ort: implement a very basic collect_merge_info()
[git] / merge-ort.c
1 /*
2  * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short.  Meant
3  * as a drop-in replacement for the "recursive" merge strategy, allowing one
4  * to replace
5  *
6  *   git merge [-s recursive]
7  *
8  * with
9  *
10  *   git merge -s ort
11  *
12  * Note: git's parser allows the space between '-s' and its argument to be
13  * missing.  (Should I have backronymed "ham", "alsa", "kip", "nap, "alvo",
14  * "cale", "peedy", or "ins" instead of "ort"?)
15  */
16
17 #include "cache.h"
18 #include "merge-ort.h"
19
20 #include "diff.h"
21 #include "diffcore.h"
22 #include "strmap.h"
23 #include "tree.h"
24 #include "xdiff-interface.h"
25
26 /*
27  * We have many arrays of size 3.  Whenever we have such an array, the
28  * indices refer to one of the sides of the three-way merge.  This is so
29  * pervasive that the constants 0, 1, and 2 are used in many places in the
30  * code (especially in arithmetic operations to find the other side's index
31  * or to compute a relevant mask), but sometimes these enum names are used
32  * to aid code clarity.
33  *
34  * See also 'filemask' and 'dirmask' in struct conflict_info; the "ith side"
35  * referred to there is one of these three sides.
36  */
37 enum merge_side {
38         MERGE_BASE = 0,
39         MERGE_SIDE1 = 1,
40         MERGE_SIDE2 = 2
41 };
42
43 struct merge_options_internal {
44         /*
45          * paths: primary data structure in all of merge ort.
46          *
47          * The keys of paths:
48          *   * are full relative paths from the toplevel of the repository
49          *     (e.g. "drivers/firmware/raspberrypi.c").
50          *   * store all relevant paths in the repo, both directories and
51          *     files (e.g. drivers, drivers/firmware would also be included)
52          *   * these keys serve to intern all the path strings, which allows
53          *     us to do pointer comparison on directory names instead of
54          *     strcmp; we just have to be careful to use the interned strings.
55          *
56          * The values of paths:
57          *   * either a pointer to a merged_info, or a conflict_info struct
58          *   * merged_info contains all relevant information for a
59          *     non-conflicted entry.
60          *   * conflict_info contains a merged_info, plus any additional
61          *     information about a conflict such as the higher orders stages
62          *     involved and the names of the paths those came from (handy
63          *     once renames get involved).
64          *   * a path may start "conflicted" (i.e. point to a conflict_info)
65          *     and then a later step (e.g. three-way content merge) determines
66          *     it can be cleanly merged, at which point it'll be marked clean
67          *     and the algorithm will ignore any data outside the contained
68          *     merged_info for that entry
69          *   * If an entry remains conflicted, the merged_info portion of a
70          *     conflict_info will later be filled with whatever version of
71          *     the file should be placed in the working directory (e.g. an
72          *     as-merged-as-possible variation that contains conflict markers).
73          */
74         struct strmap paths;
75
76         /*
77          * conflicted: a subset of keys->values from "paths"
78          *
79          * conflicted is basically an optimization between process_entries()
80          * and record_conflicted_index_entries(); the latter could loop over
81          * ALL the entries in paths AGAIN and look for the ones that are
82          * still conflicted, but since process_entries() has to loop over
83          * all of them, it saves the ones it couldn't resolve in this strmap
84          * so that record_conflicted_index_entries() can iterate just the
85          * relevant entries.
86          */
87         struct strmap conflicted;
88
89         /*
90          * current_dir_name: temporary var used in collect_merge_info_callback()
91          *
92          * Used to set merged_info.directory_name; see documentation for that
93          * variable and the requirements placed on that field.
94          */
95         const char *current_dir_name;
96
97         /* call_depth: recursion level counter for merging merge bases */
98         int call_depth;
99 };
100
101 struct version_info {
102         struct object_id oid;
103         unsigned short mode;
104 };
105
106 struct merged_info {
107         /* if is_null, ignore result.  otherwise result has oid & mode */
108         struct version_info result;
109         unsigned is_null:1;
110
111         /*
112          * clean: whether the path in question is cleanly merged.
113          *
114          * see conflict_info.merged for more details.
115          */
116         unsigned clean:1;
117
118         /*
119          * basename_offset: offset of basename of path.
120          *
121          * perf optimization to avoid recomputing offset of final '/'
122          * character in pathname (0 if no '/' in pathname).
123          */
124         size_t basename_offset;
125
126          /*
127           * directory_name: containing directory name.
128           *
129           * Note that we assume directory_name is constructed such that
130           *    strcmp(dir1_name, dir2_name) == 0 iff dir1_name == dir2_name,
131           * i.e. string equality is equivalent to pointer equality.  For this
132           * to hold, we have to be careful setting directory_name.
133           */
134         const char *directory_name;
135 };
136
137 struct conflict_info {
138         /*
139          * merged: the version of the path that will be written to working tree
140          *
141          * WARNING: It is critical to check merged.clean and ensure it is 0
142          * before reading any conflict_info fields outside of merged.
143          * Allocated merge_info structs will always have clean set to 1.
144          * Allocated conflict_info structs will have merged.clean set to 0
145          * initially.  The merged.clean field is how we know if it is safe
146          * to access other parts of conflict_info besides merged; if a
147          * conflict_info's merged.clean is changed to 1, the rest of the
148          * algorithm is not allowed to look at anything outside of the
149          * merged member anymore.
150          */
151         struct merged_info merged;
152
153         /* oids & modes from each of the three trees for this path */
154         struct version_info stages[3];
155
156         /* pathnames for each stage; may differ due to rename detection */
157         const char *pathnames[3];
158
159         /* Whether this path is/was involved in a directory/file conflict */
160         unsigned df_conflict:1;
161
162         /*
163          * For filemask and dirmask, the ith bit corresponds to whether the
164          * ith entry is a file (filemask) or a directory (dirmask).  Thus,
165          * filemask & dirmask is always zero, and filemask | dirmask is at
166          * most 7 but can be less when a path does not appear as either a
167          * file or a directory on at least one side of history.
168          *
169          * Note that these masks are related to enum merge_side, as the ith
170          * entry corresponds to side i.
171          *
172          * These values come from a traverse_trees() call; more info may be
173          * found looking at tree-walk.h's struct traverse_info,
174          * particularly the documentation above the "fn" member (note that
175          * filemask = mask & ~dirmask from that documentation).
176          */
177         unsigned filemask:3;
178         unsigned dirmask:3;
179
180         /*
181          * Optimization to track which stages match, to avoid the need to
182          * recompute it in multiple steps. Either 0 or at least 2 bits are
183          * set; if at least 2 bits are set, their corresponding stages match.
184          */
185         unsigned match_mask:3;
186 };
187
188 static int err(struct merge_options *opt, const char *err, ...)
189 {
190         va_list params;
191         struct strbuf sb = STRBUF_INIT;
192
193         strbuf_addstr(&sb, "error: ");
194         va_start(params, err);
195         strbuf_vaddf(&sb, err, params);
196         va_end(params);
197
198         error("%s", sb.buf);
199         strbuf_release(&sb);
200
201         return -1;
202 }
203
204 static int collect_merge_info_callback(int n,
205                                        unsigned long mask,
206                                        unsigned long dirmask,
207                                        struct name_entry *names,
208                                        struct traverse_info *info)
209 {
210         /*
211          * n is 3.  Always.
212          * common ancestor (mbase) has mask 1, and stored in index 0 of names
213          * head of side 1  (side1) has mask 2, and stored in index 1 of names
214          * head of side 2  (side2) has mask 4, and stored in index 2 of names
215          */
216         struct merge_options *opt = info->data;
217         struct merge_options_internal *opti = opt->priv;
218         struct conflict_info *ci;
219         struct name_entry *p;
220         size_t len;
221         char *fullpath;
222         unsigned filemask = mask & ~dirmask;
223         unsigned mbase_null = !(mask & 1);
224         unsigned side1_null = !(mask & 2);
225         unsigned side2_null = !(mask & 4);
226
227         /* n = 3 is a fundamental assumption. */
228         if (n != 3)
229                 BUG("Called collect_merge_info_callback wrong");
230
231         /*
232          * A bunch of sanity checks verifying that traverse_trees() calls
233          * us the way I expect.  Could just remove these at some point,
234          * though maybe they are helpful to future code readers.
235          */
236         assert(mbase_null == is_null_oid(&names[0].oid));
237         assert(side1_null == is_null_oid(&names[1].oid));
238         assert(side2_null == is_null_oid(&names[2].oid));
239         assert(!mbase_null || !side1_null || !side2_null);
240         assert(mask > 0 && mask < 8);
241
242         /*
243          * Get the name of the relevant filepath, which we'll pass to
244          * setup_path_info() for tracking.
245          */
246         p = names;
247         while (!p->mode)
248                 p++;
249         len = traverse_path_len(info, p->pathlen);
250
251         /* +1 in both of the following lines to include the NUL byte */
252         fullpath = xmalloc(len + 1);
253         make_traverse_path(fullpath, len + 1, info, p->path, p->pathlen);
254
255         /*
256          * TODO: record information about the path other than all zeros,
257          * so we can resolve later in process_entries.
258          */
259         ci = xcalloc(1, sizeof(struct conflict_info));
260         strmap_put(&opti->paths, fullpath, ci);
261
262         /* If dirmask, recurse into subdirectories */
263         if (dirmask) {
264                 struct traverse_info newinfo;
265                 struct tree_desc t[3];
266                 void *buf[3] = {NULL, NULL, NULL};
267                 const char *original_dir_name;
268                 int i, ret;
269
270                 ci->match_mask &= filemask;
271                 newinfo = *info;
272                 newinfo.prev = info;
273                 newinfo.name = p->path;
274                 newinfo.namelen = p->pathlen;
275                 newinfo.pathlen = st_add3(newinfo.pathlen, p->pathlen, 1);
276
277                 for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
278                         const struct object_id *oid = NULL;
279                         if (dirmask & 1)
280                                 oid = &names[i].oid;
281                         buf[i] = fill_tree_descriptor(opt->repo, t + i, oid);
282                         dirmask >>= 1;
283                 }
284
285                 original_dir_name = opti->current_dir_name;
286                 opti->current_dir_name = fullpath;
287                 ret = traverse_trees(NULL, 3, t, &newinfo);
288                 opti->current_dir_name = original_dir_name;
289
290                 for (i = MERGE_BASE; i <= MERGE_SIDE2; i++)
291                         free(buf[i]);
292
293                 if (ret < 0)
294                         return -1;
295         }
296
297         return mask;
298 }
299
300 static int collect_merge_info(struct merge_options *opt,
301                               struct tree *merge_base,
302                               struct tree *side1,
303                               struct tree *side2)
304 {
305         int ret;
306         struct tree_desc t[3];
307         struct traverse_info info;
308         const char *toplevel_dir_placeholder = "";
309
310         opt->priv->current_dir_name = toplevel_dir_placeholder;
311         setup_traverse_info(&info, toplevel_dir_placeholder);
312         info.fn = collect_merge_info_callback;
313         info.data = opt;
314         info.show_all_errors = 1;
315
316         parse_tree(merge_base);
317         parse_tree(side1);
318         parse_tree(side2);
319         init_tree_desc(t + 0, merge_base->buffer, merge_base->size);
320         init_tree_desc(t + 1, side1->buffer, side1->size);
321         init_tree_desc(t + 2, side2->buffer, side2->size);
322
323         ret = traverse_trees(NULL, 3, t, &info);
324
325         return ret;
326 }
327
328 static int detect_and_process_renames(struct merge_options *opt,
329                                       struct tree *merge_base,
330                                       struct tree *side1,
331                                       struct tree *side2)
332 {
333         int clean = 1;
334
335         /*
336          * Rename detection works by detecting file similarity.  Here we use
337          * a really easy-to-implement scheme: files are similar IFF they have
338          * the same filename.  Therefore, by this scheme, there are no renames.
339          *
340          * TODO: Actually implement a real rename detection scheme.
341          */
342         return clean;
343 }
344
345 static void process_entries(struct merge_options *opt,
346                             struct object_id *result_oid)
347 {
348         die("Not yet implemented.");
349 }
350
351 void merge_switch_to_result(struct merge_options *opt,
352                             struct tree *head,
353                             struct merge_result *result,
354                             int update_worktree_and_index,
355                             int display_update_msgs)
356 {
357         die("Not yet implemented");
358         merge_finalize(opt, result);
359 }
360
361 void merge_finalize(struct merge_options *opt,
362                     struct merge_result *result)
363 {
364         die("Not yet implemented");
365 }
366
367 static void merge_start(struct merge_options *opt, struct merge_result *result)
368 {
369         /* Sanity checks on opt */
370         assert(opt->repo);
371
372         assert(opt->branch1 && opt->branch2);
373
374         assert(opt->detect_directory_renames >= MERGE_DIRECTORY_RENAMES_NONE &&
375                opt->detect_directory_renames <= MERGE_DIRECTORY_RENAMES_TRUE);
376         assert(opt->rename_limit >= -1);
377         assert(opt->rename_score >= 0 && opt->rename_score <= MAX_SCORE);
378         assert(opt->show_rename_progress >= 0 && opt->show_rename_progress <= 1);
379
380         assert(opt->xdl_opts >= 0);
381         assert(opt->recursive_variant >= MERGE_VARIANT_NORMAL &&
382                opt->recursive_variant <= MERGE_VARIANT_THEIRS);
383
384         /*
385          * detect_renames, verbosity, buffer_output, and obuf are ignored
386          * fields that were used by "recursive" rather than "ort" -- but
387          * sanity check them anyway.
388          */
389         assert(opt->detect_renames >= -1 &&
390                opt->detect_renames <= DIFF_DETECT_COPY);
391         assert(opt->verbosity >= 0 && opt->verbosity <= 5);
392         assert(opt->buffer_output <= 2);
393         assert(opt->obuf.len == 0);
394
395         assert(opt->priv == NULL);
396
397         /* Default to histogram diff.  Actually, just hardcode it...for now. */
398         opt->xdl_opts = DIFF_WITH_ALG(opt, HISTOGRAM_DIFF);
399
400         /* Initialization of opt->priv, our internal merge data */
401         opt->priv = xcalloc(1, sizeof(*opt->priv));
402
403         /*
404          * Although we initialize opt->priv->paths with strdup_strings=0,
405          * that's just to avoid making yet another copy of an allocated
406          * string.  Putting the entry into paths means we are taking
407          * ownership, so we will later free it.
408          *
409          * In contrast, conflicted just has a subset of keys from paths, so
410          * we don't want to free those (it'd be a duplicate free).
411          */
412         strmap_init_with_options(&opt->priv->paths, NULL, 0);
413         strmap_init_with_options(&opt->priv->conflicted, NULL, 0);
414 }
415
416 /*
417  * Originally from merge_trees_internal(); heavily adapted, though.
418  */
419 static void merge_ort_nonrecursive_internal(struct merge_options *opt,
420                                             struct tree *merge_base,
421                                             struct tree *side1,
422                                             struct tree *side2,
423                                             struct merge_result *result)
424 {
425         struct object_id working_tree_oid;
426
427         if (collect_merge_info(opt, merge_base, side1, side2) != 0) {
428                 /*
429                  * TRANSLATORS: The %s arguments are: 1) tree hash of a merge
430                  * base, and 2-3) the trees for the two trees we're merging.
431                  */
432                 err(opt, _("collecting merge info failed for trees %s, %s, %s"),
433                     oid_to_hex(&merge_base->object.oid),
434                     oid_to_hex(&side1->object.oid),
435                     oid_to_hex(&side2->object.oid));
436                 result->clean = -1;
437                 return;
438         }
439
440         result->clean = detect_and_process_renames(opt, merge_base,
441                                                    side1, side2);
442         process_entries(opt, &working_tree_oid);
443
444         /* Set return values */
445         result->tree = parse_tree_indirect(&working_tree_oid);
446         /* existence of conflicted entries implies unclean */
447         result->clean &= strmap_empty(&opt->priv->conflicted);
448         if (!opt->priv->call_depth) {
449                 result->priv = opt->priv;
450                 opt->priv = NULL;
451         }
452 }
453
454 void merge_incore_nonrecursive(struct merge_options *opt,
455                                struct tree *merge_base,
456                                struct tree *side1,
457                                struct tree *side2,
458                                struct merge_result *result)
459 {
460         assert(opt->ancestor != NULL);
461         merge_start(opt, result);
462         merge_ort_nonrecursive_internal(opt, merge_base, side1, side2, result);
463 }
464
465 void merge_incore_recursive(struct merge_options *opt,
466                             struct commit_list *merge_bases,
467                             struct commit *side1,
468                             struct commit *side2,
469                             struct merge_result *result)
470 {
471         die("Not yet implemented");
472 }