merge-ort: handle directory/file conflicts that remain
When a directory/file conflict remains, we can leave the directory where it is, but need to move the information about the file to a different pathname. After moving the file to a different pathname, we allow subsequent process_entry() logic to handle any additional details that might be relevant. This depends on a new helper function, unique_path(), that dies with an unimplemented error currently but will be implemented in a subsequent commit. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
0ccfa4e5d8
commit
23366d2aa9
86
merge-ort.c
86
merge-ort.c
@ -343,6 +343,13 @@ static void path_msg(struct merge_options *opt,
|
||||
strbuf_addch(sb, '\n');
|
||||
}
|
||||
|
||||
static char *unique_path(struct strmap *existing_paths,
|
||||
const char *path,
|
||||
const char *branch)
|
||||
{
|
||||
die("Not yet implemented.");
|
||||
}
|
||||
|
||||
/*** Function Grouping: functions related to collect_merge_info() ***/
|
||||
|
||||
static void setup_path_info(struct merge_options *opt,
|
||||
@ -962,6 +969,8 @@ static void process_entry(struct merge_options *opt,
|
||||
struct conflict_info *ci,
|
||||
struct directory_versions *dir_metadata)
|
||||
{
|
||||
int df_file_index = 0;
|
||||
|
||||
VERIFY_CI(ci);
|
||||
assert(ci->filemask >= 0 && ci->filemask <= 7);
|
||||
/* ci->match_mask == 7 was handled in collect_merge_info_callback() */
|
||||
@ -998,13 +1007,86 @@ static void process_entry(struct merge_options *opt,
|
||||
oidcpy(&ci->stages[i].oid, &null_oid);
|
||||
}
|
||||
} else if (ci->df_conflict && ci->merged.result.mode != 0) {
|
||||
die("Not yet implemented.");
|
||||
/*
|
||||
* This started out as a D/F conflict, and the entries in
|
||||
* the competing directory were not removed by the merge as
|
||||
* evidenced by write_completed_directory() writing a value
|
||||
* to ci->merged.result.mode.
|
||||
*/
|
||||
struct conflict_info *new_ci;
|
||||
const char *branch;
|
||||
const char *old_path = path;
|
||||
int i;
|
||||
|
||||
assert(ci->merged.result.mode == S_IFDIR);
|
||||
|
||||
/*
|
||||
* If filemask is 1, we can just ignore the file as having
|
||||
* been deleted on both sides. We do not want to overwrite
|
||||
* ci->merged.result, since it stores the tree for all the
|
||||
* files under it.
|
||||
*/
|
||||
if (ci->filemask == 1) {
|
||||
ci->filemask = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file still exists on at least one side, and we want
|
||||
* the directory to remain here, so we need to move this
|
||||
* path to some new location.
|
||||
*/
|
||||
new_ci = xcalloc(1, sizeof(*new_ci));
|
||||
/* We don't really want new_ci->merged.result copied, but it'll
|
||||
* be overwritten below so it doesn't matter. We also don't
|
||||
* want any directory mode/oid values copied, but we'll zero
|
||||
* those out immediately. We do want the rest of ci copied.
|
||||
*/
|
||||
memcpy(new_ci, ci, sizeof(*ci));
|
||||
new_ci->match_mask = (new_ci->match_mask & ~new_ci->dirmask);
|
||||
new_ci->dirmask = 0;
|
||||
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
|
||||
if (new_ci->filemask & (1 << i))
|
||||
continue;
|
||||
/* zero out any entries related to directories */
|
||||
new_ci->stages[i].mode = 0;
|
||||
oidcpy(&new_ci->stages[i].oid, &null_oid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out which side this file came from; note that we
|
||||
* cannot just use ci->filemask, because renames could cause
|
||||
* the filemask to go back to 7. So we use dirmask, then
|
||||
* pick the opposite side's index.
|
||||
*/
|
||||
df_file_index = (ci->dirmask & (1 << 1)) ? 2 : 1;
|
||||
branch = (df_file_index == 1) ? opt->branch1 : opt->branch2;
|
||||
path = unique_path(&opt->priv->paths, path, branch);
|
||||
strmap_put(&opt->priv->paths, path, new_ci);
|
||||
|
||||
path_msg(opt, path, 0,
|
||||
_("CONFLICT (file/directory): directory in the way "
|
||||
"of %s from %s; moving it to %s instead."),
|
||||
old_path, branch, path);
|
||||
|
||||
/*
|
||||
* Zero out the filemask for the old ci. At this point, ci
|
||||
* was just an entry for a directory, so we don't need to
|
||||
* do anything more with it.
|
||||
*/
|
||||
ci->filemask = 0;
|
||||
|
||||
/*
|
||||
* Now note that we're working on the new entry (path was
|
||||
* updated above.
|
||||
*/
|
||||
ci = new_ci;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Below there is a long switch-like if-elseif-elseif... block
|
||||
* which the code goes through even for the df_conflict cases
|
||||
* above. Well, it will once we don't die-not-implemented above.
|
||||
* above.
|
||||
*/
|
||||
if (ci->match_mask) {
|
||||
ci->merged.clean = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user