This patch adds a --source-backup option that backs up source files
removed due to --remove-source-files.
To use this patch, run these commands for a successful build:
patch -p1 <patches/source-backup.diff
./configure (optional if already run)
make
-- Matt McCutchen <hashproduct@gmail.com>
based-on: d73762eea3f15f2c56bb3fa9394ad1883c25c949
diff --git a/options.c b/options.c
--- a/options.c
+++ b/options.c
@@ -35,6 +35,7 @@ extern filter_rule_list daemon_filter_list;
#define NOT_SPECIFIED (-42)
int make_backups = 0;
+int make_source_backups = 0;
/**
* If 1, send the whole file as literal data rather than trying to
@@ -730,6 +731,7 @@ void usage(enum logcode F)
rprintf(F," --existing skip creating new files on receiver\n");
rprintf(F," --ignore-existing skip updating files that already exist on receiver\n");
rprintf(F," --remove-source-files sender removes synchronized files (non-dirs)\n");
+ rprintf(F," --source-backup ... and backs up those files\n");
rprintf(F," --del an alias for --delete-during\n");
rprintf(F," --delete delete extraneous files from destination dirs\n");
rprintf(F," --delete-before receiver deletes before transfer, not during\n");
@@ -995,6 +997,7 @@ static struct poptOption long_options[] = {
{"bwlimit", 0, POPT_ARG_STRING, &bwlimit_arg, OPT_BWLIMIT, 0, 0 },
{"no-bwlimit", 0, POPT_ARG_VAL, &bwlimit, 0, 0, 0 },
{"backup", 'b', POPT_ARG_VAL, &make_backups, 1, 0, 0 },
+ {"source-backup", 0, POPT_ARG_NONE, &make_source_backups, 0, 0, 0},
{"no-backup", 0, POPT_ARG_VAL, &make_backups, 0, 0, 0 },
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
{"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
@@ -2674,6 +2677,8 @@ void server_options(char **args, int *argc_p)
goto oom;
args[ac++] = arg;
}
+ if (make_source_backups)
+ args[ac++] = "--source-backup";
}
/* --delete-missing-args needs the cooperation of both sides, but
diff --git a/rsync.yo b/rsync.yo
--- a/rsync.yo
+++ b/rsync.yo
@@ -388,6 +388,7 @@ to the detailed description below for a complete description. verb(
--existing skip creating new files on receiver
--ignore-existing skip updating files that exist on receiver
--remove-source-files sender removes synchronized files (non-dir)
+ --source-backup ... and backs up those files
--del an alias for --delete-during
--delete delete extraneous files from dest dirs
--delete-before receiver deletes before xfer, not during
@@ -1399,6 +1400,14 @@ bf(--exclude='*.new') for the rsync transfer).
Starting with 3.1.0, rsync will skip the sender-side removal (and output an
error) if the file's size or modify time has not stayed unchanged.
+dit(bf(--source-backup)) Makes the sender back up the source files it removes
+due to bf(--remove-source-files). This option is independent of
+bf(--backup) but uses the same bf(--backup-dir) and bf(--suffix) settings,
+if any. With bf(--backup-dir), rsync looks for each file's backup dir relative
+to the source argument the file came from. Consequently, if the
+bf(--backup-dir) path is relative, each source argument gets a separate backup
+dir at that path relative to the argument.
+
dit(bf(--delete)) This tells rsync to delete extraneous files from the
receiving side (ones that aren't on the sending side), but only for the
directories that are being synchronized. You must have asked rsync to
diff --git a/sender.c b/sender.c
--- a/sender.c
+++ b/sender.c
@@ -40,6 +40,7 @@ extern int protocol_version;
extern int remove_source_files;
extern int updating_basis_file;
extern int make_backups;
+extern int make_source_backups;
extern int inplace;
extern int batch_fd;
extern int write_batch;
@@ -128,6 +129,7 @@ void successful_send(int ndx)
struct file_struct *file;
struct file_list *flist;
STRUCT_STAT st;
+ int result;
if (!remove_source_files)
return;
@@ -153,7 +155,11 @@ void successful_send(int ndx)
return;
}
- if (do_unlink(fname) < 0) {
+ if (make_source_backups)
+ result = !make_backup(fname, True);
+ else
+ result = do_unlink(fname);
+ if (result < 0) {
failed_op = "remove";
failed:
if (errno == ENOENT)
diff -Nurp a/rsync.1 b/rsync.1
--- a/rsync.1
+++ b/rsync.1
@@ -464,6 +464,7 @@ to the detailed description below for a
\-\-existing skip creating new files on receiver
\-\-ignore\-existing skip updating files that exist on receiver
\-\-remove\-source\-files sender removes synchronized files (non\-dir)
+ \-\-source\-backup ... and backs up those files
\-\-del an alias for \-\-delete\-during
\-\-delete delete extraneous files from dest dirs
\-\-delete\-before receiver deletes before xfer, not during
@@ -1593,6 +1594,15 @@ it is written, rename it to \(dq\&foo\(d
Starting with 3.1.0, rsync will skip the sender\-side removal (and output an
error) if the file\(cq\&s size or modify time has not stayed unchanged.
.IP
+.IP "\fB\-\-source\-backup\fP"
+Makes the sender back up the source files it removes
+due to \fB\-\-remove\-source\-files\fP. This option is independent of
+\fB\-\-backup\fP but uses the same \fB\-\-backup\-dir\fP and \fB\-\-suffix\fP settings,
+if any. With \fB\-\-backup\-dir\fP, rsync looks for each file\(cq\&s backup dir relative
+to the source argument the file came from. Consequently, if the
+\fB\-\-backup\-dir\fP path is relative, each source argument gets a separate backup
+dir at that path relative to the argument.
+.IP
.IP "\fB\-\-delete\fP"
This tells rsync to delete extraneous files from the
receiving side (ones that aren\(cq\&t on the sending side), but only for the