merge-recursive: Don't re-sort a list whose order we depend upon
authorElijah Newren <newren@gmail.com>
Sat, 13 Aug 2011 02:23:51 +0000 (20:23 -0600)
committerJunio C Hamano <gitster@pobox.com>
Sun, 14 Aug 2011 21:27:48 +0000 (14:27 -0700)
In record_df_conflict_files() we would resort the entries list using
df_name_compare to get a convenient ordering.  Unfortunately, this broke
assumptions of the get_renames() code (via string_list_lookup() calls)
which needed the list to be in the standard ordering.  When those lookups
would fail, duplicate stage_data entries could be inserted, causing the
process_renames and process_entry code to fail (in particular, a path that
that process_renames had marked as processed would still be processed
anyway in process_entry due to the duplicate entry).

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

index 78555b6a39959b54be600cda1a5dce4e0e18ac0f..d60fd7a0cd61e1aad72779da0827136300a91bb9 100644 (file)
@@ -400,6 +400,7 @@ static void record_df_conflict_files(struct merge_options *o,
         * and the file need to be present, then the D/F file will be
         * reinstated with a new unique name at the time it is processed.
         */
+       struct string_list df_sorted_entries;
        const char *last_file = NULL;
        int last_len = 0;
        int i;
@@ -412,14 +413,20 @@ static void record_df_conflict_files(struct merge_options *o,
                return;
 
        /* Ensure D/F conflicts are adjacent in the entries list. */
-       qsort(entries->items, entries->nr, sizeof(*entries->items),
+       memset(&df_sorted_entries, 0, sizeof(struct string_list));
+       for (i = 0; i < entries->nr; i++) {
+               struct string_list_item *next = &entries->items[i];
+               string_list_append(&df_sorted_entries, next->string)->util =
+                                  next->util;
+       }
+       qsort(df_sorted_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;
+       for (i = 0; i < df_sorted_entries.nr; i++) {
+               const char *path = df_sorted_entries.items[i].string;
                int len = strlen(path);
-               struct stage_data *e = entries->items[i].util;
+               struct stage_data *e = df_sorted_entries.items[i].util;
 
                /*
                 * Check if last_file & path correspond to a D/F conflict;
@@ -447,6 +454,7 @@ static void record_df_conflict_files(struct merge_options *o,
                        last_file = NULL;
                }
        }
+       string_list_clear(&df_sorted_entries, 0);
 }
 
 struct rename {