This patches adds the --backup-deleted option, as proposed by Jonathan Kames in bug 7889. To use this patch, run these commands for a successful build: patch -p1 0 && fnamecmp_type == FNAMECMP_FNAME) { + if (inplace && make_backups > 1 && fnamecmp_type == FNAMECMP_FNAME) { if (!(backupptr = get_backup_name(fname))) goto cleanup; if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) @@ -1873,7 +1873,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto notify_others; } - if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) { + if (inplace && make_backups > 1 && fnamecmp_type == FNAMECMP_FNAME) { if (!(backupptr = get_backup_name(fname))) { close(fd); goto cleanup; @@ -1997,7 +1997,7 @@ int atomic_create(struct file_struct *file, char *fname, const char *slnk, const skip_atomic = 0; if (del_for_flag) { - if (make_backups > 0 && !dir_in_the_way) { + if (make_backups > 1 && !dir_in_the_way) { if (!make_backup(fname, skip_atomic)) return 0; } else if (skip_atomic) { diff --git a/options.c b/options.c --- a/options.c +++ b/options.c @@ -766,7 +766,8 @@ static struct poptOption long_options[] = { {"no-i", 0, POPT_ARG_VAL, &itemize_changes, 0, 0, 0 }, {"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 }, + {"backup", 'b', POPT_ARG_VAL, &make_backups, 2, 0, 0 }, + {"backup-deleted", 0, POPT_ARG_VAL, &make_backups, 1, 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 }, @@ -2726,6 +2727,10 @@ void server_options(char **args, int *argc_p) } if (am_sender) { + /* A remote sender just needs the above -b option. + * A remote receiver will override that with this option. */ + if (make_backups == 1) + args[ac++] = "--backup-deleted"; if (max_delete > 0) { if (asprintf(&arg, "--max-delete=%d", max_delete) < 0) goto oom; diff --git a/receiver.c b/receiver.c --- a/receiver.c +++ b/receiver.c @@ -420,7 +420,7 @@ static void handle_delayed_updates(char *local_name) struct file_struct *file = cur_flist->files[ndx]; fname = local_name ? local_name : f_name(file, NULL); if ((partialptr = partial_dir_fname(fname)) != NULL) { - if (make_backups > 0 && !make_backup(fname, False)) + if (make_backups > 1 && !make_backup(fname, False)) continue; if (DEBUG_GTE(RECV, 1)) { rprintf(FINFO, "renaming %s to %s\n", @@ -736,7 +736,7 @@ int recv_files(int f_in, int f_out, char *local_name) } else { /* Reminder: --inplace && --partial-dir are never * enabled at the same time. */ - if (inplace && make_backups > 0) { + if (inplace && make_backups > 1) { if (!(fnamecmp = get_backup_name(fname))) fnamecmp = fname; else diff --git a/rsync.1.md b/rsync.1.md --- a/rsync.1.md +++ b/rsync.1.md @@ -344,6 +344,7 @@ detailed description below for a complete description. --relative, -R use relative path names --no-implied-dirs don't send implied dirs with --relative --backup, -b make backups (see --suffix & --backup-dir) +--backup-deleted make backups only of deleted files --backup-dir=DIR make backups into hierarchy based in DIR --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir) --update, -u skip files that are newer on the receiver @@ -856,6 +857,13 @@ your home directory (remove the '=' for that). trailing inclusion/exclusion of `*`, the auto-added rule would never be reached). +0. --backup-deleted + + With this option, deleted destination files are renamed, while modified + destination files are not. Otherwise, this option behaves the same as + `--backup`, described above. Note that if `--backup` is also specified, + whichever option is specified last takes precedence. + 0. `--backup-dir=DIR` This implies the `--backup` option, and tells rsync to store all diff --git a/rsync.c b/rsync.c --- a/rsync.c +++ b/rsync.c @@ -721,7 +721,7 @@ int finish_transfer(const char *fname, const char *fnametmp, goto do_set_file_attrs; } - if (make_backups > 0 && overwriting_basis) { + if (make_backups > 1 && overwriting_basis) { int ok = make_backup(fname, False); if (!ok) exit_cleanup(RERR_FILEIO); diff -Nurp a/rsync.1 b/rsync.1 --- a/rsync.1 +++ b/rsync.1 @@ -420,6 +420,7 @@ detailed description below for a complet --relative, -R use relative path names --no-implied-dirs don't send implied dirs with --relative --backup, -b make backups (see --suffix & --backup-dir) +--backup-deleted make backups only of deleted files --backup-dir=DIR make backups into hierarchy based in DIR --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir) --update, -u skip files that are newer on the receiver @@ -931,6 +932,11 @@ your own exclude/protect rule somewhere has a high enough priority to be effective (e.g., if your rules specify a trailing inclusion/exclusion of \fB*\fP, the auto-added rule would never be reached). +.IP "\-\-backup-deleted" +With this option, deleted destination files are renamed, while modified +destination files are not. Otherwise, this option behaves the same as +\fB\-\-backup\fP, described above. Note that if \fB\-\-backup\fP is also specified, +whichever option is specified last takes precedence. .IP "\fB\-\-backup-dir=DIR\fP" This implies the \fB\-\-backup\fP option, and tells rsync to store all backups in the specified directory on the receiving side. This can be used diff -Nurp a/rsync.1.html b/rsync.1.html --- a/rsync.1.html +++ b/rsync.1.html @@ -335,6 +335,7 @@ detailed description below for a complet --relative, -R use relative path names --no-implied-dirs don't send implied dirs with --relative --backup, -b make backups (see --suffix & --backup-dir) +--backup-deleted make backups only of deleted files --backup-dir=DIR make backups into hierarchy based in DIR --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir) --update, -u skip files that are newer on the receiver @@ -834,6 +835,13 @@ trailing inclusion/exclusion of *< reached).

+
-⁠-⁠backup-deleted
+

With this option, deleted destination files are renamed, while modified +destination files are not. Otherwise, this option behaves the same as +--backup, described above. Note that if --backup is also specified, +whichever option is specified last takes precedence.

+
+
--backup-dir=DIR

This implies the --backup option, and tells rsync to store all backups in the specified directory on the receiving side. This can be used