Author: rhuijben
Date: Wed May 11 00:57:33 2011
New Revision: 1101701
URL: http://svn.apache.org/viewvc?rev=1101701&view=rev
Log:
Following up on r1101684, cleanup the externals code in libsvn_client a bit
more by making the export specific code directly walk the hash with
definitions. This allows performing the path calculations directly instead
of deep inside the callbacks.
* subversion/libsvn_client/client.h
(svn_client__fetch_externals): Rename to...
(svn_client__export_externals): ... this.
* subversion/libsvn_client/export.c
(svn_client_export5): Update caller.
* subversion/libsvn_client/externals.c
(handle_external_item_change_baton): Rename to...
(item_change_baton_t): ... this to avoid line wraps and remove two fields.
(handle_external_item_change): Constify arguments and add parent_dir_url
argument.
(handle_external_item_change_wrapper): Follow change on
handle_external_item_change.
(handle_externals_desc_change_baton): Remove two fields.
(handle_externals_desc_change): Remove unused variable. Remove export
specific url calculations.
(svn_client__handle_externals): Update baton initialization.
(svn_client__export_externals): Walk the hash directly and then the items
inside the externals description. Calculate directories and urls.
Modified:
subversion/trunk/subversion/libsvn_client/client.h
subversion/trunk/subversion/libsvn_client/export.c
subversion/trunk/subversion/libsvn_client/externals.c
Modified: subversion/trunk/subversion/libsvn_client/client.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1101701&r1=1101700&r2=1101701&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Wed May 11 00:57:33 2011
@@ -976,10 +976,10 @@ svn_client__handle_externals(apr_hash_t
apr_pool_t *pool);
-/* Fetch externals definitions described by EXTERNALS, a hash of the
- form returned by svn_wc_edited_externals() (which see). If
- IS_EXPORT is set, the external items will be exported instead of
- checked out -- they will have no administrative subdirectories.
+/* Export externals definitions described by EXTERNALS, a hash of the
+ form returned by svn_wc_edited_externals() (which see). The external
+ items will be exported instead of checked out -- they will have no
+ administrative subdirectories.
The checked out or exported tree's top level directory is at
TO_ABSPATH and corresponds to FROM_URL URL in the repository, which
@@ -997,16 +997,15 @@ svn_client__handle_externals(apr_hash_t
Use POOL for temporary allocation. */
svn_error_t *
-svn_client__fetch_externals(apr_hash_t *externals,
- const char *from_url,
- const char *to_abspath,
- const char *repos_root_url,
- svn_depth_t requested_depth,
- svn_boolean_t is_export,
- const char *native_eol,
- svn_boolean_t *timestamp_sleep,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
+svn_client__export_externals(apr_hash_t *externals,
+ const char *from_url,
+ const char *to_abspath,
+ const char *repos_root_url,
+ svn_depth_t requested_depth,
+ const char *native_eol,
+ svn_boolean_t *timestamp_sleep,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool);
/* Perform status operations on each external in TRAVERSAL_INFO. All
Modified: subversion/trunk/subversion/libsvn_client/export.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/export.c?rev=1101701&r1=1101700&r2=1101701&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/export.c (original)
+++ subversion/trunk/subversion/libsvn_client/export.c Wed May 11 00:57:33 2011
@@ -1183,11 +1183,12 @@ svn_client_export5(svn_revnum_t *result_
const char *to_abspath;
SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, pool));
- SVN_ERR(svn_client__fetch_externals(eb->externals,
- from_path_or_url, to_abspath,
- repos_root_url, depth, TRUE,
- native_eol, &use_sleep,
- ctx, pool));
+ SVN_ERR(svn_client__export_externals(eb->externals,
+ from_path_or_url,
+ to_abspath, repos_root_url,
+ depth,
+ native_eol, &use_sleep,
+ ctx, pool));
}
}
else if (kind == svn_node_none)
Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1101701&r1=1101700&r2=1101701&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Wed May 11 00:57:33
2011
@@ -45,14 +45,8 @@
/* Closure for handle_external_item_change. */
-struct handle_external_item_change_baton
+struct item_change_baton_t
{
- /* The directory that has this externals property. */
- const char *parent_dir_abspath;
-
- /* The URL for the directory that has this externals property. */
- const char *parent_dir_url;
-
/* The URL for the repository root. */
const char *repos_root_url;
@@ -706,11 +700,12 @@ resolve_relative_external_url(const char
}
static svn_error_t *
-handle_external_item_change(struct handle_external_item_change_baton *ib,
+handle_external_item_change(const struct item_change_baton_t *ib,
const char *parent_dir_abspath,
+ const char *parent_dir_url,
const char *target_abspath,
- svn_wc_external_item2_t *old_item,
- svn_wc_external_item2_t *new_item,
+ const svn_wc_external_item2_t *old_item,
+ const svn_wc_external_item2_t *new_item,
apr_pool_t *scratch_pool)
{
svn_ra_session_t *ra_session;
@@ -722,7 +717,7 @@ handle_external_item_change(struct handl
local_abspath = target_abspath;
- SVN_ERR_ASSERT(ib->repos_root_url && ib->parent_dir_url);
+ SVN_ERR_ASSERT(ib->repos_root_url && parent_dir_url);
/* Don't bother to check status, since we'll get that for free by
attempting to retrieve the hash values anyway. */
@@ -734,7 +729,7 @@ handle_external_item_change(struct handl
{
SVN_ERR(resolve_relative_external_url(&old_url, old_item,
ib->repos_root_url,
- ib->parent_dir_url,
+ parent_dir_url,
scratch_pool, scratch_pool));
}
else
@@ -744,7 +739,7 @@ handle_external_item_change(struct handl
{
SVN_ERR(resolve_relative_external_url(&new_url,
new_item, ib->repos_root_url,
- ib->parent_dir_url,
+ parent_dir_url,
scratch_pool, scratch_pool));
}
else
@@ -873,7 +868,7 @@ handle_external_item_change(struct handl
new_url,
&new_item->peg_revision,
&new_item->revision,
- ib->parent_dir_abspath,
+ parent_dir_abspath,
ra_session,
ra_cache.ra_session_url,
ra_cache.ra_revnum,
@@ -998,7 +993,7 @@ handle_external_item_change(struct handl
new_url,
&new_item->peg_revision,
&new_item->revision,
- ib->parent_dir_abspath,
+ parent_dir_abspath,
ra_session,
ra_cache.ra_session_url,
ra_cache.ra_revnum,
@@ -1016,16 +1011,18 @@ handle_external_item_change(struct handl
}
static svn_error_t *
-handle_external_item_change_wrapper(struct handle_external_item_change_baton
*ib,
+handle_external_item_change_wrapper(const struct item_change_baton_t *ib,
const char *parent_dir_abspath,
+ const char *parent_dir_url,
const char *target_abspath,
- svn_wc_external_item2_t *old_item,
- svn_wc_external_item2_t *new_item,
+ const svn_wc_external_item2_t *old_item,
+ const svn_wc_external_item2_t *new_item,
apr_pool_t *scratch_pool)
{
svn_error_t *err;
- err = handle_external_item_change(ib, parent_dir_abspath, target_abspath,
+ err = handle_external_item_change(ib, parent_dir_abspath, parent_dir_url,
+ target_abspath,
old_item, new_item, scratch_pool);
if (err && err->apr_err != SVN_ERR_CANCELLED)
@@ -1062,12 +1059,6 @@ struct handle_externals_desc_change_bato
depths available (e.g., svn export). */
apr_hash_t *ambient_depths;
- /* These two map a URL to a path where the URL is either checked out
- to or exported to. The to_path must be a substring of the
- external item parent directory path. */
- const char *from_url;
- const char *to_abspath;
-
/* Passed through to handle_external_item_change_baton. */
svn_client_ctx_t *ctx;
const char *repos_root_url;
@@ -1094,17 +1085,17 @@ handle_externals_desc_change(const void
void *baton)
{
struct handle_externals_desc_change_baton *cb = baton;
- struct handle_external_item_change_baton ib = { 0 };
+ struct item_change_baton_t ib = { 0 };
const char *old_desc_text, *new_desc_text;
apr_array_header_t *old_desc, *new_desc;
apr_hash_t *new_desc_hash;
- apr_size_t len;
int i;
const char *ambient_depth_w;
svn_depth_t ambient_depth;
const char *local_abspath = key;
apr_pool_t *scratch_pool;
apr_pool_t *iterpool;
+ const char *url;
/* The apr hash function doesn't hand us an iterpool, so we manage our own.*/
svn_pool_clear(cb->iterpool);
@@ -1179,36 +1170,11 @@ handle_externals_desc_change(const void
ib.native_eol = cb->native_eol;
ib.delete_only = cb->delete_only;
ib.timestamp_sleep = cb->timestamp_sleep;
- ib.parent_dir_abspath = local_abspath;
- if (!cb->from_url)
- SVN_ERR(svn_wc__node_get_url(&ib.parent_dir_url, cb->ctx->wc_ctx,
- ib.parent_dir_abspath,
- scratch_pool, scratch_pool));
- else
- {
- /* If we're doing an 'svn export' the current dir will not be a
- working copy. We can't get the parent_dir.
+ SVN_ERR(svn_wc__node_get_url(&url, cb->ctx->wc_ctx, local_abspath,
+ scratch_pool, scratch_pool));
- Get the URL of the parent directory by appending a portion of
- parent_dir to from_url. from_url is the URL for to_path and
- to_path is a substring of parent_dir, so append any characters in
- parent_dir past strlen(to_path) to from_url (making sure to move
- past a '/' in parent_dir, otherwise svn_path_url_add_component()
- will error. */
- len = strlen(cb->to_abspath);
- if (ib.parent_dir_abspath[len] == '/')
- ++len;
- ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
- ib.parent_dir_abspath + len,
- scratch_pool);
- }
-
- SVN_ERR_ASSERT(ib.parent_dir_url && ib.repos_root_url);
-
- /* We must use a custom version of svn_hash_diff so that the diff
- entries are processed in the order they were originally specified
- in the svn:externals properties. */
+ SVN_ERR_ASSERT(url && ib.repos_root_url);
for (i = 0; old_desc && (i < old_desc->nelts); i++)
{
@@ -1226,7 +1192,7 @@ handle_externals_desc_change(const void
new_item = apr_hash_get(new_desc_hash, old_item->target_dir,
APR_HASH_KEY_STRING);
- SVN_ERR(handle_external_item_change_wrapper(&ib, local_abspath,
+ SVN_ERR(handle_external_item_change_wrapper(&ib, local_abspath, url,
target_abspath,
old_item, new_item,
iterpool));
@@ -1251,7 +1217,7 @@ handle_externals_desc_change(const void
new_item->target_dir,
iterpool);
- SVN_ERR(handle_external_item_change_wrapper(&ib, local_abspath,
+ SVN_ERR(handle_external_item_change_wrapper(&ib, local_abspath, url,
target_abspath,
NULL, new_item,
iterpool));
@@ -1282,8 +1248,6 @@ svn_client__handle_externals(apr_hash_t
cb.externals_old = externals_old;
cb.requested_depth = requested_depth;
cb.ambient_depths = ambient_depths;
- cb.from_url = NULL;
- cb.to_abspath = NULL;
cb.repos_root_url = repos_root_url;
cb.ctx = ctx;
@@ -1302,40 +1266,77 @@ svn_client__handle_externals(apr_hash_t
svn_error_t *
-svn_client__fetch_externals(apr_hash_t *externals,
- const char *from_url,
- const char *to_abspath,
- const char *repos_root_url,
- svn_depth_t requested_depth,
- svn_boolean_t is_export,
- const char *native_eol,
- svn_boolean_t *timestamp_sleep,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+svn_client__export_externals(apr_hash_t *externals,
+ const char *from_url,
+ const char *to_abspath,
+ const char *repos_root_url,
+ svn_depth_t requested_depth,
+ const char *native_eol,
+ svn_boolean_t *timestamp_sleep,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
{
- struct handle_externals_desc_change_baton cb = { 0 };
- svn_error_t *err;
+ struct item_change_baton_t ib = { 0 };
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *sub_iterpool = svn_pool_create(scratch_pool);
+ apr_hash_index_t *hi;
SVN_ERR_ASSERT(svn_dirent_is_absolute(to_abspath));
- cb.externals_new = externals;
- cb.externals_old = apr_hash_make(pool);
- cb.requested_depth = requested_depth;
- cb.ambient_depths = NULL;
- cb.ctx = ctx;
- cb.from_url = from_url;
- cb.to_abspath = to_abspath;
- cb.repos_root_url = repos_root_url;
- cb.timestamp_sleep = timestamp_sleep;
- cb.native_eol = native_eol;
- cb.is_export = is_export;
- cb.iterpool = svn_pool_create(pool);
+ ib.repos_root_url = repos_root_url;
+ ib.ctx = ctx;
+ ib.native_eol = native_eol;
+ ib.timestamp_sleep = timestamp_sleep;
+ ib.is_export = TRUE;
+ ib.delete_only = FALSE;
- err = svn_hash_diff(cb.externals_old, cb.externals_new,
- handle_externals_desc_change, &cb, pool);
+ for (hi = apr_hash_first(scratch_pool, externals);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *local_abspath = svn__apr_hash_index_key(hi);
+ const char *desc_text = svn__apr_hash_index_val(hi);
+ const char *local_relpath;
+ const char *dir_url;
+ apr_array_header_t *items;
+ int i;
- svn_pool_destroy(cb.iterpool);
- return svn_error_return(err);
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_wc_parse_externals_description3(&items, local_abspath,
+ desc_text, FALSE,
+ scratch_pool));
+
+ if (! items->nelts)
+ continue;
+
+ local_relpath = svn_dirent_skip_ancestor(to_abspath, local_abspath);
+
+ dir_url = svn_path_url_add_component2(from_url, local_relpath,
+ scratch_pool);
+
+ for (i = 0; i < items->nelts; i++)
+ {
+ const char *item_abspath;
+ svn_wc_external_item2_t *item = APR_ARRAY_IDX(items, i,
+ svn_wc_external_item2_t *);
+
+ svn_pool_clear(sub_iterpool);
+
+ item_abspath = svn_dirent_join(local_abspath, item->target_dir,
+ sub_iterpool);
+
+ SVN_ERR(handle_external_item_change_wrapper(&ib, local_abspath,
+ dir_url, item_abspath,
+ NULL, item,
+ sub_iterpool));
+ }
+ }
+
+ svn_pool_destroy(sub_iterpool);
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
}