127
127
return SVN_NO_ERROR;
131
/* Examing the array of svn_wc_external_item2_t's EXT_DESC (parsed
132
from the svn:externals property set on LOCAL_ABSPATH) and determine
133
if the external working copies described by such should be
134
relocated as a side-effect of the relocation of their parent
135
working copy (from OLD_PARENT_REPOS_ROOT_URL to
136
NEW_PARENT_REPOS_ROOT_URL). If so, attempt said relocation. */
138
relocate_externals(const char *local_abspath,
139
apr_array_header_t *ext_desc,
140
const char *old_parent_repos_root_url,
141
const char *new_parent_repos_root_url,
142
svn_client_ctx_t *ctx,
143
apr_pool_t *scratch_pool)
145
apr_pool_t *iterpool;
148
/* Parse an externals definition into an array of external items. */
150
iterpool = svn_pool_create(scratch_pool);
152
for (i = 0; i < ext_desc->nelts; i++)
154
svn_wc_external_item2_t *ext_item =
155
APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *);
156
const char *target_repos_root_url;
157
const char *target_abspath;
160
svn_pool_clear(iterpool);
162
/* If this external isn't pulled in via a relative URL, ignore
163
it. There's no sense in relocating a working copy only to
164
have the next 'svn update' try to point it back to another
166
if (! ((strncmp("../", ext_item->url, 3) == 0) ||
167
(strncmp("^/", ext_item->url, 2) == 0)))
170
/* If the external working copy's not-yet-relocated repos root
171
URL matches the primary working copy's pre-relocated
172
repository root URL, try to relocate that external, too.
173
You might wonder why this check is needed, given that we're
174
already limiting ourselves to externals pulled via URLs
175
relative to their primary working copy. Well, it's because
176
you can use "../" to "crawl up" above one repository's URL
177
space and down into another one. */
178
SVN_ERR(svn_dirent_get_absolute(&target_abspath,
179
svn_dirent_join(local_abspath,
180
ext_item->target_dir,
183
err = svn_client_get_repos_root(&target_repos_root_url, NULL /* uuid */,
184
target_abspath, ctx, iterpool, iterpool);
186
/* Ignore externals that aren't present in the working copy.
187
* This can happen if an external is deleted from disk accidentally,
188
* or if an external is configured on a locally added directory. */
189
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
191
svn_error_clear(err);
197
if (strcmp(target_repos_root_url, old_parent_repos_root_url) == 0)
198
SVN_ERR(svn_client_relocate2(target_abspath,
199
old_parent_repos_root_url,
200
new_parent_repos_root_url,
201
FALSE, ctx, iterpool));
204
svn_pool_destroy(iterpool);
210
131
svn_client_relocate2(const char *wcroot_dir,
211
132
const char *from_prefix,
258
179
/* Relocate externals, too (if any). */
259
SVN_ERR(svn_wc__externals_gather_definitions(&externals_hash, NULL,
260
ctx->wc_ctx, local_abspath,
180
SVN_ERR(svn_wc__externals_defined_below(&externals_hash,
181
ctx->wc_ctx, local_abspath,
263
183
if (! apr_hash_count(externals_hash))
264
184
return SVN_NO_ERROR;
270
190
hi = apr_hash_next(hi))
272
const char *this_abspath = svn__apr_hash_index_key(hi);
273
const char *value = svn__apr_hash_index_val(hi);
274
apr_array_header_t *ext_desc;
192
svn_node_kind_t kind;
193
const char *this_abspath = apr_hash_this_key(hi);
276
195
svn_pool_clear(iterpool);
278
SVN_ERR(svn_wc_parse_externals_description3(&ext_desc, this_abspath,
282
SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url,
283
new_repos_root_url, ctx, iterpool));
197
SVN_ERR(svn_wc__read_external_info(&kind, NULL, NULL, NULL, NULL,
199
local_abspath, this_abspath,
200
FALSE, iterpool, iterpool));
202
if (kind == svn_node_dir)
204
const char *this_repos_root_url;
207
err = svn_client_get_repos_root(&this_repos_root_url, NULL /* uuid */,
208
this_abspath, ctx, iterpool, iterpool);
210
/* Ignore externals that aren't present in the working copy.
211
* This can happen if an external is deleted from disk accidentally,
212
* or if an external is configured on a locally added directory. */
213
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
215
svn_error_clear(err);
220
if (strcmp(old_repos_root_url, this_repos_root_url) == 0)
221
SVN_ERR(svn_client_relocate2(this_abspath, from_prefix, to_prefix,
222
FALSE /* ignore_externals */,
286
227
svn_pool_destroy(iterpool);