You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2011/05/27 14:38:14 UTC
svn commit: r1128282 - in /subversion/trunk/subversion/libsvn_client:
client.h externals.c switch.c update.c
Author: rhuijben
Date: Fri May 27 12:38:13 2011
New Revision: 1128282
URL: http://svn.apache.org/viewvc?rev=1128282&view=rev
Log:
More externals handling shuffling in preparation for using the EXTERNALS store:
Start by updating all existing externals and only after completing all that
remove the externals that should be removed.
* subversion/libsvn_client/client.h
(svn_client__handle_externals): Add argument in preparation for asking the
DB for the old externals.
* subversion/libsvn_client/externals.c
(handle_external_item_removal): New function, containing the remove only
code that was extracted from ...
(handle_external_item_change): ... this function, that now only handles
checkouts, updates and changes of externals.
(handle_externals_change): Receive the global hash of existing externals
instead of creating a separate hash for just this path. Remove handled
items from the hash. Move external removing code to...
(svn_client__handle_externals): ... this function. Gather the old externals
descriptions here.
* subversion/libsvn_client/switch.c
(switch_internal): Update caller.
* subversion/libsvn_client/update.c
(update_internal): Update caller.
Modified:
subversion/trunk/subversion/libsvn_client/client.h
subversion/trunk/subversion/libsvn_client/externals.c
subversion/trunk/subversion/libsvn_client/switch.c
subversion/trunk/subversion/libsvn_client/update.c
Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1128282&r1=1128281&r2=1128282&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Fri May 27 12:38:13 2011
@@ -894,6 +894,7 @@ svn_client__do_commit(const char *base_u
subdir, or call svn_wc_remove_from_revision_control() on an
existing one, or both.
+ TARGET_ABSPATH is the root of the driving operation and
REQUESTED_DEPTH is the requested depth of the driving operation
(e.g., update, switch, etc). If it is neither svn_depth_infinity
nor svn_depth_unknown, then changes to svn:externals will have no
@@ -917,6 +918,7 @@ svn_client__handle_externals(apr_hash_t
apr_hash_t *externals_new,
apr_hash_t *ambient_depths,
const char *repos_root_url,
+ const char *target_abspath,
svn_depth_t requested_depth,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1128282&r1=1128281&r2=1128282&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Fri May 27 12:38:13 2011
@@ -692,24 +692,104 @@ resolve_relative_external_url(const char
}
static svn_error_t *
+handle_external_item_removal(const struct external_change_baton_t *eb,
+ const char *local_abspath,
+ const char *old_url,
+ apr_pool_t *scratch_pool)
+{
+ /* This branch is only used when an external is deleted from the
+ repository and the working copy is updated or committed. */
+
+ svn_error_t *err;
+ svn_boolean_t lock_existed;
+ svn_node_kind_t kind;
+ const char *lock_root_abspath = NULL;
+
+ /* local_abspath should be a wcroot or a file external */
+ SVN_ERR(svn_wc_read_kind(&kind, eb->ctx->wc_ctx, local_abspath, FALSE,
+ scratch_pool));
+
+ if (kind == svn_node_none)
+ return SVN_NO_ERROR; /* It's neither... Nothing to remove */
+
+ SVN_ERR(svn_wc_locked2(&lock_existed, NULL, eb->ctx->wc_ctx,
+ local_abspath, scratch_pool));
+
+ if (! lock_existed)
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath,
+ eb->ctx->wc_ctx, local_abspath,
+ FALSE,
+ scratch_pool,
+ scratch_pool));
+ }
+
+ /* We don't use relegate_dir_external() here, because we know that
+ nothing else in this externals description (at least) is
+ going to need this directory, and therefore it's better to
+ leave stuff where the user expects it. */
+ err = svn_wc_remove_from_revision_control2(
+ eb->ctx->wc_ctx, local_abspath, TRUE, FALSE,
+ eb->ctx->cancel_func, eb->ctx->cancel_baton,
+ scratch_pool);
+
+ if (eb->ctx->notify_func2)
+ {
+ svn_wc_notify_t *notify =
+ svn_wc_create_notify(local_abspath,
+ svn_wc_notify_update_external_removed,
+ scratch_pool);
+
+ notify->kind = svn_node_dir;
+ notify->err = err;
+
+ (eb->ctx->notify_func2)(eb->ctx->notify_baton2,
+ notify, scratch_pool);
+ }
+
+ if (err && err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)
+ {
+ svn_error_clear(err);
+ err = NULL;
+ }
+
+
+ /* Unlock if we acquired the lock */
+ if (lock_root_abspath != NULL)
+ {
+ svn_error_t *err2 = svn_wc__release_write_lock(eb->ctx->wc_ctx,
+ lock_root_abspath,
+ scratch_pool);
+
+ if (err2 && err2->apr_err == SVN_ERR_WC_NOT_LOCKED)
+ {
+ /* We removed the lock by removing the node, how nice! */
+ svn_error_clear(err2);
+ }
+ else
+ err = svn_error_compose_create(err, err2);
+ }
+
+ return svn_error_return(err);
+}
+
+static svn_error_t *
handle_external_item_change(const struct external_change_baton_t *eb,
const char *parent_dir_abspath,
const char *parent_dir_url,
- const char *target_abspath,
+ const char *local_abspath,
const char *old_url,
const svn_wc_external_item2_t *new_item,
apr_pool_t *scratch_pool)
{
svn_ra_session_t *ra_session;
svn_client__ra_session_from_path_results ra_cache = { 0 };
- const char *local_abspath;
const char *new_url;
ra_cache.kind = svn_node_unknown;
- local_abspath = target_abspath;
-
SVN_ERR_ASSERT(eb->repos_root_url && parent_dir_url);
+ SVN_ERR_ASSERT(new_item != NULL);
/* Don't bother to check status, since we'll get that for free by
attempting to retrieve the hash values anyway. */
@@ -718,18 +798,10 @@ handle_external_item_change(const struct
iterpool, since the hash table values outlive the iterpool and
any pointers they have should also outlive the iterpool. */
- if (new_item)
- {
- SVN_ERR(resolve_relative_external_url(&new_url,
- new_item, eb->repos_root_url,
- parent_dir_url,
- scratch_pool, scratch_pool));
- }
- else
- new_url = NULL;
-
- /* We couldn't possibly be here if both values were null, right? */
- SVN_ERR_ASSERT(old_url || new_url);
+ SVN_ERR(resolve_relative_external_url(&new_url,
+ new_item, eb->repos_root_url,
+ parent_dir_url,
+ scratch_pool, scratch_pool));
/* There's one potential ugliness. If a target subdir changed, but
its URL did not, then ideally we'd just rename the subdir, rather
@@ -866,86 +938,9 @@ handle_external_item_change(const struct
break;
}
}
- else if (! new_item)
- {
- /* This branch is only used when an external is deleted from the
- repository and the working copy is updated or committed. */
-
- svn_error_t *err;
- svn_boolean_t lock_existed;
- svn_node_kind_t kind;
- const char *lock_root_abspath = NULL;
-
- /* local_abspath should be a wcroot or a file external */
- SVN_ERR(svn_wc_read_kind(&kind, eb->ctx->wc_ctx, local_abspath, FALSE,
- scratch_pool));
-
- if (kind == svn_node_none)
- return SVN_NO_ERROR; /* It's neither... Nothing to remove */
-
- SVN_ERR(svn_wc_locked2(&lock_existed, NULL, eb->ctx->wc_ctx,
- local_abspath, scratch_pool));
-
- if (! lock_existed)
- {
- SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath,
- eb->ctx->wc_ctx, local_abspath,
- FALSE,
- scratch_pool,
- scratch_pool));
- }
-
- /* We don't use relegate_dir_external() here, because we know that
- nothing else in this externals description (at least) is
- going to need this directory, and therefore it's better to
- leave stuff where the user expects it. */
- err = svn_wc_remove_from_revision_control2(
- eb->ctx->wc_ctx, local_abspath, TRUE, FALSE,
- eb->ctx->cancel_func, eb->ctx->cancel_baton,
- scratch_pool);
-
- if (eb->ctx->notify_func2)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_update_external_removed,
- scratch_pool);
-
- notify->kind = svn_node_dir;
- notify->err = err;
-
- (eb->ctx->notify_func2)(eb->ctx->notify_baton2,
- notify, scratch_pool);
- }
-
- if (err && err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)
- {
- svn_error_clear(err);
- err = NULL;
- }
-
-
- /* Unlock if we acquired the lock */
- if (lock_root_abspath != NULL)
- {
- svn_error_t *err2 = svn_wc__release_write_lock(eb->ctx->wc_ctx,
- lock_root_abspath,
- scratch_pool);
-
- if (err2 && err2->apr_err == SVN_ERR_WC_NOT_LOCKED)
- {
- /* We removed the lock by removing the node, how nice! */
- svn_error_clear(err2);
- }
- else
- err = svn_error_compose_create(err, err2);
- }
-
- SVN_ERR(err);
- }
else
{
- /* This branch handles all other changes. */
+ /* This branch handles a definition change or simple update. */
/* First notify that we're about to handle an external. */
if (eb->ctx->notify_func2)
@@ -1032,18 +1027,16 @@ wrap_external_error(const struct externa
static svn_error_t *
handle_externals_change(const struct external_change_baton_t *eb,
const char *local_abspath,
- const char *old_desc_text,
const char *new_desc_text,
+ apr_hash_t *old_url_hash,
svn_depth_t ambient_depth,
svn_depth_t requested_depth,
apr_pool_t *scratch_pool)
{
- apr_array_header_t *old_desc, *new_desc;
- apr_hash_t *old_url_hash;
+ apr_array_header_t *new_desc;
int i;
apr_pool_t *iterpool;
const char *url;
- apr_hash_index_t *hi;
iterpool = svn_pool_create(scratch_pool);
@@ -1056,13 +1049,6 @@ handle_externals_change(const struct ext
&& requested_depth < svn_depth_infinity))
return SVN_NO_ERROR;
- if (old_desc_text)
- SVN_ERR(svn_wc_parse_externals_description3(&old_desc, local_abspath,
- old_desc_text,
- FALSE, scratch_pool));
- else
- old_desc = NULL;
-
if (new_desc_text)
SVN_ERR(svn_wc_parse_externals_description3(&new_desc, local_abspath,
new_desc_text,
@@ -1070,35 +1056,11 @@ handle_externals_change(const struct ext
else
new_desc = NULL;
- old_url_hash = apr_hash_make(scratch_pool);
-
SVN_ERR(svn_wc__node_get_url(&url, eb->ctx->wc_ctx, local_abspath,
scratch_pool, iterpool));
SVN_ERR_ASSERT(url);
- /* Create a hash of our new item array so that we can efficiently generate
- a diff for them. */
- for (i = 0; old_desc && (i < old_desc->nelts); i++)
- {
- svn_wc_external_item2_t *item;
- const char *target_abspath;
- const char *old_url;
-
- item = APR_ARRAY_IDX(old_desc, i, svn_wc_external_item2_t *);
- svn_pool_clear(iterpool);
-
- target_abspath = svn_dirent_join(local_abspath, item->target_dir,
- scratch_pool);
-
- SVN_ERR(resolve_relative_external_url(&old_url, item,
- eb->repos_root_url,
- url, scratch_pool, iterpool));
-
- apr_hash_set(old_url_hash, target_abspath, APR_HASH_KEY_STRING,
- old_url);
- }
-
for (i = 0; new_desc && (i < new_desc->nelts); i++)
{
const char *old_url;
@@ -1128,28 +1090,6 @@ handle_externals_change(const struct ext
apr_hash_set(old_url_hash, target_abspath, APR_HASH_KEY_STRING, NULL);
}
- /* Remove the remaining externals */
- for (hi = apr_hash_first(scratch_pool, old_url_hash);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *target_abspath;
- const char *old_url;
-
- svn_pool_clear(iterpool);
-
- target_abspath = svn__apr_hash_index_key(hi);
- old_url = svn__apr_hash_index_val(hi);
-
- SVN_ERR(wrap_external_error(
- eb, target_abspath,
- handle_external_item_change(eb, local_abspath, url,
- target_abspath,
- old_url, NULL,
- iterpool),
- iterpool));
- }
-
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -1161,6 +1101,7 @@ svn_client__handle_externals(apr_hash_t
apr_hash_t *externals_new,
apr_hash_t *ambient_depths,
const char *repos_root_url,
+ const char *target_abspath,
svn_depth_t requested_depth,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
@@ -1169,6 +1110,7 @@ svn_client__handle_externals(apr_hash_t
apr_hash_t *combined;
apr_hash_index_t *hi;
apr_pool_t *iterpool;
+ apr_hash_t *old_external_urls;
struct external_change_baton_t eb;
SVN_ERR_ASSERT(repos_root_url);
@@ -1188,6 +1130,57 @@ svn_client__handle_externals(apr_hash_t
iterpool = svn_pool_create(scratch_pool);
+ old_external_urls = apr_hash_make(scratch_pool);
+
+ /* Parse the old externals. This part will be replaced by reading EXTERNALS
+ from the DB. */
+ if (externals_old)
+ {
+ for (hi = apr_hash_first(scratch_pool, externals_old);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *old_desc_text;
+ apr_array_header_t *old_desc;
+ const char *def_abspath;
+ const char *url;
+ int i;
+
+ svn_pool_clear(iterpool);
+
+ def_abspath = svn__apr_hash_index_key(hi);
+ old_desc_text = svn__apr_hash_index_val(hi);
+
+ SVN_ERR(svn_wc_parse_externals_description3(&old_desc, def_abspath,
+ old_desc_text,
+ FALSE, iterpool));
+
+ SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, def_abspath,
+ iterpool, iterpool));
+
+ SVN_ERR_ASSERT(url);
+
+ for (i = 0; old_desc && (i < old_desc->nelts); i++)
+ {
+ svn_wc_external_item2_t *item;
+ const char *target_abspath;
+ const char *old_url;
+
+ item = APR_ARRAY_IDX(old_desc, i, svn_wc_external_item2_t *);
+ target_abspath = svn_dirent_join(def_abspath, item->target_dir,
+ scratch_pool);
+
+ SVN_ERR(resolve_relative_external_url(&old_url, item,
+ repos_root_url,
+ url, scratch_pool,
+ iterpool));
+
+ apr_hash_set(old_external_urls, target_abspath,
+ APR_HASH_KEY_STRING, old_url);
+ }
+ }
+ }
+
for (hi = apr_hash_first(scratch_pool, combined);
hi;
hi = apr_hash_next(hi))
@@ -1221,12 +1214,33 @@ svn_client__handle_externals(apr_hash_t
SVN_ERR(handle_externals_change(
&eb,
svn__apr_hash_index_key(hi),
- externals_old ? apr_hash_get(externals_old, key, klen) : NULL,
externals_new ? apr_hash_get(externals_new, key, klen) : NULL,
+ old_external_urls,
ambient_depth, requested_depth,
iterpool));
}
+ /* Remove the remaining externals */
+ for (hi = apr_hash_first(scratch_pool, old_external_urls);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *target_abspath;
+ const char *old_url;
+
+ svn_pool_clear(iterpool);
+
+ target_abspath = svn__apr_hash_index_key(hi);
+ old_url = svn__apr_hash_index_val(hi);
+
+ SVN_ERR(wrap_external_error(
+ &eb, target_abspath,
+ handle_external_item_removal(&eb, target_abspath,
+ old_url, iterpool),
+ iterpool));
+ }
+
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=1128282&r1=1128281&r2=1128282&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Fri May 27 12:38:13 2011
@@ -293,7 +293,7 @@ switch_internal(svn_revnum_t *result_rev
err = svn_client__handle_externals(efb.externals_old,
efb.externals_new, efb.ambient_depths,
- source_root,
+ source_root, local_abspath,
depth, use_sleep, ctx, pool);
}
Modified: subversion/trunk/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1128282&r1=1128281&r2=1128282&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Fri May 27 12:38:13 2011
@@ -438,7 +438,7 @@ update_internal(svn_revnum_t *result_rev
SVN_ERR(svn_client__handle_externals(efb.externals_old,
efb.externals_new,
efb.ambient_depths,
- repos_root,
+ repos_root, local_abspath,
depth, use_sleep,
ctx, pool));
}