Skip to content

Commit

Permalink
ignore-non-existing-directory: add variant of ignore-non-existing
Browse files Browse the repository at this point in the history
Add new option --ignore-non-existing-directory, that is a variant of
--ignore-non-existing, but applies ONLY to directories.

This was previously proposed in bug #8366, but I independently had a use
case for it in the Gentoo infrastructure.

Reference: https://bugzilla.samba.org/show_bug.cgi?id=8366
Reference: http://superuser.com/questions/316561/rsync-synchronizing-files-only-without-creating-folders-on-destination
Reference: RsyncProject/rsync-patches#8
Reference: https://lists.samba.org/archive/rsync/2015-November/030455.html
Signed-off-by: Robin H. Johnson <[email protected]>
  • Loading branch information
robbat2 committed Apr 8, 2024
1 parent 7bc3be2 commit 8e159ab
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
21 changes: 15 additions & 6 deletions generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ extern int update_only;
extern int human_readable;
extern int ignore_existing;
extern int ignore_non_existing;
extern int ignore_non_existing_dirs;
extern int want_xattr_optim;
extern int modify_window;
extern int inplace;
Expand Down Expand Up @@ -1353,22 +1354,28 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
return;
}

if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
if ((ignore_non_existing > 0 || ignore_non_existing_dirs > 0) && statret == -1 && stat_errno == ENOENT) {
int actually_ignore = 0;
if (is_dir) {
if (is_dir < 0)
return;
actually_ignore = 1;
skip_dir = file;
file->flags |= FLAG_MISSING_DIR;
}
#ifdef SUPPORT_HARD_LINKS
else if (F_IS_HLINKED(file))
else if (ignore_non_existing > 0 && F_IS_HLINKED(file)) {
actually_ignore = 1;
handle_skipped_hlink(file, itemizing, code, f_out);
}
#endif
if (INFO_GTE(SKIP, 1)) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
is_dir ? "directory" : "file", fname);
if(actually_ignore == 1) {
if (INFO_GTE(SKIP, 1)) {
rprintf(FINFO, "not creating new %s \"%s\"\n",
is_dir ? "directory" : "file", fname);
}
return;
}
return;
}

if (statret == 0 && !(sx.st.st_mode & S_IWUSR)
Expand Down Expand Up @@ -2161,6 +2168,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
min_size = -1;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
ignore_non_existing_dirs = -ignore_non_existing_dirs;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
Expand All @@ -2186,6 +2194,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
min_size = save_min_size;
ignore_existing = -ignore_existing;
ignore_non_existing = -ignore_non_existing;
ignore_non_existing_dirs = -ignore_non_existing_dirs;
update_only = -update_only;
always_checksum = -always_checksum;
size_only = -size_only;
Expand Down
5 changes: 5 additions & 0 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ int fuzzy_basis = 0;
size_t bwlimit_writemax = 0;
int ignore_existing = 0;
int ignore_non_existing = 0;
int ignore_non_existing_dirs = 0;
int need_messages_from_generator = 0;
int max_delete = INT_MIN;
OFF_T max_size = -1;
Expand Down Expand Up @@ -693,6 +694,7 @@ static struct poptOption long_options[] = {
{"no-one-file-system",0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"no-x", 0, POPT_ARG_VAL, &one_file_system, 0, 0, 0 },
{"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
{"ignore-non-existing-directory",0,POPT_ARG_NONE, &ignore_non_existing_dirs, 0, 0, 0 },
{"existing", 0, POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"ignore-non-existing",0,POPT_ARG_NONE, &ignore_non_existing, 0, 0, 0 },
{"ignore-existing", 0, POPT_ARG_NONE, &ignore_existing, 0, 0, 0 },
Expand Down Expand Up @@ -2904,6 +2906,9 @@ void server_options(char **args, int *argc_p)
if (ignore_non_existing)
args[ac++] = "--existing";

if (ignore_non_existing_dirs)
args[ac++] = "--ignore-non-existing-directory";

if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = safe_arg("", tmpdir);
Expand Down
10 changes: 10 additions & 0 deletions rsync.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -1844,6 +1844,16 @@ expand it.
This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
exclude side effects.

0. `--ignore-non-existing-directory`

This tells rsync to skip creating directories that do not
exist yet on the destination. It is a variation of the
[`--ignore-non-existing`](#opt) option that is applied only for
directories.

This option is a [TRANSFER RULE](#TRANSFER_RULES), so don't expect any
exclude side effects.

0. `--ignore-existing`

This tells rsync to skip updating files that already exist on the
Expand Down
47 changes: 47 additions & 0 deletions testsuite/ignore-non-existing-directory.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#! /bin/sh

# This program is distributable under the terms of the GNU GPL (see
# COPYING).

. $suitedir/rsync.fns

makepath "$fromdir/subdir1" "$fromdir/subdir2" "$todir/subdir1"
echo data >"$fromdir/subdir1/file"
echo data >"$todir/subdir1/file2"
echo data >"$fromdir/subdir2/file"

# Test 1: Ensure subdir2 and content under it are not created
$RSYNC -r --ignore-non-existing-directory -vv "$fromdir/" "$todir/" | tee "$scratchdir/out"
if [ ! -d "$todir/subdir1" ]; then
test_fail 'test 1 failed: subdir1 should have been created'
fi
if [ ! -f "$todir/subdir1/file" ]; then
test_fail 'test 1 failed: subdir1/file should have been created'
fi
if [ ! -f "$todir/subdir1/file2" ]; then
test_fail 'test 1 failed: subdir1/file2 should not have been removed'
fi
if [ -d "$todir/subdir2" ]; then
test_fail 'test 1 failed: subdir2 should not have been created'
fi
if [ -f "$todir/subdir2/file" ]; then
test_fail 'test 1 failed: subdir2/file should not have been created'
fi

# Test 2: Also ensure that other delete handling was not impacted
$RSYNC -r --delete --ignore-non-existing-directory -vv "$fromdir/" "$todir/" | tee "$scratchdir/out"
if [ ! -d "$todir/subdir1" ]; then
test_fail 'test 2 failed: subdir1 should have been created'
fi
if [ ! -f "$todir/subdir1/file" ]; then
test_fail 'test 2 failed: subdir1/file should have been created'
fi
if [ -f "$todir/subdir1/file2" ]; then
test_fail 'test 2 failed: subdir1/file2 should have been removed'
fi
if [ -d "$todir/subdir2" ]; then
test_fail 'test 2 failed: subdir2 should not have been created'
fi
if [ -f "$todir/subdir2/file" ]; then
test_fail 'test 2 failed: subdir2/file should not have been created'
fi

0 comments on commit 8e159ab

Please sign in to comment.