Fixing failed hunks caused by recent removal of delete_one().
[rsync/rsync-patches.git] / delete-during.diff
CommitLineData
91cf5188
WD
1This patch creates a --delete-during functionality that deletes files on
2the receiving side incrementally as we traverse the directories. It also
3defines a --delete-before option, for the traditional way that --delete
4has worked before.
5
6This patch chooses to make --delete into a synonym for --delete-during, and
7hide --delete-during, but that can be easily changed if we want to preserve
8the old functionality (and indeed, the support for popt aliases that is now
9in CVS will let the user easily choose which method they'd like --delete to
10invoke, either personally or site-wide, without having to recompile rsync).
11
12--- orig/flist.c 2005-01-19 00:24:57
13+++ flist.c 2005-01-19 00:39:09
14@@ -45,6 +45,8 @@ extern int cvs_exclude;
15 extern int recurse;
16 extern int keep_dirs;
17 extern char curr_dir[MAXPATHLEN];
18+extern char *backup_dir;
19+extern char *backup_suffix;
20 extern int filesfrom_fd;
21
22 extern int one_file_system;
23@@ -57,11 +59,14 @@ extern int preserve_uid;
24 extern int preserve_gid;
25 extern int relative_paths;
26 extern int implied_dirs;
27+extern int make_backups;
28+extern int backup_suffix_len;
29 extern int copy_links;
30 extern int copy_unsafe_links;
31 extern int protocol_version;
32 extern int sanitize_paths;
33 extern int delete_excluded;
34+extern int max_delete;
35 extern int orig_umask;
36 extern int list_only;
37
38@@ -1044,7 +1049,8 @@ static void send_directory(int f, struct
39 || (dname[1] == '.' && dname[2] == '\0')))
40 continue;
41 if (strlcpy(p, dname, MAXPATHLEN - offset) < MAXPATHLEN - offset) {
42- send_file_name(f, flist, fname, recurse, 0);
43+ int do_subdirs = recurse >= 1 ? recurse-- : recurse;
44+ send_file_name(f, flist, fname, do_subdirs, 0);
45 } else {
46 io_error |= IOERR_GENERAL;
47 rprintf(FINFO,
48@@ -1102,6 +1108,7 @@ struct file_list *send_file_list(int f,
49 while (1) {
50 char fname2[MAXPATHLEN];
51 char *fname = fname2;
52+ int do_subdirs;
53
54 if (use_ff_fd) {
55 if (read_filesfrom_line(filesfrom_fd, fname) == 0)
56@@ -1143,7 +1150,7 @@ struct file_list *send_file_list(int f,
57 dir = NULL;
58 olddir[0] = '\0';
59
60- if (!relative_paths) {
61+ if (!relative_paths && recurse <= 0) {
62 p = strrchr(fname, '/');
63 if (p) {
64 *p = 0;
65@@ -1212,7 +1219,8 @@ struct file_list *send_file_list(int f,
66 if (one_file_system)
67 set_filesystem(fname);
68
69- send_file_name(f, flist, fname, recurse, XMIT_TOP_DIR);
70+ do_subdirs = recurse >= 1 ? recurse-- : recurse;
71+ send_file_name(f, flist, fname, do_subdirs, XMIT_TOP_DIR);
72
73 if (olddir[0]) {
74 flist_dir = NULL;
65a73542 75@@ -1634,3 +1642,89 @@ char *f_name(struct file_struct *f)
91cf5188
WD
76
77 return f_name_to(f, names[n]);
78 }
79+
91cf5188
WD
80+static int is_backup_file(char *fn)
81+{
82+ int k = strlen(fn) - backup_suffix_len;
83+ return k > 0 && strcmp(fn+k, backup_suffix) == 0;
84+}
85+
86+void delete_in_dir(struct file_list *flist, char *fname, int do_subdirs)
87+{
88+ static int deletion_count = 0;
89+ struct file_list *del_flist;
90+ int save_recurse = recurse;
91+ int save_keep_dirs = keep_dirs;
92+ int save_implied_dirs = implied_dirs;
93+ char *argv[1];
94+ int i;
95+
96+ if (max_delete && deletion_count >= max_delete)
97+ return;
98+
99+ if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
100+ rprintf(FINFO, "IO error encountered - skipping file deletion\n");
101+ max_delete = -1; /* avoid duplicating the above warning */
102+ return;
103+ }
104+
105+ recurse = do_subdirs ? -1 : 1;
106+ keep_dirs = 1;
107+ implied_dirs = 0;
108+
109+ argv[0] = fname;
110+ del_flist = send_file_list(-1, 1, argv);
111+
112+ implied_dirs = save_implied_dirs;
113+ keep_dirs = save_keep_dirs;
114+ recurse = save_recurse;
115+
116+ if (!del_flist)
117+ return;
118+
119+ if (verbose > 1)
120+ rprintf(FINFO, "deleting in %s\n", safe_fname(fname));
121+
122+ for (i = del_flist->count-1; i >= 0; i--) {
123+ if (max_delete && deletion_count >= max_delete)
124+ break;
125+ if (!del_flist->files[i]->basename)
126+ continue;
127+ if (flist_find(flist, del_flist->files[i]) < 0) {
128+ char *f = f_name(del_flist->files[i]);
129+ int mode = del_flist->files[i]->mode;
130+ if (make_backups && (backup_dir || !is_backup_file(f))
131+ && !S_ISDIR(mode)) {
132+ make_backup(f);
133+ if (verbose) {
134+ rprintf(FINFO, "deleting %s\n",
135+ safe_fname(f));
136+ }
65a73542
WD
137+ } else {
138+ delete_file(f, S_ISDIR(mode)
139+ ? DEL_DIR | DEL_NO_RECURSE : 0);
140+ }
91cf5188
WD
141+ deletion_count++;
142+ }
143+ }
144+ flist_free(del_flist);
145+}
146+
147+/* This deletes any files on the receiving side that are not present on the
148+ * sending side. This is used by --delete-before and --delete-after. */
149+void delete_files(struct file_list *flist)
150+{
151+ char fbuf[MAXPATHLEN];
152+ int j;
153+
154+ if (cvs_exclude)
155+ add_cvs_excludes();
156+
157+ for (j = 0; j < flist->count; j++) {
158+ if (!(flist->files[j]->flags & FLAG_TOP_DIR)
159+ || !S_ISDIR(flist->files[j]->mode))
160+ continue;
161+
162+ delete_in_dir(flist, f_name_to(flist->files[j], fbuf), recurse);
163+ }
164+}
65a73542 165--- orig/generator.c 2005-01-19 20:11:10
91cf5188
WD
166+++ generator.c 2005-01-18 23:14:23
167@@ -34,6 +34,8 @@ extern int preserve_hard_links;
168 extern int preserve_perms;
169 extern int preserve_uid;
170 extern int preserve_gid;
171+extern int delete_during;
172+extern int cvs_exclude;
173 extern int update_only;
174 extern int opt_ignore_existing;
175 extern int inplace;
65a73542 176@@ -233,7 +235,8 @@ static void generate_and_send_sums(int f
91cf5188
WD
177 * @note This comment was added later by mbp who was trying to work it
178 * out. It might be wrong.
179 */
180-static void recv_generator(char *fname, struct file_struct *file, int i,
181+static void recv_generator(char *fname, struct file_list *flist,
182+ struct file_struct *file, int i,
183 int f_out, int f_out_name)
184 {
185 int fd = -1, f_copy = -1;
65a73542 186@@ -294,8 +297,6 @@ static void recv_generator(char *fname,
91cf5188
WD
187 * we need to delete it. If it doesn't exist, then
188 * recursively create it. */
189
190- if (dry_run)
191- return; /* TODO: causes inaccuracies -- fix */
192 if (statret == 0 && !S_ISDIR(st.st_mode)) {
65a73542
WD
193 delete_file(fname, DEL_TERSE);
194 statret = -1;
195@@ -311,6 +312,8 @@ static void recv_generator(char *fname,
91cf5188
WD
196 }
197 /* f_out is set to -1 when doing final directory-permission
198 * and modification-time repair. */
199+ if (delete_during && f_out != -1)
200+ delete_in_dir(flist, fname, 0);
201 if (set_perms(fname, file, statret ? NULL : &st, 0)
202 && verbose && f_out != -1)
203 rprintf(FINFO, "%s/\n", safe_fname(fname));
65a73542 204@@ -621,6 +624,9 @@ void generate_files(int f_out, struct fi
91cf5188
WD
205 : "delta transmission enabled\n");
206 }
207
208+ if (delete_during && cvs_exclude)
209+ add_cvs_excludes();
210+
211 /* we expect to just sit around now, so don't exit on a
212 timeout. If we really get a timeout then the other process should
213 exit */
65a73542 214@@ -644,7 +650,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
215 }
216
217 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
218- file, i, f_out, f_out_name);
219+ flist, file, i, f_out, f_out_name);
220 }
221
222 phase++;
65a73542 223@@ -661,7 +667,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
224 while ((i = get_redo_num()) != -1) {
225 struct file_struct *file = flist->files[i];
226 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
227- file, i, f_out, f_out_name);
228+ flist, file, i, f_out, f_out_name);
229 }
230
231 phase++;
65a73542 232@@ -683,7 +689,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
233 if (!file->basename || !S_ISDIR(file->mode))
234 continue;
235 recv_generator(local_name ? local_name : f_name(file),
236- file, i, -1, -1);
237+ flist, file, i, -1, -1);
238 }
239
240 if (verbose > 2)
241--- orig/main.c 2005-01-17 23:11:45
242+++ main.c 2005-01-18 21:56:05
243@@ -33,6 +33,7 @@ extern int verbose;
244 extern int blocking_io;
245 extern int cvs_exclude;
246 extern int delete_mode;
247+extern int delete_before;
248 extern int delete_excluded;
249 extern int delete_after;
250 extern int daemon_over_rsh;
251@@ -473,9 +474,9 @@ static int do_recv(int f_in,int f_out,st
252 if (preserve_hard_links)
253 init_hard_links(flist);
254
255- if (!delete_after) {
256+ if (delete_before) {
257 /* I moved this here from recv_files() to prevent a race condition */
258- if (recurse && delete_mode && !local_name && flist->count > 0)
259+ if (recurse && !local_name && flist->count > 0)
260 delete_files(flist);
261 }
262
263--- orig/options.c 2005-01-19 00:34:19
264+++ options.c 2005-01-19 01:07:34
265@@ -54,6 +54,8 @@ int dry_run = 0;
266 int local_server = 0;
267 int ignore_times = 0;
268 int delete_mode = 0;
269+int delete_during = 0;
270+int delete_before = 0;
271 int delete_excluded = 0;
272 int one_file_system = 0;
273 int protocol_version = PROTOCOL_VERSION;
274@@ -272,14 +274,15 @@ void usage(enum logcode F)
275 rprintf(F," --existing only update files that already exist\n");
276 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
277 rprintf(F," --delete delete files that don't exist on the sending side\n");
278+ rprintf(F," --delete-before receiver deletes before transferring, not during\n");
279+ rprintf(F," --delete-after receiver deletes after transferring, not during\n");
280 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
281- rprintf(F," --delete-after receiver deletes after transferring, not before\n");
282 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
283+ rprintf(F," --force force deletion of directories even if not empty\n");
284 rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
285 rprintf(F," --max-size=SIZE don't transfer any file larger than SIZE\n");
286 rprintf(F," --partial keep partially transferred files\n");
287 rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n");
288- rprintf(F," --force force deletion of directories even if not empty\n");
289 rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
290 rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
291 rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
292@@ -320,8 +323,8 @@ void usage(enum logcode F)
293 rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
294 }
295
296-enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
297- OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED,
298+enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE,
299+ OPT_EXCLUDE_FROM, OPT_DELETE_MODE,
300 OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
301 OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
302 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
303@@ -337,11 +340,13 @@ static struct poptOption long_options[]
304 {"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
305 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
306 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
307- {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
308+ {"delete", 0, POPT_ARG_NONE, 0, OPT_DELETE_MODE, 0, 0 },
309+ {"delete-during", 0, POPT_ARG_NONE, &delete_during, OPT_DELETE_MODE, 0, 0 },
310+ {"delete-before", 0, POPT_ARG_NONE, &delete_before, OPT_DELETE_MODE, 0, 0 },
311 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
312 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
313- {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 },
314- {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 },
315+ {"delete-after", 0, POPT_ARG_NONE, &delete_after, OPT_DELETE_MODE, 0, 0 },
316+ {"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, OPT_DELETE_MODE, 0, 0 },
317 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
318 {"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 },
319 {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
320@@ -613,13 +618,7 @@ int parse_arguments(int *argc, const cha
321 modify_window_set = 1;
322 break;
323
324- case OPT_DELETE_AFTER:
325- delete_after = 1;
326- delete_mode = 1;
327- break;
328-
329- case OPT_DELETE_EXCLUDED:
330- delete_excluded = 1;
331+ case OPT_DELETE_MODE:
332 delete_mode = 1;
333 break;
334
335@@ -851,13 +850,18 @@ int parse_arguments(int *argc, const cha
336 preserve_uid = 1;
337 preserve_devices = 1;
338 }
339+
340 if (recurse) {
341+ recurse = -1; /* unlimited recursion */
342 keep_dirs = 1;
343 }
344
345 if (relative_paths < 0)
346 relative_paths = files_from? 1 : 0;
347
348+ if (delete_mode && !(delete_during || delete_before || delete_after))
349+ delete_during = 1; /* Use "delete_before" for old default. */
350+
351 *argv = poptGetArgs(pc);
352 *argc = count_args(*argv);
353
354@@ -1156,7 +1160,9 @@ void server_options(char **args,int *arg
355 if (am_sender) {
356 if (delete_excluded)
357 args[ac++] = "--delete-excluded";
358- else if (delete_mode)
359+ else if (delete_before)
360+ args[ac++] = "--delete-before";
361+ else if (delete_during || delete_after)
362 args[ac++] = "--delete";
363
364 if (delete_after)
65a73542 365--- orig/receiver.c 2005-01-19 20:11:10
91cf5188
WD
366+++ receiver.c 2005-01-18 22:47:38
367@@ -23,7 +23,6 @@
368 extern int verbose;
369 extern int recurse;
370 extern int delete_after;
371-extern int max_delete;
372 extern int csum_length;
373 extern struct stats stats;
374 extern int dry_run;
375@@ -35,7 +34,6 @@ extern int relative_paths;
376 extern int keep_dirlinks;
377 extern int preserve_hard_links;
378 extern int preserve_perms;
379-extern int cvs_exclude;
380 extern int io_error;
381 extern char *tmpdir;
382 extern char *partial_dir;
383@@ -43,9 +41,6 @@ extern char *basis_dir[];
384 extern int basis_dir_cnt;
385 extern int make_backups;
386 extern int do_progress;
387-extern char *backup_dir;
388-extern char *backup_suffix;
389-extern int backup_suffix_len;
390 extern int cleanup_got_literal;
391 extern int module_id;
392 extern int ignore_errors;
65a73542 393@@ -57,70 +52,6 @@ extern int inplace;
91cf5188
WD
394 extern struct exclude_list_struct server_exclude_list;
395
396
91cf5188
WD
397-static int is_backup_file(char *fn)
398-{
399- int k = strlen(fn) - backup_suffix_len;
400- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
401-}
402-
403-
404-/* This deletes any files on the receiving side that are not present
405- * on the sending side. */
406-void delete_files(struct file_list *flist)
407-{
408- struct file_list *local_file_list;
409- int i, j;
410- char *argv[1], fbuf[MAXPATHLEN];
411- static int deletion_count;
412-
413- if (cvs_exclude)
414- add_cvs_excludes();
415-
416- if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
417- rprintf(FINFO,"IO error encountered - skipping file deletion\n");
418- return;
419- }
420-
421- for (j = 0; j < flist->count; j++) {
422- if (!(flist->files[j]->flags & FLAG_TOP_DIR)
423- || !S_ISDIR(flist->files[j]->mode))
424- continue;
425-
426- argv[0] = f_name_to(flist->files[j], fbuf);
427-
428- if (!(local_file_list = send_file_list(-1, 1, argv)))
429- continue;
430-
431- if (verbose > 1)
432- rprintf(FINFO, "deleting in %s\n", safe_fname(fbuf));
433-
434- for (i = local_file_list->count-1; i >= 0; i--) {
435- if (max_delete && deletion_count >= max_delete)
436- break;
437- if (!local_file_list->files[i]->basename)
438- continue;
439- if (flist_find(flist,local_file_list->files[i]) < 0) {
440- char *f = f_name(local_file_list->files[i]);
441- int mode = local_file_list->files[i]->mode;
442- if (make_backups && (backup_dir || !is_backup_file(f))
443- && !S_ISDIR(mode)) {
444- make_backup(f);
445- if (verbose) {
446- rprintf(FINFO, "deleting %s\n",
447- safe_fname(f));
448- }
65a73542
WD
449- } else {
450- delete_file(f, S_ISDIR(mode)
451- ? DEL_DIR | DEL_NO_RECURSE : 0);
452- }
91cf5188
WD
453- deletion_count++;
454- }
455- }
456- flist_free(local_file_list);
457- }
458-}
459-
460-
461 /*
462 * get_tmpname() - create a tmp filename for a given filename
463 *
464--- orig/rsync.yo 2005-01-17 23:11:46
465+++ rsync.yo 2005-01-19 01:05:05
466@@ -341,14 +341,15 @@ verb(
467 --existing only update files that already exist
468 --ignore-existing ignore files that already exist on receiver
469 --delete delete files that don't exist on sender
470+ --delete-before receiver deletes before xfer, not during
471+ --delete-after receiver deletes after transfer, not during
472 --delete-excluded also delete excluded files on receiver
473- --delete-after receiver deletes after transfer, not before
474 --ignore-errors delete even if there are I/O errors
475+ --force force deletion of dirs even if not empty
476 --max-delete=NUM don't delete more than NUM files
477 --max-size=SIZE don't transfer any file larger than SIZE
478 --partial keep partially transferred files
479 --partial-dir=DIR put a partially transferred file into DIR
480- --force force deletion of dirs even if not empty
481 --numeric-ids don't map uid/gid values by user/group name
482 --timeout=TIME set I/O timeout in seconds
483 -I, --ignore-times turn off mod time & file size quick check
484@@ -669,7 +670,7 @@ by the shell and rsync thus gets a reque
485 the files' parent directory. Files that are excluded from transfer are
486 excluded from being deleted unless you use --delete-excluded.
487
488-This option has no effect if directory recursion is not selected.
489+This option has no effect unless directory recursion is selected.
490
491 This option can be dangerous if used incorrectly! It is a very good idea
492 to run first using the --dry-run option (-n) to see what files would be
493@@ -681,20 +682,29 @@ prevent temporary filesystem failures (s
494 sending side causing a massive deletion of files on the
495 destination. You can override this with the --ignore-errors option.
496
497+By default rsync does file deletions on the receiving side during the
498+transfer of files to try make it as efficient as possible. For other
499+options, see --delete-before and --delte-after.
500+
501+dit(bf(--delete-before)) Request that the file-deletions on the receving
502+side be done prior to starting the transfer, not incrementally as the
503+transfer happens. Implies --delete.
504+
505+One reason to use --delete-before is if the filesystem is tight for space
506+and removing extraneous files would help to make the transfer possible.
507+However, it does introduce a delay before the start of the transfer (while
508+the receiving side is being scanned for deletions) and this delay might
509+cause the transfer to timeout.
510+
511+dit(bf(--delete-after)) Request that the file-deletions on the receving
512+side be done after the transfer has completed, not incrementally as the
513+transfer happens. Implies --delete.
514+
515 dit(bf(--delete-excluded)) In addition to deleting the files on the
516 receiving side that are not on the sending side, this tells rsync to also
517 delete any files on the receiving side that are excluded (see --exclude).
518 Implies --delete.
519
520-dit(bf(--delete-after)) By default rsync does file deletions on the
521-receiving side before transferring files to try to ensure that there is
522-sufficient space on the receiving filesystem. If you want to delete
523-after transferring, use the --delete-after switch. Implies --delete.
524-
525-One reason to use --delete-after is to avoid a delay before the start of
526-the transfer (while the receiving side is scanned for deletions) as this
527-delay might cause the transfer to timeout.
528-
529 dit(bf(--ignore-errors)) Tells --delete to go ahead and delete files
530 even when there are I/O errors.
531