[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: paths in diff output (possible bug)

From: Dmitry Pavlenko <pavlenko_at_tmatesoft.com>
Date: Thu, 3 May 2012 14:43:11 +0200

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_at_2 file:///tmp/test/directory/subdirectory_at_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_at_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));
Received on 2012-05-03 14:44:46 CEST

This is an archived mail posted to the Subversion Dev mailing list.