[SCM] The rsync repository. - branch master updated
Rsync CVS commit messages
rsync-cvs at lists.samba.org
Fri Jul 24 03:57:40 UTC 2020
The branch, master has been updated
via 01742c07 Add --mkpath option. Fixes bugzilla bug 4621.
from e00662f2 Add packages to INSTALL.md; put INSTALL.md on ftp site
https://git.samba.org/?p=rsync.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 01742c07e6d7559d69e101a7c2e5380179c08555
Author: Wayne Davison <wayne at opencoder.net>
Date: Thu Jul 23 20:46:51 2020 -0700
Add --mkpath option. Fixes bugzilla bug 4621.
-----------------------------------------------------------------------
Summary of changes:
NEWS.md | 3 +++
main.c | 34 ++++++++++++++++++++++++++--------
options.c | 6 ++++++
rsync.1.md | 21 +++++++++++++++++++++
testsuite/mkpath.test | 43 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 99 insertions(+), 8 deletions(-)
create mode 100755 testsuite/mkpath.test
Changeset truncated at 500 lines:
diff --git a/NEWS.md b/NEWS.md
index a0ec31e0..27e8eef8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -42,6 +42,9 @@
- Added `--crtimes` (`-N`) option for preserving the file's create time (on
an OS that supports that, such as macOS).
+ - Added `--mkpath` option to tell rsync that it should create a non-existing
+ path component of the destination arg.
+
- Added the ability to specify "@netgroup" names to the `hosts allow` and
`hosts deny` daemon parameters. This is a finalized version of the
netgroup-auth patch from the patches repo.
diff --git a/main.c b/main.c
index fcc0e65e..1130e24c 100644
--- a/main.c
+++ b/main.c
@@ -57,6 +57,7 @@ extern int copy_unsafe_links;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
+extern int mkpath_dest_arg;
extern int file_total;
extern int recurse;
extern int xfer_dirs;
@@ -677,7 +678,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
static char *get_local_name(struct file_list *flist, char *dest_path)
{
STRUCT_STAT st;
- int statret;
+ int statret, trailing_slash;
char *cp;
if (DEBUG_GTE(RECV, 1)) {
@@ -710,7 +711,26 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
}
/* See what currently exists at the destination. */
- if ((statret = do_stat(dest_path, &st)) == 0) {
+ statret = do_stat(dest_path, &st);
+ cp = strrchr(dest_path, '/');
+ trailing_slash = cp && !cp[1];
+
+ if (mkpath_dest_arg && statret < 0 && (cp || file_total > 1)) {
+ int ret = make_path(dest_path, file_total > 1 && !trailing_slash ? 0 : MKP_DROP_NAME);
+ if (ret < 0)
+ goto mkdir_error;
+ if (INFO_GTE(NAME, 1)) {
+ if (file_total == 1 || trailing_slash)
+ *cp = '\0';
+ rprintf(FINFO, "created %s %s\n", ret == 1 ? "directory" : "path", dest_path);
+ if (file_total == 1 || trailing_slash)
+ *cp = '/';
+ }
+ if (file_total > 1 || trailing_slash)
+ statret = do_stat(dest_path, &st);
+ }
+
+ if (statret == 0) {
/* If the destination is a dir, enter it and use mode 1. */
if (S_ISDIR(st.st_mode)) {
if (!change_dir(dest_path, CD_NORMAL)) {
@@ -740,15 +760,12 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
exit_cleanup(RERR_FILESELECT);
}
- cp = strrchr(dest_path, '/');
-
/* If we need a destination directory because the transfer is not
* of a single non-directory or the user has requested one via a
* destination path ending in a slash, create one and use mode 1. */
- if (file_total > 1 || (cp && !cp[1])) {
- /* Lop off the final slash (if any). */
- if (cp && !cp[1])
- *cp = '\0';
+ if (file_total > 1 || trailing_slash) {
+ if (trailing_slash)
+ *cp = '\0'; /* Lop off the final slash (if any). */
if (statret == 0) {
rprintf(FERROR, "ERROR: destination path is not a directory\n");
@@ -756,6 +773,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
}
if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
+ mkdir_error:
rsyserr(FERROR, errno, "mkdir %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILEIO);
diff --git a/options.c b/options.c
index 2ef2dbf2..d92a7665 100644
--- a/options.c
+++ b/options.c
@@ -104,6 +104,7 @@ int eol_nulls = 0;
int protect_args = -1;
int human_readable = 1;
int recurse = 0;
+int mkpath_dest_arg = 0;
int allow_inc_recurse = 1;
int xfer_dirs = -1;
int am_daemon = 0;
@@ -1017,6 +1018,8 @@ static struct poptOption long_options[] = {
{"8-bit-output", '8', POPT_ARG_VAL, &allow_8bit_chars, 1, 0, 0 },
{"no-8-bit-output", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
{"no-8", 0, POPT_ARG_VAL, &allow_8bit_chars, 0, 0, 0 },
+ {"mkpath", 0, POPT_ARG_VAL, &mkpath_dest_arg, 1, 0, 0 },
+ {"no-mkpath", 0, POPT_ARG_VAL, &mkpath_dest_arg, 0, 0, 0 },
{"qsort", 0, POPT_ARG_NONE, &use_qsort, 0, 0, 0 },
{"copy-as", 0, POPT_ARG_STRING, ©_as, 0, 0, 0 },
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
@@ -3115,6 +3118,9 @@ void server_options(char **args, int *argc_p)
if (open_noatime && preserve_atimes <= 1)
args[ac++] = "--open-noatime";
+ if (mkpath_dest_arg && am_sender)
+ args[ac++] = "--mkpath";
+
if (ac > MAX_SERVER_ARGS) { /* Not possible... */
rprintf(FERROR, "argc overflow in server_options().\n");
exit_cleanup(RERR_MALLOC);
diff --git a/rsync.1.md b/rsync.1.md
index 4a2b5aeb..1aa8f5c4 100644
--- a/rsync.1.md
+++ b/rsync.1.md
@@ -351,6 +351,7 @@ detailed description below for a complete description.
--append append data onto shorter files
--append-verify --append w/old data in file checksum
--dirs, -d transfer directories without recursing
+--mkpath create the destination's path component
--links, -l copy symlinks as symlinks
--copy-links, -L transform symlink into referent file/dir
--copy-unsafe-links only "unsafe" symlinks are transformed
@@ -977,6 +978,26 @@ your home directory (remove the '=' for that).
`--old-d`) that tells rsync to use a hack of `-r --exclude='/*/*'` to get
an older rsync to list a single directory without recursing.
+0. `--mkpath`
+
+ Create a missing path component of the destination arg. This allows rsync
+ to create multiple levels of missing destination dirs and to create a path
+ in which to put a single renamed file. Keep in mind that you'll need to
+ supply a trailing slash if you want the entire destination path to be
+ treated as a directory when copying a single arg (making rsync behave the
+ same way that it would if the path component of the destination had already
+ existed).
+
+ For example, the following creates a copy of file foo as bar in the sub/dir
+ directory, creating dirs "sub" and "sub/dir" if either do not yet exist:
+
+ > rsync -ai --mkpath foo sub/dir/bar
+
+ If you instead ran the following, it would have created file foo in the
+ sub/dir/bar directory:
+
+ > rsync -ai --mkpath foo sub/dir/bar/
+
0. `--links`, `-l`
When symlinks are encountered, recreate the symlink on the destination.
diff --git a/testsuite/mkpath.test b/testsuite/mkpath.test
new file mode 100755
index 00000000..6efb2105
--- /dev/null
+++ b/testsuite/mkpath.test
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+. "$suitedir/rsync.fns"
+
+makepath "$fromdir"
+makepath "$todir"
+
+cp_p "$srcdir/rsync.h" "$fromdir/text"
+cp_p "$srcdir/configure.ac" "$fromdir/extra"
+
+cd "$tmpdir"
+
+deep_dir=to/foo/bar/baz/down/deep
+
+# Check that we can create several levels of dest dir
+$RSYNC -aiv --mkpath from/text $deep_dir/new
+test -f $deep_dir/new || test_fail "'new' file not found in $deep_dir dir"
+rm -rf to/foo
+
+$RSYNC -aiv --mkpath from/text $deep_dir/
+test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir"
+rm $deep_dir/text
+
+# Make sure we can handle an existing path
+mkdir $deep_dir/new
+$RSYNC -aiv --mkpath from/text $deep_dir/new
+test -f $deep_dir/new/text || test_fail "'text' file not found in $deep_dir/new dir"
+rm -rf to/foo
+
+# Try the tests again with multiple source args
+$RSYNC -aiv --mkpath from/ $deep_dir
+test -f $deep_dir/extra || test_fail "'extra' file not found in $deep_dir dir"
+rm -rf to/foo
+
+$RSYNC -aiv --mkpath from/ $deep_dir/
+test -f $deep_dir/text || test_fail "'text' file not found in $deep_dir dir"
+
+# Make sure that we can handle no path
+$RSYNC -aiv --mkpath from/text to_text
+test -f to_text || test_fail "'to_text' file not found in current dir"
+
+# The script would have aborted on error, so getting here means we've won.
+exit 0
--
The rsync repository.
More information about the rsync-cvs
mailing list