Author: rhuijben
Date: Mon Feb 16 11:03:12 2015
New Revision: 1660068
URL: http://svn.apache.org/r1660068
Log:
Resolve issue #4558, pin-externals fails to handle spaces properly...
and document another issue in the test expectations.
* subversion/libsvn_client/copy.c
(maybe_quote): New function.
(make_external_description): Use maybe_quote on paths in externals.
* subversion/tests/cmdline/externals_tests.py
(copy_pin_externals_whitepace_dir): Extend test. Remove XFail marker.
Modified:
subversion/trunk/subversion/libsvn_client/copy.c
subversion/trunk/subversion/tests/cmdline/externals_tests.py
Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1660068&r1=1660067&r2=1660068&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Mon Feb 16 11:03:12 2015
@@ -177,6 +177,47 @@ get_copy_pair_ancestors(const apr_array_
return SVN_NO_ERROR;
}
+/* Quote a string if it would be handled as multiple or different tokens
+ during externals parsing */
+static const char *
+maybe_quote(const char *value,
+ apr_pool_t *result_pool)
+{
+ apr_status_t status;
+ char **argv;
+
+ status = apr_tokenize_to_argv(value, &argv, result_pool);
+
+ if (!status && argv[0] && !argv[1] && strcmp(argv[0], value) == 0)
+ return apr_pstrdup(result_pool, value);
+
+ {
+ svn_stringbuf_t *sb = svn_stringbuf_create_empty(result_pool);
+ const char *c;
+
+ svn_stringbuf_appendbyte(sb, '\"');
+
+ for (c = value; *c; c++)
+ {
+ if (*c == '\\' || *c == '\"' || *c == '\'')
+ svn_stringbuf_appendbyte(sb, '\\');
+
+ svn_stringbuf_appendbyte(sb, *c);
+ }
+
+ svn_stringbuf_appendbyte(sb, '\"');
+
+#ifdef SVN_DEBUG
+ status = apr_tokenize_to_argv(sb->data, &argv, result_pool);
+
+ SVN_ERR_ASSERT_NO_RETURN(!status && argv[0] && !argv[1]
+ && !strcmp(argv[0], value));
+#endif
+
+ return sb->data;
+ }
+}
+
/* In *NEW_EXTERNALS_DESCRIPTION, return a new external description for
* use as a line in an svn:externals property, based on the external item
* ITEM and the additional parser information in INFO. Pin the external
@@ -211,7 +252,9 @@ make_external_description(const char **n
}
*new_external_description =
- apr_psprintf(pool, "%s %s%s\n", item->target_dir, rev_str,
item->url);
+ apr_psprintf(pool, "%s %s%s\n", maybe_quote(item->target_dir, pool),
+ rev_str,
+ maybe_quote(item->url, pool));
break;
case svn_wc__external_description_format_2:
@@ -239,8 +282,11 @@ make_external_description(const char **n
}
*new_external_description =
- apr_psprintf(pool, "%s%s%s %s\n", rev_str, item->url, peg_rev_str,
- item->target_dir);
+ apr_psprintf(pool, "%s%s %s\n", rev_str,
+ maybe_quote(apr_psprintf(pool, "%s%s", item->url,
+ peg_rev_str),
+ pool),
+ maybe_quote(item->target_dir, pool));
break;
default:
Modified: subversion/trunk/subversion/tests/cmdline/externals_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/externals_tests.py?rev=1660068&r1=1660067&r2=1660068&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/externals_tests.py Mon Feb 16
11:03:12 2015
@@ -3874,28 +3874,36 @@ def copy_pin_externals_wc_mixed_revision
'--pin-externals')
@Issue(4558)
-@XFail()
def copy_pin_externals_whitepace_dir(sbox):
"copy --pin-externals with whitepace dir"
sbox.build(empty=True)
repo_url = sbox.repo_url
wc_dir = sbox.wc_dir
+ ss_path = repo_url[repo_url.find('//'):]
extdef = sbox.get_tempname('extdef')
+ info = sbox.get_tempname('info')
open(extdef, 'w').write(
- '../deps/sqlite ext/sqlite\n'
+ '"' + ss_path +'/deps/sqlite" ext/sqlite\n' +
'"^/deps/A P R" \'ext/A P R\'\n' +
- repo_url + '/deps/wors%23+\'t ext/wors#+\'t')
+ '^/deps/B\ D\ B\' ext/B\ D\ B\'\n' +
+ repo_url + '/deps/wors%23+t ext/wors#+t')
+ open(info, 'w').write('info\n')
svntest.actions.run_and_verify_svnmucc(None, [], '-U', repo_url,
'mkdir', 'trunk',
'mkdir', 'branches',
'mkdir', 'deps',
'mkdir', 'deps/sqlite',
+ 'put', info, 'deps/sqlite/readme',
'mkdir', 'deps/A P R',
- 'mkdir', 'deps/wors#+\'t',
+ 'put', info, 'deps/A P R/about',
+ 'mkdir', 'deps/B D B\'',
+ 'put', info, 'deps/B D B\'/copying',
+ 'mkdir', 'deps/wors#+t',
+ 'put', info, 'deps/wors#+t/brood',
'propsetf', 'svn:externals', extdef,
'trunk',
'-mm'
@@ -3906,13 +3914,18 @@ def copy_pin_externals_whitepace_dir(sbo
sbox.simple_update('branches')
expected_status = svntest.wc.State(wc_dir, {
- '' : Item(status=' ', wc_rev='0'),
- 'trunk' : Item(status=' ', wc_rev='1'),
- 'trunk/ext' : Item(status='X '),
- 'trunk/ext/A P R' : Item(status=' ', wc_rev='1'),
- 'trunk/ext/sqlite' : Item(status=' ', wc_rev='1'),
- 'trunk/ext/wors#+\'t' : Item(status=' ', wc_rev='1'),
- 'branches' : Item(status=' ', wc_rev='1'),
+ '' : Item(status=' ', wc_rev='0'),
+ 'trunk' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext' : Item(status='X '),
+ 'trunk/ext/sqlite' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/sqlite/readme' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/A P R' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/A P R/about' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/B D B\'' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/B D B\'/copying' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/wors#+t' : Item(status=' ', wc_rev='1'),
+ 'trunk/ext/wors#+t/brood' : Item(status=' ', wc_rev='1'),
+ 'branches' : Item(status=' ', wc_rev='1'),
})
svntest.actions.run_and_verify_status(wc_dir, expected_status)
@@ -3921,6 +3934,10 @@ def copy_pin_externals_whitepace_dir(sbo
branches_url = repo_url + '/branches'
trunk_wc = sbox.ospath('trunk')
+ # Create a new revision to creat interesting pinning revisions
+ sbox.simple_propset('A', 'B', 'trunk')
+ sbox.simple_commit('trunk')
+
# And let's copy/pin
svntest.actions.run_and_verify_svn(None, [],
'copy', '--pin-externals',
@@ -3929,6 +3946,7 @@ def copy_pin_externals_whitepace_dir(sbo
svntest.actions.run_and_verify_svn(None, [],
'copy', '--pin-externals',
trunk_url, sbox.ospath('branches/url-wc'))
+ sbox.simple_commit('branches/url-wc')
svntest.actions.run_and_verify_svn(None, [],
'copy', '--pin-externals',
@@ -3937,11 +3955,69 @@ def copy_pin_externals_whitepace_dir(sbo
svntest.actions.run_and_verify_svn(None, [],
'copy', '--pin-externals',
trunk_wc, sbox.ospath('branches/wc-wc'))
+ sbox.simple_commit('branches/wc-wc')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'branches/url-url' : Item(status='A '),
+ 'branches/url-url/ext/A P R/about' : Item(status='A '),
+ 'branches/url-url/ext/B D B\'/copying' : Item(status='A '),
+ 'branches/url-url/ext/wors#+t/brood' : Item(status='A '),
+ 'branches/url-url/ext/sqlite/readme' : Item(status='A '),
+
+ # url-wc is already up to date
+
+ 'branches/wc-url' : Item(status='A '),
+ 'branches/wc-url/ext/wors#+t/brood' : Item(status='A '),
+ 'branches/wc-url/ext/sqlite/readme' : Item(status='A '),
+ 'branches/wc-url/ext/B D B\'/copying' : Item(status='A '),
+ 'branches/wc-url/ext/A P R/about' : Item(status='A '),
- expected_output = None ## TODO Add
- svntest.actions.run_and_verify_update(wc_dir, expected_output, None, None,
[])
+ ## branches/wc-wc should checkout its externals here
+ })
+ expected_status = svntest.wc.State(wc_dir, {
+ 'branches' : Item(status=' ', wc_rev='6'),
- ## TODO: Verify that all targets are here
+ 'branches/url-url' : Item(status=' ', wc_rev='6'),
+ 'branches/url-url/ext' : Item(status='X '),
+ 'branches/url-url/ext/A P R' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/A P R/about' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/sqlite' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/sqlite/readme' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/wors#+t' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/wors#+t/brood' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/B D B\'' : Item(status=' ', wc_rev='2'),
+ 'branches/url-url/ext/B D B\'/copying' : Item(status=' ', wc_rev='2'),
+
+ 'branches/url-wc' : Item(status=' ', wc_rev='6'),
+ 'branches/url-wc/ext' : Item(status='X '),
+ 'branches/url-wc/ext/wors#+t' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/wors#+t/brood' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/B D B\'' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/B D B\'/copying' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/sqlite' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/sqlite/readme' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/A P R' : Item(status=' ', wc_rev='3'),
+ 'branches/url-wc/ext/A P R/about' : Item(status=' ', wc_rev='3'),
+
+ 'branches/wc-url' : Item(status=' ', wc_rev='6'),
+ 'branches/wc-url/ext' : Item(status='X '),
+ 'branches/wc-url/ext/wors#+t' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/wors#+t/brood' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/sqlite' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/sqlite/readme' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/B D B\'' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/B D B\'/copying' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/A P R' : Item(status=' ', wc_rev='1'),
+ 'branches/wc-url/ext/A P R/about' : Item(status=' ', wc_rev='1'),
+
+ 'branches/wc-wc' : Item(status=' ', wc_rev='6'),
+ # ### Where are the externals of wc-wc?
+
+ # ### I'm guessing update doesn't want to update them because
+ # ### they are pinned?
+ })
+ svntest.actions.run_and_verify_update(wc_dir + '/branches', expected_output,
+ None, expected_status, [])