Skip to content

Commit 98bf984

Browse files
newrengitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 34e557a commit 98bf984

File tree

1 file changed

+90
-7
lines changed

1 file changed

+90
-7
lines changed

merge-ort.c

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,26 @@ struct conflict_info {
185185
unsigned match_mask:3;
186186
};
187187

188+
/*
189+
* For the next three macros, see warning for conflict_info.merged.
190+
*
191+
* In each of the below, mi is a struct merged_info*, and ci was defined
192+
* as a struct conflict_info* (but we need to verify ci isn't actually
193+
* pointed at a struct merged_info*).
194+
*
195+
* INITIALIZE_CI: Assign ci to mi but only if it's safe; set to NULL otherwise.
196+
* VERIFY_CI: Ensure that something we assigned to a conflict_info* is one.
197+
* ASSIGN_AND_VERIFY_CI: Similar to VERIFY_CI but do assignment first.
198+
*/
199+
#define INITIALIZE_CI(ci, mi) do { \
200+
(ci) = (!(mi) || (mi)->clean) ? NULL : (struct conflict_info *)(mi); \
201+
} while (0)
202+
#define VERIFY_CI(ci) assert(ci && !ci->merged.clean);
203+
#define ASSIGN_AND_VERIFY_CI(ci, mi) do { \
204+
(ci) = (struct conflict_info *)(mi); \
205+
assert((ci) && !(mi)->clean); \
206+
} while (0)
207+
188208
static int err(struct merge_options *opt, const char *err, ...)
189209
{
190210
va_list params;
@@ -201,6 +221,65 @@ static int err(struct merge_options *opt, const char *err, ...)
201221
return -1;
202222
}
203223

224+
static void setup_path_info(struct merge_options *opt,
225+
struct string_list_item *result,
226+
const char *current_dir_name,
227+
int current_dir_name_len,
228+
char *fullpath, /* we'll take over ownership */
229+
struct name_entry *names,
230+
struct name_entry *merged_version,
231+
unsigned is_null, /* boolean */
232+
unsigned df_conflict, /* boolean */
233+
unsigned filemask,
234+
unsigned dirmask,
235+
int resolved /* boolean */)
236+
{
237+
/* result->util is void*, so mi is a convenience typed variable */
238+
struct merged_info *mi;
239+
240+
assert(!is_null || resolved);
241+
assert(!df_conflict || !resolved); /* df_conflict implies !resolved */
242+
assert(resolved == (merged_version != NULL));
243+
244+
mi = xcalloc(1, resolved ? sizeof(struct merged_info) :
245+
sizeof(struct conflict_info));
246+
mi->directory_name = current_dir_name;
247+
mi->basename_offset = current_dir_name_len;
248+
mi->clean = !!resolved;
249+
if (resolved) {
250+
mi->result.mode = merged_version->mode;
251+
oidcpy(&mi->result.oid, &merged_version->oid);
252+
mi->is_null = !!is_null;
253+
} else {
254+
int i;
255+
struct conflict_info *ci;
256+
257+
ASSIGN_AND_VERIFY_CI(ci, mi);
258+
for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
259+
ci->pathnames[i] = fullpath;
260+
ci->stages[i].mode = names[i].mode;
261+
oidcpy(&ci->stages[i].oid, &names[i].oid);
262+
}
263+
ci->filemask = filemask;
264+
ci->dirmask = dirmask;
265+
ci->df_conflict = !!df_conflict;
266+
if (dirmask)
267+
/*
268+
* Assume is_null for now, but if we have entries
269+
* under the directory then when it is complete in
270+
* write_completed_directory() it'll update this.
271+
* Also, for D/F conflicts, we have to handle the
272+
* directory first, then clear this bit and process
273+
* the file to see how it is handled -- that occurs
274+
* near the top of process_entry().
275+
*/
276+
mi->is_null = 1;
277+
}
278+
strmap_put(&opt->priv->paths, fullpath, mi);
279+
result->string = fullpath;
280+
result->util = mi;
281+
}
282+
204283
static int collect_merge_info_callback(int n,
205284
unsigned long mask,
206285
unsigned long dirmask,
@@ -215,10 +294,12 @@ static int collect_merge_info_callback(int n,
215294
*/
216295
struct merge_options *opt = info->data;
217296
struct merge_options_internal *opti = opt->priv;
218-
struct conflict_info *ci;
297+
struct string_list_item pi; /* Path Info */
298+
struct conflict_info *ci; /* typed alias to pi.util (which is void*) */
219299
struct name_entry *p;
220300
size_t len;
221301
char *fullpath;
302+
const char *dirname = opti->current_dir_name;
222303
unsigned filemask = mask & ~dirmask;
223304
unsigned match_mask = 0; /* will be updated below */
224305
unsigned mbase_null = !(mask & 1);
@@ -287,13 +368,15 @@ static int collect_merge_info_callback(int n,
287368
make_traverse_path(fullpath, len + 1, info, p->path, p->pathlen);
288369

289370
/*
290-
* TODO: record information about the path other than all zeros,
291-
* so we can resolve later in process_entries.
371+
* Record information about the path so we can resolve later in
372+
* process_entries.
292373
*/
293-
ci = xcalloc(1, sizeof(struct conflict_info));
294-
ci->df_conflict = df_conflict;
374+
setup_path_info(opt, &pi, dirname, info->pathlen, fullpath,
375+
names, NULL, 0, df_conflict, filemask, dirmask, 0);
376+
377+
ci = pi.util;
378+
VERIFY_CI(ci);
295379
ci->match_mask = match_mask;
296-
strmap_put(&opti->paths, fullpath, ci);
297380

298381
/* If dirmask, recurse into subdirectories */
299382
if (dirmask) {
@@ -337,7 +420,7 @@ static int collect_merge_info_callback(int n,
337420
}
338421

339422
original_dir_name = opti->current_dir_name;
340-
opti->current_dir_name = fullpath;
423+
opti->current_dir_name = pi.string;
341424
ret = traverse_trees(NULL, 3, t, &newinfo);
342425
opti->current_dir_name = original_dir_name;
343426

0 commit comments

Comments
 (0)