My version of Matt's improvements related to missing source args:
authorWayne Davison <wayned@samba.org>
Fri, 13 Mar 2009 16:33:51 +0000 (09:33 -0700)
committerWayne Davison <wayned@samba.org>
Fri, 13 Mar 2009 16:37:31 +0000 (09:37 -0700)
- Implement --ignore-missing-args.
- In the absence of --*-missing-args, a missing source arg is an
  FERROR_XFER, but doesn't need to be an IOERR_GENERAL.
- Revise the man page.

flist.c
generator.c
options.c
rsync.yo

diff --git a/flist.c b/flist.c
index 860bf83..09b4fc5 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -51,7 +51,7 @@ extern int preserve_links;
 extern int preserve_hard_links;
 extern int preserve_devices;
 extern int preserve_specials;
-extern int delete_missing_args;
+extern int missing_args;
 extern int uid_ndx;
 extern int gid_ndx;
 extern int eol_nulls;
@@ -2177,14 +2177,21 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
                 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
                 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
-                       if (errno == ENOENT && delete_missing_args) {
-                               /* Rsync will treat a mode of 0 as deleted. */
-                               memset(&st, 0, sizeof st);
-                       } else {
-                               io_error |= IOERR_GENERAL;
+                       if (errno != ENOENT || missing_args == 0) {
+                               /* This is a transfer error, but inhibit deletion
+                                * only if we might be omitting an existing file. */
+                               if (errno != ENOENT)
+                                       io_error |= IOERR_GENERAL;
                                rsyserr(FERROR_XFER, errno, "link_stat %s failed",
                                        full_fname(fbuf));
                                continue;
+                       } else if (missing_args == 1) {
+                               /* Just ignore the arg. */
+                               continue;
+                       } else /* (missing_args == 2) */ {
+                               /* Send the arg as a "missing" entry with
+                                * mode 0, which tells the generator to delete it. */
+                               memset(&st, 0, sizeof st);
                        }
                }
 
index 4fad7f7..12007a1 100644 (file)
@@ -50,7 +50,7 @@ extern int delete_mode;
 extern int delete_before;
 extern int delete_during;
 extern int delete_after;
-extern int delete_missing_args;
+extern int missing_args;
 extern int msgdone_cnt;
 extern int ignore_errors;
 extern int remove_source_files;
@@ -1031,7 +1031,7 @@ static void list_file_entry(struct file_struct *f)
                        F_SYMLINK(f));
        } else
 #endif
-       if (delete_missing_args && !f->mode) {
+       if (missing_args == 2 && f->mode == 0) {
                rprintf(FINFO, "%-*s %s\n",
                        colwidth + 31, "*missing",
                        f_name(f, NULL));
@@ -1177,7 +1177,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                stat_errno = errno;
        }
 
-       if (delete_missing_args && file->mode == 0) {
+       if (missing_args == 2 && file->mode == 0) {
                if (filter_list.head && check_filter(&filter_list, FINFO, fname, is_dir) < 0)
                        return;
                if (statret == 0)
index 51697ad..e7c6c61 100644 (file)
--- a/options.c
+++ b/options.c
@@ -69,7 +69,6 @@ int delete_during = 0;
 int delete_before = 0;
 int delete_after = 0;
 int delete_excluded = 0;
-int delete_missing_args = 0;
 int remove_source_files = 0;
 int one_file_system = 0;
 int protocol_version = PROTOCOL_VERSION;
@@ -82,6 +81,7 @@ int am_sender = 0;
 int am_starting_up = 1;
 int relative_paths = -1;
 int implied_dirs = 1;
+int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
 int numeric_ids = 0;
 int msgs2stderr = 0;
 int allow_8bit_chars = 0;
@@ -719,7 +719,8 @@ void usage(enum logcode F)
   rprintf(F,"     --delete-delay          find deletions during, delete after\n");
   rprintf(F,"     --delete-after          receiver deletes after transfer, not during\n");
   rprintf(F,"     --delete-excluded       also delete excluded files from destination dirs\n");
-  rprintf(F,"     --delete-missing-args   receiver deletes each missing source arg\n");
+  rprintf(F,"     --ignore-missing-args   ignore missing source args without error\n");
+  rprintf(F,"     --delete-missing-args   delete missing source args from destination\n");
   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
@@ -910,7 +911,8 @@ static struct poptOption long_options[] = {
   {"delete-delay",     0,  POPT_ARG_VAL,    &delete_during, 2, 0, 0 },
   {"delete-after",     0,  POPT_ARG_NONE,   &delete_after, 0, 0, 0 },
   {"delete-excluded",  0,  POPT_ARG_NONE,   &delete_excluded, 0, 0, 0 },
-  {"delete-missing-args",0,POPT_ARG_NONE,   &delete_missing_args, 0, 0, 0 },
+  {"delete-missing-args",0,POPT_BIT_SET,    &missing_args, 2, 0, 0 },
+  {"ignore-missing-args",0,POPT_BIT_SET,    &missing_args, 1, 0, 0 },
   {"remove-sent-files",0,  POPT_ARG_VAL,    &remove_source_files, 2, 0, 0 }, /* deprecated */
   {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
   {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
@@ -1925,7 +1927,9 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                return 0;
        }
 
-       if (refused_delete && (delete_mode || delete_missing_args)) {
+       if (missing_args == 3) /* simplify if both options were specified */
+               missing_args = 2;
+       if (refused_delete && (delete_mode || missing_args == 2)) {
                create_refuse_error(refused_delete);
                return 0;
        }
@@ -2482,8 +2486,12 @@ void server_options(char **args, int *argc_p)
                }
        }
 
-       if (delete_missing_args)
+       /* --delete-missing-args needs the cooperation of both sides, but
+        * the sender can handle --ignore-missing-args by itself. */
+       if (missing_args == 2)
                args[ac++] = "--delete-missing-args";
+       else if (missing_args == 1 && !am_sender)
+               args[ac++] = "--ignore-missing-args";
 
        if (modify_window_set) {
                if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
index 2ff224f..941f7a5 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -375,7 +375,8 @@ to the detailed description below for a complete description.  verb(
      --delete-delay          find deletions during, delete after
      --delete-after          receiver deletes after transfer, not before
      --delete-excluded       also delete excluded files from dest dirs
-     --delete-missing-args   receiver deletes each missing source arg
+     --ignore-missing-args   ignore missing source args without error
+     --delete-missing-args   delete missing source args from destination
      --ignore-errors         delete even if there are I/O errors
      --force                 force deletion of dirs even if not empty
      --max-delete=NUM        don't delete more than NUM files
@@ -1264,12 +1265,22 @@ this way on the receiver, and for a way to protect files from
 bf(--delete-excluded).
 See bf(--delete) (which is implied) for more details on file-deletion.
 
-dit(bf(--delete-missing-args)) Any source arg that is found to me missing is
-treated as a request to delete the file by the receiver rather than the sender
-generating a missing-file error.  Does not affect vanished files discovered
-through recursive scanning of directories, just the args mentioned on the
-command-line or in the bf(--files-from) list.  Can be used with or without any
-other type of delete processing.
+dit(bf(--ignore-missing-args)) When rsync is first processing the explicitly
+requested source files (e.g. command-line arguments or bf(--files-from)
+entries), it is normally an error if the file cannot be found.  This option
+suppresses that error, and does not try to transfer the file.  This does not
+affect subsequent vanished-file errors if a file was initially found to be
+present and later is no longer there.
+
+dit(bf(--delete-missing-args)) This option takes the behavior of (the implied)
+bf(--ignore-missing-args) option a step farther:  each missing arg will become
+a deletion request of the corresponding destination file on the receiving side
+(should it exist).  If the destination file is a non-empty directory, it will
+only be successfully deleted if --force or --delete are in effect.  Other than
+that, this option is independent of any other type of delete processing.
+
+The missing source files are represented by special file-list entries which
+display as a "*missing" entry in the bf(--list-only) output.
 
 dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
 even when there are I/O errors.