]> git.ipfire.org Git - thirdparty/git.git/commitdiff
diffcore-rename: add computation of number of unknown renames
authorElijah Newren <newren@gmail.com>
Sat, 13 Mar 2021 22:22:06 +0000 (22:22 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Mar 2021 21:32:56 +0000 (14:32 -0700)
The previous commit can only be effective if we have a computation of
the number of paths under a given directory which are still have pending
renames, and expected this number to be recorded in the dir_rename_count
map under the key UNKNOWN_DIR.  Add the code necessary to compute these
values.

Note that this change means dir_rename_count might have a directory
whose only entry (for UNKNOWN_DIR) was removed by the time merge-ort
goes to check it.  To account for this, merge-ort needs to check for the
case where the max count is 0.

With this change we are now computing the necessary value for each
directory in dirs_removed, but are not using that value anywhere.  The
next two commits will make use of the values stored in dirs_removed in
order to compute whether each relevant_source (that is needed only for
directory rename detection) has become unnecessary.

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

index 8fa29076e0aaa86ad72d8c3b98897ce17ea453b2..9844cd48788e93dfcb0d0449d530e44807d0f8de 100644 (file)
@@ -699,7 +699,8 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
        /*
         * Although dir_rename_count was passed in
         * diffcore_rename_extended() and we want to keep it around and
-        * return it to that caller, we first want to remove any data
+        * return it to that caller, we first want to remove any counts in
+        * the maps associated with UNKNOWN_DIR entries and any data
         * associated with directories that weren't renamed.
         */
        strmap_for_each_entry(info->dir_rename_count, &iter, entry) {
@@ -711,6 +712,9 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
                        strintmap_clear(counts);
                        continue;
                }
+
+               if (strintmap_contains(counts, UNKNOWN_DIR))
+                       strintmap_remove(counts, UNKNOWN_DIR);
        }
        for (i = 0; i < to_remove.nr; ++i)
                strmap_remove(info->dir_rename_count,
@@ -1125,6 +1129,7 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
         * a majority.
         */
 
+       int i;
        struct hashmap_iter iter;
        struct strmap_entry *entry;
 
@@ -1134,10 +1139,38 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
                return; /* culling incompatbile with break detection */
 
        /*
-        * FIXME: Supplement dir_rename_count with number of potential
-        * renames, marking all potential rename sources as mapping to
-        * UNKNOWN_DIR.
+        * Supplement dir_rename_count with number of potential renames,
+        * marking all potential rename sources as mapping to UNKNOWN_DIR.
         */
+       for (i = 0; i < rename_src_nr; i++) {
+               char *old_dir;
+               struct diff_filespec *one = rename_src[i].p->one;
+
+               /*
+                * sources that are part of a rename will have already been
+                * removed by a prior call to remove_unneeded_paths_from_src()
+                */
+               assert(!one->rename_used);
+
+               old_dir = get_dirname(one->path);
+               while (*old_dir != '\0' &&
+                      NOT_RELEVANT != strintmap_get(dirs_removed, old_dir)) {
+                       char *freeme = old_dir;
+
+                       increment_count(info, old_dir, UNKNOWN_DIR);
+                       old_dir = get_dirname(old_dir);
+
+                       /* Free resources we don't need anymore */
+                       free(freeme);
+               }
+               /*
+                * old_dir and new_dir free'd in increment_count, but
+                * get_dirname() gives us a new pointer we need to free for
+                * old_dir.  Also, if the loop runs 0 times we need old_dir
+                * to be freed.
+                */
+               free(old_dir);
+       }
 
        /*
         * For any directory which we need a potential rename detected for
index e2606c73ad884671ddc4762bbb66f416fc76ee63..f2b259986e2288afea0ca795890cffc22dbdf46e 100644 (file)
@@ -1546,6 +1546,9 @@ static void get_provisional_directory_renames(struct merge_options *opt,
                        }
                }
 
+               if (max == 0)
+                       continue;
+
                if (bad_max == max) {
                        path_msg(opt, source_dir, 0,
                               _("CONFLICT (directory rename split): "