From 34e557af5469299453f63d3594d5b392a09937d1 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sun, 13 Dec 2020 08:04:15 +0000 Subject: [PATCH] merge-ort: compute a few more useful fields for collect_merge_info Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- merge-ort.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/merge-ort.c b/merge-ort.c index 690c64fe26..a6876191c0 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -220,6 +220,7 @@ static int collect_merge_info_callback(int n, size_t len; char *fullpath; unsigned filemask = mask & ~dirmask; + unsigned match_mask = 0; /* will be updated below */ unsigned mbase_null = !(mask & 1); unsigned side1_null = !(mask & 2); unsigned side2_null = !(mask & 4); @@ -233,6 +234,22 @@ static int collect_merge_info_callback(int n, names[1].mode == names[2].mode && oideq(&names[1].oid, &names[2].oid)); + /* + * Note: When a path is a file on one side of history and a directory + * in another, we have a directory/file conflict. In such cases, if + * the conflict doesn't resolve from renames and deletions, then we + * always leave directories where they are and move files out of the + * way. Thus, while struct conflict_info has a df_conflict field to + * track such conflicts, we ignore that field for any directories at + * a path and only pay attention to it for files at the given path. + * The fact that we leave directories were they are also means that + * we do not need to worry about getting additional df_conflict + * information propagated from parent directories down to children + * (unlike, say traverse_trees_recursive() in unpack-trees.c, which + * sets a newinfo.df_conflicts field specifically to propagate it). + */ + unsigned df_conflict = (filemask != 0) && (dirmask != 0); + /* n = 3 is a fundamental assumption. */ if (n != 3) BUG("Called collect_merge_info_callback wrong"); @@ -248,6 +265,14 @@ static int collect_merge_info_callback(int n, assert(!mbase_null || !side1_null || !side2_null); assert(mask > 0 && mask < 8); + /* Determine match_mask */ + if (side1_matches_mbase) + match_mask = (side2_matches_mbase ? 7 : 3); + else if (side2_matches_mbase) + match_mask = 5; + else if (sides_match) + match_mask = 6; + /* * Get the name of the relevant filepath, which we'll pass to * setup_path_info() for tracking. @@ -266,6 +291,8 @@ static int collect_merge_info_callback(int n, * so we can resolve later in process_entries. */ ci = xcalloc(1, sizeof(struct conflict_info)); + ci->df_conflict = df_conflict; + ci->match_mask = match_mask; strmap_put(&opti->paths, fullpath, ci); /* If dirmask, recurse into subdirectories */ @@ -282,6 +309,15 @@ static int collect_merge_info_callback(int n, newinfo.name = p->path; newinfo.namelen = p->pathlen; newinfo.pathlen = st_add3(newinfo.pathlen, p->pathlen, 1); + /* + * If this directory we are about to recurse into cared about + * its parent directory (the current directory) having a D/F + * conflict, then we'd propagate the masks in this way: + * newinfo.df_conflicts |= (mask & ~dirmask); + * But we don't worry about propagating D/F conflicts. (See + * comment near setting of local df_conflict variable near + * the beginning of this function). + */ for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) { if (i == 1 && side1_matches_mbase) -- 2.11.4.GIT