Helllo Stefan.

Thanks for trying to solve this problem.
Unfortunately you patch doesn't solve the problem because of 2 reasons.
1. It doesn't change "target" (in diff request), and it still may contain '/'.
2. If in my example (just replace http://localhost/svn == file:///tmp/test) 
diff fails if I compare r2 
and r4.

$ svn diff file:///tmp/test/directory/subdirectory@2 
file:///tmp/test/directory/subdirectory@4
svn: E125007: Path 'subdirectory/file1' must be an immediate child of the 
directory 
'directory/subdirectory'

Though I can confirm that for r1-r4 comparison the output is ok with your patch.

Actually I didn't expect involving "relative_to_dir" feature because currently 
svn client doesn't 
set this parameter anywhere. And I don't think it's a good idea to to use it 
now. As I wrote I think 
a better approach is to eliminate that do{}while(); cycle and to do something 
like (though it may 
require some significant efforts)

if (any or urls to compare doesn't exist in peg revision) {
 generate full addition/deletion diff using a special report
//or alternative throw an exception like svn 1.6 does
} else {
  perform diff that is currently performed
}

> On Tue, Mar 20, 2012 at 07:16:44PM +0100, Dmitry Pavlenko wrote:
> > > I expected you'd get an "/directory/subdirectory@1 doesn't exist"
> > > error.
> > 
> > I was the older (1.6) SVN behaviour
> > 
> > Now "do {} while()" cycle in "diff_prepare_repos_repos" takes parent URL
> > until URL exists in both start and end revisions. So maybe the cycle
> > should be run only once not to let '/'. Or, that is maybe better, if URL
> > doesn't exist in one of revision, diff should show complete addition or
> > complete removal. So maybe this case should be handled separatedly,
> > using a special report.
> > 
> > I a "doesn't exist" error is expected, the efforts in that "do {} while
> > ()" cycle seem to be useless.
> > 
> > To my opinion It would be reasonable to guarantee that all directories
> > are displayed relative to the parent of url1 and url2 arguments that
> > exists in both revisions (that is found in that "do {} while()" cycle).
> > Or maybe it would be reasonable to display all paths relative to targets
> > (or parents --- for diff on files) as you proposed.
> 
> Hi Dmitry,
> 
> I'm looking into this.
> 
> I think all paths should be relative to user-specified targets.
> 
> In the case where we show newly added items we need to use parent paths
> internally. These ended up being used for diff output, too, which is
> wrong in my opinion.
> 
> If you want to help you can test and review the patch below. Thanks!
> 
> I am currently running tests over all ra layers with this patch and
> should have results in a while.
> 
> (sorry, no log message yet -- not enough time right now)
> 
> Index: subversion/libsvn_client/diff.c
> ===================================================================
> --- subversion/libsvn_client/diff.c   (revision 1333046)
> +++ subversion/libsvn_client/diff.c   (working copy)
> @@ -1540,6 +1540,14 @@ resolve_pegged_diff_target_url(const char **resolv
>   * *TARGET1 and *TARGET2, based on *URL1 and *URL2.
>   * Set *BASE_PATH corresponding to the URL opened in the new *RA_SESSION
>   * which is pointing at *ANCHOR1.
> + *
> + * If one of the diff targets does not exist in the repository, diff
> targets + * specified by the user will be adjusted so that a diff can be
> generated. + * However, the resulting paths in diff output can differ from
> what users + * expect to see. If *RELATIVE_TO_DIR is not NULL and does not
> already + * contain a valid path, set it up such that generated diff
> output meets user + * expectations even if targets have to be adjusted.
> + *
>   * Use client context CTX. Do all allocations in POOL. */
>  static svn_error_t *
>  diff_prepare_repos_repos(const char **url1,
> @@ -1551,6 +1559,7 @@ diff_prepare_repos_repos(const char **url1,
>                           const char **anchor2,
>                           const char **target1,
>                           const char **target2,
> +                         const char **relative_to_dir,
>                           svn_ra_session_t **ra_session,
>                           svn_client_ctx_t *ctx,
>                           const char *path_or_url1,
> @@ -1713,6 +1722,31 @@ diff_prepare_repos_repos(const char **url1,
>          }
>        while (kind != svn_node_dir);
>        *anchor1 = *anchor2 = new_anchor;
> +
> +      /* Diff labels must appear relative to previous anchor. */
> +      if (relative_to_dir && *relative_to_dir == NULL)
> +        {
> +          const char *relative_to_url;
> +
> +          if (kind1 == svn_node_none)
> +            {
> +              if (kind2 == svn_node_file)
> +                svn_uri_split(&relative_to_url, NULL, *url2, pool);
> +              else
> +                relative_to_url = *url2;
> +            }
> +          else
> +            {
> +              if (kind1 == svn_node_file)
> +                svn_uri_split(&relative_to_url, NULL, *url1, pool);
> +              else
> +                relative_to_url = *url1;
> +            }
> +
> +          *relative_to_dir = svn_uri_skip_ancestor(repos_root,
> +                                                   relative_to_url, pool);
> +        }
> +
>        /* Diff targets must be relative to the new anchor. */
>        *target1 = svn_uri_skip_ancestor(new_anchor, *url1, pool);
>        *target2 = svn_uri_skip_ancestor(new_anchor, *url2, pool);
> @@ -2372,6 +2406,7 @@ diff_repos_repos(const svn_wc_diff_callbacks4_t *c
>    /* Prepare info for the repos repos diff. */
>    SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
>                                     &anchor1, &anchor2, &target1, &target2,
> +                                   &callback_baton->relative_to_dir,
>                                     &ra_session, ctx, path_or_url1,
> path_or_url2, revision1, revision2, peg_revision, pool));
> @@ -2745,7 +2780,7 @@ diff_summarize_repos_repos(svn_client_diff_summari
>    /* Prepare info for the repos repos diff. */
>    SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
>                                     &anchor1, &anchor2, &target1, &target2,
> -                                   &ra_session, ctx,
> +                                   NULL, &ra_session, ctx,
>                                     path_or_url1, path_or_url2, revision1,
> revision2, peg_revision, pool));

Reply via email to