17
17
#include "cache.h"
18
18
#include "merge-ort.h"
19
19
20
+ #include "blob.h"
20
21
#include "cache-tree.h"
22
+ #include "commit-reach.h"
21
23
#include "diff.h"
22
24
#include "diffcore.h"
23
25
#include "dir.h"
@@ -56,6 +58,8 @@ struct merge_options_internal {
56
58
* * these keys serve to intern all the path strings, which allows
57
59
* us to do pointer comparison on directory names instead of
58
60
* strcmp; we just have to be careful to use the interned strings.
61
+ * (Technically paths_to_free may track some strings that were
62
+ * removed from froms paths.)
59
63
*
60
64
* The values of paths:
61
65
* * either a pointer to a merged_info, or a conflict_info struct
@@ -90,6 +94,25 @@ struct merge_options_internal {
90
94
*/
91
95
struct strmap conflicted ;
92
96
97
+ /*
98
+ * paths_to_free: additional list of strings to free
99
+ *
100
+ * If keys are removed from "paths", they are added to paths_to_free
101
+ * to ensure they are later freed. We avoid free'ing immediately since
102
+ * other places (e.g. conflict_info.pathnames[]) may still be
103
+ * referencing these paths.
104
+ */
105
+ struct string_list paths_to_free ;
106
+
107
+ /*
108
+ * output: special messages and conflict notices for various paths
109
+ *
110
+ * This is a map of pathnames (a subset of the keys in "paths" above)
111
+ * to strbufs. It gathers various warning/conflict/notice messages
112
+ * for later processing.
113
+ */
114
+ struct strmap output ;
115
+
93
116
/*
94
117
* current_dir_name: temporary var used in collect_merge_info_callback()
95
118
*
@@ -163,6 +186,13 @@ struct conflict_info {
163
186
/* Whether this path is/was involved in a directory/file conflict */
164
187
unsigned df_conflict :1 ;
165
188
189
+ /*
190
+ * Whether this path is/was involved in a non-content conflict other
191
+ * than a directory/file conflict (e.g. rename/rename, rename/delete,
192
+ * file location based on possible directory rename).
193
+ */
194
+ unsigned path_conflict :1 ;
195
+
166
196
/*
167
197
* For filemask and dirmask, the ith bit corresponds to whether the
168
198
* ith entry is a file (filemask) or a directory (dirmask). Thus,
@@ -189,6 +219,8 @@ struct conflict_info {
189
219
unsigned match_mask :3 ;
190
220
};
191
221
222
+ /*** Function Grouping: various utility functions ***/
223
+
192
224
/*
193
225
* For the next three macros, see warning for conflict_info.merged.
194
226
*
@@ -219,6 +251,61 @@ static void free_strmap_strings(struct strmap *map)
219
251
}
220
252
}
221
253
254
+ static void clear_internal_opts (struct merge_options_internal * opti ,
255
+ int reinitialize )
256
+ {
257
+ assert (!reinitialize );
258
+
259
+ /*
260
+ * We marked opti->paths with strdup_strings = 0, so that we
261
+ * wouldn't have to make another copy of the fullpath created by
262
+ * make_traverse_path from setup_path_info(). But, now that we've
263
+ * used it and have no other references to these strings, it is time
264
+ * to deallocate them.
265
+ */
266
+ free_strmap_strings (& opti -> paths );
267
+ strmap_clear (& opti -> paths , 1 );
268
+
269
+ /*
270
+ * All keys and values in opti->conflicted are a subset of those in
271
+ * opti->paths. We don't want to deallocate anything twice, so we
272
+ * don't free the keys and we pass 0 for free_values.
273
+ */
274
+ strmap_clear (& opti -> conflicted , 0 );
275
+
276
+ /*
277
+ * opti->paths_to_free is similar to opti->paths; we created it with
278
+ * strdup_strings = 0 to avoid making _another_ copy of the fullpath
279
+ * but now that we've used it and have no other references to these
280
+ * strings, it is time to deallocate them. We do so by temporarily
281
+ * setting strdup_strings to 1.
282
+ */
283
+ opti -> paths_to_free .strdup_strings = 1 ;
284
+ string_list_clear (& opti -> paths_to_free , 0 );
285
+ opti -> paths_to_free .strdup_strings = 0 ;
286
+
287
+ if (!reinitialize ) {
288
+ struct hashmap_iter iter ;
289
+ struct strmap_entry * e ;
290
+
291
+ /* Release and free each strbuf found in output */
292
+ strmap_for_each_entry (& opti -> output , & iter , e ) {
293
+ struct strbuf * sb = e -> value ;
294
+ strbuf_release (sb );
295
+ /*
296
+ * While strictly speaking we don't need to free(sb)
297
+ * here because we could pass free_values=1 when
298
+ * calling strmap_clear() on opti->output, that would
299
+ * require strmap_clear to do another
300
+ * strmap_for_each_entry() loop, so we just free it
301
+ * while we're iterating anyway.
302
+ */
303
+ free (sb );
304
+ }
305
+ strmap_clear (& opti -> output , 0 );
306
+ }
307
+ }
308
+
222
309
static int err (struct merge_options * opt , const char * err , ...)
223
310
{
224
311
va_list params ;
@@ -235,6 +322,29 @@ static int err(struct merge_options *opt, const char *err, ...)
235
322
return -1 ;
236
323
}
237
324
325
+ __attribute__((format (printf , 4 , 5 )))
326
+ static void path_msg (struct merge_options * opt ,
327
+ const char * path ,
328
+ int omittable_hint , /* skippable under --remerge-diff */
329
+ const char * fmt , ...)
330
+ {
331
+ va_list ap ;
332
+ struct strbuf * sb = strmap_get (& opt -> priv -> output , path );
333
+ if (!sb ) {
334
+ sb = xmalloc (sizeof (* sb ));
335
+ strbuf_init (sb , 0 );
336
+ strmap_put (& opt -> priv -> output , path , sb );
337
+ }
338
+
339
+ va_start (ap , fmt );
340
+ strbuf_vaddf (sb , fmt , ap );
341
+ va_end (ap );
342
+
343
+ strbuf_addch (sb , '\n' );
344
+ }
345
+
346
+ /*** Function Grouping: functions related to collect_merge_info() ***/
347
+
238
348
static void setup_path_info (struct merge_options * opt ,
239
349
struct string_list_item * result ,
240
350
const char * current_dir_name ,
@@ -489,6 +599,27 @@ static int collect_merge_info(struct merge_options *opt,
489
599
return ret ;
490
600
}
491
601
602
+ /*** Function Grouping: functions related to threeway content merges ***/
603
+
604
+ static int handle_content_merge (struct merge_options * opt ,
605
+ const char * path ,
606
+ const struct version_info * o ,
607
+ const struct version_info * a ,
608
+ const struct version_info * b ,
609
+ const char * pathnames [3 ],
610
+ const int extra_marker_size ,
611
+ struct version_info * result )
612
+ {
613
+ die ("Not yet implemented" );
614
+ }
615
+
616
+ /*** Function Grouping: functions related to detect_and_process_renames(), ***
617
+ *** which are split into directory and regular rename detection sections. ***/
618
+
619
+ /*** Function Grouping: functions related to directory rename detection ***/
620
+
621
+ /*** Function Grouping: functions related to regular rename detection ***/
622
+
492
623
static int detect_and_process_renames (struct merge_options * opt ,
493
624
struct tree * merge_base ,
494
625
struct tree * side1 ,
@@ -506,6 +637,8 @@ static int detect_and_process_renames(struct merge_options *opt,
506
637
return clean ;
507
638
}
508
639
640
+ /*** Function Grouping: functions related to process_entries() ***/
641
+
509
642
static int string_list_df_name_compare (const char * one , const char * two )
510
643
{
511
644
int onelen = strlen (one );
@@ -887,9 +1020,27 @@ static void process_entry(struct merge_options *opt,
887
1020
ci -> merged .clean = 0 ;
888
1021
ci -> merged .result .mode = ci -> stages [1 ].mode ;
889
1022
oidcpy (& ci -> merged .result .oid , & ci -> stages [1 ].oid );
1023
+ /* When we fix above, we'll call handle_content_merge() */
1024
+ (void )handle_content_merge ;
890
1025
} else if (ci -> filemask == 3 || ci -> filemask == 5 ) {
891
1026
/* Modify/delete */
892
- die ("Not yet implemented." );
1027
+ const char * modify_branch , * delete_branch ;
1028
+ int side = (ci -> filemask == 5 ) ? 2 : 1 ;
1029
+ int index = opt -> priv -> call_depth ? 0 : side ;
1030
+
1031
+ ci -> merged .result .mode = ci -> stages [index ].mode ;
1032
+ oidcpy (& ci -> merged .result .oid , & ci -> stages [index ].oid );
1033
+ ci -> merged .clean = 0 ;
1034
+
1035
+ modify_branch = (side == 1 ) ? opt -> branch1 : opt -> branch2 ;
1036
+ delete_branch = (side == 1 ) ? opt -> branch2 : opt -> branch1 ;
1037
+
1038
+ path_msg (opt , path , 0 ,
1039
+ _ ("CONFLICT (modify/delete): %s deleted in %s "
1040
+ "and modified in %s. Version %s of %s left "
1041
+ "in tree." ),
1042
+ path , delete_branch , modify_branch ,
1043
+ modify_branch , path );
893
1044
} else if (ci -> filemask == 2 || ci -> filemask == 4 ) {
894
1045
/* Added on one side */
895
1046
int side = (ci -> filemask == 4 ) ? 2 : 1 ;
@@ -984,6 +1135,8 @@ static void process_entries(struct merge_options *opt,
984
1135
string_list_clear (& dir_metadata .offsets , 0 );
985
1136
}
986
1137
1138
+ /*** Function Grouping: functions related to merge_switch_to_result() ***/
1139
+
987
1140
static int checkout (struct merge_options * opt ,
988
1141
struct tree * prev ,
989
1142
struct tree * next )
@@ -1154,7 +1307,29 @@ void merge_switch_to_result(struct merge_options *opt,
1154
1307
}
1155
1308
1156
1309
if (display_update_msgs ) {
1157
- /* TODO: print out CONFLICT and other informational messages. */
1310
+ struct merge_options_internal * opti = result -> priv ;
1311
+ struct hashmap_iter iter ;
1312
+ struct strmap_entry * e ;
1313
+ struct string_list olist = STRING_LIST_INIT_NODUP ;
1314
+ int i ;
1315
+
1316
+ /* Hack to pre-allocate olist to the desired size */
1317
+ ALLOC_GROW (olist .items , strmap_get_size (& opti -> output ),
1318
+ olist .alloc );
1319
+
1320
+ /* Put every entry from output into olist, then sort */
1321
+ strmap_for_each_entry (& opti -> output , & iter , e ) {
1322
+ string_list_append (& olist , e -> key )-> util = e -> value ;
1323
+ }
1324
+ string_list_sort (& olist );
1325
+
1326
+ /* Iterate over the items, printing them */
1327
+ for (i = 0 ; i < olist .nr ; ++ i ) {
1328
+ struct strbuf * sb = olist .items [i ].util ;
1329
+
1330
+ printf ("%s" , sb -> buf );
1331
+ }
1332
+ string_list_clear (& olist , 0 );
1158
1333
}
1159
1334
1160
1335
merge_finalize (opt , result );
@@ -1167,25 +1342,12 @@ void merge_finalize(struct merge_options *opt,
1167
1342
1168
1343
assert (opt -> priv == NULL );
1169
1344
1170
- /*
1171
- * We marked opti->paths with strdup_strings = 0, so that we
1172
- * wouldn't have to make another copy of the fullpath created by
1173
- * make_traverse_path from setup_path_info(). But, now that we've
1174
- * used it and have no other references to these strings, it is time
1175
- * to deallocate them.
1176
- */
1177
- free_strmap_strings (& opti -> paths );
1178
- strmap_clear (& opti -> paths , 1 );
1179
-
1180
- /*
1181
- * All keys and values in opti->conflicted are a subset of those in
1182
- * opti->paths. We don't want to deallocate anything twice, so we
1183
- * don't free the keys and we pass 0 for free_values.
1184
- */
1185
- strmap_clear (& opti -> conflicted , 0 );
1345
+ clear_internal_opts (opti , 0 );
1186
1346
FREE_AND_NULL (opti );
1187
1347
}
1188
1348
1349
+ /*** Function Grouping: helper functions for merge_incore_*() ***/
1350
+
1189
1351
static void merge_start (struct merge_options * opt , struct merge_result * result )
1190
1352
{
1191
1353
/* Sanity checks on opt */
@@ -1226,15 +1388,25 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
1226
1388
* Although we initialize opt->priv->paths with strdup_strings=0,
1227
1389
* that's just to avoid making yet another copy of an allocated
1228
1390
* string. Putting the entry into paths means we are taking
1229
- * ownership, so we will later free it.
1391
+ * ownership, so we will later free it. paths_to_free is similar.
1230
1392
*
1231
1393
* In contrast, conflicted just has a subset of keys from paths, so
1232
1394
* we don't want to free those (it'd be a duplicate free).
1233
1395
*/
1234
1396
strmap_init_with_options (& opt -> priv -> paths , NULL , 0 );
1235
1397
strmap_init_with_options (& opt -> priv -> conflicted , NULL , 0 );
1398
+ string_list_init (& opt -> priv -> paths_to_free , 0 );
1399
+
1400
+ /*
1401
+ * keys & strbufs in output will sometimes need to outlive "paths",
1402
+ * so it will have a copy of relevant keys. It's probably a small
1403
+ * subset of the overall paths that have special output.
1404
+ */
1405
+ strmap_init (& opt -> priv -> output );
1236
1406
}
1237
1407
1408
+ /*** Function Grouping: merge_incore_*() and their internal variants ***/
1409
+
1238
1410
/*
1239
1411
* Originally from merge_trees_internal(); heavily adapted, though.
1240
1412
*/
0 commit comments