doc
csync_rename.cc
Go to the documentation of this file.
1 /*
2  * libcsync -- a library to sync a directory with another
3  *
4  * Copyright (c) 2012 by Olivier Goffart <ogoffart@woboq.com>
5  *
6  * This program is free software = NULL, you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation = NULL, either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY = NULL, without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program = NULL, if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 extern "C" {
22 #include "csync_private.h"
23 #include "csync_propagate.h"
24 }
25 
26 #include <map>
27 #include <string>
28 #include <vector>
29 #include <algorithm>
30 
31 static std::string _parentDir(const std::string &path) {
32  int len = path.length();
33  while(len > 0 && path[len-1]!='/') len--;
34  while(len > 0 && path[len-1]=='/') len--;
35  return path.substr(0, len);
36 }
37 
39  static csync_rename_s *get(CSYNC *ctx) {
40  if (!ctx->rename_info) {
41  ctx->rename_info = new csync_rename_s;
42  }
43  return reinterpret_cast<csync_rename_s *>(ctx->rename_info);
44  }
45 
46  std::map<std::string, std::string> folder_renamed_to; // map from->to
47 
48  struct renameop {
50  bool operator<(const renameop &other) const {
51  return strlen(st->destpath) < strlen(other.st->destpath);
52  }
53  };
54  std::vector<renameop> todo;
55 };
56 
57 static int _csync_rename_record(void *obj, void *data) {
58  CSYNC *ctx = reinterpret_cast<CSYNC*>(data);
60  csync_file_stat_t *st = reinterpret_cast<csync_file_stat_t *>(obj);
61 
63  return 0;
64 
65  csync_rename_s::renameop op = { st };
66  d->todo.push_back(op);
67  return 0;
68 }
69 
70 extern "C" {
72 {
73  delete reinterpret_cast<csync_rename_s *>(ctx->rename_info);
74  ctx->rename_info = 0;
75 }
76 
77 void csync_rename_record(CSYNC* ctx, const char* from, const char* to)
78 {
79  csync_rename_s::get(ctx)->folder_renamed_to[from] = to;
80 }
81 
82 char* csync_rename_adjust_path(CSYNC* ctx, const char* path)
83 {
85  for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) {
86  std::map< std::string, std::string >::iterator it = d->folder_renamed_to.find(p);
87  if (it != d->folder_renamed_to.end()) {
88  std::string rep = it->second + (path + p.length());
89  return c_strdup(rep.c_str());
90  }
91  }
92  return c_strdup(path);
93 }
94 
96 {
98  d->folder_renamed_to.clear();
99 
100  if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_rename_record) < 0) {
101  return -1;
102  }
103 
104  // we need to procceed in order of the size of the destpath to be sure that we do the roots first.
105  std::sort(d->todo.begin(), d->todo.end());
106  for (std::vector< csync_rename_s::renameop >::iterator it = d->todo.begin();
107  it != d->todo.end(); ++it) {
108 
109  int r = csync_propagate_rename_file(ctx, it->st);
110  if (r < 0)
111  return -1;
112  if (r > 0)
113  continue;
114  d->folder_renamed_to[it->st->path] = it->st->destpath;
115  }
116 
117  return 0;
118 }
119 
120 
121 };