Updated patches to work with the current trunk.
[rsync/rsync-patches.git] / detect-renamed-lax.diff
1 This patch adds the options --detect-renamed-lax and --detect-moved.
2 These modify the --detect-renamed algorithm to adopt a matching file
3 without verifying that the content is as expected.  The former blindly
4 accepts a file that matches in size and modified time.  The latter
5 requires that the filename also match (ignoring any renamed files).
6
7 This patch is EXPERIMENTAL, though it did work correctly in my light
8 testing.
9
10 To use this patch, run these commands for a successful build:
11
12     patch -p1 <patches/detect-renamed.diff
13     patch -p1 <patches/detect-renamed-lax.diff
14     ./configure                                 (optional if already run)
15     make
16
17 FIXME: If a run with --detect-renamed-lax stages a different-basename
18 destination file and then gets interrupted, a subsequent run that
19 switches to --detect-moved blindly accepts the staged file.
20
21 -- Matt McCutchen <hashproduct+rsync@gmail.com>
22
23 diff --git a/generator.c b/generator.c
24 index 35ba203..ac844ac 100644
25 --- a/generator.c
26 +++ b/generator.c
27 @@ -469,7 +469,9 @@ static int fattr_find(struct file_struct *f, char *fname)
28                                 continue;
29                         }
30                 }
31 -               ok_match = mid;
32 +               /* --detect-moved doesn't allow non-basename matches */
33 +               if (detect_renamed != 3)
34 +                       ok_match = mid;
35                 diff = u_strcmp(fmid->basename, f->basename);
36                 if (diff == 0) {
37                         good_match = mid;
38 @@ -1796,6 +1798,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
39                 fnamecmp = partialptr;
40                 fnamecmp_type = FNAMECMP_PARTIAL_DIR;
41                 statret = 0;
42 +               if (detect_renamed > 1 && unchanged_file(fnamecmp, file, &sx.st)) {
43 +                       /* Adopt the partial file. */
44 +                       finish_transfer(fname, fnamecmp, NULL, NULL, file, 1, 1);
45 +                       handle_partial_dir(partialptr, PDIR_DELETE);
46 +                       if (itemizing)
47 +                               itemize(fnamecmp, file, ndx, -1, &sx,
48 +                                               ITEM_LOCAL_CHANGE, fnamecmp_type, NULL);
49 +#ifdef SUPPORT_HARD_LINKS
50 +                       if (preserve_hard_links && F_IS_HLINKED(file))
51 +                               finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);
52 +#endif
53 +                       if (remove_source_files == 1)
54 +                               goto return_with_success;
55 +                       goto cleanup;
56 +               }
57         }
58  
59         if (!do_xfers)
60 diff --git a/options.c b/options.c
61 index 7e454b3..1da38cb 100644
62 --- a/options.c
63 +++ b/options.c
64 @@ -744,6 +744,8 @@ void usage(enum logcode F)
65    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
66    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
67    rprintf(F,"     --detect-renamed        try to find renamed files to speed up the transfer\n");
68 +  rprintf(F,"     --detect-renamed-lax    ... and assume identical to source files (risky!)\n");
69 +  rprintf(F,"     --detect-moved          ... only if basenames match (less risky)\n");
70    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
71    rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
72    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
73 @@ -939,7 +941,9 @@ static struct poptOption long_options[] = {
74    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
75    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
76    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
77 -  {"detect-renamed",   0,  POPT_ARG_NONE,   &detect_renamed, 0, 0, 0 },
78 +  {"detect-renamed",   0,  POPT_ARG_VAL,    &detect_renamed, 1, 0, 0 },
79 +  {"detect-renamed-lax",0, POPT_ARG_VAL,    &detect_renamed, 2, 0, 0 },
80 +  {"detect-moved",     0,  POPT_ARG_VAL,    &detect_renamed, 3, 0, 0 },
81    {"fuzzy",           'y', POPT_ARG_VAL,    &fuzzy_basis, 1, 0, 0 },
82    {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
83    {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
84 @@ -2480,8 +2484,14 @@ void server_options(char **args, int *argc_p)
85                         args[ac++] = "--super";
86                 if (size_only)
87                         args[ac++] = "--size-only";
88 -               if (detect_renamed)
89 -                       args[ac++] = "--detect-renamed";
90 +               if (detect_renamed) {
91 +                       if (detect_renamed == 1)
92 +                               args[ac++] = "--detect-renamed";
93 +                       else if (detect_renamed == 2)
94 +                               args[ac++] = "--detect-renamed-lax";
95 +                       else
96 +                               args[ac++] = "--detect-moved";
97 +               }
98                 if (do_stats)
99                         args[ac++] = "--stats";
100         } else {
101 diff --git a/rsync.yo b/rsync.yo
102 index 4df39b0..e254152 100644
103 --- a/rsync.yo
104 +++ b/rsync.yo
105 @@ -398,6 +398,8 @@ to the detailed description below for a complete description.  verb(
106   -T, --temp-dir=DIR          create temporary files in directory DIR
107   -y, --fuzzy                 find similar file for basis if no dest file
108       --detect-renamed        try to find renamed files to speed the xfer
109 +     --detect-renamed-lax    ...& assume identical to src files (risky!)
110 +     --detect-moved          ... only if basenames match (less risky)
111       --compare-dest=DIR      also compare received files relative to DIR
112       --copy-dest=DIR         ... and include copies of unchanged files
113       --link-dest=DIR         hardlink to files in DIR when unchanged
114 @@ -1621,6 +1623,17 @@ the bf(--partial-dir) option, that directory will be used instead.  These
115  potential alternate-basis files will be removed as the transfer progresses.
116  This option conflicts with bf(--inplace) and bf(--append).
117  
118 +dit(bf(--detect-renamed-lax)) This version of bf(--detect-renamed)
119 +makes rsync hard-link em(dest/D) to em(dest/S) without verifying that
120 +em(src/S) and em(dest/S) have the same data.  This poses a significant risk
121 +of corrupting the destination by representing a new source file by an
122 +unrelated destination file that coincidentally passes the quick check with the
123 +source file.  Use this option only if you accept the risk and disk I/O is a
124 +bottleneck.
125 +
126 +dit(bf(--detect-moved)) A less risky variant of bf(--detect-renamed-lax) that
127 +only uses a destination file that has the same basename as the new source file.
128 +
129  dit(bf(--compare-dest=DIR)) This option instructs rsync to use em(DIR) on
130  the destination machine as an additional hierarchy to compare destination
131  files against doing transfers (if the files are missing in the destination