From 86d8079739b85164bbd0b48c1385f000aa87bb9c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 21 Oct 2014 10:38:21 +0200 Subject: [PATCH] Reconcile: Make sure not to loose new files added in a directory removed on the server Found while investigating #2296 The problem is that we should not remove a directory locally if it contains modified files. But the modification time of the directory is not necessarily chaning (so the instruction of the directory may still be NONE) We have to move the child_modified test a bit down to be recursive --- csync/src/csync_reconcile.c | 6 ++++++ csync/src/csync_update.c | 10 +++++----- csync/tests/ownCloud/t1.pl | 13 +++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/csync/src/csync_reconcile.c b/csync/src/csync_reconcile.c index 91b8bf8643..6a1cc8d161 100644 --- a/csync/src/csync_reconcile.c +++ b/csync/src/csync_reconcile.c @@ -138,6 +138,12 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) { /* Do not remove a directory that has ignored files */ break; } + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Will Remove %s %d", cur->path, cur->child_modified); + if (cur->child_modified) { + /* re-create directory that has modified contents */ + cur->instruction = CSYNC_INSTRUCTION_NEW; + break; + } cur->instruction = CSYNC_INSTRUCTION_REMOVE; break; case CSYNC_INSTRUCTION_EVAL_RENAME: diff --git a/csync/src/csync_update.c b/csync/src/csync_update.c index 1a12b22504..61b31c3153 100644 --- a/csync/src/csync_update.c +++ b/csync/src/csync_update.c @@ -708,11 +708,6 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, rc = fn(ctx, filename, fs, flag); /* this function may update ctx->current and ctx->read_from_db */ - if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) { - /* If a directory has modified files, put the flag on the parent directory as well */ - previous_fs->child_modified = ctx->current_fs->child_modified; - } - /* Only for the local replica we have to destroy stat(), for the remote one it is a pointer to dirent */ if (ctx->replica == LOCAL_REPLICA) { csync_vio_file_stat_destroy(fs); @@ -747,6 +742,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, } } + if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) { + /* If a directory has modified files, put the flag on the parent directory as well */ + previous_fs->child_modified = ctx->current_fs->child_modified; + } + if (flag == CSYNC_FTW_FLAG_DIR && ctx->current_fs && (ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL || ctx->current_fs->instruction == CSYNC_INSTRUCTION_NEW)) { diff --git a/csync/tests/ownCloud/t1.pl b/csync/tests/ownCloud/t1.pl index 68e55414ea..ee73dce21d 100755 --- a/csync/tests/ownCloud/t1.pl +++ b/csync/tests/ownCloud/t1.pl @@ -169,6 +169,19 @@ assertLocalAndRemoteDir( '', 0); assert( -e localDir().'remoteToLocal1/rtlX' ); assert( -e localDir().'remoteToLocal1/rtlX/rtl11/file.txt' ); +printInfo( "Remove a directory on the server with new files on the client"); +removeRemoteDir('remoteToLocal1/rtlX'); +system("echo hello > " . localDir(). "remoteToLocal1/rtlX/rtl11/hello.txt"); +csync(); +assertLocalAndRemoteDir( '', 0); +# file.txt must be gone because the directory was removed on the server, but hello.txt must be there +# as it is a new file +assert( ! -e localDir().'remoteToLocal1/rtlX/rtl11/file.txt' ); +assert( -e localDir().'remoteToLocal1/rtlX/rtl11/hello.txt' ); + + + + # ================================================================== cleanup();