Updated to work with latest CVS.
[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
d8e9c894
WD
14--- orig/flist.c 2005-01-22 22:48:52
15+++ flist.c 2005-01-23 07:14:40
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
WD
25 extern int recurse;
26 extern int keep_dirs;
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;
d8e9c894
WD
96@@ -1129,7 +1152,9 @@ struct file_list *send_file_list(int f,
97 fname[l] = '\0';
98 }
99 }
100- if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) {
101+ if (relative_paths < 0)
102+ ; /* recurse is pre-set */
103+ else if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) {
104 if (!recurse && keep_dirs)
105 recurse = 1; /* allow one level */
106 } else if (recurse > 0)
107@@ -1644,3 +1669,75 @@ char *f_name(struct file_struct *f)
91cf5188
WD
108
109 return f_name_to(f, names[n]);
110 }
111+
91cf5188
WD
112+static int is_backup_file(char *fn)
113+{
114+ int k = strlen(fn) - backup_suffix_len;
115+ return k > 0 && strcmp(fn+k, backup_suffix) == 0;
116+}
117+
118+void delete_in_dir(struct file_list *flist, char *fname, int do_subdirs)
119+{
120+ static int deletion_count = 0;
121+ struct file_list *del_flist;
122+ int save_recurse = recurse;
123+ int save_keep_dirs = keep_dirs;
124+ int save_implied_dirs = implied_dirs;
d8e9c894 125+ int save_relative_paths = relative_paths;
91cf5188 126+ char *argv[1];
b5bbf19c 127+ int i, j, mode;
91cf5188
WD
128+
129+ if (max_delete && deletion_count >= max_delete)
130+ return;
131+
132+ if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
133+ rprintf(FINFO, "IO error encountered - skipping file deletion\n");
134+ max_delete = -1; /* avoid duplicating the above warning */
135+ return;
136+ }
137+
138+ recurse = do_subdirs ? -1 : 1;
139+ keep_dirs = 1;
140+ implied_dirs = 0;
d8e9c894 141+ relative_paths = -1;
91cf5188
WD
142+
143+ argv[0] = fname;
144+ del_flist = send_file_list(-1, 1, argv);
145+
d8e9c894 146+ relative_paths = save_relative_paths;
91cf5188
WD
147+ implied_dirs = save_implied_dirs;
148+ keep_dirs = save_keep_dirs;
149+ recurse = save_recurse;
150+
151+ if (!del_flist)
152+ return;
153+
154+ if (verbose > 1)
155+ rprintf(FINFO, "deleting in %s\n", safe_fname(fname));
156+
157+ for (i = del_flist->count-1; i >= 0; i--) {
158+ if (max_delete && deletion_count >= max_delete)
159+ break;
160+ if (!del_flist->files[i]->basename)
161+ continue;
b5bbf19c
WD
162+ mode = del_flist->files[i]->mode;
163+ if ((j = flist_find(flist, del_flist->files[i])) < 0
164+ || (delete_during && S_ISDIR(mode)
165+ && !S_ISDIR(flist->files[j]->mode))) {
91cf5188 166+ char *f = f_name(del_flist->files[i]);
91cf5188
WD
167+ if (make_backups && (backup_dir || !is_backup_file(f))
168+ && !S_ISDIR(mode)) {
169+ make_backup(f);
170+ if (verbose) {
171+ rprintf(FINFO, "deleting %s\n",
172+ safe_fname(f));
173+ }
65a73542
WD
174+ } else {
175+ delete_file(f, S_ISDIR(mode)
b5bbf19c 176+ ? DEL_DIR | DEL_RECURSE : 0);
65a73542 177+ }
91cf5188
WD
178+ deletion_count++;
179+ }
180+ }
181+ flist_free(del_flist);
182+}
b5bbf19c 183--- orig/generator.c 2005-01-20 23:05:34
f3560f28
WD
184+++ generator.c 2005-01-21 10:21:39
185@@ -34,6 +34,7 @@ extern int preserve_hard_links;
91cf5188
WD
186 extern int preserve_perms;
187 extern int preserve_uid;
188 extern int preserve_gid;
189+extern int delete_during;
91cf5188
WD
190 extern int update_only;
191 extern int opt_ignore_existing;
192 extern int inplace;
f3560f28 193@@ -233,7 +234,8 @@ static void generate_and_send_sums(int f
91cf5188
WD
194 * @note This comment was added later by mbp who was trying to work it
195 * out. It might be wrong.
196 */
197-static void recv_generator(char *fname, struct file_struct *file, int i,
198+static void recv_generator(char *fname, struct file_list *flist,
199+ struct file_struct *file, int i,
200 int f_out, int f_out_name)
201 {
202 int fd = -1, f_copy = -1;
f3560f28 203@@ -308,6 +310,11 @@ static void recv_generator(char *fname,
91cf5188
WD
204 }
205 /* f_out is set to -1 when doing final directory-permission
206 * and modification-time repair. */
5128f136
WD
207+ if (delete_during && f_out != -1
208+ && (file->flags & FLAG_DEL_START)) {
91cf5188 209+ delete_in_dir(flist, fname, 0);
5128f136
WD
210+ statret = 1;
211+ }
91cf5188
WD
212 if (set_perms(fname, file, statret ? NULL : &st, 0)
213 && verbose && f_out != -1)
214 rprintf(FINFO, "%s/\n", safe_fname(fname));
f3560f28 215@@ -641,7 +648,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
216 }
217
218 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
219- file, i, f_out, f_out_name);
220+ flist, file, i, f_out, f_out_name);
221 }
222
223 phase++;
f3560f28 224@@ -658,7 +665,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
225 while ((i = get_redo_num()) != -1) {
226 struct file_struct *file = flist->files[i];
227 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
228- file, i, f_out, f_out_name);
229+ flist, file, i, f_out, f_out_name);
230 }
231
232 phase++;
f3560f28 233@@ -680,7 +687,7 @@ void generate_files(int f_out, struct fi
91cf5188
WD
234 if (!file->basename || !S_ISDIR(file->mode))
235 continue;
236 recv_generator(local_name ? local_name : f_name(file),
237- file, i, -1, -1);
238+ flist, file, i, -1, -1);
239 }
240
241 if (verbose > 2)
d8e9c894
WD
242--- orig/main.c 2005-01-22 22:48:52
243+++ main.c 2005-01-23 01:48:52
244@@ -737,6 +737,8 @@ int client_run(int f_in, int f_out, pid_
f3560f28
WD
245
246 if (!read_batch)
247 send_exclude_list(f_out);
248+ if (cvs_exclude)
249+ add_cvs_excludes();
250
251 if (filesfrom_fd >= 0) {
252 io_set_filesfrom_fds(filesfrom_fd, f_out);
d8e9c894
WD
253--- orig/options.c 2005-01-23 01:45:43
254+++ options.c 2005-01-23 01:53:35
255@@ -54,6 +54,7 @@ int dry_run = 0;
91cf5188
WD
256 int local_server = 0;
257 int ignore_times = 0;
258 int delete_mode = 0;
259+int delete_during = 0;
d8e9c894
WD
260 int delete_before = 0;
261 int delete_after = 0;
91cf5188 262 int delete_excluded = 0;
d8e9c894 263@@ -274,7 +275,8 @@ void usage(enum logcode F)
91cf5188
WD
264 rprintf(F," --existing only update files that already exist\n");
265 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
266 rprintf(F," --delete delete files that don't exist on the sending side\n");
d8e9c894 267- rprintf(F," --delete-after receiver deletes after transferring, not before\n");
919b037d
WD
268+ rprintf(F," --delete-before receiver deletes before transfer, not during\n");
269+ rprintf(F," --delete-after receiver deletes after transfer, not during\n");
91cf5188 270 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
91cf5188 271 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
d8e9c894
WD
272 rprintf(F," --force force deletion of directories even if not empty\n");
273@@ -340,7 +342,9 @@ static struct poptOption long_options[]
91cf5188 274 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
d8e9c894
WD
275 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
276 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
277- {"delete", 0, POPT_ARG_NONE, &delete_before, 0, 0, 0 },
b5bbf19c
WD
278+ {"delete", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
279+ {"delete-during", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
280+ {"delete-before", 0, POPT_ARG_NONE, &delete_before, 0, 0, 0 },
d8e9c894
WD
281 {"delete-after", 0, POPT_ARG_NONE, &delete_after, 0, 0, 0 },
282 {"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
91cf5188 283 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
d8e9c894 284@@ -853,10 +857,10 @@ int parse_arguments(int *argc, const cha
91cf5188
WD
285 if (relative_paths < 0)
286 relative_paths = files_from? 1 : 0;
287
d8e9c894 288- if (delete_before || delete_after)
b5bbf19c 289+ if (delete_during || delete_before || delete_after)
d8e9c894
WD
290 delete_mode = 1;
291 if (delete_excluded && !delete_mode)
292- delete_mode = delete_before = 1;
b5bbf19c 293+ delete_mode = delete_during = 1;
d8e9c894 294
91cf5188
WD
295 *argv = poptGetArgs(pc);
296 *argc = count_args(*argv);
d8e9c894 297@@ -1159,7 +1163,9 @@ void server_options(char **args,int *arg
91cf5188
WD
298 if (am_sender) {
299 if (delete_excluded)
300 args[ac++] = "--delete-excluded";
d8e9c894 301- else if (delete_before || delete_after)
91cf5188
WD
302+ else if (delete_before)
303+ args[ac++] = "--delete-before";
304+ else if (delete_during || delete_after)
305 args[ac++] = "--delete";
306
307 if (delete_after)
d8e9c894
WD
308--- orig/receiver.c 2005-01-22 22:48:52
309+++ receiver.c 2005-01-23 01:50:42
310@@ -21,8 +21,8 @@
311 #include "rsync.h"
312
91cf5188 313 extern int verbose;
d8e9c894 314+extern int recurse;
91cf5188
WD
315 extern int delete_after;
316-extern int max_delete;
317 extern int csum_length;
318 extern struct stats stats;
319 extern int dry_run;
d8e9c894 320@@ -35,7 +35,6 @@ extern int keep_dirs;
91cf5188
WD
321 extern int keep_dirlinks;
322 extern int preserve_hard_links;
323 extern int preserve_perms;
324-extern int cvs_exclude;
325 extern int io_error;
326 extern char *tmpdir;
327 extern char *partial_dir;
d8e9c894 328@@ -43,9 +42,6 @@ extern char *basis_dir[];
91cf5188
WD
329 extern int basis_dir_cnt;
330 extern int make_backups;
331 extern int do_progress;
332-extern char *backup_dir;
333-extern char *backup_suffix;
334-extern int backup_suffix_len;
335 extern int cleanup_got_literal;
336 extern int module_id;
337 extern int ignore_errors;
d8e9c894 338@@ -57,66 +53,19 @@ extern int inplace;
91cf5188
WD
339 extern struct exclude_list_struct server_exclude_list;
340
341
91cf5188
WD
342-static int is_backup_file(char *fn)
343-{
344- int k = strlen(fn) - backup_suffix_len;
345- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
346-}
347-
348-
349-/* This deletes any files on the receiving side that are not present
350- * on the sending side. */
f3560f28
WD
351+/* This deletes any files on the receiving side that are not present on the
352+ * sending side. This is used by --delete-before and --delete-after. */
353 void delete_files(struct file_list *flist)
354 {
91cf5188
WD
355- struct file_list *local_file_list;
356- int i, j;
357- char *argv[1], fbuf[MAXPATHLEN];
358- static int deletion_count;
359-
360- if (cvs_exclude)
361- add_cvs_excludes();
362-
363- if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
364- rprintf(FINFO,"IO error encountered - skipping file deletion\n");
365- return;
366- }
f3560f28
WD
367+ char fbuf[MAXPATHLEN];
368+ int j;
369
370 for (j = 0; j < flist->count; j++) {
371 if (!(flist->files[j]->flags & FLAG_DEL_START)
372 || !S_ISDIR(flist->files[j]->mode))
373 continue;
374
91cf5188
WD
375- argv[0] = f_name_to(flist->files[j], fbuf);
376-
377- if (!(local_file_list = send_file_list(-1, 1, argv)))
378- continue;
379-
380- if (verbose > 1)
381- rprintf(FINFO, "deleting in %s\n", safe_fname(fbuf));
382-
383- for (i = local_file_list->count-1; i >= 0; i--) {
384- if (max_delete && deletion_count >= max_delete)
385- break;
386- if (!local_file_list->files[i]->basename)
387- continue;
388- if (flist_find(flist,local_file_list->files[i]) < 0) {
389- char *f = f_name(local_file_list->files[i]);
390- int mode = local_file_list->files[i]->mode;
391- if (make_backups && (backup_dir || !is_backup_file(f))
392- && !S_ISDIR(mode)) {
393- make_backup(f);
394- if (verbose) {
395- rprintf(FINFO, "deleting %s\n",
396- safe_fname(f));
397- }
65a73542
WD
398- } else {
399- delete_file(f, S_ISDIR(mode)
b5bbf19c 400- ? DEL_DIR | DEL_RECURSE : 0);
65a73542 401- }
91cf5188
WD
402- deletion_count++;
403- }
404- }
405- flist_free(local_file_list);
f3560f28
WD
406+ delete_in_dir(flist, f_name_to(flist->files[j], fbuf), recurse);
407 }
408 }
409
d8e9c894
WD
410--- orig/rsync.yo 2005-01-22 22:48:52
411+++ rsync.yo 2005-01-23 02:57:49
412@@ -341,7 +341,8 @@ verb(
91cf5188
WD
413 --existing only update files that already exist
414 --ignore-existing ignore files that already exist on receiver
415 --delete delete files that don't exist on sender
d8e9c894 416- --delete-after receiver deletes after transfer, not before
91cf5188
WD
417+ --delete-before receiver deletes before xfer, not during
418+ --delete-after receiver deletes after transfer, not during
419 --delete-excluded also delete excluded files on receiver
91cf5188 420 --ignore-errors delete even if there are I/O errors
d8e9c894
WD
421 --force force deletion of dirs even if not empty
422@@ -681,14 +682,23 @@ prevent temporary filesystem failures (s
91cf5188
WD
423 sending side causing a massive deletion of files on the
424 destination. You can override this with the --ignore-errors option.
425
d8e9c894
WD
426-dit(bf(--delete-after)) By default rsync does file deletions on the
427-receiving side before transferring files to try to ensure that there is
428-sufficient space on the receiving filesystem. If you want to delete
429-after transferring, use the --delete-after switch. Implies --delete.
430-
431-One reason to use --delete-after is to avoid a delay before the start of
432-the transfer (while the receiving side is scanned for deletions) as this
433-delay might cause the transfer to timeout.
91cf5188
WD
434+By default rsync does file deletions on the receiving side during the
435+transfer of files to try make it as efficient as possible. For other
436+options, see --delete-before and --delte-after.
437+
438+dit(bf(--delete-before)) Request that the file-deletions on the receving
439+side be done prior to starting the transfer, not incrementally as the
440+transfer happens. Implies --delete.
441+
442+One reason to use --delete-before is if the filesystem is tight for space
443+and removing extraneous files would help to make the transfer possible.
444+However, it does introduce a delay before the start of the transfer (while
445+the receiving side is being scanned for deletions) and this delay might
446+cause the transfer to timeout.
447+
448+dit(bf(--delete-after)) Request that the file-deletions on the receving
449+side be done after the transfer has completed, not incrementally as the
450+transfer happens. Implies --delete.
d8e9c894 451
91cf5188
WD
452 dit(bf(--delete-excluded)) In addition to deleting the files on the
453 receiving side that are not on the sending side, this tells rsync to also