--- /dev/null
+This adds the option --copy-dest, which works just like --link-dest
+except that identical files are copied into the destination instead
+of hard-linked.
+
+--- orig/generator.c 2005-03-01 19:42:49
++++ generator.c 2005-03-01 19:43:39
+@@ -65,6 +65,7 @@ extern int always_checksum;
+ extern char *partial_dir;
+ extern char *basis_dir[];
+ extern int compare_dest;
++extern int copy_dest;
+ extern int link_dest;
+ extern int whole_file;
+ extern int local_server;
+@@ -831,6 +832,8 @@ static void recv_generator(char *fname,
+ case 1:
+ if (!unchanged_file(fnamecmpbuf, file, &st))
+ continue;
++ if (copy_dest)
++ break;
+ fallback_match = i;
+ match_level = 2;
+ /* FALL THROUGH */
+@@ -848,8 +851,19 @@ static void recv_generator(char *fname,
+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
+ basis_dir[i], fname);
+ }
++ if ((copy_dest && match_level == 3 && !dry_run)
++#ifdef HAVE_LINK
++ || (link_dest && match_level == 2 && !dry_run)
++#endif
++ ) {
++ /* Copy the file locally. */
++ if (copy_file(fnamecmpbuf, fname, file->mode) < 0) {
++ fnamecmp = fnamecmpbuf;
++ fnamecmp_type = i;
++ } else
++ set_perms(fname, file, NULL, 0);
+ #ifdef HAVE_LINK
+- if (link_dest && match_level == 3 && !dry_run) {
++ } else if (link_dest && match_level == 3 && !dry_run) {
+ if (do_link(fnamecmpbuf, fname) < 0) {
+ if (verbose) {
+ rsyserr(FINFO, errno,
+@@ -860,9 +874,8 @@ static void recv_generator(char *fname,
+ fnamecmp = fnamecmpbuf;
+ fnamecmp_type = i;
+ }
+- } else
+ #endif
+- {
++ } else {
+ fnamecmp = fnamecmpbuf;
+ fnamecmp_type = i;
+ }
+--- orig/options.c 2005-03-01 05:49:24
++++ options.c 2005-02-23 02:05:34
+@@ -143,6 +143,7 @@ char *backup_dir = NULL;
+ char backup_dir_buf[MAXPATHLEN];
+ int rsync_port = 0;
+ int compare_dest = 0;
++int copy_dest = 0;
+ int link_dest = 0;
+ int basis_dir_cnt = 0;
+
+@@ -317,6 +318,7 @@ 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," --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");
+ rprintf(F," -z, --compress compress file data during the transfer\n");
+ rprintf(F," -C, --cvs-exclude auto-ignore files the same way CVS does\n");
+@@ -355,7 +357,7 @@ void usage(enum logcode F)
+ }
+
+ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
+- OPT_FILTER, OPT_COMPARE_DEST, OPT_LINK_DEST,
++ OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
+ OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
+ OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
+ OPT_REFUSED_BASE = 9000};
+@@ -424,6 +426,7 @@ static struct poptOption long_options[]
+ {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
+ {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
+ {"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 },
+ {"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 },
+ /* TODO: Should this take an optional int giving the compression level? */
+@@ -838,6 +841,11 @@ int parse_arguments(int *argc, const cha
+ return 0;
+ #endif
+
++ case OPT_COPY_DEST:
++ copy_dest = 1;
++ dest_option = "--copy-dest";
++ goto set_dest_dir;
++
+ case OPT_COMPARE_DEST:
+ compare_dest = 1;
+ dest_option = "--compare-dest";
+@@ -928,9 +936,9 @@ int parse_arguments(int *argc, const cha
+ return 0;
+ }
+
+- if (compare_dest + link_dest > 1) {
++ if (compare_dest + copy_dest + link_dest > 1) {
+ snprintf(err_buf, sizeof err_buf,
+- "You may not mix --compare-dest and --link-dest.\n");
++ "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
+ return 0;
+ }
+
+--- orig/rsync.yo 2005-03-01 19:42:49
++++ rsync.yo 2005-02-23 02:05:34
+@@ -353,6 +353,7 @@ 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
+ --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
+ -z, --compress compress file data during the transfer
+ -C, --cvs-exclude auto-ignore files in the same way CVS does
+@@ -554,8 +555,8 @@ bound.
+
+ The option implies bf(--partial) (since an interrupted transfer does not delete
+ the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
+-Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest)
+-and bf(--link-dest).
++Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest),
++bf(--copy-dest), and bf(--link-dest).
+
+ WARNING: The file's data will be in an inconsistent state during the
+ transfer (and possibly afterward if the transfer gets interrupted), so you
+@@ -949,9 +950,19 @@ finds an existing file. That first disc
+ and also determines if the transfer needs to happen.
+
+ If em(DIR) is a relative path, it is relative to the destination directory.
+-See also bf(--link-dest).
++See also bf(--copy-dest) and bf(--link-dest).
+
+-dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest), but
++dit(bf(--copy-dest=DIR)) This option behaves like bf(--compare-dest), but
++rsync will also copy unchanged files found in em(DIR) to the destination
++directory (using the data in the em(DIR) for an efficient copy). This is
++useful for doing transfers to a new destination while leaving existing
++files intact, and then doing a flash-cutover when all files have been
++successfully transferred.
++
++If em(DIR) is a relative path, it is relative to the destination directory.
++See also bf(--compare-dest) and bf(--link-dest).
++
++dit(bf(--link-dest=DIR)) This option behaves like bf(--copy-dest), but
+ unchanged files are hard linked from em(DIR) to the destination directory.
+ The files must be identical in all preserved attributes (e.g. permissions,
+ possibly ownership) in order for the files to be linked together.
+@@ -965,7 +976,7 @@ the list in the order specified), and if
+ of the em(DIR)s will be selected to try to speed up the transfer.
+
+ If em(DIR) is a relative path, it is relative to the destination directory.
+-See also bf(--compare-dest).
++See also bf(--compare-dest) and bf(--copy-dest).
+
+ Note that rsync versions prior to 2.6.1 had a bug that could prevent
+ bf(--link-dest) from working properly for a non-root user when bf(-o) was specified
+--- orig/testsuite/compare-dest.test 2005-02-26 19:51:27
++++ testsuite/compare-dest.test 2005-03-01 15:57:27
+@@ -31,9 +31,9 @@ $RSYNC -av --exclude=/text --exclude=etc
+ checkit "$RSYNC -avv --no-whole-file \
+ --compare-dest=\"$alt1dir\" --compare-dest=\"$alt2dir\" \
+ \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
+-#checkit "$RSYNC -avv --no-whole-file \
+-# --copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
+-# \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
++checkit "$RSYNC -avv --no-whole-file \
++ --copy-dest=\"$alt1dir\" --copy-dest=\"$alt2dir\" \
++ \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
+
+ # The script would have aborted on error, so getting here means we've won.
+ exit 0