diff --git a/merge-ort.c b/merge-ort.c index 10550c542b89e3..ebe275ef73c9f2 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_)