Index: subversion/libsvn_client/cmdline.c =================================================================== --- subversion/libsvn_client/cmdline.c (revision 30798) +++ subversion/libsvn_client/cmdline.c (working copy) @@ -56,6 +56,10 @@ * REPOS_ROOT_URL is the absolute URL of the repository root. * All strings are in UTF-8 encoding. * Allocate *ABSOLUTE_URL in POOL. + * + * REPOS_ROOT_URL and RELATIVE_URL do not have to be properly URI-encoded, + * canonical, or valid in any other way. The caller is expected to perform + * canonicalization on *ABSOLUTE_URL after the call to the function. */ static svn_error_t * resolve_repos_relative_url(const char **absolute_url, @@ -68,7 +72,11 @@ _("Improper relative URL '%s'"), relative_url); - *absolute_url = svn_path_join(repos_root_url, relative_url + 2, pool); + /* No assumptions are made about the canonicalization of the input + * arguments, it is presumed that the output will be canonicalized after + * this function, which will remove any duplicate path seperator. + */ + *absolute_url = apr_pstrcat(pool, repos_root_url, relative_url + 1, NULL); return SVN_NO_ERROR; } Index: subversion/tests/cmdline/basic_tests.py =================================================================== --- subversion/tests/cmdline/basic_tests.py (revision 30798) +++ subversion/tests/cmdline/basic_tests.py (working copy) @@ -2291,7 +2291,41 @@ svntest.verify.AnyOutput, 'blame', '^/A/mu', iota_url_repo1, iota_url_repo2) +def basic_relative_url_non_canonical(sbox): + "basic relative url non-canonical targets" + sbox.build() + + # First, make a new revision of iota. + iota = os.path.join(sbox.wc_dir, 'iota') + svntest.main.file_append(iota, "New contents for iota\n") + svntest.main.run_svn(None, 'ci', + '-m', '', iota) + + # Now, make a new revision of A/mu . + mu = os.path.join(sbox.wc_dir, 'A', 'mu') + mu_url = sbox.repo_url + '/A/mu' + + svntest.main.file_append(mu, "New contents for mu\n") + svntest.main.run_svn(None, 'ci', + '-m', '', mu) + + + expected_output = [ + " 1 jrandom This is the file 'iota'.\n", + " 2 jrandom New contents for iota\n", + " 1 jrandom This is the file 'mu'.\n", + " 3 jrandom New contents for mu\n", + ] + + exit_code, output, error = svntest.actions.run_and_verify_svn(None, + expected_output, [], 'blame', + '^/iota/', mu_url) + + exit_code, output, error = svntest.actions.run_and_verify_svn(None, + expected_output, [], 'blame', + '^//iota/', mu_url) + #---------------------------------------------------------------------- ######################################################################## @@ -2342,6 +2376,7 @@ basic_relative_url_using_current_dir, basic_relative_url_using_other_targets, basic_relative_url_multi_repo, + basic_relative_url_non_canonical, ] if __name__ == '__main__':