Author: julianfoad
Date: Thu Dec 18 17:34:52 2014
New Revision: 1646495

URL: http://svn.apache.org/r1646495
Log:
Introduce mergeinfo rangelist canonicalization functions.

After editing rangelists in mergeinfo, the rangelists need to be returned to
their canonical representation. The mergeinfo documentation states only that
the ranges must be sorted, but adjacent ranges usually should be combined
and at least one test assumes that.

In 'svndumpfilter.c' we were just sorting them without combining adjacent
ranges. (It is probable but not proven that the preceding code can in fact
produce combinable ranges.) In the 'renumber_mergeinfo_revs' functions in
libsvn_repos/load-fs-vtable.c and svnrdump/load_editor.c, we are currently
relying on the following 'filter_mergeinfo_by_ranges' call to combine
adjacent ranges. I plan to get rid of that filtering operation later.

* subversion/include/private/svn_mergeinfo_private.h,
* subversion/libsvn_subr/mergeinfo.c
  (svn_rangelist__canonicalize,
   svn_mergeinfo__canonicalize_ranges): New functions.
  (is_rangelist_normalized): Note the possibility of a false negative result.
  (parse_revision_line): Simplify by using svn_rangelist__canonicalize.

* subversion/svndumpfilter/svndumpfilter.c
  (adjust_mergeinfo): After adjusting mergeinfo, don't just sort it,
    canonicalize it.

Modified:
    subversion/trunk/subversion/include/private/svn_mergeinfo_private.h
    subversion/trunk/subversion/libsvn_subr/mergeinfo.c
    subversion/trunk/subversion/svndumpfilter/svndumpfilter.c

Modified: subversion/trunk/subversion/include/private/svn_mergeinfo_private.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_mergeinfo_private.h?rev=1646495&r1=1646494&r2=1646495&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_mergeinfo_private.h 
(original)
+++ subversion/trunk/subversion/include/private/svn_mergeinfo_private.h Thu Dec 
18 17:34:52 2014
@@ -65,6 +65,27 @@ svn_error_t *
 svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
                                        apr_pool_t *scratch_pool);
 
+/** Canonicalize the @a rangelist: sort the ranges, and combine adjacent or
+ * overlapping ranges into single ranges where possible.
+ *
+ * If overlapping ranges have different inheritability, return an error.
+ *
+ * Modify @a rangelist in place. Use @a scratch_pool for temporary
+ * allocations.
+ */
+svn_error_t *
+svn_rangelist__canonicalize(svn_rangelist_t *rangelist,
+                            apr_pool_t *scratch_pool);
+
+/** Canonicalize the revision range lists in the @a mergeinfo.
+ *
+ * Modify @a mergeinfo in place. Use @a scratch_pool for temporary
+ * allocations.
+ */
+svn_error_t *
+svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo,
+                                   apr_pool_t *scratch_pool);
+
 /* Set inheritability of all rangelists in MERGEINFO to INHERITABLE.
    If MERGEINFO is NULL do nothing.  If a rangelist in MERGEINFO is
    NULL leave it alone. */

Modified: subversion/trunk/subversion/libsvn_subr/mergeinfo.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/mergeinfo.c?rev=1646495&r1=1646494&r2=1646495&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_subr/mergeinfo.c Thu Dec 18 17:34:52 2014
@@ -612,7 +612,12 @@ svn_rangelist__parse(svn_rangelist_t **r
 }
 
 /* Return TRUE, if all ranges in RANGELIST are in ascending order and do
- * not overlap.  If this returns FALSE, you probaly want to qsort() the
+ * not overlap and are not adjacent.
+ *
+ * ### Can yield false negatives: ranges of differing inheritance are
+ * allowed to be adjacent.
+ *
+ * If this returns FALSE, you probaly want to qsort() the
  * ranges and then call svn_rangelist__combine_adjacent_ranges().
  */
 static svn_boolean_t
@@ -629,6 +634,20 @@ is_rangelist_normalized(svn_rangelist_t
 }
 
 svn_error_t *
+svn_rangelist__canonicalize(svn_rangelist_t *rangelist,
+                            apr_pool_t *scratch_pool)
+{
+  if (! is_rangelist_normalized(rangelist))
+    {
+      svn_sort__array(rangelist, svn_sort_compare_ranges);
+
+      SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
                                        apr_pool_t *scratch_pool)
 {
@@ -715,14 +734,9 @@ parse_revision_line(const char **input,
 
   /* Sort the rangelist, combine adjacent ranges into single ranges, and
      make sure there are no overlapping ranges.  Luckily, most data in
-     svn:mergeinfo will already be in normalized form and we can skip this.
+     svn:mergeinfo will already be in normalized form and this will be quick.
    */
-  if (! is_rangelist_normalized(rangelist))
-    {
-      svn_sort__array(rangelist, svn_sort_compare_ranges);
-
-      SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
-    }
+  SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool));
 
   /* Handle any funky mergeinfo with relative merge source paths that
      might exist due to issue #3547.  It's possible that this issue allowed
@@ -1999,6 +2013,22 @@ svn_mergeinfo_sort(svn_mergeinfo_t input
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo,
+                                   apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, mergeinfo); hi; hi = 
apr_hash_next(hi))
+    {
+      apr_array_header_t *rl = apr_hash_this_val(hi);
+
+      SVN_ERR(svn_rangelist__canonicalize(rl, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_mergeinfo_catalog_t
 svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog,
                           apr_pool_t *pool)

Modified: subversion/trunk/subversion/svndumpfilter/svndumpfilter.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svndumpfilter/svndumpfilter.c?rev=1646495&r1=1646494&r2=1646495&view=diff
==============================================================================
--- subversion/trunk/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/trunk/subversion/svndumpfilter/svndumpfilter.c Thu Dec 18 
17:34:52 2014
@@ -859,7 +859,7 @@ adjust_mergeinfo(svn_string_t **final_va
       svn_hash_sets(final_mergeinfo, merge_source, rangelist);
     }
 
-  SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
+  SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
   SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
   svn_pool_destroy(subpool);
 


Reply via email to