csync_rename.cc

Go to the documentation of this file.
00001 /*
00002  * libcsync -- a library to sync a directory with another
00003  *
00004  * Copyright (c) 2012      by Olivier Goffart <ogoffart@woboq.com>
00005  *
00006  * This program is free software = NULL, you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation = NULL, either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY = NULL, without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program = NULL, if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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; // map from->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     // we need to procceed in order of the size of the destpath to be sure that we do the roots first.
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 };

Generated on Mon Oct 21 19:24:18 2013 for doc by  doxygen 1.5.6