On 10/12/07, Greg Siekas <[EMAIL PROTECTED]> wrote:
> The other option I thought of was to only do the move when the mtime,
> size, and filename match.   Not really a 'detect-renamed' but a
> 'detected-moved' type operation.

That's a good idea, and easy to implement too!  I have improved the
patch (attached) to provide separate --trust-rename and --trust-move
options.  Wayne, please consider adding this to patches/ .

Matt
In combination with detect-renamed.diff, this patch adds an option
--trust-rename that adopts the pre-rename destination file found for a
"new" source file without verifying that the data is actually the same.
It also adds a variant --trust-move that requires that the basenames
match.  These options are somewhat risky but were what Greg Siekas wanted:

http://lists.samba.org/archive/rsync/2007-October/018827.html

This patch is EXPERIMENTAL, though it did work correctly in my light
testing.

FIXME: If a run with --trust-rename stages a different-basename destination
file and then gets interrupted, a subsequent run with --trust-move trusts
the staged file.

-- Matt McCutchen <[EMAIL PROTECTED]>

--- old/generator.c
+++ new/generator.c
@@ -80,6 +80,7 @@ extern int compare_dest;
 extern int copy_dest;
 extern int link_dest;
 extern int detect_renamed;
+extern int trust_rename;
 extern int whole_file;
 extern int list_only;
 extern int read_batch;
@@ -212,7 +213,9 @@ static int fattr_find(struct file_struct
 			high = mid - 1;
 	}
 
-	return good_match >= 0 ? good_match : ok_match;
+	return good_match >= 0 ? good_match :
+		/* --trust-move doesn't allow non-basename matches */
+		(trust_rename == 1) ? -1 : ok_match;
 }
 
 static void look_for_rename(struct file_struct *file, char *fname)
@@ -1826,6 +1829,22 @@ static void recv_generator(char *fname, 
 		fnamecmp = partialptr;
 		fnamecmp_type = FNAMECMP_PARTIAL_DIR;
 		statret = 0;
+		if (detect_renamed && trust_rename
+				&& 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
@@ -81,6 +81,7 @@ int am_starting_up = 1;
 int relative_paths = -1;
 int implied_dirs = 1;
 int detect_renamed = 0;
+int trust_rename = 0;
 int numeric_ids = 0;
 int allow_8bit_chars = 0;
 int force_delete = 0;
@@ -385,6 +386,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,"     --trust-rename          ... and assume identical to source files (risky!)\n");
+  rprintf(F,"     --trust-move            ... 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");
@@ -564,6 +567,8 @@ static struct poptOption long_options[] 
   {"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 },
+  {"trust-rename",     0,  POPT_ARG_VAL,    &trust_rename, 2, 0, 0 },
+  {"trust-move",       0,  POPT_ARG_VAL,    &trust_rename, 1, 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 +1900,13 @@ void server_options(char **args, int *ar
 		}
 	}
 	/* Both sides need to know in case this disables incremental recursion. */
-	if (detect_renamed)
+	if (detect_renamed) {
 		args[ac++] = "--detect-renamed";
+		/* But the addition of --trust-* is only the receiver's business. */
+		if (am_sender && trust_rename)
+			args[ac++] = (trust_rename == 2) ?
+					"--trust-rename" : "--trust-move";
+	}
 
 	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
+     --trust-rename          ...& assume identical to src files (risky!)
+     --trust-move            ... 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
@@ -1440,6 +1442,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(--trust-rename)) In combination with bf(--detect-renamed), this
+option 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(--trust-move)) A less risky variant of bf(--trust-rename) 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
-- 
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to