@@ -25,7 +25,7 @@ static void add_merge_entry(struct merge_list *entry)
2525 merge_result_end = & entry -> next ;
2626}
2727
28- 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 );
2929
3030static const char * explanation (struct merge_list * entry )
3131{
@@ -190,41 +190,35 @@ static void resolve(const struct traverse_info *info, struct name_entry *ours, s
190190 add_merge_entry (final );
191191}
192192
193- 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 )
194195{
195196 char * newbase ;
196197 struct name_entry * p ;
197198 struct tree_desc t [3 ];
198199 void * buf0 , * buf1 , * buf2 ;
199200
200- p = n ;
201- if (!p -> mode ) {
202- p ++ ;
203- if (!p -> mode )
204- p ++ ;
201+ for (p = n ; p < n + 3 ; p ++ ) {
202+ if (p -> mode && S_ISDIR (p -> mode ))
203+ break ;
205204 }
206- if (!S_ISDIR (p -> mode ))
207- return 0 ;
208- /*
209- * NEEDSWORK: this is broken. The path can originally be a file
210- * and then one side may have turned it into a directory, in which
211- * case we return and let the three-way merge as if the tree were
212- * a regular file. If the path that was originally a tree is
213- * now a file in either branch, fill_tree_descriptor() below will
214- * die when fed a blob sha1.
215- */
205+ if (n + 3 <= p )
206+ return ; /* there is no tree here */
216207
217208 newbase = traverse_path (info , p );
218- buf0 = fill_tree_descriptor (t + 0 , n [0 ].sha1 );
219- buf1 = fill_tree_descriptor (t + 1 , n [1 ].sha1 );
220- buf2 = fill_tree_descriptor (t + 2 , n [2 ].sha1 );
221- 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 );
222217
223218 free (buf0 );
224219 free (buf1 );
225220 free (buf2 );
226221 free (newbase );
227- return 1 ;
228222}
229223
230224
@@ -247,18 +241,26 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info
247241static void unresolved (const struct traverse_info * info , struct name_entry n [3 ])
248242{
249243 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+ }
252+
253+ unresolved_directory (info , n , dirmask && (dirmask != mask ));
250254
251- if (unresolved_directory ( info , n ) )
255+ if (dirmask == mask )
252256 return ;
253257
254- /*
255- * Do them in reverse order so that the resulting link
256- * list has the stages in order - link_entry adds new
257- * links at the front.
258- */
259- entry = link_entry (3 , info , n + 2 , entry );
260- entry = link_entry (2 , info , n + 1 , entry );
261- 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 );
262264
263265 add_merge_entry (entry );
264266}
@@ -329,15 +331,21 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
329331 return mask ;
330332}
331333
332- 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 )
333335{
334336 struct traverse_info info ;
335337
336338 setup_traverse_info (& info , base );
339+ info .data = & df_conflict ;
337340 info .fn = threeway_callback ;
338341 traverse_trees (3 , t , & info );
339342}
340343
344+ static void merge_trees (struct tree_desc t [3 ], const char * base )
345+ {
346+ merge_trees_recursive (t , base , 0 );
347+ }
348+
341349static void * get_tree_descriptor (struct tree_desc * desc , const char * rev )
342350{
343351 unsigned char sha1 [20 ];
0 commit comments