merge-ort: add a handle_deferred_entries() helper function

In order to allow trivial directory resolution, we first need to be able to gather more information to determine if the optimization is safe. To enable that, we need a way of deferring the recursion into the directory until a later time. Naturally, deferring the entry into a subtree means that we need some function that will later recurse into the subdirectory exactly the same way that collect_merge_info_callback() would have done. Add a helper function that does this. For now this function is not used but a subsequent commit will change that. Future commits will also make the function sometimes resolve directories instead of traversing inside. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jul 16, 2021 at 05:22 UTC e0ef578eae4aea91920ef394a0d38170b39777d1
1 file changed +64
merge-ort.c
+64
@@ -1202,6 +1202,70 @@ static int collect_merge_info_callback(int n,
1202 return mask;
1203 }
1204
1205 +MAYBE_UNUSED
1206 +static int handle_deferred_entries(struct merge_options *opt,
1207 + struct traverse_info *info)
1208 +{
1209 + struct rename_info *renames = &opt->priv->renames;
1210 + struct hashmap_iter iter;
1211 + struct strmap_entry *entry;
1212 + int side, ret = 0;
1213 +
1214 + for (side = MERGE_SIDE1; side <= MERGE_SIDE2; side++) {
1215 + renames->deferred[side].trivial_merges_okay = 0;
1216 + strintmap_for_each_entry(&renames->deferred[side].possible_trivial_merges,
1217 + &iter, entry) {
1218 + const char *path = entry->key;
1219 + unsigned dir_rename_mask = (intptr_t)entry->value;
1220 + struct conflict_info *ci;
1221 + unsigned dirmask;
1222 + struct tree_desc t[3];
1223 + void *buf[3] = {NULL,};
1224 + int i;
1225 +
1226 + ci = strmap_get(&opt->priv->paths, path);
1227 + VERIFY_CI(ci);
1228 + dirmask = ci->dirmask;
1229 +
1230 + info->name = path;
1231 + info->namelen = strlen(path);
1232 + info->pathlen = info->namelen + 1;
1233 +
1234 + for (i = 0; i < 3; i++, dirmask >>= 1) {
1235 + if (i == 1 && ci->match_mask == 3)
1236 + t[1] = t[0];
1237 + else if (i == 2 && ci->match_mask == 5)
1238 + t[2] = t[0];
1239 + else if (i == 2 && ci->match_mask == 6)
1240 + t[2] = t[1];
1241 + else {
1242 + const struct object_id *oid = NULL;
1243 + if (dirmask & 1)
1244 + oid = &ci->stages[i].oid;
1245 + buf[i] = fill_tree_descriptor(opt->repo,
1246 + t+i, oid);
1247 + }
1248 + }
1249 +
1250 + ci->match_mask &= ci->filemask;
1251 + opt->priv->current_dir_name = path;
1252 + renames->dir_rename_mask = dir_rename_mask;
1253 + if (renames->dir_rename_mask == 0 ||
1254 + renames->dir_rename_mask == 0x07)
1255 + ret = traverse_trees(NULL, 3, t, info);
1256 + else
1257 + ret = traverse_trees_wrapper(NULL, 3, t, info);
1258 +
1259 + for (i = MERGE_BASE; i <= MERGE_SIDE2; i++)
1260 + free(buf[i]);
1261 +
1262 + if (ret < 0)
1263 + return ret;
1264 + }
1265 + }
1266 + return ret;
1267 +}
1268 +
1269 static int collect_merge_info(struct merge_options *opt,
1270 struct tree *merge_base,
1271 struct tree *side1,