Skip to content

Commit 1218b3a

Browse files
newrengitster
authored andcommitted
merge-ort: have ll_merge() use a special attr_index for renormalization
ll_merge() needs an index when renormalization is requested. Create one specifically for just this purpose with just the one needed entry. This fixes t6418.4 and t6418.5 under GIT_TEST_MERGE_ALGORITHM=ort. NOTE 1: Even if the user has a working copy or a real index (which is not a given as merge-ort can be used in bare repositories), we explicitly ignore any .gitattributes file from either of these locations. merge-ort can be used to merge two branches that are unrelated to HEAD, so .gitattributes from the working copy and current index should not be considered relevant. NOTE 2: Since we are in the middle of merging, there is a risk that .gitattributes itself is conflicted...leaving us with an ill-defined situation about how to perform the rest of the merge. It could be that the .gitattributes file does not even exist on one of the sides of the merge, or that it has been modified on both sides. If it's been modified on both sides, it's possible that it could itself be merged cleanly, though it's also possible that it only merges cleanly if you use the right version of the .gitattributes file to drive the merge. It gets kind of complicated. The only test we ever had that attempted to test behavior in this area was seemingly unaware of the undefined behavior, but knew the test wouldn't work for lack of attribute handling support, marked it as test_expect_failure from the beginning, but managed to fail for several reasons unrelated to attribute handling. See commit 6f6e7cf ("t6038: remove problematic test", 2020-08-03) for details. So there are probably various ways to improve what initialize_attr_index() picks in the case of a conflicted .gitattributes but for now I just implemented something simple -- look for whatever .gitattributes file we can find in any of the higher order stages and use it. Signed-off-by: Elijah Newren <[email protected]> Reviewed-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ea305a6 commit 1218b3a

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

merge-ort.c

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
410410
string_list_clear(&opti->paths_to_free, 0);
411411
opti->paths_to_free.strdup_strings = 0;
412412

413-
if (opti->attr_index.cache_nr)
413+
if (opti->attr_index.cache_nr) /* true iff opt->renormalize */
414414
discard_index(&opti->attr_index);
415415

416416
/* Free memory used by various renames maps */
@@ -1201,6 +1201,63 @@ static int merge_submodule(struct merge_options *opt,
12011201
return 0;
12021202
}
12031203

1204+
static void initialize_attr_index(struct merge_options *opt)
1205+
{
1206+
/*
1207+
* The renormalize_buffer() functions require attributes, and
1208+
* annoyingly those can only be read from the working tree or from
1209+
* an index_state. merge-ort doesn't have an index_state, so we
1210+
* generate a fake one containing only attribute information.
1211+
*/
1212+
struct merged_info *mi;
1213+
struct index_state *attr_index = &opt->priv->attr_index;
1214+
struct cache_entry *ce;
1215+
1216+
attr_index->initialized = 1;
1217+
1218+
if (!opt->renormalize)
1219+
return;
1220+
1221+
mi = strmap_get(&opt->priv->paths, GITATTRIBUTES_FILE);
1222+
if (!mi)
1223+
return;
1224+
1225+
if (mi->clean) {
1226+
int len = strlen(GITATTRIBUTES_FILE);
1227+
ce = make_empty_cache_entry(attr_index, len);
1228+
ce->ce_mode = create_ce_mode(mi->result.mode);
1229+
ce->ce_flags = create_ce_flags(0);
1230+
ce->ce_namelen = len;
1231+
oidcpy(&ce->oid, &mi->result.oid);
1232+
memcpy(ce->name, GITATTRIBUTES_FILE, len);
1233+
add_index_entry(attr_index, ce,
1234+
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
1235+
get_stream_filter(attr_index, GITATTRIBUTES_FILE, &ce->oid);
1236+
} else {
1237+
int stage, len;
1238+
struct conflict_info *ci;
1239+
1240+
ASSIGN_AND_VERIFY_CI(ci, mi);
1241+
for (stage = 0; stage < 3; stage++) {
1242+
unsigned stage_mask = (1 << stage);
1243+
1244+
if (!(ci->filemask & stage_mask))
1245+
continue;
1246+
len = strlen(GITATTRIBUTES_FILE);
1247+
ce = make_empty_cache_entry(attr_index, len);
1248+
ce->ce_mode = create_ce_mode(ci->stages[stage].mode);
1249+
ce->ce_flags = create_ce_flags(stage);
1250+
ce->ce_namelen = len;
1251+
oidcpy(&ce->oid, &ci->stages[stage].oid);
1252+
memcpy(ce->name, GITATTRIBUTES_FILE, len);
1253+
add_index_entry(attr_index, ce,
1254+
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
1255+
get_stream_filter(attr_index, GITATTRIBUTES_FILE,
1256+
&ce->oid);
1257+
}
1258+
}
1259+
}
1260+
12041261
static int merge_3way(struct merge_options *opt,
12051262
const char *path,
12061263
const struct object_id *o,
@@ -1215,6 +1272,9 @@ static int merge_3way(struct merge_options *opt,
12151272
char *base, *name1, *name2;
12161273
int merge_status;
12171274

1275+
if (!opt->priv->attr_index.initialized)
1276+
initialize_attr_index(opt);
1277+
12181278
ll_opts.renormalize = opt->renormalize;
12191279
ll_opts.extra_marker_size = extra_marker_size;
12201280
ll_opts.xdl_opts = opt->xdl_opts;
@@ -1253,7 +1313,7 @@ static int merge_3way(struct merge_options *opt,
12531313

12541314
merge_status = ll_merge(result_buf, path, &orig, base,
12551315
&src1, name1, &src2, name2,
1256-
opt->repo->index, &ll_opts);
1316+
&opt->priv->attr_index, &ll_opts);
12571317

12581318
free(base);
12591319
free(name1);

0 commit comments

Comments
 (0)