3
3
#include "xdiff-interface.h"
4
4
#include "blob.h"
5
5
#include "exec_cmd.h"
6
- #include "merge-file .h"
6
+ #include "merge-blobs .h"
7
7
8
8
static const char merge_tree_usage [] = "git merge-tree <base-tree> <branch1> <branch2>" ;
9
- static int resolve_directories = 1 ;
10
9
11
10
struct merge_list {
12
11
struct merge_list * next ;
13
12
struct merge_list * link ; /* other stages for this object */
14
13
15
- unsigned int stage : 2 ,
16
- flags : 30 ;
14
+ unsigned int stage : 2 ;
17
15
unsigned int mode ;
18
16
const char * path ;
19
17
struct blob * blob ;
@@ -27,7 +25,7 @@ static void add_merge_entry(struct merge_list *entry)
27
25
merge_result_end = & entry -> next ;
28
26
}
29
27
30
- static void merge_trees (struct tree_desc t [3 ], const char * base );
28
+ static void merge_trees_recursive (struct tree_desc t [3 ], const char * base , int df_conflict );
31
29
32
30
static const char * explanation (struct merge_list * entry )
33
31
{
@@ -76,7 +74,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
76
74
their = NULL ;
77
75
if (entry )
78
76
their = entry -> blob ;
79
- return merge_file (path , base , our , their , size );
77
+ return merge_blobs (path , base , our , their , size );
80
78
}
81
79
82
80
static void * origin (struct merge_list * entry , unsigned long * size )
@@ -174,52 +172,53 @@ static char *traverse_path(const struct traverse_info *info, const struct name_e
174
172
return make_traverse_path (path , info , n );
175
173
}
176
174
177
- static void resolve (const struct traverse_info * info , struct name_entry * branch1 , struct name_entry * result )
175
+ static void resolve (const struct traverse_info * info , struct name_entry * ours , struct name_entry * result )
178
176
{
179
177
struct merge_list * orig , * final ;
180
178
const char * path ;
181
179
182
- /* If it's already branch1 , don't bother showing it */
183
- if (!branch1 )
180
+ /* If it's already ours , don't bother showing it */
181
+ if (!ours )
184
182
return ;
185
183
186
184
path = traverse_path (info , result );
187
- orig = create_entry (2 , branch1 -> mode , branch1 -> sha1 , path );
185
+ orig = create_entry (2 , ours -> mode , ours -> sha1 , path );
188
186
final = create_entry (0 , result -> mode , result -> sha1 , path );
189
187
190
188
final -> link = orig ;
191
189
192
190
add_merge_entry (final );
193
191
}
194
192
195
- static int unresolved_directory (const struct traverse_info * info , struct name_entry n [3 ])
193
+ static void unresolved_directory (const struct traverse_info * info , struct name_entry n [3 ],
194
+ int df_conflict )
196
195
{
197
196
char * newbase ;
198
197
struct name_entry * p ;
199
198
struct tree_desc t [3 ];
200
199
void * buf0 , * buf1 , * buf2 ;
201
200
202
- if (!resolve_directories )
203
- return 0 ;
204
- p = n ;
205
- if (!p -> mode ) {
206
- p ++ ;
207
- if (!p -> mode )
208
- p ++ ;
201
+ for (p = n ; p < n + 3 ; p ++ ) {
202
+ if (p -> mode && S_ISDIR (p -> mode ))
203
+ break ;
209
204
}
210
- if (!S_ISDIR (p -> mode ))
211
- return 0 ;
205
+ if (n + 3 <= p )
206
+ return ; /* there is no tree here */
207
+
212
208
newbase = traverse_path (info , p );
213
- buf0 = fill_tree_descriptor (t + 0 , n [0 ].sha1 );
214
- buf1 = fill_tree_descriptor (t + 1 , n [1 ].sha1 );
215
- buf2 = fill_tree_descriptor (t + 2 , n [2 ].sha1 );
216
- merge_trees (t , newbase );
209
+
210
+ #define ENTRY_SHA1 (e ) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->sha1 : NULL)
211
+ buf0 = fill_tree_descriptor (t + 0 , ENTRY_SHA1 (n + 0 ));
212
+ buf1 = fill_tree_descriptor (t + 1 , ENTRY_SHA1 (n + 1 ));
213
+ buf2 = fill_tree_descriptor (t + 2 , ENTRY_SHA1 (n + 2 ));
214
+ #undef ENTRY_SHA1
215
+
216
+ merge_trees_recursive (t , newbase , df_conflict );
217
217
218
218
free (buf0 );
219
219
free (buf1 );
220
220
free (buf2 );
221
221
free (newbase );
222
- return 1 ;
223
222
}
224
223
225
224
@@ -242,18 +241,26 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info
242
241
static void unresolved (const struct traverse_info * info , struct name_entry n [3 ])
243
242
{
244
243
struct merge_list * entry = NULL ;
244
+ int i ;
245
+ unsigned dirmask = 0 , mask = 0 ;
246
+
247
+ for (i = 0 ; i < 3 ; i ++ ) {
248
+ mask |= (1 << 1 );
249
+ if (n [i ].mode && S_ISDIR (n [i ].mode ))
250
+ dirmask |= (1 << i );
251
+ }
245
252
246
- if (unresolved_directory (info , n ))
253
+ unresolved_directory (info , n , dirmask && (dirmask != mask ));
254
+
255
+ if (dirmask == mask )
247
256
return ;
248
257
249
- /*
250
- * Do them in reverse order so that the resulting link
251
- * list has the stages in order - link_entry adds new
252
- * links at the front.
253
- */
254
- entry = link_entry (3 , info , n + 2 , entry );
255
- entry = link_entry (2 , info , n + 1 , entry );
256
- entry = link_entry (1 , info , n + 0 , entry );
258
+ if (n [2 ].mode && !S_ISDIR (n [2 ].mode ))
259
+ entry = link_entry (3 , info , n + 2 , entry );
260
+ if (n [1 ].mode && !S_ISDIR (n [1 ].mode ))
261
+ entry = link_entry (2 , info , n + 1 , entry );
262
+ if (n [0 ].mode && !S_ISDIR (n [0 ].mode ))
263
+ entry = link_entry (1 , info , n + 0 , entry );
257
264
258
265
add_merge_entry (entry );
259
266
}
@@ -292,20 +299,29 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
292
299
/* Same in both? */
293
300
if (same_entry (entry + 1 , entry + 2 )) {
294
301
if (entry [0 ].sha1 ) {
302
+ /* Modified identically */
295
303
resolve (info , NULL , entry + 1 );
296
304
return mask ;
297
305
}
306
+ /* "Both added the same" is left unresolved */
298
307
}
299
308
300
309
if (same_entry (entry + 0 , entry + 1 )) {
301
310
if (entry [2 ].sha1 && !S_ISDIR (entry [2 ].mode )) {
311
+ /* We did not touch, they modified -- take theirs */
302
312
resolve (info , entry + 1 , entry + 2 );
303
313
return mask ;
304
314
}
315
+ /*
316
+ * If we did not touch a directory but they made it
317
+ * into a file, we fall through and unresolved()
318
+ * recurses down. Likewise for the opposite case.
319
+ */
305
320
}
306
321
307
322
if (same_entry (entry + 0 , entry + 2 )) {
308
323
if (entry [1 ].sha1 && !S_ISDIR (entry [1 ].mode )) {
324
+ /* We modified, they did not touch -- take ours */
309
325
resolve (info , NULL , entry + 1 );
310
326
return mask ;
311
327
}
@@ -315,15 +331,21 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
315
331
return mask ;
316
332
}
317
333
318
- static void merge_trees (struct tree_desc t [3 ], const char * base )
334
+ static void merge_trees_recursive (struct tree_desc t [3 ], const char * base , int df_conflict )
319
335
{
320
336
struct traverse_info info ;
321
337
322
338
setup_traverse_info (& info , base );
339
+ info .data = & df_conflict ;
323
340
info .fn = threeway_callback ;
324
341
traverse_trees (3 , t , & info );
325
342
}
326
343
344
+ static void merge_trees (struct tree_desc t [3 ], const char * base )
345
+ {
346
+ merge_trees_recursive (t , base , 0 );
347
+ }
348
+
327
349
static void * get_tree_descriptor (struct tree_desc * desc , const char * rev )
328
350
{
329
351
unsigned char sha1 [20 ];
0 commit comments