You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2011/08/16 11:38:43 UTC

svn commit: r1158171 [4/10] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ notes/ subversion/bindings/ctypes-python/csvn/ subversion/bindings/ctypes-python/test/ subversion/bindings/javahl/native...

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/merge.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/merge.c Tue Aug 16 09:38:37 2011
@@ -427,7 +427,6 @@ perform_obstruction_check(svn_wc_notify_
                                          kind,
                                          added,
                                          deleted,
-                                         NULL,
                                          wc_ctx, local_abspath,
                                          check_root,
                                          scratch_pool));
@@ -2722,6 +2721,43 @@ notification_receiver(void *baton, const
     (*notify_b->wrapped_func)(notify_b->wrapped_baton, notify, pool);
 }
 
+/* Set *OUT_RANGELIST to the intersection of IN_RANGELIST with the simple
+ * (inheritable) revision range REV1:REV2, according to CONSIDER_INHERITANCE.
+ * If REV1 is equal to REV2, the result is an empty rangelist, otherwise
+ * REV1 must be less than REV2.
+ *
+ * Note: If CONSIDER_INHERITANCE is FALSE, the effect is to treat any non-
+ * inheritable input ranges as if they were inheritable.  If it is TRUE, the
+ * effect is to discard any non-inheritable input ranges.  Therefore the
+ * ranges in *OUT_RANGELIST will always be inheritable. */
+static svn_error_t *
+rangelist_intersect_range(apr_array_header_t **out_rangelist,
+                          const apr_array_header_t *in_rangelist,
+                          svn_revnum_t rev1,
+                          svn_revnum_t rev2,
+                          svn_boolean_t consider_inheritance,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  SVN_ERR_ASSERT(rev1 <= rev2);
+
+  if (rev1 < rev2)
+    {
+      apr_array_header_t *simple_rangelist =
+        svn_rangelist__initialize(rev1, rev2, TRUE, scratch_pool);
+
+      SVN_ERR(svn_rangelist_intersect(out_rangelist,
+                                      simple_rangelist, in_rangelist,
+                                      consider_inheritance, result_pool));
+    }
+  else
+    {
+      *out_rangelist = apr_array_make(result_pool, 0,
+                                      sizeof(svn_merge_range_t *));
+    }
+  return SVN_NO_ERROR;
+}
+
 /* Helper for fix_deleted_subtree_ranges().  Like fix_deleted_subtree_ranges()
    this function should only be called when honoring mergeinfo.
 
@@ -2820,7 +2856,6 @@ adjust_deleted_subtree_ranges(svn_client
   svn_revnum_t younger_rev = is_rollback ? revision1 : revision2;
   svn_revnum_t peg_rev = younger_rev;
   svn_revnum_t older_rev = is_rollback ? revision2 : revision1;
-  svn_revnum_t revision_primary_url_deleted = SVN_INVALID_REVNUM;
   apr_array_header_t *segments;
   const char *rel_source_path;
   const char *session_url;
@@ -2875,20 +2910,20 @@ adjust_deleted_subtree_ranges(svn_client
             }
           else
             {
-              apr_array_header_t *exists_rangelist, *deleted_rangelist;
+              apr_array_header_t *deleted_rangelist;
+              svn_revnum_t rev_primary_url_deleted;
 
               /* PRIMARY_URL@older_rev exists, so it was deleted at some
                  revision prior to peg_rev, find that revision. */
               SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
                                              older_rev, younger_rev,
-                                             &revision_primary_url_deleted,
+                                             &rev_primary_url_deleted,
                                              scratch_pool));
 
               /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
                  so svn_ra_get_deleted_rev() should always find the revision
                  PRIMARY_URL@older_rev was deleted. */
-              SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(
-                revision_primary_url_deleted));
+              SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
 
               /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
                  PARENT->REMAINING_RANGES so both will work with the
@@ -2906,43 +2941,25 @@ adjust_deleted_subtree_ranges(svn_client
               /* Find the intersection of CHILD->REMAINING_RANGES with the
                  range over which PRIMARY_URL@older_rev exists (ending at
                  the youngest revision at which it still exists). */
-              if (revision_primary_url_deleted - 1 > older_rev)
-                {
-                  /* It was not deleted immediately after OLDER_REV, so
-                     it has some relevant changes. */
-                  exists_rangelist =
-                    svn_rangelist__initialize(older_rev,
-                                              revision_primary_url_deleted - 1,
-                                              TRUE, scratch_pool);
-                  SVN_ERR(svn_rangelist_intersect(&(child->remaining_ranges),
-                                                  exists_rangelist,
-                                                  child->remaining_ranges,
-                                                  FALSE, scratch_pool));
-                }
-              else
-                {
-                  /* It was deleted immediately after the OLDER rev, so
-                     it has no relevant changes. */
-                  child->remaining_ranges
-                    = apr_array_make(scratch_pool, 0,
-                                     sizeof(svn_merge_range_t *));
-                }
-
-              /* Find the intersection of PARENT->REMAINING_RANGES with the
-                 range beginning when PRIMARY_URL@older_rev was deleted
-                 until younger_rev.
-                 Finally merge this rangelist with the rangelist above and
-                 store the result in CHILD->REMANING_RANGES. */
-              deleted_rangelist =
-                svn_rangelist__initialize(revision_primary_url_deleted - 1,
-                                          peg_rev, TRUE, scratch_pool);
-              SVN_ERR(svn_rangelist_intersect(&deleted_rangelist,
-                                              deleted_rangelist,
-                                              parent->remaining_ranges,
-                                              FALSE, scratch_pool));
+              SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
+                                                child->remaining_ranges,
+                                                older_rev,
+                                                rev_primary_url_deleted - 1,
+                                                FALSE,
+                                                scratch_pool, scratch_pool));
 
-              SVN_ERR(svn_rangelist_merge(&(child->remaining_ranges),
-                                          deleted_rangelist, scratch_pool));
+              /* Merge into CHILD->REMANING_RANGES the intersection of
+                 PARENT->REMAINING_RANGES with the range beginning when
+                 PRIMARY_URL@older_rev was deleted until younger_rev. */
+              SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
+                                                parent->remaining_ranges,
+                                                rev_primary_url_deleted - 1,
+                                                peg_rev,
+                                                FALSE,
+                                                scratch_pool, scratch_pool));
+              SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
+                                           deleted_rangelist, scratch_pool,
+                                           scratch_pool));
 
               /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
                  to reverse order if necessary. */
@@ -2962,7 +2979,7 @@ adjust_deleted_subtree_ranges(svn_client
     }
   else /* PRIMARY_URL@peg_rev exists. */
     {
-      apr_array_header_t *exists_rangelist, *non_existent_rangelist;
+      apr_array_header_t *non_existent_rangelist;
       svn_location_segment_t *segment =
         APR_ARRAY_IDX(segments, (segments->nelts - 1),
                       svn_location_segment_t *);
@@ -2989,34 +3006,25 @@ adjust_deleted_subtree_ranges(svn_client
                                         scratch_pool));
         }
 
-      /* Since segment doesn't span older_rev:peg_rev we know
+      /* Intersect CHILD->REMAINING_RANGES with the range where PRIMARY_URL
+         exists.  Since segment doesn't span older_rev:peg_rev we know
          PRIMARY_URL@peg_rev didn't come into existence until
-         segment->range_start + 1.  Create a rangelist describing
-         range where PRIMARY_URL exists and find the intersection of that
-         range and CHILD->REMAINING_RANGELIST. */
-      exists_rangelist = svn_rangelist__initialize(segment->range_start,
-                                                   peg_rev, TRUE,
-                                                   scratch_pool);
-      SVN_ERR(svn_rangelist_intersect(&(child->remaining_ranges),
-                                      exists_rangelist,
-                                      child->remaining_ranges,
-                                      FALSE, scratch_pool));
-
-      /* Create a second rangelist describing the range before
-         PRIMARY_URL@peg_rev came into existence and find the intersection of
-         that range and PARENT->REMAINING_RANGES.  Then merge that rangelist
-         with exists_rangelist and store the result in
-         CHILD->REMANING_RANGES. */
-      non_existent_rangelist = svn_rangelist__initialize(older_rev,
-                                                         segment->range_start,
-                                                         TRUE, scratch_pool);
-      SVN_ERR(svn_rangelist_intersect(&non_existent_rangelist,
-                                      non_existent_rangelist,
-                                      parent->remaining_ranges,
-                                      FALSE, scratch_pool));
-
-      SVN_ERR(svn_rangelist_merge(&(child->remaining_ranges),
-                                  non_existent_rangelist, scratch_pool));
+         segment->range_start + 1. */
+      SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
+                                        child->remaining_ranges,
+                                        segment->range_start, peg_rev,
+                                        FALSE, scratch_pool, scratch_pool));
+
+      /* Merge into CHILD->REMANING_RANGES the intersection of
+         PARENT->REMAINING_RANGES with the range before PRIMARY_URL@peg_rev
+         came into existence. */
+      SVN_ERR(rangelist_intersect_range(&non_existent_rangelist,
+                                        parent->remaining_ranges,
+                                        older_rev, segment->range_start,
+                                        FALSE, scratch_pool, scratch_pool));
+      SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
+                                   non_existent_rangelist, scratch_pool,
+                                   scratch_pool));
 
       /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
          to reverse order if necessary. */
@@ -3762,8 +3770,9 @@ filter_merged_revisions(svn_client__merg
             implicit_rangelist = apr_array_make(scratch_pool, 0,
                                                 sizeof(svn_merge_range_t *));
 
-          SVN_ERR(svn_rangelist_merge(&implicit_rangelist,
-                                      explicit_rangelist, scratch_pool));
+          SVN_ERR(svn_rangelist_merge2(implicit_rangelist,
+                                       explicit_rangelist, scratch_pool,
+                                       scratch_pool));
           SVN_ERR(svn_rangelist_reverse(implicit_rangelist, scratch_pool));
           child->remaining_ranges = svn_rangelist_dup(implicit_rangelist,
                                                       result_pool);
@@ -4150,6 +4159,7 @@ find_gaps_in_merge_source_history(svn_re
         apr_array_make(scratch_pool, 2, sizeof(svn_merge_range_t *));
       apr_array_header_t *gap_rangelist;
       apr_hash_index_t *hi;
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
       for (hi = apr_hash_first(scratch_pool, implicit_src_mergeinfo);
            hi;
@@ -4157,9 +4167,12 @@ find_gaps_in_merge_source_history(svn_re
         {
           apr_array_header_t *value = svn__apr_hash_index_val(hi);
 
-          SVN_ERR(svn_rangelist_merge(&implicit_rangelist, value,
-                                      scratch_pool));
+          svn_pool_clear(iterpool);
+
+          SVN_ERR(svn_rangelist_merge2(implicit_rangelist, value,
+                                       scratch_pool, iterpool));
         }
+      svn_pool_destroy(iterpool);
       SVN_ERR(svn_rangelist_remove(&gap_rangelist, implicit_rangelist,
                                    requested_rangelist, FALSE,
                                    scratch_pool));
@@ -4318,6 +4331,8 @@ populate_remaining_ranges(apr_array_head
 
       parent = NULL;
 
+      svn_pool_clear(iterpool);
+
       /* If the path is absent don't do subtree merge either. */
       SVN_ERR_ASSERT(child);
       if (child->absent)
@@ -4438,9 +4453,9 @@ populate_remaining_ranges(apr_array_head
                  to, CHILD->REMAINING_RANGES as appropriate. */
 
               if (overlaps_or_adjoins)
-                SVN_ERR(svn_rangelist_merge(&(child->remaining_ranges),
-                                            merge_b->implicit_src_gap,
-                                            result_pool));
+                SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
+                                             merge_b->implicit_src_gap,
+                                             result_pool, iterpool));
               else /* equals == TRUE */
                 SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
                                              merge_b->implicit_src_gap,
@@ -4614,8 +4629,7 @@ update_wc_mergeinfo(svn_mergeinfo_catalo
         }
       else
         {
-          SVN_ERR(svn_rangelist_merge(&rangelist, ranges,
-                                      iterpool));
+          SVN_ERR(svn_rangelist_merge2(rangelist, ranges, iterpool, iterpool));
         }
       /* Update the mergeinfo by adjusting the path's rangelist. */
       apr_hash_set(mergeinfo, rel_path, APR_HASH_KEY_STRING, rangelist);
@@ -5008,12 +5022,12 @@ drive_merge_report_editor(const char *ta
                                       merge_b->ctx->wc_ctx, target_abspath,
                                       depth,
                                       merge_b->ra_session2, revision1,
-                                      FALSE, merge_b->dry_run,
+                                      FALSE,
                                       &merge_callbacks, merge_b,
                                       merge_b->ctx->cancel_func,
                                       merge_b->ctx->cancel_baton,
                                       notification_receiver, notify_b,
-                                      scratch_pool, scratch_pool));
+                                      scratch_pool));
   SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
                           &reporter, &report_baton, revision2,
                           "", depth, merge_b->ignore_ancestry,
@@ -5658,10 +5672,10 @@ pre_merge_status_cb(void *baton,
      2) Path is switched.
      3) Path is a subtree of the merge target (i.e. is not equal to
         MERGE_CMD_BATON->TARGET_ABSPATH) and has no mergeinfo of its own but
-        its parent has mergeinfo with non-inheritable ranges.  If this isn't a
-        dry-run and the merge is between differences in the same repository,
-        then this function will set working mergeinfo on the path equal to
-        the mergeinfo inheritable from its parent.
+        its immediate parent has mergeinfo with non-inheritable ranges.  If
+        this isn't a dry-run and the merge is between differences in the same
+        repository, then this function will set working mergeinfo on the path
+        equal to the mergeinfo inheritable from its parent.
      4) Path has an immediate child (or children) missing from the WC because
         the child is switched or absent from the WC, or due to a sparse
         checkout.
@@ -7733,18 +7747,16 @@ record_mergeinfo_for_dir_merge(svn_merge
 
 /* Helper for do_directory_merge().
 
-   Similar to record_mergeinfo_for_dir_merge in that it records mergeinfo
-   describing a merge of MERGED_RANGE->START:MERGED_RANGE->END from the
-   repository relative path MERGEINFO_PATH to MERGE->TARGET_ABSPATH.
-   Unlike record_mergeinfo_for_dir_merge() though, this
-   funtion only records mergeinfo on *new* subtrees added by the merge which
-   are children of paths with non-inheritable ranges or which have missing
-   siblings - see criteria 3 and 5 in the doc string for get_mergeinfo_paths.
-   See also issue #2829
-   http://subversion.tigris.org/issues/show_bug.cgi?id=2829#desc14.
+   Record mergeinfo describing a merge of
+   MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path
+   MERGEINFO_PATH to each path in NOTIFY_B->ADDED_ABSPATHS which is the
+   immediate child of a parent with explicit non-inheritable mergeinfo.
 
    DEPTH, NOTIFY_B, MERGE_B, and SQUELCH_MERGEINFO_NOTIFICATIONS, are
    cascaded from do_directory_merge's arguments of the same names.
+
+   Note: This is intended to support forward merges only, i.e.
+   MERGED_RANGE->START must be older than MERGED_RANGE->END.
 */
 static svn_error_t *
 record_mergeinfo_for_added_subtrees(
@@ -7763,6 +7775,8 @@ record_mergeinfo_for_added_subtrees(
   if (!notify_b->added_abspaths)
     return SVN_NO_ERROR;
 
+  SVN_ERR_ASSERT(merged_range->start < merged_range->end);
+
   iterpool = svn_pool_create(pool);
   for (hi = apr_hash_first(pool, notify_b->added_abspaths); hi;
        hi = apr_hash_next(hi))
@@ -7860,13 +7874,53 @@ typedef struct log_noop_baton_t
      being diffed. */
   const char *source_repos_abs;
 
-  /* Initially empty rangelists allocated in POOL. */
+  /* Initially empty rangelists allocated in POOL. The rangelists are
+   * populated across multiple invocations of log_noop_revs(). */
   apr_array_header_t *operative_ranges;
   apr_array_header_t *merged_ranges;
 
+  /* Pool to store the rangelists. */
   apr_pool_t *pool;
 } log_noop_baton_t;
 
+/* Helper for log_noop_revs: Merge a svn_merge_range_t representation of
+   REVISION into RANGELIST. New elements added to rangelist are allocated
+   in RESULT_POOL.
+
+   This is *not* a general purpose rangelist merge but a special replacement
+   for svn_rangelist_merge when REVISION is guaranteed to be younger than any
+   element in RANGELIST.  svn_rangelist_merge is O(n) worst-case (i.e. when
+   all the ranges in output rangelist are older than the incoming changes).
+   This turns the special case of a single incoming younger range into O(1).
+   */
+static svn_error_t *
+rangelist_merge_revision(apr_array_header_t *rangelist,
+                         svn_revnum_t revision,
+                         apr_pool_t *result_pool)
+{
+  svn_merge_range_t *new_range;
+  if (rangelist->nelts)
+    {
+      svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,
+                                               svn_merge_range_t *);
+      if (range->end == revision - 1)
+        {
+          /* REVISION is adjacent to the youngest range in RANGELIST
+             so we can simply expand that range to encompass REVISION. */
+          range->end = revision;
+          return SVN_NO_ERROR;
+        }
+    }
+  new_range = apr_palloc(result_pool, sizeof(*new_range));
+  new_range->start = revision - 1;
+  new_range->end = revision;
+  new_range->inheritable = TRUE;
+
+  APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = new_range;
+
+  return SVN_NO_ERROR;
+}
+
 /* Implements the svn_log_entry_receiver_t interface.
 
    BATON is an log_noop_baton_t *.
@@ -7877,45 +7931,34 @@ typedef struct log_noop_baton_t
    MERGE_B->TARGET_ABSPATH per the mergeinfo in CHILDREN_WITH_MERGEINFO,
    then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES.
 
-   Use POOL for temporary allocations.  Allocate additions to
+   Use SCRATCH_POOL for temporary allocations.  Allocate additions to
    BATON->MERGED_RANGES and BATON->OPERATIVE_RANGES in BATON->POOL.
+
+   Note: This callback must be invoked from oldest LOG_ENTRY->REVISION
+   to youngest LOG_ENTRY->REVISION -- see rangelist_merge_revision().
 */
 static svn_error_t *
 log_noop_revs(void *baton,
               svn_log_entry_t *log_entry,
-              apr_pool_t *pool)
+              apr_pool_t *scratch_pool)
 {
   log_noop_baton_t *log_gap_baton = baton;
   apr_hash_index_t *hi;
   svn_revnum_t revision;
   svn_boolean_t log_entry_rev_required = FALSE;
-  apr_array_header_t *rl1;
-  apr_array_header_t *rl2;
-
-  /* The baton's pool is essentially an iterpool so we must clear it
-   * for each invocation of this function. */
-  rl1 = svn_rangelist_dup(log_gap_baton->operative_ranges, pool);
-  rl2 = svn_rangelist_dup(log_gap_baton->merged_ranges, pool);
-  svn_pool_clear(log_gap_baton->pool);
-  log_gap_baton->operative_ranges = svn_rangelist_dup(rl1,
-                                                      log_gap_baton->pool);
-  log_gap_baton->merged_ranges = svn_rangelist_dup(rl2,
-                                                   log_gap_baton->pool);
 
   revision = log_entry->revision;
 
   /* Unconditionally add LOG_ENTRY->REVISION to BATON->OPERATIVE_MERGES. */
-  SVN_ERR(svn_rangelist_merge(&(log_gap_baton->operative_ranges),
-                              svn_rangelist__initialize(revision - 1,
-                                                        revision, TRUE,
-                                                        log_gap_baton->pool),
-                              log_gap_baton->pool));
+  SVN_ERR(rangelist_merge_revision(log_gap_baton->operative_ranges,
+                                   revision,
+                                   log_gap_baton->pool));
 
   /* Examine each path affected by LOG_ENTRY->REVISION.  If the explicit or
      inherited mergeinfo for *all* of the corresponding paths under
      MERGE_B->TARGET_ABSPATH reflects that LOG_ENTRY->REVISION has been
      merged, then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES. */
-  for (hi = apr_hash_first(pool, log_entry->changed_paths2);
+  for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2);
        hi;
        hi = apr_hash_next(hi))
     {
@@ -7934,7 +7977,7 @@ log_noop_revs(void *baton,
       if (rel_path == NULL)
         continue;
       cwmi_path = svn_dirent_join(log_gap_baton->merge_b->target_abspath,
-                                  rel_path, pool);
+                                  rel_path, scratch_pool);
 
       /* Find any explicit or inherited mergeinfo for PATH. */
       while (!log_entry_rev_required)
@@ -7962,8 +8005,8 @@ log_noop_revs(void *baton,
             }
 
           /* Didn't find anything so crawl up to the parent. */
-          cwmi_path = svn_dirent_dirname(cwmi_path, pool);
-          path = svn_dirent_dirname(path, pool);
+          cwmi_path = svn_dirent_dirname(cwmi_path, scratch_pool);
+          path = svn_dirent_dirname(path, scratch_pool);
 
           /* At this point *if* we find mergeinfo it will be inherited. */
           mergeinfo_inherited = TRUE;
@@ -7972,16 +8015,17 @@ log_noop_revs(void *baton,
       if (paths_explicit_rangelist)
         {
           apr_array_header_t *intersecting_range;
+          apr_array_header_t *rangelist;
+
+          rangelist = svn_rangelist__initialize(revision - 1, revision, TRUE,
+                                                scratch_pool);
 
           /* If PATH inherited mergeinfo we must consider inheritance in the
              event the inherited mergeinfo is actually non-inheritable. */
           SVN_ERR(svn_rangelist_intersect(&intersecting_range,
                                           paths_explicit_rangelist,
-                                          svn_rangelist__initialize(
-                                            revision - 1,
-                                            revision, TRUE,
-                                            pool),
-                                          mergeinfo_inherited, pool));
+                                          rangelist,
+                                          mergeinfo_inherited, scratch_pool));
 
           if (intersecting_range->nelts == 0)
             log_entry_rev_required = TRUE;
@@ -7993,12 +8037,9 @@ log_noop_revs(void *baton,
     }
 
   if (!log_entry_rev_required)
-    SVN_ERR(svn_rangelist_merge(&(log_gap_baton->merged_ranges),
-                                svn_rangelist__initialize(revision - 1,
-                                                          revision,
-                                                          TRUE,
-                                                          log_gap_baton->pool),
-                                log_gap_baton->pool));
+    SVN_ERR(rangelist_merge_revision(log_gap_baton->merged_ranges,
+                                     revision,
+                                     log_gap_baton->pool));
 
   return SVN_NO_ERROR;
 }
@@ -8039,13 +8080,12 @@ remove_noop_subtree_ranges(const char *u
   apr_array_header_t *subtree_gap_ranges;
   apr_array_header_t *subtree_remaining_ranges;
   apr_array_header_t *log_targets;
-  apr_array_header_t *merged_ranges;
-  apr_array_header_t *operative_ranges;
   log_noop_baton_t log_gap_baton;
   svn_merge_range_t *oldest_gap_rev;
   svn_merge_range_t *youngest_gap_rev;
   apr_array_header_t *inoperative_ranges;
   const char *repos_root_url;
+  apr_pool_t *iterpool;
 
 
   /* This function is only intended to work with forward merges. */
@@ -8059,8 +8099,6 @@ remove_noop_subtree_ranges(const char *u
   subtree_remaining_ranges = apr_array_make(scratch_pool, 1,
                                             sizeof(svn_merge_range_t *));
   log_targets = apr_array_make(scratch_pool, 1, sizeof(const char *));
-  merged_ranges = apr_array_make(scratch_pool, 0, sizeof(svn_revnum_t *));
-  operative_ranges = apr_array_make(scratch_pool, 0, sizeof(svn_revnum_t *));
 
   /* Given the requested merge of REVISION1:REVISION2 might there be any
      part of this range required for subtrees but not for the target? */
@@ -8076,18 +8114,22 @@ remove_noop_subtree_ranges(const char *u
     return SVN_NO_ERROR;
 
   /* Create a rangelist describing every range required across all subtrees. */
+  iterpool = svn_pool_create(scratch_pool);
   for (i = 1; i < notify_b->children_with_mergeinfo->nelts; i++)
     {
       svn_client__merge_path_t *child =
         APR_ARRAY_IDX(notify_b->children_with_mergeinfo, i,
                       svn_client__merge_path_t *);
 
+      svn_pool_clear(iterpool);
+
       /* CHILD->REMAINING_RANGES will be NULL if child is absent. */
       if (child->remaining_ranges && child->remaining_ranges->nelts)
-        SVN_ERR(svn_rangelist_merge(&subtree_remaining_ranges,
-                                    child->remaining_ranges,
-                                    scratch_pool));
+        SVN_ERR(svn_rangelist_merge2(subtree_remaining_ranges,
+                                     child->remaining_ranges,
+                                     scratch_pool, iterpool));
     }
+  svn_pool_destroy(iterpool);
 
   /* It's possible that none of the subtrees had any remaining ranges. */
   if (!subtree_remaining_ranges->nelts)
@@ -8126,14 +8168,21 @@ remove_noop_subtree_ranges(const char *u
                     &(log_gap_baton.source_repos_abs), merge_b->ctx->wc_ctx,
                     url2, repos_root_url, TRUE, NULL,
                     result_pool, scratch_pool));
-  log_gap_baton.merged_ranges = merged_ranges;
-  log_gap_baton.operative_ranges = operative_ranges;
+  log_gap_baton.merged_ranges = apr_array_make(scratch_pool, 0,
+                                               sizeof(svn_revnum_t *));
+  log_gap_baton.operative_ranges = apr_array_make(scratch_pool, 0,
+                                                  sizeof(svn_revnum_t *));
   log_gap_baton.pool = svn_pool_create(scratch_pool);
 
   APR_ARRAY_PUSH(log_targets, const char *) = "";
 
-  SVN_ERR(svn_ra_get_log2(ra_session, log_targets, youngest_gap_rev->end,
-                          oldest_gap_rev->start + 1, 0, TRUE, TRUE, FALSE,
+  /* Invoke the svn_log_entry_receiver_t receiver log_noop_revs() from
+     oldest to youngest.  The receiver is optimized to add ranges to
+     log_gap_baton.merged_ranges and log_gap_baton.operative_ranges, but
+     requires that the revs arrive oldest to youngest -- see log_noop_revs()
+     and rangelist_merge_revision(). */
+  SVN_ERR(svn_ra_get_log2(ra_session, log_targets, oldest_gap_rev->start + 1,
+                          youngest_gap_rev->end, 0, TRUE, TRUE, FALSE,
                           apr_array_make(scratch_pool, 0,
                                          sizeof(const char *)),
                           log_noop_revs, &log_gap_baton, scratch_pool));
@@ -8145,8 +8194,8 @@ remove_noop_subtree_ranges(const char *u
                                log_gap_baton.operative_ranges,
                                inoperative_ranges, FALSE, scratch_pool));
 
-  SVN_ERR(svn_rangelist_merge(&(log_gap_baton.merged_ranges),
-                              inoperative_ranges, scratch_pool));
+  SVN_ERR(svn_rangelist_merge2(log_gap_baton.merged_ranges, inoperative_ranges,
+                               scratch_pool, scratch_pool));
 
   for (i = 1; i < notify_b->children_with_mergeinfo->nelts; i++)
     {
@@ -8166,6 +8215,8 @@ remove_noop_subtree_ranges(const char *u
         }
     }
 
+  svn_pool_destroy(log_gap_baton.pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -8356,7 +8407,7 @@ do_directory_merge(svn_mergeinfo_catalog
           /* While END_REV is valid, do the following:
 
              1. Tweak each NOTIFY_B->CHILDREN_WITH_MERGEINFO element so that
-                the element's remaing_ranges member has as it's first element
+                the element's remaining_ranges member has as its first element
                 a range that ends with end_rev.
 
              2. Starting with start_rev, call drive_merge_report_editor()
@@ -8557,7 +8608,9 @@ do_directory_merge(svn_mergeinfo_catalog
          So here we look at the root path of each subtree added during the
          merge and set explicit mergeinfo on it if it meets the aforementioned
          conditions. */
-      if (err == SVN_NO_ERROR)
+      if (err == SVN_NO_ERROR
+          && (range.start < range.end)) /* Nothing to record on added subtrees
+                                           resulting from reverse merges. */
         {
           err = record_mergeinfo_for_added_subtrees(
                   &range, mergeinfo_path, depth,
@@ -9844,6 +9897,7 @@ find_unsynced_ranges(const char *source_
         {
           svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi_catalog);
           apr_hash_index_t *hi_mergeinfo;
+          apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
           for (hi_mergeinfo = apr_hash_first(scratch_pool, mergeinfo);
                hi_mergeinfo;
@@ -9852,9 +9906,11 @@ find_unsynced_ranges(const char *source_
               apr_array_header_t *rangelist =
                 svn__apr_hash_index_val(hi_mergeinfo);
 
-              SVN_ERR(svn_rangelist_merge(&potentially_unmerged_ranges,
-                                          rangelist, scratch_pool));
+              svn_pool_clear(iterpool);
+              SVN_ERR(svn_rangelist_merge2(potentially_unmerged_ranges,
+                                           rangelist, scratch_pool, iterpool));
             }
+          svn_pool_destroy(iterpool);
         }
     }
 
@@ -10517,6 +10573,7 @@ merge_reintegrate_locked(const char *sou
   const char *target_url;
   svn_revnum_t target_base_rev;
   svn_node_kind_t kind;
+  svn_opt_revision_t no_rev;
 
   /* Make sure the target is really there. */
   SVN_ERR(svn_io_check_path(target_abspath, &kind, scratch_pool));
@@ -10588,20 +10645,16 @@ merge_reintegrate_locked(const char *sou
                               NULL, ctx, scratch_pool, scratch_pool));
 
   /* Open two RA sessions, one to our source and one to our target. */
+  no_rev.kind = svn_opt_revision_unspecified;
+  SVN_ERR(svn_client__ra_session_from_path(&source_ra_session, &rev2, &url2,
+                                           url2, NULL, peg_revision, &no_rev,
+                                           ctx, scratch_pool));
   SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, target_abspath,
                                scratch_pool, scratch_pool));
   SVN_ERR(svn_client__open_ra_session_internal(&target_ra_session, NULL,
                                                target_url,
                                                NULL, NULL, FALSE, FALSE,
                                                ctx, scratch_pool));
-  SVN_ERR(svn_client__open_ra_session_internal(&source_ra_session, NULL,
-                                               url2, NULL, NULL, FALSE, FALSE,
-                                               ctx, scratch_pool));
-
-  SVN_ERR(svn_client__get_revision_number(&rev2, NULL, ctx->wc_ctx,
-                                          "",
-                                          source_ra_session, peg_revision,
-                                          scratch_pool));
 
   SVN_ERR(calculate_left_hand_side(&url1, &rev1,
                                    &merged_to_source_mergeinfo_catalog,

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.c Tue Aug 16 09:38:37 2011
@@ -476,28 +476,66 @@ svn_client__get_repos_mergeinfo_catalog(
   apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
-  svn_mergeinfo_t repos_mergeinfo;
+  svn_mergeinfo_t repos_mergeinfo_cat;
   apr_array_header_t *rel_paths = apr_array_make(scratch_pool, 1,
                                                  sizeof(rel_path));
 
   APR_ARRAY_PUSH(rel_paths, const char *) = rel_path;
 
   /* Fetch the mergeinfo. */
-  err = svn_ra_get_mergeinfo2(ra_session, &repos_mergeinfo, rel_paths, rev,
-                              inherit, validate_inherited_mergeinfo,
+  err = svn_ra_get_mergeinfo2(ra_session, &repos_mergeinfo_cat, rel_paths,
+                              rev, inherit, validate_inherited_mergeinfo,
                               include_descendants, result_pool);
   if (err)
     {
       if (squelch_incapable && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
         {
           svn_error_clear(err);
-          repos_mergeinfo = NULL;
+          *mergeinfo_cat = NULL;
         }
       else
         return svn_error_trace(err);
     }
 
-  *mergeinfo_cat = repos_mergeinfo;
+  if (repos_mergeinfo_cat == NULL)
+    {
+      *mergeinfo_cat = NULL;
+    }
+  else
+    {
+      const char *repos_root;
+      const char *session_url;
+
+      SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, scratch_pool));
+      SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool));
+
+      if (strcmp(repos_root, session_url) == 0)
+        {
+          *mergeinfo_cat = repos_mergeinfo_cat;
+        }
+      else
+        {
+          apr_hash_index_t *hi;
+          svn_mergeinfo_catalog_t rekeyed_mergeinfo_cat =
+            apr_hash_make(result_pool);
+
+          for (hi = apr_hash_first(scratch_pool, repos_mergeinfo_cat);
+               hi;
+               hi = apr_hash_next(hi))
+            {
+              const char *path =
+                svn_path_url_add_component2(session_url,
+                                            svn__apr_hash_index_key(hi),
+                                            scratch_pool);
+              SVN_ERR(svn_ra_get_path_relative_to_root(ra_session, &path,
+                                                       path,
+                                                       result_pool));
+              apr_hash_set(rekeyed_mergeinfo_cat, path, APR_HASH_KEY_STRING,
+                           svn__apr_hash_index_val(hi));
+            }
+          *mergeinfo_cat = rekeyed_mergeinfo_cat;
+        }
+    }
   return SVN_NO_ERROR;
 }
 
@@ -560,6 +598,8 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   const char *local_abspath;
   const char *repos_root;
   const char *repos_relpath;
+  svn_mergeinfo_catalog_t target_mergeinfo_cat_wc = NULL;
+  svn_mergeinfo_catalog_t target_mergeinfo_cat_repos = NULL;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, target_wcpath,
                                   scratch_pool));
@@ -581,23 +621,37 @@ svn_client__get_wc_or_repos_mergeinfo_ca
   else
     url = NULL;
 
+  if (!repos_only)
+    {
+      SVN_ERR(svn_client__get_wc_mergeinfo_catalog(&target_mergeinfo_cat_wc,
+                                                   inherited,
+                                                   include_descendants,
+                                                   inherit,
+                                                   local_abspath,
+                                                   NULL, NULL,
+                                                   ignore_invalid_mergeinfo,
+                                                   ctx,
+                                                   result_pool,
+                                                   scratch_pool));
+
+      /* If we want LOCAL_ABSPATH's inherited mergeinfo, were we able to
+         get it from the working copy?  If not, then we must ask the
+         repository. */
+      if (! ((*inherited)
+             || (inherit == svn_mergeinfo_explicit)
+             || (repos_relpath
+                 && target_mergeinfo_cat_wc
+                 && apr_hash_get(target_mergeinfo_cat_wc, repos_relpath,
+                                 APR_HASH_KEY_STRING))))
+        {
+          repos_only = TRUE;
+          /* We already have any subtree mergeinfo from the working copy, no
+             need to ask the server for it again. */
+          include_descendants = FALSE;
+        }
+    }
+
   if (repos_only)
-    *target_mergeinfo_catalog = NULL;
-  else
-    SVN_ERR(svn_client__get_wc_mergeinfo_catalog(target_mergeinfo_catalog,
-                                                 inherited,
-                                                 include_descendants,
-                                                 inherit,
-                                                 local_abspath,
-                                                 NULL, NULL,
-                                                 ignore_invalid_mergeinfo,
-                                                 ctx,
-                                                 result_pool, scratch_pool));
-
-  /* If there is no WC mergeinfo check the repository for inherited
-     mergeinfo, unless TARGET_WCPATH is a local addition or has a
-     local modification which has removed all of its pristine mergeinfo. */
-  if (*target_mergeinfo_catalog == NULL)
     {
       /* No need to check the repos if this is a local addition. */
       if (url != NULL)
@@ -631,13 +685,14 @@ svn_client__get_wc_or_repos_mergeinfo_ca
                 }
 
               SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
-                        target_mergeinfo_catalog, ra_session,
+                        &target_mergeinfo_cat_repos, ra_session,
                         "", target_rev, inherit,
-                        TRUE, FALSE, TRUE,
+                        TRUE, include_descendants, TRUE,
                         result_pool, scratch_pool));
 
-              if (*target_mergeinfo_catalog
-                  && apr_hash_get(*target_mergeinfo_catalog, "",
+              if (target_mergeinfo_cat_repos
+                  && apr_hash_get(target_mergeinfo_cat_repos,
+                                  repos_relpath,
                                   APR_HASH_KEY_STRING))
                 {
                   *inherited = TRUE;
@@ -660,6 +715,25 @@ svn_client__get_wc_or_repos_mergeinfo_ca
             }
         }
     }
+
+  /* Combine the mergeinfo from the working copy and repository as needed. */
+  if (target_mergeinfo_cat_wc)
+    {
+      *target_mergeinfo_catalog = target_mergeinfo_cat_wc;
+      if (target_mergeinfo_cat_repos)
+        SVN_ERR(svn_mergeinfo_catalog_merge(*target_mergeinfo_catalog,
+                                            target_mergeinfo_cat_repos,
+                                            result_pool, scratch_pool));
+    }
+  else if (target_mergeinfo_cat_repos)
+    {
+      *target_mergeinfo_catalog = target_mergeinfo_cat_repos;
+    }
+  else
+    {
+      *target_mergeinfo_catalog = NULL;
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1074,41 +1148,11 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
 
   if (use_url)
     {
-      svn_mergeinfo_catalog_t tmp_catalog;
-
       rev = peg_rev;
       SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
-        &tmp_catalog, ra_session, "", rev, svn_mergeinfo_inherited,
+        mergeinfo_catalog, ra_session, "", rev, svn_mergeinfo_inherited,
         FALSE, include_descendants, TRUE,
         result_pool, scratch_pool));
-
-      /* If we're not querying the root of the repository, the catalog
-         we fetched will be keyed on paths relative to the session
-         URL.  But our caller is expecting repository relpaths.  So we
-         do a little dance...  */
-      if (tmp_catalog && (strcmp(url, *repos_root) != 0))
-        {
-          apr_hash_index_t *hi;
-
-          *mergeinfo_catalog = apr_hash_make(result_pool);
-
-          for (hi = apr_hash_first(scratch_pool, tmp_catalog);
-               hi; hi = apr_hash_next(hi))
-            {
-              /* session-relpath -> repos-url -> repos-relpath */
-              const char *path =
-                svn_path_url_add_component2(url, svn__apr_hash_index_key(hi),
-                                            scratch_pool);
-              SVN_ERR(svn_ra_get_path_relative_to_root(ra_session, &path, path,
-                                                       result_pool));
-              apr_hash_set(*mergeinfo_catalog, path, APR_HASH_KEY_STRING,
-                           svn__apr_hash_index_val(hi));
-            }
-        }
-      else
-        {
-          *mergeinfo_catalog = tmp_catalog;
-        }
     }
   else /* ! svn_path_is_url() */
     {
@@ -1312,6 +1356,8 @@ find_nearest_ancestor(const apr_array_he
    svn_log_entry_receiver_t callback. */
 struct filter_log_entry_baton_t
 {
+  /* Is TRUE if RANGELIST describes potentially merged revisions, is FALSE
+     if RANGELIST describes potentially eligible revisions. */
   svn_boolean_t filtering_merged;
 
   /* Unsorted array of repository relative paths representing the merge
@@ -1329,8 +1375,9 @@ struct filter_log_entry_baton_t
      TARGET_MERGEINFO_CATALOG. */
   apr_array_header_t *depth_first_catalog_index;
 
-  /* A rangelist describing all the ranges merged to ABS_REPOS_TARGET_PATH
-     from the */
+  /* A rangelist describing all the revisions potentially merged or
+     potentially eligible for merging (see FILTERING_MERGED) based on
+     the target's explicit or inherited mergeinfo. */
   const apr_array_header_t *rangelist;
 
   /* The wrapped svn_log_entry_receiver_t callback and baton which
@@ -1345,9 +1392,18 @@ struct filter_log_entry_baton_t
    `struct filter_log_entry_baton_t *'.
 
    Call the wrapped log receiver BATON->log_receiver (with
-   BATON->log_receiver_baton), only if the log entry falls within the
-   ranges in BATON->rangelist.
- */
+   BATON->log_receiver_baton) if:
+   
+   BATON->FILTERING_MERGED is FALSE and the changes represented by LOG_ENTRY
+   have been fully merged from BATON->MERGE_SOURCE_PATHS to the WC target
+   based on the mergeinfo for the WC contained in BATON->TARGET_MERGEINFO_CATALOG.
+
+   Or
+
+   BATON->FILTERING_MERGED is TRUE and the changes represented by LOG_ENTRY
+   have not been merged, or only partially merged, from
+   BATON->MERGE_SOURCE_PATHS to the WC target based on the mergeinfo for the
+   WC contained in BATON->TARGET_MERGEINFO_CATALOG. */
 static svn_error_t *
 filter_log_entry_with_rangelist(void *baton,
                                 svn_log_entry_t *log_entry,
@@ -1410,6 +1466,7 @@ filter_log_entry_with_rangelist(void *ba
           apr_hash_index_t *hi2;
           svn_boolean_t found_this_revision = FALSE;
           const char *merge_source_rel_target;
+          const char *merge_source_path;
 
           svn_pool_clear(iterpool);
 
@@ -1417,8 +1474,8 @@ filter_log_entry_with_rangelist(void *ba
              merge sources.  If not then ignore this path.  */
           for (i = 0; i < fleb->merge_source_paths->nelts; i++)
             {
-              const char *merge_source_path
-                = APR_ARRAY_IDX(fleb->merge_source_paths, i, const char *);
+              merge_source_path = APR_ARRAY_IDX(fleb->merge_source_paths,
+                                                i, const char *);
 
               merge_source_rel_target
                 = svn_fspath__skip_ancestor(merge_source_path, path);
@@ -1452,20 +1509,33 @@ filter_log_entry_with_rangelist(void *ba
                    hi2;
                    hi2 = apr_hash_next(hi2))
                 {
+                  const char *mergeinfo_path = svn__apr_hash_index_key(hi2);
                   apr_array_header_t *rangelist = svn__apr_hash_index_val(hi2);
-                  SVN_ERR(svn_rangelist_intersect(&intersection, rangelist,
-                                                  this_rev_rangelist, FALSE,
-                                                  iterpool));
-                  if (intersection->nelts)
+
+                  /* Does the mergeinfo for PATH reflect if
+                     LOG_ENTRY->REVISION was previously merged
+                     from MERGE_SOURCE_PATH? */
+                  if (svn_fspath__is_ancestor(merge_source_path,
+                                              mergeinfo_path))
                     {
+                      /* Something was merged from MERGE_SOURCE_PATH, does
+                         it include LOG_ENTRY->REVISION? */
                       SVN_ERR(svn_rangelist_intersect(&intersection,
                                                       rangelist,
                                                       this_rev_rangelist,
-                                                      TRUE, iterpool));
+                                                      FALSE,
+                                                      iterpool));
                       if (intersection->nelts)
                         {
-                          found_this_revision = TRUE;
-                          break;
+                          SVN_ERR(svn_rangelist_intersect(&intersection,
+                                                          rangelist,
+                                                          this_rev_rangelist,
+                                                          TRUE, iterpool));
+                          if (intersection->nelts)
+                            {
+                              found_this_revision = TRUE;
+                              break;
+                            }
                         }
                     }
                 }
@@ -1847,16 +1917,20 @@ svn_client_mergeinfo_log(svn_boolean_t f
          subtrees. */
       if (apr_hash_count(merged_noninheritable))
         {
+          apr_pool_t *iterpool2 = svn_pool_create(iterpool);
+
           for (hi = apr_hash_first(iterpool, merged_noninheritable);
                hi;
                hi = apr_hash_next(hi))
             {
               apr_array_header_t *list = svn__apr_hash_index_val(hi);
-              SVN_ERR(svn_rangelist_merge(
-                &master_noninheritable_rangelist,
+              svn_pool_clear(iterpool2);
+              SVN_ERR(svn_rangelist_merge2(
+                master_noninheritable_rangelist,
                 svn_rangelist_dup(list, scratch_pool),
-                scratch_pool));
+                scratch_pool, iterpool2));
             }
+          svn_pool_destroy(iterpool2);
         }
 
       /* Find the intersection of the inheritable part of TGT_MERGEINFO
@@ -1874,6 +1948,7 @@ svn_client_mergeinfo_log(svn_boolean_t f
              to SUBTREE_PATH. */
           apr_array_header_t *subtree_merged_rangelist =
             apr_array_make(scratch_pool, 1, sizeof(svn_merge_range_t *));
+          apr_pool_t *iterpool2 = svn_pool_create(iterpool);
 
           for (hi = apr_hash_first(iterpool, merged);
                hi;
@@ -1881,15 +1956,17 @@ svn_client_mergeinfo_log(svn_boolean_t f
             {
               apr_array_header_t *list = svn__apr_hash_index_val(hi);
 
-              SVN_ERR(svn_rangelist_merge(&master_inheritable_rangelist,
-                                          svn_rangelist_dup(list,
-                                                            scratch_pool),
-                                          scratch_pool));
-              SVN_ERR(svn_rangelist_merge(&subtree_merged_rangelist,
-                                          svn_rangelist_dup(list,
+              svn_pool_clear(iterpool2);
+              SVN_ERR(svn_rangelist_merge2(master_inheritable_rangelist,
+                                           svn_rangelist_dup(list,
+                                                             scratch_pool),
+                                           scratch_pool, iterpool2));
+              SVN_ERR(svn_rangelist_merge2(subtree_merged_rangelist,
+                                           svn_rangelist_dup(list,
                                                             scratch_pool),
-                                          scratch_pool));
+                                           scratch_pool, iterpool2));
             }
+          svn_pool_destroy(iterpool2);
 
           apr_hash_set(inheritable_subtree_merges,
                        apr_pstrdup(scratch_pool, subtree_path),
@@ -1937,9 +2014,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
           if (deleted_rangelist->nelts)
             {
               svn_rangelist__set_inheritance(deleted_rangelist, FALSE);
-              SVN_ERR(svn_rangelist_merge(&master_noninheritable_rangelist,
-                                          deleted_rangelist,
-                                          scratch_pool));
+              SVN_ERR(svn_rangelist_merge2(master_noninheritable_rangelist,
+                                           deleted_rangelist,
+                                           scratch_pool, iterpool));
               SVN_ERR(svn_rangelist_remove(&master_inheritable_rangelist,
                                            deleted_rangelist,
                                            master_inheritable_rangelist,
@@ -1952,9 +2029,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
   if (finding_merged)
     {
       /* Roll all the merged revisions into one rangelist. */
-      SVN_ERR(svn_rangelist_merge(&master_inheritable_rangelist,
-                                  master_noninheritable_rangelist,
-                                  scratch_pool));
+      SVN_ERR(svn_rangelist_merge2(master_inheritable_rangelist,
+                                   master_noninheritable_rangelist,
+                                   scratch_pool, scratch_pool));
 
     }
   else
@@ -1970,9 +2047,10 @@ svn_client_mergeinfo_log(svn_boolean_t f
           apr_array_header_t *subtree_merged_rangelist =
             svn__apr_hash_index_val(hi);
 
-          SVN_ERR(svn_rangelist_merge(&source_master_rangelist,
-                                      subtree_merged_rangelist,
-                                      iterpool));
+          svn_pool_clear(iterpool);
+          SVN_ERR(svn_rangelist_merge2(source_master_rangelist,
+                                       subtree_merged_rangelist,
+                                       scratch_pool, iterpool));
         }
 
       /* From what might be eligible subtract what we know is partially merged
@@ -1981,9 +2059,9 @@ svn_client_mergeinfo_log(svn_boolean_t f
                                    master_noninheritable_rangelist,
                                    source_master_rangelist,
                                    FALSE, scratch_pool));
-      SVN_ERR(svn_rangelist_merge(&source_master_rangelist,
-                                  master_noninheritable_rangelist,
-                                  scratch_pool));
+      SVN_ERR(svn_rangelist_merge2(source_master_rangelist,
+                                   master_noninheritable_rangelist,
+                                   scratch_pool, scratch_pool));
       SVN_ERR(svn_rangelist_remove(&master_inheritable_rangelist,
                                    master_inheritable_rangelist,
                                    source_master_rangelist,

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.h?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/mergeinfo.h Tue Aug 16 09:38:37 2011
@@ -99,7 +99,7 @@ svn_client__merge_path_dup(const svn_cli
    the range of the parent's last committed revision to the parent's base
    revision (inclusive) or is LOCAL_ABSPATH is a local addition.  If asking
    for the inherited mergeinfo of an added path (i.e. one with no base
-   revision), that path may inherit mergeinfo from it's nearest parent
+   revision), that path may inherit mergeinfo from its nearest parent
    with a base revision and explicit mergeinfo.
 
    INHERIT indicates whether explicit, explicit or inherited, or only
@@ -186,7 +186,7 @@ svn_client__get_repos_mergeinfo(svn_ra_s
 /* If INCLUDE_DESCENDANTS is FALSE, behave exactly like
    svn_client__get_repos_mergeinfo() except the mergeinfo for REL_PATH
    is put in the mergeinfo catalog MERGEINFO_CAT, with the key being
-   REL_PATH itself.
+   the repository root-relative path of REL_PATH.
 
    If INCLUDE_DESCENDANTS is true, then any subtrees under REL_PATH
    with explicit mergeinfo are also included in MERGEINFO_CAT.  The

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/patch.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/patch.c Tue Aug 16 09:38:37 2011
@@ -365,7 +365,7 @@ obtain_eol_and_keywords_for_file(apr_has
 static svn_error_t *
 resolve_target_path(patch_target_t *target,
                     const char *path_from_patchfile,
-                    const char *local_abspath,
+                    const char *wcroot_abspath,
                     int strip_count,
                     svn_boolean_t prop_changes_only,
                     svn_wc_context_t *wc_ctx,
@@ -398,7 +398,8 @@ resolve_target_path(patch_target_t *targ
 
   if (svn_dirent_is_absolute(stripped_path))
     {
-      target->local_relpath = svn_dirent_is_child(local_abspath, stripped_path,
+      target->local_relpath = svn_dirent_is_child(wcroot_abspath,
+                                                  stripped_path,
                                                   result_pool);
 
       if (! target->local_relpath)
@@ -419,7 +420,7 @@ resolve_target_path(patch_target_t *targ
   /* Make sure the path is secure to use. We want the target to be inside
    * of the working copy and not be fooled by symlinks it might contain. */
   SVN_ERR(svn_dirent_is_under_root(&under_root,
-                                   &target->local_abspath, local_abspath,
+                                   &target->local_abspath, wcroot_abspath,
                                    target->local_relpath, result_pool));
 
   if (! under_root)
@@ -478,11 +479,32 @@ resolve_target_path(patch_target_t *targ
       return SVN_NO_ERROR;
     }
 
-  /* ### Shouldn't libsvn_wc flag an obstruction in this case? */
-  if (target->locally_deleted && target->kind_on_disk != svn_node_none)
+  if (target->locally_deleted)
     {
-      target->skipped = TRUE;
-      return SVN_NO_ERROR;
+      const char *moved_to_abspath;
+
+      SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
+                                          wc_ctx, target->local_abspath,
+                                          result_pool, scratch_pool));
+      if (moved_to_abspath)
+        {
+          target->local_abspath = moved_to_abspath;
+          target->local_relpath = svn_dirent_skip_ancestor(wcroot_abspath,
+                                                          moved_to_abspath);
+          SVN_ERR_ASSERT(target->local_relpath &&
+                         target->local_relpath[0] != '\0');
+
+          /* As far as we are concerned this target is not locally deleted. */
+          target->locally_deleted = FALSE;
+
+          SVN_ERR(svn_io_check_path(target->local_abspath,
+                                    &target->kind_on_disk, scratch_pool));
+        }
+      else if (target->kind_on_disk != svn_node_none)
+        {
+          target->skipped = TRUE;
+          return SVN_NO_ERROR;
+        }
     }
 
   return SVN_NO_ERROR;
@@ -828,7 +850,7 @@ choose_target_filename(const svn_patch_t
 static svn_error_t *
 init_patch_target(patch_target_t **patch_target,
                   const svn_patch_t *patch,
-                  const char *base_dir,
+                  const char *wcroot_abspath,
                   svn_wc_context_t *wc_ctx, int strip_count,
                   svn_boolean_t remove_tempfiles,
                   apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -873,7 +895,7 @@ init_patch_target(patch_target_t **patch
   target->prop_targets = apr_hash_make(result_pool);
 
   SVN_ERR(resolve_target_path(target, choose_target_filename(patch),
-                              base_dir, strip_count, prop_changes_only,
+                              wcroot_abspath, strip_count, prop_changes_only,
                               wc_ctx, result_pool, scratch_pool));
   if (! target->skipped)
     {

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c Tue Aug 16 09:38:37 2011
@@ -67,9 +67,6 @@ struct edit_baton {
   const svn_wc_diff_callbacks4_t *diff_callbacks;
   void *diff_cmd_baton;
 
-  /* DRY_RUN is TRUE if this is a dry-run diff, false otherwise. */
-  svn_boolean_t dry_run;
-
   /* RA_SESSION is the open session for making requests to the RA layer */
   svn_ra_session_t *ra_session;
 
@@ -334,11 +331,11 @@ get_file_from_ra(struct file_baton *b,
       svn_stream_t *fstream;
 
       SVN_ERR(svn_stream_open_unique(&fstream, &(b->path_start_revision), NULL,
-                                     svn_io_file_del_on_pool_cleanup, b->pool,
-                                     b->pool));
+                                     svn_io_file_del_on_pool_cleanup,
+                                     scratch_pool, scratch_pool));
 
       fstream = svn_stream_checksummed2(fstream, NULL, &b->start_md5_checksum,
-                                        svn_checksum_md5, TRUE, b->pool);
+                                        svn_checksum_md5, TRUE, scratch_pool);
 
       /* Retrieve the file and its properties */
       SVN_ERR(svn_ra_get_file(b->edit_baton->ra_session,
@@ -456,7 +453,7 @@ get_empty_file(struct edit_baton *eb,
   return SVN_NO_ERROR;
 }
 
-/* An editor function. The root of the comparison hierarchy */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 set_target_revision(void *edit_baton,
                     svn_revnum_t target_revision,
@@ -468,7 +465,7 @@ set_target_revision(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
-/* An editor function. The root of the comparison hierarchy */
+/* An svn_delta_editor_t function. The root of the comparison hierarchy */
 static svn_error_t *
 open_root(void *edit_baton,
           svn_revnum_t base_revision,
@@ -570,7 +567,7 @@ diff_deleted_dir(const char *dir,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 delete_entry(const char *path,
              svn_revnum_t base_revision,
@@ -671,7 +668,7 @@ delete_entry(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 add_directory(const char *path,
               void *parent_baton,
@@ -761,7 +758,7 @@ add_directory(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 open_directory(const char *path,
                void *parent_baton,
@@ -795,7 +792,7 @@ open_directory(const char *path,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 add_file(const char *path,
          void *parent_baton,
@@ -825,7 +822,7 @@ add_file(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 open_file(const char *path,
           void *parent_baton,
@@ -875,7 +872,7 @@ window_handler(svn_txdelta_window_t *win
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 apply_textdelta(void *file_baton,
                 const char *base_md5_digest,
@@ -898,7 +895,7 @@ apply_textdelta(void *file_baton,
 
   /* We need the expected pristine file, so go get it */
   if (!b->added)
-    SVN_ERR(get_file_from_ra(b, FALSE, b->pool));
+    SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
   else
     SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision)));
 
@@ -942,7 +939,7 @@ apply_textdelta(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  When the file is closed we have a temporary
+/* An svn_delta_editor_t function.  When the file is closed we have a temporary
  * file containing a pristine version of the repository file. This can
  * be compared against the working copy.
  *
@@ -1089,7 +1086,7 @@ close_file(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 close_directory(void *dir_baton,
                 apr_pool_t *pool)
@@ -1113,9 +1110,6 @@ close_directory(void *dir_baton,
   if (!b->added && b->propchanges->nelts > 0)
     remove_non_prop_changes(b->pristine_props, b->propchanges);
 
-  /* Don't do the props_changed stuff if this is a dry_run and we don't
-     have an access baton, since in that case the directory will already
-     have been recognised as added, in which case they cannot conflict. */
   if (b->propchanges->nelts > 0)
     {
       svn_boolean_t tree_conflicted = FALSE;
@@ -1194,7 +1188,7 @@ close_directory(void *dir_baton,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 change_file_prop(void *file_baton,
                  const char *name,
@@ -1215,7 +1209,7 @@ change_file_prop(void *file_baton,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 change_dir_prop(void *dir_baton,
                 const char *name,
@@ -1237,7 +1231,7 @@ change_dir_prop(void *dir_baton,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 close_edit(void *edit_baton,
            apr_pool_t *pool)
@@ -1249,7 +1243,7 @@ close_edit(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 absent_directory(const char *path,
                  void *parent_baton,
@@ -1278,7 +1272,7 @@ absent_directory(const char *path,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 absent_file(const char *path,
             void *parent_baton,
@@ -1316,15 +1310,13 @@ svn_client__get_diff_editor(const svn_de
                             svn_ra_session_t *ra_session,
                             svn_revnum_t revision,
                             svn_boolean_t walk_deleted_dirs,
-                            svn_boolean_t dry_run,
                             const svn_wc_diff_callbacks4_t *diff_callbacks,
                             void *diff_cmd_baton,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
                             svn_wc_notify_func2_t notify_func,
                             void *notify_baton,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool)
+                            apr_pool_t *result_pool)
 {
   apr_pool_t *editor_pool = svn_pool_create(result_pool);
   svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
@@ -1339,7 +1331,6 @@ svn_client__get_diff_editor(const svn_de
   eb->depth = depth;
   eb->diff_callbacks = diff_callbacks;
   eb->diff_cmd_baton = diff_cmd_baton;
-  eb->dry_run = dry_run;
   eb->ra_session = ra_session;
 
   eb->revision = revision;

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff_summarize.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff_summarize.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff_summarize.c Tue Aug 16 09:38:37 2011
@@ -128,7 +128,7 @@ ensure_summarize(struct item_baton *ib)
 }
 
 
-/* An editor function. The root of the comparison hierarchy */
+/* An svn_delta_editor_t function. The root of the comparison hierarchy */
 static svn_error_t *
 open_root(void *edit_baton,
           svn_revnum_t base_revision,
@@ -219,7 +219,7 @@ diff_deleted_dir(const char *dir,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 delete_entry(const char *path,
              svn_revnum_t base_revision,
@@ -257,7 +257,7 @@ delete_entry(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 add_directory(const char *path,
               void *parent_baton,
@@ -277,7 +277,7 @@ add_directory(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 open_directory(const char *path,
                void *parent_baton,
@@ -295,7 +295,7 @@ open_directory(const char *path,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 close_directory(void *dir_baton,
                 apr_pool_t *pool)
@@ -311,7 +311,7 @@ close_directory(void *dir_baton,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 add_file(const char *path,
          void *parent_baton,
@@ -331,7 +331,7 @@ add_file(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 open_file(const char *path,
           void *parent_baton,
@@ -348,7 +348,7 @@ open_file(const char *path,
   return SVN_NO_ERROR;
 }
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 apply_textdelta(void *file_baton,
                 const char *base_checksum,
@@ -369,7 +369,7 @@ apply_textdelta(void *file_baton,
 }
 
 
-/* An editor function.  */
+/* An svn_delta_editor_t function.  */
 static svn_error_t *
 close_file(void *file_baton,
            const char *text_checksum,
@@ -386,7 +386,7 @@ close_file(void *file_baton,
 }
 
 
-/* An editor function, implementing both change_file_prop and
+/* An svn_delta_editor_t function, implementing both change_file_prop and
  * change_dir_prop.  */
 static svn_error_t *
 change_prop(void *entry_baton,

Modified: subversion/branches/svn-bisect/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/status.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/status.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/status.c Tue Aug 16 09:38:37 2011
@@ -385,7 +385,7 @@ svn_client_status5(svn_revnum_t *result_
           svn_boolean_t added;
 
           /* Our status target does not exist in HEAD.  If we've got
-             it localled added, that's okay.  But if it was previously
+             it locally added, that's okay.  But if it was previously
              versioned, then it must have since been deleted from the
              repository.  (Note that "locally replaced" doesn't count
              as "added" in this case.)  */
@@ -563,6 +563,17 @@ svn_client_status_dup(const svn_client_s
                                                              result_pool);
     }
 
+  if (status->moved_from_abspath)
+    st->moved_from_abspath =
+      apr_pstrdup(result_pool, status->moved_from_abspath);
+
+  if (status->moved_to_abspath)
+    st->moved_to_abspath = apr_pstrdup(result_pool, status->moved_to_abspath);
+
+  if (status->moved_to_op_root_abspath)
+    st->moved_to_op_root_abspath =
+      apr_pstrdup(result_pool, status->moved_to_op_root_abspath);
+
   return st;
 }
 
@@ -667,6 +678,10 @@ svn_client__create_status(svn_client_sta
         (*cst)->node_status = svn_wc_status_conflicted;
     }
 
+  (*cst)->moved_from_abspath = status->moved_from_abspath;
+  (*cst)->moved_to_abspath = status->moved_to_abspath;
+  (*cst)->moved_to_op_root_abspath = status->moved_to_op_root_abspath;
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs/fs-loader.c Tue Aug 16 09:38:37 2011
@@ -29,6 +29,7 @@
 #include <apr_thread_mutex.h>
 #include <apr_uuid.h>
 
+#include "svn_ctype.h"
 #include "svn_types.h"
 #include "svn_dso.h"
 #include "svn_version.h"
@@ -1305,6 +1306,31 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t 
            _("Lock comment contains illegal characters"));
     }
 
+  /* Enforce that the token be an XML-safe URI. */
+  if (token)
+    {
+      const char *c;
+
+      if (strncmp(token, "opaquelocktoken:", 16))
+        return svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+                                 _("Lock token URI '%s' has bad scheme; "
+                                   "expected '%s'"),
+                                 token, "opaquelocktoken");
+
+      for (c = token; *c; c++)
+        if (! svn_ctype_isascii(*c))
+          return svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+                                   _("Lock token '%s' is not ASCII "
+                                     "at byte %u"),
+                                   token, (unsigned)(c - token));
+
+      /* strlen(token) == c - token. */
+      if (! svn_xml_is_xml_safe(token, c - token))
+        return svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+                                 _("Lock token URI '%s' is not XML-safe"),
+                                 token);
+    }
+
   if (expiration_date < 0)
         return svn_error_create
           (SVN_ERR_INCORRECT_PARAMS, NULL,

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs_fs.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/fs_fs.c Tue Aug 16 09:38:37 2011
@@ -826,8 +826,10 @@ get_writable_proto_rev_body(svn_fs_t *fs
 
   if (err)
     {
-      svn_error_clear(unlock_proto_rev_list_locked(fs, txn_id, *lockcookie,
-                                                   pool));
+      err = svn_error_compose_create(
+              err,
+              unlock_proto_rev_list_locked(fs, txn_id, *lockcookie, pool));
+      
       *lockcookie = NULL;
     }
 
@@ -6629,7 +6631,7 @@ svn_fs_fs__create(svn_fs_t *fs,
                               ? "0\n" : "0 1 1\n"),
                              pool));
   SVN_ERR(svn_io_file_create(path_lock(fs, pool), "", pool));
-  SVN_ERR(svn_fs_fs__set_uuid(fs, svn_uuid_generate(pool), pool));
+  SVN_ERR(svn_fs_fs__set_uuid(fs, NULL, pool));
 
   SVN_ERR(write_revision_zero(fs));
 
@@ -7804,14 +7806,19 @@ svn_fs_fs__verify(svn_fs_t *fs,
                   apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
+  svn_boolean_t exists;
 
   if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
     return SVN_NO_ERROR;
 
-  /* Don't take any lock. */
-  SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
-                                        cancel_func, cancel_baton,
-                                        pool));
+  /* Do not attempt to walk the rep-cache database if its file does not exists,
+     since doing so would create it --- which may confuse the administrator. */
+  SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
+  if (exists)
+    /* Don't take any lock. */
+    SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
+                                          cancel_func, cancel_baton,
+                                          pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.c Tue Aug 16 09:38:37 2011
@@ -43,7 +43,12 @@ REP_CACHE_DB_SQL_DECLARE_STATEMENTS(stat
 
 
 /** Helper functions. **/
-
+static APR_INLINE const char *
+path_rep_cache_db(const char *fs_path,
+                  apr_pool_t *result_pool)
+{
+  return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool);
+}
 
 /* Check that REP refers to a revision that exists in FS. */
 static svn_error_t *
@@ -91,7 +96,7 @@ open_rep_cache(void *baton,
 
   /* Open (or create) the sqlite database.  It will be automatically
      closed when fs->pool is destoyed. */
-  db_path = svn_dirent_join(fs->path, REP_CACHE_DB_NAME, pool);
+  db_path = path_rep_cache_db(fs->path, pool);
   SVN_ERR(svn_sqlite__open(&ffd->rep_cache_db, db_path,
                            svn_sqlite__mode_rwcreate, statements,
                            0, NULL,
@@ -120,6 +125,19 @@ svn_fs_fs__open_rep_cache(svn_fs_t *fs,
 }
 
 svn_error_t *
+svn_fs_fs__exists_rep_cache(svn_boolean_t *exists,
+                            svn_fs_t *fs, apr_pool_t *pool)
+{
+  svn_node_kind_t kind;
+
+  SVN_ERR(svn_io_check_path(path_rep_cache_db(fs->path, pool),
+                            &kind, pool));
+
+  *exists = (kind != svn_node_none);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
                               svn_error_t *(*walker)(representation_t *,
                                                      void *,

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.h?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/rep-cache.h Tue Aug 16 09:38:37 2011
@@ -40,6 +40,11 @@ svn_error_t *
 svn_fs_fs__open_rep_cache(svn_fs_t *fs,
                           apr_pool_t *pool);
 
+/* Set *EXISTS to TRUE iff the rep-cache DB file exists. */
+svn_error_t *
+svn_fs_fs__exists_rep_cache(svn_boolean_t *exists,
+                            svn_fs_t *fs, apr_pool_t *pool);
+
 /* Iterate all representations currently in FS's cache. */
 svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,

Propchange: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/temp_serializer.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Aug 16 09:38:37 2011
@@ -1,2 +1,2 @@
 /subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.c:1143907,1143971,1144017,1144568,1146145
-/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c:1067687-1072301,1140046-1148712
+/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.c:1067687-1072301,1140046-1158163

Propchange: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/temp_serializer.h
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Aug 16 09:38:37 2011
@@ -1,2 +1,2 @@
 /subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.h:1143907,1143971,1144017,1144568,1146145
-/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h:1067687-1072301,1140046-1148712
+/subversion/trunk/subversion/libsvn_fs_fs/temp_serializer.h:1067687-1072301,1140046-1158163

Modified: subversion/branches/svn-bisect/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_fs_fs/tree.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_fs_fs/tree.c Tue Aug 16 09:38:37 2011
@@ -2925,7 +2925,7 @@ prev_location(const char **prev_path,
               const char *path,
               apr_pool_t *pool)
 {
-  const char *copy_path, *copy_src_path, *remainder = "";
+  const char *copy_path, *copy_src_path, *remainder_path = "";
   svn_fs_root_t *copy_root;
   svn_revnum_t copy_src_rev;
 
@@ -2955,8 +2955,8 @@ prev_location(const char **prev_path,
   SVN_ERR(fs_copied_from(&copy_src_rev, &copy_src_path,
                          copy_root, copy_path, pool));
   if (strcmp(copy_path, path) != 0)
-    remainder = svn_relpath__is_child(copy_path, path, pool);
-  *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
+    remainder_path = svn_relpath__is_child(copy_path, path, pool);
+  *prev_path = svn_fspath__join(copy_src_path, remainder_path, pool);
   *prev_rev = copy_src_rev;
   return SVN_NO_ERROR;
 }
@@ -3184,7 +3184,7 @@ history_prev(void *baton, apr_pool_t *po
 
   if (copyroot_rev > commit_rev)
     {
-      const char *remainder;
+      const char *remainder_path;
       const char *copy_dst, *copy_src;
       svn_fs_root_t *copyroot_root;
 
@@ -3202,11 +3202,11 @@ history_prev(void *baton, apr_pool_t *po
          one of these other criteria ... ### for now just fallback to
          the old copy hunt algorithm. */
       if (strcmp(path, copy_dst) == 0)
-        remainder = "";
+        remainder_path = "";
       else
-        remainder = svn_relpath__is_child(copy_dst, path, pool);
+        remainder_path = svn_relpath__is_child(copy_dst, path, pool);
 
-      if (remainder)
+      if (remainder_path)
         {
           /* If we get here, then our current path is the destination
              of, or the child of the destination of, a copy.  Fill
@@ -3215,7 +3215,7 @@ history_prev(void *baton, apr_pool_t *po
           SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copy_src, node, pool));
 
           dst_rev = copyroot_rev;
-          src_path = svn_fspath__join(copy_src, remainder, pool);
+          src_path = svn_fspath__join(copy_src, remainder_path, pool);
         }
     }
 

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_local/ra_plugin.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_local/ra_plugin.c Tue Aug 16 09:38:37 2011
@@ -860,14 +860,26 @@ struct log_baton
 };
 
 static svn_error_t *
-cancellation_log_receiver(void *baton,
-                          svn_log_entry_t *log_entry,
-                          apr_pool_t *pool)
+log_receiver_wrapper(void *baton,
+                     svn_log_entry_t *log_entry,
+                     apr_pool_t *pool)
 {
   struct log_baton *b = baton;
   svn_ra_local__session_baton_t *sess = b->sess;
 
-  SVN_ERR((sess->callbacks->cancel_func)(sess->callback_baton));
+  if (sess->callbacks->cancel_func)
+    SVN_ERR((sess->callbacks->cancel_func)(sess->callback_baton));
+
+  /* For consistency with the other RA layers, replace an empty
+     changed-paths hash with a NULL one.
+
+     ### Should this be done by svn_ra_get_log2() instead, then? */
+  if ((log_entry->changed_paths2)
+      && (apr_hash_count(log_entry->changed_paths2) == 0))
+    {
+      log_entry->changed_paths = NULL;
+      log_entry->changed_paths2 = NULL;
+    }
 
   return b->real_cb(b->real_baton, log_entry, pool);
 }
@@ -904,16 +916,11 @@ svn_ra_local__get_log(svn_ra_session_t *
         }
     }
 
-  if (sess->callbacks &&
-      sess->callbacks->cancel_func)
-    {
-      lb.real_cb = receiver;
-      lb.real_baton = receiver_baton;
-      lb.sess = sess;
-
-      receiver = cancellation_log_receiver;
-      receiver_baton = &lb;
-    }
+  lb.real_cb = receiver;
+  lb.real_baton = receiver_baton;
+  lb.sess = sess;
+  receiver = log_receiver_wrapper;
+  receiver_baton = &lb;
 
   return svn_repos_get_logs4(sess->repos,
                              abs_paths,

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_neon/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_neon/fetch.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_neon/fetch.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_neon/fetch.c Tue Aug 16 09:38:37 2011
@@ -528,7 +528,10 @@ static svn_error_t *simple_fetch_file(sv
                              TRUE, pool));
 
   /* close the handler, since the file reading completed successfully. */
-  return (*frc.handler)(NULL, frc.handler_baton);
+  if (frc.stream)
+    return svn_stream_close(frc.stream);
+  else
+    return (*frc.handler)(NULL, frc.handler_baton);
 }
 
 /* Helper for svn_ra_neon__get_file.  This implements

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_neon/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_neon/log.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_neon/log.c Tue Aug 16 09:38:37 2011
@@ -529,5 +529,5 @@ svn_error_t * svn_ra_neon__get_log(svn_r
       err = SVN_NO_ERROR;
     }
 
-  return err;
+  return svn_error_trace(err);
 }

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_neon/util.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_neon/util.c Tue Aug 16 09:38:37 2011
@@ -1589,8 +1589,9 @@ svn_ra_neon__uri_unparse(const ne_uri *u
   /* Unparse uri. */
   unparsed_uri = ne_uri_unparse(uri);
 
-  /* Copy string to result pool. */
-  result = apr_pstrdup(pool, unparsed_uri);
+  /* Copy string to result pool, and make sure it conforms to
+     Subversion rules */
+  result = svn_uri_canonicalize(unparsed_uri, pool);
 
   /* Free neon's allocated copy. */
   ne_free(unparsed_uri);

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_serf/commit.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_serf/commit.c Tue Aug 16 09:38:37 2011
@@ -355,19 +355,18 @@ checkout_dir(dir_context_t *dir)
   checkout_context_t *checkout_ctx;
   svn_ra_serf__handler_t *handler;
   svn_error_t *err;
-  dir_context_t *parent_dir = dir->parent_dir;
+  dir_context_t *p_dir = dir;
 
   if (dir->checkout)
     {
       return SVN_NO_ERROR;
     }
 
-  /* Is one of our parent dirs newly added?  If so, we're already
-   * implicitly checked out.
-   */
-  while (parent_dir)
+  /* Is this directory or one of our parent dirs newly added? 
+   * If so, we're already implicitly checked out. */
+  while (p_dir)
     {
-      if (parent_dir->added)
+      if (p_dir->added)
         {
           /* Implicitly checkout this dir now. */
           dir->checkout = apr_pcalloc(dir->pool, sizeof(*dir->checkout));
@@ -381,7 +380,7 @@ checkout_dir(dir_context_t *dir)
 
           return SVN_NO_ERROR;
         }
-      parent_dir = parent_dir->parent_dir;
+      p_dir = p_dir->parent_dir;
     }
 
   /* Checkout our directory into the activity URL now. */

Modified: subversion/branches/svn-bisect/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_ra_serf/getlocationsegments.c?rev=1158171&r1=1158170&r2=1158171&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_ra_serf/getlocationsegments.c Tue Aug 16 09:38:37 2011
@@ -184,7 +184,7 @@ svn_ra_serf__get_location_segments(svn_r
   svn_ra_serf__handler_t *handler;
   svn_ra_serf__xml_parser_t *parser_ctx;
   const char *relative_url, *basecoll_url, *req_url;
-  svn_error_t *err, *err2;
+  svn_error_t *err;
 
   gls_ctx = apr_pcalloc(pool, sizeof(*gls_ctx));
   gls_ctx->path = path;
@@ -233,20 +233,16 @@ svn_ra_serf__get_location_segments(svn_r
                             _("Location segment report failed on '%s'@'%ld'"),
                               path, peg_revision);
 
-  err2 = svn_ra_serf__error_on_status(gls_ctx->status_code,
+  err = svn_error_compose_create(
+         svn_ra_serf__error_on_status(gls_ctx->status_code,
                                       handler->path,
-                                      parser_ctx->location);
-  if (err2)
-    {
-      /* Prefer err2 to err. */
-      svn_error_clear(err);
-      return err2;
-    }
+                                      parser_ctx->location),
+         err);;
 
   svn_pool_destroy(gls_ctx->subpool);
 
   if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
     return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL);
 
-  return err;
+  return svn_error_trace(err);
 }