17
17
#include "cache.h"
18
18
#include "merge-ort.h"
19
19
20
+ #include "alloc.h"
20
21
#include "blob.h"
21
22
#include "cache-tree.h"
23
+ #include "commit.h"
22
24
#include "commit-reach.h"
23
25
#include "diff.h"
24
26
#include "diffcore.h"
@@ -251,10 +253,11 @@ static void free_strmap_strings(struct strmap *map)
251
253
}
252
254
}
253
255
254
- static void clear_internal_opts (struct merge_options_internal * opti ,
255
- int reinitialize )
256
+ static void clear_or_reinit_internal_opts (struct merge_options_internal * opti ,
257
+ int reinitialize )
256
258
{
257
- assert (!reinitialize );
259
+ void (* strmap_func )(struct strmap * , int ) =
260
+ reinitialize ? strmap_partial_clear : strmap_clear ;
258
261
259
262
/*
260
263
* We marked opti->paths with strdup_strings = 0, so that we
@@ -264,14 +267,14 @@ static void clear_internal_opts(struct merge_options_internal *opti,
264
267
* to deallocate them.
265
268
*/
266
269
free_strmap_strings (& opti -> paths );
267
- strmap_clear (& opti -> paths , 1 );
270
+ strmap_func (& opti -> paths , 1 );
268
271
269
272
/*
270
273
* All keys and values in opti->conflicted are a subset of those in
271
274
* opti->paths. We don't want to deallocate anything twice, so we
272
275
* don't free the keys and we pass 0 for free_values.
273
276
*/
274
- strmap_clear (& opti -> conflicted , 0 );
277
+ strmap_func (& opti -> conflicted , 0 );
275
278
276
279
/*
277
280
* opti->paths_to_free is similar to opti->paths; we created it with
@@ -1342,12 +1345,29 @@ void merge_finalize(struct merge_options *opt,
1342
1345
1343
1346
assert (opt -> priv == NULL );
1344
1347
1345
- clear_internal_opts (opti , 0 );
1348
+ clear_or_reinit_internal_opts (opti , 0 );
1346
1349
FREE_AND_NULL (opti );
1347
1350
}
1348
1351
1349
1352
/*** Function Grouping: helper functions for merge_incore_*() ***/
1350
1353
1354
+ static inline void set_commit_tree (struct commit * c , struct tree * t )
1355
+ {
1356
+ c -> maybe_tree = t ;
1357
+ }
1358
+
1359
+ static struct commit * make_virtual_commit (struct repository * repo ,
1360
+ struct tree * tree ,
1361
+ const char * comment )
1362
+ {
1363
+ struct commit * commit = alloc_commit_node (repo );
1364
+
1365
+ set_merge_remote_desc (commit , comment , (struct object * )commit );
1366
+ set_commit_tree (commit , tree );
1367
+ commit -> object .parsed = 1 ;
1368
+ return commit ;
1369
+ }
1370
+
1351
1371
static void merge_start (struct merge_options * opt , struct merge_result * result )
1352
1372
{
1353
1373
/* Sanity checks on opt */
@@ -1445,6 +1465,89 @@ static void merge_ort_nonrecursive_internal(struct merge_options *opt,
1445
1465
}
1446
1466
}
1447
1467
1468
+ /*
1469
+ * Originally from merge_recursive_internal(); somewhat adapted, though.
1470
+ */
1471
+ static void merge_ort_internal (struct merge_options * opt ,
1472
+ struct commit_list * merge_bases ,
1473
+ struct commit * h1 ,
1474
+ struct commit * h2 ,
1475
+ struct merge_result * result )
1476
+ {
1477
+ struct commit_list * iter ;
1478
+ struct commit * merged_merge_bases ;
1479
+ const char * ancestor_name ;
1480
+ struct strbuf merge_base_abbrev = STRBUF_INIT ;
1481
+
1482
+ if (!merge_bases ) {
1483
+ merge_bases = get_merge_bases (h1 , h2 );
1484
+ /* See merge-ort.h:merge_incore_recursive() declaration NOTE */
1485
+ merge_bases = reverse_commit_list (merge_bases );
1486
+ }
1487
+
1488
+ merged_merge_bases = pop_commit (& merge_bases );
1489
+ if (merged_merge_bases == NULL ) {
1490
+ /* if there is no common ancestor, use an empty tree */
1491
+ struct tree * tree ;
1492
+
1493
+ tree = lookup_tree (opt -> repo , opt -> repo -> hash_algo -> empty_tree );
1494
+ merged_merge_bases = make_virtual_commit (opt -> repo , tree ,
1495
+ "ancestor" );
1496
+ ancestor_name = "empty tree" ;
1497
+ } else if (merge_bases ) {
1498
+ ancestor_name = "merged common ancestors" ;
1499
+ } else {
1500
+ strbuf_add_unique_abbrev (& merge_base_abbrev ,
1501
+ & merged_merge_bases -> object .oid ,
1502
+ DEFAULT_ABBREV );
1503
+ ancestor_name = merge_base_abbrev .buf ;
1504
+ }
1505
+
1506
+ for (iter = merge_bases ; iter ; iter = iter -> next ) {
1507
+ const char * saved_b1 , * saved_b2 ;
1508
+ struct commit * prev = merged_merge_bases ;
1509
+
1510
+ opt -> priv -> call_depth ++ ;
1511
+ /*
1512
+ * When the merge fails, the result contains files
1513
+ * with conflict markers. The cleanness flag is
1514
+ * ignored (unless indicating an error), it was never
1515
+ * actually used, as result of merge_trees has always
1516
+ * overwritten it: the committed "conflicts" were
1517
+ * already resolved.
1518
+ */
1519
+ saved_b1 = opt -> branch1 ;
1520
+ saved_b2 = opt -> branch2 ;
1521
+ opt -> branch1 = "Temporary merge branch 1" ;
1522
+ opt -> branch2 = "Temporary merge branch 2" ;
1523
+ merge_ort_internal (opt , NULL , prev , iter -> item , result );
1524
+ if (result -> clean < 0 )
1525
+ return ;
1526
+ opt -> branch1 = saved_b1 ;
1527
+ opt -> branch2 = saved_b2 ;
1528
+ opt -> priv -> call_depth -- ;
1529
+
1530
+ merged_merge_bases = make_virtual_commit (opt -> repo ,
1531
+ result -> tree ,
1532
+ "merged tree" );
1533
+ commit_list_insert (prev , & merged_merge_bases -> parents );
1534
+ commit_list_insert (iter -> item ,
1535
+ & merged_merge_bases -> parents -> next );
1536
+
1537
+ clear_or_reinit_internal_opts (opt -> priv , 1 );
1538
+ }
1539
+
1540
+ opt -> ancestor = ancestor_name ;
1541
+ merge_ort_nonrecursive_internal (opt ,
1542
+ repo_get_commit_tree (opt -> repo ,
1543
+ merged_merge_bases ),
1544
+ repo_get_commit_tree (opt -> repo , h1 ),
1545
+ repo_get_commit_tree (opt -> repo , h2 ),
1546
+ result );
1547
+ strbuf_release (& merge_base_abbrev );
1548
+ opt -> ancestor = NULL ; /* avoid accidental re-use of opt->ancestor */
1549
+ }
1550
+
1448
1551
void merge_incore_nonrecursive (struct merge_options * opt ,
1449
1552
struct tree * merge_base ,
1450
1553
struct tree * side1 ,
@@ -1462,5 +1565,9 @@ void merge_incore_recursive(struct merge_options *opt,
1462
1565
struct commit * side2 ,
1463
1566
struct merge_result * result )
1464
1567
{
1465
- die ("Not yet implemented" );
1568
+ /* We set the ancestor label based on the merge_bases */
1569
+ assert (opt -> ancestor == NULL );
1570
+
1571
+ merge_start (opt , result );
1572
+ merge_ort_internal (opt , merge_bases , side1 , side2 , result );
1466
1573
}
0 commit comments