Reorganize the output to "svnserve --help".
[svn.git] / subversion / libsvn_wc / relocate.c
blobb1bb0e3cdd14624a6aa8ea5878ab2104fe69fe01
1 /*
2 * relocate.c: do wc repos relocation
4 * ====================================================================
5 * Copyright (c) 2002-2006 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include "svn_wc.h"
22 #include "svn_error.h"
23 #include "svn_pools.h"
24 #include "svn_path.h"
26 #include "wc.h"
27 #include "entries.h"
28 #include "lock.h"
29 #include "props.h"
31 #include "svn_private_config.h"
34 /* Relocate the main URL and the copyfrom URL for ENTRY by changing FROM to
35 * TO. ADM_ACCESS is the access baton for ENTRY. If DO_SYNC is set then
36 * the new entry will be written to disk immediately, otherwise only the
37 * entries cache will be affected. Calls VALIDATOR passing VALIDATOR_BATON
38 * to validate new URLs.
40 static svn_error_t *
41 relocate_entry(svn_wc_adm_access_t *adm_access,
42 const svn_wc_entry_t *entry,
43 const char *from,
44 const char *to,
45 svn_wc_relocation_validator3_t validator,
46 void *validator_baton,
47 svn_boolean_t do_sync,
48 apr_pool_t *pool)
50 svn_wc_entry_t entry2;
51 apr_uint64_t flags = 0;
52 apr_size_t from_len = strlen(from);
54 if (entry->url && ! strncmp(entry->url, from, from_len))
56 entry2.url = apr_pstrcat(pool, to, entry->url + from_len, NULL);
57 if (entry->uuid)
58 SVN_ERR(validator(validator_baton, entry->uuid, entry2.url, NULL,
59 pool));
60 flags |= SVN_WC__ENTRY_MODIFY_URL;
63 if (entry->repos && (flags & SVN_WC__ENTRY_MODIFY_URL))
65 /* We can't relocate beyond the repository root, but the user is allowed
66 to specify a redundant part of the fs path in from and to, but only
67 if this part is identical in both strings. */
68 apr_size_t repos_len = strlen(entry->repos);
70 if (from_len >= repos_len)
72 apr_size_t to_len = strlen(to);
73 apr_size_t fs_path_len = from_len - repos_len;
74 if (to_len < fs_path_len
75 || strncmp(from + repos_len, to + (to_len - fs_path_len),
76 fs_path_len) != 0)
77 return svn_error_create(SVN_ERR_WC_INVALID_RELOCATION, NULL,
78 _("Relocate can only change the "
79 "repository part of an URL"));
80 /* Since the fs path part is redundant, we don't need to change
81 that part anyway, and the below code depends on this. */
82 from_len = repos_len;
83 to = apr_pstrndup(pool, to, to_len - fs_path_len);
86 if (strncmp(from, entry->repos, from_len) == 0)
88 entry2.repos = apr_pstrcat(pool, to, entry->repos + from_len, NULL);
89 flags |= SVN_WC__ENTRY_MODIFY_REPOS;
90 /* Make sure to is really the repository root. */
91 SVN_ERR(validator(validator_baton, entry->uuid, entry2.url,
92 entry2.repos, pool));
96 if (entry->copyfrom_url && ! strncmp(entry->copyfrom_url, from, from_len))
98 entry2.copyfrom_url = apr_pstrcat(pool, to,
99 entry->copyfrom_url + from_len, NULL);
100 if (entry->uuid)
101 SVN_ERR(validator(validator_baton, entry->uuid,
102 entry2.copyfrom_url, NULL, pool));
103 flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL;
106 if (flags)
107 SVN_ERR(svn_wc__entry_modify(adm_access, entry->name,
108 &entry2, flags, do_sync, pool));
109 return SVN_NO_ERROR;
112 svn_error_t *
113 svn_wc_relocate3(const char *path,
114 svn_wc_adm_access_t *adm_access,
115 const char *from,
116 const char *to,
117 svn_boolean_t recurse,
118 svn_wc_relocation_validator3_t validator,
119 void *validator_baton,
120 apr_pool_t *pool)
122 apr_hash_t *entries;
123 apr_hash_index_t *hi;
124 const svn_wc_entry_t *entry;
125 apr_pool_t *subpool;
127 SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, pool));
128 if (! entry)
129 return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, NULL, NULL);
131 if (entry->kind == svn_node_file)
133 SVN_ERR(relocate_entry(adm_access, entry, from, to,
134 validator, validator_baton, TRUE /* sync */,
135 pool));
136 return SVN_NO_ERROR;
139 /* Relocate THIS_DIR first, in order to pre-validate the relocated URL
140 of all of the other entries. This is technically cheating because
141 it relies on knowledge of the libsvn_client implementation, but it
142 significantly cuts down on the number of expensive validations the
143 validator has to do. ### Should svn_wc.h document the ordering? */
144 SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool));
145 entry = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING);
146 SVN_ERR(relocate_entry(adm_access, entry, from, to,
147 validator, validator_baton, FALSE, pool));
149 subpool = svn_pool_create(pool);
151 for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
153 const void *key;
154 void *val;
156 apr_hash_this(hi, &key, NULL, &val);
157 entry = val;
159 if (strcmp(key, SVN_WC_ENTRY_THIS_DIR) == 0)
160 continue;
162 svn_pool_clear(subpool);
164 if (recurse && (entry->kind == svn_node_dir)
165 && (! entry->deleted || (entry->schedule == svn_wc_schedule_add))
166 && ! entry->absent)
168 svn_wc_adm_access_t *subdir_access;
169 const char *subdir = svn_path_join(path, key, subpool);
170 if (svn_wc__adm_missing(adm_access, subdir))
171 continue;
172 SVN_ERR(svn_wc_adm_retrieve(&subdir_access, adm_access,
173 subdir, subpool));
174 SVN_ERR(svn_wc_relocate3(subdir, subdir_access, from, to,
175 recurse, validator,
176 validator_baton, subpool));
178 SVN_ERR(relocate_entry(adm_access, entry, from, to,
179 validator, validator_baton, FALSE, subpool));
182 svn_pool_destroy(subpool);
184 SVN_ERR(svn_wc__props_delete(path, svn_wc__props_wcprop, adm_access, pool));
185 SVN_ERR(svn_wc__entries_write(entries, adm_access, pool));
186 return SVN_NO_ERROR;
189 /* Compatibility baton and wrapper. */
190 struct compat2_baton {
191 svn_wc_relocation_validator2_t validator;
192 void *baton;
195 /* Compatibility baton and wrapper. */
196 struct compat_baton {
197 svn_wc_relocation_validator_t validator;
198 void *baton;
201 /* This implements svn_wc_relocate_validator3_t. */
202 static svn_error_t *
203 compat2_validator(void *baton,
204 const char *uuid,
205 const char *url,
206 const char *root_url,
207 apr_pool_t *pool)
209 struct compat2_baton *cb = baton;
210 /* The old callback type doesn't set root_url. */
211 return cb->validator(cb->baton, uuid,
212 (root_url ? root_url : url), (root_url ? TRUE : FALSE),
213 pool);
216 /* This implements svn_wc_relocate_validator3_t. */
217 static svn_error_t *
218 compat_validator(void *baton,
219 const char *uuid,
220 const char *url,
221 const char *root_url,
222 apr_pool_t *pool)
224 struct compat_baton *cb = baton;
225 /* The old callback type doesn't allow uuid to be NULL. */
226 if (uuid)
227 return cb->validator(cb->baton, uuid, url);
228 return SVN_NO_ERROR;
231 svn_error_t *
232 svn_wc_relocate2(const char *path,
233 svn_wc_adm_access_t *adm_access,
234 const char *from,
235 const char *to,
236 svn_boolean_t recurse,
237 svn_wc_relocation_validator2_t validator,
238 void *validator_baton,
239 apr_pool_t *pool)
241 struct compat2_baton cb;
243 cb.validator = validator;
244 cb.baton = validator_baton;
246 return svn_wc_relocate3(path, adm_access, from, to, recurse,
247 compat2_validator, &cb, pool);
250 svn_error_t *
251 svn_wc_relocate(const char *path,
252 svn_wc_adm_access_t *adm_access,
253 const char *from,
254 const char *to,
255 svn_boolean_t recurse,
256 svn_wc_relocation_validator_t validator,
257 void *validator_baton,
258 apr_pool_t *pool)
260 struct compat_baton cb;
262 cb.validator = validator;
263 cb.baton = validator_baton;
265 return svn_wc_relocate3(path, adm_access, from, to, recurse,
266 compat_validator, &cb, pool);