Renamed option to --remove-sent-files so that the --delete prefixed
[rsync/rsync-patches.git] / remove-sent-files.diff
1 After applying this patch and running configure, you MUST run this
2 command before "make":
3
4     make proto
5
6
7 --- orig/generator.c    2005-02-15 20:40:53
8 +++ generator.c 2005-02-15 20:43:59
9 @@ -38,6 +38,7 @@ extern int preserve_gid;
10  extern int preserve_times;
11  extern int omit_dir_times;
12  extern int delete_during;
13 +extern int remove_sent_files;
14  extern int update_only;
15  extern int opt_ignore_existing;
16  extern int inplace;
17 @@ -524,6 +525,11 @@ static void recv_generator(char *fname, 
18                                     itemize_changes ? "" : safe_fname(fname),
19                                     safe_fname(file->u.link));
20                         }
21 +                       if (remove_sent_files) {
22 +                               char numbuf[4];
23 +                               SIVAL(numbuf, 0, ndx);
24 +                               io_multiplex_write(MSG_SUCCESS, numbuf, 4);
25 +                       }
26                 }
27  #endif
28                 return;
29 --- orig/io.c   2005-02-03 02:04:20
30 +++ io.c        2005-02-15 20:43:59
31 @@ -244,6 +244,14 @@ static void read_msg_fd(void)
32                 read_loop(fd, buf, 4);
33                 redo_list_add(IVAL(buf,0));
34                 break;
35 +       case MSG_SUCCESS:
36 +               if (len != 4) {
37 +                       rprintf(FERROR, "invalid message %d:%d\n", tag, len);
38 +                       exit_cleanup(RERR_STREAMIO);
39 +               }
40 +               read_loop(fd, buf, len);
41 +               io_multiplex_write(MSG_SUCCESS, buf, len);
42 +               break;
43         case MSG_INFO:
44         case MSG_ERROR:
45         case MSG_LOG:
46 @@ -677,6 +685,16 @@ static int readfd_unbuffered(int fd, cha
47                         read_loop(fd, iobuf_in, remaining);
48                         iobuf_in_ndx = 0;
49                         break;
50 +               case MSG_SUCCESS:
51 +                       if (remaining != 4) {
52 +                               rprintf(FERROR, "invalid multi-message %d:%ld\n",
53 +                                       tag, (long)remaining);
54 +                               exit_cleanup(RERR_STREAMIO);
55 +                       }
56 +                       read_loop(fd, line, remaining);
57 +                       successful_send(IVAL(line, 0));
58 +                       remaining = 0;
59 +                       break;
60                 case MSG_INFO:
61                 case MSG_ERROR:
62                         if (remaining >= sizeof line) {
63 --- orig/main.c 2005-02-15 19:27:04
64 +++ main.c      2005-02-15 20:43:59
65 @@ -33,12 +33,14 @@ extern int verbose;
66  extern int itemize_changes;
67  extern int blocking_io;
68  extern int delete_before;
69 +extern int remove_sent_files;
70  extern int daemon_over_rsh;
71  extern int do_stats;
72  extern int dry_run;
73  extern int list_only;
74  extern int log_got_error;
75  extern int module_id;
76 +extern int need_messages_from_generator;
77  extern int orig_umask;
78  extern int copy_links;
79  extern int keep_dirlinks;
80 @@ -442,6 +444,12 @@ static void do_server_sender(int f_in, i
81                 exit_cleanup(RERR_SYNTAX);
82                 return;
83         }
84 +       if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
85 +               rprintf(FERROR,
86 +                   "ERROR: --remove-sent-files cannot be used with a read-only module\n");
87 +               exit_cleanup(RERR_SYNTAX);
88 +               return;
89 +       }
90  
91         if (!relative_paths && !push_dir(dir)) {
92                 rsyserr(FERROR, errno, "push_dir#3 %s failed",
93 @@ -673,6 +681,8 @@ void start_server(int f_in, int f_out, i
94  
95         if (am_sender) {
96                 keep_dirlinks = 0; /* Must be disabled on the sender. */
97 +               if (need_messages_from_generator)
98 +                       io_start_multiplex_in();
99  
100                 recv_filter_list(f_in);
101                 do_server_sender(f_in, f_out, argc, argv);
102 @@ -750,6 +760,9 @@ int client_run(int f_in, int f_out, pid_
103                 exit_cleanup(status);
104         }
105  
106 +       if (need_messages_from_generator && !read_batch)
107 +               io_start_multiplex_out();
108 +
109         if (argc == 0)
110                 list_only |= 1;
111  
112 --- orig/options.c      2005-02-15 19:27:05
113 +++ options.c   2005-02-15 20:44:00
114 @@ -59,6 +59,7 @@ int delete_during = 0;
115  int delete_before = 0;
116  int delete_after = 0;
117  int delete_excluded = 0;
118 +int remove_sent_files = 0;
119  int one_file_system = 0;
120  int protocol_version = PROTOCOL_VERSION;
121  int sparse_files = 0;
122 @@ -93,6 +94,7 @@ int fuzzy_basis = 0;
123  size_t bwlimit_writemax = 0;
124  int only_existing = 0;
125  int opt_ignore_existing = 0;
126 +int need_messages_from_generator = 0;
127  int max_delete = 0;
128  OFF_T max_size = 0;
129  int ignore_errors = 0;
130 @@ -285,6 +287,7 @@ void usage(enum logcode F)
131    rprintf(F,"     --rsync-path=PATH       specify path to rsync on the remote machine\n");
132    rprintf(F,"     --existing              only update files that already exist on receiver\n");
133    rprintf(F,"     --ignore-existing       ignore files that already exist on receiving side\n");
134 +  rprintf(F,"     --remove-sent-files     updated/sent files are removed from sending side\n");
135    rprintf(F,"     --del                   an alias for --delete-during\n");
136    rprintf(F,"     --delete                delete files that don't exist on the sending side\n");
137    rprintf(F,"     --delete-before         receiver deletes before transfer (default)\n");
138 @@ -368,6 +371,7 @@ static struct poptOption long_options[] 
139    {"delete-during",    0,  POPT_ARG_NONE,   &delete_during, 0, 0, 0 },
140    {"delete-after",     0,  POPT_ARG_NONE,   &delete_after, 0, 0, 0 },
141    {"delete-excluded",  0,  POPT_ARG_NONE,   &delete_excluded, 0, 0, 0 },
142 +  {"remove-sent-files",0,  POPT_ARG_NONE,   &remove_sent_files, 0, 0, 0 },
143    {"force",            0,  POPT_ARG_NONE,   &force_delete, 0, 0, 0 },
144    {"numeric-ids",      0,  POPT_ARG_NONE,   &numeric_ids, 0, 0, 0 },
145    {"filter",          'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
146 @@ -961,6 +965,14 @@ int parse_arguments(int *argc, const cha
147                 return 0;
148         }
149  
150 +       if (remove_sent_files) {
151 +               if (refused_delete) {
152 +                       create_refuse_error(refused_delete);
153 +                       return 0;
154 +               }
155 +               need_messages_from_generator = 1;
156 +       }
157 +
158         *argv = poptGetArgs(pc);
159         *argc = count_args(*argv);
160  
161 @@ -1393,6 +1405,9 @@ void server_options(char **args,int *arg
162         if (fuzzy_basis && am_sender)
163                 args[ac++] = "--fuzzy";
164  
165 +       if (remove_sent_files)
166 +               args[ac++] = "--remove-sent-files";
167 +
168         *argc = ac;
169         return;
170  
171 --- orig/receiver.c     2005-02-15 19:27:05
172 +++ receiver.c  2005-02-15 20:44:00
173 @@ -42,6 +42,7 @@ extern int basis_dir_cnt;
174  extern int make_backups;
175  extern int do_progress;
176  extern int cleanup_got_literal;
177 +extern int remove_sent_files;
178  extern int module_id;
179  extern int ignore_errors;
180  extern int orig_umask;
181 @@ -307,7 +308,7 @@ int recv_files(int f_in, struct file_lis
182         char *fname, fbuf[MAXPATHLEN];
183         char template[MAXPATHLEN];
184         char fnametmp[MAXPATHLEN];
185 -       char *fnamecmp, *partialptr;
186 +       char *fnamecmp, *partialptr, numbuf[4];
187         char fnamecmpbuf[MAXPATHLEN];
188         uchar *delayed_bits = NULL;
189         struct file_struct *file;
190 @@ -569,7 +570,12 @@ int recv_files(int f_in, struct file_lis
191  
192                 cleanup_disable();
193  
194 -               if (!recv_ok) {
195 +               if (recv_ok) {
196 +                       if (remove_sent_files) {
197 +                               SIVAL(numbuf, 0, i);
198 +                               send_msg(MSG_SUCCESS, numbuf, 4);
199 +                       }
200 +               } else {
201                         int msgtype = csum_length == SUM_LENGTH || read_batch ?
202                                 FERROR : FINFO;
203                         if (msgtype == FERROR || verbose) {
204 @@ -593,9 +599,8 @@ int recv_files(int f_in, struct file_lis
205                                         keptstr, redostr);
206                         }
207                         if (csum_length != SUM_LENGTH) {
208 -                               char buf[4];
209 -                               SIVAL(buf, 0, i);
210 -                               send_msg(MSG_REDO, buf, 4);
211 +                               SIVAL(numbuf, 0, i);
212 +                               send_msg(MSG_REDO, numbuf, 4);
213                         }
214                 }
215         }
216 --- orig/rsync.h        2005-02-15 19:27:05
217 +++ rsync.h     2005-02-15 20:44:00
218 @@ -62,6 +62,7 @@
219  #define FLAG_MOUNT_POINT (1<<2)        /* sender only */
220  #define FLAG_NO_FUZZY (1<<2)   /* generator only */
221  #define FLAG_DEL_HERE (1<<3)   /* receiver/generator */
222 +#define FLAG_SENT (1<<7)       /* sender only */
223  
224  /* update this if you make incompatible changes */
225  #define PROTOCOL_VERSION 29
226 @@ -144,6 +145,7 @@ enum logcode { FERROR=1, FINFO=2, FLOG=3
227  /* Messages types that are sent over the message channel.  The logcode
228   * values must all be present here with identical numbers. */
229  enum msgcode {
230 +       MSG_SUCCESS=6,  /* successfully updated indicated flist index */
231         MSG_DONE=5,     /* current phase is done */
232         MSG_REDO=4,     /* reprocess indicated flist index */
233         MSG_ERROR=FERROR, MSG_INFO=FINFO, MSG_LOG=FLOG, /* remote logging */
234 --- orig/rsync.yo       2005-02-15 20:42:04
235 +++ rsync.yo    2005-02-15 20:44:02
236 @@ -332,6 +332,7 @@ to the detailed description below for a 
237       --rsync-path=PATH       specify path to rsync on the remote machine
238       --existing              only update files that already exist
239       --ignore-existing       ignore files that already exist on receiver
240 +     --remove-sent-files     sent files/symlinks are removed from sender
241       --del                   an alias for --delete-during
242       --delete                delete files that don't exist on sender
243       --delete-before         receiver deletes before transfer (default)
244 @@ -665,6 +666,11 @@ dit(bf(--ignore-existing))
245  This tells rsync not to update files that already exist on
246  the destination.
247  
248 +dit(bf(--remove-sent-files)) This tells rsync to remove the source files
249 +on the sending side that are successfully transferred to the receiving
250 +side.  Directories and devices are not removed, nor are files/symlinks
251 +whose content was not updated (just changing attributes does not count).
252 +
253  dit(bf(--delete)) This tells rsync to delete extraneous files from the
254  receiving side (ones that aren't on the sending side), but only for the
255  directories that are being synchronized.  You must have asked rsync to
256 --- orig/sender.c       2005-02-15 19:27:05
257 +++ sender.c    2005-02-15 20:44:02
258 @@ -27,6 +27,7 @@ extern int io_error;
259  extern int dry_run;
260  extern int am_server;
261  extern int am_daemon;
262 +extern int remove_sent_files;
263  extern int protocol_version;
264  extern int updating_basis_file;
265  extern int make_backups;
266 @@ -95,7 +96,32 @@ static struct sum_struct *receive_sums(i
267         return s;
268  }
269  
270 +static struct file_list *the_flist;
271  
272 +void successful_send(int i)
273 +{
274 +       char fname[MAXPATHLEN];
275 +       struct file_struct *file;
276 +       unsigned int offset;
277 +
278 +       if (!the_flist || i < 0 || i >= the_flist->count)
279 +               return;
280 +
281 +       file = the_flist->files[i];
282 +       /* The generator can tell us about symlinks we didn't send. */
283 +       if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
284 +               return; /* We didn't send it -- impossible! */
285 +       if (file->dir.root) {
286 +               offset = stringjoin(fname, sizeof fname,
287 +                                   file->dir.root, "/", NULL);
288 +       } else
289 +               offset = 0;
290 +       f_name_to(file, fname + offset);
291 +       if (remove_sent_files && do_unlink(fname) == 0 && verbose) {
292 +               rprintf(FINFO, "sender removed %s\n",
293 +                       safe_fname(fname + offset));
294 +       }
295 +}
296  
297  void send_files(struct file_list *flist, int f_out, int f_in)
298  {
299 @@ -114,6 +140,8 @@ void send_files(struct file_list *flist,
300         if (verbose > 2)
301                 rprintf(FINFO, "send_files starting\n");
302  
303 +       the_flist = flist;
304 +
305         while (1) {
306                 unsigned int offset;
307  
308 @@ -256,6 +284,9 @@ void send_files(struct file_list *flist,
309                         rprintf(FINFO, "sender finished %s\n",
310                                 safe_fname(fname));
311                 }
312 +
313 +               /* Flag that we actually sent this entry. */
314 +               file->flags |= FLAG_SENT;
315         }
316         make_backups = save_make_backups;
317