The patches for 3.3.0.
[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 based-on: patch/master/detect-renamed
24 diff --git a/generator.c b/generator.c
25 --- a/generator.c
26 +++ b/generator.c
27 @@ -467,7 +467,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 @@ -1991,6 +1993,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 && quick_check_ok(FT_REG, 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 --- a/options.c
62 +++ b/options.c
63 @@ -744,7 +744,9 @@ static struct poptOption long_options[] = {
64    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
65    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
66    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
67 -  {"detect-renamed",   0,  POPT_ARG_NONE,   &detect_renamed, 0, 0, 0 },
68 +  {"detect-renamed",   0,  POPT_ARG_VAL,    &detect_renamed, 1, 0, 0 },
69 +  {"detect-renamed-lax",0, POPT_ARG_VAL,    &detect_renamed, 2, 0, 0 },
70 +  {"detect-moved",     0,  POPT_ARG_VAL,    &detect_renamed, 3, 0, 0 },
71    {"fuzzy",           'y', POPT_ARG_NONE,   0, 'y', 0, 0 },
72    {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
73    {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
74 @@ -2838,8 +2840,14 @@ void server_options(char **args, int *argc_p)
75                         args[ac++] = "--super";
76                 if (size_only)
77                         args[ac++] = "--size-only";
78 -               if (detect_renamed)
79 -                       args[ac++] = "--detect-renamed";
80 +               if (detect_renamed) {
81 +                       if (detect_renamed == 1)
82 +                               args[ac++] = "--detect-renamed";
83 +                       else if (detect_renamed == 2)
84 +                               args[ac++] = "--detect-renamed-lax";
85 +                       else
86 +                               args[ac++] = "--detect-moved";
87 +               }
88                 if (do_stats)
89                         args[ac++] = "--stats";
90         } else {
91 diff --git a/rsync.1.md b/rsync.1.md
92 --- a/rsync.1.md
93 +++ b/rsync.1.md
94 @@ -508,6 +508,8 @@ has its own detailed description later in this manpage.
95  --temp-dir=DIR, -T       create temporary files in directory DIR
96  --fuzzy, -y              find similar file for basis if no dest file
97  --detect-renamed         try to find renamed files to speed the xfer
98 +--detect-renamed-lax     ...& assume identical to src files (risky!)
99 +--detect-moved           ... only if basenames match (less risky)
100  --compare-dest=DIR       also compare destination files relative to DIR
101  --copy-dest=DIR          ... and include copies of unchanged files
102  --link-dest=DIR          hardlink to files in DIR when unchanged
103 @@ -2652,6 +2654,20 @@ expand it.
104      otential alternate-basis files will be removed as the transfer progresses.
105      This option conflicts with [`--inplace`](#opt) and [`--append`](#opt).
106  
107 +0.  `--detect-renamed-lax`
108 +
109 +    This version of [`--detect-renamed`](#opt) makes rsync hard-link `dest/D`
110 +    to `dest/S` without verifying that `src/S` and `dest/S` have the same data.
111 +    This poses a significant risk of corrupting the destination by representing
112 +    a new source file by an unrelated destination file that coincidentally
113 +    passes the quick check with the source file.  Use this option only if you
114 +    accept the risk and disk I/O is a bottleneck.
115 +
116 +0.  `--detect-moved`
117 +
118 +    A less risky variant of [`--detect-renamed-lax`](#opt) that only uses a
119 +    destination file that has the same basename as the new source file.
120 +
121  0.  `--compare-dest=DIR`
122  
123      This option instructs rsync to use _DIR_ on the destination machine as an