My version of Matt's --trust-rename patch.
authorWayne Davison <wayned@samba.org>
Sat, 13 Oct 2007 05:19:57 +0000 (05:19 +0000)
committerWayne Davison <wayned@samba.org>
Sat, 13 Oct 2007 05:19:57 +0000 (05:19 +0000)
detect-renamed-lax.diff [new file with mode: 0644]

diff --git a/detect-renamed-lax.diff b/detect-renamed-lax.diff
new file mode 100644 (file)
index 0000000..66cb788
--- /dev/null
@@ -0,0 +1,125 @@
+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 <patches/detect-renamed.diff
+    patch -p1 <patches/detect-renamed-lax.diff
+    ./configure                                 (optional if already run)
+    make
+
+FIXME: If a run with --detect-renamed-lax stages a different-basename
+destination file and then gets interrupted, a subsequent run that
+switches to --detect-moved blindly accepts the staged file.
+
+-- Matt McCutchen <hashproduct+rsync@gmail.com>
+
+--- old/generator.c
++++ new/generator.c
+@@ -188,7 +188,9 @@ static int fattr_find(struct file_struct
+                               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;
+@@ -1826,6 +1828,21 @@ static void recv_generator(char *fname, 
+               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)
+--- old/options.c
++++ new/options.c
+@@ -385,6 +385,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");
+@@ -563,7 +565,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_NONE,   &fuzzy_basis, 0, 0, 0 },
+   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
+   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
+@@ -1895,8 +1899,14 @@ void server_options(char **args, int *ar
+               }
+       }
+       /* Both sides need to know in case this disables incremental recursion. */
+-      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 (modify_window_set) {
+               if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
+--- old/rsync.yo
++++ new/rsync.yo
+@@ -385,6 +385,8 @@ to the detailed description below for a 
+  -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
+@@ -1446,6 +1448,17 @@ the bf(--partial-dir) option, that direc
+ 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