Index: subversion/include/svn_types.h =================================================================== --- subversion/include/svn_types.h (revision 15206) +++ subversion/include/svn_types.h (working copy) @@ -283,6 +283,19 @@ /** A compressed combination of the other four keywords. */ #define SVN_KEYWORD_ID "Id" +/** Special revision descriptors HEAD */ +#define SVN_KEYWORD_REVISION_HEAD "head" + +/** Special revision descriptors BASE */ +#define SVN_KEYWORD_REVISION_BASE "base" + +/** Special revision descriptors PREV */ +#define SVN_KEYWORD_REVISION_PREV "prev" + +/** Special revision descriptors COMMITTED */ +#define SVN_KEYWORD_REVISION_COMMIT "committed" + + /** @} */ Index: subversion/libsvn_subr/opt.c =================================================================== --- subversion/libsvn_subr/opt.c (revision 15206) +++ subversion/libsvn_subr/opt.c (working copy) @@ -289,19 +289,19 @@ static int revision_from_word (svn_opt_revision_t *revision, const char *word) { - if (strcasecmp (word, "head") == 0) + if (strcasecmp (word, SVN_KEYWORD_REVISION_HEAD) == 0) { revision->kind = svn_opt_revision_head; } - else if (strcasecmp (word, "prev") == 0) + else if (strcasecmp (word, SVN_KEYWORD_REVISION_PREV) == 0) { revision->kind = svn_opt_revision_previous; } - else if (strcasecmp (word, "base") == 0) + else if (strcasecmp (word, SVN_KEYWORD_REVISION_BASE) == 0) { revision->kind = svn_opt_revision_base; } - else if (strcasecmp (word, "committed") == 0) + else if (strcasecmp (word, SVN_KEYWORD_REVISION_COMMIT) == 0) { revision->kind = svn_opt_revision_committed; } @@ -498,13 +498,37 @@ if (path[i] == '@') { + svn_boolean_t is_url; + int ret; svn_opt_revision_t start_revision, end_revision; end_revision.kind = svn_opt_revision_unspecified; - if (svn_opt_parse_revision (&start_revision, - &end_revision, - path + i + 1, pool) - || end_revision.kind != svn_opt_revision_unspecified) + + /* URLs and wc-paths get treated differently. */ + is_url = svn_path_is_url (path); + + /* If empty peg-rev was attached to URL target, then assume HEAD. */ + if (path [i + 1] == '\0' && is_url) + { + ret = svn_opt_parse_revision (&start_revision, + &end_revision, + SVN_KEYWORD_REVISION_HEAD, pool); + } + /* If empty peg-rev was attached to PATH target, then assume BASE. */ + else if (path [i + 1] == '\0' && !is_url) + { + ret = svn_opt_parse_revision (&start_revision, + &end_revision, + SVN_KEYWORD_REVISION_BASE, pool); + } + else + { + ret = svn_opt_parse_revision (&start_revision, + &end_revision, + path + i + 1, pool); + } + + if (ret || end_revision.kind != svn_opt_revision_unspecified) return svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Syntax error parsing revision '%s'"), path + i + 1); Index: subversion/tests/clients/cmdline/basic_tests.py =================================================================== --- subversion/tests/clients/cmdline/basic_tests.py (revision 15206) +++ subversion/tests/clients/cmdline/basic_tests.py (working copy) @@ -1584,6 +1584,30 @@ "lambda")) check_repos_root(output) +def basic_peg_revision(sbox): + "checks peg revision on filename with @ sign" + + sbox.build() + wc_dir = sbox.wc_dir + repos_dir = sbox.repo_url + filename = 'abc@abc' + + wc_file = wc_dir + '/' + filename + repos_file = repos_dir + '/' + filename + + svntest.main.file_append(wc_file, 'A probe into the secrets about the Solar System') + svntest.main.run_svn(None, 'add', wc_file) + svntest.main.run_svn(None, 'ci', '-m', 'secret log msg', wc_file) + + output, errlines = svntest.main.run_svn(0, 'cat', wc_file+'@') + if len(output) < 1: + raise svntest.Failure + + output, errlines = svntest.main.run_svn(0, 'cat', repos_file+'@') + if len(output) < 1: + raise svntest.Failure + + #---------------------------------------------------------------------- ######################################################################## # Run the tests @@ -1617,6 +1641,7 @@ basic_add_local_ignores, basic_add_no_ignores, repos_root, + basic_peg_revision, ### todo: more tests needed: ### test "svn rm http://some_url" ### not sure this file is the right place, though.