[[[ Canonicalize dirent/URL before passing to client API
* subversion/svn/merge-cmd.c (svn_cl__merge), subversion/svn/propget-cmd.c (svn_cl__propget), subversion/svn/proplist-cmd.c (svn_cl__proplist), subversion/svn/copy-cmd.c (svn_cl__copy), subversion/svn/mergeinfo-cmd.c (svn_cl__mergeinfo), subversion/svn/blame-cmd.c (svn_cl__blame), subversion/svn/log-cmd.c (svn_cl__log), subversion/svn/export-cmd.c (svn_cl__export), subversion/svn/info-cmd.c (svn_cl__info): Use svn_cl__opt_parse_path() instead of svn_opt_parse_path() followed by canonicalizing. * subversion/svn/propdel-cmd.c (svn_cl__propdel), subversion/svn/propget-cmd.c (svn_cl__propget), subversion/svn/propset-cmd.c (svn_cl__propset), subversion/svn/proplist-cmd.c (svn_cl__proplist): Canonicalize URL * subversion/tests/cmdline/mergeinfo_tests.py (mergeinfo_url_special_characters), subversion/tests/cmdline/prop_tests.py (props_url_special_characters), subversion/tests/cmdline/merge_tests.py (merge_url_special_characters), subversion/tests/cmdline/log_tests.py (log_url_special_characters), subversion/tests/cmdline/copy_tests.py (copy_url_special_characters), subversion/tests/cmdline/blame_tests.py (blame_url_special_characters): New tests Patch by: Noorul Islam K M <noorul{_AT_}collab.net> ]]] Thanks and Regards Noorul
Index: subversion/tests/cmdline/mergeinfo_tests.py =================================================================== --- subversion/tests/cmdline/mergeinfo_tests.py (revision 1033415) +++ subversion/tests/cmdline/mergeinfo_tests.py (working copy) @@ -478,6 +478,18 @@ adjust_error_for_server_version(''), ['4', '5'], A_path, A_COPY_path + '@PREV', '--show-revs', 'eligible') +def mergeinfo_url_special_characters(sbox): + """special characters in svn mergeinfo URL""" + + sbox.build() + wc_dir = sbox.wc_dir + special_url = sbox.repo_url + '/%2E' + + svntest.actions.run_and_verify_svn(None, None, [], 'ps', SVN_PROP_MERGEINFO, + '/:1', wc_dir) + svntest.actions.run_and_verify_mergeinfo(adjust_error_for_server_version(""), + ['1'], special_url, wc_dir) + ######################################################################## # Run the tests @@ -493,6 +505,7 @@ SkipUnless(recursive_mergeinfo, server_has_mergeinfo), SkipUnless(mergeinfo_on_pegged_wc_path, server_has_mergeinfo), + mergeinfo_url_special_characters, ] if __name__ == '__main__': Index: subversion/tests/cmdline/prop_tests.py =================================================================== --- subversion/tests/cmdline/prop_tests.py (revision 1033415) +++ subversion/tests/cmdline/prop_tests.py (working copy) @@ -2335,6 +2335,31 @@ if ((len(expected_output) * 3) - 6) != len(pg_stdout_redir): raise svntest.Failure("Redirected pg -vR has unexpected duplicates") +def props_url_special_characters(sbox): + "set/get/list/del with special characters in URL" + + sbox.build() + wc_dir = sbox.wc_dir + special_url = sbox.repo_url + '/%2E' + + svntest.actions.enable_revprop_changes(sbox.repo_dir) + + svntest.actions.run_and_verify_svn(None, None, [], + 'propset', '--revprop', '-r', '0', + 'cash-sound', 'cha-ching!', special_url) + + svntest.actions.run_and_verify_svn(None, None, [], + 'propget', '--revprop', '-r', '0', + 'cash-sound', special_url) + + svntest.actions.run_and_verify_svn(None, None, [], + 'proplist', '--revprop', '-r', '0', + special_url) + + svntest.actions.run_and_verify_svn(None, None, [], + 'propdel', '--revprop', '-r', '0', + 'cash-sound', special_url) + ######################################################################## # Run the tests @@ -2380,6 +2405,7 @@ obstructed_subdirs, atomic_over_ra, propget_redirection, + props_url_special_characters, ] if __name__ == '__main__': Index: subversion/tests/cmdline/merge_tests.py =================================================================== --- subversion/tests/cmdline/merge_tests.py (revision 1033415) +++ subversion/tests/cmdline/merge_tests.py (working copy) @@ -16225,6 +16225,33 @@ None, None, None, None, None, 1) +def merge_url_special_characters(sbox): + """special characters in svn merge URL""" + + sbox.build() + wc_dir = sbox.wc_dir + a_dir = os.path.join(wc_dir, 'A') + new_file = os.path.join(a_dir, "new file") + + # Make r2. + svntest.main.file_append(new_file, "Initial text in the file.\n") + svntest.main.run_svn(None, "add", new_file) + svntest.actions.run_and_verify_svn(None, None, [], + "ci", "-m", "r2", wc_dir) + + # Make r3. + svntest.main.file_append(new_file, "Next line of text in the file.\n") + svntest.actions.run_and_verify_svn(None, None, [], + "ci", "-m", "r3", wc_dir) + + os.chdir(wc_dir) + svntest.actions.run_and_verify_svn(None, None, [], + "up") + + special_url = sbox.repo_url + '/A' + '/%2E' + svntest.actions.run_and_verify_svn(None, None, [], + "merge", "-r3:2", special_url) + ######################################################################## # Run the tests @@ -16415,6 +16442,7 @@ merge_into_locally_added_directory, merge_with_os_deleted_subtrees, XFail(no_self_referential_or_nonexistent_inherited_mergeinfo), + merge_url_special_characters, ] if __name__ == '__main__': Index: subversion/tests/cmdline/log_tests.py =================================================================== --- subversion/tests/cmdline/log_tests.py (revision 1033415) +++ subversion/tests/cmdline/log_tests.py (working copy) @@ -1746,6 +1746,20 @@ "differs from that on move source '%s'" % (psi_moved_path, psi_path)) +def log_url_special_characters(sbox): + """special characters in svn log URL""" + sbox.build(create_wc = False) + + special_urls = [sbox.repo_url + '/A' + '/%2E', + sbox.repo_url + '%2F' + 'A'] + + for url in special_urls: + exit_code, output, err = svntest.actions.run_and_verify_svn(None, None, [], + 'log', '-c', + 1, url) + log_chain = parse_log_output(output) + check_log_chain(log_chain, [1]) + ######################################################################## # Run the tests @@ -1788,6 +1802,7 @@ SkipUnless(merge_sensitive_log_propmod_merge_inheriting_path, server_has_mergeinfo), log_of_local_copy, + log_url_special_characters, ] if __name__ == '__main__': Index: subversion/tests/cmdline/copy_tests.py =================================================================== --- subversion/tests/cmdline/copy_tests.py (revision 1033415) +++ subversion/tests/cmdline/copy_tests.py (working copy) @@ -4921,7 +4921,23 @@ Item(status=' ', wc_rev='-', copied='+')}) svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) +def copy_url_special_characters(sbox): + """special characters in svn cp URL""" + sbox.build() + wc_dir = sbox.wc_dir + a_path = os.path.join(wc_dir, 'A') + new_path1 = os.path.join(a_path, 'Folder1') + os.mkdir(new_path1) + new_path2 = os.path.join(a_path, 'Folder2') + os.mkdir(new_path2) + svntest.main.run_svn(None, "add", new_path1, new_path2) + sbox.simple_commit() + from_special_url = sbox.repo_url + '/A/Folder1' + '/%2E' + + svntest.actions.run_and_verify_svn(None, None, [], 'copy', + from_special_url, new_path2) + ######################################################################## # Run the tests @@ -5024,6 +5040,7 @@ copy_repos_over_deleted_other_kind, copy_wc_over_deleted_same_kind, copy_wc_over_deleted_other_kind, + copy_url_special_characters, ] if __name__ == '__main__': Index: subversion/tests/cmdline/blame_tests.py =================================================================== --- subversion/tests/cmdline/blame_tests.py (revision 1033415) +++ subversion/tests/cmdline/blame_tests.py (working copy) @@ -703,7 +703,19 @@ svntest.actions.run_and_verify_svn(None, expected_output, [], 'blame', '-g', mu_path) +def blame_url_special_characters(sbox): + """special characters in svn blame URL""" + sbox.build(create_wc = False) + special_urls = [sbox.repo_url + '/A' + '/%2E', + sbox.repo_url + '%2F' + 'A'] + + expected_err = "svn: '/A' is not a file in revision 1\n" + + for url in special_urls: + svntest.actions.run_and_verify_svn2(None, None, expected_err, 1, + 'blame', url) + ######################################################################## # Run the tests @@ -724,6 +736,7 @@ blame_peg_rev_file_not_in_head, blame_file_not_in_head, blame_output_after_merge, + blame_url_special_characters ] if __name__ == '__main__': Index: subversion/svn/merge-cmd.c =================================================================== --- subversion/svn/merge-cmd.c (revision 1033415) +++ subversion/svn/merge-cmd.c (working copy) @@ -121,13 +121,13 @@ } else /* Parse at least one, and possible two, sources. */ { - SVN_ERR(svn_opt_parse_path(&peg_revision1, &sourcepath1, - APR_ARRAY_IDX(targets, 0, const char *), - pool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision1, &sourcepath1, + APR_ARRAY_IDX(targets, 0, const char *), + pool)); if (targets->nelts >= 2) - SVN_ERR(svn_opt_parse_path(&peg_revision2, &sourcepath2, - APR_ARRAY_IDX(targets, 1, const char *), - pool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision2, &sourcepath2, + APR_ARRAY_IDX(targets, 1, const char *), + pool)); } /* We could have one or two sources. Deliberately written to stay Index: subversion/svn/propdel-cmd.c =================================================================== --- subversion/svn/propdel-cmd.c (revision 1033415) +++ subversion/svn/propdel-cmd.c (working copy) @@ -105,6 +105,7 @@ SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, &URL, ctx, pool)); + URL = svn_uri_canonicalize(URL, pool); /* Let libsvn_client do the real work. */ SVN_ERR(svn_client_revprop_set2(pname_utf8, NULL, NULL, Index: subversion/svn/copy-cmd.c =================================================================== --- subversion/svn/copy-cmd.c (revision 1033415) +++ subversion/svn/copy-cmd.c (working copy) @@ -68,7 +68,7 @@ svn_opt_revision_t *peg_revision = apr_palloc(pool, sizeof(*peg_revision)); - SVN_ERR(svn_opt_parse_path(peg_revision, &src, target, pool)); + SVN_ERR(svn_cl__opt_parse_path(peg_revision, &src, target, pool)); source->path = src; source->revision = &(opt_state->start_revision); source->peg_revision = peg_revision; Index: subversion/svn/mergeinfo-cmd.c =================================================================== --- subversion/svn/mergeinfo-cmd.c (revision 1033415) +++ subversion/svn/mergeinfo-cmd.c (working copy) @@ -84,15 +84,16 @@ _("Too many arguments given")); /* Parse the source-u...@rev] argument. */ - SVN_ERR(svn_opt_parse_path(&src_peg_revision, &source, - APR_ARRAY_IDX(targets, 0, const char *), pool)); + SVN_ERR(svn_cl__opt_parse_path(&src_peg_revision, &source, + APR_ARRAY_IDX(targets, 0, const char *), + pool)); /* Parse the targ...@rev] argument (if provided). */ if (targets->nelts == 2) { - SVN_ERR(svn_opt_parse_path(&tgt_peg_revision, &target, - APR_ARRAY_IDX(targets, 1, const char *), - pool)); + SVN_ERR(svn_cl__opt_parse_path(&tgt_peg_revision, &target, + APR_ARRAY_IDX(targets, 1, const char *), + pool)); } else { Index: subversion/svn/blame-cmd.c =================================================================== --- subversion/svn/blame-cmd.c (revision 1033415) +++ subversion/svn/blame-cmd.c (working copy) @@ -327,8 +327,8 @@ SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); /* Check for a peg revision. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, - subpool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target, + subpool)); if (end_revision_unspecified) { Index: subversion/svn/propget-cmd.c =================================================================== --- subversion/svn/propget-cmd.c (revision 1033415) +++ subversion/svn/propget-cmd.c (working copy) @@ -225,6 +225,7 @@ SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, &URL, ctx, pool)); + URL = svn_uri_canonicalize(URL, pool); /* Let libsvn_client do the real work. */ SVN_ERR(svn_client_revprop_get(pname_utf8, &propval, @@ -304,9 +305,9 @@ SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); /* Check for a peg revision. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, - subpool)); - + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target, + subpool)); + SVN_ERR(svn_client_propget3(&props, pname_utf8, truepath, &peg_revision, &(opt_state->start_revision), Index: subversion/svn/log-cmd.c =================================================================== --- subversion/svn/log-cmd.c (revision 1033415) +++ subversion/svn/log-cmd.c (working copy) @@ -637,7 +637,7 @@ } /* Strip peg revision. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &true_path, target, pool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &true_path, target, pool)); APR_ARRAY_IDX(targets, 0, const char *) = true_path; if (svn_path_is_url(target)) Index: subversion/svn/propset-cmd.c =================================================================== --- subversion/svn/propset-cmd.c (revision 1033415) +++ subversion/svn/propset-cmd.c (working copy) @@ -113,6 +113,7 @@ SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, &URL, ctx, scratch_pool)); + URL = svn_uri_canonicalize(URL, scratch_pool); /* Let libsvn_client do the real work. */ SVN_ERR(svn_client_revprop_set2(pname_utf8, propval, NULL, Index: subversion/svn/proplist-cmd.c =================================================================== --- subversion/svn/proplist-cmd.c (revision 1033415) +++ subversion/svn/proplist-cmd.c (working copy) @@ -128,6 +128,7 @@ SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets, &URL, ctx, scratch_pool)); + URL = svn_uri_canonicalize(URL, scratch_pool); /* Let libsvn_client do the real work. */ SVN_ERR(svn_client_revprop_list(&proplist, @@ -196,8 +197,8 @@ pl_baton.opt_state = opt_state; /* Check for a peg revision. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, - iterpool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target, + iterpool)); SVN_ERR(svn_cl__try (svn_client_proplist3(truepath, &peg_revision, Index: subversion/svn/export-cmd.c =================================================================== --- subversion/svn/export-cmd.c (revision 1033415) +++ subversion/svn/export-cmd.c (working copy) @@ -68,7 +68,7 @@ from = APR_ARRAY_IDX(targets, 0, const char *); /* Get the peg revision if present. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &truefrom, from, pool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truefrom, from, pool)); /* If only one target was given, split off the basename to use as the `to' path. Else, a `to' path was supplied. */ Index: subversion/svn/info-cmd.c =================================================================== --- subversion/svn/info-cmd.c (revision 1033415) +++ subversion/svn/info-cmd.c (working copy) @@ -546,22 +546,17 @@ SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); /* Get peg revisions. */ - SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, subpool)); + SVN_ERR(svn_cl__opt_parse_path(&peg_revision, &truepath, target, + subpool)); /* If no peg-rev was attached to a URL target, then assume HEAD. */ if (svn_path_is_url(truepath)) - { - truepath = svn_uri_canonicalize(truepath, subpool); - + { if (peg_revision.kind == svn_opt_revision_unspecified) peg_revision.kind = svn_opt_revision_head; - } + } else - { - truepath = svn_dirent_canonicalize(truepath, subpool); - SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool)); - } err = svn_client_info3(truepath, &peg_revision, &(opt_state->start_revision),