mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
merge-ort: record stage and auxiliary info for every path
Create a helper function, setup_path_info(), which can be used to record all the information we want in a merged_info or conflict_info. While there is currently only one caller of this new function, and some of its particular parameters are fixed, future callers of this function will be added later. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
34e557af54
commit
98bf984167
97
merge-ort.c
97
merge-ort.c
@ -185,6 +185,26 @@ struct conflict_info {
|
||||
unsigned match_mask:3;
|
||||
};
|
||||
|
||||
/*
|
||||
* For the next three macros, see warning for conflict_info.merged.
|
||||
*
|
||||
* In each of the below, mi is a struct merged_info*, and ci was defined
|
||||
* as a struct conflict_info* (but we need to verify ci isn't actually
|
||||
* pointed at a struct merged_info*).
|
||||
*
|
||||
* INITIALIZE_CI: Assign ci to mi but only if it's safe; set to NULL otherwise.
|
||||
* VERIFY_CI: Ensure that something we assigned to a conflict_info* is one.
|
||||
* ASSIGN_AND_VERIFY_CI: Similar to VERIFY_CI but do assignment first.
|
||||
*/
|
||||
#define INITIALIZE_CI(ci, mi) do { \
|
||||
(ci) = (!(mi) || (mi)->clean) ? NULL : (struct conflict_info *)(mi); \
|
||||
} while (0)
|
||||
#define VERIFY_CI(ci) assert(ci && !ci->merged.clean);
|
||||
#define ASSIGN_AND_VERIFY_CI(ci, mi) do { \
|
||||
(ci) = (struct conflict_info *)(mi); \
|
||||
assert((ci) && !(mi)->clean); \
|
||||
} while (0)
|
||||
|
||||
static int err(struct merge_options *opt, const char *err, ...)
|
||||
{
|
||||
va_list params;
|
||||
@ -201,6 +221,65 @@ static int err(struct merge_options *opt, const char *err, ...)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void setup_path_info(struct merge_options *opt,
|
||||
struct string_list_item *result,
|
||||
const char *current_dir_name,
|
||||
int current_dir_name_len,
|
||||
char *fullpath, /* we'll take over ownership */
|
||||
struct name_entry *names,
|
||||
struct name_entry *merged_version,
|
||||
unsigned is_null, /* boolean */
|
||||
unsigned df_conflict, /* boolean */
|
||||
unsigned filemask,
|
||||
unsigned dirmask,
|
||||
int resolved /* boolean */)
|
||||
{
|
||||
/* result->util is void*, so mi is a convenience typed variable */
|
||||
struct merged_info *mi;
|
||||
|
||||
assert(!is_null || resolved);
|
||||
assert(!df_conflict || !resolved); /* df_conflict implies !resolved */
|
||||
assert(resolved == (merged_version != NULL));
|
||||
|
||||
mi = xcalloc(1, resolved ? sizeof(struct merged_info) :
|
||||
sizeof(struct conflict_info));
|
||||
mi->directory_name = current_dir_name;
|
||||
mi->basename_offset = current_dir_name_len;
|
||||
mi->clean = !!resolved;
|
||||
if (resolved) {
|
||||
mi->result.mode = merged_version->mode;
|
||||
oidcpy(&mi->result.oid, &merged_version->oid);
|
||||
mi->is_null = !!is_null;
|
||||
} else {
|
||||
int i;
|
||||
struct conflict_info *ci;
|
||||
|
||||
ASSIGN_AND_VERIFY_CI(ci, mi);
|
||||
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
|
||||
ci->pathnames[i] = fullpath;
|
||||
ci->stages[i].mode = names[i].mode;
|
||||
oidcpy(&ci->stages[i].oid, &names[i].oid);
|
||||
}
|
||||
ci->filemask = filemask;
|
||||
ci->dirmask = dirmask;
|
||||
ci->df_conflict = !!df_conflict;
|
||||
if (dirmask)
|
||||
/*
|
||||
* Assume is_null for now, but if we have entries
|
||||
* under the directory then when it is complete in
|
||||
* write_completed_directory() it'll update this.
|
||||
* Also, for D/F conflicts, we have to handle the
|
||||
* directory first, then clear this bit and process
|
||||
* the file to see how it is handled -- that occurs
|
||||
* near the top of process_entry().
|
||||
*/
|
||||
mi->is_null = 1;
|
||||
}
|
||||
strmap_put(&opt->priv->paths, fullpath, mi);
|
||||
result->string = fullpath;
|
||||
result->util = mi;
|
||||
}
|
||||
|
||||
static int collect_merge_info_callback(int n,
|
||||
unsigned long mask,
|
||||
unsigned long dirmask,
|
||||
@ -215,10 +294,12 @@ static int collect_merge_info_callback(int n,
|
||||
*/
|
||||
struct merge_options *opt = info->data;
|
||||
struct merge_options_internal *opti = opt->priv;
|
||||
struct conflict_info *ci;
|
||||
struct string_list_item pi; /* Path Info */
|
||||
struct conflict_info *ci; /* typed alias to pi.util (which is void*) */
|
||||
struct name_entry *p;
|
||||
size_t len;
|
||||
char *fullpath;
|
||||
const char *dirname = opti->current_dir_name;
|
||||
unsigned filemask = mask & ~dirmask;
|
||||
unsigned match_mask = 0; /* will be updated below */
|
||||
unsigned mbase_null = !(mask & 1);
|
||||
@ -287,13 +368,15 @@ static int collect_merge_info_callback(int n,
|
||||
make_traverse_path(fullpath, len + 1, info, p->path, p->pathlen);
|
||||
|
||||
/*
|
||||
* TODO: record information about the path other than all zeros,
|
||||
* so we can resolve later in process_entries.
|
||||
* Record information about the path so we can resolve later in
|
||||
* process_entries.
|
||||
*/
|
||||
ci = xcalloc(1, sizeof(struct conflict_info));
|
||||
ci->df_conflict = df_conflict;
|
||||
setup_path_info(opt, &pi, dirname, info->pathlen, fullpath,
|
||||
names, NULL, 0, df_conflict, filemask, dirmask, 0);
|
||||
|
||||
ci = pi.util;
|
||||
VERIFY_CI(ci);
|
||||
ci->match_mask = match_mask;
|
||||
strmap_put(&opti->paths, fullpath, ci);
|
||||
|
||||
/* If dirmask, recurse into subdirectories */
|
||||
if (dirmask) {
|
||||
@ -337,7 +420,7 @@ static int collect_merge_info_callback(int n,
|
||||
}
|
||||
|
||||
original_dir_name = opti->current_dir_name;
|
||||
opti->current_dir_name = fullpath;
|
||||
opti->current_dir_name = pi.string;
|
||||
ret = traverse_trees(NULL, 3, t, &newinfo);
|
||||
opti->current_dir_name = original_dir_name;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user