Author: philip
Date: Fri Mar 5 13:57:09 2010
New Revision: 919416
URL: http://svn.apache.org/viewvc?rev=919416&view=rev
Log:
Remove access batons from checkout/update/switch.
* subversion/include/private/svn_wc_private.h
(svn_wc__acquire_write_lock, svn_wc__release_write_lock): Tweak doc strings.
* subversion/libsvn_wc/lock.c
(svn_wc__acquire_write_lock): More complete anchor calculation.
(svn_wc__release_write_lock): Don't remove lock if work queue item exists.
* subversion/libsvn_wc/update_editor.c
(struct edit_baton): Remove adm_access, add close_edit_complete.
(cleanup_dir_baton): Remove locks if not close_edit_complete.
(prep_directory): Acquire lock rather than access baton.
(schedule_existing_item_for_re_add): Remove comment, locks are recursive.
(close_directory): Kill cleanup handler.
(merge_file): Adjust file external checks for possible entry cache bug.
(close_edit): Set close_edit_complete.
(make_editor): Remove access batons.
* subversion/libsvn_wc/log.c
(log_do_delete_entry): Remove call to extend access baton.
* subversion/libsvn_client/deprecated.c
(svn_client_switch): Don't pass NULL for access baton.
* subversion/libsvn_client/client.h
(svn_client__switch_internal, svn_client__handle_externals): Remove
adm_access parameter.
* subversion/libsvn_client/switch.c
(switch_internal): New, copied from svn_client__switch_internal. Add
local_abspath and anchor_abspath parameters, remove access baton code.
(svn_client__switch_internal): Gutted. Remove adm_access parameter. Now
just a wrapper to acquire and release locks.
(svn_client_switch2): Don't pass NULL for access baton.
* subversion/libsvn_client/update.c
(update_internal): New, copied from svn_client__update_internal. Add
local_abspath and anchor_abspath parameters, remove access baton code.
(svn_client__update_internal): Gutted. Now just a wrapper to acquire
and release locks.
* subversion/libsvn_client/externals.c
(struct handle_external_item_change_baton): Remove adm_access.
(switch_dir_external): Don't pass NULL for access baton.
(switch_file_external): Remove adm_access parameter. Remove access batons,
acquire lock instead. Avoid SVN_ERR and goto cleanup instead.
(handle_external_item_change): Don't pass access baton.
(struct handle_externals_desc_change_baton): Remove adm_access.
(handle_externals_desc_change): Remove access baton code.
(svn_client__handle_externals): Remove adm_access parameter.
* subversion/tests/cmdline/upgrade_tests.py
(test_list): Remove XFail from update_1_5.
Modified:
subversion/trunk/subversion/include/private/svn_wc_private.h
subversion/trunk/subversion/libsvn_client/client.h
subversion/trunk/subversion/libsvn_client/deprecated.c
subversion/trunk/subversion/libsvn_client/externals.c
subversion/trunk/subversion/libsvn_client/switch.c
subversion/trunk/subversion/libsvn_client/update.c
subversion/trunk/subversion/libsvn_wc/lock.c
subversion/trunk/subversion/libsvn_wc/log.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/tests/cmdline/upgrade_tests.py
Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Fri Mar 5
13:57:09 2010
@@ -520,7 +520,14 @@
* @a anchor_abspath is NULL. If @a anchor_abspath is not NULL then
* recursively acquire write locks for the anchor of @a local_abspath
* and return the anchor path in @a *anchor_abspath. Use @a wc_ctx
- * for working copy access.
+ * for working copy access.
+ *
+ * Returns @c SVN_ERR_WC_LOCKED an existing lock is encountered, but
+ * may have set locks of it's own; it's not clear how the caller is
+ * expected to handle this.
+ *
+ * If @a *anchor_abspath is not NULL it will be set evenwhen
+ * SVN_ERR_WC_LOCKED is returned.
*
* ### @a anchor_abspath should be removed when we move to centralised
* ### metadata as it will be unnecessary.
@@ -535,7 +542,8 @@
/**
* Recursively release write locks for @a local_abspath, using @a wc_ctx
- * for working copy access.
+ * for working copy access. Locks are not removed if work queue items are
+ * present. Only the @c db member of @c wc_ctx is used.
*/
svn_error_t *
svn_wc__release_write_lock(svn_wc_context_t *wc_ctx,
Modified: subversion/trunk/subversion/libsvn_client/client.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Fri Mar 5 13:57:09 2010
@@ -615,9 +615,8 @@
apr_pool_t *pool);
/* Switch a working copy PATH to u...@peg_revision at REVISION, and (if not
- NULL) set RESULT_REV to the switch revision. ADM_ACCESS may be NULL, but
- if is not, it is a write locked working copy administrative access baton
- that has an associated baton for PATH. Only switch as deeply as DEPTH
+ NULL) set RESULT_REV to the switch revision. A write lock will be
+ acquired and released if not held. Only switch as deeply as DEPTH
indicates. If TIMESTAMP_SLEEP is NULL this function will sleep before
returning to ensure timestamp integrity. If TIMESTAMP_SLEEP is not
NULL then the function will not sleep but will set *TIMESTAMP_SLEEP
@@ -637,7 +636,6 @@
const char *url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
- svn_wc_adm_access_t *adm_access,
svn_depth_t depth,
svn_boolean_t depth_is_sticky,
svn_boolean_t *timestamp_sleep,
@@ -951,10 +949,11 @@
/*** Externals (Modules) ***/
/* Handle changes to the svn:externals property described by EXTERNALS_OLD,
- EXTERNALS_NEW, and AMBIENT_DEPTHS. The tree's top level
- directory is at TO_PATH and should have a write lock in ADM_ACCESS
- and corresponds to FROM_URL URL in the repository, which has a root
- URL of REPOS_ROOT_URL.
+
+ EXTERNALS_NEW, and AMBIENT_DEPTHS. The tree's top level directory
+ is at TO_PATH and corresponds to FROM_URL URL in the repository,
+ which has a root URL of REPOS_ROOT_URL. A write lock should be
+ held.
For each changed value of the property, discover the nature of the
change and behave appropriately -- either check a new "external"
@@ -984,8 +983,7 @@
Use POOL for temporary allocation. */
svn_error_t *
-svn_client__handle_externals(svn_wc_adm_access_t *adm_access,
- apr_hash_t *externals_old,
+svn_client__handle_externals(apr_hash_t *externals_old,
apr_hash_t *externals_new,
apr_hash_t *ambient_depths,
const char *from_url,
Modified: subversion/trunk/subversion/libsvn_client/deprecated.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/deprecated.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_client/deprecated.c Fri Mar 5 13:57:09
2010
@@ -1614,7 +1614,7 @@
svn_opt_revision_t peg_revision;
peg_revision.kind = svn_opt_revision_unspecified;
return svn_client__switch_internal(result_rev, path, switch_url,
- &peg_revision, revision, NULL,
+ &peg_revision, revision,
SVN_DEPTH_INFINITY_OR_FILES(recurse),
FALSE, NULL, FALSE, FALSE, FALSE, ctx,
pool);
Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Fri Mar 5 13:57:09
2010
@@ -53,10 +53,6 @@
/* The directory that has this externals property. */
const char *parent_dir;
- /* Access baton for parent_dir. If the external is an export, this
- this must be NULL, otherwise it must be non-NULL. */
- svn_wc_adm_access_t *adm_access;
-
/* The URL for the directory that has this externals property. */
const char *parent_dir_url;
@@ -235,7 +231,7 @@
SVN_ERR(svn_client__switch_internal(NULL, path, url,
peg_revision, revision,
- NULL, svn_depth_infinity,
+ svn_depth_infinity,
TRUE, timestamp_sleep,
FALSE, FALSE, TRUE, ctx,
subpool));
@@ -293,7 +289,6 @@
const char *url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
- svn_wc_adm_access_t *adm_access,
svn_ra_session_t *ra_session,
const char *ra_session_url,
svn_revnum_t ra_revnum,
@@ -303,7 +298,6 @@
apr_pool_t *pool)
{
apr_pool_t *subpool = svn_pool_create(pool);
- svn_wc_adm_access_t *target_adm_access;
const char *anchor;
const char *anchor_abspath;
const char *local_abspath;
@@ -316,9 +310,14 @@
svn_boolean_t unlink_file = FALSE;
svn_boolean_t revert_file = FALSE;
svn_boolean_t remove_from_revision_control = FALSE;
- svn_boolean_t close_adm_access = FALSE;
+ svn_boolean_t locked_here;
svn_error_t *err = NULL;
+ /* See if the user wants last-commit timestamps instead of current ones. */
+ SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
+ SVN_CONFIG_SECTION_MISCELLANY,
+ SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
+
/* There must be a working copy to place the file external into. */
SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ctx->wc_ctx, path,
subpool, subpool));
@@ -329,52 +328,42 @@
baton. If this fails and returns SVN_ERR_WC_NOT_LOCKED, then try
to get a new access baton to support inserting a file external
into a directory external. */
- err = svn_wc_adm_retrieve(&target_adm_access, adm_access, anchor, subpool);
- if (err)
- {
- if (err->apr_err == SVN_ERR_WC_NOT_LOCKED)
- {
- const char *dest_wc_repos_root_url;
- svn_opt_revision_t peg_rev;
+ SVN_ERR(svn_wc_locked2(&locked_here, NULL, ctx->wc_ctx, anchor_abspath,
+ subpool));
+ if (!locked_here)
+ {
+ const char *dest_wc_repos_root_url;
+ svn_opt_revision_t peg_rev;
+
+ /* Check that the repository root URL for the newly opened
+ wc is the same as the file external. */
+ peg_rev.kind = svn_opt_revision_base;
+ SVN_ERR(svn_client__get_repos_root(&dest_wc_repos_root_url,
+ anchor_abspath, &peg_rev,
+ ctx, subpool, subpool));
- svn_error_clear(err);
- close_adm_access = TRUE;
- SVN_ERR(svn_wc__adm_open_in_context(&target_adm_access, ctx->wc_ctx,
- anchor, TRUE, -1,
- ctx->cancel_func,
- ctx->cancel_baton, subpool));
-
- /* Check that the repository root URL for the newly opened
- wc is the same as the file external. */
- peg_rev.kind = svn_opt_revision_base;
- SVN_ERR(svn_client__get_repos_root(&dest_wc_repos_root_url,
- anchor_abspath, &peg_rev,
- ctx, subpool, subpool));
-
- if (0 != strcmp(repos_root_url, dest_wc_repos_root_url))
- return svn_error_createf
- (SVN_ERR_RA_REPOS_ROOT_URL_MISMATCH, NULL,
- _("Cannot insert a file external from '%s' into a working "
- "copy from a different repository rooted at '%s'"),
- url, dest_wc_repos_root_url);
- }
- else
- return svn_error_return(err);
+ if (0 != strcmp(repos_root_url, dest_wc_repos_root_url))
+ return svn_error_createf
+ (SVN_ERR_RA_REPOS_ROOT_URL_MISMATCH, NULL,
+ _("Cannot insert a file external from '%s' into a working "
+ "copy from a different repository rooted at '%s'"),
+ url, dest_wc_repos_root_url);
+
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, anchor_abspath,
+ subpool, subpool));
}
- SVN_ERR(svn_wc__maybe_get_entry(&entry, ctx->wc_ctx, local_abspath,
- svn_node_unknown, FALSE, FALSE, subpool,
- subpool));
+ err = svn_wc__maybe_get_entry(&entry, ctx->wc_ctx, local_abspath,
+ svn_node_unknown, FALSE, FALSE, subpool,
+ subpool);
+ if (err)
+ goto cleanup;
+
/* Only one notification is done for the external, so don't notify
for any following steps. Use the following trick to add the file
then switch it to the external URL. */
- /* See if the user wants last-commit timestamps instead of current ones. */
- SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
- SVN_CONFIG_SECTION_MISCELLANY,
- SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
-
/* If there is a versioned item with this name, ensure it's a file
external before working with it. If there is no entry in the
working copy, then create an empty file and add it to the working
@@ -383,8 +372,9 @@
{
if (! entry->file_external_path)
{
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+ if (!locked_here)
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+ subpool));
return svn_error_createf
(SVN_ERR_CLIENT_FILE_EXTERNAL_OVERWRITE_VERSIONED, 0,
@@ -405,9 +395,12 @@
conflict on the directory. To prevent resolving a conflict
due to another change on the directory, do not allow a file
external to be added when one exists. */
- SVN_ERR(svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
- &tree_conflicted, ctx->wc_ctx,
- anchor_abspath, subpool));
+ err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
+ &tree_conflicted, ctx->wc_ctx,
+ anchor_abspath, subpool);
+ if (err)
+ goto cleanup;
+
if (text_conflicted || prop_conflicted || tree_conflicted)
return svn_error_createf
(SVN_ERR_WC_FOUND_CONFLICT, 0,
@@ -417,11 +410,14 @@
/* Try to create an empty file. If there is a file already
there, then don't touch it. */
- SVN_ERR(svn_io_file_open(&f,
- local_abspath,
- APR_WRITE | APR_CREATE | APR_EXCL,
- APR_OS_DEFAULT,
- subpool));
+ err = svn_io_file_open(&f,
+ local_abspath,
+ APR_WRITE | APR_CREATE | APR_EXCL,
+ APR_OS_DEFAULT,
+ subpool);
+ if (err)
+ goto cleanup;
+
unlink_file = TRUE;
err = svn_io_file_close(f, pool);
if (err)
@@ -446,7 +442,7 @@
}
err = svn_client__switch_internal(NULL, path, url, peg_revision, revision,
- target_adm_access, svn_depth_empty,
+ svn_depth_empty,
FALSE, /* depth_is_sticky */
timestamp_sleep,
TRUE, /* ignore_externals */
@@ -468,8 +464,8 @@
remove_from_revision_control = TRUE;
}
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+ if (!locked_here)
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, subpool));
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
@@ -501,8 +497,9 @@
if (unlink_file)
svn_error_clear(svn_io_remove_file2(path, TRUE, subpool));
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+ if (!locked_here)
+ svn_error_clear(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+ subpool));
svn_pool_destroy(subpool);
return svn_error_return(err);
@@ -877,7 +874,6 @@
new_item->url,
&new_item->peg_revision,
&new_item->revision,
- ib->adm_access,
ra_session,
ra_cache.ra_session_url,
ra_cache.ra_revnum,
@@ -994,7 +990,6 @@
new_item->url,
&new_item->peg_revision,
&new_item->revision,
- ib->adm_access,
ra_session,
ra_cache.ra_session_url,
ra_cache.ra_revnum,
@@ -1067,7 +1062,6 @@
const char *to_path;
/* Passed through to handle_external_item_change_baton. */
- svn_wc_adm_access_t *adm_access;
svn_client_ctx_t *ctx;
const char *repos_root_url;
svn_boolean_t *timestamp_sleep;
@@ -1099,11 +1093,6 @@
const char *abs_parent_dir;
svn_error_t *err;
- if (cb->is_export)
- SVN_ERR_ASSERT(!cb->adm_access);
- else
- SVN_ERR_ASSERT(cb->adm_access);
-
if (cb->ambient_depths)
{
ambient_depth_w = apr_hash_get(cb->ambient_depths, key, klen);
@@ -1168,7 +1157,6 @@
ib.new_desc = new_desc_hash;
ib.parent_dir = (const char *) key;
ib.repos_root_url = cb->repos_root_url;
- ib.adm_access = cb->adm_access;
ib.ctx = cb->ctx;
ib.is_export = cb->is_export;
ib.timestamp_sleep = cb->timestamp_sleep;
@@ -1246,8 +1234,7 @@
svn_error_t *
-svn_client__handle_externals(svn_wc_adm_access_t *adm_access,
- apr_hash_t *externals_old,
+svn_client__handle_externals(apr_hash_t *externals_old,
apr_hash_t *externals_new,
apr_hash_t *ambient_depths,
const char *from_url,
@@ -1272,7 +1259,6 @@
cb.from_url = from_url;
cb.to_path = to_path;
cb.repos_root_url = repos_root_url;
- cb.adm_access = adm_access;
cb.ctx = ctx;
cb.timestamp_sleep = timestamp_sleep;
cb.is_export = FALSE;
@@ -1300,7 +1286,6 @@
cb.externals_old = apr_hash_make(pool);
cb.requested_depth = requested_depth;
cb.ambient_depths = NULL;
- cb.adm_access = NULL;
cb.ctx = ctx;
cb.from_url = from_url;
cb.to_path = to_path;
Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Fri Mar 5 13:57:09 2010
@@ -56,20 +56,21 @@
svn_error_t *
-svn_client__switch_internal(svn_revnum_t *result_rev,
- const char *path,
- const char *switch_url,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_wc_adm_access_t *adm_access,
- svn_depth_t depth,
- svn_boolean_t depth_is_sticky,
- svn_boolean_t *timestamp_sleep,
- svn_boolean_t ignore_externals,
- svn_boolean_t allow_unver_obstructions,
- svn_boolean_t innerswitch,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+switch_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *local_abspath,
+ const char *anchor_abspath,
+ const char *switch_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t innerswitch,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
const svn_ra_reporter3_t *reporter;
void *report_baton;
@@ -77,8 +78,6 @@
svn_ra_session_t *ra_session;
svn_revnum_t revnum;
svn_error_t *err = SVN_NO_ERROR;
- svn_wc_adm_access_t *dir_access;
- const svn_boolean_t close_adm_access = ! adm_access;
const char *diff3_cmd;
svn_boolean_t use_commit_times;
svn_boolean_t sleep_here = FALSE;
@@ -86,18 +85,14 @@
const svn_delta_editor_t *switch_editor;
void *switch_edit_baton;
const char *preserved_exts_str;
- const char *anchor_abspath;
apr_array_header_t *preserved_exts;
svn_boolean_t server_supports_depth;
- const char *local_abspath;
svn_client__external_func_baton_t efb;
svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING)
: NULL;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
/* An unknown depth can't be sticky. */
if (depth == svn_depth_unknown)
depth_is_sticky = FALSE;
@@ -125,49 +120,16 @@
: NULL;
/* Sanity check. Without these, the switch is meaningless. */
- SVN_ERR_ASSERT(path);
SVN_ERR_ASSERT(switch_url && (switch_url[0] != '\0'));
- /* ### Need to lock the whole target tree to invalidate wcprops. Does
- non-recursive switch really need to invalidate the whole tree? */
- if (innerswitch)
- {
- SVN_ERR(svn_wc__adm_open_in_context(&adm_access, ctx->wc_ctx,
- path, TRUE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
- dir_access = adm_access;
- target = "";
- anchor = svn_wc_adm_access_path(adm_access);
- }
- else if (adm_access)
- {
- svn_wc_adm_access_t *a = adm_access;
- const char *dir_access_path;
-
- /* This is a little hacky, but open two new read-only access
- baton's to get the anchor and target access batons that would
- be used if a locked access baton was not available. */
- SVN_ERR(svn_wc_adm_open_anchor(&adm_access, &dir_access, &target, path,
- FALSE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
- anchor = svn_wc_adm_access_path(adm_access);
- dir_access_path = svn_wc_adm_access_path(dir_access);
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
- SVN_ERR(svn_wc_adm_retrieve(&adm_access, a, anchor, pool));
- SVN_ERR(svn_wc_adm_retrieve(&dir_access, a, dir_access_path, pool));
- }
+ if (strcmp(local_abspath, anchor_abspath))
+ svn_dirent_split(path, &anchor, &target, pool);
else
{
- SVN_ERR(svn_wc__adm_open_anchor_in_context(&adm_access, &dir_access,
- &target, ctx->wc_ctx, path,
- TRUE, -1, ctx->cancel_func,
- ctx->cancel_baton, pool));
-
- anchor = svn_wc_adm_access_path(adm_access);
+ target = "";
+ anchor = path;
}
- SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, anchor_abspath, pool, pool));
if (! url)
return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
@@ -188,10 +150,6 @@
pool));
/* Target excluded, we are done now */
-
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
return SVN_NO_ERROR;
}
@@ -280,7 +238,7 @@
handling external items (and any errors therefrom) doesn't delay
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
- err = svn_client__handle_externals(adm_access, efb.externals_old,
+ err = svn_client__handle_externals(efb.externals_old,
efb.externals_new, efb.ambient_depths,
switch_url, path, source_root, depth,
use_sleep, ctx, pool);
@@ -294,9 +252,6 @@
if (err)
return svn_error_return(err);
- if (close_adm_access)
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
-
/* Let everyone know we're finished here. */
if (ctx->notify_func2)
{
@@ -318,6 +273,57 @@
}
svn_error_t *
+svn_client__switch_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *switch_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t innerswitch,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *local_abspath, *anchor_abspath;
+ svn_boolean_t acquired_lock;
+ svn_error_t *err, *err1, *err2;
+
+ SVN_ERR_ASSERT(path);
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ /* Rely on svn_wc__acquire_write_lock setting ANCHOR_ABSPATH even
+ when it returns SVN_ERR_WC_LOCKED */
+ err = svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
+ local_abspath, pool, pool);
+ if (err && err->apr_err != SVN_ERR_WC_LOCKED)
+ return svn_error_return(err);
+ else if (err)
+ {
+ svn_error_clear(err);
+ acquired_lock = FALSE;
+ }
+ else
+ acquired_lock = TRUE;
+
+ err1 = switch_internal(result_rev, path, local_abspath, anchor_abspath,
+ switch_url, peg_revision, revision,
+ depth, depth_is_sticky,
+ timestamp_sleep, ignore_externals,
+ allow_unver_obstructions, innerswitch, ctx, pool);
+
+ if (acquired_lock)
+ err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
+ else
+ err2 = SVN_NO_ERROR;
+
+ return svn_error_compose_create(err1, err2);
+}
+
+svn_error_t *
svn_client_switch2(svn_revnum_t *result_rev,
const char *path,
const char *switch_url,
@@ -331,7 +337,7 @@
apr_pool_t *pool)
{
return svn_client__switch_internal(result_rev, path, switch_url,
- peg_revision, revision, NULL, depth,
+ peg_revision, revision, depth,
depth_is_sticky, NULL, ignore_externals,
allow_unver_obstructions, FALSE, ctx,
pool);
Modified: subversion/trunk/subversion/libsvn_client/update.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Fri Mar 5 13:57:09 2010
@@ -79,19 +79,21 @@
}
-svn_error_t *
-svn_client__update_internal(svn_revnum_t *result_rev,
- const char *path,
- const svn_opt_revision_t *revision,
- svn_depth_t depth,
- svn_boolean_t depth_is_sticky,
- svn_boolean_t ignore_externals,
- svn_boolean_t allow_unver_obstructions,
- svn_boolean_t *timestamp_sleep,
- svn_boolean_t send_copyfrom_args,
- svn_boolean_t innerupdate,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+static svn_error_t *
+update_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const char *local_abspath,
+ const char *anchor_abspath,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t innerupdate,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
const svn_delta_editor_t *update_editor;
void *update_edit_baton;
@@ -102,18 +104,14 @@
const char *repos_root;
svn_error_t *err;
svn_revnum_t revnum;
- svn_wc_adm_access_t *adm_access;
svn_boolean_t use_commit_times;
svn_boolean_t sleep_here = FALSE;
svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
const char *diff3_cmd;
svn_ra_session_t *ra_session;
- svn_wc_adm_access_t *dir_access;
const char *preserved_exts_str;
apr_array_header_t *preserved_exts;
struct ff_baton *ffb;
- const char *local_abspath;
- const char *anchor_abspath;
svn_client__external_func_baton_t efb;
svn_boolean_t server_supports_depth;
svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
@@ -124,44 +122,18 @@
if (depth == svn_depth_unknown)
depth_is_sticky = FALSE;
- /* Sanity check. Without this, the update is meaningless. */
- SVN_ERR_ASSERT(path);
-
- if (svn_path_is_url(path))
- return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
- _("Path '%s' is not a directory"),
- path);
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-
- if (!innerupdate)
+ if (strcmp(local_abspath, anchor_abspath))
{
- /* Use PATH to get the update's anchor and targets and get a write lock.
- */
- SVN_ERR(svn_wc__adm_open_anchor_in_context(&adm_access, &dir_access,
- &target, ctx->wc_ctx, path,
- TRUE,
- -1, /* recursive lock */
- ctx->cancel_func,
- ctx->cancel_baton, pool));
+ target = svn_dirent_basename(local_abspath, pool);
+ anchor = svn_dirent_basename(path, pool);
}
else
{
- /* Assume the exact root is specified (required for externals to work,
- as these would otherwise try to open the parent working copy again) */
- SVN_ERR(svn_wc__adm_open_in_context(&adm_access, ctx->wc_ctx, path, TRUE,
- -1, /* recursive lock */
- ctx->cancel_func, ctx->cancel_baton,
- pool));
- dir_access = adm_access;
target = "";
+ anchor = path;
}
- anchor = svn_wc_adm_access_path(adm_access);
- SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
-
/* Get full URL from the ANCHOR. */
-
SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
pool, pool));
if (! anchor_url)
@@ -183,7 +155,8 @@
pool));
/* Target excluded, we are done now */
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+ pool));
return SVN_NO_ERROR;
}
@@ -297,17 +270,18 @@
the primary operation. */
if (SVN_DEPTH_IS_RECURSIVE(depth) && (! ignore_externals))
{
- SVN_ERR(svn_client__handle_externals(adm_access, efb.externals_old,
+ SVN_ERR(svn_client__handle_externals(efb.externals_old,
efb.externals_new,
efb.ambient_depths,
- anchor_url, anchor, repos_root,
+ anchor_url, anchor,
+ repos_root,
depth, use_sleep, ctx, pool));
}
if (sleep_here)
svn_io_sleep_for_timestamps(path, pool);
- SVN_ERR(svn_wc_adm_close2(adm_access, pool));
+ SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
/* Let everyone know we're finished here. */
if (ctx->notify_func2)
@@ -330,6 +304,56 @@
}
svn_error_t *
+svn_client__update_internal(svn_revnum_t *result_rev,
+ const char *path,
+ const svn_opt_revision_t *revision,
+ svn_depth_t depth,
+ svn_boolean_t depth_is_sticky,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t *timestamp_sleep,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t innerupdate,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *local_abspath, *anchor_abspath;
+ svn_error_t *err1, *err2;
+
+ SVN_ERR_ASSERT(path);
+
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("Path '%s' is not a directory"),
+ path);
+
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+ if (!innerupdate)
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
+ local_abspath, pool, pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx,
+ local_abspath, pool, pool));
+ anchor_abspath = local_abspath;
+ }
+
+ err1 = update_internal(result_rev, path, local_abspath, anchor_abspath,
+ revision, depth, depth_is_sticky,
+ ignore_externals, allow_unver_obstructions,
+ timestamp_sleep, send_copyfrom_args,
+ innerupdate, ctx, pool);
+
+ err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
+
+ return svn_error_compose_create(err1, err2);
+}
+
+
+svn_error_t *
svn_client_update3(apr_array_header_t **result_revs,
const apr_array_header_t *paths,
const svn_opt_revision_t *revision,
Modified: subversion/trunk/subversion/libsvn_wc/lock.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/lock.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/lock.c (original)
+++ subversion/trunk/subversion/libsvn_wc/lock.c Fri Mar 5 13:57:09 2010
@@ -1733,41 +1733,51 @@
svn_wc__db_kind_t kind;
apr_pool_t *iterpool;
const apr_array_header_t *children;
- svn_boolean_t parent_is_anchor = FALSE;
int format, i;
svn_error_t *err;
+ SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
+ scratch_pool));
+
if (anchor_abspath)
{
- const char *parent_abspath, *base;
+ const char *parent_abspath;
+ svn_wc__db_kind_t parent_kind;
- svn_dirent_split(local_abspath, &parent_abspath, &base, scratch_pool);
- err = svn_wc__db_read_children(&children, wc_ctx->db, parent_abspath,
- scratch_pool, scratch_pool);
- if (err)
- svn_error_clear(err);
+ parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ err = svn_wc__db_read_kind(&parent_kind, wc_ctx->db, parent_abspath,
TRUE,
+ scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
+ {
+ svn_error_clear(err);
+ parent_kind = svn_wc__db_kind_unknown;
+ }
else
+ SVN_ERR(err);
+
+ if (kind == svn_wc__db_kind_dir && parent_kind == svn_wc__db_kind_dir)
{
- for (i = 0; i < children->nelts; ++i)
- if (! strcmp(APR_ARRAY_IDX(children, i, const char *), base))
- break;
- if (i < children->nelts)
- parent_is_anchor = TRUE;
+ svn_boolean_t disjoint;
+ SVN_ERR(child_is_disjoint(&disjoint, wc_ctx->db, local_abspath,
+ scratch_pool));
+ if (!disjoint)
+ local_abspath = parent_abspath;
}
- local_abspath = parent_is_anchor ? parent_abspath : local_abspath;
+ else if (parent_kind == svn_wc__db_kind_dir)
+ local_abspath = parent_abspath;
+ else if (kind != svn_wc__db_kind_dir)
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("'%s' is not a working copy"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
*anchor_abspath = apr_pstrdup(result_pool, local_abspath);
}
+ else if (kind != svn_wc__db_kind_dir)
+ local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- if (! parent_is_anchor)
- {
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
- scratch_pool));
- if (kind != svn_wc__db_kind_dir)
- local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
- SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
- }
+ SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
+ scratch_pool, scratch_pool));
/* The current lock paradigm is that each directory holds a lock for itself,
and there are no inherited locks. In the eventual wc-ng paradigm, a
@@ -1815,6 +1825,8 @@
svn_wc__db_kind_t kind;
apr_pool_t *iterpool;
const apr_array_header_t *children;
+ apr_uint64_t id;
+ svn_skel_t *work_item;
int i;
SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
@@ -1822,6 +1834,11 @@
if (kind != svn_wc__db_kind_dir)
local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+ SVN_ERR(svn_wc__db_wq_fetch(&id, &work_item, wc_ctx->db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (work_item)
+ return SVN_NO_ERROR;
+
/* We need to recursively remove locks (see comment in
svn_wc__acquire_write_lock(). */
Modified: subversion/trunk/subversion/libsvn_wc/log.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/log.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/log.c (original)
+++ subversion/trunk/subversion/libsvn_wc/log.c Fri Mar 5 13:57:09 2010
@@ -578,14 +578,6 @@
return SVN_NO_ERROR;
}
}
- else
- {
- /* Deleting full_path requires that any children it has are
- also locked (issue #3039). */
- SVN_ERR(svn_wc__adm_extend_lock_to_tree(loggy->db,
- local_abspath,
- loggy->pool));
- }
}
err = svn_wc__internal_remove_from_revision_control(loggy->db,
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Mar 5 13:57:09
2010
@@ -168,9 +168,6 @@
svn_wc__db_t *db;
svn_wc_context_t *wc_ctx;
- /* ADM_ACCESS is an access baton that includes the ANCHOR directory */
- svn_wc_adm_access_t *adm_access;
-
/* Array of file extension patterns to preserve as extensions in
generated conflict files. */
apr_array_header_t *ext_patterns;
@@ -201,6 +198,11 @@
/* Allow unversioned obstructions when adding a path. */
svn_boolean_t allow_unver_obstructions;
+ /* The close_edit method destroys the edit pool and so runs the
+ cleanup_dir_baton cleanup handlers. This flag is set to indicate
+ that the edit was completed successfully. */
+ svn_boolean_t close_edit_complete;
+
/* If this is a 'switch' operation, the target URL (### corresponding to
the ANCHOR plus TARGET path?), else NULL. */
const char *switch_url;
@@ -494,6 +496,21 @@
if (!err)
err = svn_wc__run_log2(eb->db, db->local_abspath, pool);
+ /* If the editor aborts for some sort of error, the command line
+ client relies on pool cleanup to run outstanding work queues and
+ remove locks. This avoids leaving the working copy locked in
+ many cases, but plays havoc with operations that do multiple
+ updates (think externals). So we flag updates that complete
+ successfully and avoid removing locks. In 1.6 locks were
+ associated with a pool distinct from the edit pool and so were
+ removed separately. */
+ if (!err && !eb->close_edit_complete)
+ {
+ svn_wc_context_t fake_ctx;
+ fake_ctx.db = eb->db;
+ err = svn_wc__release_write_lock(&fake_ctx, db->local_abspath, pool);
+ }
+
if (err)
{
apr_status_t apr_err = err->apr_err;
@@ -1141,6 +1158,7 @@
{
const char *repos;
const char *dir_abspath;
+ svn_boolean_t locked_here;
dir_abspath = db->local_abspath;
@@ -1162,25 +1180,13 @@
db->edit_baton->uuid, ancestor_revision,
db->ambient_depth, pool));
- if (NULL == svn_wc__adm_retrieve_internal2(db->edit_baton->db, dir_abspath,
- pool))
- {
- svn_wc_adm_access_t *adm_access;
- apr_pool_t *adm_access_pool;
- const char *rel_path;
-
- SVN_ERR(svn_wc__temp_get_relpath(&rel_path, db->edit_baton->db,
+ SVN_ERR(svn_wc_locked2(&locked_here, NULL, db->edit_baton->wc_ctx,
+ dir_abspath, pool));
+ if (!locked_here)
+ /* Recursive lock release on parent will release this lock. */
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, db->edit_baton->wc_ctx,
dir_abspath, pool, pool));
- adm_access_pool = svn_wc_adm_access_pool(db->edit_baton->adm_access);
-
- SVN_ERR(svn_wc__adm_open_in_context(&adm_access, db->edit_baton->wc_ctx,
- rel_path, TRUE, -1,
- db->edit_baton->cancel_func,
- db->edit_baton->cancel_baton,
- adm_access_pool));
- }
-
return SVN_NO_ERROR;
}
@@ -2192,7 +2198,6 @@
/* ### Need to change the "base" into a "revert-base" ? */
/* Determine which adm dir holds this node's entry */
- /* ### But this will fail if eb->adm_access holds only a shallow lock. */
SVN_ERR(svn_wc__entry_modify2(eb->db,
local_abspath,
entry->kind,
@@ -3374,6 +3379,7 @@
while (bdi && !bdi->ref_count)
{
apr_pool_t *destroy_pool = bdi->pool;
+ apr_pool_cleanup_kill(destroy_pool, db, cleanup_dir_baton);
bdi = bdi->parent;
svn_pool_destroy(destroy_pool);
}
@@ -4773,11 +4779,18 @@
Special case: The working file is referring to a file external? If so
then we must mark it as unmodified in order to avoid bogus
conflicts, since this file was added as a place holder to
- merge externals item from the repository. */
+ merge externals item from the repository.
+
+ ### Possible entry caching bug? Before the removal of the access
+ batons a newly added file external caused svn_wc__get_entry to
+ return an entry with entry->schedule=svn_wc_schedule_add (the
+ entry was retrieved from the cache). Now the svn_wc__get_entry
+ call reads the entries from the database the returned entry is
+ svn_wc_schedule_replace. 2 lines marked ### EBUG below. */
if (fb->copied_working_text)
is_locally_modified = TRUE;
else if (entry && entry->file_external_path
- && entry->schedule == svn_wc_schedule_add)
+ && entry->schedule == svn_wc_schedule_replace) /* ###EBUG */
is_locally_modified = FALSE;
else if (! fb->existed)
SVN_ERR(svn_wc__internal_text_modified_p(&is_locally_modified, eb->db,
@@ -4794,7 +4807,8 @@
else
is_locally_modified = FALSE;
- if (entry && entry->schedule == svn_wc_schedule_replace)
+ if (entry && entry->schedule == svn_wc_schedule_replace
+ && ! entry->file_external_path) /* ### EBUG */
is_replaced = TRUE;
if (fb->add_existed)
@@ -5354,6 +5368,7 @@
should also make eb->pool not be a subpool (see make_editor),
and change callers of svn_client_{checkout,update,switch} to do
better pool management. ### */
+ eb->close_edit_complete = TRUE;
svn_pool_destroy(eb->pool);
return SVN_NO_ERROR;
@@ -5397,12 +5412,10 @@
svn_delta_editor_t *tree_editor = svn_delta_default_editor(edit_pool);
const svn_delta_editor_t *inner_editor;
const char *repos_root, *repos_uuid;
- svn_wc_adm_access_t *adm_access;
const char *anchor;
- adm_access = svn_wc__adm_retrieve_internal2(wc_ctx->db, anchor_abspath,
- scratch_pool);
- anchor = svn_wc_adm_access_path(adm_access);
+ SVN_ERR(svn_wc__temp_get_relpath(&anchor, wc_ctx->db, anchor_abspath,
+ result_pool, scratch_pool));
/* An unknown depth can't be sticky. */
if (depth == svn_depth_unknown)
@@ -5433,7 +5446,6 @@
eb->uuid = repos_uuid;
eb->db = wc_ctx->db;
eb->wc_ctx = wc_ctx;
- eb->adm_access = adm_access;
eb->target_basename = target_basename;
eb->anchor_abspath = anchor_abspath;
@@ -5457,6 +5469,7 @@
eb->fetch_func = fetch_func;
eb->fetch_baton = fetch_baton;
eb->allow_unver_obstructions = allow_unver_obstructions;
+ eb->close_edit_complete = FALSE;
eb->skipped_trees = apr_hash_make(edit_pool);
eb->ext_patterns = preserved_exts;
Modified: subversion/trunk/subversion/tests/cmdline/upgrade_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests.py?rev=919416&r1=919415&r2=919416&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/upgrade_tests.py Fri Mar 5
13:57:09 2010
@@ -329,7 +329,7 @@
test_list = [ None,
basic_upgrade,
upgrade_1_5,
- XFail(update_1_5),
+ update_1_5,
logs_left_1_5,
upgrade_wcprops,
basic_upgrade_1_0