@@ -864,6 +864,16 @@ static void get_renamed_dir_portion(const char *old_path, const char *new_path,
864
864
* new_dir = xstrndup (new_path , end_of_new - new_path );
865
865
}
866
866
867
+ static int path_in_way (struct strmap * paths , const char * path , unsigned side_mask )
868
+ {
869
+ struct merged_info * mi = strmap_get (paths , path );
870
+ struct conflict_info * ci ;
871
+ if (!mi )
872
+ return 0 ;
873
+ INITIALIZE_CI (ci , mi );
874
+ return mi -> clean || (side_mask & (ci -> filemask | ci -> dirmask ));
875
+ }
876
+
867
877
/*
868
878
* See if there is a directory rename for path, and if there are any file
869
879
* level conflicts on the given side for the renamed location. If there is
@@ -876,7 +886,67 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
876
886
struct strmap_entry * rename_info ,
877
887
struct strmap * collisions )
878
888
{
879
- die ("Not yet implemented" );
889
+ char * new_path = NULL ;
890
+ struct collision_info * c_info ;
891
+ int clean = 1 ;
892
+ struct strbuf collision_paths = STRBUF_INIT ;
893
+
894
+ /*
895
+ * entry has the mapping of old directory name to new directory name
896
+ * that we want to apply to path.
897
+ */
898
+ new_path = apply_dir_rename (rename_info , path );
899
+ if (!new_path )
900
+ BUG ("Failed to apply directory rename!" );
901
+
902
+ /*
903
+ * The caller needs to have ensured that it has pre-populated
904
+ * collisions with all paths that map to new_path. Do a quick check
905
+ * to ensure that's the case.
906
+ */
907
+ c_info = strmap_get (collisions , new_path );
908
+ if (c_info == NULL )
909
+ BUG ("c_info is NULL" );
910
+
911
+ /*
912
+ * Check for one-sided add/add/.../add conflicts, i.e.
913
+ * where implicit renames from the other side doing
914
+ * directory rename(s) can affect this side of history
915
+ * to put multiple paths into the same location. Warn
916
+ * and bail on directory renames for such paths.
917
+ */
918
+ if (c_info -> reported_already ) {
919
+ clean = 0 ;
920
+ } else if (path_in_way (& opt -> priv -> paths , new_path , 1 << side_index )) {
921
+ c_info -> reported_already = 1 ;
922
+ strbuf_add_separated_string_list (& collision_paths , ", " ,
923
+ & c_info -> source_files );
924
+ path_msg (opt , new_path , 0 ,
925
+ _ ("CONFLICT (implicit dir rename): Existing file/dir "
926
+ "at %s in the way of implicit directory rename(s) "
927
+ "putting the following path(s) there: %s." ),
928
+ new_path , collision_paths .buf );
929
+ clean = 0 ;
930
+ } else if (c_info -> source_files .nr > 1 ) {
931
+ c_info -> reported_already = 1 ;
932
+ strbuf_add_separated_string_list (& collision_paths , ", " ,
933
+ & c_info -> source_files );
934
+ path_msg (opt , new_path , 0 ,
935
+ _ ("CONFLICT (implicit dir rename): Cannot map more "
936
+ "than one path to %s; implicit directory renames "
937
+ "tried to put these paths there: %s" ),
938
+ new_path , collision_paths .buf );
939
+ clean = 0 ;
940
+ }
941
+
942
+ /* Free memory we no longer need */
943
+ strbuf_release (& collision_paths );
944
+ if (!clean && new_path ) {
945
+ free (new_path );
946
+ return NULL ;
947
+ }
948
+
949
+ return new_path ;
880
950
}
881
951
882
952
static void increment_count (struct strmap * dir_rename_count ,
0 commit comments