diff options
Diffstat (limited to 'subversion/libsvn_client/relocate.c')
-rw-r--r-- | subversion/libsvn_client/relocate.c | 125 |
1 files changed, 33 insertions, 92 deletions
diff --git a/subversion/libsvn_client/relocate.c b/subversion/libsvn_client/relocate.c index ed8d09c..dcd9017 100644 --- a/subversion/libsvn_client/relocate.c +++ b/subversion/libsvn_client/relocate.c @@ -127,85 +127,6 @@ validator_func(void *baton, return SVN_NO_ERROR; } - -/* Examing the array of svn_wc_external_item2_t's EXT_DESC (parsed - from the svn:externals property set on LOCAL_ABSPATH) and determine - if the external working copies described by such should be - relocated as a side-effect of the relocation of their parent - working copy (from OLD_PARENT_REPOS_ROOT_URL to - NEW_PARENT_REPOS_ROOT_URL). If so, attempt said relocation. */ -static svn_error_t * -relocate_externals(const char *local_abspath, - apr_array_header_t *ext_desc, - const char *old_parent_repos_root_url, - const char *new_parent_repos_root_url, - svn_client_ctx_t *ctx, - apr_pool_t *scratch_pool) -{ - apr_pool_t *iterpool; - int i; - - /* Parse an externals definition into an array of external items. */ - - iterpool = svn_pool_create(scratch_pool); - - for (i = 0; i < ext_desc->nelts; i++) - { - svn_wc_external_item2_t *ext_item = - APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *); - const char *target_repos_root_url; - const char *target_abspath; - svn_error_t *err; - - svn_pool_clear(iterpool); - - /* If this external isn't pulled in via a relative URL, ignore - it. There's no sense in relocating a working copy only to - have the next 'svn update' try to point it back to another - location. */ - if (! ((strncmp("../", ext_item->url, 3) == 0) || - (strncmp("^/", ext_item->url, 2) == 0))) - continue; - - /* If the external working copy's not-yet-relocated repos root - URL matches the primary working copy's pre-relocated - repository root URL, try to relocate that external, too. - You might wonder why this check is needed, given that we're - already limiting ourselves to externals pulled via URLs - relative to their primary working copy. Well, it's because - you can use "../" to "crawl up" above one repository's URL - space and down into another one. */ - SVN_ERR(svn_dirent_get_absolute(&target_abspath, - svn_dirent_join(local_abspath, - ext_item->target_dir, - iterpool), - iterpool)); - err = svn_client_get_repos_root(&target_repos_root_url, NULL /* uuid */, - target_abspath, ctx, iterpool, iterpool); - - /* Ignore externals that aren't present in the working copy. - * This can happen if an external is deleted from disk accidentally, - * or if an external is configured on a locally added directory. */ - if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) - { - svn_error_clear(err); - continue; - } - else - SVN_ERR(err); - - if (strcmp(target_repos_root_url, old_parent_repos_root_url) == 0) - SVN_ERR(svn_client_relocate2(target_abspath, - old_parent_repos_root_url, - new_parent_repos_root_url, - FALSE, ctx, iterpool)); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - svn_error_t * svn_client_relocate2(const char *wcroot_dir, const char *from_prefix, @@ -256,10 +177,9 @@ svn_client_relocate2(const char *wcroot_dir, /* Relocate externals, too (if any). */ - SVN_ERR(svn_wc__externals_gather_definitions(&externals_hash, NULL, - ctx->wc_ctx, local_abspath, - svn_depth_infinity, - pool, pool)); + SVN_ERR(svn_wc__externals_defined_below(&externals_hash, + ctx->wc_ctx, local_abspath, + pool, pool)); if (! apr_hash_count(externals_hash)) return SVN_NO_ERROR; @@ -269,18 +189,39 @@ svn_client_relocate2(const char *wcroot_dir, hi != NULL; hi = apr_hash_next(hi)) { - const char *this_abspath = svn__apr_hash_index_key(hi); - const char *value = svn__apr_hash_index_val(hi); - apr_array_header_t *ext_desc; + svn_node_kind_t kind; + const char *this_abspath = apr_hash_this_key(hi); svn_pool_clear(iterpool); - SVN_ERR(svn_wc_parse_externals_description3(&ext_desc, this_abspath, - value, FALSE, - iterpool)); - if (ext_desc->nelts) - SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url, - new_repos_root_url, ctx, iterpool)); + SVN_ERR(svn_wc__read_external_info(&kind, NULL, NULL, NULL, NULL, + ctx->wc_ctx, + local_abspath, this_abspath, + FALSE, iterpool, iterpool)); + + if (kind == svn_node_dir) + { + const char *this_repos_root_url; + svn_error_t *err; + + err = svn_client_get_repos_root(&this_repos_root_url, NULL /* uuid */, + this_abspath, ctx, iterpool, iterpool); + + /* Ignore externals that aren't present in the working copy. + * This can happen if an external is deleted from disk accidentally, + * or if an external is configured on a locally added directory. */ + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + svn_error_clear(err); + continue; + } + SVN_ERR(err); + + if (strcmp(old_repos_root_url, this_repos_root_url) == 0) + SVN_ERR(svn_client_relocate2(this_abspath, from_prefix, to_prefix, + FALSE /* ignore_externals */, + ctx, iterpool)); + } } svn_pool_destroy(iterpool); |