diff options
author | Taylor Blau <me@ttaylorr.com> | 2022-10-31 04:04:43 +0300 |
---|---|---|
committer | Taylor Blau <me@ttaylorr.com> | 2022-10-31 04:04:43 +0300 |
commit | 969230b64fe76972d55b55cee8136e43a7e84752 (patch) | |
tree | 880d47df834dc02f7707b021ae7b43132e3426fc /merge-ort.c | |
parent | a23e0b69e2d25a893e187d86719de0b12b324579 (diff) | |
parent | 2b86c10084a54ee2b2e2cfd69ac02f3719fb47e0 (diff) |
Merge branch 'en/ort-dir-rename-and-symlink-fix'
Merging a branch with directory renames into a branch that changes
the directory to a symlink was mishandled by the ort merge
strategy, which has been corrected.
* en/ort-dir-rename-and-symlink-fix:
merge-ort: fix bug with dir rename vs change dir to symlink
Diffstat (limited to 'merge-ort.c')
-rw-r--r-- | merge-ort.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/merge-ort.c b/merge-ort.c index 7e83ebfaa9..d1611ca400 100644 --- a/merge-ort.c +++ b/merge-ort.c @@ -2619,8 +2619,40 @@ static void apply_directory_rename_modifications(struct merge_options *opt, } assert(ci->filemask == 2 || ci->filemask == 4); - assert(ci->dirmask == 0); - strmap_remove(&opt->priv->paths, old_path, 0); + assert(ci->dirmask == 0 || ci->dirmask == 1); + if (ci->dirmask == 0) + strmap_remove(&opt->priv->paths, old_path, 0); + else { + /* + * This file exists on one side, but we still had a directory + * at the old location that we can't remove until after + * processing all paths below it. So, make a copy of ci in + * new_ci and only put the file information into it. + */ + new_ci = mem_pool_calloc(&opt->priv->pool, 1, sizeof(*new_ci)); + memcpy(new_ci, ci, sizeof(*ci)); + assert(!new_ci->match_mask); + new_ci->dirmask = 0; + new_ci->stages[1].mode = 0; + oidcpy(&new_ci->stages[1].oid, null_oid()); + + /* + * Now that we have the file information in new_ci, make sure + * ci only has the directory information. + */ + ci->filemask = 0; + ci->merged.clean = 1; + for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) { + if (ci->dirmask & (1 << i)) + continue; + /* zero out any entries related to files */ + ci->stages[i].mode = 0; + oidcpy(&ci->stages[i].oid, null_oid()); + } + + // Now we want to focus on new_ci, so reassign ci to it + ci = new_ci; + } branch_with_new_path = (ci->filemask == 2) ? opt->branch1 : opt->branch2; branch_with_dir_rename = (ci->filemask == 2) ? opt->branch2 : opt->branch1; |