diff --git a/src/csync_propagate.c b/src/csync_propagate.c index 329f001ee..f06105b3f 100644 --- a/src/csync_propagate.c +++ b/src/csync_propagate.c @@ -1451,23 +1451,8 @@ err: return -1; } -static int _csync_propagation_dir_rename(void *obj, void *data) { - csync_file_stat_t *st = NULL; - CSYNC *ctx = NULL; - int ret = 0; - - st = (csync_file_stat_t *) obj; - ctx = (CSYNC *) data; - - if (st->type != CSYNC_FTW_TYPE_DIR || st->instruction != CSYNC_INSTRUCTION_RENAME) - return 0; - - ret = _csync_rename_file(ctx, st); - if (ret < 0) - return ret; - - csync_rename_record(ctx, st->path, st->destpath); - return ret; +int csync_propagate_rename_file(CSYNC *ctx, csync_file_stat_t *st) { + return _csync_rename_file(ctx, st); } int csync_propagate_files(CSYNC *ctx) { @@ -1498,29 +1483,5 @@ int csync_propagate_files(CSYNC *ctx) { return 0; } -int csync_propagate_rename_dirs(CSYNC* ctx) -{ - c_rbtree_t *tree = NULL; - switch (ctx->current) { - case LOCAL_REPLICA: - tree = ctx->local.tree; - break; - case REMOTE_REPLICA: - tree = ctx->remote.tree; - break; - default: - break; - } - - /* We need to start from scratch the renaming */ - csync_rename_destroy(ctx); - - if (c_rbtree_walk(tree, (void *) ctx, _csync_propagation_dir_rename) < 0) { - return -1; - } - - return 0; -} - /* vim: set ts=8 sw=2 et cindent: */ diff --git a/src/csync_propagate.h b/src/csync_propagate.h index 6b62133c1..3c6b8537a 100644 --- a/src/csync_propagate.h +++ b/src/csync_propagate.h @@ -67,7 +67,7 @@ int csync_propagate_files(CSYNC *ctx); int csync_correct_id(CSYNC *ctx); -int csync_propagate_rename_dirs(CSYNC *ctx); +int csync_propagate_rename_file(CSYNC *ctx, csync_file_stat_t *st); /** * }@ diff --git a/src/csync_reconcile.c b/src/csync_reconcile.c index 7b6511d2d..8916d4e71 100644 --- a/src/csync_reconcile.c +++ b/src/csync_reconcile.c @@ -121,20 +121,10 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) { node = c_rbtree_find(tree, &h); } if(node) { - char *adjusted; other = (csync_file_stat_t*)node->data; - adjusted = csync_rename_adjust_path(ctx, other->path); - CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"about to move: %s -> %s %d", adjusted, cur->path, cur->type != CSYNC_FTW_TYPE_DIR); - if (!c_streq(adjusted, cur->path) || cur->type != CSYNC_FTW_TYPE_DIR) { - other->instruction = CSYNC_INSTRUCTION_RENAME; - other->destpath = c_strdup( cur->path ); - cur->instruction = CSYNC_INSTRUCTION_NONE; - } else { - /* The parent directory is going to be renamed */ - cur->instruction = CSYNC_INSTRUCTION_NONE; - other->instruction = CSYNC_INSTRUCTION_IGNORE; - } - SAFE_FREE(adjusted); + other->instruction = CSYNC_INSTRUCTION_RENAME; + other->destpath = c_strdup( cur->path ); + cur->instruction = CSYNC_INSTRUCTION_NONE; } if( ! other ) { cur->instruction = CSYNC_INSTRUCTION_NEW; diff --git a/src/csync_rename.cc b/src/csync_rename.cc index d0172639e..853072190 100644 --- a/src/csync_rename.cc +++ b/src/csync_rename.cc @@ -20,10 +20,13 @@ extern "C" { #include "csync_private.h" +#include "csync_propagate.h" } #include #include +#include +#include static std::string _parentDir(const std::string &path) { int len = path.length(); @@ -40,9 +43,30 @@ struct csync_rename_s { return reinterpret_cast(ctx->rename_info); } - std::map folder_renamed_to; + std::map folder_renamed_to; // map from->to + + struct renameop { + //std::string from, to; + csync_file_stat_t *st; + bool operator<(const renameop &other) const { + return strlen(st->destpath) < strlen(other.st->destpath); + } + }; + std::vector todo; // map to->from }; +static int _csync_rename_dir_record(void *obj, void *data) { + CSYNC *ctx = reinterpret_cast(data); + csync_rename_s* d = csync_rename_s::get(ctx); + csync_file_stat_t *st = reinterpret_cast(obj); + + if (st->type != CSYNC_FTW_TYPE_DIR || st->instruction != CSYNC_INSTRUCTION_RENAME) + return 0; + + csync_rename_s::renameop op = { st }; + d->todo.push_back(op); + return 0; +} extern "C" { void csync_rename_destroy(CSYNC* ctx) @@ -69,4 +93,30 @@ char* csync_rename_adjust_path(CSYNC* ctx, const char* path) return c_strdup(path); } +int csync_propagate_rename_dirs(CSYNC* ctx) +{ + csync_rename_s* d = csync_rename_s::get(ctx); + d->folder_renamed_to.clear(); + + if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_rename_dir_record) < 0) { + return -1; + } + + // we need to procceed in order of the file + std::sort(d->todo.begin(), d->todo.end()); + for (std::vector< csync_rename_s::renameop >::iterator it = d->todo.begin(); + it != d->todo.end(); ++it) { + + int r = csync_propagate_rename_file(ctx, it->st); + if (r < 0) + return -1; + if (r > 0) + continue; + d->folder_renamed_to[it->st->path] = it->st->destpath; + } + + return 0; +} + + }; diff --git a/src/csync_rename.h b/src/csync_rename.h index f5c408345..ef5c7904b 100644 --- a/src/csync_rename.h +++ b/src/csync_rename.h @@ -26,11 +26,10 @@ extern "C" { #endif -//void csync_rename_adjust_tree(CSYNC *ctx); char *csync_rename_adjust_path(CSYNC *ctx, const char *path); -void csync_rename_record(CSYNC *ctx, const char *from, const char *to); void csync_rename_destroy(CSYNC *ctx); - +void csync_rename_record(CSYNC *ctx, const char *from, const char *to); +int csync_propagate_rename_dirs(CSYNC* ctx); #ifdef __cplusplus }