Code

merge-recursive: Save D/F conflict filenames instead of unlinking them
authorElijah Newren <newren@gmail.com>
Fri, 12 Aug 2011 05:19:58 +0000 (23:19 -0600)
committerJunio C Hamano <gitster@pobox.com>
Sun, 14 Aug 2011 21:19:35 +0000 (14:19 -0700)
Rename make_room_for_directories_of_df_conflicts() to
record_df_conflict_files() to reflect the change in functionality.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
merge-recursive.c
merge-recursive.h

index 3515ece55a508068f0eb85f135eeb51cd21c7dab..99c38d55140604f2287835afca82c91d2bb29a60 100644 (file)
@@ -360,20 +360,24 @@ static int string_list_df_name_compare(const void *a, const void *b)
        return onelen - twolen;
 }
 
-
-
-static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
-                                                     struct string_list *entries)
+static void record_df_conflict_files(struct merge_options *o,
+                                    struct string_list *entries)
 {
-       /* If there are D/F conflicts, and the paths currently exist
-        * in the working copy as a file, we want to remove them to
-        * make room for the corresponding directory.  Such paths will
-        * later be processed in process_df_entry() at the end.  If
-        * the corresponding directory ends up being removed by the
-        * merge, then the file will be reinstated at that time;
-        * otherwise, if the file is not supposed to be removed by the
-        * merge, the contents of the file will be placed in another
-        * unique filename.
+       /* If there is a D/F conflict and the file for such a conflict
+        * currently exist in the working copy, we want to allow it to
+        * be removed to make room for the corresponding directory if
+        * needed.  The files underneath the directories of such D/F
+        * conflicts will be handled in process_entry(), while the
+        * files of such D/F conflicts will be processed later in
+        * process_df_entry().  If the corresponding directory ends up
+        * being removed by the merge, then no additional work needs
+        * to be done by process_df_entry() for the conflicting file.
+        * If the directory needs to be written to the working copy,
+        * then the conflicting file will simply be removed (e.g. in
+        * make_room_for_path).  If the directory is written to the
+        * working copy but the file also has a conflict that needs to
+        * be resolved, then process_df_entry() will reinstate the
+        * file with a new unique name.
         */
        const char *last_file = NULL;
        int last_len = 0;
@@ -390,6 +394,7 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
        qsort(entries->items, entries->nr, sizeof(*entries->items),
              string_list_df_name_compare);
 
+       string_list_clear(&o->df_conflict_file_set, 1);
        for (i = 0; i < entries->nr; i++) {
                const char *path = entries->items[i].string;
                int len = strlen(path);
@@ -398,14 +403,15 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
                /*
                 * Check if last_file & path correspond to a D/F conflict;
                 * i.e. whether path is last_file+'/'+<something>.
-                * If so, remove last_file to make room for path and friends.
+                * If so, record that it's okay to remove last_file to make
+                * room for path and friends if needed.
                 */
                if (last_file &&
                    len > last_len &&
                    memcmp(path, last_file, last_len) == 0 &&
                    path[last_len] == '/') {
                        output(o, 3, "Removing %s to make room for subdirectory; may re-add later.", last_file);
-                       unlink(last_file);
+                       string_list_insert(&o->df_conflict_file_set, last_file);
                }
 
                /*
@@ -1569,7 +1575,7 @@ int merge_trees(struct merge_options *o,
                get_files_dirs(o, merge);
 
                entries = get_unmerged();
-               make_room_for_directories_of_df_conflicts(o, entries);
+               record_df_conflict_files(o, entries);
                re_head  = get_renames(o, head, common, head, merge, entries);
                re_merge = get_renames(o, merge, common, head, merge, entries);
                clean = process_renames(o, re_head, re_merge);
@@ -1795,6 +1801,8 @@ void init_merge_options(struct merge_options *o)
        o->current_file_set.strdup_strings = 1;
        memset(&o->current_directory_set, 0, sizeof(struct string_list));
        o->current_directory_set.strdup_strings = 1;
+       memset(&o->df_conflict_file_set, 0, sizeof(struct string_list));
+       o->df_conflict_file_set.strdup_strings = 1;
 }
 
 int parse_merge_opt(struct merge_options *o, const char *s)
index 7e1e972b13cb8a9f2fae084f769fffede24c8dbb..58f3435e9e854ab82c2fd0c10c55520bc69e5ed0 100644 (file)
@@ -26,6 +26,7 @@ struct merge_options {
        struct strbuf obuf;
        struct string_list current_file_set;
        struct string_list current_directory_set;
+       struct string_list df_conflict_file_set;
 };
 
 /* merge_trees() but with recursive ancestor consolidation */