6a08ebd4e69a1af6db8994565553ca48a5b8ab29
[rsync-patches.git] / backup-deleted.diff
1 This patches adds the --backup-deleted option, as proposed by Jonathan
2 Kames in bug 7889.
3
4 To use this patch, run these commands for a successful build:
5
6     patch -p1 <patches/backup-deleted.diff
7     ./configure                                 (optional if already run)
8     make
9
10 based-on: 9a06b2edb0ea1a226bcc642682c07bacd2ea47d3
11 diff --git a/generator.c b/generator.c
12 --- a/generator.c
13 +++ b/generator.c
14 @@ -1846,7 +1846,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
15                 goto notify_others;
16  
17         if (read_batch || whole_file) {
18 -               if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) {
19 +               if (inplace && make_backups > 1 && fnamecmp_type == FNAMECMP_FNAME) {
20                         if (!(backupptr = get_backup_name(fname)))
21                                 goto cleanup;
22                         if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
23 @@ -1882,7 +1882,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
24                 goto notify_others;
25         }
26  
27 -       if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) {
28 +       if (inplace && make_backups > 1 && fnamecmp_type == FNAMECMP_FNAME) {
29                 if (!(backupptr = get_backup_name(fname))) {
30                         goto cleanup;
31                 }
32 @@ -2002,7 +2002,7 @@ int atomic_create(struct file_struct *file, char *fname, const char *slnk, const
33                 skip_atomic = 0;
34  
35         if (del_for_flag) {
36 -               if (make_backups > 0 && !dir_in_the_way) {
37 +               if (make_backups > 1 && !dir_in_the_way) {
38                         if (!make_backup(fname, skip_atomic))
39                                 return 0;
40                 } else if (skip_atomic) {
41 diff --git a/options.c b/options.c
42 --- a/options.c
43 +++ b/options.c
44 @@ -776,7 +776,8 @@ static struct poptOption long_options[] = {
45    {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
46    {"bwlimit",          0,  POPT_ARG_STRING, &bwlimit_arg, OPT_BWLIMIT, 0, 0 },
47    {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
48 -  {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
49 +  {"backup",          'b', POPT_ARG_VAL,    &make_backups, 2, 0, 0 },
50 +  {"backup-deleted",   0,  POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
51    {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
52    {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
53    {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
54 @@ -2803,6 +2804,10 @@ void server_options(char **args, int *argc_p)
55                 args[ac++] = safe_arg("--compress-choice", compress_choice);
56  
57         if (am_sender) {
58 +               /* A remote sender just needs the above -b option.
59 +                * A remote receiver will override that with this option. */
60 +               if (make_backups == 1)
61 +                       args[ac++] = "--backup-deleted";
62                 if (max_delete > 0) {
63                         if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
64                                 goto oom;
65 diff --git a/receiver.c b/receiver.c
66 --- a/receiver.c
67 +++ b/receiver.c
68 @@ -427,7 +427,7 @@ static void handle_delayed_updates(char *local_name)
69                 struct file_struct *file = cur_flist->files[ndx];
70                 fname = local_name ? local_name : f_name(file, NULL);
71                 if ((partialptr = partial_dir_fname(fname)) != NULL) {
72 -                       if (make_backups > 0 && !make_backup(fname, False))
73 +                       if (make_backups > 1 && !make_backup(fname, False))
74                                 continue;
75                         if (DEBUG_GTE(RECV, 1)) {
76                                 rprintf(FINFO, "renaming %s to %s\n",
77 @@ -748,7 +748,7 @@ int recv_files(int f_in, int f_out, char *local_name)
78                 } else {
79                         /* Reminder: --inplace && --partial-dir are never
80                          * enabled at the same time. */
81 -                       if (inplace && make_backups > 0) {
82 +                       if (inplace && make_backups > 1) {
83                                 if (!(fnamecmp = get_backup_name(fname)))
84                                         fnamecmp = fname;
85                                 else
86 diff --git a/rsync.1.md b/rsync.1.md
87 --- a/rsync.1.md
88 +++ b/rsync.1.md
89 @@ -428,6 +428,7 @@ has its own detailed description later in this manpage.
90  --relative, -R           use relative path names
91  --no-implied-dirs        don't send implied dirs with --relative
92  --backup, -b             make backups (see --suffix & --backup-dir)
93 +--backup-deleted         make backups only of deleted files
94  --backup-dir=DIR         make backups into hierarchy based in DIR
95  --suffix=SUFFIX          backup suffix (default ~ w/o --backup-dir)
96  --update, -u             skip files that are newer on the receiver
97 @@ -1006,6 +1007,13 @@ expand it.
98      rules specify a trailing inclusion/exclusion of `*`, the auto-added rule
99      would never be reached).
100  
101 +0.  `--backup-deleted`
102 +
103 +    With this option, deleted destination files are renamed, while modified
104 +    destination files are not. Otherwise, this option behaves the same as
105 +    [`--backup`](#opt), described above.  Note that if [`--backup`](#opt) is
106 +    also specified, whichever option is specified last takes precedence.
107 +
108  0.  `--backup-dir=DIR`
109  
110      This implies the [`--backup`](#opt) option, and tells rsync to store all
111 diff --git a/rsync.c b/rsync.c
112 --- a/rsync.c
113 +++ b/rsync.c
114 @@ -733,7 +733,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
115                 goto do_set_file_attrs;
116         }
117  
118 -       if (make_backups > 0 && overwriting_basis) {
119 +       if (make_backups > 1 && overwriting_basis) {
120                 int ok = make_backup(fname, False);
121                 if (!ok)
122                         exit_cleanup(RERR_FILEIO);