merge-recursive: Consolidate process_entry() and process_df_entry()
The whole point of adding process_df_entry() was to ensure that files of D/F conflicts were processed after paths under the corresponding directory. However, given that the entries are in sorted order, all we need to do is iterate through them in reverse order to achieve the same effect. That lets us remove some duplicated code, and lets us keep track of one less thing as we read the code ("do we need to make sure this is processed before process_df_entry() or do we need to defer it until then?"). Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Aug 11, 2011 at 23:20 UTC
edd2faf52eda344eca2c01bc0b1d9f7f2f002a42
1 file changed
+57
-131
merge-recursive.c
+57
-131
@@ -116,7 +116,6 @@ static inline void setup_rename_df_conflict_info(enum rename_type rename_type,
116
ci->dst_entry2 = dst_entry2;
117
ci->pair2 = pair2;
118
dst_entry2->rename_df_conflict_info = ci;
119
- dst_entry2->processed = 0;
119
}
120
}
121
@@ -365,20 +364,17 @@ static void record_df_conflict_files(struct merge_options *o,
364
struct string_list *entries)
365
{
366
/* If there is a D/F conflict and the file for such a conflict
368
- * currently exist in the working copy, we want to allow it to
369
- * be removed to make room for the corresponding directory if
370
- * needed. The files underneath the directories of such D/F
371
- * conflicts will be handled in process_entry(), while the
372
- * files of such D/F conflicts will be processed later in
373
- * process_df_entry(). If the corresponding directory ends up
374
- * being removed by the merge, then no additional work needs
375
- * to be done by process_df_entry() for the conflicting file.
376
- * If the directory needs to be written to the working copy,
377
- * then the conflicting file will simply be removed (e.g. in
378
- * make_room_for_path). If the directory is written to the
379
- * working copy but the file also has a conflict that needs to
380
- * be resolved, then process_df_entry() will reinstate the
381
- * file with a new unique name.
367
+ * currently exist in the working copy, we want to allow it to be
368
+ * removed to make room for the corresponding directory if needed.
369
+ * The files underneath the directories of such D/F conflicts will
370
+ * be processed before the corresponding file involved in the D/F
371
+ * conflict. If the D/F directory ends up being removed by the
372
+ * merge, then we won't have to touch the D/F file. If the D/F
373
+ * directory needs to be written to the working copy, then the D/F
374
+ * file will simply be removed (in make_room_for_path()) to make
375
+ * room for the necessary paths. Note that if both the directory
376
+ * and the file need to be present, then the D/F file will be
377
+ * reinstated with a new unique name at the time it is processed.
378
*/
379
const char *last_file = NULL;
380
int last_len = 0;
@@ -1323,17 +1319,17 @@ static void handle_delete_modify(struct merge_options *o,
1319
"and modified in %s. Version %s of %s left in tree%s%s.",
1320
path, o->branch1,
1321
o->branch2, o->branch2, path,
1326
- path == new_path ? "" : " at ",
1327
- path == new_path ? "" : new_path);
1328
- update_file(o, 0, b_sha, b_mode, new_path);
1322
+ NULL == new_path ? "" : " at ",
1323
+ NULL == new_path ? "" : new_path);
1324
+ update_file(o, 0, b_sha, b_mode, new_path ? new_path : path);
1325
} else {
1326
output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
1327
"and modified in %s. Version %s of %s left in tree%s%s.",
1328
path, o->branch2,
1329
o->branch1, o->branch1, path,
1334
- path == new_path ? "" : " at ",
1335
- path == new_path ? "" : new_path);
1336
- update_file(o, 0, a_sha, a_mode, new_path);
1330
+ NULL == new_path ? "" : " at ",
1331
+ NULL == new_path ? "" : new_path);
1332
+ update_file(o, 0, a_sha, a_mode, new_path ? new_path : path);
1333
}
1334
}
1335
@@ -1431,93 +1427,6 @@ static int process_entry(struct merge_options *o,
1427
unsigned char *a_sha = stage_sha(entry->stages[2].sha, a_mode);
1428
unsigned char *b_sha = stage_sha(entry->stages[3].sha, b_mode);
1429
1434
- if (entry->rename_df_conflict_info)
1435
- return 1; /* Such cases are handled elsewhere. */
1436
-
1437
- entry->processed = 1;
1438
- if (o_sha && (!a_sha || !b_sha)) {
1439
- /* Case A: Deleted in one */
1440
- if ((!a_sha && !b_sha) ||
1441
- (!b_sha && blob_unchanged(o_sha, a_sha, normalize, path)) ||
1442
- (!a_sha && blob_unchanged(o_sha, b_sha, normalize, path))) {
1443
- /* Deleted in both or deleted in one and
1444
- * unchanged in the other */
1445
- if (a_sha)
1446
- output(o, 2, "Removing %s", path);
1447
- /* do not touch working file if it did not exist */
1448
- remove_file(o, 1, path, !a_sha);
1449
- } else if (dir_in_way(path, 0 /*check_wc*/)) {
1450
- entry->processed = 0;
1451
- return 1; /* Assume clean until processed */
1452
- } else {
1453
- /* Deleted in one and changed in the other */
1454
- clean_merge = 0;
1455
- handle_delete_modify(o, path, path,
1456
- a_sha, a_mode, b_sha, b_mode);
1457
- }
1458
-
1459
- } else if ((!o_sha && a_sha && !b_sha) ||
1460
- (!o_sha && !a_sha && b_sha)) {
1461
- /* Case B: Added in one. */
1462
- unsigned mode;
1463
- const unsigned char *sha;
1464
-
1465
- if (a_sha) {
1466
- mode = a_mode;
1467
- sha = a_sha;
1468
- } else {
1469
- mode = b_mode;
1470
- sha = b_sha;
1471
- }
1472
- if (dir_in_way(path, 0 /*check_wc*/)) {
1473
- /* Handle D->F conflicts after all subfiles */
1474
- entry->processed = 0;
1475
- return 1; /* Assume clean until processed */
1476
- } else {
1477
- output(o, 2, "Adding %s", path);
1478
- update_file(o, 1, sha, mode, path);
1479
- }
1480
- } else if (a_sha && b_sha) {
1481
- /* Case C: Added in both (check for same permissions) and */
1482
- /* case D: Modified in both, but differently. */
1483
- clean_merge = merge_content(o, entry->involved_in_rename, path,
1484
- o_sha, o_mode, a_sha, a_mode, b_sha, b_mode,
1485
- NULL);
1486
- } else if (!o_sha && !a_sha && !b_sha) {
1487
- /*
1488
- * this entry was deleted altogether. a_mode == 0 means
1489
- * we had that path and want to actively remove it.
1490
- */
1491
- remove_file(o, 1, path, !a_mode);
1492
- } else
1493
- die("Fatal merge failure, shouldn't happen.");
1494
-
1495
- return clean_merge;
1496
-}
1497
-
1498
-/*
1499
- * Per entry merge function for D/F (and/or rename) conflicts. In the
1500
- * cases we can cleanly resolve D/F conflicts, process_entry() can
1501
- * clean out all the files below the directory for us. All D/F
1502
- * conflict cases must be handled here at the end to make sure any
1503
- * directories that can be cleaned out, are.
1504
- *
1505
- * Some rename conflicts may also be handled here that don't necessarily
1506
- * involve D/F conflicts, since the code to handle them is generic enough
1507
- * to handle those rename conflicts with or without D/F conflicts also
1508
- * being involved.
1509
- */
1510
-static int process_df_entry(struct merge_options *o,
1511
- const char *path, struct stage_data *entry)
1512
-{
1513
- int clean_merge = 1;
1514
- unsigned o_mode = entry->stages[1].mode;
1515
- unsigned a_mode = entry->stages[2].mode;
1516
- unsigned b_mode = entry->stages[3].mode;
1517
- unsigned char *o_sha = stage_sha(entry->stages[1].sha, o_mode);
1518
- unsigned char *a_sha = stage_sha(entry->stages[2].sha, a_mode);
1519
- unsigned char *b_sha = stage_sha(entry->stages[3].sha, b_mode);
1520
-
1430
entry->processed = 1;
1431
if (entry->rename_df_conflict_info) {
1432
struct rename_df_conflict_info *conflict_info = entry->rename_df_conflict_info;
@@ -1552,24 +1461,38 @@ static int process_df_entry(struct merge_options *o,
1461
conflict_info->branch1,
1462
conflict_info->pair2,
1463
conflict_info->branch2);
1555
- conflict_info->dst_entry2->processed = 1;
1464
break;
1465
default:
1466
entry->processed = 0;
1467
break;
1468
}
1469
} else if (o_sha && (!a_sha || !b_sha)) {
1562
- /* Modify/delete; deleted side may have put a directory in the way */
1563
- char *renamed = NULL;
1564
- if (dir_in_way(path, !o->call_depth)) {
1565
- renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
1470
+ /* Case A: Deleted in one */
1471
+ if ((!a_sha && !b_sha) ||
1472
+ (!b_sha && blob_unchanged(o_sha, a_sha, normalize, path)) ||
1473
+ (!a_sha && blob_unchanged(o_sha, b_sha, normalize, path))) {
1474
+ /* Deleted in both or deleted in one and
1475
+ * unchanged in the other */
1476
+ if (a_sha)
1477
+ output(o, 2, "Removing %s", path);
1478
+ /* do not touch working file if it did not exist */
1479
+ remove_file(o, 1, path, !a_sha);
1480
+ } else {
1481
+ /* Modify/delete; deleted side may have put a directory in the way */
1482
+ char *renamed = NULL;
1483
+ clean_merge = 0;
1484
+ if (dir_in_way(path, !o->call_depth)) {
1485
+ renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
1486
+ }
1487
+ handle_delete_modify(o, path, renamed,
1488
+ a_sha, a_mode, b_sha, b_mode);
1489
+ free(renamed);
1490
}
1567
- clean_merge = 0;
1568
- handle_delete_modify(o, path, renamed ? renamed : path,
1569
- a_sha, a_mode, b_sha, b_mode);
1570
- free(renamed);
1571
- } else if (!o_sha && !!a_sha != !!b_sha) {
1572
- /* directory -> (directory, file) or <nothing> -> (directory, file) */
1491
+ } else if ((!o_sha && a_sha && !b_sha) ||
1492
+ (!o_sha && !a_sha && b_sha)) {
1493
+ /* Case B: Added in one. */
1494
+ /* [nothing|directory] -> ([nothing|directory], file) */
1495
+
1496
const char *add_branch;
1497
const char *other_branch;
1498
unsigned mode;
@@ -1605,10 +1528,20 @@ static int process_df_entry(struct merge_options *o,
1528
output(o, 2, "Adding %s", path);
1529
update_file(o, 1, sha, mode, path);
1530
}
1608
- } else {
1609
- entry->processed = 0;
1610
- return 1; /* not handled; assume clean until processed */
1611
- }
1531
+ } else if (a_sha && b_sha) {
1532
+ /* Case C: Added in both (check for same permissions) and */
1533
+ /* case D: Modified in both, but differently. */
1534
+ clean_merge = merge_content(o, entry->involved_in_rename, path,
1535
+ o_sha, o_mode, a_sha, a_mode, b_sha, b_mode,
1536
+ NULL);
1537
+ } else if (!o_sha && !a_sha && !b_sha) {
1538
+ /*
1539
+ * this entry was deleted altogether. a_mode == 0 means
1540
+ * we had that path and want to actively remove it.
1541
+ */
1542
+ remove_file(o, 1, path, !a_mode);
1543
+ } else
1544
+ die("Fatal merge failure, shouldn't happen.");
1545
1546
return clean_merge;
1547
}
@@ -1656,20 +1589,13 @@ int merge_trees(struct merge_options *o,
1589
re_head = get_renames(o, head, common, head, merge, entries);
1590
re_merge = get_renames(o, merge, common, head, merge, entries);
1591
clean = process_renames(o, re_head, re_merge);
1659
- for (i = 0; i < entries->nr; i++) {
1592
+ for (i = entries->nr-1; 0 <= i; i--) {
1593
const char *path = entries->items[i].string;
1594
struct stage_data *e = entries->items[i].util;
1595
if (!e->processed
1596
&& !process_entry(o, path, e))
1597
clean = 0;
1598
}
1666
- for (i = 0; i < entries->nr; i++) {
1667
- const char *path = entries->items[i].string;
1668
- struct stage_data *e = entries->items[i].util;
1669
- if (!e->processed
1670
- && !process_df_entry(o, path, e))
1671
- clean = 0;
1672
- }
1599
for (i = 0; i < entries->nr; i++) {
1600
struct stage_data *e = entries->items[i].util;
1601
if (!e->processed)