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 2014/06/24 23:30:01 UTC

svn commit: r1605201 [4/5] - in /subversion/branches/svn-auth-x509: ./ build/generator/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subve...

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.c Tue Jun 24 21:29:59 2014
@@ -43,6 +43,7 @@
 #include "rep-cache.h"
 
 #include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
 #include "private/svn_sorts_private.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_string_private.h"
@@ -540,12 +541,12 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
 
 /* For the in-transaction NODEREV within FS, write the sha1->rep mapping
  * file in the respective transaction, if rep sharing has been enabled etc.
- * Use POOL for temporary allocations.
+ * Use SCATCH_POOL for temporary allocations.
  */
 static svn_error_t *
 store_sha1_rep_mapping(svn_fs_t *fs,
                        node_revision_t *noderev,
-                       apr_pool_t *pool)
+                       apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
@@ -559,20 +560,20 @@ store_sha1_rep_mapping(svn_fs_t *fs,
       const char *file_name = path_txn_sha1(fs,
                                             &noderev->data_rep->txn_id,
                                             noderev->data_rep->sha1_digest,
-                                            pool);
+                                            scratch_pool);
       svn_stringbuf_t *rep_string
         = svn_fs_fs__unparse_representation(noderev->data_rep,
                                             ffd->format,
                                             (noderev->kind == svn_node_dir),
-                                            pool);
+                                            scratch_pool, scratch_pool);
       SVN_ERR(svn_io_file_open(&rep_file, file_name,
                                APR_WRITE | APR_CREATE | APR_TRUNCATE
-                               | APR_BUFFERED, APR_OS_DEFAULT, pool));
+                               | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool));
 
       SVN_ERR(svn_io_file_write_full(rep_file, rep_string->data,
-                                     rep_string->len, NULL, pool));
+                                     rep_string->len, NULL, scratch_pool));
 
-      SVN_ERR(svn_io_file_close(rep_file, pool));
+      SVN_ERR(svn_io_file_close(rep_file, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -650,18 +651,18 @@ replace_change(svn_fs_path_change2_t *ol
 }
 
 /* Merge the internal-use-only CHANGE into a hash of public-FS
-   svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
+   svn_fs_path_change2_t CHANGED_PATHS, collapsing multiple changes into a
    single summarical (is that real word?) change per path.  */
 static svn_error_t *
-fold_change(apr_hash_t *changes,
+fold_change(apr_hash_t *changed_paths,
             const change_t *change)
 {
-  apr_pool_t *pool = apr_hash_pool_get(changes);
+  apr_pool_t *pool = apr_hash_pool_get(changed_paths);
   svn_fs_path_change2_t *old_change, *new_change;
   const svn_string_t *path = &change->path;
   const svn_fs_path_change2_t *info = &change->info;
 
-  if ((old_change = apr_hash_get(changes, path->data, path->len)))
+  if ((old_change = apr_hash_get(changed_paths, path->data, path->len)))
     {
       /* This path already exists in the hash, so we have to merge
          this change into the already existing one. */
@@ -754,7 +755,7 @@ fold_change(apr_hash_t *changes,
 
       /* remove old_change from the cache if it is no longer needed. */
       if (old_change == NULL)
-        apr_hash_set(changes, path->data, path->len, NULL);
+        apr_hash_set(changed_paths, path->data, path->len, NULL);
     }
   else
     {
@@ -769,7 +770,7 @@ fold_change(apr_hash_t *changes,
       /* Add this path.  The API makes no guarantees that this (new) key
         will not be retained.  Thus, we copy the key into the target pool
         to ensure a proper lifetime.  */
-      apr_hash_set(changes,
+      apr_hash_set(changed_paths,
                    apr_pstrmemdup(pool, path->data, path->len), path->len,
                    new_change);
     }
@@ -777,84 +778,72 @@ fold_change(apr_hash_t *changes,
   return SVN_NO_ERROR;
 }
 
-/* Examine all the changed path entries in CHANGES and store them in
+/* An implementation of svn_fs_fs__change_receiver_t.
+   Examine all the changed path entries in CHANGES and store them in
    *CHANGED_PATHS.  Folding is done to remove redundant or unnecessary
    data. Do all allocations in POOL. */
 static svn_error_t *
-process_changes(apr_hash_t *changed_paths,
-                apr_array_header_t *changes,
-                apr_pool_t *pool)
-{
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  int i;
-
-  /* Read in the changes one by one, folding them into our local hash
-     as necessary. */
-
-  for (i = 0; i < changes->nelts; ++i)
-    {
-      /* The ITERPOOL will be cleared at the end of this function
-       * since it is only used rarely and for a single hash iterator.
-       */
-      change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
-
-      SVN_ERR(fold_change(changed_paths, change));
-
-      /* Now, if our change was a deletion or replacement, we have to
-         blow away any changes thus far on paths that are (or, were)
-         children of this path.
-         ### i won't bother with another iteration pool here -- at
-         most we talking about a few extra dups of paths into what
-         is already a temporary subpool.
+process_changes(void *baton,
+                change_t *change,
+                apr_pool_t *scratch_pool)
+{
+  apr_hash_t *changed_paths = baton;
+
+  SVN_ERR(fold_change(changed_paths, change));
+
+  /* Now, if our change was a deletion or replacement, we have to
+     blow away any changes thus far on paths that are (or, were)
+     children of this path.
+     ### i won't bother with another iteration pool here -- at
+     most we talking about a few extra dups of paths into what
+     is already a temporary subpool.
+  */
+
+  if ((change->info.change_kind == svn_fs_path_change_delete)
+       || (change->info.change_kind == svn_fs_path_change_replace))
+    {
+      apr_hash_index_t *hi;
+
+      /* a potential child path must contain at least 2 more chars
+         (the path separator plus at least one char for the name).
+         Also, we should not assume that all paths have been normalized
+         i.e. some might have trailing path separators.
       */
-
-      if ((change->info.change_kind == svn_fs_path_change_delete)
-           || (change->info.change_kind == svn_fs_path_change_replace))
-        {
-          apr_hash_index_t *hi;
-
-          /* a potential child path must contain at least 2 more chars
-             (the path separator plus at least one char for the name).
-             Also, we should not assume that all paths have been normalized
-             i.e. some might have trailing path separators.
-          */
-          apr_ssize_t path_len = change->path.len;
-          apr_ssize_t min_child_len = path_len == 0
-                                    ? 1
-                                    : change->path.data[path_len-1] == '/'
-                                        ? path_len + 1
-                                        : path_len + 2;
-
-          /* CAUTION: This is the inner loop of an O(n^2) algorithm.
-             The number of changes to process may be >> 1000.
-             Therefore, keep the inner loop as tight as possible.
-          */
-          for (hi = apr_hash_first(iterpool, changed_paths);
-               hi;
-               hi = apr_hash_next(hi))
+      apr_ssize_t path_len = change->path.len;
+      apr_ssize_t min_child_len = path_len == 0
+                                ? 1
+                                : change->path.data[path_len-1] == '/'
+                                    ? path_len + 1
+                                    : path_len + 2;
+
+      /* CAUTION: This is the inner loop of an O(n^2) algorithm.
+         The number of changes to process may be >> 1000.
+         Therefore, keep the inner loop as tight as possible.
+      */
+      for (hi = apr_hash_first(scratch_pool, changed_paths);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          /* KEY is the path. */
+          const void *path;
+          apr_ssize_t klen;
+          apr_hash_this(hi, &path, &klen, NULL);
+
+          /* If we come across a child of our path, remove it.
+             Call svn_fspath__skip_ancestor only if there is a chance that
+             this is actually a sub-path.
+           */
+          if (klen >= min_child_len)
             {
-              /* KEY is the path. */
-              const void *path;
-              apr_ssize_t klen;
-              apr_hash_this(hi, &path, &klen, NULL);
-
-              /* If we come across a child of our path, remove it.
-                 Call svn_dirent_is_child only if there is a chance that
-                 this is actually a sub-path.
-               */
-              if (   klen >= min_child_len
-                  && svn_dirent_is_child(change->path.data, path, iterpool))
+              const char *child;
+
+              child = svn_fspath__skip_ancestor(change->path.data, path);
+              if (child && child[0] != '\0')
                 apr_hash_set(changed_paths, path, klen, NULL);
             }
-
-          /* Clear the per-iteration subpool. */
-          svn_pool_clear(iterpool);
         }
     }
 
-  /* Destroy the per-iteration subpool. */
-  svn_pool_destroy(iterpool);
-
   return SVN_NO_ERROR;
 }
 
@@ -866,7 +855,6 @@ svn_fs_fs__txn_changes_fetch(apr_hash_t 
 {
   apr_file_t *file;
   apr_hash_t *changed_paths = apr_hash_make(pool);
-  apr_array_header_t *changes;
   apr_pool_t *scratch_pool = svn_pool_create(pool);
 
   SVN_ERR(svn_io_file_open(&file,
@@ -874,11 +862,11 @@ svn_fs_fs__txn_changes_fetch(apr_hash_t 
                            APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
                            scratch_pool));
 
-  SVN_ERR(svn_fs_fs__read_changes(&changes,
+  SVN_ERR(svn_fs_fs__read_changes_incrementally(
                                   svn_stream_from_aprfile2(file, TRUE,
                                                            scratch_pool),
+                                  process_changes, changed_paths,
                                   scratch_pool));
-  SVN_ERR(process_changes(changed_paths, changes, pool));
   svn_pool_destroy(scratch_pool);
 
   *changed_paths_p = changed_paths;
@@ -924,7 +912,7 @@ create_new_txn_noderev_from_rev(svn_fs_t
   node_revision_t *noderev;
   const svn_fs_fs__id_part_t *node_id, *copy_id;
 
-  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, src, pool));
+  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, src, pool, pool));
 
   if (svn_fs_fs__id_is_txn(noderev->id))
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1100,7 +1088,7 @@ svn_fs_fs__create_txn(svn_fs_txn_t **txn
   *txn_p = txn;
 
   /* Create a new root node for this transaction. */
-  SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, rev, pool));
+  SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, rev, pool, pool));
   SVN_ERR(create_new_txn_noderev_from_rev(fs, &ftd->txn_id, root_id, pool));
 
   /* Create an empty rev file. */
@@ -1248,7 +1236,7 @@ svn_fs_fs__get_txn(transaction_t **txn_p
   SVN_ERR(get_txn_proplist(txn->proplist, fs, txn_id, pool));
   root_id = svn_fs_fs__id_txn_create_root(txn_id, pool);
 
-  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, root_id, pool));
+  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, root_id, pool, pool));
 
   txn->root_id = svn_fs_fs__id_copy(noderev->id, pool);
   txn->base_id = svn_fs_fs__id_copy(noderev->predecessor_id, pool);
@@ -1828,9 +1816,11 @@ struct rep_write_baton
   /* calculate a modified FNV-1a checksum of the on-disk representation */
   svn_checksum_ctx_t *fnv1a_checksum_ctx;
 
-  apr_pool_t *pool;
+  /* Local / scratch pool, available for temporary allocations. */
+  apr_pool_t *scratch_pool;
 
-  apr_pool_t *parent_pool;
+  /* Outer / result pool. */
+  apr_pool_t *result_pool;
 };
 
 /* Handler for the write method of the representation writable stream.
@@ -1866,13 +1856,17 @@ shards_spanned(int *spanned,
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   int shard_size = ffd->max_files_per_dir ? ffd->max_files_per_dir : 1;
+  apr_pool_t *iterpool;
 
   int count = walk ? 1 : 0; /* The start of a walk already touches a shard. */
   svn_revnum_t shard, last_shard = ffd->youngest_rev_cache / shard_size;
+  iterpool = svn_pool_create(pool);
   while (walk-- && noderev->predecessor_count)
     {
+      svn_pool_clear(iterpool);
       SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs,
-                                           noderev->predecessor_id, pool));
+                                           noderev->predecessor_id, pool,
+                                           iterpool));
       shard = svn_fs_fs__id_rev(noderev->id) / shard_size;
       if (shard != last_shard)
         {
@@ -1880,6 +1874,7 @@ shards_spanned(int *spanned,
           last_shard = shard;
         }
     }
+  svn_pool_destroy(iterpool);
 
   *spanned = count;
   return SVN_NO_ERROR;
@@ -1906,6 +1901,7 @@ choose_delta_base(representation_t **rep
   int walk;
   node_revision_t *base;
   fs_fs_data_t *ffd = fs->fsap_data;
+  apr_pool_t *iterpool;
 
   /* If we have no predecessors, or that one is empty, then use the empty
    * stream as a base. */
@@ -1952,9 +1948,15 @@ choose_delta_base(representation_t **rep
      if noderev has ten predecessors and we want the eighth file rev,
      walk back two predecessors.) */
   base = noderev;
+  iterpool = svn_pool_create(pool);
   while ((count++) < noderev->predecessor_count)
-    SVN_ERR(svn_fs_fs__get_node_revision(&base, fs,
-                                         base->predecessor_id, pool));
+    {
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_fs_fs__get_node_revision(&base, fs,
+                                           base->predecessor_id, pool,
+                                           iterpool));
+    }
+  svn_pool_destroy(iterpool);
 
   /* return a suitable base representation */
   *rep = props ? base->prop_rep : base->data_rep;
@@ -2012,8 +2014,9 @@ rep_write_cleanup(void *data)
   svn_error_t *err;
 
   /* Truncate and close the protorevfile. */
-  err = svn_io_file_trunc(b->file, b->rep_offset, b->pool);
-  err = svn_error_compose_create(err, svn_io_file_close(b->file, b->pool));
+  err = svn_io_file_trunc(b->file, b->rep_offset, b->scratch_pool);
+  err = svn_error_compose_create(err, svn_io_file_close(b->file,
+                                                        b->scratch_pool));
 
   /* Remove our lock regardless of any preceding errors so that the
      being_written flag is always removed and stays consistent with the
@@ -2022,7 +2025,7 @@ rep_write_cleanup(void *data)
   err = svn_error_compose_create(err,
                                  unlock_proto_rev(b->fs,
                                      svn_fs_fs__id_txn_id(b->noderev->id),
-                                     b->lockcookie, b->pool));
+                                     b->lockcookie, b->scratch_pool));
   if (err)
     {
       apr_status_t rc = err->apr_err;
@@ -2059,27 +2062,28 @@ rep_write_get_baton(struct rep_write_bat
   b->md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool);
 
   b->fs = fs;
-  b->parent_pool = pool;
-  b->pool = svn_pool_create(pool);
+  b->result_pool = pool;
+  b->scratch_pool = svn_pool_create(pool);
   b->rep_size = 0;
   b->noderev = noderev;
 
   /* Open the prototype rev file and seek to its end. */
   SVN_ERR(get_writable_proto_rev(&file, &b->lockcookie,
                                  fs, svn_fs_fs__id_txn_id(noderev->id),
-                                 b->pool));
+                                 b->scratch_pool));
 
   b->file = file;
   b->rep_stream = fnv1a_wrap_stream(&b->fnv1a_checksum_ctx,
                                     svn_stream_from_aprfile2(file, TRUE,
-                                                             b->pool),
-                                    b->pool);
+                                                             b->scratch_pool),
+                                    b->scratch_pool);
 
-  SVN_ERR(svn_fs_fs__get_file_offset(&b->rep_offset, file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&b->rep_offset, file, b->scratch_pool));
 
   /* Get the base for this delta. */
-  SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->pool));
-  SVN_ERR(svn_fs_fs__get_contents(&source, fs, base_rep, TRUE, b->pool));
+  SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->scratch_pool));
+  SVN_ERR(svn_fs_fs__get_contents(&source, fs, base_rep, TRUE,
+                                  b->scratch_pool));
 
   /* Write out the rep header. */
   if (base_rep)
@@ -2093,13 +2097,15 @@ rep_write_get_baton(struct rep_write_bat
     {
       header.type = svn_fs_fs__rep_self_delta;
     }
-  SVN_ERR(svn_fs_fs__write_rep_header(&header, b->rep_stream, b->pool));
+  SVN_ERR(svn_fs_fs__write_rep_header(&header, b->rep_stream,
+                                      b->scratch_pool));
 
   /* Now determine the offset of the actual svndiff data. */
-  SVN_ERR(svn_fs_fs__get_file_offset(&b->delta_start, file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&b->delta_start, file,
+                                     b->scratch_pool));
 
   /* Cleanup in case something goes wrong. */
-  apr_pool_cleanup_register(b->pool, b, rep_write_cleanup,
+  apr_pool_cleanup_register(b->scratch_pool, b, rep_write_cleanup,
                             apr_pool_cleanup_null);
 
   /* Prepare to write the svndiff data. */
@@ -2110,7 +2116,8 @@ rep_write_get_baton(struct rep_write_bat
                           ffd->delta_compression_level,
                           pool);
 
-  b->delta_stream = svn_txdelta_target_push(wh, whb, source, b->pool);
+  b->delta_stream = svn_txdelta_target_push(wh, whb, source,
+                                            b->scratch_pool);
 
   *wb_p = b;
 
@@ -2123,15 +2130,16 @@ rep_write_get_baton(struct rep_write_bat
    there may be new duplicate representations within the same uncommitted
    revision, those can be passed in REPS_HASH (maps a sha1 digest onto
    representation_t*), otherwise pass in NULL for REPS_HASH.
-   POOL will be used for allocations. The lifetime of the returned rep is
-   limited by both, POOL and REP lifetime.
+   Use RESULT_POOL for *OLD_REP  allocations and SCRATCH_POOL for temporaries.
+   The lifetime of *OLD_REP is limited by both, RESULT_POOL and REP lifetime.
  */
 static svn_error_t *
 get_shared_rep(representation_t **old_rep,
                svn_fs_t *fs,
                representation_t *rep,
                apr_hash_t *reps_hash,
-               apr_pool_t *pool)
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -2155,12 +2163,12 @@ get_shared_rep(representation_t **old_re
       svn_checksum_t checksum;
       checksum.digest = rep->sha1_digest;
       checksum.kind = svn_checksum_sha1;
-      err = svn_fs_fs__get_rep_reference(old_rep, fs, &checksum, pool);
+      err = svn_fs_fs__get_rep_reference(old_rep, fs, &checksum, result_pool);
       /* ### Other error codes that we shouldn't mask out? */
       if (err == SVN_NO_ERROR)
         {
           if (*old_rep)
-            SVN_ERR(svn_fs_fs__check_rep(*old_rep, fs, NULL, pool));
+            SVN_ERR(svn_fs_fs__check_rep(*old_rep, fs, NULL, scratch_pool));
         }
       else if (err->apr_err == SVN_ERR_FS_CORRUPT
                || SVN_ERROR_IN_CATEGORY(err->apr_err,
@@ -2193,17 +2201,19 @@ get_shared_rep(representation_t **old_re
     {
       svn_node_kind_t kind;
       const char *file_name
-        = path_txn_sha1(fs, &rep->txn_id, rep->sha1_digest, pool);
+        = path_txn_sha1(fs, &rep->txn_id, rep->sha1_digest, scratch_pool);
 
       /* in our txn, is there a rep file named with the wanted SHA1?
          If so, read it and use that rep.
        */
-      SVN_ERR(svn_io_check_path(file_name, &kind, pool));
+      SVN_ERR(svn_io_check_path(file_name, &kind, scratch_pool));
       if (kind == svn_node_file)
         {
           svn_stringbuf_t *rep_string;
-          SVN_ERR(svn_stringbuf_from_file2(&rep_string, file_name, pool));
-          SVN_ERR(svn_fs_fs__parse_representation(old_rep, rep_string, pool));
+          SVN_ERR(svn_stringbuf_from_file2(&rep_string, file_name,
+                                           scratch_pool));
+          SVN_ERR(svn_fs_fs__parse_representation(old_rep, rep_string,
+                                                  result_pool, scratch_pool));
         }
     }
 
@@ -2250,7 +2260,7 @@ rep_write_contents_close(void *baton)
   representation_t *old_rep;
   apr_off_t offset;
 
-  rep = apr_pcalloc(b->parent_pool, sizeof(*rep));
+  rep = apr_pcalloc(b->result_pool, sizeof(*rep));
 
   /* Close our delta stream so the last bits of svndiff are written
      out. */
@@ -2258,27 +2268,28 @@ rep_write_contents_close(void *baton)
     SVN_ERR(svn_stream_close(b->delta_stream));
 
   /* Determine the length of the svndiff data. */
-  SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->scratch_pool));
   rep->size = offset - b->delta_start;
 
   /* Fill in the rest of the representation field. */
   rep->expanded_size = b->rep_size;
   rep->txn_id = *svn_fs_fs__id_txn_id(b->noderev->id);
-  SVN_ERR(set_uniquifier(b->fs, rep, b->pool));
+  SVN_ERR(set_uniquifier(b->fs, rep, b->scratch_pool));
   rep->revision = SVN_INVALID_REVNUM;
 
   /* Finalize the checksum. */
   SVN_ERR(digests_final(rep, b->md5_checksum_ctx, b->sha1_checksum_ctx,
-                        b->parent_pool));
+                        b->result_pool));
 
   /* Check and see if we already have a representation somewhere that's
      identical to the one we just wrote out. */
-  SVN_ERR(get_shared_rep(&old_rep, b->fs, rep, NULL, b->parent_pool));
+  SVN_ERR(get_shared_rep(&old_rep, b->fs, rep, NULL, b->result_pool,
+                         b->scratch_pool));
 
   if (old_rep)
     {
       /* We need to erase from the protorev the data we just wrote. */
-      SVN_ERR(svn_io_file_trunc(b->file, b->rep_offset, b->pool));
+      SVN_ERR(svn_io_file_trunc(b->file, b->rep_offset, b->scratch_pool));
 
       /* Use the old rep for this content. */
       b->noderev->data_rep = old_rep;
@@ -2289,39 +2300,40 @@ rep_write_contents_close(void *baton)
       SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n"));
       SVN_ERR(allocate_item_index(&rep->item_index, b->fs, &rep->txn_id,
                                   SVN_INVALID_REVNUM, b->rep_offset,
-                                  b->pool));
+                                  b->scratch_pool));
 
       b->noderev->data_rep = rep;
     }
 
   /* Remove cleanup callback. */
-  apr_pool_cleanup_kill(b->pool, b, rep_write_cleanup);
+  apr_pool_cleanup_kill(b->scratch_pool, b, rep_write_cleanup);
 
   /* Write out the new node-rev information. */
   SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev,
-                                       FALSE, b->pool));
+                                       FALSE, b->scratch_pool));
   if (!old_rep)
     {
       svn_fs_fs__p2l_entry_t entry;
 
       entry.offset = b->rep_offset;
-      SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->scratch_pool));
       entry.size = offset - b->rep_offset;
       entry.type = SVN_FS_FS__ITEM_TYPE_FILE_REP;
       entry.item.revision = SVN_INVALID_REVNUM;
       entry.item.number = rep->item_index;
       SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum,
                                       b->fnv1a_checksum_ctx,
-                                      b->pool));
+                                      b->scratch_pool));
 
-      SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->pool));
+      SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->scratch_pool));
       SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, SVN_INVALID_REVNUM,
-                                    &entry, b->pool));
+                                    &entry, b->scratch_pool));
     }
 
-  SVN_ERR(svn_io_file_close(b->file, b->pool));
-  SVN_ERR(unlock_proto_rev(b->fs, &rep->txn_id, b->lockcookie, b->pool));
-  svn_pool_destroy(b->pool);
+  SVN_ERR(svn_io_file_close(b->file, b->scratch_pool));
+  SVN_ERR(unlock_proto_rev(b->fs, &rep->txn_id, b->lockcookie,
+                           b->scratch_pool));
+  svn_pool_destroy(b->scratch_pool);
 
   return SVN_NO_ERROR;
 }
@@ -2499,7 +2511,7 @@ write_directory_to_stream(svn_stream_t *
    found, we will truncate the one just written from the file and return
    the existing rep.  If FINAL_REVISION is not SVN_INVALID_REVNUM, use it
    to determine whether to write to the proto-index files.
-   Perform temporary allocations in POOL. */
+   Perform temporary allocations in SCRATCH_POOL. */
 static svn_error_t *
 write_container_rep(representation_t *rep,
                     apr_file_t *file,
@@ -2509,7 +2521,7 @@ write_container_rep(representation_t *re
                     apr_hash_t *reps_hash,
                     int item_type,
                     svn_revnum_t final_revision,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
   svn_stream_t *stream;
   struct write_container_baton *whb;
@@ -2517,35 +2529,37 @@ write_container_rep(representation_t *re
   representation_t *old_rep;
   apr_off_t offset = 0;
 
-  SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
 
-  whb = apr_pcalloc(pool, sizeof(*whb));
+  whb = apr_pcalloc(scratch_pool, sizeof(*whb));
 
   whb->stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx,
-                                  svn_stream_from_aprfile2(file, TRUE, pool),
-                                  pool);
+                                  svn_stream_from_aprfile2(file, TRUE,
+                                                           scratch_pool),
+                                  scratch_pool);
   whb->size = 0;
-  whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool);
-  whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, pool);
+  whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
+  whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
 
-  stream = svn_stream_create(whb, pool);
+  stream = svn_stream_create(whb, scratch_pool);
   svn_stream_set_write(stream, write_container_handler);
 
   SVN_ERR(svn_stream_puts(whb->stream, "PLAIN\n"));
 
-  SVN_ERR(writer(stream, collection, pool));
+  SVN_ERR(writer(stream, collection, scratch_pool));
 
   /* Store the results. */
-  SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, pool));
+  SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, scratch_pool));
 
   /* Check and see if we already have a representation somewhere that's
      identical to the one we just wrote out. */
-  SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, pool));
+  SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, scratch_pool,
+                         scratch_pool));
 
   if (old_rep)
     {
       /* We need to erase from the protorev the data we just wrote. */
-      SVN_ERR(svn_io_file_trunc(file, offset, pool));
+      SVN_ERR(svn_io_file_trunc(file, offset, scratch_pool));
 
       /* Use the old rep for this content. */
       memcpy(rep, old_rep, sizeof (*rep));
@@ -2558,20 +2572,20 @@ write_container_rep(representation_t *re
       SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n"));
 
       SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id,
-                                  final_revision, offset, pool));
+                                  final_revision, offset, scratch_pool));
 
       entry.offset = offset;
-      SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
       entry.size = offset - entry.offset;
       entry.type = item_type;
       entry.item.revision = SVN_INVALID_REVNUM;
       entry.item.number = rep->item_index;
       SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum,
                                       fnv1a_checksum_ctx,
-                                      pool));
+                                      scratch_pool));
 
       SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
-                                    &entry, pool));
+                                    &entry, scratch_pool));
 
       /* update the representation */
       rep->size = whb->size;
@@ -2593,7 +2607,8 @@ write_container_rep(representation_t *re
    If ITEM_TYPE is IS_PROPS equals SVN_FS_FS__ITEM_TYPE_*_PROPS, assume
    that we want to a props representation as the base for our delta.
    If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
-   to write to the proto-index files.  Perform temporary allocations in POOL.
+   to write to the proto-index files.
+   Perform temporary allocations in SCRATCH_POOL.
  */
 static svn_error_t *
 write_container_delta_rep(representation_t *rep,
@@ -2605,7 +2620,7 @@ write_container_delta_rep(representation
                           apr_hash_t *reps_hash,
                           int item_type,
                           svn_revnum_t final_revision,
-                          apr_pool_t *pool)
+                          apr_pool_t *scratch_pool)
 {
   svn_txdelta_window_handler_t diff_wh;
   void *diff_whb;
@@ -2629,10 +2644,10 @@ write_container_delta_rep(representation
                         || (item_type == SVN_FS_FS__ITEM_TYPE_DIR_PROPS);
 
   /* Get the base for this delta. */
-  SVN_ERR(choose_delta_base(&base_rep, fs, noderev, is_props, pool));
-  SVN_ERR(svn_fs_fs__get_contents(&source, fs, base_rep, FALSE, pool));
+  SVN_ERR(choose_delta_base(&base_rep, fs, noderev, is_props, scratch_pool));
+  SVN_ERR(svn_fs_fs__get_contents(&source, fs, base_rep, FALSE, scratch_pool));
 
-  SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
 
   /* Write out the rep header. */
   if (base_rep)
@@ -2648,10 +2663,11 @@ write_container_delta_rep(representation
     }
 
   file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx,
-                                  svn_stream_from_aprfile2(file, TRUE, pool),
-                                  pool);
-  SVN_ERR(svn_fs_fs__write_rep_header(&header, file_stream, pool));
-  SVN_ERR(svn_fs_fs__get_file_offset(&delta_start, file, pool));
+                                  svn_stream_from_aprfile2(file, TRUE,
+                                                           scratch_pool),
+                                  scratch_pool);
+  SVN_ERR(svn_fs_fs__write_rep_header(&header, file_stream, scratch_pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&delta_start, file, scratch_pool));
 
   /* Prepare to write the svndiff data. */
   svn_txdelta_to_svndiff3(&diff_wh,
@@ -2659,32 +2675,34 @@ write_container_delta_rep(representation
                           file_stream,
                           diff_version,
                           ffd->delta_compression_level,
-                          pool);
+                          scratch_pool);
 
-  whb = apr_pcalloc(pool, sizeof(*whb));
-  whb->stream = svn_txdelta_target_push(diff_wh, diff_whb, source, pool);
+  whb = apr_pcalloc(scratch_pool, sizeof(*whb));
+  whb->stream = svn_txdelta_target_push(diff_wh, diff_whb, source,
+                                        scratch_pool);
   whb->size = 0;
-  whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool);
-  whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, pool);
+  whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
+  whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
 
   /* serialize the hash */
-  stream = svn_stream_create(whb, pool);
+  stream = svn_stream_create(whb, scratch_pool);
   svn_stream_set_write(stream, write_container_handler);
 
-  SVN_ERR(writer(stream, collection, pool));
+  SVN_ERR(writer(stream, collection, scratch_pool));
   SVN_ERR(svn_stream_close(whb->stream));
 
   /* Store the results. */
-  SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, pool));
+  SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, scratch_pool));
 
   /* Check and see if we already have a representation somewhere that's
      identical to the one we just wrote out. */
-  SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, pool));
+  SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, scratch_pool,
+                         scratch_pool));
 
   if (old_rep)
     {
       /* We need to erase from the protorev the data we just wrote. */
-      SVN_ERR(svn_io_file_trunc(file, offset, pool));
+      SVN_ERR(svn_io_file_trunc(file, offset, scratch_pool));
 
       /* Use the old rep for this content. */
       memcpy(rep, old_rep, sizeof (*rep));
@@ -2694,24 +2712,24 @@ write_container_delta_rep(representation
       svn_fs_fs__p2l_entry_t entry;
 
       /* Write out our cosmetic end marker. */
-      SVN_ERR(svn_fs_fs__get_file_offset(&rep_end, file, pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&rep_end, file, scratch_pool));
       SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
       SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id,
-                                  final_revision, offset, pool));
+                                  final_revision, offset, scratch_pool));
 
       entry.offset = offset;
-      SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
       entry.size = offset - entry.offset;
       entry.type = item_type;
       entry.item.revision = SVN_INVALID_REVNUM;
       entry.item.number = rep->item_index;
       SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum,
                                       fnv1a_checksum_ctx,
-                                      pool));
+                                      scratch_pool));
 
       SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
-                                    &entry, pool));
+                                    &entry, scratch_pool));
 
       /* update the representation */
       rep->expanded_size = whb->size;
@@ -2748,8 +2766,7 @@ validate_root_noderev(svn_fs_t *fs,
     SVN_ERR(svn_fs_fs__revision_root(&head_revision, fs, head_revnum, pool));
     SVN_ERR(svn_fs_fs__node_id(&head_root_id, head_revision, "/", pool));
     SVN_ERR(svn_fs_fs__get_node_revision(&head_root_noderev, fs, head_root_id,
-                                         pool));
-
+                                         pool, pool));
     head_predecessor_count = head_root_noderev->predecessor_count;
   }
 
@@ -2855,6 +2872,7 @@ write_final_rev(const svn_fs_id_t **new_
   const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__id_txn_id(id);
   svn_stream_t *file_stream;
   svn_checksum_ctx_t *fnv1a_checksum_ctx;
+  apr_pool_t *subpool;
 
   *new_id_p = NULL;
 
@@ -2862,16 +2880,15 @@ write_final_rev(const svn_fs_id_t **new_
   if (! svn_fs_fs__id_is_txn(id))
     return SVN_NO_ERROR;
 
-  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, id, pool));
+  subpool = svn_pool_create(pool);
+  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, id, pool, subpool));
 
   if (noderev->kind == svn_node_dir)
     {
-      apr_pool_t *subpool;
       apr_array_header_t *entries;
       int i;
 
       /* This is a directory.  Write out all the children first. */
-      subpool = svn_pool_create(pool);
 
       SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, noderev, pool,
                                           subpool));
@@ -2888,7 +2905,6 @@ write_final_rev(const svn_fs_id_t **new_
           if (new_id && (svn_fs_fs__id_rev(new_id) == rev))
             dirent->id = svn_fs_fs__id_copy(new_id, pool);
         }
-      svn_pool_destroy(subpool);
 
       if (noderev->data_rep && is_txn_rep(noderev->data_rep))
         {
@@ -2934,6 +2950,8 @@ write_final_rev(const svn_fs_id_t **new_
         }
     }
 
+  svn_pool_destroy(subpool);
+
   /* Fix up the property reps. */
   if (noderev->prop_rep && is_txn_rep(noderev->prop_rep))
     {
@@ -3189,36 +3207,37 @@ write_final_current(svn_fs_t *fs,
 static svn_error_t *
 verify_locks(svn_fs_t *fs,
              const svn_fs_fs__id_part_t *txn_id,
+             apr_hash_t *changed_paths,
              apr_pool_t *pool)
 {
   apr_pool_t *subpool = svn_pool_create(pool);
-  apr_hash_t *changes;
   apr_hash_index_t *hi;
-  apr_array_header_t *changed_paths;
+  apr_array_header_t *changed_paths_sorted;
   svn_stringbuf_t *last_recursed = NULL;
   int i;
 
-  /* Fetch the changes for this transaction. */
-  SVN_ERR(svn_fs_fs__txn_changes_fetch(&changes, fs, txn_id, pool));
-
   /* Make an array of the changed paths, and sort them depth-first-ily.  */
-  changed_paths = apr_array_make(pool, apr_hash_count(changes) + 1,
-                                 sizeof(const char *));
-  for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
-    APR_ARRAY_PUSH(changed_paths, const char *) = svn__apr_hash_index_key(hi);
-  svn_sort__array(changed_paths, svn_sort_compare_paths);
+  changed_paths_sorted = apr_array_make(pool,
+                                        apr_hash_count(changed_paths) + 1,
+                                        sizeof(const char *));
+  for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
+    {
+      APR_ARRAY_PUSH(changed_paths_sorted, const char *) =
+        svn__apr_hash_index_key(hi);
+    }
+  svn_sort__array(changed_paths_sorted, svn_sort_compare_paths);
 
   /* Now, traverse the array of changed paths, verify locks.  Note
      that if we need to do a recursive verification a path, we'll skip
      over children of that path when we get to them. */
-  for (i = 0; i < changed_paths->nelts; i++)
+  for (i = 0; i < changed_paths_sorted->nelts; i++)
     {
       const char *path;
       svn_fs_path_change2_t *change;
       svn_boolean_t recurse = TRUE;
 
       svn_pool_clear(subpool);
-      path = APR_ARRAY_IDX(changed_paths, i, const char *);
+      path = APR_ARRAY_IDX(changed_paths_sorted, i, const char *);
 
       /* If this path has already been verified as part of a recursive
          check of one of its parents, no need to do it again.  */
@@ -3227,7 +3246,7 @@ verify_locks(svn_fs_t *fs,
         continue;
 
       /* Fetch the change associated with our path.  */
-      change = svn_hash_gets(changes, path);
+      change = svn_hash_gets(changed_paths, path);
 
       /* What does it mean to succeed at lock verification for a given
          path?  For an existing file or directory getting modified
@@ -3407,7 +3426,7 @@ upgrade_transaction(svn_fs_t *fs,
                                APR_OS_DEFAULT,
                                iterpool));
       stream = svn_stream_from_aprfile2(file, TRUE, iterpool);
-      SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, iterpool));
+      SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, iterpool, iterpool));
       if (   noderev->data_rep == NULL
           || noderev->data_rep->revision != SVN_INVALID_REVNUM
           || noderev->kind != svn_node_file)
@@ -3446,7 +3465,7 @@ upgrade_transaction(svn_fs_t *fs,
                                    iterpool));
           SVN_ERR(svn_fs_fs__read_rep_header(&header,
                     svn_stream_from_aprfile2(proto_file, TRUE, iterpool),
-                    iterpool));
+                    iterpool, iterpool));
 
           /* Create the corresponding entry for the P2L proto-index.
 
@@ -3553,6 +3572,42 @@ write_final_revprop(const char **path,
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_fs__add_index_data(svn_fs_t *fs,
+                          apr_file_t *file,
+                          const char *l2p_proto_index,
+                          const char *p2l_proto_index,
+                          svn_revnum_t revision,
+                          apr_pool_t *pool)
+{
+  apr_off_t l2p_offset;
+  apr_off_t p2l_offset;
+  svn_stringbuf_t *footer;
+  unsigned char footer_length;
+
+  /* Append the actual index data to the pack file. */
+  l2p_offset = 0;
+  SVN_ERR(svn_io_file_seek(file, APR_CUR, &l2p_offset, pool));
+  SVN_ERR(svn_fs_fs__l2p_index_append(fs, file, l2p_proto_index, revision,
+                                      pool));
+
+  p2l_offset = 0;
+  SVN_ERR(svn_io_file_seek(file, APR_CUR, &p2l_offset, pool));
+  SVN_ERR(svn_fs_fs__p2l_index_append(fs, file, p2l_proto_index, revision,
+                                      pool));
+
+  /* Append footer. */
+  footer = svn_fs_fs__unparse_footer(l2p_offset, p2l_offset, pool);
+  SVN_ERR(svn_io_file_write_full(file, footer->data, footer->len, NULL,
+                                 pool));
+
+  footer_length = footer->len;
+  SVN_ERR_ASSERT(footer_length == footer->len);
+  SVN_ERR(svn_io_file_write_full(file, &footer_length, 1, NULL, pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Baton used for commit_body below. */
 struct commit_baton {
   svn_revnum_t *new_rev_p;
@@ -3596,17 +3651,17 @@ commit_body(void *baton, apr_pool_t *poo
     return svn_error_create(SVN_ERR_FS_TXN_OUT_OF_DATE, NULL,
                             _("Transaction out of date"));
 
-  /* Locks may have been added (or stolen) between the calling of
-     previous svn_fs.h functions and svn_fs_commit_txn(), so we need
-     to re-examine every changed-path in the txn and re-verify all
-     discovered locks. */
-  SVN_ERR(verify_locks(cb->fs, txn_id, pool));
-
   /* We need the changes list for verification as well as for writing it
      to the final rev file. */
   SVN_ERR(svn_fs_fs__txn_changes_fetch(&changed_paths, cb->fs, txn_id,
                                        pool));
 
+  /* Locks may have been added (or stolen) between the calling of
+     previous svn_fs.h functions and svn_fs_commit_txn(), so we need
+     to re-examine every changed-path in the txn and re-verify all
+     discovered locks. */
+  SVN_ERR(verify_locks(cb->fs, txn_id, changed_paths, pool));
+
   /* We are going to be one better than this puny old revision. */
   new_rev = old_rev + 1;
 
@@ -3651,6 +3706,15 @@ commit_body(void *baton, apr_pool_t *poo
       SVN_ERR(svn_io_file_write_full(proto_file, trailer->data, trailer->len,
                                      NULL, pool));
     }
+  else
+    {
+      /* Append the index data to the rev file. */
+      SVN_ERR(svn_fs_fs__add_index_data(cb->fs, proto_file,
+                      svn_fs_fs__path_l2p_proto_index(cb->fs, txn_id, pool),
+                      svn_fs_fs__path_p2l_proto_index(cb->fs, txn_id, pool),
+                      new_rev, pool));
+    }
+
 
   SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool));
   SVN_ERR(svn_io_file_close(proto_file, pool));
@@ -3696,20 +3760,6 @@ commit_body(void *baton, apr_pool_t *poo
         }
     }
 
-  if (svn_fs_fs__use_log_addressing(cb->fs, new_rev))
-    {
-      /* Convert the index files from the proto format into their form
-         in their final location */
-      SVN_ERR(svn_fs_fs__l2p_index_create(cb->fs,
-                      svn_fs_fs__path_l2p_index(cb->fs, new_rev, FALSE, pool),
-                      svn_fs_fs__path_l2p_proto_index(cb->fs, txn_id, pool),
-                      new_rev, pool));
-      SVN_ERR(svn_fs_fs__p2l_index_create(cb->fs,
-                      svn_fs_fs__path_p2l_index(cb->fs, new_rev, FALSE, pool),
-                      svn_fs_fs__path_p2l_proto_index(cb->fs, txn_id, pool),
-                      new_rev, pool));
-    }
-
   /* Move the finished rev file into place.
 
      ### This "breaks" the transaction by removing the protorev file
@@ -3930,7 +3980,7 @@ svn_fs_fs__delete_node_revision(svn_fs_t
 {
   node_revision_t *noderev;
 
-  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, id, pool));
+  SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, id, pool, pool));
 
   /* Delete any mutable property representation. */
   if (noderev->prop_rep && is_txn_rep(noderev->prop_rep))

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/transaction.h Tue Jun 24 21:29:59 2014
@@ -198,6 +198,18 @@ svn_fs_fs__set_proplist(svn_fs_t *fs,
                         apr_hash_t *proplist,
                         apr_pool_t *pool);
 
+/* Append the L2P and P2L indexes given by their proto index file names
+ * L2P_PROTO_INDEX and P2L_PROTO_INDEX to the revision / pack FILE.
+ * The latter contains revision(s) starting at REVISION in FS.
+ * Use POOL for temporary allocations.  */
+svn_error_t *
+svn_fs_fs__add_index_data(svn_fs_t *fs,
+                          apr_file_t *file,
+                          const char *l2p_proto_index,
+                          const char *p2l_proto_index,
+                          svn_revnum_t revision,
+                          apr_pool_t *pool);
+
 /* Commit the transaction TXN in filesystem FS and return its new
    revision number in *REV.  If the transaction is out of date, return
    the error SVN_ERR_FS_TXN_OUT_OF_DATE. Use POOL for temporary

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/tree.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/tree.c Tue Jun 24 21:29:59 2014
@@ -416,7 +416,9 @@ cache_lookup( fs_fs_dag_cache_t *cache
 /* 2nd level cache */
 
 /* Find and return the DAG node cache for ROOT and the key that
-   should be used for PATH. */
+   should be used for PATH.
+
+   Pool will only be used for allocating a new keys if necessary */
 static void
 locate_cache(svn_cache__t **cache,
              const char **key,
@@ -427,15 +429,20 @@ locate_cache(svn_cache__t **cache,
   if (root->is_txn_root)
     {
       fs_txn_root_data_t *frd = root->fsap_data;
-      if (cache) *cache = frd->txn_node_cache;
-      if (key && path) *key = path;
+
+      if (cache)
+        *cache = frd->txn_node_cache;
+      if (key && path)
+        *key = path;
     }
   else
     {
       fs_fs_data_t *ffd = root->fs->fsap_data;
-      if (cache) *cache = ffd->rev_node_cache;
-      if (key && path) *key
-        = svn_fs_fs__combine_number_and_string(root->rev, path, pool);
+
+      if (cache)
+        *cache = ffd->rev_node_cache;
+      if (key && path)
+        *key = svn_fs_fs__combine_number_and_string(root->rev, path, pool);
     }
 }
 
@@ -1856,11 +1863,19 @@ merge(svn_stringbuf_t *conflict_p,
   {
     node_revision_t *tgt_nr, *anc_nr, *src_nr;
     svn_boolean_t same;
+    apr_pool_t *scratch_pool;
 
     /* Get node revisions for our id's. */
-    SVN_ERR(svn_fs_fs__get_node_revision(&tgt_nr, fs, target_id, pool));
-    SVN_ERR(svn_fs_fs__get_node_revision(&anc_nr, fs, ancestor_id, pool));
-    SVN_ERR(svn_fs_fs__get_node_revision(&src_nr, fs, source_id, pool));
+    scratch_pool = svn_pool_create(pool);
+    SVN_ERR(svn_fs_fs__get_node_revision(&tgt_nr, fs, target_id, pool,
+                                         scratch_pool));
+    svn_pool_clear(scratch_pool);
+    SVN_ERR(svn_fs_fs__get_node_revision(&anc_nr, fs, ancestor_id, pool,
+                                         scratch_pool));
+    svn_pool_clear(scratch_pool);
+    SVN_ERR(svn_fs_fs__get_node_revision(&src_nr, fs, source_id, pool,
+                                         scratch_pool));
+    svn_pool_destroy(scratch_pool);
 
     /* Now compare the prop-keys of the skels.  Note that just because
        the keys are different -doesn't- mean the proplists have
@@ -2518,65 +2533,6 @@ fs_same_p(svn_boolean_t *same_p,
   return SVN_NO_ERROR;
 }
 
-/* Set CHANGES to TRUE if PATH in ROOT is unchanged in REVISION if the
-   same files system.  If the content is identical, parent path copies and
-   deletions still count as changes.  Use POOL for temporary allocations.
-   Not that we will return an error if PATH does not exist in ROOT or
-   REVISION- */
-static svn_error_t *
-is_changed_node(svn_boolean_t *changed,
-                svn_fs_root_t *root,
-                const char *path,
-                svn_revnum_t revision,
-                apr_pool_t *pool)
-{
-  dag_node_t *node, *rev_node;
-  svn_fs_root_t *rev_root;
-  svn_fs_root_t *copy_from_root1, *copy_from_root2;
-  const char *copy_from_path1, *copy_from_path2;
-
-  SVN_ERR(svn_fs_fs__revision_root(&rev_root, root->fs, revision, pool));
-
-  /* Get the NODE for FROM_PATH in FROM_ROOT.*/
-  SVN_ERR(get_dag(&node, root, path, TRUE, pool));
-  SVN_ERR(get_dag(&rev_node, rev_root, path, TRUE, pool));
-
-  /* different ID -> got changed */
-  if (!svn_fs_fs__id_eq(svn_fs_fs__dag_get_id(node),
-                        svn_fs_fs__dag_get_id(rev_node)))
-    {
-      *changed = TRUE;
-       return SVN_NO_ERROR;
-    }
-
-  /* same node. might still be a lazy copy with separate history */
-  SVN_ERR(fs_closest_copy(&copy_from_root1, &copy_from_path1, root,
-                          path, pool));
-  SVN_ERR(fs_closest_copy(&copy_from_root2, &copy_from_path2, rev_root,
-                          path, pool));
-
-  if (copy_from_root1 == NULL && copy_from_root2 == NULL)
-    {
-      /* never copied -> same line of history */
-      *changed = FALSE;
-    }
-  else if (copy_from_root1 != NULL && copy_from_root2 != NULL)
-    {
-      /* both got copied. At the same time & location? */
-      *changed = (copy_from_root1->rev != copy_from_root2->rev)
-                 || strcmp(copy_from_path1, copy_from_path2);
-    }
-  else
-    {
-      /* one is a copy while the other one is not
-       * -> different lines of history */
-      *changed = TRUE;
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Copy the node at FROM_PATH under FROM_ROOT to TO_PATH under
    TO_ROOT.  If PRESERVE_HISTORY is set, then the copy is recorded in
    the copies table.  Perform temporary allocations in POOL. */
@@ -4475,7 +4431,7 @@ verify_node(dag_node_t *node,
               /* access mergeinfo counter with minimal overhead */
               node_revision_t *noderev;
               SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, dirent->id,
-                                                   iterpool));
+                                                   iterpool, iterpool));
               child_mergeinfo = noderev->mergeinfo_count;
             }
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.c Tue Jun 24 21:29:59 2014
@@ -154,26 +154,6 @@ path_rev_absolute_internal(svn_fs_t *fs,
 }
 
 const char *
-svn_fs_fs__path_l2p_index(svn_fs_t *fs,
-                          svn_revnum_t rev,
-                          svn_boolean_t packed,
-                          apr_pool_t *pool)
-{
-  return apr_psprintf(pool, "%s" PATH_EXT_L2P_INDEX,
-                      path_rev_absolute_internal(fs, rev, packed, pool));
-}
-
-const char *
-svn_fs_fs__path_p2l_index(svn_fs_t *fs,
-                          svn_revnum_t rev,
-                          svn_boolean_t packed,
-                          apr_pool_t *pool)
-{
-  return apr_psprintf(pool, "%s" PATH_EXT_P2L_INDEX,
-                      path_rev_absolute_internal(fs, rev, packed, pool));
-}
-
-const char *
 svn_fs_fs__path_rev_absolute(svn_fs_t *fs,
                              svn_revnum_t rev,
                              apr_pool_t *pool)

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/util.h Tue Jun 24 21:29:59 2014
@@ -176,24 +176,6 @@ svn_fs_fs__path_revprops(svn_fs_t *fs,
                          svn_revnum_t rev,
                          apr_pool_t *pool);
 
-/* Return the path of the file containing the log-to-phys index for the
- * file containing revision REV in FS. The result will be allocated in POOL.
- */
-const char *
-svn_fs_fs__path_l2p_index(svn_fs_t *fs,
-                          svn_revnum_t rev,
-                          svn_boolean_t packed,
-                          apr_pool_t *pool);
-
-/* Return the path of the file containing the phys-to-log index for the
- * file containing revision REV in FS. The result will be allocated in POOL.
- */
-const char *
-svn_fs_fs__path_p2l_index(svn_fs_t *fs,
-                          svn_revnum_t rev,
-                          svn_boolean_t packed,
-                          apr_pool_t *pool);
-
 /* Return the path of the file storing the oldest non-packed revision in FS.
  * The result will be allocated in POOL.
  */

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/verify.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/verify.c Tue Jun 24 21:29:59 2014
@@ -177,8 +177,8 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
   apr_array_header_t *max_ids;
 
   /* common file access structure */
-  svn_fs_fs__revision_file_t rev_file;
-  svn_fs_fs__init_revision_file(&rev_file, fs, start, pool);
+  svn_fs_fs__revision_file_t *rev_file;
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, start, pool));
 
   /* determine the range of items to check for each revision */
   SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, start, count, pool));
@@ -197,13 +197,13 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
           svn_pool_clear(iterpool);
 
           /* get L2P entry.  Ignore unused entries. */
-          SVN_ERR(svn_fs_fs__item_offset(&offset, fs, &rev_file, revision,
+          SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, revision,
                                          NULL, k, iterpool));
           if (offset == -1)
             continue;
 
           /* find the corresponding P2L entry */
-          SVN_ERR(svn_fs_fs__p2l_entry_lookup(&p2l_entry, fs, &rev_file,
+          SVN_ERR(svn_fs_fs__p2l_entry_lookup(&p2l_entry, fs, rev_file,
                                               revision, offset, iterpool));
 
           if (p2l_entry == NULL)
@@ -233,7 +233,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs,
 
   svn_pool_destroy(iterpool);
 
-  SVN_ERR(svn_fs_fs__close_revision_file(&rev_file));
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
 
   return SVN_NO_ERROR;
 }
@@ -260,11 +260,11 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
   apr_off_t offset = 0;
 
   /* common file access structure */
-  svn_fs_fs__revision_file_t rev_file;
-  svn_fs_fs__init_revision_file(&rev_file, fs, start, pool);
+  svn_fs_fs__revision_file_t *rev_file;
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, start, pool));
 
   /* get the size of the rev / pack file as covered by the P2L index */
-  SVN_ERR(svn_fs_fs__p2l_get_max_offset(&max_offset, fs, &rev_file, start,
+  SVN_ERR(svn_fs_fs__p2l_get_max_offset(&max_offset, fs, rev_file, start,
                                         pool));
 
   /* for all offsets in the file, get the P2L index entries and check
@@ -278,7 +278,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
       svn_pool_clear(iterpool);
 
       /* get all entries for the current block */
-      SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, &rev_file, start,
+      SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, rev_file, start,
                                           offset, ffd->p2l_page_size,
                                           iterpool));
       if (entries->nelts == 0)
@@ -302,7 +302,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
           if (entry->type != SVN_FS_FS__ITEM_TYPE_UNUSED)
             {
               apr_off_t l2p_offset;
-              SVN_ERR(svn_fs_fs__item_offset(&l2p_offset, fs, &rev_file,
+              SVN_ERR(svn_fs_fs__item_offset(&l2p_offset, fs, rev_file,
                                              entry->item.revision, NULL,
                                              entry->item.number, iterpool));
 
@@ -325,7 +325,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
 
   svn_pool_destroy(iterpool);
 
-  SVN_ERR(svn_fs_fs__close_revision_file(&rev_file));
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
 
   return SVN_NO_ERROR;
 }
@@ -503,15 +503,15 @@ compare_p2l_to_rev(svn_fs_t *fs,
   SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, start, pool));
 
   /* check file size vs. range covered by index */
-  SVN_ERR(svn_io_file_seek(rev_file->file, APR_END, &offset, pool));
+  SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
   SVN_ERR(svn_fs_fs__p2l_get_max_offset(&max_offset, fs, rev_file, start,
                                         pool));
 
-  if (offset != max_offset)
+  if (rev_file->l2p_offset != max_offset)
     return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT, NULL,
                              _("File size of %s for revision r%ld does "
                                "not match p2l index size of %s"),
-                             apr_off_t_toa(pool, offset), start,
+                             apr_off_t_toa(pool, rev_file->l2p_offset), start,
                              apr_off_t_toa(pool, max_offset));
 
   SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL, 0,

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_repos/log.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_repos/log.c Tue Jun 24 21:29:59 2014
@@ -189,21 +189,29 @@ detect_changed(apr_hash_t **changed,
 {
   apr_hash_t *changes = prefetched_changes;
   apr_hash_index_t *hi;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
   svn_boolean_t found_readable = FALSE;
   svn_boolean_t found_unreadable = FALSE;
 
-  *changed = svn_hash__make(pool);
+  /* If we create the CHANGES hash ourselves, we can reuse it as the
+   * result hash as it contains the exact same keys - but with _all_
+   * values being replaced by structs of a different type. */
   if (changes == NULL)
-    SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
+    {
+      SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
+      *changed = changes;
+    }
+  else
+    {
+      *changed = svn_hash__make(pool);
+    }
 
   if (apr_hash_count(changes) == 0)
     /* No paths changed in this revision?  Uh, sure, I guess the
        revision is readable, then.  */
     return SVN_NO_ERROR;
 
-  subpool = svn_pool_create(pool);
-
+  iterpool = svn_pool_create(pool);
   for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
     {
       /* NOTE:  Much of this loop is going to look quite similar to
@@ -215,7 +223,7 @@ detect_changed(apr_hash_t **changed,
       char action;
       svn_log_changed_path2_t *item;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
       /* Skip path if unreadable. */
       if (authz_read_func)
@@ -223,7 +231,7 @@ detect_changed(apr_hash_t **changed,
           svn_boolean_t readable;
           SVN_ERR(authz_read_func(&readable,
                                   root, path,
-                                  authz_read_baton, subpool));
+                                  authz_read_baton, iterpool));
           if (! readable)
             {
               found_unreadable = TRUE;
@@ -281,26 +289,26 @@ detect_changed(apr_hash_t **changed,
               svn_revnum_t prev_rev;
               const char *parent_path, *name;
 
-              svn_fspath__split(&parent_path, &name, path, subpool);
+              svn_fspath__split(&parent_path, &name, path, iterpool);
 
               SVN_ERR(svn_fs_node_history2(&history, root, parent_path,
-                                           subpool, subpool));
+                                           iterpool, iterpool));
 
               /* Two calls because the first call returns the original
                  revision as the deleted child means it is 'interesting' */
-              SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, subpool,
-                                           subpool));
-              SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, subpool,
-                                           subpool));
+              SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, iterpool,
+                                           iterpool));
+              SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, iterpool,
+                                           iterpool));
 
               SVN_ERR(svn_fs_history_location(&parent_path, &prev_rev, history,
-                                              subpool));
-              SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, subpool));
-              check_path = svn_fspath__join(parent_path, name, subpool);
+                                              iterpool));
+              SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, iterpool));
+              check_path = svn_fspath__join(parent_path, name, iterpool);
             }
 
           SVN_ERR(svn_fs_check_path(&item->node_kind, check_root, check_path,
-                                    subpool));
+                                    iterpool));
         }
 
 
@@ -315,7 +323,7 @@ detect_changed(apr_hash_t **changed,
           if (!change->copyfrom_known)
             {
               SVN_ERR(svn_fs_copied_from(&copyfrom_rev, &copyfrom_path,
-                                        root, path, subpool));
+                                        root, path, iterpool));
               copyfrom_path = apr_pstrdup(pool, copyfrom_path);
             }
 
@@ -328,10 +336,10 @@ detect_changed(apr_hash_t **changed,
                   svn_fs_root_t *copyfrom_root;
 
                   SVN_ERR(svn_fs_revision_root(&copyfrom_root, fs,
-                                               copyfrom_rev, subpool));
+                                               copyfrom_rev, iterpool));
                   SVN_ERR(authz_read_func(&readable,
                                           copyfrom_root, copyfrom_path,
-                                          authz_read_baton, subpool));
+                                          authz_read_baton, iterpool));
                   if (! readable)
                     found_unreadable = TRUE;
                 }
@@ -347,7 +355,7 @@ detect_changed(apr_hash_t **changed,
       apr_hash_set(*changed, path, path_len, item);
     }
 
-  svn_pool_destroy(subpool);
+  svn_pool_destroy(iterpool);
 
   if (! found_readable)
     /* Every changed-path was unreadable. */
@@ -1300,6 +1308,8 @@ send_log(svn_revnum_t rev,
      revision. */
   if (found_rev_of_interest)
     {
+      apr_pool_t *scratch_pool;
+
       /* Is REV a merged revision we've already sent? */
       if (nested_merges && handling_merged_revision)
         {
@@ -1317,12 +1327,14 @@ send_log(svn_revnum_t rev,
             }
         }
 
-      return (*receiver)(receiver_baton, log_entry, pool);
-    }
-  else
-    {
-      return SVN_NO_ERROR;
+      /* Pass a scratch pool to ensure no temporary state stored
+         by the receiver callback persists. */
+      scratch_pool = svn_pool_create(pool);
+      SVN_ERR(receiver(receiver_baton, log_entry, scratch_pool));
+      svn_pool_destroy(scratch_pool);
     }
+
+  return SVN_NO_ERROR;
 }
 
 /* This controls how many history objects we keep open.  For any targets

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_repos/repos.c Tue Jun 24 21:29:59 2014
@@ -267,9 +267,9 @@ create_locks(svn_repos_t *repos, apr_poo
 
 
 #define HOOKS_ENVIRONMENT_TEXT                                                \
-  "# The hook program typically does not inherit the environment of"       NL \
-  "# its parent process.  For example, a common problem is for the"        NL \
-  "# PATH environment variable to not be set to its usual value, so"       NL \
+  "# The hook program runs in an empty environment, unless the server is"  NL \
+  "# explicitly configured otherwise.  For example, a common problem is for" NL \
+  "# the PATH environment variable to not be set to its usual value, so"   NL \
   "# that subprograms fail to launch unless invoked via absolute path."    NL \
   "# If you're having unexpected problems with a hook program, the"        NL \
   "# culprit may be unusual (or missing) environment variables."           NL
@@ -280,6 +280,16 @@ create_locks(svn_repos_t *repos, apr_poo
   "# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and"        NL \
   "# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/"          NL
 
+#define HOOKS_QUOTE_ARGUMENTS_TEXT                                            \
+  "# CAUTION:"                                                             NL \
+  "# For security reasons, you MUST always properly quote arguments when"  NL \
+  "# you use them, as those arguments could contain whitespace or other"   NL \
+  "# problematic characters. Additionally, you should delimit the list"    NL \
+  "# of options with \"--\" before passing the arguments, so malicious"    NL \
+  "# clients cannot bootleg unexpected options to the commands your"       NL \
+  "# script aims to execute."                                              NL \
+  "# For similar reasons, you should also add a trailing @ to URLs which"  NL \
+  "# are passed to SVN commands accepting URLs with peg revisions."        NL
 
 static svn_error_t *
 create_hooks(svn_repos_t *repos, apr_pool_t *pool)
@@ -354,6 +364,8 @@ create_hooks(svn_repos_t *repos, apr_poo
 "# "                                                                         NL
 HOOKS_ENVIRONMENT_TEXT
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter."          NL
 PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
@@ -439,6 +451,8 @@ PREWRITTEN_HOOKS_TEXT
 "#"                                                                          NL
 HOOKS_ENVIRONMENT_TEXT
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter."          NL
 PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
@@ -522,6 +536,8 @@ PREWRITTEN_HOOKS_TEXT
 "#"                                                                          NL
 HOOKS_ENVIRONMENT_TEXT
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter."          NL
 PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
@@ -594,6 +610,8 @@ PREWRITTEN_HOOKS_TEXT
 "# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe',"                              NL
 "# but the basic idea is the same."                                          NL
 "#"                                                                          NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter:"          NL
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
@@ -681,6 +699,8 @@ PREWRITTEN_HOOKS_TEXT
 "# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe',"                              NL
 "# but the basic idea is the same."                                          NL
 "#"                                                                          NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter:"          NL
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
@@ -767,6 +787,8 @@ PREWRITTEN_HOOKS_TEXT
 "# "                                                                         NL
 HOOKS_ENVIRONMENT_TEXT
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter."          NL
 PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
@@ -830,6 +852,8 @@ PREWRITTEN_HOOKS_TEXT
 "# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe',"                              NL
 "# but the basic idea is the same."                                          NL
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter:"          NL
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
@@ -888,6 +912,8 @@ PREWRITTEN_HOOKS_TEXT
 "# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe',"                              NL
 "# but the basic idea is the same."                                          NL
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter:"          NL
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
@@ -951,6 +977,8 @@ PREWRITTEN_HOOKS_TEXT
 "# "                                                                         NL
 HOOKS_ENVIRONMENT_TEXT
 "# "                                                                         NL
+HOOKS_QUOTE_ARGUMENTS_TEXT
+"# "                                                                         NL
 "# Here is an example hook script, for a Unix /bin/sh interpreter."          NL
 PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/checksum.c Tue Jun 24 21:29:59 2014
@@ -739,7 +739,7 @@ close_handler(void *baton)
  * function does not enforce any such restriction.  Also, the caller must
  * make sure that DIGEST refers to a buffer of sufficient length.
  */
-svn_stream_t *
+static svn_stream_t *
 wrap_write_stream(svn_checksum_t **checksum,
                   unsigned char *digest,
                   svn_stream_t *inner_stream,

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c Tue Jun 24 21:29:59 2014
@@ -2839,6 +2839,10 @@ svn_io_start_cmd3(apr_proc_t *cmd_proc,
     {
       const char *path_apr;
 
+      /* APR doesn't like our canonical path format for current directory */
+      if (path[0] == '\0')
+        path = ".";
+
       SVN_ERR(cstring_from_utf8(&path_apr, path, pool));
       apr_err = apr_procattr_dir_set(cmdproc_attr, path_apr);
       if (apr_err)

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c Tue Jun 24 21:29:59 2014
@@ -1056,7 +1056,7 @@ svn__strtoul(const char* buffer, const c
    */
   while (1)
     {
-      unsigned long c = *buffer - '0';
+      unsigned long c = (unsigned char)*buffer - (unsigned char)'0';
       if (c > 9)
         break;
 
@@ -1068,6 +1068,15 @@ svn__strtoul(const char* buffer, const c
   return result;
 }
 
+long
+svn__strtol(const char* buffer, const char** end)
+{
+  if (*buffer == '-')
+    return -(long)svn__strtoul(buffer+1, end);
+  else
+    return (long)svn__strtoul(buffer, end);
+}
+
 
 /* "Precalculated" itoa values for 2 places (including leading zeros).
  * For maximum performance, make sure all table entries are word-aligned.

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/win32_crashrpt.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/win32_crashrpt.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/win32_crashrpt.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/win32_crashrpt.c Tue Jun 24 21:29:59 2014
@@ -252,9 +252,9 @@ write_process_info(EXCEPTION_RECORD *exc
                 context->R12, context->R13, context->R14, context->R15);
 
   fprintf(log_file,
-                "cs=%04x  ss=%04x  ds=%04x  es=%04x  fs=%04x  gs=%04x  ss=%04x\n",
-                context->SegCs, context->SegDs, context->SegEs,
-                context->SegFs, context->SegGs, context->SegSs);
+                "cs=%04x  ss=%04x  ds=%04x  es=%04x  fs=%04x  gs=%04x\n",
+                context->SegCs, context->SegSs, context->SegDs,
+                context->SegEs, context->SegFs, context->SegGs);
 #else
 #error Unknown processortype, please disable SVN_USE_WIN32_CRASHHANDLER
 #endif

Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/dav_svn.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/dav_svn.h Tue Jun 24 21:29:59 2014
@@ -329,6 +329,10 @@ svn_boolean_t dav_svn__get_fulltext_cach
 /* for the repository referred to by this request, is revprop caching active? */
 svn_boolean_t dav_svn__get_revprop_cache_flag(request_rec *r);
 
+/* has block read mode been enabled for the repository referred to by this
+ * request? */
+svn_boolean_t dav_svn__get_block_read_flag(request_rec *r);
+
 /* for the repository referred to by this request, are subrequests bypassed?
  * A function pointer if yes, NULL if not.
  */

Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c Tue Jun 24 21:29:59 2014
@@ -105,6 +105,7 @@ typedef struct dir_conf_t {
   enum conf_flag txdelta_cache;      /* whether to enable txdelta caching */
   enum conf_flag fulltext_cache;     /* whether to enable fulltext caching */
   enum conf_flag revprop_cache;      /* whether to enable revprop caching */
+  enum conf_flag block_read;         /* whether to enable block read mode */
   const char *hooks_env;             /* path to hook script env config file */
 } dir_conf_t;
 
@@ -248,6 +249,7 @@ merge_dir_config(apr_pool_t *p, void *ba
   newconf->txdelta_cache = INHERIT_VALUE(parent, child, txdelta_cache);
   newconf->fulltext_cache = INHERIT_VALUE(parent, child, fulltext_cache);
   newconf->revprop_cache = INHERIT_VALUE(parent, child, revprop_cache);
+  newconf->block_read = INHERIT_VALUE(parent, child, block_read);  
   newconf->root_dir = INHERIT_VALUE(parent, child, root_dir);
   newconf->hooks_env = INHERIT_VALUE(parent, child, hooks_env);
 
@@ -544,6 +546,19 @@ SVNCacheRevProps_cmd(cmd_parms *cmd, voi
 }
 
 static const char *
+SVNBlockRead_cmd(cmd_parms *cmd, void *config, int arg)
+{
+  dir_conf_t *conf = config;
+
+  if (arg)
+    conf->block_read = CONF_FLAG_ON;
+  else
+    conf->block_read = CONF_FLAG_OFF;
+
+  return NULL;
+}
+
+static const char *
 SVNInMemoryCacheSize_cmd(cmd_parms *cmd, void *config, const char *arg1)
 {
   svn_cache_config_t settings = *svn_cache_config_get();
@@ -948,6 +963,15 @@ dav_svn__get_revprop_cache_flag(request_
 }
 
 
+svn_boolean_t
+dav_svn__get_block_read_flag(request_rec *r)
+{
+  dir_conf_t *conf;
+
+  conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
+  return conf->block_read == CONF_FLAG_ON;
+}
+
 int
 dav_svn__get_compression_level(request_rec *r)
 {
@@ -1289,6 +1313,13 @@ static const command_rec cmds[] =
                "in the documentation"
                "(default is Off)."),
 
+  /* per directory/location */
+  AP_INIT_FLAG("SVNBlockRead", SVNBlockRead_cmd, NULL,
+               ACCESS_CONF|RSRC_CONF,
+               "speeds up operations of FSFS 1.9+ repositories if large"
+               "caches (see SVNInMemoryCacheSize) have been configured."
+               "(default is Off)."),
+
   /* per server */
   AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL,
                 RSRC_CONF,

Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/repos.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/repos.c Tue Jun 24 21:29:59 2014
@@ -2269,6 +2269,8 @@ get_resource(request_rec *r,
                     dav_svn__get_fulltext_cache_flag(r) ? "1" :"0");
       svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                     dav_svn__get_revprop_cache_flag(r) ? "2" :"0");
+      svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ,
+                    dav_svn__get_block_read_flag(r) ? "1" :"0");
 
       /* Disallow BDB/event until issue 4157 is fixed. */
       if (!strcmp(ap_show_mpm(), "event"))

Modified: subversion/branches/svn-auth-x509/subversion/svn/log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/log-cmd.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svn/log-cmd.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svn/log-cmd.c Tue Jun 24 21:29:59 2014
@@ -364,6 +364,7 @@ svn_cl__log_entry_receiver(void *baton,
     {
       apr_array_header_t *sorted_paths;
       int i;
+      apr_pool_t *iterpool;
 
       /* Get an array of sorted hash keys. */
       sorted_paths = svn_sort__hash(log_entry->changed_paths2,
@@ -371,6 +372,7 @@ svn_cl__log_entry_receiver(void *baton,
 
       SVN_ERR(svn_cmdline_printf(pool,
                                  _("Changed paths:\n")));
+      iterpool = svn_pool_create(pool);
       for (i = 0; i < sorted_paths->nelts; i++)
         {
           svn_sort__item_t *item = &(APR_ARRAY_IDX(sorted_paths, i,
@@ -379,6 +381,8 @@ svn_cl__log_entry_receiver(void *baton,
           svn_log_changed_path2_t *log_item = item->value;
           const char *copy_data = "";
 
+          svn_pool_clear(iterpool);
+
           if (lb->ctx->cancel_func)
             SVN_ERR(lb->ctx->cancel_func(lb->ctx->cancel_baton));
 
@@ -386,34 +390,39 @@ svn_cl__log_entry_receiver(void *baton,
               && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev))
             {
               copy_data
-                = apr_psprintf(pool,
+                = apr_psprintf(iterpool,
                                _(" (from %s:%ld)"),
                                log_item->copyfrom_path,
                                log_item->copyfrom_rev);
             }
-          SVN_ERR(svn_cmdline_printf(pool, "   %c %s%s\n",
+          SVN_ERR(svn_cmdline_printf(iterpool, "   %c %s%s\n",
                                      log_item->action, path,
                                      copy_data));
         }
+      svn_pool_destroy(iterpool);
     }
 
   if (lb->merge_stack && lb->merge_stack->nelts > 0)
     {
       int i;
+      apr_pool_t *iterpool;
 
       /* Print the result of merge line */
       if (log_entry->subtractive_merge)
         SVN_ERR(svn_cmdline_printf(pool, _("Reverse merged via:")));
       else
         SVN_ERR(svn_cmdline_printf(pool, _("Merged via:")));
+      iterpool = svn_pool_create(pool);
       for (i = 0; i < lb->merge_stack->nelts; i++)
         {
           svn_revnum_t rev = APR_ARRAY_IDX(lb->merge_stack, i, svn_revnum_t);
 
-          SVN_ERR(svn_cmdline_printf(pool, " r%ld%c", rev,
+          svn_pool_clear(iterpool);
+          SVN_ERR(svn_cmdline_printf(iterpool, " r%ld%c", rev,
                                      i == lb->merge_stack->nelts - 1 ?
                                                                   '\n' : ','));
         }
+      svn_pool_destroy(iterpool);
     }
 
   if (message != NULL)

Modified: subversion/branches/svn-auth-x509/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/notify.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svn/notify.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svn/notify.c Tue Jun 24 21:29:59 2014
@@ -1056,6 +1056,14 @@ notify_body(struct notify_baton *nb,
                  path_local));
       break;
 
+    case svn_wc_notify_commit_finalizing:
+      if (nb->sent_first_txdelta)
+        {
+          SVN_ERR(svn_cmdline_printf(pool, _("done\n")));
+          SVN_ERR(svn_cmdline_printf(pool, _("Committing transaction...")));
+        }
+      break;
+
     default:
       break;
     }

Modified: subversion/branches/svn-auth-x509/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/svn.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svn/svn.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svn/svn.c Tue Jun 24 21:29:59 2014
@@ -210,6 +210,8 @@ const apr_getopt_option_t svn_cl__option
                        "                             "
                        "  --ignore-eol-style: Ignore changes in EOL style\n"
                        "                             "
+                       "  -U ARG, --context ARG: Show ARG lines of context\n"
+                       "                             "
                        "  -p, --show-c-function: Show C function name")},
   {"targets",       opt_targets, 1,
                     N_("pass contents of file ARG as additional args")},

Modified: subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svnadmin/svnadmin.c Tue Jun 24 21:29:59 2014
@@ -120,6 +120,7 @@ open_repos(svn_repos_t **repos,
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2");
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS,
                            svn_uuid_generate(pool));
+  svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, "1");
 
   /* now, open the requested repository */
   SVN_ERR(svn_repos_open3(repos, path, fs_config, pool, pool));

Modified: subversion/branches/svn-auth-x509/subversion/svnlook/svnlook.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnlook/svnlook.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svnlook/svnlook.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svnlook/svnlook.c Tue Jun 24 21:29:59 2014
@@ -191,6 +191,8 @@ static const apr_getopt_option_t options
       "                             "
       "  --ignore-eol-style: Ignore changes in EOL style\n"
       "                             "
+      "  -U ARG, --context ARG: Show ARG lines of context\n"
+      "                             "
       "  -p, --show-c-function: Show C function name")},
 
   {"quiet",             'q', 0,