subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pbu...@apache.org
Subject svn commit: r1130690 - in /subversion/trunk/subversion: include/svn_error_codes.h libsvn_client/merge.c libsvn_client/mergeinfo.c libsvn_client/mergeinfo.h svn/merge-cmd.c
Date Thu, 02 Jun 2011 17:50:16 GMT
Author: pburba
Date: Thu Jun  2 17:50:15 2011
New Revision: 1130690

URL: http://svn.apache.org/viewvc?rev=1130690&view=rev
Log:
Last fix for issue #3896 'mergeinfo syntax errors should be treated
gracefully': Tolerate invalid mergeinfo on the client side to the extent
possible.

This allows 'svn mergeinfo' to function in the presence of of invalid
mergeinfo in the working copy.  It also allows 'svn merge' to function if
invalid mergeinfo is inherited by a merge target from within the working
copy.  In both cases the invalid mergeinfo is treated as if it doesn't exist.

Merge tracking aware merges still fail if the merge target or one of its
subtrees has invalid mergeinfo, but a more precise error is now raised
describing the offending paths and allowing the client to recommend a
course of action. 

* subversion/include/svn_error_codes.h

  (SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING): New error code
   describing a more precise type of SVN_ERR_MERGEINFO_PARSE_ERROR, i.e.
   that invalid mergeinfo exists in a merge target and cannot be parsed, so
   merge-tracking is not possible.  Clients can use this to make suggestions
   as to how to fix the problem.

* subversion/libsvn_client/merge.c

  (update_wc_mergeinfo): Update call to svn_client__get_wc_mergeinfo(),
   keeping existing intolerance for invalid mergeinfo.

  (get_mergeinfo_paths): Wrap any SVN_ERR_MERGEINFO_PARSE_ERROR errors
   in the new SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING error
   and add the offending path to the error message.  Update call to
   svn_client__get_wc_mergeinfo(), keeping existing intolerance for
   invalid mergeinfo when handling switched subtrees.

  (do_file_merge): Wrap any SVN_ERR_MERGEINFO_PARSE_ERROR errors
   in the new SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING error
   and add the offending path to the error message.

  (process_children_with_new_mergeinfo,
   record_mergeinfo_for_added_subtrees,
   svn_client__elide_mergeinfo): Update calls to
   svn_client__get_wc_mergeinfo(), keeping existing intolerance for
   invalid mergeinfo.

* subversion/libsvn_client/mergeinfo.h

  (svn_client__get_wc_mergeinfo,
   svn_client__get_wc_mergeinfo_catalog,
   svn_client__get_wc_or_repos_mergeinfo_catalog): Add new argument to
   optionally ignore invalid mergeinfo

* subversion/libsvn_client/mergeinfo.c

  (svn_client__get_wc_mergeinfo): Add new argument to optionally ignore
   explicit invalid mergeinfo on the target.  Ignore inherited invalid
   mergeinfo by default.

  (svn_client__get_wc_mergeinfo_catalog): Add new argument to optionally
   ignore invalid mergeinfo.  Pass it along to
   svn_client__get_wc_mergeinfo().

  (svn_client__get_wc_or_repos_mergeinfo): Update call to
   svn_client__get_wc_or_repos_mergeinfo_catalog(), keeping existing
   intolerance for invalid mergeinfo.

  (svn_client__get_wc_or_repos_mergeinfo_catalog): Add new argument to
   optionally ignore invalid mergeinfo.  Pass it along to
   svn_client__get_wc_mergeinfo_catalog().

  (get_mergeinfo): Add new argument to optionally ignore invalid mergeinfo.
   Pass it along to svn_client__get_wc_or_repos_mergeinfo_catalog().

  (svn_client_mergeinfo_get_merged): Update call to get_mergeinfo(), keeping
   existing intolerance for invalid mergeinfo.

  (svn_client_mergeinfo_log,
   svn_client_suggest_merge_sources): Update calls to get_mergeinfo(),
   tolerating invalid mergeinfo.  Note: Both these APIs date back to 1.5.
   We no longer use either so leaving both with the earlier behavior (for
   now).

* subversion/svn/merge-cmd.c

  (svn_cl__merge): If 'svn merge' blows up due to invalid mergeinfo in the
   merge target, then offer some advice on how to address this.

Modified:
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.h
    subversion/trunk/subversion/svn/merge-cmd.c

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1130690&r1=1130689&r2=1130690&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Thu Jun  2 17:50:15 2011
@@ -1201,6 +1201,11 @@ SVN_ERROR_START
              SVN_ERR_CLIENT_CATEGORY_START + 20,
              "Working copy and merge source not ready for reintegration")
 
+  /** @since New in 1.7. */
+  SVN_ERRDEF(SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING,
+             SVN_ERR_CLIENT_CATEGORY_START + 21,
+             "Invalid mergeinfo detected in merge target")
+
   /* misc errors */
 
   SVN_ERRDEF(SVN_ERR_BASE,

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1130690&r1=1130689&r2=1130690&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Jun  2 17:50:15 2011
@@ -4487,7 +4487,7 @@ update_wc_mergeinfo(svn_mergeinfo_catalo
           SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, &inherited,
                                                svn_mergeinfo_nearest_ancestor,
                                                local_abspath, NULL, NULL,
-                                               ctx, iterpool, iterpool));
+                                               FALSE, ctx, iterpool, iterpool));
         }
 
       if (mergeinfo == NULL)
@@ -5646,6 +5646,7 @@ get_mergeinfo_paths(apr_array_header_t *
            hi;
            hi = apr_hash_next(hi))
         {
+          svn_error_t *err;
           svn_mergeinfo_t child_pre_merge_mergeinfo;
           const char *wc_path = svn__apr_hash_index_key(hi);
           svn_string_t *mergeinfo_string = svn__apr_hash_index_val(hi);
@@ -5654,9 +5655,20 @@ get_mergeinfo_paths(apr_array_header_t *
 
           svn_pool_clear(iterpool);
           mergeinfo_child->abspath = apr_pstrdup(result_pool, wc_path);
-          SVN_ERR(svn_mergeinfo_parse(&child_pre_merge_mergeinfo,
-                                      mergeinfo_string->data, result_pool));
-
+          err = svn_mergeinfo_parse(&child_pre_merge_mergeinfo,
+                                    mergeinfo_string->data, result_pool);
+          if (err)
+            {
+              if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
+                {
+                  err = svn_error_createf(
+                    SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
+                    _("Invalid mergeinfo detected on '%s', "
+                      "mergetracking not possible"),
+                    svn_path_local_style(wc_path, scratch_pool));
+                }
+              return svn_error_return(err);
+            }
           /* Stash this child's pre-existing mergeinfo. */
           mergeinfo_child->pre_merge_mergeinfo = child_pre_merge_mergeinfo;
 
@@ -6006,7 +6018,7 @@ get_mergeinfo_paths(apr_array_header_t *
                         &mergeinfo, &inherited,
                         svn_mergeinfo_nearest_ancestor,
                         child_of_noninheritable->abspath,
-                        merge_cmd_baton->target_abspath, NULL,
+                        merge_cmd_baton->target_abspath, NULL, FALSE,
                         merge_cmd_baton->ctx, iterpool, iterpool));
 
                       SVN_ERR(svn_client__record_wc_mergeinfo(
@@ -6684,6 +6696,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
   range.inheritable = TRUE;
   if (honor_mergeinfo)
     {
+      svn_error_t *err;
       const char *source_root_url;
       merge_target = apr_pcalloc(scratch_pool, sizeof(*merge_target));
       merge_target->abspath = target_abspath;
@@ -6700,13 +6713,26 @@ do_file_merge(svn_mergeinfo_catalog_t re
          working copy target URL). */
       SVN_ERR(svn_ra_reparent(merge_b->ra_session1, target_url,
                               iterpool));
-      SVN_ERR(get_full_mergeinfo(&target_mergeinfo,
-                                 &(merge_target->implicit_mergeinfo),
-                                 &indirect, svn_mergeinfo_inherited,
-                                 merge_b->ra_session1, target_abspath,
-                                 MAX(revision1, revision2),
-                                 0, /* Get all implicit mergeinfo */
-                                 ctx, scratch_pool, iterpool));
+      err = get_full_mergeinfo(&target_mergeinfo,
+                               &(merge_target->implicit_mergeinfo),
+                               &indirect, svn_mergeinfo_inherited,
+                               merge_b->ra_session1, target_abspath,
+                               MAX(revision1, revision2),
+                               0, /* Get all implicit mergeinfo */
+                               ctx, scratch_pool, iterpool);
+
+      if (err)
+        {
+          if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
+            {
+              err = svn_error_createf(
+                SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
+                _("Invalid mergeinfo detected on merge target '%s', "
+                  "mergetracking not possible"),
+                svn_path_local_style(target_abspath, scratch_pool));
+            }
+          return svn_error_return(err);
+        }
 
       SVN_ERR(svn_ra_reparent(merge_b->ra_session1, url1, iterpool));
 
@@ -7040,7 +7066,7 @@ process_children_with_new_mergeinfo(merg
                                            &indirect,
                                            svn_mergeinfo_explicit,
                                            abspath_with_new_mergeinfo,
-                                           NULL, NULL,
+                                           NULL, NULL, FALSE,
                                            merge_b->ctx,
                                            iterpool, iterpool));
       /* ...there *should* always be explicit mergeinfo at this point
@@ -7651,7 +7677,7 @@ record_mergeinfo_for_added_subtrees(
          mergeinfo? */
       SVN_ERR(svn_client__get_wc_mergeinfo(&parent_mergeinfo, &inherited,
                                            svn_mergeinfo_explicit,
-                                           dir_abspath, NULL, NULL,
+                                           dir_abspath, NULL, NULL, FALSE,
                                            merge_b->ctx,
                                            iterpool, iterpool));
       if (svn_mergeinfo__is_noninheritable(parent_mergeinfo, iterpool))
@@ -7700,7 +7726,7 @@ record_mergeinfo_for_added_subtrees(
           SVN_ERR(svn_client__get_wc_mergeinfo(
             &added_path_mergeinfo, &inherited,
             svn_mergeinfo_explicit, added_abspath,
-            NULL, NULL, merge_b->ctx, iterpool, iterpool));
+            NULL, NULL, FALSE, merge_b->ctx, iterpool, iterpool));
 
           /* Combine the explict mergeinfo on the added path (if any)
              with the mergeinfo for this merge. */

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1130690&r1=1130689&r2=1130690&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Thu Jun  2 17:50:15 2011
@@ -176,6 +176,7 @@ svn_client__get_wc_mergeinfo(svn_mergein
                              const char *local_abspath,
                              const char *limit_abspath,
                              const char **walked_path,
+                             svn_boolean_t ignore_invalid_mergeinfo,
                              svn_client_ctx_t *ctx,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
@@ -211,9 +212,23 @@ svn_client__get_wc_mergeinfo(svn_mergein
              we encounter either (a) an unversioned directory, or
              (b) mergeinfo.  If we encounter (b), use that inherited
              mergeinfo as our baseline. */
-          SVN_ERR(svn_client__parse_mergeinfo(&wc_mergeinfo, ctx->wc_ctx,
-                                              local_abspath, result_pool,
-                                              iterpool));
+          svn_error_t *err = svn_client__parse_mergeinfo(&wc_mergeinfo,
+                                                         ctx->wc_ctx,
+                                                         local_abspath,
+                                                         result_pool,
+                                                         iterpool);
+          if ((ignore_invalid_mergeinfo || walk_relpath [0] != '\0')
+              && err
+              && err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
+            {
+              svn_error_clear(err);
+              wc_mergeinfo = apr_hash_make(result_pool);
+              break;
+            }
+          else
+            {
+              SVN_ERR(err);
+            }
         }
 
       if (wc_mergeinfo == NULL &&
@@ -318,6 +333,7 @@ svn_client__get_wc_mergeinfo_catalog(svn
                                      const char *local_abspath,
                                      const char *limit_path,
                                      const char **walked_path,
+                                     svn_boolean_t ignore_invalid_mergeinfo,
                                      svn_client_ctx_t *ctx,
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool)
@@ -351,8 +367,8 @@ svn_client__get_wc_mergeinfo_catalog(svn
      *WALKED_PATH. */
   SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, inherited, inherit,
                                        local_abspath, limit_path,
-                                       walked_path, ctx, result_pool,
-                                       scratch_pool));
+                                       walked_path, ignore_invalid_mergeinfo,
+                                       ctx, result_pool, scratch_pool));
 
   /* Add any explicit/inherited mergeinfo for LOCAL_ABSPATH to
      *MERGEINFO_CAT. */
@@ -502,7 +518,8 @@ svn_client__get_wc_or_repos_mergeinfo(sv
   SVN_ERR(svn_client__get_wc_or_repos_mergeinfo_catalog(&tgt_mergeinfo_cat,
                                                         indirect, FALSE,
                                                         repos_only,
-                                                        inherit, ra_session,
+                                                        FALSE, inherit,
+                                                        ra_session,
                                                         target_wcpath, ctx,
                                                         pool, pool));
   if (tgt_mergeinfo_cat && apr_hash_count(tgt_mergeinfo_cat))
@@ -526,6 +543,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   svn_boolean_t *indirect,
   svn_boolean_t include_descendants,
   svn_boolean_t repos_only,
+  svn_boolean_t ignore_invalid_mergeinfo,
   svn_mergeinfo_inheritance_t inherit,
   svn_ra_session_t *ra_session,
   const char *target_wcpath,
@@ -564,7 +582,9 @@ svn_client__get_wc_or_repos_mergeinfo_ca
                                                  include_descendants,
                                                  inherit,
                                                  local_abspath,
-                                                 NULL, NULL, ctx,
+                                                 NULL, NULL,
+                                                 ignore_invalid_mergeinfo,
+                                                 ctx,
                                                  result_pool, scratch_pool));
 
   /* If there is no WC mergeinfo check the repository for inherited
@@ -892,7 +912,8 @@ svn_client__elide_mergeinfo(const char *
                                          svn_mergeinfo_inherited,
                                          target_abspath,
                                          limit_abspath,
-                                         &walk_path, ctx, pool, pool);
+                                         &walk_path, FALSE,
+                                         ctx, pool, pool);
       if (err)
         {
           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -919,7 +940,7 @@ svn_client__elide_mergeinfo(const char *
                                          svn_mergeinfo_nearest_ancestor,
                                          target_abspath,
                                          limit_abspath,
-                                         &walk_path, ctx, pool, pool);
+                                         &walk_path, FALSE, ctx, pool, pool);
       if (err)
         {
           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -993,6 +1014,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
               const char *path_or_url,
               const svn_opt_revision_t *peg_revision,
               svn_boolean_t include_descendants,
+              svn_boolean_t ignore_invalid_mergeinfo,
               svn_client_ctx_t *ctx,
               apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
@@ -1089,7 +1111,8 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
       /* Acquire return values. */
       SVN_ERR(svn_client__get_wc_or_repos_mergeinfo_catalog(
         mergeinfo_catalog, &indirect, include_descendants, FALSE,
-        svn_mergeinfo_inherited, ra_session, path_or_url, ctx,
+        ignore_invalid_mergeinfo, svn_mergeinfo_inherited,
+        ra_session, path_or_url, ctx,
         result_pool, scratch_pool));
     }
 
@@ -1580,7 +1603,7 @@ svn_client_mergeinfo_get_merged(apr_hash
   svn_mergeinfo_t mergeinfo;
 
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, ctx, pool, pool));
+                        peg_revision, FALSE, FALSE, ctx, pool, pool));
   if (mergeinfo_cat)
     {
       const char *path_or_url_repos_rel;
@@ -1673,7 +1696,7 @@ svn_client_mergeinfo_log(svn_boolean_t f
   /* This get_mergeinfo() call doubles as a mergeinfo capabilities check. */
   SVN_ERR(get_mergeinfo(&path_or_url_mergeinfo_cat, &repos_root,
                         path_or_url, peg_revision,
-                        depth == svn_depth_infinity,
+                        depth == svn_depth_infinity, TRUE,
                         ctx, scratch_pool, scratch_pool));
 
   if (!svn_path_is_url(path_or_url))
@@ -2061,7 +2084,7 @@ svn_client_suggest_merge_sources(apr_arr
 
   /* ### TODO: Share ra_session batons to improve efficiency? */
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, ctx, pool, pool));
+                        peg_revision, FALSE, FALSE, ctx, pool, pool));
 
   if (mergeinfo_cat && apr_hash_count(mergeinfo_cat))
     {

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.h?rev=1130690&r1=1130689&r2=1130690&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.h Thu Jun  2 17:50:15 2011
@@ -109,7 +109,16 @@ svn_client__merge_path_dup(const svn_cli
    (ignored if NULL) or beyond any switched path.
 
    Set *WALKED_PATH to the path climbed from LOCAL_ABSPATH to find inherited
-   mergeinfo, or "" if none was found. (ignored if NULL). */
+   mergeinfo, or "" if none was found. (ignored if NULL).
+
+   If IGNORE_INVALID_MERGEINFO is true, then syntactically invalid explicit
+   mergeinfo on found on LOCAL_ABSPATH is ignored and *MERGEINFO is set to an
+   empty hash.  If IGNORE_INVALID_MERGEINFO is false, then syntactically
+   invalid explicit mergeinfo on found on LOCAL_ABSPATH results in a
+   SVN_ERR_MERGEINFO_PARSE_ERROR error.  Regardless of
+   IGNORE_INVALID_MERGEINFO, if LOCAL_ABSPATH inherits invalid mergeinfo,
+   then *MERGEINFO is always set to an empty hash and no parse error is
+   raised. */
 svn_error_t *
 svn_client__get_wc_mergeinfo(svn_mergeinfo_t *mergeinfo,
                              svn_boolean_t *inherited,
@@ -117,6 +126,7 @@ svn_client__get_wc_mergeinfo(svn_mergein
                              const char *local_abspath,
                              const char *limit_abspath,
                              const char **walked_path,
+                             svn_boolean_t ignore_invalid_mergeinfo,
                              svn_client_ctx_t *ctx,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
@@ -138,6 +148,7 @@ svn_client__get_wc_mergeinfo_catalog(svn
                                      const char *local_abspath,
                                      const char *limit_path,
                                      const char **walked_path,
+                                     svn_boolean_t ignore_invalid_mergeinfo,
                                      svn_client_ctx_t *ctx,
                                      apr_pool_t *result_pool,
                                      apr_pool_t *scratch_pool);
@@ -253,6 +264,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   svn_boolean_t *indirect,
   svn_boolean_t include_descendants,
   svn_boolean_t repos_only,
+  svn_boolean_t ignore_invalid_mergeinfo,
   svn_mergeinfo_inheritance_t inherit,
   svn_ra_session_t *ra_session,
   const char *target_wcpath,

Modified: subversion/trunk/subversion/svn/merge-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/merge-cmd.c?rev=1130690&r1=1130689&r2=1130690&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/merge-cmd.c (original)
+++ subversion/trunk/subversion/svn/merge-cmd.c Thu Jun  2 17:50:15 2011
@@ -365,8 +365,20 @@ svn_cl__merge(apr_getopt_t *os,
   if (! opt_state->quiet)
     SVN_ERR(svn_cl__print_conflict_stats(ctx->notify_baton2, pool));
 
-  if (err && (! opt_state->reintegrate))
-    return svn_cl__may_need_force(err);
+  if (err)
+    {
+      if(err->apr_err == SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING)
+        {
+          err = svn_error_quick_wrap(
+            err,
+            _("Merge tracking not possible, use --ignore-ancestry or\n"
+              "fix invalid mergeinfo in target with 'svn propset'"));
+        }
+      else if (! opt_state->reintegrate)
+        {
+          return svn_cl__may_need_force(err);      
+        }
+    }
 
   return svn_error_return(err);
 }



Mime
View raw message