csync_rename.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 extern "C" {
00022 #include "csync_private.h"
00023 #include "csync_propagate.h"
00024 }
00025
00026 #include <map>
00027 #include <string>
00028 #include <vector>
00029 #include <algorithm>
00030
00031 static std::string _parentDir(const std::string &path) {
00032 int len = path.length();
00033 while(len > 0 && path[len-1]!='/') len--;
00034 while(len > 0 && path[len-1]=='/') len--;
00035 return path.substr(0, len);
00036 }
00037
00038 struct csync_rename_s {
00039 static csync_rename_s *get(CSYNC *ctx) {
00040 if (!ctx->rename_info) {
00041 ctx->rename_info = new csync_rename_s;
00042 }
00043 return reinterpret_cast<csync_rename_s *>(ctx->rename_info);
00044 }
00045
00046 std::map<std::string, std::string> folder_renamed_to;
00047
00048 struct renameop {
00049 csync_file_stat_t *st;
00050 bool operator<(const renameop &other) const {
00051 return strlen(st->destpath) < strlen(other.st->destpath);
00052 }
00053 };
00054 std::vector<renameop> todo;
00055 };
00056
00057 static int _csync_rename_record(void *obj, void *data) {
00058 CSYNC *ctx = reinterpret_cast<CSYNC*>(data);
00059 csync_rename_s* d = csync_rename_s::get(ctx);
00060 csync_file_stat_t *st = reinterpret_cast<csync_file_stat_t *>(obj);
00061
00062 if ( st->instruction != CSYNC_INSTRUCTION_RENAME)
00063 return 0;
00064
00065 csync_rename_s::renameop op = { st };
00066 d->todo.push_back(op);
00067 return 0;
00068 }
00069
00070 extern "C" {
00071 void csync_rename_destroy(CSYNC* ctx)
00072 {
00073 delete reinterpret_cast<csync_rename_s *>(ctx->rename_info);
00074 ctx->rename_info = 0;
00075 }
00076
00077 void csync_rename_record(CSYNC* ctx, const char* from, const char* to)
00078 {
00079 csync_rename_s::get(ctx)->folder_renamed_to[from] = to;
00080 }
00081
00082 char* csync_rename_adjust_path(CSYNC* ctx, const char* path)
00083 {
00084 csync_rename_s* d = csync_rename_s::get(ctx);
00085 for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) {
00086 std::map< std::string, std::string >::iterator it = d->folder_renamed_to.find(p);
00087 if (it != d->folder_renamed_to.end()) {
00088 std::string rep = it->second + (path + p.length());
00089 return c_strdup(rep.c_str());
00090 }
00091 }
00092 return c_strdup(path);
00093 }
00094
00095 int csync_propagate_renames(CSYNC* ctx)
00096 {
00097 csync_rename_s* d = csync_rename_s::get(ctx);
00098 d->folder_renamed_to.clear();
00099
00100 if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_rename_record) < 0) {
00101 return -1;
00102 }
00103
00104
00105 std::sort(d->todo.begin(), d->todo.end());
00106 for (std::vector< csync_rename_s::renameop >::iterator it = d->todo.begin();
00107 it != d->todo.end(); ++it) {
00108
00109 int r = csync_propagate_rename_file(ctx, it->st);
00110 if (r < 0)
00111 return -1;
00112 if (r > 0)
00113 continue;
00114 d->folder_renamed_to[it->st->path] = it->st->destpath;
00115 }
00116
00117 return 0;
00118 }
00119
00120
00121 };