@@ -185,6 +185,26 @@ struct conflict_info {
185
185
unsigned match_mask :3 ;
186
186
};
187
187
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
+
188
208
static int err (struct merge_options * opt , const char * err , ...)
189
209
{
190
210
va_list params ;
@@ -201,6 +221,65 @@ static int err(struct merge_options *opt, const char *err, ...)
201
221
return -1 ;
202
222
}
203
223
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
+
204
283
static int collect_merge_info_callback (int n ,
205
284
unsigned long mask ,
206
285
unsigned long dirmask ,
@@ -215,10 +294,12 @@ static int collect_merge_info_callback(int n,
215
294
*/
216
295
struct merge_options * opt = info -> data ;
217
296
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*) */
219
299
struct name_entry * p ;
220
300
size_t len ;
221
301
char * fullpath ;
302
+ const char * dirname = opti -> current_dir_name ;
222
303
unsigned filemask = mask & ~dirmask ;
223
304
unsigned match_mask = 0 ; /* will be updated below */
224
305
unsigned mbase_null = !(mask & 1 );
@@ -287,13 +368,15 @@ static int collect_merge_info_callback(int n,
287
368
make_traverse_path (fullpath , len + 1 , info , p -> path , p -> pathlen );
288
369
289
370
/*
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.
292
373
*/
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 );
295
379
ci -> match_mask = match_mask ;
296
- strmap_put (& opti -> paths , fullpath , ci );
297
380
298
381
/* If dirmask, recurse into subdirectories */
299
382
if (dirmask ) {
@@ -337,7 +420,7 @@ static int collect_merge_info_callback(int n,
337
420
}
338
421
339
422
original_dir_name = opti -> current_dir_name ;
340
- opti -> current_dir_name = fullpath ;
423
+ opti -> current_dir_name = pi . string ;
341
424
ret = traverse_trees (NULL , 3 , t , & newinfo );
342
425
opti -> current_dir_name = original_dir_name ;
343
426
0 commit comments