Author: stsp
Date: Wed Feb 4 16:03:23 2015
New Revision: 1657297
URL: http://svn.apache.org/r1657297
Log:
On the pin-externals branch, error out if users attempt to pin checked out
externals which have local modifications, switched subtrees, or mixed revisions.
Suggested by: julianfoad
* subversion/libsvn_client/copy.c
(pin_externals_prop): Ensure that directory externals are at a single
revision, have no switched subtrees and no local mods. Otherwise
error out with an informative error message.
* subversion/tests/cmdline/externals_tests.py
(copy_pin_externals): Verify the above error conditions.
Modified:
subversion/branches/pin-externals/subversion/libsvn_client/copy.c
subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
Modified: subversion/branches/pin-externals/subversion/libsvn_client/copy.c
URL:
http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/libsvn_client/copy.c?rev=1657297&r1=1657296&r2=1657297&view=diff
==============================================================================
--- subversion/branches/pin-externals/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/pin-externals/subversion/libsvn_client/copy.c Wed Feb
4 16:03:23 2015
@@ -366,6 +366,7 @@ pin_externals_prop(svn_string_t **pinned
{
const char *external_abspath;
svn_node_kind_t external_kind;
+ svn_revnum_t external_checked_out_rev;
external_abspath = svn_dirent_join(local_abspath_or_url,
item->target_dir,
@@ -388,12 +389,83 @@ pin_externals_prop(svn_string_t **pinned
local_abspath_or_url, iterpool),
svn_dirent_local_style(
external_abspath, iterpool));
+ else if (external_kind == svn_node_dir)
+ {
+ svn_boolean_t is_switched;
+ svn_boolean_t is_modified;
+ svn_revnum_t min_rev;
+ svn_revnum_t max_rev;
+
+ /* Perform some sanity checks on the checked-out external. */
+
+ SVN_ERR(svn_wc__has_switched_subtrees(&is_switched,
+ ctx->wc_ctx,
+ external_abspath, NULL,
+ iterpool));
+ if (is_switched)
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+ NULL,
+ _("Cannot pin external '%s'
defined "
+ "in %s at '%s' because '%s' has
"
+ "switched subtrees (switches "
+ "cannot be represented in %s)"),
+ item->url, SVN_PROP_EXTERNALS,
+ svn_dirent_local_style(
+ local_abspath_or_url, iterpool),
+ svn_dirent_local_style(
+ external_abspath, iterpool),
+ SVN_PROP_EXTERNALS);
+
+ SVN_ERR(svn_wc__has_local_mods(&is_modified, ctx->wc_ctx,
+ external_abspath,
+ ctx->cancel_func,
+ ctx->cancel_baton,
+ iterpool));
+ if (is_modified)
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+ NULL,
+ _("Cannot pin external '%s'
defined "
+ "in %s at '%s' because '%s' has
"
+ "local modifications (local "
+ "modifications cannot be "
+ "represented in %s)"),
+ item->url, SVN_PROP_EXTERNALS,
+ svn_dirent_local_style(
+ local_abspath_or_url, iterpool),
+ svn_dirent_local_style(
+ external_abspath, iterpool),
+ SVN_PROP_EXTERNALS);
+
+ SVN_ERR(svn_wc__min_max_revisions(&min_rev, &max_rev,
ctx->wc_ctx,
+ external_abspath, FALSE,
+ iterpool));
+ if (min_rev != max_rev)
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+ NULL,
+ _("Cannot pin external '%s'
defined "
+ "in %s at '%s' because '%s' is
a "
+ "mixed-revision working copy "
+ "(mixed-revisions cannot be "
+ "represented in %s)"),
+ item->url, SVN_PROP_EXTERNALS,
+ svn_dirent_local_style(
+ local_abspath_or_url, iterpool),
+ svn_dirent_local_style(
+ external_abspath, iterpool),
+ SVN_PROP_EXTERNALS);
+ external_checked_out_rev = min_rev;
+ }
+ else
+ {
+ SVN_ERR_ASSERT(external_kind == svn_node_file);
+
SVN_ERR(svn_wc__node_get_repos_info(&external_checked_out_rev,
+ NULL, NULL, NULL,
+ ctx->wc_ctx,
external_abspath,
+ iterpool, iterpool));
+ }
external_pegrev.kind = svn_opt_revision_number;
-
SVN_ERR(svn_wc__node_get_repos_info(&external_pegrev.value.number,
- NULL, NULL, NULL,
- ctx->wc_ctx,
external_abspath,
- iterpool, iterpool));
+ external_pegrev.value.number = external_checked_out_rev;
}
}
Modified:
subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
URL:
http://svn.apache.org/viewvc/subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py?rev=1657297&r1=1657296&r2=1657297&view=diff
==============================================================================
---
subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
(original)
+++
subversion/branches/pin-externals/subversion/tests/cmdline/externals_tests.py
Wed Feb 4 16:03:23 2015
@@ -3757,6 +3757,54 @@ def copy_pin_externals(sbox):
external_url_for["A/B/gamma"] = '^/A/D/gamma'
verify_pinned_externals(wc_dir)
+ # Clean up.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'revert', '-R', wc_dir)
+ svntest.main.safe_rmtree(os.path.join(wc_dir, 'A_copy'))
+
+ # Cannot pin WC externals with local mods.
+ svntest.main.file_append(sbox.ospath('A/C/exdir_G/pi'), 'this file changed')
+ expected_stderr = verify.RegexOutput(".*Cannot pin.*local modifications.*",
+ match_all=False)
+ svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+ 'copy',
+ os.path.join(wc_dir, 'A'),
+ os.path.join(wc_dir, 'A_copy'),
+ '--pin-externals')
+
+ # Clean up.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'revert', '-R',
+ sbox.ospath('A/C/exdir_G/pi'))
+
+ # Cannot pin WC externals with switched subtrees.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'switch', '--ignore-ancestry', '^/A/B',
+ sbox.ospath('A/D-moved/exdir_A/C'))
+ expected_stderr = verify.RegexOutput(".*Cannot pin.*switched subtree.*",
+ match_all=False)
+ svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+ 'copy',
+ os.path.join(wc_dir, 'A'),
+ os.path.join(wc_dir, 'A_copy'),
+ '--pin-externals')
+ # Clean up.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'switch', '--ignore-ancestry', '^/A/C',
+ sbox.ospath('A/D-moved/exdir_A/C'))
+
+ # Cannot pin WC externals with mixed revisions
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'update', '-r1',
+ sbox.ospath('A/D-moved/exdir_A/mu'))
+ expected_stderr = verify.RegexOutput(".*Cannot pin.*mixed-revision.*",
+ match_all=False)
+ svntest.actions.run_and_verify_svn(None, None, expected_stderr,
+ 'copy',
+ os.path.join(wc_dir, 'A'),
+ os.path.join(wc_dir, 'A_copy'),
+ '--pin-externals')
+
########################################################################
# Run the tests