merge-recursive: switch from (oid,mode) pairs to a diff_filespec
There was a significant inconsistency in the various parts of the API used in merge-recursive; many places used a pair of (oid, mode) to track file version/contents, while other parts used a diff_filespec (which have an oid and mode embedded in it). This inconsistency caused lots of places to need to pack and unpack data to call into other functions. This has been the subject of some past cleanups (see e.g. commit 0270a07ad0b2 ("merge-recursive: remove final remaining caller of merge_file_one()", 2018-09-19)), but let's just remove the underlying mess altogether by switching to use diff_filespec. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Apr 5, 2019 at 08:00 UTC
8daec1df03de7db13d5d551a8b54f32fc6021132
1 file changed
+215
-268
merge-recursive.c
+215
-268
@@ -201,10 +201,7 @@ enum rename_type {
201
* for these (temporary) data.
202
*/
203
struct stage_data {
204
- struct {
205
- unsigned short mode;
206
- struct object_id oid;
207
- } stages[4];
204
+ struct diff_filespec stages[4]; /* mostly for oid & mode; maybe path */
205
struct rename_conflict_info *rename_conflict_info;
206
unsigned processed:1;
207
};
@@ -269,7 +266,6 @@ static inline void setup_rename_conflict_info(enum rename_type rename_type,
266
267
ci->ren1->dst_entry->processed = 0;
268
ci->ren1->dst_entry->rename_conflict_info = ci;
272
-
269
if (ren2) {
270
ci->ren2->dst_entry->rename_conflict_info = ci;
271
}
@@ -326,14 +322,14 @@ static void output_commit_title(struct merge_options *opt, struct commit *commit
322
}
323
324
static int add_cacheinfo(struct merge_options *opt,
329
- unsigned int mode, const struct object_id *oid,
325
+ const struct diff_filespec *blob,
326
const char *path, int stage, int refresh, int options)
327
{
328
struct index_state *istate = opt->repo->index;
329
struct cache_entry *ce;
330
int ret;
331
336
- ce = make_cache_entry(istate, mode, oid ? oid : &null_oid, path, stage, 0);
332
+ ce = make_cache_entry(istate, blob->mode, &blob->oid, path, stage, 0);
333
if (!ce)
334
return err(opt, _("add_cacheinfo failed for path '%s'; merge aborting."), path);
335
@@ -464,15 +460,14 @@ static void get_files_dirs(struct merge_options *opt, struct tree *tree)
460
461
static int get_tree_entry_if_blob(const struct object_id *tree,
462
const char *path,
467
- struct object_id *hashy,
468
- unsigned short *mode_o)
463
+ struct diff_filespec *dfs)
464
{
465
int ret;
466
472
- ret = get_tree_entry(tree, path, hashy, mode_o);
473
- if (S_ISDIR(*mode_o)) {
474
- oidcpy(hashy, &null_oid);
475
- *mode_o = 0;
467
+ ret = get_tree_entry(tree, path, &dfs->oid, &dfs->mode);
468
+ if (S_ISDIR(dfs->mode)) {
469
+ oidcpy(&dfs->oid, &null_oid);
470
+ dfs->mode = 0;
471
}
472
return ret;
473
}
@@ -487,12 +482,9 @@ static struct stage_data *insert_stage_data(const char *path,
482
{
483
struct string_list_item *item;
484
struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
490
- get_tree_entry_if_blob(&o->object.oid, path,
491
- &e->stages[1].oid, &e->stages[1].mode);
492
- get_tree_entry_if_blob(&a->object.oid, path,
493
- &e->stages[2].oid, &e->stages[2].mode);
494
- get_tree_entry_if_blob(&b->object.oid, path,
495
- &e->stages[3].oid, &e->stages[3].mode);
485
+ get_tree_entry_if_blob(&o->object.oid, path, &e->stages[1]);
486
+ get_tree_entry_if_blob(&a->object.oid, path, &e->stages[2]);
487
+ get_tree_entry_if_blob(&b->object.oid, path, &e->stages[3]);
488
item = string_list_insert(entries, path);
489
item->util = e;
490
return e;
@@ -648,13 +640,13 @@ static int update_stages(struct merge_options *opt, const char *path,
640
if (remove_file_from_index(opt->repo->index, path))
641
return -1;
642
if (o)
651
- if (add_cacheinfo(opt, o->mode, &o->oid, path, 1, 0, options))
643
+ if (add_cacheinfo(opt, o, path, 1, 0, options))
644
return -1;
645
if (a)
654
- if (add_cacheinfo(opt, a->mode, &a->oid, path, 2, 0, options))
646
+ if (add_cacheinfo(opt, a, path, 2, 0, options))
647
return -1;
648
if (b)
657
- if (add_cacheinfo(opt, b->mode, &b->oid, path, 3, 0, options))
649
+ if (add_cacheinfo(opt, b, path, 3, 0, options))
650
return -1;
651
return 0;
652
}
@@ -767,7 +759,7 @@ static int dir_in_way(struct index_state *istate, const char *path,
759
* and its oid and mode match the specified values
760
*/
761
static int was_tracked_and_matches(struct merge_options *opt, const char *path,
770
- const struct object_id *oid, unsigned mode)
762
+ const struct diff_filespec *blob)
763
{
764
int pos = index_name_pos(&opt->orig_index, path, strlen(path));
765
struct cache_entry *ce;
@@ -778,7 +770,7 @@ static int was_tracked_and_matches(struct merge_options *opt, const char *path,
770
771
/* See if the file we were tracking before matches */
772
ce = opt->orig_index.cache[pos];
781
- return (oid_eq(&ce->oid, oid) && ce->ce_mode == mode);
773
+ return (oid_eq(&ce->oid, &blob->oid) && ce->ce_mode == blob->mode);
774
}
775
776
/*
@@ -903,8 +895,7 @@ static int make_room_for_path(struct merge_options *opt, const char *path)
895
}
896
897
static int update_file_flags(struct merge_options *opt,
906
- const struct object_id *oid,
907
- unsigned mode,
898
+ const struct diff_filespec *contents,
899
const char *path,
900
int update_cache,
901
int update_wd)
@@ -919,7 +910,7 @@ static int update_file_flags(struct merge_options *opt,
910
void *buf;
911
unsigned long size;
912
922
- if (S_ISGITLINK(mode)) {
913
+ if (S_ISGITLINK(contents->mode)) {
914
/*
915
* We may later decide to recursively descend into
916
* the submodule directory and update its index
@@ -929,14 +920,16 @@ static int update_file_flags(struct merge_options *opt,
920
goto update_index;
921
}
922
932
- buf = read_object_file(oid, &type, &size);
923
+ buf = read_object_file(&contents->oid, &type, &size);
924
if (!buf)
934
- return err(opt, _("cannot read object %s '%s'"), oid_to_hex(oid), path);
925
+ return err(opt, _("cannot read object %s '%s'"),
926
+ oid_to_hex(&contents->oid), path);
927
if (type != OBJ_BLOB) {
936
- ret = err(opt, _("blob expected for %s '%s'"), oid_to_hex(oid), path);
928
+ ret = err(opt, _("blob expected for %s '%s'"),
929
+ oid_to_hex(&contents->oid), path);
930
goto free_buf;
931
}
939
- if (S_ISREG(mode)) {
932
+ if (S_ISREG(contents->mode)) {
933
struct strbuf strbuf = STRBUF_INIT;
934
if (convert_to_working_tree(opt->repo->index, path, buf, size, &strbuf)) {
935
free(buf);
@@ -949,12 +942,11 @@ static int update_file_flags(struct merge_options *opt,
942
update_wd = 0;
943
goto free_buf;
944
}
952
- if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) {
945
+ if (S_ISREG(contents->mode) ||
946
+ (!has_symlinks && S_ISLNK(contents->mode))) {
947
int fd;
954
- if (mode & 0100)
955
- mode = 0777;
956
- else
957
- mode = 0666;
948
+ int mode = (contents->mode & 0100 ? 0777 : 0666);
949
+
950
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
951
if (fd < 0) {
952
ret = err(opt, _("failed to open '%s': %s"),
@@ -963,7 +955,7 @@ static int update_file_flags(struct merge_options *opt,
955
}
956
write_in_full(fd, buf, size);
957
close(fd);
966
- } else if (S_ISLNK(mode)) {
958
+ } else if (S_ISLNK(contents->mode)) {
959
char *lnk = xmemdupz(buf, size);
960
safe_create_leading_directories_const(path);
961
unlink(path);
@@ -974,13 +966,13 @@ static int update_file_flags(struct merge_options *opt,
966
} else
967
ret = err(opt,
968
_("do not know what to do with %06o %s '%s'"),
977
- mode, oid_to_hex(oid), path);
969
+ contents->mode, oid_to_hex(&contents->oid), path);
970
free_buf:
971
free(buf);
972
}
973
update_index:
974
if (!ret && update_cache)
983
- if (add_cacheinfo(opt, mode, oid, path, 0, update_wd,
975
+ if (add_cacheinfo(opt, contents, path, 0, update_wd,
976
ADD_CACHE_OK_TO_ADD))
977
return -1;
978
return ret;
@@ -988,18 +980,17 @@ update_index:
980
981
static int update_file(struct merge_options *opt,
982
int clean,
991
- const struct object_id *oid,
992
- unsigned mode,
983
+ const struct diff_filespec *contents,
984
const char *path)
985
{
995
- return update_file_flags(opt, oid, mode, path, opt->call_depth || clean, !opt->call_depth);
986
+ return update_file_flags(opt, contents, path,
987
+ opt->call_depth || clean, !opt->call_depth);
988
}
989
990
/* Low level file merging, update and removal */
991
992
struct merge_file_info {
1001
- struct object_id oid;
1002
- unsigned mode;
993
+ struct diff_filespec blob; /* mostly use oid & mode; sometimes path */
994
unsigned clean:1,
995
merge:1;
996
};
@@ -1039,6 +1030,7 @@ static int merge_3way(struct merge_options *opt,
1030
}
1031
}
1032
1033
+ assert(a->path && b->path);
1034
if (strcmp(a->path, b->path) ||
1035
(opt->ancestor != NULL && strcmp(a->path, o->path) != 0)) {
1036
base_name = opt->ancestor == NULL ? NULL :
@@ -1140,6 +1132,11 @@ static void print_commit(struct commit *commit)
1132
strbuf_release(&sb);
1133
}
1134
1135
+static int is_valid(const struct diff_filespec *dfs)
1136
+{
1137
+ return dfs->mode != 0 && !is_null_oid(&dfs->oid);
1138
+}
1139
+
1140
static int merge_submodule(struct merge_options *opt,
1141
struct object_id *result, const char *path,
1142
const struct object_id *base, const struct object_id *a,
@@ -1278,11 +1275,11 @@ static int merge_mode_and_contents(struct merge_options *opt,
1275
if ((S_IFMT & a->mode) != (S_IFMT & b->mode)) {
1276
result->clean = 0;
1277
if (S_ISREG(a->mode)) {
1281
- result->mode = a->mode;
1282
- oidcpy(&result->oid, &a->oid);
1278
+ result->blob.mode = a->mode;
1279
+ oidcpy(&result->blob.oid, &a->oid);
1280
} else {
1284
- result->mode = b->mode;
1285
- oidcpy(&result->oid, &b->oid);
1281
+ result->blob.mode = b->mode;
1282
+ oidcpy(&result->blob.oid, &b->oid);
1283
}
1284
} else {
1285
if (!oid_eq(&a->oid, &o->oid) && !oid_eq(&b->oid, &o->oid))
@@ -1292,9 +1289,9 @@ static int merge_mode_and_contents(struct merge_options *opt,
1289
* Merge modes
1290
*/
1291
if (a->mode == b->mode || a->mode == o->mode)
1295
- result->mode = b->mode;
1292
+ result->blob.mode = b->mode;
1293
else {
1297
- result->mode = a->mode;
1294
+ result->blob.mode = a->mode;
1295
if (b->mode != o->mode) {
1296
result->clean = 0;
1297
result->merge = 1;
@@ -1302,9 +1299,9 @@ static int merge_mode_and_contents(struct merge_options *opt,
1299
}
1300
1301
if (oid_eq(&a->oid, &b->oid) || oid_eq(&a->oid, &o->oid))
1305
- oidcpy(&result->oid, &b->oid);
1302
+ oidcpy(&result->blob.oid, &b->oid);
1303
else if (oid_eq(&b->oid, &o->oid))
1307
- oidcpy(&result->oid, &a->oid);
1304
+ oidcpy(&result->blob.oid, &a->oid);
1305
else if (S_ISREG(a->mode)) {
1306
mmbuffer_t result_buf;
1307
int ret = 0, merge_status;
@@ -1318,7 +1315,7 @@ static int merge_mode_and_contents(struct merge_options *opt,
1315
1316
if (!ret &&
1317
write_object_file(result_buf.ptr, result_buf.size,
1321
- blob_type, &result->oid))
1318
+ blob_type, &result->blob.oid))
1319
ret = err(opt, _("Unable to add %s to database"),
1320
a->path);
1321
@@ -1327,7 +1324,7 @@ static int merge_mode_and_contents(struct merge_options *opt,
1324
return ret;
1325
result->clean = (merge_status == 0);
1326
} else if (S_ISGITLINK(a->mode)) {
1330
- result->clean = merge_submodule(opt, &result->oid,
1327
+ result->clean = merge_submodule(opt, &result->blob.oid,
1328
o->path,
1329
&o->oid,
1330
&a->oid,
@@ -1335,15 +1332,15 @@ static int merge_mode_and_contents(struct merge_options *opt,
1332
} else if (S_ISLNK(a->mode)) {
1333
switch (opt->recursive_variant) {
1334
case MERGE_RECURSIVE_NORMAL:
1338
- oidcpy(&result->oid, &a->oid);
1335
+ oidcpy(&result->blob.oid, &a->oid);
1336
if (!oid_eq(&a->oid, &b->oid))
1337
result->clean = 0;
1338
break;
1339
case MERGE_RECURSIVE_OURS:
1343
- oidcpy(&result->oid, &a->oid);
1340
+ oidcpy(&result->blob.oid, &a->oid);
1341
break;
1342
case MERGE_RECURSIVE_THEIRS:
1346
- oidcpy(&result->oid, &b->oid);
1343
+ oidcpy(&result->blob.oid, &b->oid);
1344
break;
1345
}
1346
} else
@@ -1379,7 +1376,7 @@ static int handle_rename_via_dir(struct merge_options *opt,
1376
* index. Instead, write to dest->path for the index but
1377
* only at the higher appropriate stage.
1378
*/
1382
- if (update_file(opt, 0, &dest->oid, dest->mode, alt_path))
1379
+ if (update_file(opt, 0, dest, alt_path))
1380
return -1;
1381
free(alt_path);
1382
return update_stages(opt, dest->path, NULL,
@@ -1388,16 +1385,15 @@ static int handle_rename_via_dir(struct merge_options *opt,
1385
}
1386
1387
/* Update dest->path both in index and in worktree */
1391
- if (update_file(opt, 1, &dest->oid, dest->mode, dest->path))
1388
+ if (update_file(opt, 1, dest, dest->path))
1389
return -1;
1390
return 0;
1391
}
1392
1393
static int handle_change_delete(struct merge_options *opt,
1394
const char *path, const char *old_path,
1398
- const struct object_id *o_oid, int o_mode,
1399
- const struct object_id *changed_oid,
1400
- int changed_mode,
1395
+ const struct diff_filespec *o,
1396
+ const struct diff_filespec *changed,
1397
const char *change_branch,
1398
const char *delete_branch,
1399
const char *change, const char *change_past)
@@ -1419,7 +1415,7 @@ static int handle_change_delete(struct merge_options *opt,
1415
*/
1416
ret = remove_file_from_index(opt->repo->index, path);
1417
if (!ret)
1422
- ret = update_file(opt, 0, o_oid, o_mode, update_path);
1418
+ ret = update_file(opt, 0, o, update_path);
1419
} else {
1420
/*
1421
* Despite the four nearly duplicate messages and argument
@@ -1468,7 +1464,7 @@ static int handle_change_delete(struct merge_options *opt,
1464
* and update_wd=0, but that's a no-op.
1465
*/
1466
if (change_branch != opt->branch1 || alt_path)
1471
- ret = update_file(opt, 0, changed_oid, changed_mode, update_path);
1467
+ ret = update_file(opt, 0, changed, update_path);
1468
}
1469
free(alt_path);
1470
@@ -1488,8 +1484,7 @@ static int handle_rename_delete(struct merge_options *opt,
1484
if (handle_change_delete(opt,
1485
opt->call_depth ? orig->path : dest->path,
1486
opt->call_depth ? NULL : orig->path,
1491
- &orig->oid, orig->mode,
1492
- &dest->oid, dest->mode,
1487
+ orig, dest,
1488
rename_branch, delete_branch,
1489
_("rename"), _("renamed")))
1490
return -1;
@@ -1502,31 +1497,16 @@ static int handle_rename_delete(struct merge_options *opt,
1497
rename_branch == opt->branch1 ? NULL : dest);
1498
}
1499
1505
-static struct diff_filespec *filespec_from_entry(struct diff_filespec *target,
1506
- struct stage_data *entry,
1507
- int stage)
1508
-{
1509
- struct object_id *oid = &entry->stages[stage].oid;
1510
- unsigned mode = entry->stages[stage].mode;
1511
- if (mode == 0 || is_null_oid(oid))
1512
- return NULL;
1513
- oidcpy(&target->oid, oid);
1514
- target->mode = mode;
1515
- return target;
1516
-}
1517
-
1500
static int handle_file_collision(struct merge_options *opt,
1501
const char *collide_path,
1502
const char *prev_path1,
1503
const char *prev_path2,
1504
const char *branch1, const char *branch2,
1523
- const struct object_id *a_oid,
1524
- unsigned int a_mode,
1525
- const struct object_id *b_oid,
1526
- unsigned int b_mode)
1505
+ struct diff_filespec *a,
1506
+ struct diff_filespec *b)
1507
{
1508
struct merge_file_info mfi;
1529
- struct diff_filespec null, a, b;
1509
+ struct diff_filespec null;
1510
char *alt_path = NULL;
1511
const char *update_path = collide_path;
1512
@@ -1540,29 +1520,28 @@ static int handle_file_collision(struct merge_options *opt,
1520
return handle_file_collision(opt, collide_path,
1521
prev_path2, prev_path1,
1522
branch2, branch1,
1543
- b_oid, b_mode,
1544
- a_oid, a_mode);
1523
+ b, a);
1524
}
1525
1526
/*
1527
* In the recursive case, we just opt to undo renames
1528
*/
1529
if (opt->call_depth && (prev_path1 || prev_path2)) {
1551
- /* Put first file (a_oid, a_mode) in its original spot */
1530
+ /* Put first file (a->oid, a->mode) in its original spot */
1531
if (prev_path1) {
1553
- if (update_file(opt, 1, a_oid, a_mode, prev_path1))
1532
+ if (update_file(opt, 1, a, prev_path1))
1533
return -1;
1534
} else {
1556
- if (update_file(opt, 1, a_oid, a_mode, collide_path))
1535
+ if (update_file(opt, 1, a, collide_path))
1536
return -1;
1537
}
1538
1560
- /* Put second file (b_oid, b_mode) in its original spot */
1539
+ /* Put second file (b->oid, b->mode) in its original spot */
1540
if (prev_path2) {
1562
- if (update_file(opt, 1, b_oid, b_mode, prev_path2))
1541
+ if (update_file(opt, 1, b, prev_path2))
1542
return -1;
1543
} else {
1565
- if (update_file(opt, 1, b_oid, b_mode, collide_path))
1544
+ if (update_file(opt, 1, b, collide_path))
1545
return -1;
1546
}
1547
@@ -1616,26 +1595,18 @@ static int handle_file_collision(struct merge_options *opt,
1595
}
1596
1597
/* Store things in diff_filespecs for functions that need it */
1619
- memset(&a, 0, sizeof(struct diff_filespec));
1620
- memset(&b, 0, sizeof(struct diff_filespec));
1621
- null.path = a.path = b.path = (char *)collide_path;
1598
+ null.path = (char *)collide_path;
1599
oidcpy(&null.oid, &null_oid);
1600
null.mode = 0;
1624
- oidcpy(&a.oid, a_oid);
1625
- a.mode = a_mode;
1626
- a.oid_valid = 1;
1627
- oidcpy(&b.oid, b_oid);
1628
- b.mode = b_mode;
1629
- b.oid_valid = 1;
1630
-
1631
- if (merge_mode_and_contents(opt, &null, &a, &b, collide_path,
1601
+
1602
+ if (merge_mode_and_contents(opt, &null, a, b, collide_path,
1603
branch1, branch2, opt->call_depth * 2, &mfi))
1604
return -1;
1605
mfi.clean &= !alt_path;
1635
- if (update_file(opt, mfi.clean, &mfi.oid, mfi.mode, update_path))
1606
+ if (update_file(opt, mfi.clean, &mfi.blob, update_path))
1607
return -1;
1608
if (!mfi.clean && !opt->call_depth &&
1638
- update_stages(opt, collide_path, NULL, &a, &b))
1609
+ update_stages(opt, collide_path, NULL, a, b))
1610
return -1;
1611
free(alt_path);
1612
/*
@@ -1654,7 +1625,6 @@ static int handle_rename_add(struct merge_options *opt,
1625
/* a was renamed to c, and a separate c was added. */
1626
struct diff_filespec *a = ci->ren1->pair->one;
1627
struct diff_filespec *c = ci->ren1->pair->two;
1657
- struct diff_filespec tmp;
1628
char *path = c->path;
1629
char *prev_path_desc;
1630
struct merge_file_info mfi;
@@ -1669,23 +1639,21 @@ static int handle_rename_add(struct merge_options *opt,
1639
a->path, c->path, rename_branch,
1640
c->path, add_branch);
1641
1672
- filespec_from_entry(&tmp, ci->ren1->src_entry, other_stage);
1673
- tmp.path = a->path;
1674
-
1642
prev_path_desc = xstrfmt("version of %s from %s", path, a->path);
1676
- if (merge_mode_and_contents(opt, a, c, &tmp,
1643
+ if (merge_mode_and_contents(opt, a, c,
1644
+ &ci->ren1->src_entry->stages[other_stage],
1645
prev_path_desc,
1646
opt->branch1, opt->branch2,
1647
1 + opt->call_depth * 2, &mfi))
1648
return -1;
1649
free(prev_path_desc);
1650
1651
+ ci->ren1->dst_entry->stages[other_stage].path = mfi.blob.path = c->path;
1652
return handle_file_collision(opt,
1653
c->path, a->path, NULL,
1654
rename_branch, add_branch,
1686
- &mfi.oid, mfi.mode,
1687
- &ci->ren1->dst_entry->stages[other_stage].oid,
1688
- ci->ren1->dst_entry->stages[other_stage].mode);
1655
+ &mfi.blob,
1656
+ &ci->ren1->dst_entry->stages[other_stage]);
1657
}
1658
1659
static char *find_path_for_conflict(struct merge_options *opt,
@@ -1714,7 +1682,6 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
1682
{
1683
/* One file was renamed in both branches, but to different names. */
1684
struct merge_file_info mfi;
1717
- struct diff_filespec other;
1685
struct diff_filespec *add;
1686
struct diff_filespec *o = ci->ren1->pair->one;
1687
struct diff_filespec *a = ci->ren1->pair->two;
@@ -1743,7 +1710,7 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
1710
* pathname and then either rename the add-source file to that
1711
* unique path, or use that unique path instead of src here.
1712
*/
1746
- if (update_file(opt, 0, &mfi.oid, mfi.mode, o->path))
1713
+ if (update_file(opt, 0, &mfi.blob, o->path))
1714
return -1;
1715
1716
/*
@@ -1754,16 +1721,16 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
1721
* such cases, we should keep the added file around,
1722
* resolving the conflict at that path in its favor.
1723
*/
1757
- add = filespec_from_entry(&other, ci->ren1->dst_entry, 2 ^ 1);
1758
- if (add) {
1759
- if (update_file(opt, 0, &add->oid, add->mode, a->path))
1724
+ add = &ci->ren1->dst_entry->stages[2 ^ 1];
1725
+ if (is_valid(add)) {
1726
+ if (update_file(opt, 0, add, a->path))
1727
return -1;
1728
}
1729
else
1730
remove_file_from_index(opt->repo->index, a->path);
1764
- add = filespec_from_entry(&other, ci->ren2->dst_entry, 3 ^ 1);
1765
- if (add) {
1766
- if (update_file(opt, 0, &add->oid, add->mode, b->path))
1731
+ add = &ci->ren2->dst_entry->stages[3 ^ 1];
1732
+ if (is_valid(add)) {
1733
+ if (update_file(opt, 0, add, b->path))
1734
return -1;
1735
}
1736
else
@@ -1774,40 +1741,42 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
1741
* rename/add collision. If not, we can write the file out
1742
* to the specified location.
1743
*/
1777
- add = filespec_from_entry(&other, ci->ren1->dst_entry, 2 ^ 1);
1778
- if (add) {
1744
+ add = &ci->ren1->dst_entry->stages[2 ^ 1];
1745
+ if (is_valid(add)) {
1746
+ add->path = mfi.blob.path = a->path;
1747
if (handle_file_collision(opt, a->path,
1748
NULL, NULL,
1749
ci->ren1->branch,
1750
ci->ren2->branch,
1783
- &mfi.oid, mfi.mode,
1784
- &add->oid, add->mode) < 0)
1751
+ &mfi.blob, add) < 0)
1752
return -1;
1753
} else {
1754
char *new_path = find_path_for_conflict(opt, a->path,
1755
ci->ren1->branch,
1756
ci->ren2->branch);
1790
- if (update_file(opt, 0, &mfi.oid, mfi.mode, new_path ? new_path : a->path))
1757
+ if (update_file(opt, 0, &mfi.blob,
1758
+ new_path ? new_path : a->path))
1759
return -1;
1760
free(new_path);
1761
if (update_stages(opt, a->path, NULL, a, NULL))
1762
return -1;
1763
}
1764
1797
- add = filespec_from_entry(&other, ci->ren2->dst_entry, 3 ^ 1);
1798
- if (add) {
1765
+ add = &ci->ren2->dst_entry->stages[3 ^ 1];
1766
+ if (is_valid(add)) {
1767
+ add->path = mfi.blob.path = b->path;
1768
if (handle_file_collision(opt, b->path,
1769
NULL, NULL,
1770
ci->ren1->branch,
1771
ci->ren2->branch,
1803
- &add->oid, add->mode,
1804
- &mfi.oid, mfi.mode) < 0)
1772
+ add, &mfi.blob) < 0)
1773
return -1;
1774
} else {
1775
char *new_path = find_path_for_conflict(opt, b->path,
1776
ci->ren2->branch,
1777
ci->ren1->branch);
1810
- if (update_file(opt, 0, &mfi.oid, mfi.mode, new_path ? new_path : b->path))
1778
+ if (update_file(opt, 0, &mfi.blob,
1779
+ new_path ? new_path : b->path))
1780
return -1;
1781
free(new_path);
1782
if (update_stages(opt, b->path, NULL, NULL, b))
@@ -1826,12 +1795,12 @@ static int handle_rename_rename_2to1(struct merge_options *opt,
1795
struct diff_filespec *b = ci->ren2->pair->one;
1796
struct diff_filespec *c1 = ci->ren1->pair->two;
1797
struct diff_filespec *c2 = ci->ren2->pair->two;
1829
- struct diff_filespec tmp1, tmp2;
1798
char *path = c1->path; /* == c2->path */
1799
char *path_side_1_desc;
1800
char *path_side_2_desc;
1801
struct merge_file_info mfi_c1;
1802
struct merge_file_info mfi_c2;
1803
+ int ostage1, ostage2;
1804
1805
output(opt, 1, _("CONFLICT (rename/rename): "
1806
"Rename %s->%s in %s. "
@@ -1839,27 +1808,31 @@ static int handle_rename_rename_2to1(struct merge_options *opt,
1808
a->path, c1->path, ci->ren1->branch,
1809
b->path, c2->path, ci->ren2->branch);
1810
1842
- filespec_from_entry(&tmp1, ci->ren1->src_entry, 3);
1843
- tmp1.path = a->path;
1844
- filespec_from_entry(&tmp2, ci->ren2->src_entry, 2);
1845
- tmp2.path = b->path;
1846
-
1811
path_side_1_desc = xstrfmt("version of %s from %s", path, a->path);
1812
path_side_2_desc = xstrfmt("version of %s from %s", path, b->path);
1849
- if (merge_mode_and_contents(opt, a, c1, &tmp1, path_side_1_desc,
1813
+ ostage1 = ci->ren1->branch == opt->branch1 ? 3 : 2;
1814
+ ostage2 = ostage1 ^ 1;
1815
+ ci->ren1->src_entry->stages[ostage1].path = a->path;
1816
+ ci->ren2->src_entry->stages[ostage2].path = b->path;
1817
+ if (merge_mode_and_contents(opt, a, c1,
1818
+ &ci->ren1->src_entry->stages[ostage1],
1819
+ path_side_1_desc,
1820
opt->branch1, opt->branch2,
1821
1 + opt->call_depth * 2, &mfi_c1) ||
1852
- merge_mode_and_contents(opt, b, &tmp2, c2, path_side_2_desc,
1822
+ merge_mode_and_contents(opt, b,
1823
+ &ci->ren2->src_entry->stages[ostage2],
1824
+ c2, path_side_2_desc,
1825
opt->branch1, opt->branch2,
1826
1 + opt->call_depth * 2, &mfi_c2))
1827
return -1;
1828
free(path_side_1_desc);
1829
free(path_side_2_desc);
1830
+ mfi_c1.blob.path = path;
1831
+ mfi_c2.blob.path = path;
1832
1833
return handle_file_collision(opt, path, a->path, b->path,
1834
ci->ren1->branch, ci->ren2->branch,
1861
- &mfi_c1.oid, mfi_c1.mode,
1862
- &mfi_c2.oid, mfi_c2.mode);
1835
+ &mfi_c1.blob, &mfi_c2.blob);
1836
}
1837
1838
/*
@@ -2722,7 +2695,6 @@ static int process_renames(struct merge_options *opt,
2695
2696
setup_rename_conflict_info(RENAME_TWO_FILES_TO_ONE,
2697
opt, ren1, ren2);
2725
-
2698
} else {
2699
/* Renamed in 1, maybe changed in 2 */
2700
/* we only use sha1 and mode of these */
@@ -2771,8 +2743,7 @@ static int process_renames(struct merge_options *opt,
2743
* update_file().
2744
*/
2745
if (update_file_flags(opt,
2774
- &ren1->pair->two->oid,
2775
- ren1->pair->two->mode,
2746
+ ren1->pair->two,
2747
ren1_dst,
2748
1, /* update_cache */
2749
0 /* update_wd */))
@@ -2923,11 +2894,6 @@ static void final_cleanup_renames(struct rename_info *re_info)
2894
final_cleanup_rename(re_info->merge_renames);
2895
}
2896
2926
-static struct object_id *stage_oid(const struct object_id *oid, unsigned mode)
2927
-{
2928
- return (is_null_oid(oid) || mode == 0) ? NULL: (struct object_id *)oid;
2929
-}
2930
-
2897
static int read_oid_strbuf(struct merge_options *opt,
2898
const struct object_id *oid,
2899
struct strbuf *dst)
@@ -2947,10 +2913,8 @@ static int read_oid_strbuf(struct merge_options *opt,
2913
}
2914
2915
static int blob_unchanged(struct merge_options *opt,
2950
- const struct object_id *o_oid,
2951
- unsigned o_mode,
2952
- const struct object_id *a_oid,
2953
- unsigned a_mode,
2916
+ const struct diff_filespec *o,
2917
+ const struct diff_filespec *a,
2918
int renormalize, const char *path)
2919
{
2920
struct strbuf obuf = STRBUF_INIT;
@@ -2958,16 +2922,15 @@ static int blob_unchanged(struct merge_options *opt,
2922
int ret = 0; /* assume changed for safety */
2923
const struct index_state *idx = opt->repo->index;
2924
2961
- if (a_mode != o_mode)
2925
+ if (a->mode != o->mode)
2926
return 0;
2963
- if (oid_eq(o_oid, a_oid))
2927
+ if (oid_eq(&o->oid, &a->oid))
2928
return 1;
2929
if (!renormalize)
2930
return 0;
2931
2968
- assert(o_oid && a_oid);
2969
- if (read_oid_strbuf(opt, o_oid, &obuf) ||
2970
- read_oid_strbuf(opt, a_oid, &abuf))
2932
+ if (read_oid_strbuf(opt, &o->oid, &obuf) ||
2933
+ read_oid_strbuf(opt, &a->oid, &abuf))
2934
goto error_return;
2935
/*
2936
* Note: binary | is used so that both renormalizations are
@@ -2986,30 +2949,26 @@ error_return:
2949
2950
static int handle_modify_delete(struct merge_options *opt,
2951
const char *path,
2989
- struct object_id *o_oid, int o_mode,
2990
- struct object_id *a_oid, int a_mode,
2991
- struct object_id *b_oid, int b_mode)
2952
+ const struct diff_filespec *o,
2953
+ const struct diff_filespec *a,
2954
+ const struct diff_filespec *b)
2955
{
2956
const char *modify_branch, *delete_branch;
2994
- struct object_id *changed_oid;
2995
- int changed_mode;
2957
+ const struct diff_filespec *changed;
2958
2997
- if (a_oid) {
2959
+ if (is_valid(a)) {
2960
modify_branch = opt->branch1;
2961
delete_branch = opt->branch2;
3000
- changed_oid = a_oid;
3001
- changed_mode = a_mode;
2962
+ changed = a;
2963
} else {
2964
modify_branch = opt->branch2;
2965
delete_branch = opt->branch1;
3005
- changed_oid = b_oid;
3006
- changed_mode = b_mode;
2966
+ changed = b;
2967
}
2968
2969
return handle_change_delete(opt,
2970
path, NULL,
3011
- o_oid, o_mode,
3012
- changed_oid, changed_mode,
2971
+ o, changed,
2972
modify_branch, delete_branch,
2973
_("modify"), _("modified"));
2974
}
@@ -3017,50 +2976,24 @@ static int handle_modify_delete(struct merge_options *opt,
2976
static int handle_content_merge(struct merge_options *opt,
2977
const char *path,
2978
int is_dirty,
3020
- struct object_id *o_oid, int o_mode,
3021
- struct object_id *a_oid, int a_mode,
3022
- struct object_id *b_oid, int b_mode,
2979
+ const struct diff_filespec *o,
2980
+ const struct diff_filespec *a,
2981
+ const struct diff_filespec *b,
2982
struct rename_conflict_info *ci)
2983
{
2984
const char *reason = _("content");
3026
- const char *path1 = NULL, *path2 = NULL;
2985
struct merge_file_info mfi;
3028
- struct diff_filespec one, a, b;
2986
unsigned df_conflict_remains = 0;
2987
3031
- if (!o_oid) {
2988
+ if (!is_valid(o))
2989
reason = _("add/add");
3033
- o_oid = (struct object_id *)&null_oid;
3034
- }
3035
- one.path = a.path = b.path = (char *)path;
3036
- oidcpy(&one.oid, o_oid);
3037
- one.mode = o_mode;
3038
- oidcpy(&a.oid, a_oid);
3039
- a.mode = a_mode;
3040
- oidcpy(&b.oid, b_oid);
3041
- b.mode = b_mode;
3042
-
3043
- if (ci) {
3044
- struct diff_filepair *pair1 = ci->ren1->pair;
3045
-
3046
- path1 = (opt->branch1 == ci->ren1->branch) ?
3047
- pair1->two->path : pair1->one->path;
3048
- /* If ci->ren2->pair != NULL, we are in
3049
- * RENAME_ONE_FILE_TO_ONE case. Otherwise, we have a
3050
- * normal rename.
3051
- */
3052
- path2 = ((ci->ren2 && ci->ren2->pair) ||
3053
- opt->branch2 == ci->ren1->branch) ?
3054
- pair1->two->path : pair1->one->path;
3055
- one.path = pair1->one->path;
3056
- a.path = (char *)path1;
3057
- b.path = (char *)path2;
3058
-
3059
- if (dir_in_way(opt->repo->index, path, !opt->call_depth,
3060
- S_ISGITLINK(pair1->two->mode)))
3061
- df_conflict_remains = 1;
3062
- }
3063
- if (merge_mode_and_contents(opt, &one, &a, &b, path,
2990
+
2991
+ assert(o->path && a->path && b->path);
2992
+ if (ci && dir_in_way(opt->repo->index, path, !opt->call_depth,
2993
+ S_ISGITLINK(ci->ren1->pair->two->mode)))
2994
+ df_conflict_remains = 1;
2995
+
2996
+ if (merge_mode_and_contents(opt, o, a, b, path,
2997
opt->branch1, opt->branch2,
2998
opt->call_depth * 2, &mfi))
2999
return -1;
@@ -3071,14 +3004,13 @@ static int handle_content_merge(struct merge_options *opt,
3004
* b) The merge matches what was in HEAD (content, mode, pathname)
3005
* c) The target path is usable (i.e. not involved in D/F conflict)
3006
*/
3074
- if (mfi.clean &&
3075
- was_tracked_and_matches(opt, path, &mfi.oid, mfi.mode) &&
3007
+ if (mfi.clean && was_tracked_and_matches(opt, path, &mfi.blob) &&
3008
!df_conflict_remains) {
3009
int pos;
3010
struct cache_entry *ce;
3011
3012
output(opt, 3, _("Skipped %s (merged same as existing)"), path);
3081
- if (add_cacheinfo(opt, mfi.mode, &mfi.oid, path,
3013
+ if (add_cacheinfo(opt, &mfi.blob, path,
3014
0, (!opt->call_depth && !is_dirty), 0))
3015
return -1;
3016
/*
@@ -3098,12 +3030,12 @@ static int handle_content_merge(struct merge_options *opt,
3030
}
3031
3032
if (!mfi.clean) {
3101
- if (S_ISGITLINK(mfi.mode))
3033
+ if (S_ISGITLINK(mfi.blob.mode))
3034
reason = _("submodule");
3035
output(opt, 1, _("CONFLICT (%s): Merge conflict in %s"),
3036
reason, path);
3037
if (ci && !df_conflict_remains)
3106
- if (update_stages(opt, path, &one, &a, &b))
3038
+ if (update_stages(opt, path, o, a, b))
3039
return -1;
3040
}
3041
@@ -3113,17 +3045,14 @@ static int handle_content_merge(struct merge_options *opt,
3045
remove_file_from_index(opt->repo->index, path);
3046
} else {
3047
if (!mfi.clean) {
3116
- if (update_stages(opt, path, &one, &a, &b))
3048
+ if (update_stages(opt, path, o, a, b))
3049
return -1;
3050
} else {
3051
int file_from_stage2 = was_tracked(opt, path);
3120
- struct diff_filespec merged;
3121
- oidcpy(&merged.oid, &mfi.oid);
3122
- merged.mode = mfi.mode;
3052
3053
if (update_stages(opt, path, NULL,
3125
- file_from_stage2 ? &merged : NULL,
3126
- file_from_stage2 ? NULL : &merged))
3054
+ file_from_stage2 ? &mfi.blob : NULL,
3055
+ file_from_stage2 ? NULL : &mfi.blob))
3056
return -1;
3057
}
3058
@@ -3134,28 +3063,27 @@ static int handle_content_merge(struct merge_options *opt,
3063
path);
3064
}
3065
output(opt, 1, _("Adding as %s instead"), new_path);
3137
- if (update_file(opt, 0, &mfi.oid, mfi.mode, new_path)) {
3066
+ if (update_file(opt, 0, &mfi.blob, new_path)) {
3067
free(new_path);
3068
return -1;
3069
}
3070
free(new_path);
3071
mfi.clean = 0;
3143
- } else if (update_file(opt, mfi.clean, &mfi.oid, mfi.mode, path))
3072
+ } else if (update_file(opt, mfi.clean, &mfi.blob, path))
3073
return -1;
3074
return !is_dirty && mfi.clean;
3075
}
3076
3077
static int handle_rename_normal(struct merge_options *opt,
3078
const char *path,
3150
- struct object_id *o_oid, unsigned int o_mode,
3151
- struct object_id *a_oid, unsigned int a_mode,
3152
- struct object_id *b_oid, unsigned int b_mode,
3079
+ const struct diff_filespec *o,
3080
+ const struct diff_filespec *a,
3081
+ const struct diff_filespec *b,
3082
struct rename_conflict_info *ci)
3083
{
3084
/* Merge the content and write it out */
3085
return handle_content_merge(opt, path, was_dirty(opt, path),
3157
- o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,
3158
- ci);
3086
+ o, a, b, ci);
3087
}
3088
3089
/* Per entry merge function */
@@ -3164,24 +3092,36 @@ static int process_entry(struct merge_options *opt,
3092
{
3093
int clean_merge = 1;
3094
int normalize = opt->renormalize;
3167
- unsigned o_mode = entry->stages[1].mode;
3168
- unsigned a_mode = entry->stages[2].mode;
3169
- unsigned b_mode = entry->stages[3].mode;
3170
- struct object_id *o_oid = stage_oid(&entry->stages[1].oid, o_mode);
3171
- struct object_id *a_oid = stage_oid(&entry->stages[2].oid, a_mode);
3172
- struct object_id *b_oid = stage_oid(&entry->stages[3].oid, b_mode);
3095
+
3096
+ struct diff_filespec *o = &entry->stages[1];
3097
+ struct diff_filespec *a = &entry->stages[2];
3098
+ struct diff_filespec *b = &entry->stages[3];
3099
+ int o_valid = is_valid(o);
3100
+ int a_valid = is_valid(a);
3101
+ int b_valid = is_valid(b);
3102
+ o->path = a->path = b->path = (char*)path;
3103
3104
entry->processed = 1;
3105
if (entry->rename_conflict_info) {
3106
struct rename_conflict_info *ci = entry->rename_conflict_info;
3107
+ struct diff_filespec *temp;
3108
+
3109
+ /*
3110
+ * For cases with a single rename, {o,a,b}->path have all been
3111
+ * set to the rename target path; we need to set two of these
3112
+ * back to the rename source.
3113
+ * For rename/rename conflicts, we'll manually fix paths below.
3114
+ */
3115
+ temp = (opt->branch1 == ci->ren1->branch) ? b : a;
3116
+ o->path = temp->path = ci->ren1->pair->one->path;
3117
+ if (ci->ren2) {
3118
+ assert(opt->branch1 == ci->ren1->branch);
3119
+ }
3120
+
3121
switch (ci->rename_type) {
3122
case RENAME_NORMAL:
3123
case RENAME_ONE_FILE_TO_ONE:
3180
- clean_merge = handle_rename_normal(opt,
3181
- path,
3182
- o_oid, o_mode,
3183
- a_oid, a_mode,
3184
- b_oid, b_mode,
3124
+ clean_merge = handle_rename_normal(opt, path, o, a, b,
3125
ci);
3126
break;
3127
case RENAME_VIA_DIR:
@@ -3204,11 +3144,27 @@ static int process_entry(struct merge_options *opt,
3144
clean_merge = -1;
3145
break;
3146
case RENAME_ONE_FILE_TO_TWO:
3147
+ /*
3148
+ * Manually fix up paths; note:
3149
+ * ren[12]->pair->one->path are equal.
3150
+ */
3151
+ o->path = ci->ren1->pair->one->path;
3152
+ a->path = ci->ren1->pair->two->path;
3153
+ b->path = ci->ren2->pair->two->path;
3154
+
3155
clean_merge = 0;
3156
if (handle_rename_rename_1to2(opt, ci))
3157
clean_merge = -1;
3158
break;
3159
case RENAME_TWO_FILES_TO_ONE:
3160
+ /*
3161
+ * Manually fix up paths; note,
3162
+ * ren[12]->pair->two->path are actually equal.
3163
+ */
3164
+ o->path = NULL;
3165
+ a->path = ci->ren1->pair->two->path;
3166
+ b->path = ci->ren2->pair->two->path;
3167
+
3168
/*
3169
* Probably unclean merge, but if the two renamed
3170
* files merge cleanly and the two resulting files
@@ -3221,57 +3177,53 @@ static int process_entry(struct merge_options *opt,
3177
entry->processed = 0;
3178
break;
3179
}
3224
- } else if (o_oid && (!a_oid || !b_oid)) {
3180
+ } else if (o_valid && (!a_valid || !b_valid)) {
3181
/* Case A: Deleted in one */
3226
- if ((!a_oid && !b_oid) ||
3227
- (!b_oid && blob_unchanged(opt, o_oid, o_mode, a_oid, a_mode, normalize, path)) ||
3228
- (!a_oid && blob_unchanged(opt, o_oid, o_mode, b_oid, b_mode, normalize, path))) {
3182
+ if ((!a_valid && !b_valid) ||
3183
+ (!b_valid && blob_unchanged(opt, o, a, normalize, path)) ||
3184
+ (!a_valid && blob_unchanged(opt, o, b, normalize, path))) {
3185
/* Deleted in both or deleted in one and
3186
* unchanged in the other */
3231
- if (a_oid)
3187
+ if (a_valid)
3188
output(opt, 2, _("Removing %s"), path);
3189
/* do not touch working file if it did not exist */
3234
- remove_file(opt, 1, path, !a_oid);
3190
+ remove_file(opt, 1, path, !a_valid);
3191
} else {
3192
/* Modify/delete; deleted side may have put a directory in the way */
3193
clean_merge = 0;
3238
- if (handle_modify_delete(opt, path, o_oid, o_mode,
3239
- a_oid, a_mode, b_oid, b_mode))
3194
+ if (handle_modify_delete(opt, path, o, a, b))
3195
clean_merge = -1;
3196
}
3242
- } else if ((!o_oid && a_oid && !b_oid) ||
3243
- (!o_oid && !a_oid && b_oid)) {
3197
+ } else if ((!o_valid && a_valid && !b_valid) ||
3198
+ (!o_valid && !a_valid && b_valid)) {
3199
/* Case B: Added in one. */
3200
/* [nothing|directory] -> ([nothing|directory], file) */
3201
3202
const char *add_branch;
3203
const char *other_branch;
3249
- unsigned mode;
3250
- const struct object_id *oid;
3204
const char *conf;
3205
+ const struct diff_filespec *contents;
3206
3253
- if (a_oid) {
3207
+ if (a_valid) {
3208
add_branch = opt->branch1;
3209
other_branch = opt->branch2;
3256
- mode = a_mode;
3257
- oid = a_oid;
3210
+ contents = a;
3211
conf = _("file/directory");
3212
} else {
3213
add_branch = opt->branch2;
3214
other_branch = opt->branch1;
3262
- mode = b_mode;
3263
- oid = b_oid;
3215
+ contents = b;
3216
conf = _("directory/file");
3217
}
3218
if (dir_in_way(opt->repo->index, path,
3267
- !opt->call_depth && !S_ISGITLINK(a_mode),
3219
+ !opt->call_depth && !S_ISGITLINK(a->mode),
3220
0)) {
3221
char *new_path = unique_path(opt, path, add_branch);
3222
clean_merge = 0;
3223
output(opt, 1, _("CONFLICT (%s): There is a directory with name %s in %s. "
3224
"Adding %s as %s"),
3225
conf, path, other_branch, path, new_path);
3274
- if (update_file(opt, 0, oid, mode, new_path))
3226
+ if (update_file(opt, 0, contents, new_path))
3227
clean_merge = -1;
3228
else if (opt->call_depth)
3229
remove_file_from_index(opt->repo->index, path);
@@ -3279,11 +3231,11 @@ static int process_entry(struct merge_options *opt,
3231
} else {
3232
output(opt, 2, _("Adding %s"), path);
3233
/* do not overwrite file if already present */
3282
- if (update_file_flags(opt, oid, mode, path, 1, !a_oid))
3234
+ if (update_file_flags(opt, contents, path, 1, !a_valid))
3235
clean_merge = -1;
3236
}
3285
- } else if (a_oid && b_oid) {
3286
- if (!o_oid) {
3237
+ } else if (a_valid && b_valid) {
3238
+ if (!o_valid) {
3239
/* Case C: Added in both (check for same permissions) */
3240
output(opt, 1,
3241
_("CONFLICT (add/add): Merge conflict in %s"),
@@ -3292,24 +3244,19 @@ static int process_entry(struct merge_options *opt,
3244
path, NULL, NULL,
3245
opt->branch1,
3246
opt->branch2,
3295
- a_oid, a_mode,
3296
- b_oid, b_mode);
3247
+ a, b);
3248
} else {
3249
/* case D: Modified in both, but differently. */
3250
int is_dirty = 0; /* unpack_trees would have bailed if dirty */
3300
- clean_merge = handle_content_merge(opt, path,
3301
- is_dirty,
3302
- o_oid, o_mode,
3303
- a_oid, a_mode,
3304
- b_oid, b_mode,
3305
- NULL);
3251
+ clean_merge = handle_content_merge(opt, path, is_dirty,
3252
+ o, a, b, NULL);
3253
}
3307
- } else if (!o_oid && !a_oid && !b_oid) {
3254
+ } else if (!o_valid && !a_valid && !b_valid) {
3255
/*
3256
* this entry was deleted altogether. a_mode == 0 means
3257
* we had that path and want to actively remove it.
3258
*/
3312
- remove_file(opt, 1, path, !a_mode);
3259
+ remove_file(opt, 1, path, !a->mode);
3260
} else
3261
BUG("fatal merge failure, shouldn't happen.");
3262