You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/07/25 17:34:38 UTC

svn commit: r1150751 [2/5] - in /subversion/branches/gpg-agent-password-store: ./ build/ac-macros/ build/generator/swig/ notes/ subversion/bindings/swig/perl/native/t/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion...

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/merge.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/merge.c Mon Jul 25 15:34:28 2011
@@ -2722,6 +2722,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 +2857,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 +2911,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 +2942,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(svn_rangelist_merge(&(child->remaining_ranges),
-                                          deleted_rangelist, 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));
+
+              /* 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 +2980,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 +3007,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 +3771,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 +4160,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 +4168,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 +4332,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 +4454,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 +4630,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 +5023,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,
@@ -7860,13 +7875,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,13 +7932,16 @@ 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;
@@ -7893,17 +7951,15 @@ log_noop_revs(void *baton,
   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))
     {
@@ -7922,7 +7978,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)
@@ -7950,8 +8006,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;
@@ -7960,16 +8016,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;
@@ -7981,12 +8038,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;
 }
@@ -8027,13 +8081,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. */
@@ -8047,8 +8100,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? */
@@ -8064,18 +8115,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)
@@ -8114,14 +8169,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.pool = scratch_pool;
+  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));
@@ -8133,8 +8195,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++)
     {
@@ -8154,6 +8216,8 @@ remove_noop_subtree_ranges(const char *u
         }
     }
 
+  svn_pool_destroy(log_gap_baton.pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -8344,7 +8408,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()
@@ -9832,6 +9896,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;
@@ -9840,9 +9905,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);
         }
     }
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.c Mon Jul 25 15:34:28 2011
@@ -1812,7 +1812,7 @@ svn_client_mergeinfo_log(svn_boolean_t f
           SVN_ERR(svn_mergeinfo_intersect2(&merged_via_history,
                                            subtree_history,
                                            subtree_source_history, TRUE,
-                                           scratch_pool, scratch_pool));
+                                           scratch_pool, iterpool));
           SVN_ERR(svn_mergeinfo_merge(subtree_mergeinfo,
                                       merged_via_history,
                                       scratch_pool));
@@ -1847,16 +1847,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 +1878,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 +1886,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 +1944,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 +1959,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 +1977,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 +1989,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/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.h?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/mergeinfo.h Mon Jul 25 15:34:28 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

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/repos_diff.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/repos_diff.c Mon Jul 25 15:34:28 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,
@@ -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)));
 
@@ -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;
@@ -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/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c Mon Jul 25 15:34:28 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/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/fs_fs.c Mon Jul 25 15:34:28 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;
     }
 
@@ -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/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.c Mon Jul 25 15:34:28 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/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.h?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_fs/rep-cache.h Mon Jul 25 15:34:28 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,

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_local/ra_plugin.c Mon Jul 25 15:34:28 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/gpg-agent-password-store/subversion/libsvn_ra_neon/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/log.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_neon/log.c Mon Jul 25 15:34:28 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/gpg-agent-password-store/subversion/libsvn_ra_serf/getlocationsegments.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/getlocationsegments.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/getlocationsegments.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/getlocationsegments.c Mon Jul 25 15:34:28 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);
 }

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/log.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/log.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/log.c Mon Jul 25 15:34:28 2011
@@ -121,11 +121,12 @@ push_state(svn_ra_serf__xml_parser_t *pa
   if (state == ITEM)
     {
       log_info_t *info;
+      apr_pool_t *info_pool = svn_pool_create(parser->state->pool);
 
-      info = apr_pcalloc(parser->state->pool, sizeof(*info));
-      info->log_entry = svn_log_entry_create(parser->state->pool);
+      info = apr_pcalloc(info_pool, sizeof(*info));
+      info->pool = info_pool;
+      info->log_entry = svn_log_entry_create(info_pool);
 
-      info->pool = parser->state->pool;
       info->log_entry->revision = SVN_INVALID_REVNUM;
 
       parser->state->private = info;
@@ -220,11 +221,14 @@ start_log(svn_ra_serf__xml_parser_t *par
         }
       else if (strcmp(name.name, "revprop") == 0)
         {
+          const char *revprop_name;
           info = push_state(parser, log_ctx, REVPROP);
-          info->revprop_name = svn_xml_get_attr_value("name", attrs);
-          if (info->revprop_name == NULL)
+          revprop_name = svn_xml_get_attr_value("name", attrs);
+          if (revprop_name == NULL)
             return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                                      _("Missing name attr in revprop element"));
+
+          info->revprop_name = apr_pstrdup(info->pool, revprop_name);
         }
       else if (strcmp(name.name, "has-children") == 0)
         {
@@ -342,6 +346,7 @@ end_log(svn_ra_serf__xml_parser_t *parse
           log_ctx->nest_level--;
         }
 
+      svn_pool_destroy(info->pool);
       svn_ra_serf__xml_pop_state(parser);
     }
   else if (state == VERSION &&
@@ -459,7 +464,7 @@ cdata_log(svn_ra_serf__xml_parser_t *par
       case DELETED_PATH:
       case MODIFIED_PATH:
         svn_ra_serf__expand_string(&info->tmp, &info->tmp_len,
-                                   data, len, parser->state->pool);
+                                   data, len, info->pool);
         break;
       default:
         break;
@@ -584,6 +589,7 @@ svn_ra_serf__get_log(svn_ra_session_t *r
   svn_ra_serf__xml_parser_t *parser_ctx;
   svn_boolean_t want_custom_revprops;
   svn_revnum_t peg_rev;
+  svn_error_t *err;
   const char *relative_url, *basecoll_url, *req_url;
 
   log_ctx = apr_pcalloc(pool, sizeof(*log_ctx));
@@ -669,7 +675,13 @@ svn_ra_serf__get_log(svn_ra_session_t *r
 
   svn_ra_serf__request_create(handler);
 
-  SVN_ERR(svn_ra_serf__context_run_wait(&log_ctx->done, session, pool));
+  err = svn_ra_serf__context_run_wait(&log_ctx->done, session, pool);
+
+  SVN_ERR(svn_error_compose_create(
+              svn_ra_serf__error_on_status(log_ctx->status_code,
+                                           req_url,
+                                           parser_ctx->location),
+              err));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/ra_serf.h Mon Jul 25 15:34:28 2011
@@ -139,9 +139,13 @@ struct svn_ra_serf__session_t {
   const svn_ra_callbacks2_t *wc_callbacks;
   void *wc_callback_baton;
 
-  /* Callback function to send info to WC */
-  svn_ra_progress_notify_func_t wc_progress_func;
-  void *wc_progress_baton;
+  /* Callback function to send progress info to the client */
+  svn_ra_progress_notify_func_t progress_func;
+  void *progress_baton;
+
+  /* Callback function to handle cancellation */
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
 
   /* Error that we've received but not yet returned upstream. */
   svn_error_t *pending_error;
@@ -535,6 +539,10 @@ struct svn_ra_serf__xml_parser_t {
   /* Temporary allocations should be made in this pool. */
   apr_pool_t *pool;
 
+  /* What kind of response are we parsing? If set, this should typically
+     define the report name.  */
+  const char *response_type;
+
   /* Caller-specific data passed to the start, end, cdata callbacks.  */
   void *user_data;
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/replay.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/replay.c Mon Jul 25 15:34:28 2011
@@ -194,6 +194,7 @@ start_replay(svn_ra_serf__xml_parser_t *
 
       /* Create a pool for the commit editor. */
       ctx->dst_rev_pool = svn_pool_create(ctx->src_rev_pool);
+      ctx->file_pool = svn_pool_create(ctx->dst_rev_pool);
 
       /* ### it would be nice to have a proper scratch_pool.  */
       SVN_ERR(svn_ra_serf__select_revprops(&ctx->props,
@@ -650,7 +651,6 @@ svn_ra_serf__replay(svn_ra_session_t *ra
 
   replay_ctx = apr_pcalloc(pool, sizeof(*replay_ctx));
   replay_ctx->src_rev_pool = pool;
-  replay_ctx->file_pool = svn_pool_create(pool);
   replay_ctx->editor = editor;
   replay_ctx->editor_baton = edit_baton;
   replay_ctx->done = FALSE;
@@ -756,6 +756,9 @@ svn_ra_serf__replay_range(svn_ra_session
          to store the response status code. */
       int status_code;
 
+      if (session->cancel_func)
+        SVN_ERR(session->cancel_func(session->cancel_baton));
+
       /* Send pending requests, if any. Limit the number of outstanding
          requests to MAX_OUTSTANDING_REQUESTS. */
       if (rev <= end_revision  && active_reports < MAX_OUTSTANDING_REQUESTS)

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/serf.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/serf.c Mon Jul 25 15:34:28 2011
@@ -326,11 +326,11 @@ static void
 svn_ra_serf__progress(void *progress_baton, apr_off_t read, apr_off_t written)
 {
   const svn_ra_serf__session_t *serf_sess = progress_baton;
-  if (serf_sess->wc_progress_func)
+  if (serf_sess->progress_func)
     {
-      serf_sess->wc_progress_func(read + written, -1,
-                                  serf_sess->wc_progress_baton,
-                                  serf_sess->pool);
+      serf_sess->progress_func(read + written, -1,
+                               serf_sess->progress_baton,
+                               serf_sess->pool);
     }
 }
 
@@ -355,8 +355,10 @@ svn_ra_serf__open(svn_ra_session_t *sess
   serf_sess->pool = svn_pool_create(pool);
   serf_sess->wc_callbacks = callbacks;
   serf_sess->wc_callback_baton = callback_baton;
-  serf_sess->wc_progress_baton = callbacks->progress_baton;
-  serf_sess->wc_progress_func = callbacks->progress_func;
+  serf_sess->progress_func = callbacks->progress_func;
+  serf_sess->progress_baton = callbacks->progress_baton;
+  serf_sess->cancel_func = callbacks->cancel_func;
+  serf_sess->cancel_baton = callback_baton;
 
   /* todo: reuse serf context across sessions */
   serf_sess->context = serf_context_create(serf_sess->pool);

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/update.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/update.c Mon Jul 25 15:34:28 2011
@@ -2324,6 +2324,7 @@ finish_report(void *report_baton,
   parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
 
   parser_ctx->pool = pool;
+  parser_ctx->response_type = "update-report";
   parser_ctx->user_data = report;
   parser_ctx->start = start_report;
   parser_ctx->end = end_report;
@@ -2361,6 +2362,9 @@ finish_report(void *report_baton,
       /* Note: this throws out the old ITERPOOL_INNER.  */
       svn_pool_clear(iterpool);
 
+      if (sess->cancel_func)
+        SVN_ERR(sess->cancel_func(sess->cancel_baton));
+
       /* We need to be careful between the outer and inner ITERPOOLs,
          and what items are allocated within.  */
       iterpool_inner = svn_pool_create(iterpool);

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/util.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_ra_serf/util.c Mon Jul 25 15:34:28 2011
@@ -103,7 +103,71 @@ struct svn_ra_serf__pending_t {
 #define SPILL_SIZE 1000000
 
 /* See notes/ra-serf-testing.txt for some information on testing this
-   new "paused" feature.  */
+   new "paused" feature (aka network pushback).
+
+   Define PBTEST_ACTIVE, if you would like to run the pushback tests.  */
+#undef PBTEST_ACTIVE
+#ifdef PBTEST_ACTIVE
+
+static int pbtest_step = 0;
+
+/* Note: this cannot resolve states 5 and 7.  */
+#define PBTEST_STATE(p) \
+  ((p) == NULL ? 1                                                 \
+               : ((p)->spill == NULL ? ((p)->head == NULL ? 2 : 3) \
+                                     : ((p)->head == NULL ? 6 : 4)))
+
+/* Note: INJECT and COMPLETED are only used for debug output.  */
+typedef struct {
+  svn_boolean_t paused;   /* pause the parser on this step?  */
+  svn_boolean_t inject;   /* inject pending content on this step?  */
+  int when_next;          /* when to move to the next step?  */
+  const char *completed;  /* what test was completed?  */
+} pbtest_desc_t;
+
+static const pbtest_desc_t pbtest_description[] = {
+  { 0 }, /* unused */
+  { TRUE,  FALSE, 3, "1.1" },
+  { TRUE,  FALSE, 3, "1.3" },
+  { FALSE, FALSE, 3, "2.3" },
+  { FALSE, TRUE,  2, "3.3" },  /* WHEN_NEXT is ignored due to INJECT  */
+  { TRUE,  FALSE, 3, "1.2" },
+  { TRUE,  FALSE, 4, NULL  },
+  { TRUE,  FALSE, 4, "1.4" },
+  { FALSE, FALSE, 4, "2.4" },
+  { FALSE, TRUE,  6, "3.4" },  /* WHEN_NEXT is ignored due to INJECT  */
+  { TRUE,  FALSE, 6, "1.6" },
+  { FALSE, FALSE, 6, "2.6" },
+  { FALSE, TRUE,  7, "3.6" },  /* WHEN_NEXT is ignored due to INJECT  */
+  { TRUE,  FALSE, 6, "1.7" },
+  { 0 } /* unused */
+};
+
+#define PBTEST_SET_PAUSED(ctx) \
+  (PBTEST_THIS_REQ(ctx) && pbtest_step < 14                  \
+   ? (ctx)->paused = pbtest_description[pbtest_step].paused  \
+   : FALSE)
+
+#define PBTEST_MAYBE_STEP(ctx, force) maybe_next_step(ctx, force)
+
+#define PBTEST_FORCE_SPILL(ctx) (PBTEST_THIS_REQ(ctx) && pbtest_step == 6)
+
+#define PBTEST_THIS_REQ(ctx) \
+  ((ctx)->response_type != NULL \
+   && strcmp((ctx)->response_type, "update-report") == 0)
+
+#else /* PBTEST_ACTIVE  */
+
+/* Be wary with the definition of these macros so that we don't
+   end up with "statement with no effect" warnings. Obviously, this
+   depends upon particular usage, which is easy to verify.  */
+#define PBTEST_SET_PAUSED(ctx)  /* empty */
+#define PBTEST_MAYBE_STEP(ctx, force)  /* empty */
+
+#define PBTEST_FORCE_SPILL(ctx) FALSE
+#define PBTEST_THIS_REQ(ctx) FALSE
+
+#endif /* PBTEST_ACTIVE  */
 
 
 
@@ -685,9 +749,8 @@ svn_ra_serf__context_run_wait(svn_boolea
 
       svn_pool_clear(iterpool);
 
-      if (sess->wc_callbacks &&
-          sess->wc_callbacks->cancel_func)
-        SVN_ERR((sess->wc_callbacks->cancel_func)(sess->wc_callback_baton));
+      if (sess->cancel_func)
+        SVN_ERR((*sess->cancel_func)(sess->cancel_baton));
 
       status = serf_context_run(sess->context, sess->timeout, iterpool);
 
@@ -1250,6 +1313,54 @@ add_done_item(svn_ra_serf__xml_parser_t 
 }
 
 
+#ifdef PBTEST_ACTIVE
+
+/* Determine whether we should move to the next step. Print out the
+   transition for debugging purposes. If FORCE is TRUE, then we
+   definitely make a step (injection has completed).  */
+static void
+maybe_next_step(svn_ra_serf__xml_parser_t *parser, svn_boolean_t force)
+{
+  const pbtest_desc_t *desc;
+  int state;
+
+  /* This would fail the state transition, but for clarity... just return
+     when the testing has completed.  */
+  if (pbtest_step == 14)
+    return;
+
+  /* If this is not the request running the test, then exit.  */
+  if (!PBTEST_THIS_REQ(parser))
+    return;
+
+  desc = &pbtest_description[pbtest_step];
+  state = PBTEST_STATE(parser->pending);
+
+  /* Forced? ... or reached target state?  */
+  if (force || state == desc->when_next)
+    {
+      ++pbtest_step;
+
+      if (desc->completed != NULL)
+        SVN_DBG(("PBTEST: completed TEST %s\n", desc->completed));
+
+      /* Pause the parser based on the new step's config.  */
+      ++desc;
+      parser->paused = desc->paused;
+
+      SVN_DBG(("PBTEST: advanced: step=%d  paused=%d  inject=%d  state=%d\n",
+               pbtest_step, desc->paused, desc->inject, state));
+    }
+  else
+    {
+      SVN_DBG(("PBTEST: step[%d]: state=%d  waiting_for=%d\n",
+               pbtest_step, state, desc->when_next));
+    }
+}
+
+#endif /* PBTEST_ACTIVE  */
+
+
 /* Get a buffer from the parsing context. It will come from the free list,
    or allocated as necessary.  */
 static struct pending_buffer_t *
@@ -1293,10 +1404,18 @@ write_to_pending(svn_ra_serf__xml_parser
 
   /* We do not (yet) have a spill file, but the amount stored in memory
      has grown too large. Create the file and place the pending data into
-     the temporary file.  */
-  if (ctx->pending->spill == NULL
-      && ctx->pending->memory_size > SPILL_SIZE)
-    {
+     the temporary file.
+
+     For testing purposes, there are points when we may want to
+     create the spill file, regardless.  */
+  if (PBTEST_FORCE_SPILL(ctx)
+      || (ctx->pending->spill == NULL
+          && ctx->pending->memory_size > SPILL_SIZE))
+    {
+#ifdef PBTEST_ACTIVE
+      /* Only allow a spill file for steps 6 or later.  */
+      if (!PBTEST_THIS_REQ(ctx) || pbtest_step >= 6)
+#endif
       SVN_ERR(svn_io_open_unique_file3(&ctx->pending->spill,
                                        NULL /* temp_path */,
                                        NULL /* dirpath */,
@@ -1371,6 +1490,10 @@ inject_to_parser(svn_ra_serf__xml_parser
   if (ctx->error && !ctx->ignore_errors)
     return svn_error_trace(ctx->error);
 
+  /* We may want to ignore the callbacks choice for the PAUSED flag.
+     Set this value, as appropriate.  */
+  PBTEST_SET_PAUSED(ctx);
+
   return SVN_NO_ERROR;
 }
 
@@ -1383,8 +1506,21 @@ svn_ra_serf__process_pending(svn_ra_serf
   svn_error_t *err;
   apr_off_t output_unused;
 
-  /* Fast path exit: already paused, or nothing to do.  */
-  if (parser->paused || parser->pending == NULL)
+  /* We may need to repair the PAUSED state when testing.  */
+  PBTEST_SET_PAUSED(parser);
+
+#ifdef PBTEST_ACTIVE
+  /* If this step should not inject content, then fast-path exit.  */
+  if (PBTEST_THIS_REQ(parser)
+      && pbtest_step < 14 && !pbtest_description[pbtest_step].inject)
+    {
+      SVN_DBG(("PBTEST: process: injection disabled\n"));
+      return SVN_NO_ERROR;
+    }
+#endif
+
+  /* Fast path exit: already paused, nothing to do, or already done.  */
+  if (parser->paused || parser->pending == NULL || *parser->done)
     return SVN_NO_ERROR;
 
   /* ### it is possible that the XML parsing of the pending content is
@@ -1420,6 +1556,18 @@ svn_ra_serf__process_pending(svn_ra_serf
         return SVN_NO_ERROR;
     }
 
+#ifdef PBTEST_ACTIVE
+  /* For steps 4 and 9, we wait until all of the memory content has been
+     injected. At that point, we can take another step which will pause
+     the parser, and we'll need to exit.  */
+  if (PBTEST_THIS_REQ(parser)
+      && (pbtest_step == 4 || pbtest_step == 9))
+    {
+      PBTEST_MAYBE_STEP(parser, TRUE);
+      return SVN_NO_ERROR;
+    }
+#endif
+
   /* If we don't have a spill file, then we've exhausted all
      pending content.  */
   if (parser->pending->spill == NULL)
@@ -1474,13 +1622,26 @@ svn_ra_serf__process_pending(svn_ra_serf
      the network, then we're completely done with the parsing.  */
   if (parser->pending->network_eof)
     {
+#ifdef PBTEST_ACTIVE
+      if (PBTEST_THIS_REQ(parser))
+        SVN_DBG(("process: terminating parse.\n"));
+#endif
+
+      SVN_ERR_ASSERT(parser->xmlp != NULL);
+
       /* Tell the parser that no more content will be parsed. Ignore the
          return status. We just don't care.  */
       (void) XML_Parse(parser->xmlp, NULL, 0, 1);
 
       XML_ParserFree(parser->xmlp);
+      parser->xmlp = NULL;
       add_done_item(parser);
     }
+
+  /* For testing step 12, we have written all of the disk content. This
+     will advance to step 13 and pause the parser again.  */
+  PBTEST_MAYBE_STEP(parser, TRUE);
+
   return SVN_NO_ERROR;
 }
 
@@ -1538,6 +1699,13 @@ svn_ra_serf__handle_xml_parser(serf_requ
         {
           XML_SetCharacterDataHandler(ctx->xmlp, cdata_xml);
         }
+
+      /* This is the first invocation. If we're looking at an update
+         report, then move to step 1 of the testing sequence.  */
+#ifdef PBTEST_ACTIVE
+      if (PBTEST_THIS_REQ(ctx))
+        PBTEST_MAYBE_STEP(ctx, TRUE);
+#endif
     }
 
   /* If we are storing content into a spill file, then move to the end of
@@ -1564,6 +1732,24 @@ svn_ra_serf__handle_xml_parser(serf_requ
           return svn_error_wrap_apr(status, NULL);
         }
 
+      /* Ensure that the parser's PAUSED state is correct before we test
+         the flag.  */
+      PBTEST_SET_PAUSED(ctx);
+
+#ifdef PBTEST_ACTIVE
+      if (PBTEST_THIS_REQ(ctx))
+        {
+          SVN_DBG(("response: len=%d  paused=%d  status=%08x\n",
+                   (int)len, ctx->paused, status));
+#if 0
+          /* ### DATA is not necessarily NUL-terminated, but this
+             ### generally works. so if you want to see content... */
+          if (len > 0)
+            SVN_DBG(("content=%s\n", data));
+#endif
+        }
+#endif
+
       /* Note: once the callbacks invoked by inject_to_parser() sets the
          PAUSED flag, then it will not be cleared. write_to_pending() will
          only save the content. Logic outside of serf_context_run() will
@@ -1573,13 +1759,18 @@ svn_ra_serf__handle_xml_parser(serf_requ
          We want to save arriving content into the PENDING structures if
          the parser has been paused, or we already have data in there (so
          the arriving data is appended, rather than injected out of order)  */
-#ifdef DISABLE_THIS_FOR_NOW
       if (ctx->paused || HAS_PENDING_DATA(ctx->pending))
         {
           err = write_to_pending(ctx, data, len, pool);
+
+          /* We may have a transition to a next step.
+
+             Note: this only happens on writing to PENDING. If the
+             parser is unpaused, then we will never change state within
+             this network-reading loop.  */
+          PBTEST_MAYBE_STEP(ctx, FALSE);
         }
       else
-#endif
         {
           err = inject_to_parser(ctx, data, len, &sl);
           if (err)
@@ -1590,7 +1781,10 @@ svn_ra_serf__handle_xml_parser(serf_requ
         }
       if (err)
         {
+          SVN_ERR_ASSERT(ctx->xmlp != NULL);
+
           XML_ParserFree(ctx->xmlp);
+          ctx->xmlp = NULL;
           add_done_item(ctx);
           return svn_error_trace(err);
         }
@@ -1605,14 +1799,27 @@ svn_ra_serf__handle_xml_parser(serf_requ
           if (ctx->pending != NULL)
             ctx->pending->network_eof = TRUE;
 
+#ifdef PBTEST_ACTIVE
+          if (PBTEST_THIS_REQ(ctx))
+            SVN_DBG(("network: reached EOF.\n"));
+#endif
+
           /* We just hit the end of the network content. If we have nothing
              in the PENDING structures, then we're completely done.  */
           if (!HAS_PENDING_DATA(ctx->pending))
             {
+#ifdef PBTEST_ACTIVE
+              if (PBTEST_THIS_REQ(ctx))
+                SVN_DBG(("network: terminating parse.\n"));
+#endif
+
+              SVN_ERR_ASSERT(ctx->xmlp != NULL);
+
               /* Ignore the return status. We just don't care.  */
               (void) XML_Parse(ctx->xmlp, NULL, 0, 1);
 
               XML_ParserFree(ctx->xmlp);
+              ctx->xmlp = NULL;
               add_done_item(ctx);
             }
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/commit.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/commit.c Mon Jul 25 15:34:28 2011
@@ -94,6 +94,9 @@ struct edit_baton
   /* The object representing the root directory of the svn txn. */
   svn_fs_root_t *txn_root;
 
+  /* Avoid aborting an fs transaction more than once */
+  svn_boolean_t txn_aborted;
+
   /** Filled in when the edit is closed: **/
 
   /* The new revision created by this commit. */
@@ -718,12 +721,13 @@ close_edit(void *edit_baton,
          So, in a nutshell: svn commits are an all-or-nothing deal.
          Each commit creates a new fs txn which either succeeds or is
          aborted completely.  No second chances;  the user simply
-         needs to update and commit again  :)
+         needs to update and commit again  :) */
+
+      eb->txn_aborted = TRUE;
 
-         We ignore the possible error result from svn_fs_abort_txn();
-         it's more important to return the original error. */
-      svn_error_clear(svn_fs_abort_txn(eb->txn, pool));
-      return svn_error_trace(err);
+      return svn_error_trace(
+                svn_error_compose_create(err,
+                                         svn_fs_abort_txn(eb->txn, pool)));
     }
 
   /* Pass new revision information to the caller's callback. */
@@ -769,9 +773,12 @@ abort_edit(void *edit_baton,
            apr_pool_t *pool)
 {
   struct edit_baton *eb = edit_baton;
-  if ((! eb->txn) || (! eb->txn_owner))
+  if ((! eb->txn) || (! eb->txn_owner) || eb->txn_aborted)
     return SVN_NO_ERROR;
-  return svn_fs_abort_txn(eb->txn, pool);
+
+  eb->txn_aborted = TRUE;
+
+  return svn_error_trace(svn_fs_abort_txn(eb->txn, pool));
 }
 
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/hooks.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_repos/hooks.c Mon Jul 25 15:34:28 2011
@@ -202,7 +202,8 @@ run_hook_cmd(svn_string_t **result,
 
   if (err)
     {
-      err = svn_error_createf
+      /* CMD_PROC is not safe to use. Bail. */
+      return svn_error_createf
         (SVN_ERR_REPOS_HOOK_FAILURE, err, _("Failed to start '%s' hook"), cmd);
     }
   else
@@ -618,18 +619,9 @@ svn_repos__hooks_pre_lock(svn_repos_t *r
                            pool));
 
       if (token)
-        {
-          svn_error_t *err;
-          /* Convert hook output from native encoding to UTF-8. */
-          err = svn_utf_cstring_to_utf8(token, buf->data, pool);
-          if (err)
-            {
-              return svn_error_create(SVN_ERR_REPOS_HOOK_FAILURE, err,
-                                      _("Output of pre-lock hook could not be "
-                                        "translated from the native locale to "
-                                        "UTF-8."));
-            }
-        }
+        /* No validation here; the FS will take care of that. */
+        *token = buf->data;
+
     }
   else if (token)
     *token = "";

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/deprecated.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/deprecated.c Mon Jul 25 15:34:28 2011
@@ -1126,3 +1126,12 @@ svn_xml_make_header(svn_stringbuf_t **st
 {
   svn_xml_make_header2(str, NULL, pool);
 }
+
+svn_error_t *
+svn_rangelist_merge(apr_array_header_t **rangelist,
+                    const apr_array_header_t *changes,
+                    apr_pool_t *pool)
+{
+  return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
+                                              pool, pool));
+}

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/dso.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/dso.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/dso.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/dso.c Mon Jul 25 15:34:28 2011
@@ -105,9 +105,12 @@ svn_dso_load(apr_dso_handle_t **dso, con
       status = apr_dso_load(dso, fname, dso_pool);
       if (status)
         {
-#if 0
+#ifdef SVN_DEBUG_DSO
           char buf[1024];
-          fprintf(stderr, "%s\n", apr_dso_error(*dso, buf, 1024));
+          fprintf(stderr,
+                  "Dynamic loading of '%s' failed with the following error:\n%s\n",
+                  fname,
+                  apr_dso_error(*dso, buf, 1024));
 #endif
           *dso = NULL;
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/io.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/io.c Mon Jul 25 15:34:28 2011
@@ -2489,10 +2489,17 @@ svn_io_start_cmd2(apr_proc_t *cmd_proc,
 
   /* Forward request for pipes to APR. */
   if (infile_pipe || outfile_pipe || errfile_pipe)
-    apr_procattr_io_set(cmdproc_attr,
-                        infile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
-                        outfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
-                        errfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE);
+    {
+      apr_err = apr_procattr_io_set(cmdproc_attr,
+                                    infile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
+                                    outfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE,
+                                    errfile_pipe ? APR_FULL_BLOCK : APR_NO_PIPE);
+
+      if (apr_err)
+        return svn_error_wrap_apr(apr_err,
+                                  _("Can't set process '%s' stdio pipes"),
+                                  cmd);
+    }
 
   /* Have the child print any problems executing its program to errfile. */
   apr_err = apr_pool_userdata_set(errfile, ERRFILE_KEY, NULL, pool);

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/mergeinfo.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/mergeinfo.c Mon Jul 25 15:34:28 2011
@@ -37,6 +37,7 @@
 #include "private/svn_string_private.h"
 #include "svn_private_config.h"
 #include "svn_hash.h"
+#include "private/svn_dep_compat.h"
 
 /* Attempt to combine two ranges, IN1 and IN2. If they are adjacent or
    overlapping, and their inheritability allows them to be combined, put
@@ -671,7 +672,7 @@ parse_revision_line(const char **input, 
      absolute path key. */
   existing_rangelist = apr_hash_get(hash, pathname->data, APR_HASH_KEY_STRING);
   if (existing_rangelist)
-    SVN_ERR(svn_rangelist_merge(&rangelist, existing_rangelist, pool));
+    SVN_ERR(svn_rangelist_merge2(rangelist, existing_rangelist, pool, pool));
 
   apr_hash_set(hash, pathname->data, APR_HASH_KEY_STRING, rangelist);
 
@@ -707,23 +708,26 @@ svn_mergeinfo_parse(svn_mergeinfo_t *mer
   return err;
 }
 
-
 svn_error_t *
-svn_rangelist_merge(apr_array_header_t **rangelist,
-                    const apr_array_header_t *changes,
-                    apr_pool_t *pool)
+svn_rangelist_merge2(apr_array_header_t *rangelist,
+                     const apr_array_header_t *changes,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
   int i, j;
-  apr_array_header_t *output = apr_array_make(pool, 1,
-                                              sizeof(svn_merge_range_t *));
+  apr_array_header_t *original_rangelist;
+  
+  original_rangelist = apr_array_copy(scratch_pool, rangelist);
+  apr_array_clear(rangelist);
+
   i = 0;
   j = 0;
-  while (i < (*rangelist)->nelts && j < changes->nelts)
+  while (i < (original_rangelist)->nelts && j < changes->nelts)
     {
       svn_merge_range_t *elt1, *elt2;
       int res;
 
-      elt1 = APR_ARRAY_IDX(*rangelist, i, svn_merge_range_t *);
+      elt1 = APR_ARRAY_IDX(original_rangelist, i, svn_merge_range_t *);
       elt2 = APR_ARRAY_IDX(changes, j, svn_merge_range_t *);
 
       res = svn_sort_compare_ranges(&elt1, &elt2);
@@ -734,46 +738,45 @@ svn_rangelist_merge(apr_array_header_t *
              result. */
           if (elt1->inheritable || elt2->inheritable)
             elt1->inheritable = TRUE;
-          SVN_ERR(combine_with_lastrange(elt1, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt1, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           i++;
           j++;
         }
       else if (res < 0)
         {
-          SVN_ERR(combine_with_lastrange(elt1, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt1, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           i++;
         }
       else
         {
-          SVN_ERR(combine_with_lastrange(elt2, output,
-                                         TRUE, pool, pool));
+          SVN_ERR(combine_with_lastrange(elt2, rangelist, TRUE, result_pool,
+                                         scratch_pool));
           j++;
         }
     }
   /* Copy back any remaining elements.
      Only one of these loops should end up running, if anything. */
 
-  SVN_ERR_ASSERT(!(i < (*rangelist)->nelts && j < changes->nelts));
+  SVN_ERR_ASSERT(!(i < (original_rangelist)->nelts && j < changes->nelts));
 
-  for (; i < (*rangelist)->nelts; i++)
+  for (; i < (original_rangelist)->nelts; i++)
     {
-      svn_merge_range_t *elt = APR_ARRAY_IDX(*rangelist, i,
+      svn_merge_range_t *elt = APR_ARRAY_IDX(original_rangelist, i,
                                              svn_merge_range_t *);
-      SVN_ERR(combine_with_lastrange(elt, output,
-                                     TRUE, pool, pool));
+      SVN_ERR(combine_with_lastrange(elt, rangelist, TRUE, result_pool,
+                                     scratch_pool));
     }
 
 
   for (; j < changes->nelts; j++)
     {
       svn_merge_range_t *elt = APR_ARRAY_IDX(changes, j, svn_merge_range_t *);
-      SVN_ERR(combine_with_lastrange(elt, output,
-                                     TRUE, pool, pool));
+      SVN_ERR(combine_with_lastrange(elt, rangelist,
+                                     TRUE, result_pool, scratch_pool));
     }
 
-  *rangelist = output;
   return SVN_NO_ERROR;
 }
 
@@ -1297,6 +1300,7 @@ svn_mergeinfo_merge(svn_mergeinfo_t merg
 {
   apr_array_header_t *sorted1, *sorted2;
   int i, j;
+  apr_pool_t *iterpool;
 
   if (!apr_hash_count(changes))
     return SVN_NO_ERROR;
@@ -1306,11 +1310,14 @@ svn_mergeinfo_merge(svn_mergeinfo_t merg
 
   i = 0;
   j = 0;
+  iterpool = svn_pool_create(pool);
   while (i < sorted1->nelts && j < sorted2->nelts)
     {
       svn_sort__item_t elt1, elt2;
       int res;
 
+      svn_pool_clear(iterpool);
+
       elt1 = APR_ARRAY_IDX(sorted1, i, svn_sort__item_t);
       elt2 = APR_ARRAY_IDX(sorted2, j, svn_sort__item_t);
       res = svn_sort_compare_items_as_paths(&elt1, &elt2);
@@ -1322,8 +1329,7 @@ svn_mergeinfo_merge(svn_mergeinfo_t merg
           rl1 = elt1.value;
           rl2 = elt2.value;
 
-          SVN_ERR(svn_rangelist_merge(&rl1, rl2,
-                                      pool));
+          SVN_ERR(svn_rangelist_merge2(rl1, rl2, pool, iterpool));
           apr_hash_set(mergeinfo, elt1.key, elt1.klen, rl1);
           i++;
           j++;
@@ -1338,6 +1344,7 @@ svn_mergeinfo_merge(svn_mergeinfo_t merg
           j++;
         }
     }
+  svn_pool_destroy(iterpool);
 
   /* Copy back any remaining elements from the second hash. */
   for (; j < sorted2->nelts; j++)

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/subst.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/subst.c Mon Jul 25 15:34:28 2011
@@ -1267,15 +1267,16 @@ static svn_error_t *
 translated_stream_close(void *baton)
 {
   struct translated_stream_baton *b = baton;
+  svn_error_t *err = NULL;
 
   if (b->written)
-    SVN_ERR(translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool));
+    err = translate_chunk(b->stream, b->out_baton, NULL, 0, b->iterpool);
 
-  SVN_ERR(svn_stream_close(b->stream));
+  err = svn_error_compose_create(err, svn_stream_close(b->stream));
 
   svn_pool_destroy(b->iterpool);
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(err);
 }
 
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/svn_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/svn_string.c?rev=1150751&r1=1150750&r2=1150751&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/svn_string.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_subr/svn_string.c Mon Jul 25 15:34:28 2011
@@ -839,3 +839,16 @@ svn_cstring_atoi(int *n, const char *str
   *n = (int)val;
   return SVN_NO_ERROR;
 }
+
+
+apr_status_t
+svn__strtoff(apr_off_t *offset, const char *buf, char **end, int base)
+{
+#if !APR_VERSION_AT_LEAST(1,0,0)
+  errno = 0;
+  *offset = strtol(buf, end, base);
+  return APR_FROM_OS_ERROR(errno);
+#else
+  return apr_strtoff(offset, buf, end, base);
+#endif
+}