summaryrefslogtreecommitdiff
path: root/merge-ort.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2020-12-14 16:21:34 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-12-14 16:45:59 (GMT)
commitc2d267df0215d49f06638463889465389134021a (patch)
tree02d70a8b7ac7df1ee56b359d2e4af5fa380c4f1d /merge-ort.c
parent965a7bc21c6bb11fb15eb798fd472ec9deb5e3fa (diff)
downloadgit-c2d267df0215d49f06638463889465389134021a.zip
git-c2d267df0215d49f06638463889465389134021a.tar.gz
git-c2d267df0215d49f06638463889465389134021a.tar.bz2
merge-ort: add basic outline for process_renames()
Add code which determines which kind of special rename case each rename corresponds to, but leave the handling of each type unimplemented for now. Future commits will implement each one. There is some tenuous resemblance to merge-recursive's process_renames(), but comparing the two is very unlikely to yield any insights. merge-ort's process_renames() is a bit complex and I would prefer if I could simplify it more, but it is far easier to grok than merge-recursive's function of the same name in my opinion. Plus, merge-ort handles more rename conflict types than merge-recursive does. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-ort.c')
-rw-r--r--merge-ort.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/merge-ort.c b/merge-ort.c
index 10550c5..ebe275e 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -647,7 +647,103 @@ static int handle_content_merge(struct merge_options *opt,
static int process_renames(struct merge_options *opt,
struct diff_queue_struct *renames)
{
- die("Not yet implemented.");
+ int clean_merge = 1, i;
+
+ for (i = 0; i < renames->nr; ++i) {
+ const char *oldpath = NULL, *newpath;
+ struct diff_filepair *pair = renames->queue[i];
+ struct conflict_info *oldinfo = NULL, *newinfo = NULL;
+ struct strmap_entry *old_ent, *new_ent;
+ unsigned int old_sidemask;
+ int target_index, other_source_index;
+ int source_deleted, collision, type_changed;
+
+ old_ent = strmap_get_entry(&opt->priv->paths, pair->one->path);
+ oldpath = old_ent->key;
+ oldinfo = old_ent->value;
+
+ new_ent = strmap_get_entry(&opt->priv->paths, pair->two->path);
+ newpath = new_ent->key;
+ newinfo = new_ent->value;
+
+ /*
+ * diff_filepairs have copies of pathnames, thus we have to
+ * use standard 'strcmp()' (negated) instead of '=='.
+ */
+ if (i + 1 < renames->nr &&
+ !strcmp(oldpath, renames->queue[i+1]->one->path)) {
+ /* Handle rename/rename(1to2) or rename/rename(1to1) */
+ const char *pathnames[3];
+
+ pathnames[0] = oldpath;
+ pathnames[1] = newpath;
+ pathnames[2] = renames->queue[i+1]->two->path;
+
+ if (!strcmp(pathnames[1], pathnames[2])) {
+ /* Both sides renamed the same way. */
+ die("Not yet implemented");
+
+ /* We handled both renames, i.e. i+1 handled */
+ i++;
+ /* Move to next rename */
+ continue;
+ }
+
+ /* This is a rename/rename(1to2) */
+ die("Not yet implemented");
+
+ i++; /* We handled both renames, i.e. i+1 handled */
+ continue;
+ }
+
+ VERIFY_CI(oldinfo);
+ VERIFY_CI(newinfo);
+ target_index = pair->score; /* from collect_renames() */
+ assert(target_index == 1 || target_index == 2);
+ other_source_index = 3 - target_index;
+ old_sidemask = (1 << other_source_index); /* 2 or 4 */
+ source_deleted = (oldinfo->filemask == 1);
+ collision = ((newinfo->filemask & old_sidemask) != 0);
+ type_changed = !source_deleted &&
+ (S_ISREG(oldinfo->stages[other_source_index].mode) !=
+ S_ISREG(newinfo->stages[target_index].mode));
+ if (type_changed && collision) {
+ /* special handling so later blocks can handle this */
+ die("Not yet implemented");
+ }
+
+ assert(source_deleted || oldinfo->filemask & old_sidemask);
+
+ /* Need to check for special types of rename conflicts... */
+ if (collision && !source_deleted) {
+ /* collision: rename/add or rename/rename(2to1) */
+ die("Not yet implemented");
+ } else if (collision && source_deleted) {
+ /* rename/add/delete or rename/rename(2to1)/delete */
+ die("Not yet implemented");
+ } else {
+ /* a few different cases... */
+ if (type_changed) {
+ /* rename vs. typechange */
+ die("Not yet implemented");
+ } else if (source_deleted) {
+ /* rename/delete */
+ die("Not yet implemented");
+ } else {
+ /* normal rename */
+ die("Not yet implemented");
+ }
+ }
+
+ if (!type_changed) {
+ /* Mark the original as resolved by removal */
+ oldinfo->merged.is_null = 1;
+ oldinfo->merged.clean = 1;
+ }
+
+ }
+
+ return clean_merge;
}
static int compare_pairs(const void *a_, const void *b_)