Changed the short option from -d to -O.
[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
4b1dce55
WD
12Be sure to run "make proto" before "make".
13
559625f9 14--- orig/flist.c 2005-01-24 00:18:21
8ace861d 15+++ flist.c 2005-01-23 08:02:39
b5bbf19c
WD
16@@ -35,6 +35,7 @@ extern int am_root;
17 extern int am_server;
18 extern int am_daemon;
19 extern int am_sender;
20+extern int delete_during;
21 extern int always_checksum;
22 extern int module_id;
23 extern int ignore_errors;
24@@ -45,6 +46,8 @@ extern int cvs_exclude;
91cf5188 25 extern int recurse;
559625f9 26 extern int xfer_dirs;
91cf5188
WD
27 extern char curr_dir[MAXPATHLEN];
28+extern char *backup_dir;
29+extern char *backup_suffix;
30 extern int filesfrom_fd;
31
32 extern int one_file_system;
b5bbf19c 33@@ -57,11 +60,14 @@ extern int preserve_uid;
91cf5188
WD
34 extern int preserve_gid;
35 extern int relative_paths;
36 extern int implied_dirs;
37+extern int make_backups;
38+extern int backup_suffix_len;
39 extern int copy_links;
40 extern int copy_unsafe_links;
41 extern int protocol_version;
42 extern int sanitize_paths;
43 extern int delete_excluded;
44+extern int max_delete;
45 extern int orig_umask;
46 extern int list_only;
47
5128f136
WD
48@@ -534,6 +540,8 @@ void receive_file_entry(struct file_stru
49 static gid_t gid;
50 static char lastname[MAXPATHLEN], *lastdir;
51 static int lastdir_depth, lastdir_len = -1;
52+ static unsigned int del_heir_name_len = -1;
53+ static int in_del_hier = 0;
54 char thisname[MAXPATHLEN];
55 unsigned int l1 = 0, l2 = 0;
56 int alloc_len, basename_len, dirname_len, linkname_len, sum_len;
57@@ -547,7 +555,8 @@ void receive_file_entry(struct file_stru
58 rdev_major = 0;
59 uid = 0, gid = 0;
60 *lastname = '\0';
61- lastdir_len = -1;
62+ del_heir_name_len = lastdir_len = -1;
63+ in_del_hier = 0;
64 return;
65 }
66
67@@ -645,13 +654,27 @@ void receive_file_entry(struct file_stru
68 memset(bp, 0, file_struct_len);
69 bp += file_struct_len;
70
71- file->flags = flags & XMIT_DEL_START ? FLAG_DEL_START : 0;
72+ file->flags = 0;
73 file->modtime = modtime;
74 file->length = file_length;
75 file->mode = mode;
76 file->uid = uid;
77 file->gid = gid;
78
79+ if (S_ISDIR(mode)) {
80+ if (flags & XMIT_DEL_START) {
81+ in_del_hier = 1;
82+ del_heir_name_len = l1 + l2;
83+ file->flags |= FLAG_DEL_START;
84+ } else if (delete_during && in_del_hier) {
85+ if (!relative_paths || (l1 >= del_heir_name_len
86+ && thisname[del_heir_name_len] == '/'))
87+ file->flags |= FLAG_DEL_START;
88+ else
89+ in_del_hier = 0;
90+ }
91+ }
92+
93 if (dirname_len) {
94 file->dirname = lastdir = bp;
95 lastdir_len = dirname_len - 1;
8ace861d
WD
96@@ -1064,14 +1087,13 @@ static void send_directory(int f, struct
97 }
98
99
100-/**
101- * This function is normally called by the sender, but the receiver also
102- * uses it to construct its own file list if --delete has been specified.
103- * The delete_files() function in receiver.c sets f to -1 so that we just
104- * construct the file list in memory without sending it over the wire. It
105- * also has the side-effect of ignoring user-excludes if delete_excluded
106- * is set (so that the delete list includes user-excluded files).
107- **/
108+/* This function is normally called by the sender, but the receiving side
109+ * also uses it to construct one or more file lists if one of the --delete
110+ * options have been specified. The delete_in_dir() function sets f to -1
111+ * so that we just construct the file list in memory without sending it
112+ * over the wire. It also has the side-effect of ignoring user-excludes if
113+ * delete_excluded is set (so that the delete list includes user-excluded
114+ * files). */
115 struct file_list *send_file_list(int f, int argc, char *argv[])
116 {
117 int l;
118@@ -1129,7 +1151,9 @@ struct file_list *send_file_list(int f,
d8e9c894
WD
119 fname[l] = '\0';
120 }
121 }
122- if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) {
8ace861d 123+ if (f == -1 && delete_during)
d8e9c894
WD
124+ ; /* recurse is pre-set */
125+ else if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) {
559625f9 126 if (!recurse && xfer_dirs)
d8e9c894
WD
127 recurse = 1; /* allow one level */
128 } else if (recurse > 0)
8ace861d 129@@ -1644,3 +1668,77 @@ char *f_name(struct file_struct *f)
91cf5188
WD
130
131 return f_name_to(f, names[n]);
132 }
133+
91cf5188
WD
134+static int is_backup_file(char *fn)
135+{
136+ int k = strlen(fn) - backup_suffix_len;
137+ return k > 0 && strcmp(fn+k, backup_suffix) == 0;
138+}
139+
8ace861d 140+void delete_in_dir(struct file_list *flist, char *fname)
91cf5188
WD
141+{
142+ static int deletion_count = 0;
143+ struct file_list *del_flist;
144+ int save_recurse = recurse;
559625f9 145+ int save_xfer_dirs = xfer_dirs;
91cf5188 146+ int save_implied_dirs = implied_dirs;
d8e9c894 147+ int save_relative_paths = relative_paths;
91cf5188 148+ char *argv[1];
b5bbf19c 149+ int i, j, mode;
91cf5188
WD
150+
151+ if (max_delete && deletion_count >= max_delete)
152+ return;
153+
154+ if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
155+ rprintf(FINFO, "IO error encountered - skipping file deletion\n");
156+ max_delete = -1; /* avoid duplicating the above warning */
157+ return;
158+ }
159+
8ace861d
WD
160+ if (delete_during) {
161+ recurse = 1; /* allow one level only */
559625f9 162+ xfer_dirs = 1;
8ace861d
WD
163+ implied_dirs = 0;
164+ relative_paths = 1;
165+ }
91cf5188
WD
166+
167+ argv[0] = fname;
168+ del_flist = send_file_list(-1, 1, argv);
169+
d8e9c894 170+ relative_paths = save_relative_paths;
91cf5188 171+ implied_dirs = save_implied_dirs;
559625f9 172+ xfer_dirs = save_xfer_dirs;
91cf5188
WD
173+ recurse = save_recurse;
174+
175+ if (!del_flist)
176+ return;
177+
178+ if (verbose > 1)
179+ rprintf(FINFO, "deleting in %s\n", safe_fname(fname));
180+
181+ for (i = del_flist->count-1; i >= 0; i--) {
182+ if (max_delete && deletion_count >= max_delete)
183+ break;
184+ if (!del_flist->files[i]->basename)
185+ continue;
b5bbf19c
WD
186+ mode = del_flist->files[i]->mode;
187+ if ((j = flist_find(flist, del_flist->files[i])) < 0
188+ || (delete_during && S_ISDIR(mode)
189+ && !S_ISDIR(flist->files[j]->mode))) {
91cf5188 190+ char *f = f_name(del_flist->files[i]);
91cf5188
WD
191+ if (make_backups && (backup_dir || !is_backup_file(f))
192+ && !S_ISDIR(mode)) {
193+ make_backup(f);
194+ if (verbose) {
195+ rprintf(FINFO, "deleting %s\n",
196+ safe_fname(f));
197+ }
65a73542
WD
198+ } else {
199+ delete_file(f, S_ISDIR(mode)
b5bbf19c 200+ ? DEL_DIR | DEL_RECURSE : 0);
65a73542 201+ }
91cf5188
WD
202+ deletion_count++;
203+ }
204+ }
205+ flist_free(del_flist);
206+}
b5bbf19c 207--- orig/generator.c 2005-01-20 23:05:34
8ace861d 208+++ generator.c 2005-01-23 07:55:40
f3560f28 209@@ -34,6 +34,7 @@ extern int preserve_hard_links;
91cf5188
WD
210 extern int preserve_perms;
211 extern int preserve_uid;
212 extern int preserve_gid;
213+extern int delete_during;
91cf5188
WD
214 extern int update_only;
215 extern int opt_ignore_existing;
216 extern int inplace;
f3560f28 217@@ -233,7 +234,8 @@ static void generate_and_send_sums(int f
91cf5188
WD
218 * @note This comment was added later by mbp who was trying to work it
219 * out. It might be wrong.
220 */
221-static void recv_generator(char *fname, struct file_struct *file, int i,
222+static void recv_generator(char *fname, struct file_list *flist,
223+ struct file_struct *file, int i,
224 int f_out, int f_out_name)
225 {
226 int fd = -1, f_copy = -1;
f3560f28 227@@ -308,6 +310,11 @@ static void recv_generator(char *fname,
91cf5188
WD
228 }
229 /* f_out is set to -1 when doing final directory-permission
230 * and modification-time repair. */
5128f136
WD
231+ if (delete_during && f_out != -1
232+ && (file->flags & FLAG_DEL_START)) {
8ace861d 233+ delete_in_dir(flist, fname);
5128f136
WD
234+ statret = 1;
235+ }
91cf5188
WD
236 if (set_perms(fname, file, statret ? NULL : &st, 0)
237 && verbose && f_out != -1)
238 rprintf(FINFO, "%s/\n", safe_fname(fname));
f3560f28 239@@ -641,7 +648,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
240 }
241
242 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
243- file, i, f_out, f_out_name);
244+ flist, file, i, f_out, f_out_name);
245 }
246
247 phase++;
f3560f28 248@@ -658,7 +665,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
249 while ((i = get_redo_num()) != -1) {
250 struct file_struct *file = flist->files[i];
251 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
252- file, i, f_out, f_out_name);
253+ flist, file, i, f_out, f_out_name);
254 }
255
256 phase++;
f3560f28 257@@ -680,7 +687,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
258 if (!file->basename || !S_ISDIR(file->mode))
259 continue;
260 recv_generator(local_name ? local_name : f_name(file),
261- file, i, -1, -1);
262+ flist, file, i, -1, -1);
263 }
264
265 if (verbose > 2)
786384c2 266--- orig/main.c 2005-01-23 07:27:24
d8e9c894 267+++ main.c 2005-01-23 01:48:52
786384c2 268@@ -736,6 +736,8 @@ int client_run(int f_in, int f_out, pid_
f3560f28
WD
269
270 if (!read_batch)
271 send_exclude_list(f_out);
272+ if (cvs_exclude)
273+ add_cvs_excludes();
274
275 if (filesfrom_fd >= 0) {
276 io_set_filesfrom_fds(filesfrom_fd, f_out);
559625f9 277--- orig/options.c 2005-01-24 00:18:21
d8e9c894
WD
278+++ options.c 2005-01-23 01:53:35
279@@ -54,6 +54,7 @@ int dry_run = 0;
91cf5188
WD
280 int local_server = 0;
281 int ignore_times = 0;
282 int delete_mode = 0;
283+int delete_during = 0;
d8e9c894
WD
284 int delete_before = 0;
285 int delete_after = 0;
91cf5188 286 int delete_excluded = 0;
d8e9c894 287@@ -274,7 +275,8 @@ void usage(enum logcode F)
91cf5188
WD
288 rprintf(F," --existing only update files that already exist\n");
289 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
290 rprintf(F," --delete delete files that don't exist on the sending side\n");
d8e9c894 291- rprintf(F," --delete-after receiver deletes after transferring, not before\n");
919b037d
WD
292+ rprintf(F," --delete-before receiver deletes before transfer, not during\n");
293+ rprintf(F," --delete-after receiver deletes after transfer, not during\n");
91cf5188 294 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
91cf5188 295 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
d8e9c894 296 rprintf(F," --force force deletion of directories even if not empty\n");
559625f9 297@@ -341,7 +343,9 @@ static struct poptOption long_options[]
91cf5188 298 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
d8e9c894
WD
299 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
300 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
301- {"delete", 0, POPT_ARG_NONE, &delete_before, 0, 0, 0 },
b5bbf19c
WD
302+ {"delete", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
303+ {"delete-during", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
304+ {"delete-before", 0, POPT_ARG_NONE, &delete_before, 0, 0, 0 },
d8e9c894
WD
305 {"delete-after", 0, POPT_ARG_NONE, &delete_after, 0, 0, 0 },
306 {"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
91cf5188 307 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
559625f9 308@@ -854,10 +858,10 @@ int parse_arguments(int *argc, const cha
91cf5188
WD
309 if (relative_paths < 0)
310 relative_paths = files_from? 1 : 0;
311
d8e9c894 312- if (delete_before || delete_after)
b5bbf19c 313+ if (delete_during || delete_before || delete_after)
d8e9c894
WD
314 delete_mode = 1;
315 if (delete_excluded && !delete_mode)
316- delete_mode = delete_before = 1;
b5bbf19c 317+ delete_mode = delete_during = 1;
d8e9c894 318
91cf5188
WD
319 *argv = poptGetArgs(pc);
320 *argc = count_args(*argv);
559625f9 321@@ -1160,7 +1164,9 @@ void server_options(char **args,int *arg
91cf5188
WD
322 if (am_sender) {
323 if (delete_excluded)
324 args[ac++] = "--delete-excluded";
d8e9c894 325- else if (delete_before || delete_after)
91cf5188
WD
326+ else if (delete_before)
327+ args[ac++] = "--delete-before";
328+ else if (delete_during || delete_after)
329 args[ac++] = "--delete";
330
331 if (delete_after)
786384c2 332--- orig/receiver.c 2005-01-23 07:27:24
8ace861d 333+++ receiver.c 2005-01-23 07:55:58
786384c2 334@@ -23,7 +23,6 @@
91cf5188 335 extern int verbose;
786384c2 336 extern int recurse;
91cf5188
WD
337 extern int delete_after;
338-extern int max_delete;
339 extern int csum_length;
340 extern struct stats stats;
341 extern int dry_run;
786384c2 342@@ -35,7 +34,6 @@ extern int relative_paths;
91cf5188
WD
343 extern int keep_dirlinks;
344 extern int preserve_hard_links;
345 extern int preserve_perms;
346-extern int cvs_exclude;
347 extern int io_error;
348 extern char *tmpdir;
349 extern char *partial_dir;
786384c2 350@@ -43,9 +41,6 @@ extern char *basis_dir[];
91cf5188
WD
351 extern int basis_dir_cnt;
352 extern int make_backups;
353 extern int do_progress;
354-extern char *backup_dir;
355-extern char *backup_suffix;
356-extern int backup_suffix_len;
357 extern int cleanup_got_literal;
358 extern int module_id;
359 extern int ignore_errors;
786384c2 360@@ -57,66 +52,19 @@ extern int inplace;
91cf5188
WD
361 extern struct exclude_list_struct server_exclude_list;
362
363
91cf5188
WD
364-static int is_backup_file(char *fn)
365-{
366- int k = strlen(fn) - backup_suffix_len;
367- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
368-}
369-
370-
371-/* This deletes any files on the receiving side that are not present
372- * on the sending side. */
f3560f28
WD
373+/* This deletes any files on the receiving side that are not present on the
374+ * sending side. This is used by --delete-before and --delete-after. */
375 void delete_files(struct file_list *flist)
376 {
91cf5188
WD
377- struct file_list *local_file_list;
378- int i, j;
379- char *argv[1], fbuf[MAXPATHLEN];
380- static int deletion_count;
381-
382- if (cvs_exclude)
383- add_cvs_excludes();
384-
385- if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
386- rprintf(FINFO,"IO error encountered - skipping file deletion\n");
387- return;
388- }
f3560f28
WD
389+ char fbuf[MAXPATHLEN];
390+ int j;
391
392 for (j = 0; j < flist->count; j++) {
393 if (!(flist->files[j]->flags & FLAG_DEL_START)
394 || !S_ISDIR(flist->files[j]->mode))
395 continue;
396
91cf5188
WD
397- argv[0] = f_name_to(flist->files[j], fbuf);
398-
399- if (!(local_file_list = send_file_list(-1, 1, argv)))
400- continue;
401-
402- if (verbose > 1)
403- rprintf(FINFO, "deleting in %s\n", safe_fname(fbuf));
404-
405- for (i = local_file_list->count-1; i >= 0; i--) {
406- if (max_delete && deletion_count >= max_delete)
407- break;
408- if (!local_file_list->files[i]->basename)
409- continue;
410- if (flist_find(flist,local_file_list->files[i]) < 0) {
411- char *f = f_name(local_file_list->files[i]);
412- int mode = local_file_list->files[i]->mode;
413- if (make_backups && (backup_dir || !is_backup_file(f))
414- && !S_ISDIR(mode)) {
415- make_backup(f);
416- if (verbose) {
417- rprintf(FINFO, "deleting %s\n",
418- safe_fname(f));
419- }
65a73542
WD
420- } else {
421- delete_file(f, S_ISDIR(mode)
b5bbf19c 422- ? DEL_DIR | DEL_RECURSE : 0);
65a73542 423- }
91cf5188
WD
424- deletion_count++;
425- }
426- }
427- flist_free(local_file_list);
8ace861d 428+ delete_in_dir(flist, f_name_to(flist->files[j], fbuf));
f3560f28
WD
429 }
430 }
431
559625f9 432--- orig/rsync.yo 2005-01-24 00:18:21
d8e9c894 433+++ rsync.yo 2005-01-23 02:57:49
559625f9 434@@ -342,7 +342,8 @@ verb(
91cf5188
WD
435 --existing only update files that already exist
436 --ignore-existing ignore files that already exist on receiver
437 --delete delete files that don't exist on sender
d8e9c894 438- --delete-after receiver deletes after transfer, not before
91cf5188
WD
439+ --delete-before receiver deletes before xfer, not during
440+ --delete-after receiver deletes after transfer, not during
441 --delete-excluded also delete excluded files on receiver
91cf5188 442 --ignore-errors delete even if there are I/O errors
d8e9c894 443 --force force deletion of dirs even if not empty
559625f9 444@@ -689,14 +690,23 @@ prevent temporary filesystem failures (s
91cf5188
WD
445 sending side causing a massive deletion of files on the
446 destination. You can override this with the --ignore-errors option.
447
d8e9c894
WD
448-dit(bf(--delete-after)) By default rsync does file deletions on the
449-receiving side before transferring files to try to ensure that there is
450-sufficient space on the receiving filesystem. If you want to delete
451-after transferring, use the --delete-after switch. Implies --delete.
452-
453-One reason to use --delete-after is to avoid a delay before the start of
454-the transfer (while the receiving side is scanned for deletions) as this
455-delay might cause the transfer to timeout.
91cf5188
WD
456+By default rsync does file deletions on the receiving side during the
457+transfer of files to try make it as efficient as possible. For other
458+options, see --delete-before and --delte-after.
459+
460+dit(bf(--delete-before)) Request that the file-deletions on the receving
461+side be done prior to starting the transfer, not incrementally as the
462+transfer happens. Implies --delete.
463+
464+One reason to use --delete-before is if the filesystem is tight for space
465+and removing extraneous files would help to make the transfer possible.
466+However, it does introduce a delay before the start of the transfer (while
467+the receiving side is being scanned for deletions) and this delay might
468+cause the transfer to timeout.
469+
470+dit(bf(--delete-after)) Request that the file-deletions on the receving
471+side be done after the transfer has completed, not incrementally as the
472+transfer happens. Implies --delete.
d8e9c894 473
91cf5188
WD
474 dit(bf(--delete-excluded)) In addition to deleting the files on the
475 receiving side that are not on the sending side, this tells rsync to also