If diff.cacherenames is true, then renames will be cached to $GIT_DIR/rename-cache. By default, it will not overwrite existing cache. Add --refresh-cache to overwrite. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- if git-svn is going to use this, then perharps we should add a rule to prevent overwriting certain cache files with .keep files, so that git-svn generated cache does not get lost Documentation/config.txt | 5 ++++ Documentation/diff-options.txt | 5 ++++ diff.c | 12 +++++++++++ diff.h | 2 + diffcore-rename.c | 41 ++++++++++++++++++++++++++++++++++++++++ t/t4030-rename-cache.sh | 27 ++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 0 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 29369d0..81160d3 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -630,6 +630,11 @@ diff.renames:: will enable basic rename detection. If set to "copies" or "copy", it will detect copies, as well. +diff.cacherenames:: + Tells git to automatically cache renames when detected. The + cache resides in $GIT_DIR/rename-cache, which is used by git + if exists. + fetch.unpackLimit:: If the number of objects fetched over the git native transfer is below this diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index c62b45c..d477a40 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -102,6 +102,11 @@ endif::git-format-patch[] Turn off rename detection, even when the configuration file gives the default to do so. +--refresh-rename-cache:: + By default, when git finds a cached version of a commit, it + will not overwrite the cache. This option makes git overwrite + old cache or create a new one. + --check:: Warn if changes introduce trailing whitespace or an indent that uses a space before a tab. Exits with diff --git a/diff.c b/diff.c index e368fef..1d65bd9 100644 --- a/diff.c +++ b/diff.c @@ -26,6 +26,7 @@ int diff_use_color_default = -1; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; +static int diff_cache_renames; static char diff_colors[][COLOR_MAXLEN] = { "\033[m", /* reset */ @@ -109,6 +110,11 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } + if (!strcmp(var, "diff.cacherenames")) { + diff_cache_renames = git_config_bool(var, value); + return 0; + } + if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); if (!value) @@ -2248,6 +2254,8 @@ int diff_setup_done(struct diff_options *options) if (options->detect_rename && options->rename_limit < 0) options->rename_limit = diff_rename_limit_default; + if (options->detect_rename) + options->cache_renames = diff_cache_renames; if (options->setup & DIFF_SETUP_USE_CACHE) { if (!active_cache) /* read-cache does not die even when it fails @@ -2415,6 +2423,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, RELATIVE_NAME); options->prefix = arg + 11; } + else if (!strcmp(arg, "--refresh-rename-cache")) { + options->cache_renames = 1; + options->refresh_rename_cache = 1; + } /* xdiff options */ else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) diff --git a/diff.h b/diff.h index 8b68f6f..eb97955 100644 --- a/diff.h +++ b/diff.h @@ -85,6 +85,8 @@ struct diff_options { int pickaxe_opts; int rename_score; int rename_limit; + int cache_renames; + int refresh_rename_cache; int warn_on_too_large_rename; int dirstat_percent; int setup; diff --git a/diffcore-rename.c b/diffcore-rename.c index 598cc8d..2b87e4e 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -527,6 +527,44 @@ static void load_rename_cache(struct diff_queue_struct *q, free_hash(&filepair_table); } +static void save_rename_cache(struct diff_queue_struct *outq, + struct diff_options *options) +{ + int i; + FILE *fp = NULL; + struct stat st; + + for (i = 0;i < outq->nr; i++) { + struct diff_filepair *dp = outq->queue[i]; + + if (!(dp->renamed_pair || /* rename pair */ + (!DIFF_FILE_VALID(dp->one) && DIFF_FILE_VALID(dp->two)))) /* create pair */ + continue; + + if (!fp) { + char *sha1 = sha1_to_hex(options->commit->object.sha1); + char *path = git_path("rename-cache/%c%c/%s", sha1[0], sha1[1], sha1+2); + + /* Already cached. If not force refresh, move on */ + if (!stat(path, &st) && !options->refresh_rename_cache) + return; + + safe_create_leading_directories(path); + fp = fopen(path, "w"); + + if (!fp) + return; + } + + fprintf(fp, "%s ", sha1_to_hex(dp->two->sha1)); + fprintf(fp, "%s %d\n", + sha1_to_hex(DIFF_FILE_VALID(dp->one) ? dp->one->sha1 : null_sha1), + dp->score); + } + if (fp) + fclose(fp); +} + void diffcore_rename(struct diff_options *options) { int detect_rename = options->detect_rename; @@ -770,6 +808,9 @@ void diffcore_rename(struct diff_options *options) } diff_debug_queue("done copying original", &outq); + if (options->commit && options->cache_renames) + save_rename_cache(&outq, options); + free(q->queue); if (cacheq.queue) free(cacheq.queue); diff --git a/t/t4030-rename-cache.sh b/t/t4030-rename-cache.sh index 0d8390c..24d3667 100755 --- a/t/t4030-rename-cache.sh +++ b/t/t4030-rename-cache.sh @@ -52,4 +52,31 @@ test_expect_success 'load create pair cache' ' test_cmp expected result ' +cat >expected <<EOF +f2ad6c76f0115a6ba5b00456a849810e7ec0af20 0000000000000000000000000000000000000000 0 +78981922613b2afb6025042ff6bd878ac1994e85 78981922613b2afb6025042ff6bd878ac1994e85 60000 +EOF +test_expect_success 'save rename cache' ' + P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,") && + rm -r .git/rename-cache + git config diff.cacherenames true + git show --summary -C -M --find-copies-harder > /dev/null + test_cmp expected $P +' + +test_expect_success 'subsequent command does not change cache' ' + P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,") && + echo corrupted >> $P + ! test_cmp expected $P && + git show --summary -C -M --find-copies-harder HEAD > /dev/null && + ! test_cmp expected $P +' + +test_expect_success 'overwrite cache with --refresh-rename-cache' ' + P=.git/rename-cache/$(git rev-parse HEAD|sed "s,\(..\)\(.*\),\1/\2,") && + ! test_cmp expected $P && + git show --summary -C -M --find-copies-harder --refresh-rename-cache HEAD > /dev/null && + test_cmp expected $P +' + test_done -- 1.6.0.3.802.g47c38 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html