This patch adds the options --detect-renamed-lax and --detect-moved. These modify the --detect-renamed algorithm to adopt a matching file without verifying that the content is as expected. The former blindly accepts a file that matches in size and modified time. The latter requires that the filename also match (ignoring any renamed files). This patch is EXPERIMENTAL, though it did work correctly in my light testing. To use this patch, run these commands for a successful build: patch -p1 based-on: patch/master/detect-renamed diff --git a/generator.c b/generator.c --- a/generator.c +++ b/generator.c @@ -468,7 +468,9 @@ static int fattr_find(struct file_struct *f, char *fname) continue; } } - ok_match = mid; + /* --detect-moved doesn't allow non-basename matches */ + if (detect_renamed != 3) + ok_match = mid; diff = u_strcmp(fmid->basename, f->basename); if (diff == 0) { good_match = mid; @@ -1783,6 +1785,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, fnamecmp = partialptr; fnamecmp_type = FNAMECMP_PARTIAL_DIR; statret = 0; + if (detect_renamed > 1 && unchanged_file(fnamecmp, file, &sx.st)) { + /* Adopt the partial file. */ + finish_transfer(fname, fnamecmp, NULL, NULL, file, 1, 1); + handle_partial_dir(partialptr, PDIR_DELETE); + if (itemizing) + itemize(fnamecmp, file, ndx, -1, &sx, + ITEM_LOCAL_CHANGE, fnamecmp_type, NULL); +#ifdef SUPPORT_HARD_LINKS + if (preserve_hard_links && F_IS_HLINKED(file)) + finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); +#endif + if (remove_source_files == 1) + goto return_with_success; + goto cleanup; + } } if (!do_xfers) diff --git a/options.c b/options.c --- a/options.c +++ b/options.c @@ -745,6 +745,8 @@ void usage(enum logcode F) rprintf(F," -T, --temp-dir=DIR create temporary files in directory DIR\n"); rprintf(F," -y, --fuzzy find similar file for basis if no dest file\n"); rprintf(F," --detect-renamed try to find renamed files to speed up the transfer\n"); + rprintf(F," --detect-renamed-lax ... and assume identical to source files (risky!)\n"); + rprintf(F," --detect-moved ... only if basenames match (less risky)\n"); rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n"); rprintf(F," --copy-dest=DIR ... and include copies of unchanged files\n"); rprintf(F," --link-dest=DIR hardlink to files in DIR when unchanged\n"); @@ -940,7 +942,9 @@ static struct poptOption long_options[] = { {"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 }, {"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 }, {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 }, - {"detect-renamed", 0, POPT_ARG_NONE, &detect_renamed, 0, 0, 0 }, + {"detect-renamed", 0, POPT_ARG_VAL, &detect_renamed, 1, 0, 0 }, + {"detect-renamed-lax",0, POPT_ARG_VAL, &detect_renamed, 2, 0, 0 }, + {"detect-moved", 0, POPT_ARG_VAL, &detect_renamed, 3, 0, 0 }, {"fuzzy", 'y', POPT_ARG_VAL, &fuzzy_basis, 1, 0, 0 }, {"no-fuzzy", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 }, {"no-y", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 }, @@ -2532,8 +2536,14 @@ void server_options(char **args, int *argc_p) args[ac++] = "--super"; if (size_only) args[ac++] = "--size-only"; - if (detect_renamed) - args[ac++] = "--detect-renamed"; + if (detect_renamed) { + if (detect_renamed == 1) + args[ac++] = "--detect-renamed"; + else if (detect_renamed == 2) + args[ac++] = "--detect-renamed-lax"; + else + args[ac++] = "--detect-moved"; + } if (do_stats) args[ac++] = "--stats"; } else { diff --git a/rsync.yo b/rsync.yo --- a/rsync.yo +++ b/rsync.yo @@ -398,6 +398,8 @@ to the detailed description below for a complete description. verb( -T, --temp-dir=DIR create temporary files in directory DIR -y, --fuzzy find similar file for basis if no dest file --detect-renamed try to find renamed files to speed the xfer + --detect-renamed-lax ...& assume identical to src files (risky!) + --detect-moved ... only if basenames match (less risky) --compare-dest=DIR also compare received files relative to DIR --copy-dest=DIR ... and include copies of unchanged files --link-dest=DIR hardlink to files in DIR when unchanged @@ -1656,6 +1658,17 @@ the bf(--partial-dir) option, that directory will be used instead. These potential alternate-basis files will be removed as the transfer progresses. This option conflicts with bf(--inplace) and bf(--append). +dit(bf(--detect-renamed-lax)) This version of bf(--detect-renamed) +makes rsync hard-link em(dest/D) to em(dest/S) without verifying that +em(src/S) and em(dest/S) have the same data. This poses a significant risk +of corrupting the destination by representing a new source file by an +unrelated destination file that coincidentally passes the quick check with the +source file. Use this option only if you accept the risk and disk I/O is a +bottleneck. + +dit(bf(--detect-moved)) A less risky variant of bf(--detect-renamed-lax) that +only uses a destination file that has the same basename as the new source file. + dit(bf(--compare-dest=DIR)) This option instructs rsync to use em(DIR) on the destination machine as an additional hierarchy to compare destination files against doing transfers (if the files are missing in the destination