git
/
diffcore-rename.c
1724 строки · 51.5 Кб
1/*
2*
3* Copyright (C) 2005 Junio C Hamano
4*/
5
6#define USE_THE_REPOSITORY_VARIABLE7
8#include "git-compat-util.h"9#include "diff.h"10#include "diffcore.h"11#include "object-store-ll.h"12#include "hashmap.h"13#include "mem-pool.h"14#include "oid-array.h"15#include "progress.h"16#include "promisor-remote.h"17#include "string-list.h"18#include "strmap.h"19#include "trace2.h"20
21/* Table of rename/copy destinations */
22
23static struct diff_rename_dst {24struct diff_filepair *p;25struct diff_filespec *filespec_to_free;26int is_rename; /* false -> just a create; true -> rename or copy */27} *rename_dst;28static int rename_dst_nr, rename_dst_alloc;29/* Mapping from break source pathname to break destination index */
30static struct strintmap *break_idx = NULL;31
32static struct diff_rename_dst *locate_rename_dst(struct diff_filepair *p)33{
34/* Lookup by p->ONE->path */35int idx = break_idx ? strintmap_get(break_idx, p->one->path) : -1;36return (idx == -1) ? NULL : &rename_dst[idx];37}
38
39/*
40* Returns 0 on success, -1 if we found a duplicate.
41*/
42static int add_rename_dst(struct diff_filepair *p)43{
44ALLOC_GROW(rename_dst, rename_dst_nr + 1, rename_dst_alloc);45rename_dst[rename_dst_nr].p = p;46rename_dst[rename_dst_nr].filespec_to_free = NULL;47rename_dst[rename_dst_nr].is_rename = 0;48rename_dst_nr++;49return 0;50}
51
52/* Table of rename/copy src files */
53static struct diff_rename_src {54struct diff_filepair *p;55unsigned short score; /* to remember the break score */56} *rename_src;57static int rename_src_nr, rename_src_alloc;58
59static void register_rename_src(struct diff_filepair *p)60{
61if (p->broken_pair) {62if (!break_idx) {63break_idx = xmalloc(sizeof(*break_idx));64strintmap_init_with_options(break_idx, -1, NULL, 0);65}66strintmap_set(break_idx, p->one->path, rename_dst_nr);67}68
69ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);70rename_src[rename_src_nr].p = p;71rename_src[rename_src_nr].score = p->score;72rename_src_nr++;73}
74
75static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)76{
77int src_len = strlen(src->path), dst_len = strlen(dst->path);78while (src_len && dst_len) {79char c1 = src->path[--src_len];80char c2 = dst->path[--dst_len];81if (c1 != c2)82return 0;83if (c1 == '/')84return 1;85}86return (!src_len || src->path[src_len - 1] == '/') &&87(!dst_len || dst->path[dst_len - 1] == '/');88}
89
90struct diff_score {91int src; /* index in rename_src */92int dst; /* index in rename_dst */93unsigned short score;94short name_score;95};96
97struct inexact_prefetch_options {98struct repository *repo;99int skip_unmodified;100};101static void inexact_prefetch(void *prefetch_options)102{
103struct inexact_prefetch_options *options = prefetch_options;104int i;105struct oid_array to_fetch = OID_ARRAY_INIT;106
107for (i = 0; i < rename_dst_nr; i++) {108if (rename_dst[i].p->renamed_pair)109/*110* The loop in diffcore_rename() will not need these
111* blobs, so skip prefetching.
112*/
113continue; /* already found exact match */114diff_add_if_missing(options->repo, &to_fetch,115rename_dst[i].p->two);116}117for (i = 0; i < rename_src_nr; i++) {118if (options->skip_unmodified &&119diff_unmodified_pair(rename_src[i].p))120/*121* The loop in diffcore_rename() will not need these
122* blobs, so skip prefetching.
123*/
124continue;125diff_add_if_missing(options->repo, &to_fetch,126rename_src[i].p->one);127}128promisor_remote_get_direct(options->repo, to_fetch.oid, to_fetch.nr);129oid_array_clear(&to_fetch);130}
131
132static int estimate_similarity(struct repository *r,133struct diff_filespec *src,134struct diff_filespec *dst,135int minimum_score,136struct diff_populate_filespec_options *dpf_opt)137{
138/* src points at a file that existed in the original tree (or139* optionally a file in the destination tree) and dst points
140* at a newly created file. They may be quite similar, in which
141* case we want to say src is renamed to dst or src is copied into
142* dst, and then some edit has been applied to dst.
143*
144* Compare them and return how similar they are, representing
145* the score as an integer between 0 and MAX_SCORE.
146*
147* When there is an exact match, it is considered a better
148* match than anything else; the destination does not even
149* call into this function in that case.
150*/
151unsigned long max_size, delta_size, base_size, src_copied, literal_added;152int score;153
154/* We deal only with regular files. Symlink renames are handled155* only when they are exact matches --- in other words, no edits
156* after renaming.
157*/
158if (!S_ISREG(src->mode) || !S_ISREG(dst->mode))159return 0;160
161/*162* Need to check that source and destination sizes are
163* filled in before comparing them.
164*
165* If we already have "cnt_data" filled in, we know it's
166* all good (avoid checking the size for zero, as that
167* is a possible size - we really should have a flag to
168* say whether the size is valid or not!)
169*/
170dpf_opt->check_size_only = 1;171
172if (!src->cnt_data &&173diff_populate_filespec(r, src, dpf_opt))174return 0;175if (!dst->cnt_data &&176diff_populate_filespec(r, dst, dpf_opt))177return 0;178
179max_size = ((src->size > dst->size) ? src->size : dst->size);180base_size = ((src->size < dst->size) ? src->size : dst->size);181delta_size = max_size - base_size;182
183/* We would not consider edits that change the file size so184* drastically. delta_size must be smaller than
185* (MAX_SCORE-minimum_score)/MAX_SCORE * min(src->size, dst->size).
186*
187* Note that base_size == 0 case is handled here already
188* and the final score computation below would not have a
189* divide-by-zero issue.
190*/
191if (max_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)192return 0;193
194dpf_opt->check_size_only = 0;195
196if (!src->cnt_data && diff_populate_filespec(r, src, dpf_opt))197return 0;198if (!dst->cnt_data && diff_populate_filespec(r, dst, dpf_opt))199return 0;200
201if (diffcore_count_changes(r, src, dst,202&src->cnt_data, &dst->cnt_data,203&src_copied, &literal_added))204return 0;205
206/* How similar are they?207* what percentage of material in dst are from source?
208*/
209if (!dst->size)210score = 0; /* should not happen */211else212score = (int)(src_copied * MAX_SCORE / max_size);213return score;214}
215
216static void record_rename_pair(int dst_index, int src_index, int score)217{
218struct diff_filepair *src = rename_src[src_index].p;219struct diff_filepair *dst = rename_dst[dst_index].p;220
221if (dst->renamed_pair)222die("internal error: dst already matched.");223
224src->one->rename_used++;225src->one->count++;226
227rename_dst[dst_index].filespec_to_free = dst->one;228rename_dst[dst_index].is_rename = 1;229
230dst->one = src->one;231dst->renamed_pair = 1;232if (!strcmp(dst->one->path, dst->two->path))233dst->score = rename_src[src_index].score;234else235dst->score = score;236}
237
238/*
239* We sort the rename similarity matrix with the score, in descending
240* order (the most similar first).
241*/
242static int score_compare(const void *a_, const void *b_)243{
244const struct diff_score *a = a_, *b = b_;245
246/* sink the unused ones to the bottom */247if (a->dst < 0)248return (0 <= b->dst);249else if (b->dst < 0)250return -1;251
252if (a->score == b->score)253return b->name_score - a->name_score;254
255return b->score - a->score;256}
257
258struct file_similarity {259struct hashmap_entry entry;260int index;261struct diff_filespec *filespec;262};263
264static unsigned int hash_filespec(struct repository *r,265struct diff_filespec *filespec)266{
267if (!filespec->oid_valid) {268if (diff_populate_filespec(r, filespec, NULL))269return 0;270hash_object_file(r->hash_algo, filespec->data, filespec->size,271OBJ_BLOB, &filespec->oid);272}273return oidhash(&filespec->oid);274}
275
276static int find_identical_files(struct hashmap *srcs,277int dst_index,278struct diff_options *options)279{
280int renames = 0;281struct diff_filespec *target = rename_dst[dst_index].p->two;282struct file_similarity *p, *best = NULL;283int i = 100, best_score = -1;284unsigned int hash = hash_filespec(options->repo, target);285
286/*287* Find the best source match for specified destination.
288*/
289p = hashmap_get_entry_from_hash(srcs, hash, NULL,290struct file_similarity, entry);291hashmap_for_each_entry_from(srcs, p, entry) {292int score;293struct diff_filespec *source = p->filespec;294
295/* False hash collision? */296if (!oideq(&source->oid, &target->oid))297continue;298/* Non-regular files? If so, the modes must match! */299if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) {300if (source->mode != target->mode)301continue;302}303/* Give higher scores to sources that haven't been used already */304score = !source->rename_used;305if (source->rename_used && options->detect_rename != DIFF_DETECT_COPY)306continue;307score += basename_same(source, target);308if (score > best_score) {309best = p;310best_score = score;311if (score == 2)312break;313}314
315/* Too many identical alternatives? Pick one */316if (!--i)317break;318}319if (best) {320record_rename_pair(dst_index, best->index, MAX_SCORE);321renames++;322}323return renames;324}
325
326static void insert_file_table(struct repository *r,327struct mem_pool *pool,328struct hashmap *table, int index,329struct diff_filespec *filespec)330{
331struct file_similarity *entry = mem_pool_alloc(pool, sizeof(*entry));332
333entry->index = index;334entry->filespec = filespec;335
336hashmap_entry_init(&entry->entry, hash_filespec(r, filespec));337hashmap_add(table, &entry->entry);338}
339
340/*
341* Find exact renames first.
342*
343* The first round matches up the up-to-date entries,
344* and then during the second round we try to match
345* cache-dirty entries as well.
346*/
347static int find_exact_renames(struct diff_options *options,348struct mem_pool *pool)349{
350int i, renames = 0;351struct hashmap file_table;352
353/* Add all sources to the hash table in reverse order, because354* later on they will be retrieved in LIFO order.
355*/
356hashmap_init(&file_table, NULL, NULL, rename_src_nr);357for (i = rename_src_nr-1; i >= 0; i--)358insert_file_table(options->repo, pool,359&file_table, i,360rename_src[i].p->one);361
362/* Walk the destinations and find best source match */363for (i = 0; i < rename_dst_nr; i++)364renames += find_identical_files(&file_table, i, options);365
366/* Free the hash data structure (entries will be freed with the pool) */367hashmap_clear(&file_table);368
369return renames;370}
371
372struct dir_rename_info {373struct strintmap idx_map;374struct strmap dir_rename_guess;375struct strmap *dir_rename_count;376struct strintmap *relevant_source_dirs;377unsigned setup;378};379
380static char *get_dirname(const char *filename)381{
382char *slash = strrchr(filename, '/');383return slash ? xstrndup(filename, slash - filename) : xstrdup("");384}
385
386static void dirname_munge(char *filename)387{
388char *slash = strrchr(filename, '/');389if (!slash)390slash = filename;391*slash = '\0';392}
393
394static const char *get_highest_rename_path(struct strintmap *counts)395{
396int highest_count = 0;397const char *highest_destination_dir = NULL;398struct hashmap_iter iter;399struct strmap_entry *entry;400
401strintmap_for_each_entry(counts, &iter, entry) {402const char *destination_dir = entry->key;403intptr_t count = (intptr_t)entry->value;404if (count > highest_count) {405highest_count = count;406highest_destination_dir = destination_dir;407}408}409return highest_destination_dir;410}
411
412static const char *UNKNOWN_DIR = "/"; /* placeholder -- short, illegal directory */413
414static int dir_rename_already_determinable(struct strintmap *counts)415{
416struct hashmap_iter iter;417struct strmap_entry *entry;418int first = 0, second = 0, unknown = 0;419strintmap_for_each_entry(counts, &iter, entry) {420const char *destination_dir = entry->key;421intptr_t count = (intptr_t)entry->value;422if (!strcmp(destination_dir, UNKNOWN_DIR)) {423unknown = count;424} else if (count >= first) {425second = first;426first = count;427} else if (count >= second) {428second = count;429}430}431return first > second + unknown;432}
433
434static void increment_count(struct dir_rename_info *info,435const char *old_dir,436const char *new_dir)437{
438struct strintmap *counts;439struct strmap_entry *e;440
441/* Get the {new_dirs -> counts} mapping using old_dir */442e = strmap_get_entry(info->dir_rename_count, old_dir);443if (e) {444counts = e->value;445} else {446counts = xmalloc(sizeof(*counts));447strintmap_init_with_options(counts, 0, NULL, 1);448strmap_put(info->dir_rename_count, old_dir, counts);449}450
451/* Increment the count for new_dir */452strintmap_incr(counts, new_dir, 1);453}
454
455static void update_dir_rename_counts(struct dir_rename_info *info,456struct strintmap *dirs_removed,457const char *oldname,458const char *newname)459{
460char *old_dir;461char *new_dir;462const char new_dir_first_char = newname[0];463int first_time_in_loop = 1;464
465if (!info->setup)466/*467* info->setup is 0 here in two cases: (1) all auxiliary
468* vars (like dirs_removed) were NULL so
469* initialize_dir_rename_info() returned early, or (2)
470* either break detection or copy detection are active so
471* that we never called initialize_dir_rename_info(). In
472* the former case, we don't have enough info to know if
473* directories were renamed (because dirs_removed lets us
474* know about a necessary prerequisite, namely if they were
475* removed), and in the latter, we don't care about
476* directory renames or find_basename_matches.
477*
478* This matters because both basename and inexact matching
479* will also call update_dir_rename_counts(). In either of
480* the above two cases info->dir_rename_counts will not
481* have been properly initialized which prevents us from
482* updating it, but in these two cases we don't care about
483* dir_rename_counts anyway, so we can just exit early.
484*/
485return;486
487
488old_dir = xstrdup(oldname);489new_dir = xstrdup(newname);490
491while (1) {492int drd_flag = NOT_RELEVANT;493
494/* Get old_dir, skip if its directory isn't relevant. */495dirname_munge(old_dir);496if (info->relevant_source_dirs &&497!strintmap_contains(info->relevant_source_dirs, old_dir))498break;499
500/* Get new_dir */501dirname_munge(new_dir);502
503/*504* When renaming
505* "a/b/c/d/e/foo.c" -> "a/b/some/thing/else/e/foo.c"
506* then this suggests that both
507* a/b/c/d/e/ => a/b/some/thing/else/e/
508* a/b/c/d/ => a/b/some/thing/else/
509* so we want to increment counters for both. We do NOT,
510* however, also want to suggest that there was the following
511* rename:
512* a/b/c/ => a/b/some/thing/
513* so we need to quit at that point.
514*
515* Note the when first_time_in_loop, we only strip off the
516* basename, and we don't care if that's different.
517*/
518if (!first_time_in_loop) {519char *old_sub_dir = strchr(old_dir, '\0')+1;520char *new_sub_dir = strchr(new_dir, '\0')+1;521if (!*new_dir) {522/*523* Special case when renaming to root directory,
524* i.e. when new_dir == "". In this case, we had
525* something like
526* a/b/subdir => subdir
527* and so dirname_munge() sets things up so that
528* old_dir = "a/b\0subdir\0"
529* new_dir = "\0ubdir\0"
530* We didn't have a '/' to overwrite a '\0' onto
531* in new_dir, so we have to compare differently.
532*/
533if (new_dir_first_char != old_sub_dir[0] ||534strcmp(old_sub_dir+1, new_sub_dir))535break;536} else {537if (strcmp(old_sub_dir, new_sub_dir))538break;539}540}541
542/*543* Above we suggested that we'd keep recording renames for
544* all ancestor directories where the trailing directories
545* matched, i.e. for
546* "a/b/c/d/e/foo.c" -> "a/b/some/thing/else/e/foo.c"
547* we'd increment rename counts for each of
548* a/b/c/d/e/ => a/b/some/thing/else/e/
549* a/b/c/d/ => a/b/some/thing/else/
550* However, we only need the rename counts for directories
551* in dirs_removed whose value is RELEVANT_FOR_SELF.
552* However, we add one special case of also recording it for
553* first_time_in_loop because find_basename_matches() can
554* use that as a hint to find a good pairing.
555*/
556if (dirs_removed)557drd_flag = strintmap_get(dirs_removed, old_dir);558if (drd_flag == RELEVANT_FOR_SELF || first_time_in_loop)559increment_count(info, old_dir, new_dir);560
561first_time_in_loop = 0;562if (drd_flag == NOT_RELEVANT)563break;564/* If we hit toplevel directory ("") for old or new dir, quit */565if (!*old_dir || !*new_dir)566break;567}568
569/* Free resources we don't need anymore */570free(old_dir);571free(new_dir);572}
573
574static void initialize_dir_rename_info(struct dir_rename_info *info,575struct strintmap *relevant_sources,576struct strintmap *dirs_removed,577struct strmap *dir_rename_count,578struct strmap *cached_pairs)579{
580struct hashmap_iter iter;581struct strmap_entry *entry;582int i;583
584if (!dirs_removed && !relevant_sources) {585info->setup = 0;586return;587}588info->setup = 1;589
590info->dir_rename_count = dir_rename_count;591if (!info->dir_rename_count) {592info->dir_rename_count = xmalloc(sizeof(*dir_rename_count));593strmap_init(info->dir_rename_count);594}595strintmap_init_with_options(&info->idx_map, -1, NULL, 0);596strmap_init_with_options(&info->dir_rename_guess, NULL, 0);597
598/* Setup info->relevant_source_dirs */599info->relevant_source_dirs = NULL;600if (dirs_removed || !relevant_sources) {601info->relevant_source_dirs = dirs_removed; /* might be NULL */602} else {603info->relevant_source_dirs = xmalloc(sizeof(struct strintmap));604strintmap_init(info->relevant_source_dirs, 0 /* unused */);605strintmap_for_each_entry(relevant_sources, &iter, entry) {606char *dirname = get_dirname(entry->key);607if (!dirs_removed ||608strintmap_contains(dirs_removed, dirname))609strintmap_set(info->relevant_source_dirs,610dirname, 0 /* value irrelevant */);611free(dirname);612}613}614
615/*616* Loop setting up both info->idx_map, and doing setup of
617* info->dir_rename_count.
618*/
619for (i = 0; i < rename_dst_nr; ++i) {620/*621* For non-renamed files, make idx_map contain mapping of
622* filename -> index (index within rename_dst, that is)
623*/
624if (!rename_dst[i].is_rename) {625char *filename = rename_dst[i].p->two->path;626strintmap_set(&info->idx_map, filename, i);627continue;628}629
630/*631* For everything else (i.e. renamed files), make
632* dir_rename_count contain a map of a map:
633* old_directory -> {new_directory -> count}
634* In other words, for every pair look at the directories for
635* the old filename and the new filename and count how many
636* times that pairing occurs.
637*/
638update_dir_rename_counts(info, dirs_removed,639rename_dst[i].p->one->path,640rename_dst[i].p->two->path);641}642
643/* Add cached_pairs to counts */644strmap_for_each_entry(cached_pairs, &iter, entry) {645const char *old_name = entry->key;646const char *new_name = entry->value;647if (!new_name)648/* known delete; ignore it */649continue;650
651update_dir_rename_counts(info, dirs_removed, old_name, new_name);652}653
654/*655* Now we collapse
656* dir_rename_count: old_directory -> {new_directory -> count}
657* down to
658* dir_rename_guess: old_directory -> best_new_directory
659* where best_new_directory is the one with the highest count.
660*/
661strmap_for_each_entry(info->dir_rename_count, &iter, entry) {662/* entry->key is source_dir */663struct strintmap *counts = entry->value;664char *best_newdir;665
666best_newdir = xstrdup(get_highest_rename_path(counts));667strmap_put(&info->dir_rename_guess, entry->key,668best_newdir);669}670}
671
672void partial_clear_dir_rename_count(struct strmap *dir_rename_count)673{
674struct hashmap_iter iter;675struct strmap_entry *entry;676
677strmap_for_each_entry(dir_rename_count, &iter, entry) {678struct strintmap *counts = entry->value;679strintmap_clear(counts);680}681strmap_partial_clear(dir_rename_count, 1);682}
683
684static void cleanup_dir_rename_info(struct dir_rename_info *info,685struct strintmap *dirs_removed,686int keep_dir_rename_count)687{
688struct hashmap_iter iter;689struct strmap_entry *entry;690struct string_list to_remove = STRING_LIST_INIT_NODUP;691int i;692
693if (!info->setup)694return;695
696/* idx_map */697strintmap_clear(&info->idx_map);698
699/* dir_rename_guess */700strmap_clear(&info->dir_rename_guess, 1);701
702/* relevant_source_dirs */703if (info->relevant_source_dirs &&704info->relevant_source_dirs != dirs_removed) {705strintmap_clear(info->relevant_source_dirs);706FREE_AND_NULL(info->relevant_source_dirs);707}708
709/* dir_rename_count */710if (!keep_dir_rename_count) {711partial_clear_dir_rename_count(info->dir_rename_count);712strmap_clear(info->dir_rename_count, 1);713FREE_AND_NULL(info->dir_rename_count);714return;715}716
717/*718* Although dir_rename_count was passed in
719* diffcore_rename_extended() and we want to keep it around and
720* return it to that caller, we first want to remove any counts in
721* the maps associated with UNKNOWN_DIR entries and any data
722* associated with directories that weren't renamed.
723*/
724strmap_for_each_entry(info->dir_rename_count, &iter, entry) {725const char *source_dir = entry->key;726struct strintmap *counts = entry->value;727
728if (!strintmap_get(dirs_removed, source_dir)) {729string_list_append(&to_remove, source_dir);730strintmap_clear(counts);731continue;732}733
734if (strintmap_contains(counts, UNKNOWN_DIR))735strintmap_remove(counts, UNKNOWN_DIR);736}737for (i = 0; i < to_remove.nr; ++i)738strmap_remove(info->dir_rename_count,739to_remove.items[i].string, 1);740string_list_clear(&to_remove, 0);741}
742
743static const char *get_basename(const char *filename)744{
745/*746* gitbasename() has to worry about special drives, multiple
747* directory separator characters, trailing slashes, NULL or
748* empty strings, etc. We only work on filenames as stored in
749* git, and thus get to ignore all those complications.
750*/
751const char *base = strrchr(filename, '/');752return base ? base + 1 : filename;753}
754
755static int idx_possible_rename(char *filename, struct dir_rename_info *info)756{
757/*758* Our comparison of files with the same basename (see
759* find_basename_matches() below), is only helpful when after exact
760* rename detection we have exactly one file with a given basename
761* among the rename sources and also only exactly one file with
762* that basename among the rename destinations. When we have
763* multiple files with the same basename in either set, we do not
764* know which to compare against. However, there are some
765* filenames that occur in large numbers (particularly
766* build-related filenames such as 'Makefile', '.gitignore', or
767* 'build.gradle' that potentially exist within every single
768* subdirectory), and for performance we want to be able to quickly
769* find renames for these files too.
770*
771* The reason basename comparisons are a useful heuristic was that it
772* is common for people to move files across directories while keeping
773* their filename the same. If we had a way of determining or even
774* making a good educated guess about which directory these non-unique
775* basename files had moved the file to, we could check it.
776* Luckily...
777*
778* When an entire directory is in fact renamed, we have two factors
779* helping us out:
780* (a) the original directory disappeared giving us a hint
781* about when we can apply an extra heuristic.
782* (a) we often have several files within that directory and
783* subdirectories that are renamed without changes
784* So, rules for a heuristic:
785* (0) If there basename matches are non-unique (the condition under
786* which this function is called) AND
787* (1) the directory in which the file was found has disappeared
788* (i.e. dirs_removed is non-NULL and has a relevant entry) THEN
789* (2) use exact renames of files within the directory to determine
790* where the directory is likely to have been renamed to. IF
791* there is at least one exact rename from within that
792* directory, we can proceed.
793* (3) If there are multiple places the directory could have been
794* renamed to based on exact renames, ignore all but one of them.
795* Just use the destination with the most renames going to it.
796* (4) Check if applying that directory rename to the original file
797* would result in a destination filename that is in the
798* potential rename set. If so, return the index of the
799* destination file (the index within rename_dst).
800* (5) Compare the original file and returned destination for
801* similarity, and if they are sufficiently similar, record the
802* rename.
803*
804* This function, idx_possible_rename(), is only responsible for (4).
805* The conditions/steps in (1)-(3) are handled via setting up
806* dir_rename_count and dir_rename_guess in
807* initialize_dir_rename_info(). Steps (0) and (5) are handled by
808* the caller of this function.
809*/
810char *old_dir, *new_dir;811struct strbuf new_path = STRBUF_INIT;812int idx;813
814if (!info->setup)815return -1;816
817old_dir = get_dirname(filename);818new_dir = strmap_get(&info->dir_rename_guess, old_dir);819free(old_dir);820if (!new_dir)821return -1;822
823strbuf_addstr(&new_path, new_dir);824strbuf_addch(&new_path, '/');825strbuf_addstr(&new_path, get_basename(filename));826
827idx = strintmap_get(&info->idx_map, new_path.buf);828strbuf_release(&new_path);829return idx;830}
831
832struct basename_prefetch_options {833struct repository *repo;834struct strintmap *relevant_sources;835struct strintmap *sources;836struct strintmap *dests;837struct dir_rename_info *info;838};839static void basename_prefetch(void *prefetch_options)840{
841struct basename_prefetch_options *options = prefetch_options;842struct strintmap *relevant_sources = options->relevant_sources;843struct strintmap *sources = options->sources;844struct strintmap *dests = options->dests;845struct dir_rename_info *info = options->info;846int i;847struct oid_array to_fetch = OID_ARRAY_INIT;848
849/*850* TODO: The following loops mirror the code/logic from
851* find_basename_matches(), though not quite exactly. Maybe
852* abstract the iteration logic out somehow?
853*/
854for (i = 0; i < rename_src_nr; ++i) {855char *filename = rename_src[i].p->one->path;856const char *base = NULL;857intptr_t src_index;858intptr_t dst_index;859
860/* Skip irrelevant sources */861if (relevant_sources &&862!strintmap_contains(relevant_sources, filename))863continue;864
865/*866* If the basename is unique among remaining sources, then
867* src_index will equal 'i' and we can attempt to match it
868* to a unique basename in the destinations. Otherwise,
869* use directory rename heuristics, if possible.
870*/
871base = get_basename(filename);872src_index = strintmap_get(sources, base);873assert(src_index == -1 || src_index == i);874
875if (strintmap_contains(dests, base)) {876struct diff_filespec *one, *two;877
878/* Find a matching destination, if possible */879dst_index = strintmap_get(dests, base);880if (src_index == -1 || dst_index == -1) {881src_index = i;882dst_index = idx_possible_rename(filename, info);883}884if (dst_index == -1)885continue;886
887/* Ignore this dest if already used in a rename */888if (rename_dst[dst_index].is_rename)889continue; /* already used previously */890
891one = rename_src[src_index].p->one;892two = rename_dst[dst_index].p->two;893
894/* Add the pairs */895diff_add_if_missing(options->repo, &to_fetch, two);896diff_add_if_missing(options->repo, &to_fetch, one);897}898}899
900promisor_remote_get_direct(options->repo, to_fetch.oid, to_fetch.nr);901oid_array_clear(&to_fetch);902}
903
904static int find_basename_matches(struct diff_options *options,905int minimum_score,906struct dir_rename_info *info,907struct strintmap *relevant_sources,908struct strintmap *dirs_removed)909{
910/*911* When I checked in early 2020, over 76% of file renames in linux
912* just moved files to a different directory but kept the same
913* basename. gcc did that with over 64% of renames, gecko did it
914* with over 79%, and WebKit did it with over 89%.
915*
916* Therefore we can bypass the normal exhaustive NxM matrix
917* comparison of similarities between all potential rename sources
918* and destinations by instead using file basename as a hint (i.e.
919* the portion of the filename after the last '/'), checking for
920* similarity between files with the same basename, and if we find
921* a pair that are sufficiently similar, record the rename pair and
922* exclude those two from the NxM matrix.
923*
924* This *might* cause us to find a less than optimal pairing (if
925* there is another file that we are even more similar to but has a
926* different basename). Given the huge performance advantage
927* basename matching provides, and given the frequency with which
928* people use the same basename in real world projects, that's a
929* trade-off we are willing to accept when doing just rename
930* detection.
931*
932* If someone wants copy detection that implies they are willing to
933* spend more cycles to find similarities between files, so it may
934* be less likely that this heuristic is wanted. If someone is
935* doing break detection, that means they do not want filename
936* similarity to imply any form of content similiarity, and thus
937* this heuristic would definitely be incompatible.
938*/
939
940int i, renames = 0;941struct strintmap sources;942struct strintmap dests;943struct diff_populate_filespec_options dpf_options = {944.check_binary = 0,945.missing_object_cb = NULL,946.missing_object_data = NULL947};948struct basename_prefetch_options prefetch_options = {949.repo = options->repo,950.relevant_sources = relevant_sources,951.sources = &sources,952.dests = &dests,953.info = info954};955
956/*957* Create maps of basename -> fullname(s) for remaining sources and
958* dests.
959*/
960strintmap_init_with_options(&sources, -1, NULL, 0);961strintmap_init_with_options(&dests, -1, NULL, 0);962for (i = 0; i < rename_src_nr; ++i) {963char *filename = rename_src[i].p->one->path;964const char *base;965
966/* exact renames removed in remove_unneeded_paths_from_src() */967assert(!rename_src[i].p->one->rename_used);968
969/* Record index within rename_src (i) if basename is unique */970base = get_basename(filename);971if (strintmap_contains(&sources, base))972strintmap_set(&sources, base, -1);973else974strintmap_set(&sources, base, i);975}976for (i = 0; i < rename_dst_nr; ++i) {977char *filename = rename_dst[i].p->two->path;978const char *base;979
980if (rename_dst[i].is_rename)981continue; /* involved in exact match already. */982
983/* Record index within rename_dst (i) if basename is unique */984base = get_basename(filename);985if (strintmap_contains(&dests, base))986strintmap_set(&dests, base, -1);987else988strintmap_set(&dests, base, i);989}990
991if (options->repo == the_repository && repo_has_promisor_remote(the_repository)) {992dpf_options.missing_object_cb = basename_prefetch;993dpf_options.missing_object_data = &prefetch_options;994}995
996/* Now look for basename matchups and do similarity estimation */997for (i = 0; i < rename_src_nr; ++i) {998char *filename = rename_src[i].p->one->path;999const char *base = NULL;1000intptr_t src_index;1001intptr_t dst_index;1002
1003/* Skip irrelevant sources */1004if (relevant_sources &&1005!strintmap_contains(relevant_sources, filename))1006continue;1007
1008/*1009* If the basename is unique among remaining sources, then
1010* src_index will equal 'i' and we can attempt to match it
1011* to a unique basename in the destinations. Otherwise,
1012* use directory rename heuristics, if possible.
1013*/
1014base = get_basename(filename);1015src_index = strintmap_get(&sources, base);1016assert(src_index == -1 || src_index == i);1017
1018if (strintmap_contains(&dests, base)) {1019struct diff_filespec *one, *two;1020int score;1021
1022/* Find a matching destination, if possible */1023dst_index = strintmap_get(&dests, base);1024if (src_index == -1 || dst_index == -1) {1025src_index = i;1026dst_index = idx_possible_rename(filename, info);1027}1028if (dst_index == -1)1029continue;1030
1031/* Ignore this dest if already used in a rename */1032if (rename_dst[dst_index].is_rename)1033continue; /* already used previously */1034
1035/* Estimate the similarity */1036one = rename_src[src_index].p->one;1037two = rename_dst[dst_index].p->two;1038score = estimate_similarity(options->repo, one, two,1039minimum_score, &dpf_options);1040
1041/* If sufficiently similar, record as rename pair */1042if (score < minimum_score)1043continue;1044record_rename_pair(dst_index, src_index, score);1045renames++;1046update_dir_rename_counts(info, dirs_removed,1047one->path, two->path);1048
1049/*1050* Found a rename so don't need text anymore; if we
1051* didn't find a rename, the filespec_blob would get
1052* re-used when doing the matrix of comparisons.
1053*/
1054diff_free_filespec_blob(one);1055diff_free_filespec_blob(two);1056}1057}1058
1059strintmap_clear(&sources);1060strintmap_clear(&dests);1061
1062return renames;1063}
1064
1065#define NUM_CANDIDATE_PER_DST 41066static void record_if_better(struct diff_score m[], struct diff_score *o)1067{
1068int i, worst;1069
1070/* find the worst one */1071worst = 0;1072for (i = 1; i < NUM_CANDIDATE_PER_DST; i++)1073if (score_compare(&m[i], &m[worst]) > 0)1074worst = i;1075
1076/* is it better than the worst one? */1077if (score_compare(&m[worst], o) > 0)1078m[worst] = *o;1079}
1080
1081/*
1082* Returns:
1083* 0 if we are under the limit;
1084* 1 if we need to disable inexact rename detection;
1085* 2 if we would be under the limit if we were given -C instead of -C -C.
1086*/
1087static int too_many_rename_candidates(int num_destinations, int num_sources,1088struct diff_options *options)1089{
1090int rename_limit = options->rename_limit;1091int i, limited_sources;1092
1093options->needed_rename_limit = 0;1094
1095/*1096* This basically does a test for the rename matrix not
1097* growing larger than a "rename_limit" square matrix, ie:
1098*
1099* num_destinations * num_sources > rename_limit * rename_limit
1100*
1101* We use st_mult() to check overflow conditions; in the
1102* exceptional circumstance that size_t isn't large enough to hold
1103* the multiplication, the system won't be able to allocate enough
1104* memory for the matrix anyway.
1105*/
1106if (rename_limit <= 0)1107return 0; /* treat as unlimited */1108if (st_mult(num_destinations, num_sources)1109<= st_mult(rename_limit, rename_limit))1110return 0;1111
1112options->needed_rename_limit =1113num_sources > num_destinations ? num_sources : num_destinations;1114
1115/* Are we running under -C -C? */1116if (!options->flags.find_copies_harder)1117return 1;1118
1119/* Would we bust the limit if we were running under -C? */1120for (limited_sources = i = 0; i < num_sources; i++) {1121if (diff_unmodified_pair(rename_src[i].p))1122continue;1123limited_sources++;1124}1125if (st_mult(num_destinations, limited_sources)1126<= st_mult(rename_limit, rename_limit))1127return 2;1128return 1;1129}
1130
1131static int find_renames(struct diff_score *mx,1132int dst_cnt,1133int minimum_score,1134int copies,1135struct dir_rename_info *info,1136struct strintmap *dirs_removed)1137{
1138int count = 0, i;1139
1140for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {1141struct diff_rename_dst *dst;1142
1143if ((mx[i].dst < 0) ||1144(mx[i].score < minimum_score))1145break; /* there is no more usable pair. */1146dst = &rename_dst[mx[i].dst];1147if (dst->is_rename)1148continue; /* already done, either exact or fuzzy. */1149if (!copies && rename_src[mx[i].src].p->one->rename_used)1150continue;1151record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);1152count++;1153update_dir_rename_counts(info, dirs_removed,1154rename_src[mx[i].src].p->one->path,1155rename_dst[mx[i].dst].p->two->path);1156}1157return count;1158}
1159
1160static void remove_unneeded_paths_from_src(int detecting_copies,1161struct strintmap *interesting)1162{
1163int i, new_num_src;1164
1165if (detecting_copies && !interesting)1166return; /* nothing to remove */1167if (break_idx)1168return; /* culling incompatible with break detection */1169
1170/*1171* Note on reasons why we cull unneeded sources but not destinations:
1172* 1) Pairings are stored in rename_dst (not rename_src), which we
1173* need to keep around. So, we just can't cull rename_dst even
1174* if we wanted to. But doing so wouldn't help because...
1175*
1176* 2) There is a matrix pairwise comparison that follows the
1177* "Performing inexact rename detection" progress message.
1178* Iterating over the destinations is done in the outer loop,
1179* hence we only iterate over each of those once and we can
1180* easily skip the outer loop early if the destination isn't
1181* relevant. That's only one check per destination path to
1182* skip.
1183*
1184* By contrast, the sources are iterated in the inner loop; if
1185* we check whether a source can be skipped, then we'll be
1186* checking it N separate times, once for each destination.
1187* We don't want to have to iterate over known-not-needed
1188* sources N times each, so avoid that by removing the sources
1189* from rename_src here.
1190*/
1191for (i = 0, new_num_src = 0; i < rename_src_nr; i++) {1192struct diff_filespec *one = rename_src[i].p->one;1193
1194/*1195* renames are stored in rename_dst, so if a rename has
1196* already been detected using this source, we can just
1197* remove the source knowing rename_dst has its info.
1198*/
1199if (!detecting_copies && one->rename_used)1200continue;1201
1202/* If we don't care about the source path, skip it */1203if (interesting && !strintmap_contains(interesting, one->path))1204continue;1205
1206if (new_num_src < i)1207memcpy(&rename_src[new_num_src], &rename_src[i],1208sizeof(struct diff_rename_src));1209new_num_src++;1210}1211
1212rename_src_nr = new_num_src;1213}
1214
1215static void handle_early_known_dir_renames(struct dir_rename_info *info,1216struct strintmap *relevant_sources,1217struct strintmap *dirs_removed)1218{
1219/*1220* Directory renames are determined via an aggregate of all renames
1221* under them and using a "majority wins" rule. The fact that
1222* "majority wins", though, means we don't need all the renames
1223* under the given directory, we only need enough to ensure we have
1224* a majority.
1225*/
1226
1227int i, new_num_src;1228struct hashmap_iter iter;1229struct strmap_entry *entry;1230
1231if (!dirs_removed || !relevant_sources)1232return; /* nothing to cull */1233if (break_idx)1234return; /* culling incompatbile with break detection */1235
1236/*1237* Supplement dir_rename_count with number of potential renames,
1238* marking all potential rename sources as mapping to UNKNOWN_DIR.
1239*/
1240for (i = 0; i < rename_src_nr; i++) {1241char *old_dir;1242struct diff_filespec *one = rename_src[i].p->one;1243
1244/*1245* sources that are part of a rename will have already been
1246* removed by a prior call to remove_unneeded_paths_from_src()
1247*/
1248assert(!one->rename_used);1249
1250old_dir = get_dirname(one->path);1251while (*old_dir != '\0' &&1252NOT_RELEVANT != strintmap_get(dirs_removed, old_dir)) {1253char *freeme = old_dir;1254
1255increment_count(info, old_dir, UNKNOWN_DIR);1256old_dir = get_dirname(old_dir);1257
1258/* Free resources we don't need anymore */1259free(freeme);1260}1261/*1262* old_dir and new_dir free'd in increment_count, but
1263* get_dirname() gives us a new pointer we need to free for
1264* old_dir. Also, if the loop runs 0 times we need old_dir
1265* to be freed.
1266*/
1267free(old_dir);1268}1269
1270/*1271* For any directory which we need a potential rename detected for
1272* (i.e. those marked as RELEVANT_FOR_SELF in dirs_removed), check
1273* whether we have enough renames to satisfy the "majority rules"
1274* requirement such that detecting any more renames of files under
1275* it won't change the result. For any such directory, mark that
1276* we no longer need to detect a rename for it. However, since we
1277* might need to still detect renames for an ancestor of that
1278* directory, use RELEVANT_FOR_ANCESTOR.
1279*/
1280strmap_for_each_entry(info->dir_rename_count, &iter, entry) {1281/* entry->key is source_dir */1282struct strintmap *counts = entry->value;1283
1284if (strintmap_get(dirs_removed, entry->key) ==1285RELEVANT_FOR_SELF &&1286dir_rename_already_determinable(counts)) {1287strintmap_set(dirs_removed, entry->key,1288RELEVANT_FOR_ANCESTOR);1289}1290}1291
1292for (i = 0, new_num_src = 0; i < rename_src_nr; i++) {1293struct diff_filespec *one = rename_src[i].p->one;1294int val;1295
1296val = strintmap_get(relevant_sources, one->path);1297
1298/*1299* sources that were not found in relevant_sources should
1300* have already been removed by a prior call to
1301* remove_unneeded_paths_from_src()
1302*/
1303assert(val != -1);1304
1305if (val == RELEVANT_LOCATION) {1306int removable = 1;1307char *dir = get_dirname(one->path);1308while (1) {1309char *freeme = dir;1310int res = strintmap_get(dirs_removed, dir);1311
1312/* Quit if not found or irrelevant */1313if (res == NOT_RELEVANT)1314break;1315/* If RELEVANT_FOR_SELF, can't remove */1316if (res == RELEVANT_FOR_SELF) {1317removable = 0;1318break;1319}1320/* Else continue searching upwards */1321assert(res == RELEVANT_FOR_ANCESTOR);1322dir = get_dirname(dir);1323free(freeme);1324}1325free(dir);1326if (removable) {1327strintmap_set(relevant_sources, one->path,1328RELEVANT_NO_MORE);1329continue;1330}1331}1332
1333if (new_num_src < i)1334memcpy(&rename_src[new_num_src], &rename_src[i],1335sizeof(struct diff_rename_src));1336new_num_src++;1337}1338
1339rename_src_nr = new_num_src;1340}
1341
1342static void free_filespec_data(struct diff_filespec *spec)1343{
1344if (!--spec->count)1345diff_free_filespec_data(spec);1346}
1347
1348static void pool_free_filespec(struct mem_pool *pool,1349struct diff_filespec *spec)1350{
1351if (!pool) {1352free_filespec(spec);1353return;1354}1355
1356/*1357* Similar to free_filespec(), but only frees the data. The spec
1358* itself was allocated in the pool and should not be individually
1359* freed.
1360*/
1361free_filespec_data(spec);1362}
1363
1364void pool_diff_free_filepair(struct mem_pool *pool,1365struct diff_filepair *p)1366{
1367if (!pool) {1368diff_free_filepair(p);1369return;1370}1371
1372/*1373* Similar to diff_free_filepair() but only frees the data from the
1374* filespecs; not the filespecs or the filepair which were
1375* allocated from the pool.
1376*/
1377free_filespec_data(p->one);1378free_filespec_data(p->two);1379}
1380
1381void diffcore_rename_extended(struct diff_options *options,1382struct mem_pool *pool,1383struct strintmap *relevant_sources,1384struct strintmap *dirs_removed,1385struct strmap *dir_rename_count,1386struct strmap *cached_pairs)1387{
1388int detect_rename = options->detect_rename;1389int minimum_score = options->rename_score;1390struct diff_queue_struct *q = &diff_queued_diff;1391struct diff_queue_struct outq;1392struct diff_score *mx;1393int i, j, rename_count, skip_unmodified = 0;1394int num_destinations, dst_cnt;1395int num_sources, want_copies;1396struct progress *progress = NULL;1397struct mem_pool local_pool;1398struct dir_rename_info info;1399struct diff_populate_filespec_options dpf_options = {1400.check_binary = 0,1401.missing_object_cb = NULL,1402.missing_object_data = NULL1403};1404struct inexact_prefetch_options prefetch_options = {1405.repo = options->repo1406};1407
1408trace2_region_enter("diff", "setup", options->repo);1409info.setup = 0;1410assert(!dir_rename_count || strmap_empty(dir_rename_count));1411want_copies = (detect_rename == DIFF_DETECT_COPY);1412if (dirs_removed && (break_idx || want_copies))1413BUG("dirs_removed incompatible with break/copy detection");1414if (break_idx && relevant_sources)1415BUG("break detection incompatible with source specification");1416if (!minimum_score)1417minimum_score = DEFAULT_RENAME_SCORE;1418
1419for (i = 0; i < q->nr; i++) {1420struct diff_filepair *p = q->queue[i];1421if (!DIFF_FILE_VALID(p->one)) {1422if (!DIFF_FILE_VALID(p->two))1423continue; /* unmerged */1424else if (options->single_follow &&1425strcmp(options->single_follow, p->two->path))1426continue; /* not interested */1427else if (!options->flags.rename_empty &&1428is_empty_blob_oid(&p->two->oid, the_repository->hash_algo))1429continue;1430else if (add_rename_dst(p) < 0) {1431warning("skipping rename detection, detected"1432" duplicate destination '%s'",1433p->two->path);1434goto cleanup;1435}1436}1437else if (!options->flags.rename_empty &&1438is_empty_blob_oid(&p->one->oid, the_repository->hash_algo))1439continue;1440else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {1441/*1442* If the source is a broken "delete", and
1443* they did not really want to get broken,
1444* that means the source actually stays.
1445* So we increment the "rename_used" score
1446* by one, to indicate ourselves as a user
1447*/
1448if (p->broken_pair && !p->score)1449p->one->rename_used++;1450register_rename_src(p);1451}1452else if (want_copies) {1453/*1454* Increment the "rename_used" score by
1455* one, to indicate ourselves as a user.
1456*/
1457p->one->rename_used++;1458register_rename_src(p);1459}1460}1461trace2_region_leave("diff", "setup", options->repo);1462if (rename_dst_nr == 0 || rename_src_nr == 0)1463goto cleanup; /* nothing to do */1464
1465trace2_region_enter("diff", "exact renames", options->repo);1466mem_pool_init(&local_pool, 32*1024);1467/*1468* We really want to cull the candidates list early
1469* with cheap tests in order to avoid doing deltas.
1470*/
1471rename_count = find_exact_renames(options, &local_pool);1472/*1473* Discard local_pool immediately instead of at "cleanup:" in order
1474* to reduce maximum memory usage; inexact rename detection uses up
1475* a fair amount of memory, and mem_pools can too.
1476*/
1477mem_pool_discard(&local_pool, 0);1478trace2_region_leave("diff", "exact renames", options->repo);1479
1480/* Did we only want exact renames? */1481if (minimum_score == MAX_SCORE)1482goto cleanup;1483
1484num_sources = rename_src_nr;1485
1486if (want_copies || break_idx) {1487/*1488* Cull sources:
1489* - remove ones corresponding to exact renames
1490* - remove ones not found in relevant_sources
1491*/
1492trace2_region_enter("diff", "cull after exact", options->repo);1493remove_unneeded_paths_from_src(want_copies, relevant_sources);1494trace2_region_leave("diff", "cull after exact", options->repo);1495} else {1496/* Determine minimum score to match basenames */1497double factor = 0.5;1498char *basename_factor = getenv("GIT_BASENAME_FACTOR");1499int min_basename_score;1500
1501if (basename_factor)1502factor = strtol(basename_factor, NULL, 10)/100.0;1503assert(factor >= 0.0 && factor <= 1.0);1504min_basename_score = minimum_score +1505(int)(factor * (MAX_SCORE - minimum_score));1506
1507/*1508* Cull sources:
1509* - remove ones involved in renames (found via exact match)
1510*/
1511trace2_region_enter("diff", "cull after exact", options->repo);1512remove_unneeded_paths_from_src(want_copies, NULL);1513trace2_region_leave("diff", "cull after exact", options->repo);1514
1515/* Preparation for basename-driven matching. */1516trace2_region_enter("diff", "dir rename setup", options->repo);1517initialize_dir_rename_info(&info, relevant_sources,1518dirs_removed, dir_rename_count,1519cached_pairs);1520trace2_region_leave("diff", "dir rename setup", options->repo);1521
1522/* Utilize file basenames to quickly find renames. */1523trace2_region_enter("diff", "basename matches", options->repo);1524rename_count += find_basename_matches(options,1525min_basename_score,1526&info,1527relevant_sources,1528dirs_removed);1529trace2_region_leave("diff", "basename matches", options->repo);1530
1531/*1532* Cull sources, again:
1533* - remove ones involved in renames (found via basenames)
1534* - remove ones not found in relevant_sources
1535* and
1536* - remove ones in relevant_sources which are needed only
1537* for directory renames IF no ancestory directory
1538* actually needs to know any more individual path
1539* renames under them
1540*/
1541trace2_region_enter("diff", "cull basename", options->repo);1542remove_unneeded_paths_from_src(want_copies, relevant_sources);1543handle_early_known_dir_renames(&info, relevant_sources,1544dirs_removed);1545trace2_region_leave("diff", "cull basename", options->repo);1546}1547
1548/* Calculate how many rename destinations are left */1549num_destinations = (rename_dst_nr - rename_count);1550num_sources = rename_src_nr; /* rename_src_nr reflects lower number */1551
1552/* All done? */1553if (!num_destinations || !num_sources)1554goto cleanup;1555
1556switch (too_many_rename_candidates(num_destinations, num_sources,1557options)) {1558case 1:1559goto cleanup;1560case 2:1561options->degraded_cc_to_c = 1;1562skip_unmodified = 1;1563break;1564default:1565break;1566}1567
1568trace2_region_enter("diff", "inexact renames", options->repo);1569if (options->show_rename_progress) {1570progress = start_delayed_progress(1571_("Performing inexact rename detection"),1572(uint64_t)num_destinations * (uint64_t)num_sources);1573}1574
1575/* Finish setting up dpf_options */1576prefetch_options.skip_unmodified = skip_unmodified;1577if (options->repo == the_repository && repo_has_promisor_remote(the_repository)) {1578dpf_options.missing_object_cb = inexact_prefetch;1579dpf_options.missing_object_data = &prefetch_options;1580}1581
1582CALLOC_ARRAY(mx, st_mult(NUM_CANDIDATE_PER_DST, num_destinations));1583for (dst_cnt = i = 0; i < rename_dst_nr; i++) {1584struct diff_filespec *two = rename_dst[i].p->two;1585struct diff_score *m;1586
1587if (rename_dst[i].is_rename)1588continue; /* exact or basename match already handled */1589
1590m = &mx[dst_cnt * NUM_CANDIDATE_PER_DST];1591for (j = 0; j < NUM_CANDIDATE_PER_DST; j++)1592m[j].dst = -1;1593
1594for (j = 0; j < rename_src_nr; j++) {1595struct diff_filespec *one = rename_src[j].p->one;1596struct diff_score this_src;1597
1598assert(!one->rename_used || want_copies || break_idx);1599
1600if (skip_unmodified &&1601diff_unmodified_pair(rename_src[j].p))1602continue;1603
1604this_src.score = estimate_similarity(options->repo,1605one, two,1606minimum_score,1607&dpf_options);1608this_src.name_score = basename_same(one, two);1609this_src.dst = i;1610this_src.src = j;1611record_if_better(m, &this_src);1612/*1613* Once we run estimate_similarity,
1614* We do not need the text anymore.
1615*/
1616diff_free_filespec_blob(one);1617diff_free_filespec_blob(two);1618}1619dst_cnt++;1620display_progress(progress,1621(uint64_t)dst_cnt * (uint64_t)num_sources);1622}1623stop_progress(&progress);1624
1625/* cost matrix sorted by most to least similar pair */1626STABLE_QSORT(mx, dst_cnt * NUM_CANDIDATE_PER_DST, score_compare);1627
1628rename_count += find_renames(mx, dst_cnt, minimum_score, 0,1629&info, dirs_removed);1630if (want_copies)1631rename_count += find_renames(mx, dst_cnt, minimum_score, 1,1632&info, dirs_removed);1633free(mx);1634trace2_region_leave("diff", "inexact renames", options->repo);1635
1636cleanup:1637/* At this point, we have found some renames and copies and they1638* are recorded in rename_dst. The original list is still in *q.
1639*/
1640trace2_region_enter("diff", "write back to queue", options->repo);1641DIFF_QUEUE_CLEAR(&outq);1642for (i = 0; i < q->nr; i++) {1643struct diff_filepair *p = q->queue[i];1644struct diff_filepair *pair_to_free = NULL;1645
1646if (DIFF_PAIR_UNMERGED(p)) {1647diff_q(&outq, p);1648}1649else if (!DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {1650/* Creation */1651diff_q(&outq, p);1652}1653else if (DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two)) {1654/*1655* Deletion
1656*
1657* We would output this delete record if:
1658*
1659* (1) this is a broken delete and the counterpart
1660* broken create remains in the output; or
1661* (2) this is not a broken delete, and rename_dst
1662* does not have a rename/copy to move p->one->path
1663* out of existence.
1664*
1665* Otherwise, the counterpart broken create
1666* has been turned into a rename-edit; or
1667* delete did not have a matching create to
1668* begin with.
1669*/
1670if (DIFF_PAIR_BROKEN(p)) {1671/* broken delete */1672struct diff_rename_dst *dst = locate_rename_dst(p);1673if (!dst)1674BUG("tracking failed somehow; failed to find associated dst for broken pair");1675if (dst->is_rename)1676/* counterpart is now rename/copy */1677pair_to_free = p;1678}1679else {1680if (p->one->rename_used)1681/* this path remains */1682pair_to_free = p;1683}1684
1685if (!pair_to_free)1686diff_q(&outq, p);1687}1688else if (!diff_unmodified_pair(p))1689/* all the usual ones need to be kept */1690diff_q(&outq, p);1691else1692/* no need to keep unmodified pairs */1693pair_to_free = p;1694
1695if (pair_to_free)1696pool_diff_free_filepair(pool, pair_to_free);1697}1698diff_debug_queue("done copying original", &outq);1699
1700free(q->queue);1701*q = outq;1702diff_debug_queue("done collapsing", q);1703
1704for (i = 0; i < rename_dst_nr; i++)1705if (rename_dst[i].filespec_to_free)1706pool_free_filespec(pool, rename_dst[i].filespec_to_free);1707
1708cleanup_dir_rename_info(&info, dirs_removed, dir_rename_count != NULL);1709FREE_AND_NULL(rename_dst);1710rename_dst_nr = rename_dst_alloc = 0;1711FREE_AND_NULL(rename_src);1712rename_src_nr = rename_src_alloc = 0;1713if (break_idx) {1714strintmap_clear(break_idx);1715FREE_AND_NULL(break_idx);1716}1717trace2_region_leave("diff", "write back to queue", options->repo);1718return;1719}
1720
1721void diffcore_rename(struct diff_options *options)1722{
1723diffcore_rename_extended(options, NULL, NULL, NULL, NULL, NULL);1724}
1725