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

Re: svn commit: r1215273 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/client.h libsvn_client/ra.c svn/cl.h svn/merge-cmd.c svn/mergeinfo-cmd.c svn/util.c

From: Hyrum K Wright <hyrum.wright_at_wandisco.com>
Date: Fri, 16 Dec 2011 15:44:08 -0600

On Fri, Dec 16, 2011 at 3:05 PM, <julianfoad_at_apache.org> wrote:
> Author: julianfoad
> Date: Fri Dec 16 21:05:07 2011
> New Revision: 1215273
>
> URL: http://svn.apache.org/viewvc?rev=1215273&view=rev
> Log:
> Reject attempts to merge between unrelated branches, or where the source and
> target are different objects within their respective branches.  These checks
> are applied in 'svn merge', only on 'reintegrate' and simple 'sync' merges
> where no revision range is specified.  They are also applied in the
> 'svn mergeinfo' command.

We should probably make sure this change ends up in the 1.8 docs, as
it potentially removes merging scenarios which folks may be using.

-Hyrum

>
> * subversion/include/private/svn_client_private.h,
>  subversion/libsvn_client/ra.c
>  (svn_client__youngest_common_ancestor): New function.
>
> * subversion/libsvn_client/client.h
>  (svn_client__get_youngest_common_ancestor): Cross-reference to
>    svn_client__youngest_common_ancestor().
>
> * subversion/svn/cl.h,
>  subversion/svn/util.c
>  (svn_cl__check_related_source_and_target, path_for_display): New functions.
>
> * subversion/svn/merge-cmd.c
>  (svn_cl__merge): Check relatedness of source and target for 'reintegrate'
>    and simple 'sync' merges.
>
> * subversion/svn/mergeinfo-cmd.c
>  (svn_cl__mergeinfo): Check relatedness of source and target.
>
> Modified:
>    subversion/trunk/subversion/include/private/svn_client_private.h
>    subversion/trunk/subversion/libsvn_client/client.h
>    subversion/trunk/subversion/libsvn_client/ra.c
>    subversion/trunk/subversion/svn/cl.h
>    subversion/trunk/subversion/svn/merge-cmd.c
>    subversion/trunk/subversion/svn/mergeinfo-cmd.c
>    subversion/trunk/subversion/svn/util.c
>
> Modified: subversion/trunk/subversion/include/private/svn_client_private.h
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/include/private/svn_client_private.h (original)
> +++ subversion/trunk/subversion/include/private/svn_client_private.h Fri Dec 16 21:05:07 2011
> @@ -59,6 +59,29 @@ svn_client__create_status(svn_client_sta
>                           apr_pool_t *result_pool,
>                           apr_pool_t *scratch_pool);
>
> +/* Set *ANCESTOR_URL and *ANCESTOR_REVISION to the URL and revision,
> + * respectively, of the youngest common ancestor of the two locations
> + * PATH_OR_URL1_at_REV1 and PATH_OR_URL2_at_REV2.  Set *ANCESTOR_RELPATH to
> + * NULL and *ANCESTOR_REVISION to SVN_INVALID_REVNUM if they have no
> + * common ancestor.  This function assumes that PATH_OR_URL1_at_REV1 and
> + * PATH_OR_URL2_at_REV2 both refer to the same repository.
> + *
> + * Use the authentication baton cached in CTX to authenticate against
> + * the repository.
> + *
> + * See also svn_client__get_youngest_common_ancestor().
> + */
> +svn_error_t *
> +svn_client__youngest_common_ancestor(const char **ancestor_url,
> +                                     svn_revnum_t *ancestor_rev,
> +                                     const char *path_or_url1,
> +                                     const svn_opt_revision_t *revision1,
> +                                     const char *path_or_url2,
> +                                     const svn_opt_revision_t *revision2,
> +                                     svn_client_ctx_t *ctx,
> +                                     apr_pool_t *result_pool,
> +                                     apr_pool_t *scratch_pool);
> +
>  #ifdef __cplusplus
>  }
>  #endif /* __cplusplus */
>
> Modified: subversion/trunk/subversion/libsvn_client/client.h
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_client/client.h (original)
> +++ subversion/trunk/subversion/libsvn_client/client.h Fri Dec 16 21:05:07 2011
> @@ -199,6 +199,8 @@ svn_client__repos_location_segments(apr_
>
>    Use the authentication baton cached in CTX to authenticate against
>    the repository.  Use POOL for all allocations.
> +
> +   See also svn_client__youngest_common_ancestor().
>  */
>  svn_error_t *
>  svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
>
> Modified: subversion/trunk/subversion/libsvn_client/ra.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/ra.c?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_client/ra.c (original)
> +++ subversion/trunk/subversion/libsvn_client/ra.c Fri Dec 16 21:05:07 2011
> @@ -897,3 +897,36 @@ svn_client__get_youngest_common_ancestor
>     *ancestor_revision = yc_revision;
>   return SVN_NO_ERROR;
>  }
> +
> +svn_error_t *
> +svn_client__youngest_common_ancestor(const char **ancestor_url,
> +                                     svn_revnum_t *ancestor_rev,
> +                                     const char *path_or_url1,
> +                                     const svn_opt_revision_t *revision1,
> +                                     const char *path_or_url2,
> +                                     const svn_opt_revision_t *revision2,
> +                                     svn_client_ctx_t *ctx,
> +                                     apr_pool_t *result_pool,
> +                                     apr_pool_t *scratch_pool)
> +{
> +  apr_pool_t *sesspool = svn_pool_create(scratch_pool);
> +  svn_ra_session_t *session;
> +  const char *url1, *url2;
> +  svn_revnum_t rev1, rev2;
> +
> +  /* Resolve the two locations */
> +  SVN_ERR(svn_client__ra_session_from_path(&session, &rev1, &url1,
> +                                           path_or_url1, NULL,
> +                                           revision1, revision1,
> +                                           ctx, sesspool));
> +  SVN_ERR(resolve_rev_and_url(&rev2, &url2, session,
> +                              path_or_url2, revision2, revision2,
> +                              ctx, scratch_pool));
> +
> +  SVN_ERR(svn_client__get_youngest_common_ancestor(
> +            NULL, ancestor_url, ancestor_rev,
> +            url1, rev1, url2, rev2, ctx, result_pool));
> +
> +  svn_pool_destroy(sesspool);
> +  return SVN_NO_ERROR;
> +}
>
> Modified: subversion/trunk/subversion/svn/cl.h
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/svn/cl.h (original)
> +++ subversion/trunk/subversion/svn/cl.h Fri Dec 16 21:05:07 2011
> @@ -822,6 +822,23 @@ svn_cl__local_style_skip_ancestor(const
>                                   const char *path,
>                                   apr_pool_t *pool);
>
> +/* Check that PATH_OR_URL1_at_REVISION1 is related to PATH_OR_URL2_at_REVISION2.
> + * Raise an error if not.
> + *
> + * ### Ideally we would also check that they are on different lines of
> + * history.  That is easy in common cases, but to give a correct answer in
> + * general we need to know the operative revision(s) as well.  For example,
> + * when one location is the branch point from which the other branch was
> + * copied.
> + */
> +svn_error_t *
> +svn_cl__check_related_source_and_target(const char *path_or_url1,
> +                                        const svn_opt_revision_t *revision1,
> +                                        const char *path_or_url2,
> +                                        const svn_opt_revision_t *revision2,
> +                                        svn_client_ctx_t *ctx,
> +                                        apr_pool_t *pool);
> +
>  #ifdef __cplusplus
>  }
>  #endif /* __cplusplus */
>
> Modified: subversion/trunk/subversion/svn/merge-cmd.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/merge-cmd.c?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/svn/merge-cmd.c (original)
> +++ subversion/trunk/subversion/svn/merge-cmd.c Fri Dec 16 21:05:07 2011
> @@ -112,6 +112,7 @@ svn_cl__merge(apr_getopt_t *os,
>   svn_opt_revision_t first_range_start, first_range_end, peg_revision1,
>     peg_revision2;
>   apr_array_header_t *options, *ranges_to_merge = opt_state->revision_ranges;
> +  svn_opt_revision_t unspecified = { svn_opt_revision_unspecified, { 0 } };
>
>   /* Merge doesn't support specifying a revision or revision range
>      when using --reintegrate. */
> @@ -347,6 +348,11 @@ svn_cl__merge(apr_getopt_t *os,
>
>   if (opt_state->reintegrate)
>     {
> +      SVN_ERR_W(svn_cl__check_related_source_and_target(
> +                  sourcepath1, &peg_revision1, targetpath, &unspecified,
> +                  ctx, pool),
> +                _("Source and target must be different but related branches"));
> +
>       err = merge_reintegrate(sourcepath1, &peg_revision1, targetpath,
>                               opt_state->dry_run, options, ctx, pool);
>     }
> @@ -364,6 +370,12 @@ svn_cl__merge(apr_getopt_t *os,
>           range->start.value.number = 1;
>           range->end = peg_revision1;
>           APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) = range;
> +
> +          /* This must be a 'sync' merge so check branch relationship. */
> +          SVN_ERR_W(svn_cl__check_related_source_and_target(
> +                      sourcepath1, &peg_revision1, targetpath, &unspecified,
> +                      ctx, pool),
> +                _("Source and target must be different but related branches"));
>         }
>
>       err = svn_client_merge_peg4(sourcepath1,
>
> Modified: subversion/trunk/subversion/svn/mergeinfo-cmd.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/mergeinfo-cmd.c?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/svn/mergeinfo-cmd.c (original)
> +++ subversion/trunk/subversion/svn/mergeinfo-cmd.c Fri Dec 16 21:05:07 2011
> @@ -114,6 +114,11 @@ svn_cl__mergeinfo(apr_getopt_t *os,
>         tgt_peg_revision.kind = svn_opt_revision_base;
>     }
>
> +  SVN_ERR_W(svn_cl__check_related_source_and_target(source, &src_peg_revision,
> +                                                    target, &tgt_peg_revision,
> +                                                    ctx, pool),
> +            _("Source and target must be different but related branches"));
> +
>   /* Do the real work, depending on the requested data flavor. */
>   if (opt_state->show_revs == svn_cl__show_revs_merged)
>     {
>
> Modified: subversion/trunk/subversion/svn/util.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/util.c?rev=1215273&r1=1215272&r2=1215273&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/svn/util.c (original)
> +++ subversion/trunk/subversion/svn/util.c Fri Dec 16 21:05:07 2011
> @@ -1423,3 +1423,43 @@ svn_cl__local_style_skip_ancestor(const
>
>   return svn_dirent_local_style(relpath ? relpath : path, pool);
>  }
> +
> +/* Return a string of the form "PATH_OR_URL_at_REVISION". */
> +static const char *
> +path_for_display(const char *path_or_url,
> +                 const svn_opt_revision_t *revision,
> +                 apr_pool_t *pool)
> +{
> +  const char *rev_str = svn_opt__revision_to_string(revision, pool);
> +
> +  if (! svn_path_is_url(path_or_url))
> +    path_or_url = svn_dirent_local_style(path_or_url, pool);
> +  return apr_psprintf(pool, "%s@%s", path_or_url, rev_str);
> +}
> +
> +svn_error_t *
> +svn_cl__check_related_source_and_target(const char *path_or_url1,
> +                                        const svn_opt_revision_t *revision1,
> +                                        const char *path_or_url2,
> +                                        const svn_opt_revision_t *revision2,
> +                                        svn_client_ctx_t *ctx,
> +                                        apr_pool_t *pool)
> +{
> +  const char *ancestor_url;
> +  svn_revnum_t ancestor_rev;
> +
> +  SVN_ERR(svn_client__youngest_common_ancestor(
> +            &ancestor_url, &ancestor_rev,
> +            path_or_url1, revision1, path_or_url2, revision2,
> +            ctx, pool, pool));
> +
> +  if (ancestor_url == NULL)
> +    {
> +      return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
> +                               _("Source and target have no common ancestor: "
> +                                 "'%s' and '%s'"),
> +                               path_for_display(path_or_url1, revision1, pool),
> +                               path_for_display(path_or_url2, revision2, pool));
> +    }
> +  return SVN_NO_ERROR;
> +}
>
>

-- 
uberSVN: Apache Subversion Made Easy
http://www.uberSVN.com/
Received on 2011-12-16 22:44:46 CET

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.