Feature request for rsync for running scripts

Wayne Davison wayned at samba.org
Fri Jul 22 18:49:37 GMT 2005


On Wed, Jul 20, 2005 at 08:16:49PM -0500, Evan Harris wrote:
> Instead of putting those bits of info in the environment, why not just use
> the same substitutions as are available in the log format directive in the
> command string?

I like the environment method better.  Its seems easier for the user to
code their script safely and to get it working without having to worry
about getting the positional parameters synchronized (since each script
would have its own list of positional parameters that it was expecting
to receive).  Also, the log-format escapes include values that won't
expand to anything useful (such as the various byte-count escapes).
Your idea would certainly avoid the configure issues with putenv(), but
I think I'd still prefer going that route.

> maybe the -R option could be modified to be able to take a numeric
> parameter that specifies how many levels of the relative path should
> be removed, similar to what patch does?

Yes, something like that would be nice.  I suggested something similar
in the discussion about a tar-like --directory option (that resulted in
a patches diff for a --source-cd option, but I din't like it due to its
side-effects).  My latest idea is to let someone put a "/./" dir into
the relative path to indicate where the implied dirs start.  For
instance:

    rsync -avR host::module/some/path/./to/the/files/foo.txt /dest

That would duplicate the directories "to/the/files" in /dest instead of
"some/path/to/the/files".  The advantage of this over a single strip
count is that it also works with multiple source paths.  Attached is a
patch that implements this idea.

..wayne..
-------------- next part --------------
Index: flist.c
--- flist.c	7 Jul 2005 19:49:14 -0000	1.299
+++ flist.c	22 Jul 2005 18:40:42 -0000
@@ -1166,34 +1166,16 @@ struct file_list *send_file_list(int f, 
 					dir = fname;
 				fname = p + 1;
 			}
-		} else if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
-			/* this ensures we send the intermediate directories,
-			   thus getting their permissions right */
-			char *lp = lastpath, *fn = fname, *slash = fname;
-			*p = 0;
-			/* Skip any initial directories in our path that we
-			 * have in common with lastpath. */
-			while (*fn && *lp == *fn) {
-				if (*fn == '/')
-					slash = fn;
-				lp++, fn++;
-			}
-			*p = '/';
-			if (fn != p || (*lp && *lp != '/')) {
-				int save_copy_links = copy_links;
-				int save_xfer_dirs = xfer_dirs;
-				copy_links = copy_unsafe_links;
-				xfer_dirs = 1;
-				while ((slash = strchr(slash+1, '/')) != 0) {
-					*slash = 0;
-					send_file_name(f, flist, fname, 0);
-					*slash = '/';
-				}
-				copy_links = save_copy_links;
-				xfer_dirs = save_xfer_dirs;
-				*p = 0;
-				strlcpy(lastpath, fname, sizeof lastpath);
-				*p = '/';
+		} else {
+			if (*fname == '.' && fname[1] == '/')
+				fname += 2;
+			if ((p = strstr(fname, "/./")) != NULL) {
+				*p = '\0';
+				if (p == fname)
+					dir = "/";
+				else
+					dir = fname;
+				fname = p + 3;
 			}
 		}
 
@@ -1222,6 +1204,37 @@ struct file_list *send_file_list(int f, 
 			}
 		}
 
+		if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
+			/* Send the implied directories at the start of the
+			 * source spec, so we get their permissions right. */
+			char *lp = lastpath, *fn = fname, *slash = fname;
+			*p = '\0';
+			/* Skip any initial directories in our path that we
+			 * have in common with lastpath. */
+			while (*fn && *lp == *fn) {
+				if (*fn == '/')
+					slash = fn;
+				lp++, fn++;
+			}
+			*p = '/';
+			if (fn != p || (*lp && *lp != '/')) {
+				int save_copy_links = copy_links;
+				int save_xfer_dirs = xfer_dirs;
+				copy_links = copy_unsafe_links;
+				xfer_dirs = 1;
+				while ((slash = strchr(slash+1, '/')) != 0) {
+					*slash = 0;
+					send_file_name(f, flist, fname, 0);
+					*slash = '/';
+				}
+				copy_links = save_copy_links;
+				xfer_dirs = save_xfer_dirs;
+				*p = 0;
+				strlcpy(lastpath, fname, sizeof lastpath);
+				*p = '/';
+			}
+		}
+
 		if (one_file_system)
 			filesystem_dev = st.st_dev;
 
Index: options.c
--- options.c	19 May 2005 08:52:17 -0000	1.265
+++ options.c	22 Jul 2005 18:40:43 -0000
@@ -973,6 +973,8 @@ int parse_arguments(int *argc, const cha
 
 	if (relative_paths < 0)
 		relative_paths = files_from? 1 : 0;
+	if (!relative_paths)
+		implied_dirs = 0;
 
 	if (!!delete_before + delete_during + delete_after > 1) {
 		snprintf(err_buf, sizeof err_buf,
@@ -1471,7 +1473,7 @@ void server_options(char **args,int *arg
 		if (!relative_paths)
 			args[ac++] = "--no-relative";
 	}
-	if (!implied_dirs && !am_sender)
+	if (relative_paths && !implied_dirs && !am_sender)
 		args[ac++] = "--no-implied-dirs";
 
 	if (fuzzy_basis && am_sender)


More information about the rsync mailing list