svn-3651

Version:

1.7.0

Bug Link:

http://subversion.tigris.org/issues/show_bug.cgi?id=3651

Patch Link:

source code patch: http://svn.apache.org/viewvc?diff_format=h&view=revision&revision=952973

reproduction: http://subversion.tigris.org/nonav/issues/showattachment.cgi/1101/3651.sh

Symptom:

‘svn copy’ does not support ‘peg revision’ within copy target path. For example, if you run ‘svn copy trunk/file@2 trunk/file@HEAD’, then SVN created a file named “trunk/file@HEAD” in the latest revision (HEAD).

The correct behavior should be that the target file is ‘trunk/file’ of revision HEAD.

How it is diagnosed:

reproduced

 

How to reproduce:

Run http://subversion.tigris.org/nonav/issues/showattachment.cgi/1101/3651.sh

 

*Result: When running ‘svn cp file://REPOS/dir1@2 file://REPOS/dir3@HEAD’,

target path is ‘dir3@head’ instead of ‘dir3’.

 

Root Cause:

Brief:

‘svn copy’ doesn’t support ‘peg revision’ within copy target path.

Detail:

--- subversion/trunk/subversion/svn/copy-cmd.c          2010/06/09 12:03:15            952972

+++ subversion/trunk/subversion/svn/copy-cmd.c   2010/06/09 12:05:20            952973

@@ -77,6 +77,8 @@ svn_cl__copy(apr_getopt_t *os,

           APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source;

         }

 

+  SVN_ERR(svn_opt_eat_peg_revisions(&targets, targets, pool));

+

 
svn_cl__copy(...)
{
    ...
   for (i = 0; i < (targets->nelts - 1); i++)
   {
     ...
     source->path = src;
     source->revision = &(opt_state->start_revision);
     source->peg_revision = peg_revision;
     APR_ARRAY_PUSH(sources, svn_client_copy_source_t *) = source;
   }
+ SVN_ERR(svn_opt_eat_peg_revisions(&targets, targets, pool));
  ...

  /*if we did not eat peg revision as above it’s set wrong!!*/
 
dst_path = APR_ARRAY_IDX(targets, targets->nelts - 1, const char *);
 ...
 err =
svn_client_copy5(&commit_info, sources, dst_path, TRUE,
                        opt_state->parents, opt_state->ignore_externals,
                        opt_state->revprop_table, ctx, pool);
 ...
 return SVN_NO_ERROR;
}
svn_client_copy5(...)
{
        ...
 err = try_copy(&commit_info,sources, dst_path,
                FALSE /* is_move */,TUE /* force, set to avoid deletion check */,...);
  /* If the destination exists, try to copy the sources as children of the
    destination. In the buggy case, err is NULL, but it should */

 if (copy_as_child && err && (sources->nelts == 1)
       && (err->apr_err == SVN_ERR_ENTRY_EXISTS
           || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS))
   {
            ...
             err =
try_copy(...);
   }
   ...
   return svn_error_return(err);
}
try_copy(...)
{
    ...
     return svn_error_return(
repos_to_repos_copy(commit_info_p, copy_pairs...);
   ...
}

repos_to_repos_copy(...)
{
     …
     if (dst_kind != svn_node_none)
       return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
                                _("Path '%s' already exists"), dst_rel);
     ...
     ...
     err = svn_delta_path_driver(editor, edit_baton, youngest, paths,
                             path_driver_cb_func, &cb_baton, pool);
     …
}

// just inserted to call ‘svn_opt_eat_peg_revisions’ to handle a peg revision.

   /* Figure out which type of trace editor to use.

          If the src_paths are not homogeneous, setup_copy will return an error. */

   src_path = APR_ARRAY_IDX(targets, 0, const char *);

 

·        Call stack

#0  svn_opt__split_arg_at_peg_revision (utf8_target=

"file:///home/yyzhou/mmlee/LOG-project/svn/3651/repos1/dir3@HEAD")

at subversion/libsvn_subr/opt.c:940

#1  svn_cl__eat_peg_revisions () at subversion/svn/util.c:1325

#2  svn_cl__copy () at subversion/svn/copy-cmd.c:79

#3  main () at subversion/svn/main.c:2373

 

The added ‘svn_cl__eat_peg_revisions’ function calls ‘svn_opt__split_arg_at_peg_revision’ and this function extracts ‘peg revision from the target path. The refined path is "file:///home/yyzhou/mmlee/LOG-project/svn/3651/repos1/dir3”.

Failure type

wrong result

Is there any log message?

No

Can we anticipate error?

No. Simply the result is wrong, there is no check on the result!

But the root cause is very obvious from the symptom.