You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/10 20:06:33 UTC

svn commit: r984153 [20/39] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hu...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/mergeinfo.c Tue Aug 10 18:06:17 2010
@@ -115,10 +115,20 @@ parse_pathname(const char **input,
   return SVN_NO_ERROR;
 }
 
-/* Ways in which two svn_merge_range_t can intersect, if at all. */
+/* Return TRUE iff (svn_merge_range_t *) RANGE describes a valid, forward
+ * revision range.
+ *
+ * Note: The smallest valid value of RANGE->start is 0 because it is an
+ * exclusive endpoint, being one less than the revision number of the first
+ * change described by the range, and the oldest possible change is "r1" as
+ * there cannot be a change "r0". */
+#define IS_VALID_FORWARD_RANGE(range) \
+  (SVN_IS_VALID_REVNUM((range)->start) && ((range)->start < (range)->end))
+
+/* Ways in which two svn_merge_range_t can intersect or adjoin, if at all. */
 typedef enum
 {
-  /* Ranges don't intersect. */
+  /* Ranges don't intersect and don't adjoin. */
   svn__no_intersection,
 
   /* Ranges are equal. */
@@ -127,7 +137,7 @@ typedef enum
   /* Ranges adjoin but don't overlap. */
   svn__adjoining_intersection,
 
-  /* Ranges overalp but neither is a subset of the other. */
+  /* Ranges overlap but neither is a subset of the other. */
   svn__overlapping_intersection,
 
   /* One range is a proper subset of the other. */
@@ -144,16 +154,8 @@ get_type_of_intersection(const svn_merge
 {
   SVN_ERR_ASSERT(r1);
   SVN_ERR_ASSERT(r2);
-
-  /* Why not use SVN_IS_VALID_REVNUM here?  Because revision 0
-     is described START = -1, END = 0.  See svn_merge_range_t. */
-  SVN_ERR_ASSERT(r1->start >= -1);
-  SVN_ERR_ASSERT(r2->start >= -1);
-
-  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(r1->end));
-  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(r2->end));
-  SVN_ERR_ASSERT(r1->start < r1->end);
-  SVN_ERR_ASSERT(r2->start < r2->end);
+  SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(r1));
+  SVN_ERR_ASSERT(IS_VALID_FORWARD_RANGE(r2));
 
   if (!(r1->start <= r2->end && r2->start <= r1->end))
     *intersection_type = svn__no_intersection;
@@ -457,6 +459,10 @@ range_to_string(const svn_merge_range_t 
 }
 
 /* Helper for svn_mergeinfo_parse()
+   Append revision ranges onto the array RANGELIST to represent the range
+   descriptions found in the string *INPUT.  Read only as far as a newline
+   or the position END, whichever comes first.  Set *INPUT to the position
+   after the last character of INPUT that was used.
 
    revisionlist -> (revisionelement)(COMMA revisionelement)*
    revisionrange -> REVISION "-" REVISION("*")
@@ -501,6 +507,11 @@ parse_rangelist(const char **input, cons
       mrange->end = firstrev;
       mrange->inheritable = TRUE;
 
+      if (firstrev == 0)
+        return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
+                                 _("Invalid revision number '0' found in "
+                                   "range list"));
+
       if (*curr == '-')
         {
           svn_revnum_t secondrev;
@@ -696,7 +707,7 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer
 
 svn_error_t *
 svn_rangelist_merge(apr_array_header_t **rangelist,
-                    apr_array_header_t *changes,
+                    const apr_array_header_t *changes,
                     apr_pool_t *pool)
 {
   int i, j;
@@ -763,20 +774,31 @@ svn_rangelist_merge(apr_array_header_t *
   return SVN_NO_ERROR;
 }
 
+/* Return TRUE iff the forward revision ranges FIRST and SECOND overlap and
+ * (if CONSIDER_INHERITANCE is TRUE) have the same inheritability. */
 static svn_boolean_t
 range_intersect(const svn_merge_range_t *first, const svn_merge_range_t *second,
                 svn_boolean_t consider_inheritance)
 {
+  SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
+  SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+
   return (first->start + 1 <= second->end)
     && (second->start + 1 <= first->end)
     && (!consider_inheritance
         || (!(first->inheritable) == !(second->inheritable)));
 }
 
+/* Return TRUE iff the forward revision range FIRST wholly contains the
+ * forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has
+ * the same inheritability. */
 static svn_boolean_t
 range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second,
                svn_boolean_t consider_inheritance)
 {
+  SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(first));
+  SVN_ERR_ASSERT_NO_RETURN(IS_VALID_FORWARD_RANGE(second));
+
   return (first->start <= second->start) && (second->end <= first->end)
     && (!consider_inheritance
         || (!(first->inheritable) == !(second->inheritable)));
@@ -848,12 +870,7 @@ svn_mergeinfo__set_inheritance(svn_merge
            hi;
            hi = apr_hash_next(hi))
         {
-          apr_array_header_t *rangelist;
-          const void *path;
-          void *val;
-          apr_hash_this(hi, &path, NULL, &val);
-
-          rangelist = apr_hash_get(mergeinfo, path, APR_HASH_KEY_STRING);
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
 
           if (rangelist)
             svn_rangelist__set_inheritance(rangelist, inheritable);
@@ -862,84 +879,126 @@ svn_mergeinfo__set_inheritance(svn_merge
   return;
 }
 
-/* Either remove any overlapping ranges described by ERASER from
-   WHITEBOARD (when DO_REMOVE is TRUE), or capture the overlap, and
-   place the remaining or overlapping ranges in OUTPUT. */
-/*  ### FIXME: Some variables names and inline comments for this method
-    ### are legacy from when it was solely the remove() impl. */
+/* If DO_REMOVE is true, then remove any overlapping ranges described by
+   RANGELIST1 from RANGELIST2 and place the results in *OUTPUT.  When
+   DO_REMOVE is true, RANGELIST1 is effectively the "eraser" and RANGELIST2
+   the "whiteboard".
+
+   If DO_REMOVE is false, then capture the intersection between RANGELIST1
+   and RANGELIST2 and place the results in *OUTPUT.  The ordering of
+   RANGELIST1 and RANGELIST2 doesn't matter when DO_REMOVE is false.
+
+   If CONSIDER_INHERITANCE is true, then take the inheritance of the
+   ranges in RANGELIST1 and RANGELIST2 into account when comparing them
+   for intersection, see the doc string for svn_rangelist_intersection().
+
+   If CONSIDER_INHERITANCE is false, then ranges with differing inheritance
+   may intersect, but the resulting intersection is non-inheritable only
+   if both ranges were non-inheritable, e.g.:
+
+   RANGELIST1  RANGELIST2  CONSIDER     DO_REMOVE  *OUTPUT
+                           INHERITANCE
+   ----------  ------      -----------  ---------  -------
+
+   90-420*     1-100       TRUE         FALSE      Empty Rangelist
+   90-420      1-100*      TRUE         FALSE      Empty Rangelist
+   90-420      1-100       TRUE         FALSE      90-100
+   90-420*     1-100*      TRUE         FALSE      90-100*
+
+   90-420*     1-100       FALSE        FALSE      90-100
+   90-420      1-100*      FALSE        FALSE      90-100
+   90-420      1-100       FALSE        FALSE      90-100
+   90-420*     1-100*      FALSE        FALSE      90-100*
+
+   Allocate the contents of *OUTPUT in POOL. */
 static svn_error_t *
 rangelist_intersect_or_remove(apr_array_header_t **output,
-                              apr_array_header_t *eraser,
-                              apr_array_header_t *whiteboard,
+                              const apr_array_header_t *rangelist1,
+                              const apr_array_header_t *rangelist2,
                               svn_boolean_t do_remove,
                               svn_boolean_t consider_inheritance,
                               apr_pool_t *pool)
 {
-  int i, j, lasti;
-  svn_merge_range_t wboardelt;
+  int i1, i2, lasti2;
+  svn_merge_range_t working_elt2;
 
   *output = apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
 
-  i = 0;
-  j = 0;
-  lasti = -1;  /* Initialized to a value that "i" will never be. */
+  i1 = 0;
+  i2 = 0;
+  lasti2 = -1;  /* Initialized to a value that "i2" will never be. */
 
-  while (i < whiteboard->nelts && j < eraser->nelts)
+  while (i1 < rangelist1->nelts && i2 < rangelist2->nelts)
     {
       svn_merge_range_t *elt1, *elt2;
 
-      elt2 = APR_ARRAY_IDX(eraser, j, svn_merge_range_t *);
+      elt1 = APR_ARRAY_IDX(rangelist1, i1, svn_merge_range_t *);
 
-      /* Instead of making a copy of the entire array of whiteboard
-         elements, we just keep a copy of the current whiteboard element
+      /* Instead of making a copy of the entire array of rangelist2
+         elements, we just keep a copy of the current rangelist2 element
          that needs to be used, and modify our copy if necessary. */
-      if (i != lasti)
+      if (i2 != lasti2)
         {
-          wboardelt = *(APR_ARRAY_IDX(whiteboard, i, svn_merge_range_t *));
-          lasti = i;
+          working_elt2 =
+            *(APR_ARRAY_IDX(rangelist2, i2, svn_merge_range_t *));
+          lasti2 = i2;
         }
 
-      elt1 = &wboardelt;
+      elt2 = &working_elt2;
 
-      /* If the whiteboard range is contained completely in the
-         eraser, we increment the whiteboard.
+      /* If the rangelist2 range is contained completely in the
+         rangelist1, we increment the rangelist2.
          If the ranges intersect, and match exactly, we increment both
-         eraser and whiteboard.
+         rangelist1 and rangelist2.
          Otherwise, we have to generate a range for the left part of
-         the removal of eraser from whiteboard, and possibly change
-         the whiteboard to the remaining portion of the right part of
+         the removal of rangelist1 from rangelist2, and possibly change
+         the rangelist2 to the remaining portion of the right part of
          the removal, to test against. */
-      if (range_contains(elt2, elt1, consider_inheritance))
+      if (range_contains(elt1, elt2, consider_inheritance))
         {
           if (!do_remove)
-            SVN_ERR(combine_with_lastrange(elt1, *output,
-                                           consider_inheritance, pool,
-                                           pool));
+            {
+              svn_merge_range_t tmp_range;
+              tmp_range.start = elt2->start;
+              tmp_range.end = elt2->end;
+              /* The intersection of two ranges is non-inheritable only
+                 if both ranges are non-inheritable. */
+              tmp_range.inheritable =
+                (elt2->inheritable || elt1->inheritable);
+              SVN_ERR(combine_with_lastrange(&tmp_range, *output,
+                                             consider_inheritance, pool,
+                                             pool));
+            }
 
-          i++;
+          i2++;
 
-          if (elt1->start == elt2->start && elt1->end == elt2->end)
-            j++;
+          if (elt2->start == elt1->start && elt2->end == elt1->end)
+            i1++;
         }
-      else if (range_intersect(elt2, elt1, consider_inheritance))
+      else if (range_intersect(elt1, elt2, consider_inheritance))
         {
-          if (elt1->start < elt2->start)
+          if (elt2->start < elt1->start)
             {
-              /* The whiteboard range starts before the eraser range. */
+              /* The rangelist2 range starts before the rangelist1 range. */
               svn_merge_range_t tmp_range;
-              tmp_range.inheritable = elt1->inheritable;
               if (do_remove)
                 {
-                  /* Retain the range that falls before the eraser start. */
-                  tmp_range.start = elt1->start;
-                  tmp_range.end = elt2->start;
+                  /* Retain the range that falls before the rangelist1
+                     start. */
+                  tmp_range.start = elt2->start;
+                  tmp_range.end = elt1->start;
+                  tmp_range.inheritable = elt2->inheritable;
                 }
               else
                 {
-                  /* Retain the range that falls between the eraser
-                     start and whiteboard end. */
-                  tmp_range.start = elt2->start;
-                  tmp_range.end = MIN(elt1->end, elt2->end);
+                  /* Retain the range that falls between the rangelist1
+                     start and rangelist2 end. */
+                  tmp_range.start = elt1->start;
+                  tmp_range.end = MIN(elt2->end, elt1->end);
+                  /* The intersection of two ranges is non-inheritable only
+                     if both ranges are non-inheritable. */
+                  tmp_range.inheritable =
+                    (elt2->inheritable || elt1->inheritable);
                 }
 
               SVN_ERR(combine_with_lastrange(&tmp_range,
@@ -947,40 +1006,43 @@ rangelist_intersect_or_remove(apr_array_
                                              pool, pool));
             }
 
-          /* Set up the rest of the whiteboard range for further
+          /* Set up the rest of the rangelist2 range for further
              processing.  */
-          if (elt1->end > elt2->end)
+          if (elt2->end > elt1->end)
             {
-              /* The whiteboard range ends after the eraser range. */
+              /* The rangelist2 range ends after the rangelist1 range. */
               if (!do_remove)
                 {
                   /* Partial overlap. */
                   svn_merge_range_t tmp_range;
-                  tmp_range.start = MAX(elt1->start, elt2->start);
-                  tmp_range.end = elt2->end;
-                  tmp_range.inheritable = elt1->inheritable;
+                  tmp_range.start = MAX(elt2->start, elt1->start);
+                  tmp_range.end = elt1->end;
+                  /* The intersection of two ranges is non-inheritable only
+                     if both ranges are non-inheritable. */
+                  tmp_range.inheritable =
+                    (elt2->inheritable || elt1->inheritable);
                   SVN_ERR(combine_with_lastrange(&tmp_range,
                                                  *output,
                                                  consider_inheritance,
                                                  pool, pool));
                 }
 
-              wboardelt.start = elt2->end;
-              wboardelt.end = elt1->end;
+              working_elt2.start = elt1->end;
+              working_elt2.end = elt2->end;
             }
           else
-            i++;
+            i2++;
         }
       else  /* ranges don't intersect */
         {
-          /* See which side of the whiteboard the eraser is on.  If it
-             is on the left side, we need to move the eraser.
+          /* See which side of the rangelist2 the rangelist1 is on.  If it
+             is on the left side, we need to move the rangelist1.
 
-             If it is on past the whiteboard on the right side, we
-             need to output the whiteboard and increment the
-             whiteboard.  */
-          if (svn_sort_compare_ranges(&elt2, &elt1) < 0)
-            j++;
+             If it is on past the rangelist2 on the right side, we
+             need to output the rangelist2 and increment the
+             rangelist2.  */
+          if (svn_sort_compare_ranges(&elt1, &elt2) < 0)
+            i1++;
           else
             {
               svn_merge_range_t *lastrange;
@@ -992,36 +1054,36 @@ rangelist_intersect_or_remove(apr_array_
                 lastrange = NULL;
 
               if (do_remove && !(lastrange &&
-                                 combine_ranges(lastrange, lastrange, elt1,
+                                 combine_ranges(lastrange, lastrange, elt2,
                                                 consider_inheritance)))
                 {
-                  lastrange = svn_merge_range_dup(elt1, pool);
+                  lastrange = svn_merge_range_dup(elt2, pool);
                   APR_ARRAY_PUSH(*output, svn_merge_range_t *) = lastrange;
                 }
-              i++;
+              i2++;
             }
         }
     }
 
   if (do_remove)
     {
-      /* Copy the current whiteboard element if we didn't hit the end
-         of the whiteboard, and we still had it around.  This element
-         may have been touched, so we can't just walk the whiteboard
+      /* Copy the current rangelist2 element if we didn't hit the end
+         of the rangelist2, and we still had it around.  This element
+         may have been touched, so we can't just walk the rangelist2
          array, we have to use our copy.  This case only happens when
-         we ran out of eraser before whiteboard, *and* we had changed
-         the whiteboard element. */
-      if (i == lasti && i < whiteboard->nelts)
+         we ran out of rangelist1 before rangelist2, *and* we had changed
+         the rangelist2 element. */
+      if (i2 == lasti2 && i2 < rangelist2->nelts)
         {
-          SVN_ERR(combine_with_lastrange(&wboardelt, *output,
+          SVN_ERR(combine_with_lastrange(&working_elt2, *output,
                                          consider_inheritance, pool, pool));
-          i++;
+          i2++;
         }
 
-      /* Copy any other remaining untouched whiteboard elements.  */
-      for (; i < whiteboard->nelts; i++)
+      /* Copy any other remaining untouched rangelist2 elements.  */
+      for (; i2 < rangelist2->nelts; i2++)
         {
-          svn_merge_range_t *elt = APR_ARRAY_IDX(whiteboard, i,
+          svn_merge_range_t *elt = APR_ARRAY_IDX(rangelist2, i2,
                                                  svn_merge_range_t *);
 
           SVN_ERR(combine_with_lastrange(elt, *output,
@@ -1035,8 +1097,8 @@ rangelist_intersect_or_remove(apr_array_
 
 svn_error_t *
 svn_rangelist_intersect(apr_array_header_t **output,
-                        apr_array_header_t *rangelist1,
-                        apr_array_header_t *rangelist2,
+                        const apr_array_header_t *rangelist1,
+                        const apr_array_header_t *rangelist2,
                         svn_boolean_t consider_inheritance,
                         apr_pool_t *pool)
 {
@@ -1046,8 +1108,8 @@ svn_rangelist_intersect(apr_array_header
 
 svn_error_t *
 svn_rangelist_remove(apr_array_header_t **output,
-                     apr_array_header_t *eraser,
-                     apr_array_header_t *whiteboard,
+                     const apr_array_header_t *eraser,
+                     const apr_array_header_t *whiteboard,
                      svn_boolean_t consider_inheritance,
                      apr_pool_t *pool)
 {
@@ -1057,7 +1119,7 @@ svn_rangelist_remove(apr_array_header_t 
 
 svn_error_t *
 svn_rangelist_diff(apr_array_header_t **deleted, apr_array_header_t **added,
-                   apr_array_header_t *from, apr_array_header_t *to,
+                   const apr_array_header_t *from, const apr_array_header_t *to,
                    svn_boolean_t consider_inheritance,
                    apr_pool_t *pool)
 {
@@ -1295,7 +1357,7 @@ svn_error_t *
 svn_mergeinfo_intersect2(svn_mergeinfo_t *mergeinfo,
                          svn_mergeinfo_t mergeinfo1,
                          svn_mergeinfo_t mergeinfo2,
-                         svn_boolean_t consider_ineheritance,
+                         svn_boolean_t consider_inheritance,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
@@ -1311,23 +1373,20 @@ svn_mergeinfo_intersect2(svn_mergeinfo_t
   for (hi = apr_hash_first(apr_hash_pool_get(mergeinfo1), mergeinfo1);
        hi; hi = apr_hash_next(hi))
     {
-      apr_array_header_t *rangelist;
-      const void *path;
-      void *val;
-      apr_hash_this(hi, &path, NULL, &val);
-
-      rangelist = apr_hash_get(mergeinfo2, path, APR_HASH_KEY_STRING);
-      if (rangelist)
-        {
-          SVN_ERR(svn_rangelist_intersect(&rangelist,
-                                          (apr_array_header_t *) val,
-                                          rangelist, consider_ineheritance,
-                                          scratch_pool));
-          if (rangelist->nelts > 0)
+      const char *path = svn__apr_hash_index_key(hi);
+      apr_array_header_t *rangelist1 = svn__apr_hash_index_val(hi);
+      apr_array_header_t *rangelist2;
+
+      rangelist2 = apr_hash_get(mergeinfo2, path, APR_HASH_KEY_STRING);
+      if (rangelist2)
+        {
+          SVN_ERR(svn_rangelist_intersect(&rangelist2, rangelist1, rangelist2,
+                                          consider_inheritance, scratch_pool));
+          if (rangelist2->nelts > 0)
             apr_hash_set(*mergeinfo,
                          apr_pstrdup(result_pool, path),
                          APR_HASH_KEY_STRING,
-                         svn_rangelist_dup(rangelist, result_pool));
+                         svn_rangelist_dup(rangelist2, result_pool));
         }
     }
   return SVN_NO_ERROR;
@@ -1345,13 +1404,13 @@ svn_error_t *
 svn_mergeinfo_remove2(svn_mergeinfo_t *mergeinfo,
                       svn_mergeinfo_t eraser,
                       svn_mergeinfo_t whiteboard,
-                      svn_boolean_t consider_ineritance,
+                      svn_boolean_t consider_inheritance,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
   *mergeinfo = apr_hash_make(result_pool);
   return walk_mergeinfo_hash_for_diff(whiteboard, eraser, *mergeinfo, NULL,
-                                      consider_ineritance, result_pool,
+                                      consider_inheritance, result_pool,
                                       scratch_pool);
 }
 
@@ -1447,14 +1506,11 @@ svn_error_t *
 svn_mergeinfo_sort(svn_mergeinfo_t input, apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  void *val;
 
   for (hi = apr_hash_first(pool, input); hi; hi = apr_hash_next(hi))
     {
-      apr_array_header_t *rl;
-      apr_hash_this(hi, NULL, NULL, &val);
+      apr_array_header_t *rl = svn__apr_hash_index_val(hi);
 
-      rl = val;
       qsort(rl->elts, rl->nelts, rl->elt_size, svn_sort_compare_ranges);
     }
   return SVN_NO_ERROR;
@@ -1471,9 +1527,9 @@ svn_mergeinfo_catalog_dup(svn_mergeinfo_
        hi;
        hi = apr_hash_next(hi))
     {
-      const void *key;
-      void *val;
-      apr_hash_this(hi, &key, NULL, &val);
+      const char *key = svn__apr_hash_index_key(hi);
+      svn_mergeinfo_t val = svn__apr_hash_index_val(hi);
+
       apr_hash_set(new_mergeinfo_catalog,
                    apr_pstrdup(pool, key),
                    APR_HASH_KEY_STRING,
@@ -1488,15 +1544,15 @@ svn_mergeinfo_dup(svn_mergeinfo_t mergei
 {
   svn_mergeinfo_t new_mergeinfo = apr_hash_make(pool);
   apr_hash_index_t *hi;
-  const void *path;
-  apr_ssize_t pathlen;
-  void *rangelist;
 
   for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
     {
-      apr_hash_this(hi, &path, &pathlen, &rangelist);
+      const char *path = svn__apr_hash_index_key(hi);
+      apr_ssize_t pathlen = svn__apr_hash_index_klen(hi);
+      apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+
       apr_hash_set(new_mergeinfo, apr_pstrmemdup(pool, path, pathlen), pathlen,
-                   svn_rangelist_dup((apr_array_header_t *) rangelist, pool));
+                   svn_rangelist_dup(rangelist, pool));
     }
 
   return new_mergeinfo;
@@ -1513,25 +1569,23 @@ svn_mergeinfo_inheritable2(svn_mergeinfo
                            apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
-  const void *key;
-  apr_ssize_t keylen;
-  void *rangelist;
-
   svn_mergeinfo_t inheritable_mergeinfo = apr_hash_make(result_pool);
+
   for (hi = apr_hash_first(scratch_pool, mergeinfo);
        hi;
        hi = apr_hash_next(hi))
     {
+      const char *key = svn__apr_hash_index_key(hi);
+      apr_ssize_t keylen = svn__apr_hash_index_klen(hi);
+      apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
       apr_array_header_t *inheritable_rangelist;
-      apr_hash_this(hi, &key, &keylen, &rangelist);
-      if (!path || svn_path_compare_paths(path, (const char *)key) == 0)
-        SVN_ERR(svn_rangelist_inheritable2(&inheritable_rangelist,
-                                           (apr_array_header_t *) rangelist,
+
+      if (!path || svn_path_compare_paths(path, key) == 0)
+        SVN_ERR(svn_rangelist_inheritable2(&inheritable_rangelist, rangelist,
                                            start, end, inheritable,
                                            result_pool, scratch_pool));
       else
-        inheritable_rangelist =
-          svn_rangelist_dup((apr_array_header_t *)rangelist, result_pool);
+        inheritable_rangelist = svn_rangelist_dup(rangelist, result_pool);
 
       /* Only add this rangelist if some ranges remain.  A rangelist with
          a path mapped to an empty rangelist is not syntactically valid */
@@ -1544,47 +1598,10 @@ svn_mergeinfo_inheritable2(svn_mergeinfo
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_mergeinfo_inheritable(svn_mergeinfo_t *output,
-                          svn_mergeinfo_t mergeinfo,
-                          const char *path,
-                          svn_revnum_t start,
-                          svn_revnum_t end,
-                          apr_pool_t *pool)
-{
-  apr_hash_index_t *hi;
-  const void *key;
-  apr_ssize_t keylen;
-  void *rangelist;
-
-  svn_mergeinfo_t inheritable_mergeinfo = apr_hash_make(pool);
-  for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
-    {
-      apr_array_header_t *inheritable_rangelist;
-      apr_hash_this(hi, &key, &keylen, &rangelist);
-      if (!path || svn_path_compare_paths(path, (const char *)key) == 0)
-        SVN_ERR(svn_rangelist_inheritable(&inheritable_rangelist,
-                                          (apr_array_header_t *) rangelist,
-                                          start, end, pool));
-      else
-        inheritable_rangelist =
-          svn_rangelist_dup((apr_array_header_t *)rangelist, pool);
-
-      /* Only add this rangelist if some ranges remain.  A rangelist with
-         a path mapped to an empty rangelist is not syntactically valid */
-      if (inheritable_rangelist->nelts)
-        apr_hash_set(inheritable_mergeinfo,
-                     apr_pstrmemdup(pool, key, keylen), keylen,
-                     inheritable_rangelist);
-    }
-  *output = inheritable_mergeinfo;
-  return SVN_NO_ERROR;
-}
-
 
 svn_error_t *
 svn_rangelist_inheritable2(apr_array_header_t **inheritable_rangelist,
-                           apr_array_header_t *rangelist,
+                           const apr_array_header_t *rangelist,
                            svn_revnum_t start,
                            svn_revnum_t end,
                            svn_boolean_t inheritable,
@@ -1622,13 +1639,7 @@ svn_rangelist_inheritable2(apr_array_hea
           /* We want only the non-inheritable ranges bound by START
              and END removed. */
           apr_array_header_t *ranges_inheritable =
-            apr_array_make(scratch_pool, 0, sizeof(svn_merge_range_t *));
-          svn_merge_range_t *range = apr_palloc(scratch_pool, sizeof(*range));
-
-          range->start = start;
-          range->end = end;
-          range->inheritable = inheritable;
-          APR_ARRAY_PUSH(ranges_inheritable, svn_merge_range_t *) = range;
+            svn_rangelist__initialize(start, end, inheritable, scratch_pool);
 
           if (rangelist->nelts)
             SVN_ERR(svn_rangelist_remove(inheritable_rangelist,
@@ -1641,17 +1652,6 @@ svn_rangelist_inheritable2(apr_array_hea
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_rangelist_inheritable(apr_array_header_t **inheritable_rangelist,
-                          apr_array_header_t *rangelist,
-                          svn_revnum_t start,
-                          svn_revnum_t end,
-                          apr_pool_t *pool)
-{
-  return svn_rangelist_inheritable2(inheritable_rangelist, rangelist,
-                                    start, end, TRUE, pool, pool);
-}
-
 svn_boolean_t
 svn_mergeinfo__remove_empty_rangelists(svn_mergeinfo_t mergeinfo,
                                        apr_pool_t *pool)
@@ -1663,14 +1663,8 @@ svn_mergeinfo__remove_empty_rangelists(s
     {
       for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
         {
-          const void *key;
-          void *value;
-          const char *path;
-          apr_array_header_t *rangelist;
-
-          apr_hash_this(hi, &key, NULL, &value);
-          path = key;
-          rangelist = value;
+          const char *path = svn__apr_hash_index_key(hi);
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
 
           if (rangelist->nelts == 0)
             {
@@ -1695,15 +1689,12 @@ svn_mergeinfo__remove_prefix_from_catalo
 
   for (hi = apr_hash_first(pool, in_catalog); hi; hi = apr_hash_next(hi))
     {
-      const void *key;
-      const char *original_path;
-      void *value;
-      apr_ssize_t klen;
+      const char *original_path = svn__apr_hash_index_key(hi);
+      apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+      svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
 
-      apr_hash_this(hi, &key, &klen, &value);
-      original_path = key;
       SVN_ERR_ASSERT(klen >= prefix_len);
-      SVN_ERR_ASSERT(strncmp(key, prefix, prefix_len) == 0);
+      SVN_ERR_ASSERT(strncmp(original_path, prefix, prefix_len) == 0);
 
       apr_hash_set(*out_catalog, original_path + prefix_len,
                    klen-prefix_len, value);
@@ -1734,8 +1725,8 @@ svn_mergeinfo__add_suffix_to_mergeinfo(s
            hi;
            hi = apr_hash_next(hi))
         {
-          const char *path = svn_apr_hash_index_key(hi);
-          apr_array_header_t *rangelist = svn_apr_hash_index_val(hi);
+          const char *path = svn__apr_hash_index_key(hi);
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
 
           apr_hash_set(*out_mergeinfo,
                        svn_dirent_join(path, canonical_suffix, result_pool),
@@ -1748,7 +1739,7 @@ svn_mergeinfo__add_suffix_to_mergeinfo(s
 }
 
 apr_array_header_t *
-svn_rangelist_dup(apr_array_header_t *rangelist, apr_pool_t *pool)
+svn_rangelist_dup(const apr_array_header_t *rangelist, apr_pool_t *pool)
 {
   apr_array_header_t *new_rl = apr_array_make(pool, rangelist->nelts,
                                               sizeof(svn_merge_range_t *));
@@ -1890,14 +1881,7 @@ svn_mergeinfo__get_range_endpoints(svn_r
 
       for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
         {
-          const void *key;
-          void *value;
-          const char *path;
-          apr_array_header_t *rangelist;
-
-          apr_hash_this(hi, &key, NULL, &value);
-          path = key;
-          rangelist = value;
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
 
           if (rangelist->nelts)
             {
@@ -1923,31 +1907,31 @@ svn_mergeinfo__filter_catalog_by_ranges(
                                         svn_mergeinfo_catalog_t catalog,
                                         svn_revnum_t youngest_rev,
                                         svn_revnum_t oldest_rev,
-                                        apr_pool_t *pool)
+                                        svn_boolean_t include_range,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
 
-  *filtered_cat = apr_hash_make(pool);
-  for (hi = apr_hash_first(pool, catalog);
+  *filtered_cat = apr_hash_make(result_pool);
+  for (hi = apr_hash_first(scratch_pool, catalog);
        hi;
        hi = apr_hash_next(hi))
     {
-      const void *key;
-      void *val;
-      const char *path;
-
-      svn_mergeinfo_t mergeinfo, filtered_mergeinfo;
-      apr_hash_this(hi, &key, NULL, &val);
-      path = key;
-      mergeinfo = val;
+      const char *path = svn__apr_hash_index_key(hi);
+      svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi);
+      svn_mergeinfo_t filtered_mergeinfo;
+
       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&filtered_mergeinfo,
                                                         mergeinfo,
                                                         youngest_rev,
                                                         oldest_rev,
-                                                        pool));
+                                                        include_range,
+                                                        result_pool,
+                                                        scratch_pool));
       if (apr_hash_count(filtered_mergeinfo))
         apr_hash_set(*filtered_cat,
-                     apr_pstrdup(pool, path),
+                     apr_pstrdup(result_pool, path),
                      APR_HASH_KEY_STRING,
                      filtered_mergeinfo);
     }
@@ -1960,42 +1944,37 @@ svn_mergeinfo__filter_mergeinfo_by_range
                                           svn_mergeinfo_t mergeinfo,
                                           svn_revnum_t youngest_rev,
                                           svn_revnum_t oldest_rev,
-                                          apr_pool_t *pool)
+                                          svn_boolean_t include_range,
+                                          apr_pool_t *result_pool,
+                                          apr_pool_t *scratch_pool)
 {
-  *filtered_mergeinfo = apr_hash_make(pool);
+  *filtered_mergeinfo = apr_hash_make(result_pool);
 
   if (mergeinfo)
     {
       apr_hash_index_t *hi;
-      svn_merge_range_t *range = apr_palloc(pool, sizeof(*range));
       apr_array_header_t *filter_rangelist =
-        apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
+        svn_rangelist__initialize(oldest_rev, youngest_rev, TRUE,
+                                  scratch_pool);
 
-      range->start = oldest_rev;
-      range->end = youngest_rev;
-      range->inheritable = TRUE;
-      APR_ARRAY_PUSH(filter_rangelist, svn_merge_range_t *) = range;
-
-      for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi))
+      for (hi = apr_hash_first(scratch_pool, mergeinfo);
+           hi;
+           hi = apr_hash_next(hi))
         {
-          const void *key;
-          void *value;
-          const char *path;
-          apr_array_header_t *rangelist;
-
-          apr_hash_this(hi, &key, NULL, &value);
-          path = key;
-          rangelist = value;
+          const char *path = svn__apr_hash_index_key(hi);
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
 
           if (rangelist->nelts)
             {
               apr_array_header_t *new_rangelist;
 
-              svn_rangelist_intersect(&new_rangelist, rangelist,
-                                      filter_rangelist, FALSE, pool);
+              SVN_ERR(rangelist_intersect_or_remove(
+                        &new_rangelist, filter_rangelist, rangelist,
+                        ! include_range, FALSE, result_pool));
+
               if (new_rangelist->nelts)
                 apr_hash_set(*filtered_mergeinfo,
-                             apr_pstrdup(pool, path),
+                             apr_pstrdup(result_pool, path),
                              APR_HASH_KEY_STRING,
                              new_rangelist);
             }
@@ -2016,7 +1995,7 @@ svn_mergeinfo__is_noninheritable(svn_mer
            hi;
            hi = apr_hash_next(hi))
         {
-          apr_array_header_t *rangelist = svn_apr_hash_index_val(hi);
+          apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
           int i;
 
           for (i = 0; i < rangelist->nelts; i++)
@@ -2049,3 +2028,21 @@ svn_mergeinfo__string_has_noninheritable
 
   return SVN_NO_ERROR;
 }
+
+apr_array_header_t *
+svn_rangelist__initialize(svn_revnum_t start,
+                          svn_revnum_t end,
+                          svn_boolean_t inheritable,
+                          apr_pool_t *result_pool)
+{
+  apr_array_header_t *rangelist =
+    apr_array_make(result_pool, 1, sizeof(svn_merge_range_t *));
+  svn_merge_range_t *range = apr_pcalloc(result_pool, sizeof(*range));
+
+  range->start = start;
+  range->end = end;
+  range->inheritable = inheritable;
+  APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = range;
+  return rangelist;
+}
+

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/opt.c Tue Aug 10 18:06:17 2010
@@ -686,6 +686,7 @@ svn_opt_parse_path(svn_opt_revision_t *r
         {
           ret = 0;
           start_revision.kind = svn_opt_revision_unspecified;
+          start_revision.value.number = 0;
         }
       else  /* looking at non-empty peg revision */
         {
@@ -738,7 +739,7 @@ svn_opt_parse_path(svn_opt_revision_t *r
 svn_error_t *
 svn_opt__args_to_target_array(apr_array_header_t **targets_p,
                               apr_getopt_t *os,
-                              apr_array_header_t *known_targets,
+                              const apr_array_header_t *known_targets,
                               apr_pool_t *pool)
 {
   int i;
@@ -1066,7 +1067,7 @@ svn_opt_print_help3(apr_getopt_t *os,
 
 svn_error_t *
 svn_opt_eat_peg_revisions(apr_array_header_t **true_targets_p,
-                          apr_array_header_t *targets,
+                          const apr_array_header_t *targets,
                           apr_pool_t *pool)
 {
   int i;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/prompt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/prompt.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/prompt.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/prompt.c Tue Aug 10 18:06:17 2010
@@ -71,7 +71,7 @@ static apr_status_t wait_for_input(apr_f
    * ourselves here.
    */
   return APR_ENOTIMPL;
-#endif  
+#endif
 }
 
 /* Set @a *result to the result of prompting the user with @a

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/quoprint.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/quoprint.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/quoprint.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/quoprint.c Tue Aug 10 18:06:17 2010
@@ -37,24 +37,24 @@
 
 /* Caveats:
 
-	(1) This code is for the encoding and decoding of binary data
-	    only.  Thus, CRLF sequences are encoded as =0D=0A, and we
-	    don't have to worry about tabs and spaces coming before
-	    hard newlines, since there aren't any.
-
-	(2) The decoder does no error reporting, and instead throws
-	    away invalid sequences.  It also discards CRLF sequences,
-	    since those can only appear in the encoding of text data.
-
-	(3) The decoder does not strip whitespace at the end of a
-	    line, so it is not actually compliant with RFC 2045.
-	    (Such whitespace should never occur, even in the encoding
-	    of text data, but RFC 2045 requires a decoder to detect
-	    that a transport agent has added trailing whitespace).
-
-	(4) The encoder is tailored to make output embeddable in XML,
-	    which means it quotes <>'"& as well as the characters
-	    required by RFC 2045.  */
+        (1) This code is for the encoding and decoding of binary data
+            only.  Thus, CRLF sequences are encoded as =0D=0A, and we
+            don't have to worry about tabs and spaces coming before
+            hard newlines, since there aren't any.
+
+        (2) The decoder does no error reporting, and instead throws
+            away invalid sequences.  It also discards CRLF sequences,
+            since those can only appear in the encoding of text data.
+
+        (3) The decoder does not strip whitespace at the end of a
+            line, so it is not actually compliant with RFC 2045.
+            (Such whitespace should never occur, even in the encoding
+            of text data, but RFC 2045 requires a decoder to detect
+            that a transport agent has added trailing whitespace).
+
+        (4) The encoder is tailored to make output embeddable in XML,
+            which means it quotes <>'"& as well as the characters
+            required by RFC 2045.  */
 
 #define QUOPRINT_LINELEN 76
 #define VALID_LITERAL(c) ((c) == '\t' || ((c) >= ' ' && (c) <= '~' \

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/simple_providers.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/simple_providers.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/simple_providers.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/simple_providers.c Tue Aug 10 18:06:17 2010
@@ -202,7 +202,7 @@ svn_auth__simple_first_creds_helper(void
               else
                 need_to_save = TRUE;
             }
-	}
+        }
 
       /* See if we need to save this password if it is not present in
          auth cache. */

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/skel.c Tue Aug 10 18:06:17 2010
@@ -609,6 +609,24 @@ void svn_skel__prepend_str(const char *v
   svn_skel__prepend(atom, skel);
 }
 
+
+void svn_skel__append(svn_skel_t *list_skel, const svn_skel_t *skel)
+{
+  SVN_ERR_ASSERT_NO_RETURN(list_skel != NULL && !list_skel->is_atom);
+
+  if (list_skel->children == NULL)
+    {
+      list_skel->children = (svn_skel_t *)skel;
+    }
+  else
+    {
+      list_skel = list_skel->children;
+      while (list_skel->next != NULL)
+        list_skel = list_skel->next;
+      list_skel->next = (svn_skel_t *)skel;
+    }
+}
+
 
 /* Examining skels.  */
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sorts.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sorts.c Tue Aug 10 18:06:17 2010
@@ -196,7 +196,7 @@ bsearch_lower_bound(const void *key,
 
 int
 svn_sort__bsearch_lower_bound(const void *key,
-                              apr_array_header_t *array,
+                              const apr_array_header_t *array,
                               int (*compare_func)(const void *, const void *))
 {
   return bsearch_lower_bound(key,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/sqlite.c Tue Aug 10 18:06:17 2010
@@ -117,6 +117,16 @@ exec_sql(svn_sqlite__db_t *db, const cha
   return SVN_NO_ERROR;
 }
 
+
+svn_error_t *
+svn_sqlite__exec_statements(svn_sqlite__db_t *db, int stmt_idx)
+{
+  SVN_ERR_ASSERT(stmt_idx < db->nbr_statements);
+
+  return svn_error_return(exec_sql(db, db->statement_strings[stmt_idx]));
+}
+
+
 svn_error_t *
 svn_sqlite__get_statement(svn_sqlite__stmt_t **stmt, svn_sqlite__db_t *db,
                           int stmt_idx)
@@ -898,7 +908,8 @@ svn_sqlite__open(svn_sqlite__db_t **db, 
 #endif
 
   /* Validate the schema, upgrading if necessary. */
-  SVN_ERR(check_format(*db, latest_schema, upgrade_sql, scratch_pool));
+  if (upgrade_sql != NULL)
+    SVN_ERR(check_format(*db, latest_schema, upgrade_sql, scratch_pool));
 
   /* Store the provided statements. */
   if (statements)

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/stream.c Tue Aug 10 18:06:17 2010
@@ -456,7 +456,7 @@ svn_error_t *svn_stream_copy3(svn_stream
 
       err = svn_stream_read(from, buf, &len);
       if (err)
-      	 break;
+         break;
 
       if (len > 0)
         err = svn_stream_write(to, buf, &len);
@@ -472,22 +472,27 @@ svn_error_t *svn_stream_copy3(svn_stream
 }
 
 svn_error_t *
-svn_stream_contents_same(svn_boolean_t *same,
-                         svn_stream_t *stream1,
-                         svn_stream_t *stream2,
-                         apr_pool_t *pool)
+svn_stream_contents_same2(svn_boolean_t *same,
+                          svn_stream_t *stream1,
+                          svn_stream_t *stream2,
+                          apr_pool_t *pool)
 {
   char *buf1 = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
   char *buf2 = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
   apr_size_t bytes_read1 = SVN__STREAM_CHUNK_SIZE;
   apr_size_t bytes_read2 = SVN__STREAM_CHUNK_SIZE;
+  svn_error_t *err = NULL;
 
   *same = TRUE;  /* assume TRUE, until disproved below */
   while (bytes_read1 == SVN__STREAM_CHUNK_SIZE
          && bytes_read2 == SVN__STREAM_CHUNK_SIZE)
     {
-      SVN_ERR(svn_stream_read(stream1, buf1, &bytes_read1));
-      SVN_ERR(svn_stream_read(stream2, buf2, &bytes_read2));
+      err = svn_stream_read(stream1, buf1, &bytes_read1);
+      if (err)
+        break;
+      err = svn_stream_read(stream2, buf2, &bytes_read2);
+      if (err)
+        break;
 
       if ((bytes_read1 != bytes_read2)
           || (memcmp(buf1, buf2, bytes_read1)))
@@ -497,7 +502,10 @@ svn_stream_contents_same(svn_boolean_t *
         }
     }
 
-  return SVN_NO_ERROR;
+  return svn_error_compose_create(err,
+                                  svn_error_compose_create(
+                                    svn_stream_close(stream1),
+                                    svn_stream_close(stream2)));
 }
 
 
@@ -676,35 +684,6 @@ read_handler_apr(void *baton, char *buff
   struct baton_apr *btn = baton;
   svn_error_t *err;
 
-  /* Check for range restriction. */
-  if (btn->start >= 0 && btn->end > 0)
-    {
-      /* Get the current file position and make sure it is in range. */
-      apr_off_t pos;
-
-      pos = 0;
-      SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &pos, btn->pool));
-      if (pos < btn->start)
-        {
-          /* We're before the range, so forward the file cursor to
-           * the start of the range. */
-          pos = btn->start;
-          SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &pos, btn->pool));
-        }
-      else if (pos >= btn->end)
-        {
-          /* We're past the range, indicate that no bytes can be read. */
-          *len = 0;
-          return SVN_NO_ERROR;
-        }
-      else
-        {
-          /* We're in range, but don't read over the end of the range. */
-          if (pos + *len > btn->end)
-              *len = btn->end - pos;
-        }
-    }
-
   err = svn_io_file_read_full(btn->file, buffer, *len, len, btn->pool);
   if (err && APR_STATUS_IS_EOF(err->apr_err))
     {
@@ -846,12 +825,47 @@ svn_stream_from_aprfile2(apr_file_t *fil
   return stream;
 }
 
-svn_stream_t *
-svn_stream_from_aprfile(apr_file_t *file, apr_pool_t *pool)
+/* A read handler (#svn_read_fn_t) that forwards to read_handler_apr()
+   but only allows reading between BATON->start and BATON->end. */
+static svn_error_t *
+read_range_handler_apr(void *baton, char *buffer, apr_size_t *len)
 {
-  return svn_stream_from_aprfile2(file, TRUE, pool);
+  struct baton_apr *btn = baton;
+
+  /* ### BH: I think this can be simplified/optimized by just keeping
+             track of the current position. */
+
+  /* Check for range restriction. */
+  if (btn->start >= 0 && btn->end > 0)
+    {
+      /* Get the current file position and make sure it is in range. */
+      apr_off_t pos;
+
+      pos = 0;
+      SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &pos, btn->pool));
+      if (pos < btn->start)
+        {
+          /* We're before the range, so forward the file cursor to
+           * the start of the range. */
+          pos = btn->start;
+          SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &pos, btn->pool));
+        }
+      else if (pos >= btn->end)
+        {
+          /* We're past the range, indicate that no bytes can be read. */
+          *len = 0;
+          return SVN_NO_ERROR;
+        }
+
+      /* We're in range, but don't read over the end of the range. */
+      if (pos + *len > btn->end)
+        *len = (apr_size_t)(btn->end - pos);
+    }
+
+  return read_handler_apr(baton, buffer, len);
 }
 
+
 svn_stream_t *
 svn_stream_from_aprfile_range_readonly(apr_file_t *file,
                                        svn_boolean_t disown,
@@ -863,6 +877,7 @@ svn_stream_from_aprfile_range_readonly(a
   svn_stream_t *stream;
   apr_off_t pos;
 
+  /* ### HACK: These shortcuts don't handle disown FALSE properly */
   if (file == NULL || start < 0 || end <= 0 || start >= end)
     return svn_stream_empty(pool);
 
@@ -877,7 +892,7 @@ svn_stream_from_aprfile_range_readonly(a
   baton->start = start;
   baton->end = end;
   stream = svn_stream_create(baton, pool);
-  svn_stream_set_read(stream, read_handler_apr);
+  svn_stream_set_read(stream, read_range_handler_apr);
   svn_stream_set_reset(stream, reset_handler_apr);
   svn_stream_set_mark(stream, mark_handler_apr);
   svn_stream_set_seek(stream, seek_handler_apr);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/subst.c Tue Aug 10 18:06:17 2010
@@ -769,9 +769,9 @@ struct translation_baton
   apr_hash_t *keywords;
   svn_boolean_t expand;
 
-  /* Characters (excluding the terminating NUL character) which
+  /* 'short boolean' array that encodes what character values
      may trigger a translation action, hence are 'interesting' */
-  const char *interesting;
+  char interesting[256];
 
   /* Length of the string EOL_STR points to. */
   apr_size_t eol_str_len;
@@ -821,11 +821,21 @@ create_translation_baton(const char *eol
   b->repair = repair;
   b->keywords = keywords;
   b->expand = expand;
-  b->interesting = (eol_str && keywords) ? "$\r\n" : eol_str ? "\r\n" : "$";
   b->newline_off = 0;
   b->keyword_off = 0;
   b->src_format_len = 0;
 
+  /* Most characters don't start translation actions.
+   * Mark those that do depending on the parameters we got. */
+  memset(b->interesting, FALSE, sizeof(b->interesting));
+  if (keywords)
+    b->interesting['$'] = TRUE;
+  if (eol_str)
+    {
+      b->interesting['\r'] = TRUE;
+      b->interesting['\n'] = TRUE;
+    }
+
   return b;
 }
 
@@ -938,14 +948,9 @@ translate_chunk(svn_stream_t *dst,
           len = 0;
 
           /* We wanted memcspn(), but lacking that, the loop below has
-             the same effect.
-
-             Also, skip NUL characters explicitly, since strchr()
-             considers them part of the string argument,
-             but we don't consider them interesting
+             the same effect. Also, skip NUL characters.
           */
-          while ((p + len) < end
-                 && (! p[len] || ! strchr(interesting, p[len])))
+          while ((p + len) < end && !interesting[(unsigned char)p[len]])
             len++;
 
           if (len)
@@ -1033,6 +1038,7 @@ struct translated_stream_baton
 };
 
 
+/* Implements svn_read_fn_t. */
 static svn_error_t *
 translated_stream_read(void *baton,
                        char *buffer,
@@ -1044,6 +1050,25 @@ translated_stream_read(void *baton,
   apr_size_t off = 0;
   apr_pool_t *iterpool;
 
+  /* Optimization for a frequent special case. The configuration parser (and
+     a few others) reads the stream one byte at a time. All the memcpy, pool
+     clearing etc. imposes a huge overhead in that case. In most cases, we
+     can just take that single byte directly from the read buffer.
+
+     Since *len > 1 requires lots of code to be run anyways, we can afford
+     the extra overhead of checking for *len == 1.
+
+     See <http://mail-archives.apache.org/mod_mbox/subversion-dev/201003.mbox/%3C4B94011E.1070207@alice-dsl.de%3E>.
+  */
+  if (unsatisfied == 1 && b->readbuf_off < b->readbuf->len)
+    {
+      /* Just take it from the read buffer */
+      *buffer = b->readbuf->data[b->readbuf_off++];
+
+      return SVN_NO_ERROR;
+    }
+
+  /* Standard code path. */
   iterpool = b->iterpool;
   while (readlen == SVN__STREAM_CHUNK_SIZE && unsatisfied > 0)
     {
@@ -1086,6 +1111,7 @@ translated_stream_read(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_write_fn_t. */
 static svn_error_t *
 translated_stream_write(void *baton,
                         const char *buffer,
@@ -1098,6 +1124,7 @@ translated_stream_write(void *baton,
   return translate_chunk(b->stream, b->out_baton, buffer, *len, b->iterpool);
 }
 
+/* Implements svn_close_fn_t. */
 static svn_error_t *
 translated_stream_close(void *baton)
 {
@@ -1112,6 +1139,7 @@ translated_stream_close(void *baton)
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_io_reset_fn_t. */
 static svn_error_t *
 translated_stream_reset(void *baton)
 {
@@ -1136,6 +1164,45 @@ translated_stream_reset(void *baton)
   return svn_error_return(err);
 }
 
+/* Implements svn_io_mark_fn_t. */
+static svn_error_t *
+translated_stream_mark(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool)
+{
+  struct translated_stream_baton *b = baton;
+
+  return svn_error_return(svn_stream_mark(b->stream, mark, pool));
+}
+
+/* Implements svn_io_seek_fn_t. */
+static svn_error_t *
+translated_stream_seek(void *baton, svn_stream_mark_t *mark)
+{
+  struct translated_stream_baton *b = baton;
+  svn_error_t *err;
+
+  /* Flush output buffer if necessary. */
+  if (b->written)
+    SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool));
+
+  err = svn_stream_seek(b->stream, mark);
+  if (err == NULL)
+    {
+      /* Force into boring state. */
+      b->in_baton->newline_off = 0;
+      b->in_baton->keyword_off = 0;
+      b->out_baton->newline_off = 0;
+      b->out_baton->keyword_off = 0;
+
+      /* Output buffer has been flushed. */
+      b->written = FALSE;
+
+      /* Reset read buffer. */
+      svn_stringbuf_setempty(b->readbuf);
+      b->readbuf_off = 0;
+    }
+
+  return svn_error_return(err);
+}
 
 svn_error_t *
 svn_subst_read_specialfile(svn_stream_t **stream,
@@ -1235,6 +1302,8 @@ svn_subst_stream_translated(svn_stream_t
   svn_stream_set_write(s, translated_stream_write);
   svn_stream_set_close(s, translated_stream_close);
   svn_stream_set_reset(s, translated_stream_reset);
+  svn_stream_set_mark(s, translated_stream_mark);
+  svn_stream_set_seek(s, translated_stream_seek);
 
   return s;
 }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/svn_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/svn_string.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/svn_string.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/svn_string.c Tue Aug 10 18:06:17 2010
@@ -536,7 +536,7 @@ svn_cstring_split(const char *input,
 
 
 svn_boolean_t svn_cstring_match_glob_list(const char *str,
-                                          apr_array_header_t *list)
+                                          const apr_array_header_t *list)
 {
   int i;
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_crashrpt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_crashrpt.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_crashrpt.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_subr/win32_crashrpt.c Tue Aug 10 18:06:17 2010
@@ -40,7 +40,7 @@
 HANDLE dbghelp_dll = INVALID_HANDLE_VALUE;
 
 /* Email address where the crash reports should be sent too. */
-#define CRASHREPORT_EMAIL "svn-breakage@subversion.tigris.org"
+#define CRASHREPORT_EMAIL "notifications@subversion.apache.org"
 
 #define DBGHELP_DLL "dbghelp.dll"