Skip to content

Commit 3860220

Browse files
newrengitster
authored andcommitted
merge-ort: let renormalization change modify/delete into clean delete
When we have a modify/delete conflict, but the only change to the modification is e.g. change of line endings, then if renormalization is requested then we should be able to recognize such a case as a not-modified/delete and resolve the conflict automatically. This fixes t6418.10 under GIT_TEST_MERGE_ALGORITHM=ort. Signed-off-by: Elijah Newren <[email protected]> Reviewed-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1218b3a commit 3860220

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
@@ -2549,6 +2549,61 @@ static int string_list_df_name_compare(const char *one, const char *two)
25492549
return onelen - twolen;
25502550
}
25512551

2552+
static int read_oid_strbuf(struct merge_options *opt,
2553+
const struct object_id *oid,
2554+
struct strbuf *dst)
2555+
{
2556+
void *buf;
2557+
enum object_type type;
2558+
unsigned long size;
2559+
buf = read_object_file(oid, &type, &size);
2560+
if (!buf)
2561+
return err(opt, _("cannot read object %s"), oid_to_hex(oid));
2562+
if (type != OBJ_BLOB) {
2563+
free(buf);
2564+
return err(opt, _("object %s is not a blob"), oid_to_hex(oid));
2565+
}
2566+
strbuf_attach(dst, buf, size, size + 1);
2567+
return 0;
2568+
}
2569+
2570+
static int blob_unchanged(struct merge_options *opt,
2571+
const struct version_info *base,
2572+
const struct version_info *side,
2573+
const char *path)
2574+
{
2575+
struct strbuf basebuf = STRBUF_INIT;
2576+
struct strbuf sidebuf = STRBUF_INIT;
2577+
int ret = 0; /* assume changed for safety */
2578+
const struct index_state *idx = &opt->priv->attr_index;
2579+
2580+
if (!idx->initialized)
2581+
initialize_attr_index(opt);
2582+
2583+
if (base->mode != side->mode)
2584+
return 0;
2585+
if (oideq(&base->oid, &side->oid))
2586+
return 1;
2587+
2588+
if (read_oid_strbuf(opt, &base->oid, &basebuf) ||
2589+
read_oid_strbuf(opt, &side->oid, &sidebuf))
2590+
goto error_return;
2591+
/*
2592+
* Note: binary | is used so that both renormalizations are
2593+
* performed. Comparison can be skipped if both files are
2594+
* unchanged since their sha1s have already been compared.
2595+
*/
2596+
if (renormalize_buffer(idx, path, basebuf.buf, basebuf.len, &basebuf) |
2597+
renormalize_buffer(idx, path, sidebuf.buf, sidebuf.len, &sidebuf))
2598+
ret = (basebuf.len == sidebuf.len &&
2599+
!memcmp(basebuf.buf, sidebuf.buf, basebuf.len));
2600+
2601+
error_return:
2602+
strbuf_release(&basebuf);
2603+
strbuf_release(&sidebuf);
2604+
return ret;
2605+
}
2606+
25522607
struct directory_versions {
25532608
/*
25542609
* versions: list of (basename -> version_info)
@@ -3136,8 +3191,13 @@ static void process_entry(struct merge_options *opt,
31363191
modify_branch = (side == 1) ? opt->branch1 : opt->branch2;
31373192
delete_branch = (side == 1) ? opt->branch2 : opt->branch1;
31383193

3139-
if (ci->path_conflict &&
3140-
oideq(&ci->stages[0].oid, &ci->stages[side].oid)) {
3194+
if (opt->renormalize &&
3195+
blob_unchanged(opt, &ci->stages[0], &ci->stages[side],
3196+
path)) {
3197+
ci->merged.is_null = 1;
3198+
ci->merged.clean = 1;
3199+
} else if (ci->path_conflict &&
3200+
oideq(&ci->stages[0].oid, &ci->stages[side].oid)) {
31413201
/*
31423202
* This came from a rename/delete; no action to take,
31433203
* but avoid printing "modify/delete" conflict notice

0 commit comments

Comments
 (0)