The local copy we do for --compare-dest simplifies the logic near
[rsync/rsync-patches.git] / copy-dest.diff
1 This adds the option --copy-dest, which works just like --link-dest
2 except that identical files are copied into the destination instead
3 of hard-linked.
4
5 --- orig/generator.c    2005-03-03 00:14:56
6 +++ generator.c 2005-03-03 00:25:59
7 @@ -65,6 +65,7 @@ extern int always_checksum;
8  extern char *partial_dir;
9  extern char *basis_dir[];
10  extern int compare_dest;
11 +extern int copy_dest;
12  extern int link_dest;
13  extern int whole_file;
14  extern int local_server;
15 @@ -824,6 +825,8 @@ static void recv_generator(char *fname, 
16                                         continue;
17                                 best_match = i;
18                                 match_level = 2;
19 +                               if (copy_dest)
20 +                                       break;
21                                 /* FALL THROUGH */
22                         case 2:
23                                 if (!unchanged_attrs(file, &st))
24 @@ -857,7 +860,20 @@ static void recv_generator(char *fname, 
25                                 match_level = 2;
26                         }
27  #endif
28 -                       if (compare_dest || (match_level && match_level < 3)) {
29 +                       if (match_level == 2) {
30 +                               /* Copy the file locally. */
31 +                               if (copy_file(fnamecmpbuf, fname, file->mode) < 0) {
32 +                                       if (verbose) {
33 +                                               rsyserr(FINFO, errno,
34 +                                                       "copy_file %s => %s",
35 +                                                       full_fname(fnamecmpbuf),
36 +                                                       safe_fname(fname));
37 +                                       }
38 +                                       match_level = 0;
39 +                                       statret = -1;
40 +                               } else
41 +                                       set_perms(fname, file, NULL, 0);
42 +                       } else if (compare_dest || match_level == 1) {
43                                 fnamecmp = fnamecmpbuf;
44                                 fnamecmp_type = i;
45                         }
46 @@ -935,11 +951,9 @@ static void recv_generator(char *fname, 
47                         return;
48                 }
49                 /* Only --compare-dest gets here. */
50 -               if (unchanged_attrs(file, &st)) {
51 -                       itemize(file, statret, &st, ITEM_NO_DEST_AND_NO_UPDATE,
52 -                               f_out, ndx);
53 -                       return;
54 -               }
55 +               itemize(file, statret, &st, ITEM_NO_DEST_AND_NO_UPDATE,
56 +                       f_out, ndx);
57 +               return;
58         }
59  
60  prepare_to_open:
61 --- orig/options.c      2005-03-02 09:52:06
62 +++ options.c   2005-03-02 10:05:21
63 @@ -143,6 +143,7 @@ char *backup_dir = NULL;
64  char backup_dir_buf[MAXPATHLEN];
65  int rsync_port = 0;
66  int compare_dest = 0;
67 +int copy_dest = 0;
68  int link_dest = 0;
69  int basis_dir_cnt = 0;
70  
71 @@ -317,6 +318,7 @@ void usage(enum logcode F)
72    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
73    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
74    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
75 +  rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
76    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
77    rprintf(F," -z, --compress              compress file data during the transfer\n");
78    rprintf(F," -C, --cvs-exclude           auto-ignore files the same way CVS does\n");
79 @@ -355,7 +357,7 @@ void usage(enum logcode F)
80  }
81  
82  enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
83 -      OPT_FILTER, OPT_COMPARE_DEST, OPT_LINK_DEST,
84 +      OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
85        OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
86        OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
87        OPT_REFUSED_BASE = 9000};
88 @@ -424,6 +426,7 @@ static struct poptOption long_options[] 
89    {"timeout",          0,  POPT_ARG_INT,    &io_timeout, OPT_TIMEOUT, 0, 0 },
90    {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
91    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
92 +  {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
93    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
94    {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
95    /* TODO: Should this take an optional int giving the compression level? */
96 @@ -838,6 +841,11 @@ int parse_arguments(int *argc, const cha
97                         return 0;
98  #endif
99  
100 +               case OPT_COPY_DEST:
101 +                       copy_dest = 1;
102 +                       dest_option = "--copy-dest";
103 +                       goto set_dest_dir;
104 +
105                 case OPT_COMPARE_DEST:
106                         compare_dest = 1;
107                         dest_option = "--compare-dest";
108 @@ -928,9 +936,9 @@ int parse_arguments(int *argc, const cha
109                 return 0;
110         }
111  
112 -       if (compare_dest + link_dest > 1) {
113 +       if (compare_dest + copy_dest + link_dest > 1) {
114                 snprintf(err_buf, sizeof err_buf,
115 -                       "You may not mix --compare-dest and --link-dest.\n");
116 +                       "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
117                 return 0;
118         }
119  
120 --- orig/rsync.yo       2005-03-02 18:01:33
121 +++ rsync.yo    2005-02-23 02:05:34
122 @@ -353,6 +353,7 @@ to the detailed description below for a 
123   -T, --temp-dir=DIR          create temporary files in directory DIR
124   -y, --fuzzy                 find similar file for basis if no dest file
125       --compare-dest=DIR      also compare received files relative to DIR
126 +     --copy-dest=DIR         ... and include copies of unchanged files
127       --link-dest=DIR         hardlink to files in DIR when unchanged
128   -z, --compress              compress file data during the transfer
129   -C, --cvs-exclude           auto-ignore files in the same way CVS does
130 @@ -554,8 +555,8 @@ bound.
131  
132  The option implies bf(--partial) (since an interrupted transfer does not delete
133  the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
134 -Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest)
135 -and bf(--link-dest).
136 +Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest),
137 +bf(--copy-dest), and bf(--link-dest).
138  
139  WARNING: The file's data will be in an inconsistent state during the
140  transfer (and possibly afterward if the transfer gets interrupted), so you
141 @@ -957,9 +958,19 @@ the list in the order specified), and if
142  of the em(DIR)s will be selected to try to speed up the transfer.
143  
144  If em(DIR) is a relative path, it is relative to the destination directory.
145 -See also bf(--link-dest).
146 +See also bf(--copy-dest) and bf(--link-dest).
147  
148 -dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest), but
149 +dit(bf(--copy-dest=DIR)) This option behaves like bf(--compare-dest), but
150 +rsync will also copy unchanged files found in em(DIR) to the destination
151 +directory (using the data in the em(DIR) for an efficient copy).  This is
152 +useful for doing transfers to a new destination while leaving existing
153 +files intact, and then doing a flash-cutover when all files have been
154 +successfully transferred.
155 +
156 +If em(DIR) is a relative path, it is relative to the destination directory.
157 +See also bf(--compare-dest) and bf(--link-dest).
158 +
159 +dit(bf(--link-dest=DIR)) This option behaves like bf(--copy-dest), but
160  unchanged files are hard linked from em(DIR) to the destination directory.
161  The files must be identical in all preserved attributes (e.g. permissions,
162  possibly ownership) in order for the files to be linked together.
163 @@ -973,7 +984,7 @@ the list in the order specified), and if
164  of the em(DIR)s will be selected to try to speed up the transfer.
165  
166  If em(DIR) is a relative path, it is relative to the destination directory.
167 -See also bf(--compare-dest).
168 +See also bf(--compare-dest) and bf(--copy-dest).
169  
170  Note that rsync versions prior to 2.6.1 had a bug that could prevent
171  bf(--link-dest) from working properly for a non-root user when bf(-o) was specified
172 --- orig/testsuite/compare-dest.test    2005-02-26 19:51:27
173 +++ testsuite/compare-dest.test 2005-03-01 15:57:27
174 @@ -31,9 +31,9 @@ $RSYNC -av --exclude=/text --exclude=etc
175  checkit "$RSYNC -avv --no-whole-file \
176      --compare-dest=\"$alt1dir\" --compare-dest=\"$alt2dir\" \
177      \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
178 -#checkit "$RSYNC -avv --no-whole-file \
179 -#    --copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
180 -#    \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
181 +checkit "$RSYNC -avv --no-whole-file \
182 +    --copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
183 +    \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
184  
185  # The script would have aborted on error, so getting here means we've won.
186  exit 0