Author: rhuijben
Date: Sun May 8 09:06:31 2011
New Revision: 1100708
URL: http://svn.apache.org/viewvc?rev=1100708&view=rev
Log:
Plug the accidentally reopened hole that allowed us to introduce file
externals in 1.6: stop allowing switching uncommitted paths.
File externals are introduced in a much cleaner way now, and this scenario
wasn't supported in 1.6 either.
* subversion/include/private/svn_wc_private.h
(svn_wc__node_has_working): New function.
* subversion/libsvn_client/switch.c
(switch_internal): Allow all excluded switches, not just sticky ones.
Deny switch targets that are shadowed and/or do not exist in BASE.
Add note on svn_client__get_youngest_common_ancestor.
* subversion/libsvn_wc/node.c
(svn_wc__node_has_working): New function.
* subversion/libsvn_wc/update_editor.c
(make_editor): Use db argument and just use svn_wc__db_scan_base_repos,
which also performs a does exist in BASE check for us.
(svn_wc_get_update_editor4,
svn_wc_get_switch_editor4): Update caller.
* subversion/tests/cmdline/switch_tests.py
(switch_scheduled_add): Expect a proper error instead of accepting a tree
conflict as success.
Modified:
subversion/trunk/subversion/include/private/svn_wc_private.h
subversion/trunk/subversion/libsvn_client/switch.c
subversion/trunk/subversion/libsvn_wc/node.c
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/tests/cmdline/switch_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=1100708&r1=1100707&r2=1100708&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Sun May 8
09:06:31 2011
@@ -401,6 +401,19 @@ svn_wc__node_is_added(svn_boolean_t *is_
apr_pool_t *scratch_pool);
/**
+ * Set @a *has_working to whether @a local_abspath has a working node (which
+ * might shadow BASE nodes)
+ *
+ * This is a check similar to status = added or status = deleted.
+ */
+svn_error_t *
+svn_wc__node_has_working(svn_boolean_t *has_working,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool);
+
+
+/**
* Get the base revision of @a local_abspath using @a wc_ctx. If
* @a local_abspath is not in the working copy, return
* @c SVN_ERR_WC_PATH_NOT_FOUND.
Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=1100708&r1=1100707&r2=1100708&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Sun May 8 09:06:31 2011
@@ -99,7 +99,7 @@ switch_internal(svn_revnum_t *result_rev
depth_is_sticky = FALSE;
/* Do not support the situation of both exclude and switch a target. */
- if (depth_is_sticky && depth == svn_depth_exclude)
+ if (depth == svn_depth_exclude)
return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Cannot both exclude and switch a path"));
@@ -115,6 +115,18 @@ switch_internal(svn_revnum_t *result_rev
SVN_CONFIG_SECTION_MISCELLANY,
SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
+ {
+ svn_boolean_t has_working;
+ SVN_ERR(svn_wc__node_has_working(&has_working, ctx->wc_ctx, local_abspath,
+ pool));
+
+ if (has_working)
+ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Cannot switch '%s' because it is not in the "
+ "repository yet"),
+ svn_dirent_local_style(local_abspath, pool));
+ }
+
/* See which files the user wants to preserve the extension of when
conflict files are made. */
svn_config_get(cfg, &preserved_exts_str, SVN_CONFIG_SECTION_MISCELLANY,
@@ -194,6 +206,8 @@ switch_internal(svn_revnum_t *result_rev
pool, pool));
SVN_ERR(svn_wc__node_get_base_rev(&target_rev, ctx->wc_ctx,
local_abspath, pool));
+ /* ### It would be nice if this function could reuse the existing
+ ra session instead of opening two for its own use. */
SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_path, &yc_rev,
switch_rev_url, revnum,
target_url, target_rev,
Modified: subversion/trunk/subversion/libsvn_wc/node.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/node.c?rev=1100708&r1=1100707&r2=1100708&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/node.c (original)
+++ subversion/trunk/subversion/libsvn_wc/node.c Sun May 8 09:06:31 2011
@@ -818,6 +818,26 @@ svn_wc__node_is_added(svn_boolean_t *is_
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__node_has_working(svn_boolean_t *has_working,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_status_t status;
+
+ SVN_ERR(svn_wc__db_read_info(&status,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, has_working,
+ wc_ctx->db, local_abspath,
+ scratch_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+
static svn_error_t *
get_base_rev(svn_revnum_t *base_revision,
svn_wc__db_t *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=1100708&r1=1100707&r2=1100708&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Sun May 8 09:06:31
2011
@@ -4171,7 +4171,7 @@ close_edit(void *edit_baton,
/* Helper for the three public editor-supplying functions. */
static svn_error_t *
make_editor(svn_revnum_t *target_revision,
- svn_wc_context_t *wc_ctx,
+ svn_wc__db_t *db,
const char *anchor_abspath,
const char *target_basename,
svn_boolean_t use_commit_times,
@@ -4202,27 +4202,15 @@ make_editor(svn_revnum_t *target_revisio
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__db_status_t status;
/* An unknown depth can't be sticky. */
if (depth == svn_depth_unknown)
depth_is_sticky = FALSE;
- /* Get the anchor's repository root and uuid. */
- SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL,
- &repos_root, &repos_uuid,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- wc_ctx->db, anchor_abspath,
- result_pool, scratch_pool));
-
- /* ### For adds, REPOS_ROOT and REPOS_UUID would be NULL now. */
- if (status == svn_wc__db_status_added)
- SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL,
- &repos_root, &repos_uuid,
- NULL, NULL, NULL, NULL,
- wc_ctx->db, anchor_abspath,
+ /* Get the anchor's repository root and uuid. The anchor must already exist
+ in BASE. */
+ SVN_ERR(svn_wc__db_scan_base_repos(NULL, &repos_root, &repos_uuid,
+ db, anchor_abspath,
result_pool, scratch_pool));
/* With WC-NG we need a valid repository root */
@@ -4242,12 +4230,11 @@ make_editor(svn_revnum_t *target_revisio
eb->target_revision = target_revision;
eb->repos_root = repos_root;
eb->repos_uuid = repos_uuid;
- eb->db = wc_ctx->db;
+ eb->db = db;
eb->target_basename = target_basename;
eb->anchor_abspath = anchor_abspath;
- SVN_ERR(svn_wc__db_get_wcroot(&eb->wcroot_abspath,
- wc_ctx->db, anchor_abspath,
+ SVN_ERR(svn_wc__db_get_wcroot(&eb->wcroot_abspath, db, anchor_abspath,
edit_pool, scratch_pool));
if (switch_url)
@@ -4316,7 +4303,7 @@ make_editor(svn_revnum_t *target_revisio
&& !depth_is_sticky)
SVN_ERR(svn_wc__ambient_depth_filter_editor(&inner_editor,
&inner_baton,
- wc_ctx->db,
+ db,
anchor_abspath,
target_basename,
inner_editor,
@@ -4359,7 +4346,7 @@ svn_wc_get_update_editor4(const svn_delt
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- return make_editor(target_revision, wc_ctx, anchor_abspath,
+ return make_editor(target_revision, wc_ctx->db, anchor_abspath,
target_basename, use_commit_times,
NULL, depth, depth_is_sticky, allow_unver_obstructions,
adds_as_modification, server_performs_filtering,
@@ -4399,7 +4386,7 @@ svn_wc_get_switch_editor4(const svn_delt
{
SVN_ERR_ASSERT(switch_url && svn_uri_is_canonical(switch_url, scratch_pool));
- return make_editor(target_revision, wc_ctx, anchor_abspath,
+ return make_editor(target_revision, wc_ctx->db, anchor_abspath,
target_basename, use_commit_times,
switch_url,
depth, depth_is_sticky, allow_unver_obstructions,
Modified: subversion/trunk/subversion/tests/cmdline/switch_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/switch_tests.py?rev=1100708&r1=1100707&r2=1100708&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/switch_tests.py Sun May 8
09:06:31 2011
@@ -1729,14 +1729,22 @@ def switch_scheduled_add(sbox):
file_path = os.path.join(wc_dir, 'stub_file')
switch_url = sbox.repo_url + '/iota'
+ nodo_path = os.path.join(wc_dir, 'nodo')
svntest.main.file_append(file_path, "")
svntest.actions.run_and_verify_svn(None, None, [],
'add', file_path)
- svntest.actions.run_and_verify_svn(None, None, [], 'switch',
- '--ignore-ancestry',
+ svntest.actions.run_and_verify_svn(None, None,
+ "svn: E200007: Cannot switch '.*file' " +
+ "because it is not in the repository yet",
+ 'switch', '--ignore-ancestry',
switch_url, file_path)
+ svntest.actions.run_and_verify_svn(None, None,
+ "svn: E155010: The node '.*nodo' was not",
+ 'switch', '--ignore-ancestry',
+ switch_url, nodo_path)
+
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
def mergeinfo_switch_elision(sbox):