You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2012/03/14 14:07:09 UTC

svn commit: r1300532 [3/9] - in /subversion/branches/multi-layer-moves: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ notes/ notes/directory-index/ subversion/bindings/javahl/ subversion/bindings/javahl/native/ sub...

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.c Wed Mar 14 13:07:02 2012
@@ -81,7 +81,7 @@
 /* Begin deltification after a node history exceeded this this limit.
    Useful values are 4 to 64 with 16 being a good compromise between
    computational overhead and pository size savings.
-   Should be a power of 2.  
+   Should be a power of 2.
    Values < 2 will result in standard skip-delta behavior. */
 #define SVN_FS_FS_MAX_LINEAR_DELTIFICATION 16
 
@@ -800,7 +800,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
       err = svn_error_compose_create(
               err,
               unlock_proto_rev_list_locked(fs, txn_id, *lockcookie, pool));
-      
+
       *lockcookie = NULL;
     }
 
@@ -1548,6 +1548,16 @@ ensure_revision_exists(svn_fs_t *fs,
                            _("No such revision %ld"), rev);
 }
 
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+                           svn_fs_t *fs,
+                           apr_pool_t *pool)
+{
+  /* Different order of parameters. */
+  SVN_ERR(ensure_revision_exists(fs, rev, pool));
+  return SVN_NO_ERROR;
+}
+
 /* Open the correct revision file for REV.  If the filesystem FS has
    been packed, *FILE will be set to the packed file; otherwise, set *FILE
    to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
@@ -2879,7 +2889,7 @@ create_rep_state(struct rep_state **rep_
          ### going to jump straight to this comment anyway! */
       return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
                                "Corrupt representation '%s'",
-                               rep 
+                               rep
                                ? representation_string(rep, ffd->format, TRUE,
                                                        TRUE, pool)
                                : "(null)");
@@ -2895,7 +2905,7 @@ struct rep_read_baton
 
   /* If not NULL, this is the base for the first delta window in rs_list */
   svn_stringbuf_t *base_window;
-  
+
   /* The state of all prior delta representations. */
   apr_array_header_t *rs_list;
 
@@ -3139,14 +3149,14 @@ build_rep_list(apr_array_header_t **list
       SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
       if (is_cached)
         {
-          /* We already have a reconstructed window in our cache. 
+          /* We already have a reconstructed window in our cache.
              Write a pseudo rep_state with the full length. */
           rs->off = rs->start;
           rs->end = rs->start + (*window_p)->len;
           *src_state = rs;
           return SVN_NO_ERROR;
         }
-      
+
       if (rep_args->is_delta == FALSE)
         {
           /* This is a plaintext, so just return the current rep_state. */
@@ -3205,7 +3215,7 @@ rep_read_get_baton(struct rep_read_baton
   else
     b->current_fulltext = NULL;
 
-  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window, 
+  SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
                          &b->src_state, fs, rep,
                          b->filehandle_pool));
 
@@ -3286,7 +3296,7 @@ get_combined_window(svn_stringbuf_t **re
     {
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       SVN_ERR(read_window(&window, rb->chunk_index, rs, window_pool));
-      
+
       APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
       if (window->src_ops == 0)
         {
@@ -3294,7 +3304,7 @@ get_combined_window(svn_stringbuf_t **re
           break;
         }
     }
-    
+
   /* Combine in the windows from the other delta reps. */
   pool = svn_pool_create(rb->pool);
   for (--i; i >= 0; --i)
@@ -3307,7 +3317,7 @@ get_combined_window(svn_stringbuf_t **re
       new_pool = svn_pool_create(rb->pool);
       buf = svn_stringbuf_create_ensure(window->tview_len, new_pool);
       buf->len = window->tview_len;
-      
+
       svn_txdelta_apply_instructions(window, source ? source->data : NULL,
                                      buf->data, &buf->len);
       if (buf->len != window->tview_len)
@@ -3327,7 +3337,7 @@ get_combined_window(svn_stringbuf_t **re
     }
 
   svn_pool_destroy(window_pool);
-  
+
   *result = buf;
   return SVN_NO_ERROR;
 }
@@ -3519,7 +3529,7 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      const char *fulltext_key = NULL;
+      const char *fulltext_cache_key = NULL;
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
@@ -3528,10 +3538,11 @@ read_representation(svn_stream_t **conte
         {
           svn_stringbuf_t *fulltext;
           svn_boolean_t is_cached;
-          fulltext_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
+          fulltext_cache_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
                                       rep->revision, rep->offset);
           SVN_ERR(svn_cache__get((void **) &fulltext, &is_cached,
-                                 ffd->fulltext_cache, fulltext_key, pool));
+                                 ffd->fulltext_cache, fulltext_cache_key,
+                                 pool));
           if (is_cached)
             {
               *contents_p = svn_stream_from_stringbuf(fulltext, pool);
@@ -3539,7 +3550,7 @@ read_representation(svn_stream_t **conte
             }
         }
 
-      SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_key, pool));
+      SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool));
 
       *contents_p = svn_stream_create(rb, pool);
       svn_stream_set_read(*contents_p, rep_read_contents);
@@ -5268,7 +5279,7 @@ choose_delta_base(representation_t **rep
   count = noderev->predecessor_count;
   count = count & (count - 1);
 
-  /* We use skip delta for limiting the number of delta operations 
+  /* We use skip delta for limiting the number of delta operations
      along very long node histories.  Close to HEAD however, we create
      a linear history to minimize delta size.  */
   walk = noderev->predecessor_count - count;
@@ -5387,8 +5398,8 @@ rep_write_get_baton(struct rep_write_bat
    limited by both, POOL and REP lifetime.
  */
 static svn_error_t *
-get_shared_rep(representation_t **old_rep, 
-               svn_fs_t *fs, 
+get_shared_rep(representation_t **old_rep,
+               svn_fs_t *fs,
                representation_t *rep,
                apr_hash_t *reps_hash,
                apr_pool_t *pool)
@@ -5408,7 +5419,7 @@ get_shared_rep(representation_t **old_re
     *old_rep = apr_hash_get(reps_hash,
                             rep->sha1_checksum->digest,
                             APR_SHA1_DIGESTSIZE);
-   
+
   /* If we haven't found anything yet, try harder and consult our DB. */
   if (*old_rep == NULL)
     {
@@ -5447,7 +5458,7 @@ get_shared_rep(representation_t **old_re
       (*old_rep)->md5_checksum = rep->md5_checksum;
       (*old_rep)->uniquifier = rep->uniquifier;
     }
-    
+
   return SVN_NO_ERROR;
 }
 
@@ -5771,7 +5782,7 @@ write_hash_delta_rep(representation_t *r
 {
   svn_txdelta_window_handler_t diff_wh;
   void *diff_whb;
-  
+
   svn_stream_t *file_stream;
   svn_stream_t *stream;
   representation_t *base_rep;
@@ -5779,8 +5790,8 @@ write_hash_delta_rep(representation_t *r
   svn_stream_t *source;
   const char *header;
 
-  apr_off_t rep_end = 0; 
-  apr_off_t delta_start = 0; 
+  apr_off_t rep_end = 0;
+  apr_off_t delta_start = 0;
 
   struct write_hash_baton *whb;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -5809,7 +5820,7 @@ write_hash_delta_rep(representation_t *r
 
   SVN_ERR(get_file_offset(&delta_start, file, pool));
   file_stream = svn_stream_from_aprfile2(file, TRUE, pool);
-  
+
   /* Prepare to write the svndiff data. */
   svn_txdelta_to_svndiff3(&diff_wh,
                           &diff_whb,
@@ -5865,6 +5876,8 @@ write_hash_delta_rep(representation_t *r
 /* Sanity check ROOT_NODEREV, a candidate for being the root node-revision
    of (not yet committed) revision REV in FS.  Use POOL for temporary
    allocations.
+
+   If you change this function, consider updating svn_fs_fs__verify() too.
  */
 static svn_error_t *
 validate_root_noderev(svn_fs_t *fs,
@@ -5911,8 +5924,11 @@ validate_root_noderev(svn_fs_t *fs,
       return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                _("predecessor count for "
                                  "the root node-revision is wrong: "
-                                 "found %d, committing r%ld"),
-                                 root_noderev->predecessor_count, rev);
+                                 "found (%d+%ld != %d), committing r%ld"),
+                                 head_predecessor_count,
+                                 rev - head_revnum, /* This is equal to 1. */
+                                 root_noderev->predecessor_count,
+                                 rev);
     }
 
   return SVN_NO_ERROR;
@@ -6053,7 +6069,7 @@ write_final_rev(const svn_fs_id_t **new_
                                    proplist, fs, noderev, reps_hash,
                                    pool));
 #else
-      SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist, 
+      SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
                              fs, reps_hash, pool));
 #endif
     }
@@ -6112,15 +6128,15 @@ write_final_rev(const svn_fs_id_t **new_
       if (noderev->prop_rep && noderev->prop_rep->revision == rev)
         {
           /* Add new property reps to hash and on-disk cache. */
-          representation_t *copy 
+          representation_t *copy
             = svn_fs_fs__rep_copy(noderev->prop_rep, reps_pool);
 
           SVN_ERR_ASSERT(reps_to_cache && reps_pool);
           APR_ARRAY_PUSH(reps_to_cache, representation_t *) = copy;
 
-          apr_hash_set(reps_hash, 
-                        copy->sha1_checksum->digest, 
-                        APR_SHA1_DIGESTSIZE, 
+          apr_hash_set(reps_hash,
+                        copy->sha1_checksum->digest,
+                        APR_SHA1_DIGESTSIZE,
                         copy);
         }
     }
@@ -7878,7 +7894,7 @@ svn_fs_fs__pack(svn_fs_t *fs,
 
 /** Verifying. **/
 
-/* Body of svn_fs_fs__verify().
+/* Used by svn_fs_fs__verify().
    Implements svn_fs_fs__walk_rep_reference().walker.  */
 static svn_error_t *
 verify_walker(representation_t *rep,
@@ -7899,23 +7915,93 @@ svn_error_t *
 svn_fs_fs__verify(svn_fs_t *fs,
                   svn_cancel_func_t cancel_func,
                   void *cancel_baton,
+                  svn_revnum_t start,
+                  svn_revnum_t end,
                   apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_boolean_t exists;
+  svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
     return SVN_NO_ERROR;
 
-  /* 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. */
+  /* Input validation. */
+  if (! SVN_IS_VALID_REVNUM(start))
+    start = 0;
+  if (! SVN_IS_VALID_REVNUM(end))
+    end = youngest;
+  SVN_ERR(ensure_revision_exists(fs, start, iterpool));
+  SVN_ERR(ensure_revision_exists(fs, end, iterpool));
+
+  /* rep-cache verification. */
   SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
   if (exists)
-    /* Don't take any lock. */
+    /* Do not attempt to walk the rep-cache database if its file does not exist,
+       since doing so would create it --- which may confuse the administrator.
+       Don't take any lock. */
     SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
                                           cancel_func, cancel_baton,
+                                          start, end,
                                           pool));
 
+  /* Issue #4129: bogus pred-counts on the root node-rev. */
+  {
+    svn_revnum_t i;
+    int predecessor_predecessor_count;
+
+    /* Compute PREDECESSOR_PREDECESSOR_COUNT. */
+    if (start == 0)
+      /* The value that passes the if() at the end of the loop. */
+      predecessor_predecessor_count = -1;
+    else
+      {
+        svn_fs_id_t *root_id;
+        node_revision_t *root_noderev;
+        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, start-1, iterpool));
+        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+                                             iterpool));
+        predecessor_predecessor_count = root_noderev->predecessor_count;
+      }
+
+    for (i = start; i <= end; i++)
+      {
+        /* ### Caching.
+
+           svn_fs_fs__rev_get_root() consults caches, which in verify we
+           don't want.  But we can't easily bypass that, as
+           svn_fs_revision_root()+svn_fs_node_id()'s implementation uses
+           svn_fs_fs__rev_get_root() too.
+
+           ### A future revision will make fs_verify() disable caches when it
+           ### opens ffd.
+         */
+        svn_fs_id_t *root_id;
+        node_revision_t *root_noderev;
+
+        if ((i % 128) == 0) /* uneducated guess */
+          svn_pool_clear(iterpool);
+
+        /* Fetch ROOT_NODEREV. */
+        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, i, iterpool));
+        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+                                             iterpool));
+
+        /* Check correctness. (Compare validate_root_noderev().) */
+        if (1+predecessor_predecessor_count != root_noderev->predecessor_count)
+          return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                   _("predecessor count for "
+                                     "the root node-revision is wrong: "
+                                     "r%ld has %d, but r%ld has %d"),
+                                   i, root_noderev->predecessor_count,
+                                   i-1, predecessor_predecessor_count);
+
+        predecessor_predecessor_count = root_noderev->predecessor_count;
+      }
+  }
+
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -8079,7 +8165,7 @@ hotcopy_io_copy_dir_recursively(const ch
           else if (this_entry.filetype == APR_DIR) /* recurse */
             {
               const char *src_target;
-              
+
               /* Prevent infinite recursion by filtering off our
                  newly created destination path. */
               if (strcmp(src, dst_parent) == 0
@@ -8284,7 +8370,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f
   for (rev = start_rev; rev < end_rev; rev++)
     {
       const char *rev_path;
-      
+
       svn_pool_clear(iterpool);
 
       /* If necessary, update paths for shard. */

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/fs_fs.h Wed Mar 14 13:07:02 2012
@@ -42,6 +42,8 @@ svn_error_t *svn_fs_fs__upgrade(svn_fs_t
 svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
                                svn_cancel_func_t cancel_func,
                                void *cancel_baton,
+                               svn_revnum_t start,
+                               svn_revnum_t end,
                                apr_pool_t *pool);
 
 /* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
@@ -106,6 +108,12 @@ svn_error_t *svn_fs_fs__youngest_rev(svn
                                      svn_fs_t *fs,
                                      apr_pool_t *pool);
 
+/* Return an error iff REV does not exist in FS. */
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+                           svn_fs_t *fs,
+                           apr_pool_t *pool);
+
 /* Set *ROOT_ID to the node-id for the root of revision REV in
    filesystem FS.  Do any allocations in POOL. */
 svn_error_t *svn_fs_fs__rev_get_root(svn_fs_id_t **root_id,

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache-db.sql Wed Mar 14 13:07:02 2012
@@ -33,6 +33,11 @@ CREATE TABLE rep_cache (
   expanded_size INTEGER NOT NULL
   );
 
+/* There isn't an implicit index on a TEXT column, so create an explicit one. */
+CREATE INDEX I_HASH on REP_CACHE (hash);
+
+/* The index didn't exist until 1.7.5; therefore, some USER_VERSION=1
+   rep-cache.db files out there DO NOT contain an I_HASH index. */
 PRAGMA USER_VERSION = 1;
 
 
@@ -47,9 +52,15 @@ INSERT OR FAIL INTO rep_cache (hash, rev
 VALUES (?1, ?2, ?3, ?4, ?5)
 
 
--- STMT_GET_ALL_REPS
+-- STMT_GET_REPS_FOR_RANGE
 SELECT hash, revision, offset, size, expanded_size
 FROM rep_cache
+WHERE revision >= ?1 AND revision <= ?2
+
+
+-- STMT_GET_MAX_REV
+SELECT MAX(revision)
+FROM rep_cache
 
 
 -- STMT_DEL_REPS_YOUNGER_THAN_REV

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.c Wed Mar 14 13:07:02 2012
@@ -56,24 +56,9 @@ rep_has_been_born(representation_t *rep,
                   svn_fs_t *fs,
                   apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fsap_data;
-  svn_revnum_t youngest;
-
   SVN_ERR_ASSERT(rep);
 
-  youngest = ffd->youngest_rev_cache;
-  if (youngest < rep->revision)
-  {
-    /* Stale cache. */
-    SVN_ERR(svn_fs_fs__youngest_rev(&youngest, fs, pool));
-
-    /* Fresh cache. */
-    if (youngest < rep->revision)
-      return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                               _("Youngest revision is r%ld, but "
-                                 "rep-cache contains r%ld"),
-                               youngest, rep->revision);
-  }
+  SVN_ERR(svn_fs_fs__revision_exists(rep->revision, fs, pool));
 
   return SVN_NO_ERROR;
 }
@@ -141,11 +126,13 @@ svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
                               svn_error_t *(*walker)(representation_t *,
                                                      void *,
-                                                     svn_fs_t *, 
+                                                     svn_fs_t *,
                                                      apr_pool_t *),
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -161,9 +148,25 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
   if (! ffd->rep_cache_db)
     SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool));
 
+  /* Check global invariants. */
+  if (start == 0)
+    {
+      svn_sqlite__stmt_t *stmt2;
+      svn_revnum_t max;
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt2, ffd->rep_cache_db,
+                                        STMT_GET_MAX_REV));
+      SVN_ERR(svn_sqlite__step(&have_row, stmt2));
+      max = svn_sqlite__column_revnum(stmt2, 0);
+      SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
+      SVN_ERR(svn_sqlite__reset(stmt2));
+    }
+
   /* Get the statement. (There are no arguments to bind.) */
   SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
-                                    STMT_GET_ALL_REPS));
+                                    STMT_GET_REPS_FOR_RANGE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "rr",
+                            start, end));
 
   /* Walk the cache entries. */
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -171,7 +174,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
     {
       representation_t *rep;
       const char *sha1_digest;
-      
+
       /* Clear ITERPOOL occasionally. */
       if (iterations++ % 16 == 0)
         svn_pool_clear(iterpool);
@@ -191,10 +194,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
       rep->size = svn_sqlite__column_int64(stmt, 3);
       rep->expanded_size = svn_sqlite__column_int64(stmt, 4);
 
-      /* Sanity check. */
-      if (rep)
-        SVN_ERR(rep_has_been_born(rep, fs, iterpool));
-
       /* Walk. */
       SVN_ERR(walker(rep, walker_baton, fs, iterpool));
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/rep-cache.h Wed Mar 14 13:07:02 2012
@@ -50,11 +50,13 @@ svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
                               svn_error_t *(*walker)(representation_t *rep,
                                                      void *walker_baton,
-                                                     svn_fs_t *fs, 
+                                                     svn_fs_t *fs,
                                                      apr_pool_t *scratch_pool),
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               apr_pool_t *pool);
 
 /* Return the representation REP in FS which has fulltext CHECKSUM.

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/structure?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/structure Wed Mar 14 13:07:02 2012
@@ -266,7 +266,7 @@ Within a revision:
   "r<rev>/<offset>" txn-id fields.
 
   In Format 3 and above, this uniqueness is done by changing a temporary
-  id of "_<base36>" to "<rev>-<base36>".  Note that this means that the
+  id of "_<base36>" to "<base36>-<rev>".  Note that this means that the
   originating revision of a line of history or a copy can be determined
   by looking at the node ID.
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.c Wed Mar 14 13:07:02 2012
@@ -136,7 +136,7 @@ serialize_svn_string(svn_temp_serializer
    * Thus, we cannot use svn_temp_serializer__add_string. */
   svn_temp_serializer__push(context,
                             (const void * const *)&string->data,
-                            string->len);
+                            string->len + 1);
 
   /* back to the caller's nesting level */
   svn_temp_serializer__pop(context);
@@ -579,6 +579,142 @@ svn_fs_fs__deserialize_manifest(void **o
   return SVN_NO_ERROR;
 }
 
+/* Auxilliary structure representing the content of a properties hash.
+   This structure is much easier to (de-)serialize than an apr_hash.
+ */
+typedef struct properties_data_t
+{
+  /* number of entries in the hash */
+  apr_size_t count;
+
+  /* reference to the keys */
+  const char **keys;
+
+  /* reference to the values */
+  const svn_string_t **values;
+} properties_data_t;
+
+/* Serialize COUNT C-style strings from *STRINGS into CONTEXT. */
+static void
+serialize_cstring_array(svn_temp_serializer__context_t *context,
+                        const char ***strings,
+                        apr_size_t count)
+{
+  apr_size_t i;
+  const char **entries = *strings;
+  
+  /* serialize COUNT entries pointers (the array) */
+  svn_temp_serializer__push(context,
+                            (const void * const *)strings,
+                            count * sizeof(const char*));
+
+  /* serialize array elements */
+  for (i = 0; i < count; ++i)
+    svn_temp_serializer__add_string(context, &entries[i]);
+
+  svn_temp_serializer__pop(context);
+}
+
+/* Serialize COUNT svn_string_t* items from *STRINGS into CONTEXT. */
+static void
+serialize_svn_string_array(svn_temp_serializer__context_t *context,
+                           const svn_string_t ***strings,
+                           apr_size_t count)
+{
+  apr_size_t i;
+  const svn_string_t **entries = *strings;
+  
+  /* serialize COUNT entries pointers (the array) */
+  svn_temp_serializer__push(context,
+                            (const void * const *)strings,
+                            count * sizeof(const char*));
+
+  /* serialize array elements */
+  for (i = 0; i < count; ++i)
+    serialize_svn_string(context, &entries[i]);
+
+  svn_temp_serializer__pop(context);
+}
+
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+                                apr_size_t *data_len,
+                                void *in,
+                                apr_pool_t *pool)
+{
+  apr_hash_t *hash = in;
+  properties_data_t properties;
+  svn_temp_serializer__context_t *context;
+  apr_hash_index_t *hi;
+  svn_stringbuf_t *serialized;
+  apr_size_t i;
+
+  /* create our auxilliary data structure */
+  properties.count = apr_hash_count(hash);
+  properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
+  properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
+  
+  /* populate it with the hash entries */
+  for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
+    {
+      properties.keys[i] = svn__apr_hash_index_key(hi);
+      properties.values[i] = svn__apr_hash_index_val(hi);
+    }
+  
+  /* serialize it */
+  context = svn_temp_serializer__init(&properties,
+                                      sizeof(properties),
+                                      properties.count * 100,
+                                      pool);
+
+  properties.keys[i] = "";
+  serialize_cstring_array(context, &properties.keys, properties.count + 1);
+  serialize_svn_string_array(context, &properties.values, properties.count);
+
+  /* return the serialized result */
+  serialized = svn_temp_serializer__get(context);
+
+  *data = serialized->data;
+  *data_len = serialized->len;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+                                  char *data,
+                                  apr_size_t data_len,
+                                  apr_pool_t *pool)
+{
+  apr_hash_t *hash = apr_hash_make(pool);
+  properties_data_t *properties = (properties_data_t *)data;
+  size_t i;
+
+  /* de-serialize our auxilliary data structure */
+  svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
+  svn_temp_deserializer__resolve(properties, (void**)&properties->values);
+  
+  /* de-serialize each entry and put it into the hash */
+  for (i = 0; i < properties->count; ++i)
+    {
+      apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
+      svn_temp_deserializer__resolve(properties->keys, 
+                                     (void**)&properties->keys[i]);
+      
+      deserialize_svn_string(properties->values, 
+                             (svn_string_t **)&properties->values[i]);
+      
+      apr_hash_set(hash, 
+                   properties->keys[i], len, 
+                   properties->values[i]);
+    }
+
+  /* done */
+  *out = hash;
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__serialize_id(char **data,
                         apr_size_t *data_len,

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/temp_serializer.h Wed Mar 14 13:07:02 2012
@@ -113,6 +113,26 @@ svn_fs_fs__deserialize_manifest(void **o
                                 apr_pool_t *pool);
 
 /**
+ * Implements #svn_cache__serialize_func_t for a properties hash
+ * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+                                apr_size_t *data_len,
+                                void *in,
+                                apr_pool_t *pool);
+
+/**
+ * Implements #svn_cache__deserialize_func_t for a properties hash
+ * (@a *out is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+                                  char *data,
+                                  apr_size_t data_len,
+                                  apr_pool_t *pool);
+
+/**
  * Implements #svn_cache__serialize_func_t for #svn_fs_id_t
  */
 svn_error_t *

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/tree.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_fs_fs/tree.c Wed Mar 14 13:07:02 2012
@@ -115,7 +115,7 @@ typedef struct fs_rev_root_data_t
 typedef struct fs_txn_root_data_t
 {
   /* Cache of txn DAG nodes (without their nested noderevs, because
-   * it's mutable). */
+   * it's mutable). Same keys/values as ffd->rev_node_cache. */
   svn_cache__t *txn_node_cache;
 } fs_txn_root_data_t;
 
@@ -2807,8 +2807,10 @@ find_youngest_copyroot(svn_revnum_t *rev
                        parent_path_t *parent_path,
                        apr_pool_t *pool)
 {
-  svn_revnum_t rev_mine, rev_parent = -1;
-  const char *path_mine, *path_parent;
+  svn_revnum_t rev_mine;
+  svn_revnum_t rev_parent = SVN_INVALID_REVNUM;
+  const char *path_mine;
+  const char *path_parent = NULL;
 
   /* First find our parent's youngest copyroot. */
   if (parent_path->parent)

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.c Wed Mar 14 13:07:02 2012
@@ -1304,6 +1304,15 @@ svn_ra_print_ra_libraries(svn_stringbuf_
 }
 
 
+svn_error_t *
+svn_ra__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                       svn_delta_shim_callbacks_t *callbacks)
+{
+  SVN_ERR(session->vtable->register_editor_shim_callbacks(session, callbacks));
+  return SVN_NO_ERROR;
+}
+
+
 /* Return the library version number. */
 const svn_version_t *
 svn_ra_version(void)

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra/ra_loader.h Wed Mar 14 13:07:02 2012
@@ -293,6 +293,8 @@ typedef struct svn_ra__vtable_t {
                                   svn_revnum_t end_revision,
                                   svn_revnum_t *revision_deleted,
                                   apr_pool_t *pool);
+  svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
 
 } svn_ra__vtable_t;
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_local/ra_plugin.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_local/ra_plugin.c Wed Mar 14 13:07:02 2012
@@ -153,7 +153,7 @@ cache_init(void *baton, apr_pool_t *pool
       SVN_ERR(svn_error_quick_wrap(svn_cstring_atoui64(&memory_cache_size,
                                                        memory_cache_size_str),
                                    _("memory-cache-size invalid")));
-      settings.cache_size = 1024 * 1024 * memory_cache_size; 
+      settings.cache_size = 1024 * 1024 * memory_cache_size;
       svn_cache_config_set(&settings);
     }
 
@@ -1505,6 +1505,15 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  /* This is currenly a no-op, since we don't provide our own editor, just
+     use the one the libsvn_repos hands back to us. */
+  return SVN_NO_ERROR;
+}
+
 /*----------------------------------------------------------------*/
 
 static const svn_version_t *
@@ -1551,7 +1560,8 @@ static const svn_ra__vtable_t ra_local_v
   svn_ra_local__replay,
   svn_ra_local__has_capability,
   svn_ra_local__replay_range,
-  svn_ra_local__get_deleted_rev
+  svn_ra_local__get_deleted_rev,
+  svn_ra_local__register_editor_shim_callbacks
 };
 
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/commit.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/commit.c Wed Mar 14 13:07:02 2012
@@ -1570,8 +1570,6 @@ svn_error_t * svn_ra_neon__get_commit_ed
   svn_delta_editor_t *commit_editor;
   commit_ctx_t *cc;
   apr_hash_index_t *hi;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                svn_delta_shim_callbacks_default(pool);
 
   /* Build the main commit editor's baton. */
   cc = apr_pcalloc(pool, sizeof(*cc));
@@ -1622,7 +1620,7 @@ svn_error_t * svn_ra_neon__get_commit_ed
   *edit_baton = cc;
 
   SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
-                                   shim_callbacks, pool, pool));
+                                   ras->shim_callbacks, pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/log.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/log.c Wed Mar 14 13:07:02 2012
@@ -166,7 +166,7 @@ log_start_element(int *elem, void *baton
       lb->want_cdata = lb->cdata;
       svn_stringbuf_setempty(lb->cdata);
       lb->cdata_encoding = NULL;
-          
+
       /* Some tags might contain encoded CDATA. */
       if ((elm->id == ELEM_comment) ||
           (elm->id == ELEM_creator_displayname) ||
@@ -280,7 +280,7 @@ maybe_decode_log_cdata(const svn_string_
   return SVN_NO_ERROR;
 }
 
-                       
+
 
 /*
  * This implements the `svn_ra_neon__xml_endelm_cb' prototype.

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/ra_neon.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/ra_neon.h Wed Mar 14 13:07:02 2012
@@ -131,6 +131,9 @@ typedef struct svn_ra_neon__session_t {
      deadprop-count property.*/
   svn_tristate_t supports_deadprop_count;
 
+  /* Ev2 shim callbacks. */
+  svn_delta_shim_callbacks_t *shim_callbacks;
+
   /*** HTTP v2 protocol stuff. ***
    *
    * We assume that if mod_dav_svn sends one of the special v2 OPTIONs
@@ -1181,6 +1184,10 @@ svn_ra_neon__get_deadprop_count_support(
                                         const char *final_url,
                                         apr_pool_t *pool);
 
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/session.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/session.c Wed Mar 14 13:07:02 2012
@@ -1229,7 +1229,8 @@ static const svn_ra__vtable_t neon_vtabl
   svn_ra_neon__replay,
   svn_ra_neon__has_capability,
   svn_ra_neon__replay_range,
-  svn_ra_neon__get_deleted_rev
+  svn_ra_neon__get_deleted_rev,
+  svn_ra_neon__register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/util.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_neon/util.c Wed Mar 14 13:07:02 2012
@@ -38,6 +38,7 @@
 #include "svn_utf.h"
 #include "svn_xml.h"
 #include "svn_props.h"
+#include "../libsvn_ra/ra_loader.h"
 
 #include "private/svn_fspath.h"
 #include "svn_private_config.h"
@@ -1649,3 +1650,13 @@ svn_ra_neon__get_deadprop_count_support(
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_neon__session_t *ras = session->priv;
+
+  ras->shim_callbacks = callbacks;
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/commit.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/commit.c Wed Mar 14 13:07:02 2012
@@ -328,7 +328,7 @@ checkout_dir(dir_context_t *dir)
       return SVN_NO_ERROR;
     }
 
-  /* Is this directory or one of our parent dirs newly added? 
+  /* Is this directory or one of our parent dirs newly added?
    * If so, we're already implicitly checked out. */
   while (p_dir)
     {
@@ -2319,8 +2319,6 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   svn_delta_editor_t *editor;
   commit_context_t *ctx;
   apr_hash_index_t *hi;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   ctx = apr_pcalloc(pool, sizeof(*ctx));
 
@@ -2368,7 +2366,8 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   *edit_baton = ctx;
 
   SVN_ERR(svn_editor__insert_shims(ret_editor, edit_baton, *ret_editor,
-                                   *edit_baton, shim_callbacks, pool, pool));
+                                   *edit_baton, session->shim_callbacks,
+                                   pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/locks.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/locks.c Wed Mar 14 13:07:02 2012
@@ -412,7 +412,7 @@ handle_lock(serf_request_t *request,
       if (err && APR_STATUS_IS_EOF(err->apr_err))
         {
           ctx->done = TRUE;
-          err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED,
+          err = svn_error_createf(SVN_ERR_RA_DAV_FORBIDDEN,
                                   err,
                                   _("Lock request failed: %d %s"),
                                   ctx->status_code, ctx->reason);
@@ -572,44 +572,43 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
                   svn_boolean_t force,
                   svn_ra_lock_callback_t lock_func,
                   void *lock_baton,
-                  apr_pool_t *pool)
+                  apr_pool_t *scratch_pool)
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   apr_hash_index_t *hi;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
 
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(scratch_pool);
 
   /* ### TODO for issue 2263: Send all the locks over the wire at once.  This
      loop is just a temporary shim. */
-  for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(scratch_pool, path_revs);
+       hi;
+       hi = apr_hash_next(hi))
     {
       svn_ra_serf__handler_t *handler;
       svn_ra_serf__xml_parser_t *parser_ctx;
       const char *req_url;
       lock_info_t *lock_ctx;
-      const void *key;
-      void *val;
       svn_error_t *err;
       svn_error_t *new_err = NULL;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
-      lock_ctx = apr_pcalloc(subpool, sizeof(*lock_ctx));
+      lock_ctx = apr_pcalloc(iterpool, sizeof(*lock_ctx));
 
-      apr_hash_this(hi, &key, NULL, &val);
-      lock_ctx->pool = subpool;
-      lock_ctx->path = key;
-      lock_ctx->revision = *((svn_revnum_t*)val);
-      lock_ctx->lock = svn_lock_create(subpool);
-      lock_ctx->lock->path = key;
+      lock_ctx->pool = iterpool;
+      lock_ctx->path = svn__apr_hash_index_key(hi);
+      lock_ctx->revision = *((svn_revnum_t*)svn__apr_hash_index_val(hi));
+      lock_ctx->lock = svn_lock_create(iterpool);
+      lock_ctx->lock->path = lock_ctx->path;
       lock_ctx->lock->comment = comment;
 
       lock_ctx->force = force;
       req_url = svn_path_url_add_component2(session->session_url.path,
-                                            lock_ctx->path, subpool);
+                                            lock_ctx->path, iterpool);
 
-      handler = apr_pcalloc(subpool, sizeof(*handler));
+      handler = apr_pcalloc(iterpool, sizeof(*handler));
 
       handler->method = "LOCK";
       handler->path = req_url;
@@ -617,9 +616,9 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
       handler->conn = session->conns[0];
       handler->session = session;
 
-      parser_ctx = apr_pcalloc(subpool, sizeof(*parser_ctx));
+      parser_ctx = apr_pcalloc(iterpool, sizeof(*parser_ctx));
 
-      parser_ctx->pool = subpool;
+      parser_ctx->pool = iterpool;
       parser_ctx->user_data = lock_ctx;
       parser_ctx->start = start_lock;
       parser_ctx->end = end_lock;
@@ -636,16 +635,18 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
       handler->response_baton = parser_ctx;
 
       svn_ra_serf__request_create(handler);
-      err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, subpool);
+      err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, iterpool);
 
       if (lock_func)
         new_err = lock_func(lock_baton, lock_ctx->path, TRUE, lock_ctx->lock,
-                            err, subpool);
+                            err, iterpool);
       svn_error_clear(err);
 
       SVN_ERR(new_err);
     }
 
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }
 
@@ -677,45 +678,44 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
                     svn_boolean_t force,
                     svn_ra_lock_callback_t lock_func,
                     void *lock_baton,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   apr_hash_index_t *hi;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
 
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(scratch_pool);
 
   /* ### TODO for issue 2263: Send all the locks over the wire at once.  This
      loop is just a temporary shim. */
-  for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(scratch_pool, path_tokens);
+       hi;
+       hi = apr_hash_next(hi))
     {
       svn_ra_serf__handler_t *handler;
       svn_ra_serf__simple_request_context_t *ctx;
       const char *req_url, *path, *token;
-      const void *key;
-      void *val;
       svn_lock_t *existing_lock = NULL;
       struct unlock_context_t unlock_ctx;
-      svn_error_t *lock_err = NULL;
+      svn_error_t *err = NULL;
+      svn_error_t *new_err = NULL;
+
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
-      ctx = apr_pcalloc(subpool, sizeof(*ctx));
-      ctx->pool = subpool;
+      ctx = apr_pcalloc(iterpool, sizeof(*ctx));
+      ctx->pool = iterpool;
 
-      apr_hash_this(hi, &key, NULL, &val);
-      path = key;
-      token = val;
+      path = svn__apr_hash_index_key(hi);
+      token = svn__apr_hash_index_val(hi);
 
       if (force && (!token || token[0] == '\0'))
         {
           SVN_ERR(svn_ra_serf__get_lock(ra_session, &existing_lock, path,
-                                        subpool));
+                                        iterpool));
           token = existing_lock->token;
           if (!token)
             {
-              svn_error_t *err;
-
               err = svn_error_createf(SVN_ERR_RA_NOT_LOCKED, NULL,
                                       _("'%s' is not locked in the repository"),
                                       path);
@@ -723,22 +723,29 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
               if (lock_func)
                 {
                   svn_error_t *err2;
-                  err2 = lock_func(lock_baton, path, FALSE, NULL, err, subpool);
+                  err2 = lock_func(lock_baton, path, FALSE, NULL, err,
+                                   iterpool);
                   svn_error_clear(err);
+                  err = NULL;
                   if (err2)
-                    return err2;
+                    return svn_error_trace(err2);
+                }
+              else
+                {
+                  svn_error_clear(err);
+                  err = NULL;
                 }
               continue;
             }
         }
 
       unlock_ctx.force = force;
-      unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", (char *)NULL);
+      unlock_ctx.token = apr_pstrcat(iterpool, "<", token, ">", (char *)NULL);
 
       req_url = svn_path_url_add_component2(session->session_url.path, path,
-                                            subpool);
+                                            iterpool);
 
-      handler = apr_pcalloc(subpool, sizeof(*handler));
+      handler = apr_pcalloc(iterpool, sizeof(*handler));
 
       handler->method = "UNLOCK";
       handler->path = req_url;
@@ -752,7 +759,7 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
       handler->response_baton = ctx;
 
       svn_ra_serf__request_create(handler);
-      SVN_ERR(svn_ra_serf__context_run_wait(&ctx->done, session, subpool));
+      SVN_ERR(svn_ra_serf__context_run_wait(&ctx->done, session, iterpool));
 
       switch (ctx->status)
         {
@@ -760,23 +767,25 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
             break; /* OK */
           case 403:
             /* Api users expect this specific error code to detect failures */
-            lock_err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH, NULL,
-                                         _("Unlock request failed: %d %s"),
-                                         ctx->status, ctx->reason);
+            err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH, NULL,
+                                    _("Unlock request failed: %d %s"),
+                                    ctx->status, ctx->reason);
             break;
           default:
-            lock_err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
-                                   _("Unlock request failed: %d %s"),
-                                   ctx->status, ctx->reason);
+            err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+                                    _("Unlock request failed: %d %s"),
+                                    ctx->status, ctx->reason);
         }
 
       if (lock_func)
-        {
-          SVN_ERR(lock_func(lock_baton, path, FALSE, existing_lock,
-                            lock_err, subpool));
-          svn_error_clear(lock_err);
-        }
+        new_err = lock_func(lock_baton, path, FALSE, existing_lock, err,
+                            iterpool);
+
+      svn_error_clear(err);
+      SVN_ERR(new_err);
     }
 
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/ra_serf.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/ra_serf.h Wed Mar 14 13:07:02 2012
@@ -148,6 +148,9 @@ struct svn_ra_serf__session_t {
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
 
+  /* Ev2 shim callbacks */
+  svn_delta_shim_callbacks_t *shim_callbacks;
+
   /* Error that we've received but not yet returned upstream. */
   svn_error_t *pending_error;
 
@@ -1454,6 +1457,11 @@ svn_ra_serf__error_on_status(int status_
                              const char *path,
                              const char *location);
 
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/serf.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/serf.c Wed Mar 14 13:07:02 2012
@@ -1157,7 +1157,8 @@ static const svn_ra__vtable_t serf_vtabl
   svn_ra_serf__replay,
   svn_ra_serf__has_capability,
   svn_ra_serf__replay_range,
-  svn_ra_serf__get_deleted_rev
+  svn_ra_serf__get_deleted_rev,
+  svn_ra_serf__register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/util.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_serf/util.c Wed Mar 14 13:07:02 2012
@@ -38,6 +38,7 @@
 #include "svn_private_config.h"
 #include "svn_string.h"
 #include "svn_xml.h"
+#include "../libsvn_ra/ra_loader.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
 
@@ -2466,3 +2467,13 @@ svn_ra_serf__error_on_status(int status_
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *ra_session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_serf__session_t *session = ra_session->priv;
+
+  session->shim_callbacks = callbacks;
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/client.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/client.c Wed Mar 14 13:07:02 2012
@@ -2496,6 +2496,18 @@ ra_svn_get_deleted_rev(svn_ra_session_t 
   return svn_ra_svn_read_cmd_response(conn, pool, "r", revision_deleted);
 }
 
+static svn_error_t *
+ra_svn_register_editor_shim_callbacks(svn_ra_session_t *session,
+                                      svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_svn__session_baton_t *sess_baton = session->priv;
+  svn_ra_svn_conn_t *conn = sess_baton->conn;
+
+  conn->shim_callbacks = callbacks;
+
+  return SVN_NO_ERROR;
+}
+
 
 static const svn_ra__vtable_t ra_svn_vtable = {
   svn_ra_svn_version,
@@ -2532,7 +2544,8 @@ static const svn_ra__vtable_t ra_svn_vta
   ra_svn_replay,
   ra_svn_has_capability,
   ra_svn_replay_range,
-  ra_svn_get_deleted_rev
+  ra_svn_get_deleted_rev,
+  ra_svn_register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/cyrus_auth.c Wed Mar 14 13:07:02 2012
@@ -125,7 +125,7 @@ static int check_result(svn_error_t *err
       svn_error_clear(err);
       return -1;
     }
-    
+
   return 0;
 }
 
@@ -180,9 +180,9 @@ svn_ra_svn__sasl_common_init(apr_pool_t 
                  sasl_mutex_free_cb);
   free_mutexes = apr_array_make(sasl_pool, 0, sizeof(svn_mutex__t *));
   return svn_mutex__init(&array_mutex, TRUE, sasl_pool);
-    
+
 #endif /* APR_HAS_THREADS */
-  
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/editorp.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/editorp.c Wed Mar 14 13:07:02 2012
@@ -408,8 +408,6 @@ void svn_ra_svn_get_editor(const svn_del
 {
   svn_delta_editor_t *ra_svn_editor = svn_delta_default_editor(pool);
   ra_svn_edit_baton_t *eb;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   eb = apr_palloc(pool, sizeof(*eb));
   eb->conn = conn;
@@ -439,7 +437,7 @@ void svn_ra_svn_get_editor(const svn_del
   *edit_baton = eb;
 
   svn_error_clear(svn_editor__insert_shims(editor, edit_baton, *editor,
-                                           *edit_baton, shim_callbacks,
+                                           *edit_baton, conn->shim_callbacks,
                                            pool, pool));
 }
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/marshal.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/marshal.c Wed Mar 14 13:07:02 2012
@@ -125,6 +125,14 @@ svn_error_t *svn_ra_svn_set_capabilities
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra_svn__set_shim_callbacks(svn_ra_svn_conn_t *conn,
+                               svn_delta_shim_callbacks_t *shim_callbacks)
+{
+  conn->shim_callbacks = shim_callbacks;
+  return SVN_NO_ERROR;
+}
+
 svn_boolean_t svn_ra_svn_has_capability(svn_ra_svn_conn_t *conn,
                                         const char *capability)
 {

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/ra_svn.h?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_ra_svn/ra_svn.h Wed Mar 14 13:07:02 2012
@@ -87,6 +87,7 @@ struct svn_ra_svn_conn_st {
   apr_hash_t *capabilities;
   int compression_level;
   char *remote_ip;
+  svn_delta_shim_callbacks_t *shim_callbacks;
   apr_pool_t *pool;
 };
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/commit.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/commit.c Wed Mar 14 13:07:02 2012
@@ -783,31 +783,45 @@ abort_edit(void *edit_baton,
 
 
 static svn_error_t *
-prop_fetch_func(apr_hash_t **props,
-                void *baton,
-                const char *path,
-                svn_revnum_t base_revision,
-                apr_pool_t *result_pool,
-                apr_pool_t *scratch_pool)
+rationalize_shim_path(const char **fs_path,
+                      struct edit_baton *eb,
+                      const char *path,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
-  struct edit_baton *eb = baton;
-  svn_fs_root_t *fs_root;
-  svn_error_t *err;
-
   if (svn_path_is_url(path))
     {
       /* This is a copyfrom URL. */
       path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
-      path = svn_fspath__canonicalize(path, scratch_pool);
+      *fs_path = svn_fspath__canonicalize(path, scratch_pool);
     }
   else
     {
       /* This is a base-relative path. */
       if (path[0] != '/')
         /* Get an absolute path for use in the FS. */
-        path = svn_fspath__join(eb->base_path, path, scratch_pool);
+        *fs_path = svn_fspath__join(eb->base_path, path, scratch_pool);
+      else
+        *fs_path = path;
     }
 
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  svn_fs_root_t *fs_root;
+  svn_error_t *err;
+
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs,
                                svn_fs_txn_base_revision(eb->txn),
                                scratch_pool));
@@ -825,7 +839,7 @@ prop_fetch_func(apr_hash_t **props,
 }
 
 static svn_error_t *
-kind_fetch_func(svn_kind_t *kind,
+fetch_kind_func(svn_kind_t *kind,
                 void *baton,
                 const char *path,
                 svn_revnum_t base_revision,
@@ -838,27 +852,14 @@ kind_fetch_func(svn_kind_t *kind,
   if (!SVN_IS_VALID_REVNUM(base_revision))
     base_revision = svn_fs_txn_base_revision(eb->txn);
 
-  if (svn_path_is_url(path))
-    {
-      /* This is a copyfrom URL. */
-      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
-      path = svn_fspath__canonicalize(path, scratch_pool);
-    }
-  else
-    {
-      /* This is a base-relative path. */
-      if (path[0] != '/')
-        /* Get an absolute path for use in the FS. */
-        path = svn_fspath__join(eb->base_path, path, scratch_pool);
-    }
-
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
 
   return SVN_NO_ERROR;
-} 
+}
 
 static svn_error_t *
 fetch_base_func(const char **filename,
@@ -878,20 +879,7 @@ fetch_base_func(const char **filename,
   if (!SVN_IS_VALID_REVNUM(base_revision))
     base_revision = svn_fs_txn_base_revision(eb->txn);
 
-  if (svn_path_is_url(path))
-    {
-      /* This is a copyfrom URL. */
-      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
-      path = svn_fspath__canonicalize(path, scratch_pool);
-    }
-  else
-    {
-      /* This is a base-relative path. */
-      if (path[0] != '/')
-        /* Get an absolute path for use in the FS. */
-        path = svn_fspath__join(eb->base_path, path, scratch_pool);
-    }
-
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
@@ -987,8 +975,8 @@ svn_repos_get_commit_editor5(const svn_d
   *edit_baton = eb;
   *editor = e;
 
-  shim_callbacks->fetch_props_func = prop_fetch_func;
-  shim_callbacks->fetch_kind_func = kind_fetch_func;
+  shim_callbacks->fetch_props_func = fetch_props_func;
+  shim_callbacks->fetch_kind_func = fetch_kind_func;
   shim_callbacks->fetch_base_func = fetch_base_func;
   shim_callbacks->fetch_baton = eb;
 

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/dump.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/dump.c Wed Mar 14 13:07:02 2012
@@ -864,8 +864,14 @@ fetch_props_func(apr_hash_t **props,
 {
   struct edit_baton *eb = baton;
   svn_error_t *err;
+  svn_fs_root_t *fs_root;
+
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->current_rev - 1;
 
-  err = svn_fs_node_proplist(props, eb->fs_root, path, result_pool);
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
+
+  err = svn_fs_node_proplist(props, fs_root, path, result_pool);
   if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
     {
       svn_error_clear(err);
@@ -890,10 +896,9 @@ fetch_kind_func(svn_kind_t *kind,
   svn_fs_root_t *fs_root;
 
   if (!SVN_IS_VALID_REVNUM(base_revision))
-    fs_root = eb->fs_root;
-  else
-    SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision,
-                                 scratch_pool));
+    base_revision = eb->current_rev - 1;
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
@@ -917,10 +922,9 @@ fetch_base_func(const char **filename,
   svn_fs_root_t *fs_root;
 
   if (!SVN_IS_VALID_REVNUM(base_revision))
-    fs_root = eb->fs_root;
-  else
-    SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision,
-                                 scratch_pool));
+    base_revision = eb->current_rev - 1;
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
   if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
@@ -1391,10 +1395,9 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                "(youngest revision is %ld)"),
                              end_rev, youngest);
 
-  /* Verify global/auxiliary data before verifying revisions. */
-  if (start_rev == 0)
-    SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
-                          pool));
+  /* Verify global/auxiliary data and backend-specific data first. */
+  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+                        start_rev, end_rev, pool));
 
   /* Create a notify object that we can reuse within the loop. */
   if (notify_func)
@@ -1415,7 +1418,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
       /* Get cancellable dump editor, but with our close_directory handler. */
       SVN_ERR(get_dump_editor((const svn_delta_editor_t **)&dump_editor,
                               &dump_edit_baton, fs, rev, "",
-                              svn_stream_empty(pool),
+                              svn_stream_empty(iterpool),
                               NULL, NULL,
                               verify_close_directory,
                               notify_func, notify_baton,
@@ -1432,6 +1435,10 @@ svn_repos_verify_fs2(svn_repos_t *repos,
       SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
                                 cancel_editor, cancel_edit_baton,
                                 NULL, NULL, iterpool));
+      /* While our editor close_edit implementation is a no-op, we still
+         do this for completeness. */
+      SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, iterpool));
+
       SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
 
       if (notify_func)

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/hooks.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/hooks.c Wed Mar 14 13:07:02 2012
@@ -171,8 +171,8 @@ env_from_env_hash(apr_hash_t *env_hash,
   apr_hash_index_t *hi;
   const char **env;
   const char **envp;
-  
-  if (!env_hash)
+
+  if (!env_hash || apr_hash_count(env_hash) == 0)
     return NULL;
 
   env = apr_palloc(result_pool,

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/load-fs-vtable.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/load-fs-vtable.c Wed Mar 14 13:07:02 2012
@@ -487,7 +487,7 @@ new_revision_record(void **revision_bato
      several separate operations. It is highly susceptible to race conditions.
      Calculate the revision 'offset' for finding copyfrom sources.
      It might be positive or negative. */
-  rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
+  rb->rev_offset = (apr_int32_t) ((rb->rev) - (head_rev + 1));
 
   if ((rb->rev > 0) && (! rb->skipped))
     {
@@ -506,7 +506,7 @@ new_revision_record(void **revision_bato
       if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
         pb->oldest_old_rev = rb->rev;
     }
-  
+
   /* If we're skipping this revision, try to notify someone. */
   if (rb->skipped && pb->notify_func)
     {

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/log.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/log.c Wed Mar 14 13:07:02 2012
@@ -268,7 +268,38 @@ detect_changed(apr_hash_t **changed,
       /* Pre-1.6 revision files don't store the change path kind, so fetch
          it manually. */
       if (item->node_kind == svn_node_unknown)
-        SVN_ERR(svn_fs_check_path(&item->node_kind, root, path, subpool));
+        {
+          svn_fs_root_t *check_root = root;
+          const char *check_path = path;
+
+          /* Deleted items don't exist so check earlier revision.  We
+             know the parent must exist and could be a copy */
+          if (change->change_kind == svn_fs_path_change_delete)
+            {
+              svn_fs_history_t *history;
+              svn_revnum_t prev_rev;
+              const char *parent_path, *name;
+
+              svn_fspath__split(&parent_path, &name, path, subpool);
+
+              SVN_ERR(svn_fs_node_history(&history, root, parent_path,
+                                          subpool));
+
+              /* Two calls because the first call returns the original
+                 revision as the deleted child means it is 'interesting' */
+              SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool));
+              SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool));
+
+              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);
+            }
+
+          SVN_ERR(svn_fs_check_path(&item->node_kind, check_root, check_path,
+                                    subpool));
+        }
+
 
       if ((action == 'A') || (action == 'R'))
         {
@@ -1121,7 +1152,6 @@ send_log(svn_revnum_t rev,
       && log_target_history_as_mergeinfo
       && apr_hash_count(log_target_history_as_mergeinfo))
     {
-      svn_boolean_t path_is_in_history = FALSE;
       apr_hash_index_t *hi;
       apr_pool_t *subpool = svn_pool_create(pool);
 
@@ -1134,10 +1164,12 @@ send_log(svn_revnum_t rev,
            hi;
            hi = apr_hash_next(hi))
         {
+          svn_boolean_t path_is_in_history = FALSE;
           const char *changed_path = svn__apr_hash_index_key(hi);
           apr_hash_index_t *hi2;
           apr_pool_t *inner_subpool = svn_pool_create(subpool);
 
+          /* Look at each path on the log target's mergeinfo. */
           for (hi2 = apr_hash_first(inner_subpool,
                                     log_target_history_as_mergeinfo);
                hi2;
@@ -1148,6 +1180,8 @@ send_log(svn_revnum_t rev,
               apr_array_header_t *rangelist =
                 svn__apr_hash_index_val(hi2);
 
+              /* Check whether CHANGED_PATH at revision REV is a child of
+                 a (path, revision) tuple in LOG_TARGET_HISTORY_AS_MERGEINFO. */
               if (svn_fspath__skip_ancestor(mergeinfo_path, changed_path))
                 {
                   int i;
@@ -1777,7 +1811,7 @@ store_search(svn_mergeinfo_t processed,
                                                   sizeof(svn_merge_range_t*));
       svn_merge_range_t *range = apr_palloc(processed_pool,
                                             sizeof(svn_merge_range_t));
-      
+
       range->start = start;
       range->end = end;
       range->inheritable = TRUE;
@@ -2234,17 +2268,40 @@ svn_repos_get_logs4(svn_repos_t *repos,
       int i;
       apr_pool_t *iterpool = svn_pool_create(pool);
 
+      /* If we are provided an authz callback function, use it to
+         verify that the user has read access to the root path in the
+         first of our revisions.
+
+         ### FIXME:  Strictly speaking, we should be checking this
+         ### access in every revision along the line.  But currently,
+         ### there are no known authz implementations which concern
+         ### themselves with per-revision access.  */
+      if (authz_read_func)
+        {
+          svn_boolean_t readable;
+          svn_fs_root_t *rev_root;
+
+          SVN_ERR(svn_fs_revision_root(&rev_root, fs,
+                                       descending_order ? end : start, pool));
+          SVN_ERR(authz_read_func(&readable, rev_root, "",
+                                  authz_read_baton, pool));
+          if (! readable)
+            return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE, NULL, NULL);
+        }
+
       send_count = end - start + 1;
       if (limit && send_count > limit)
         send_count = limit;
       for (i = 0; i < send_count; ++i)
         {
-          svn_revnum_t rev = start + i;
+          svn_revnum_t rev;
 
           svn_pool_clear(iterpool);
 
           if (descending_order)
             rev = end - i;
+          else
+            rev = start + i;
           SVN_ERR(send_log(rev, fs, NULL, NULL, discover_changed_paths, FALSE,
                            FALSE, revprops, FALSE, receiver,
                            receiver_baton, authz_read_func,

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_repos/replay.c?rev=1300532&r1=1300531&r2=1300532&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_repos/replay.c Wed Mar 14 13:07:02 2012
@@ -352,6 +352,116 @@ is_within_base_path(const char *path, co
   return FALSE;
 }
 
+/* Given PATH deleted under ROOT, return in READABLE whether the path was
+   readable prior to the deletion.  Consult COPIES (a stack of 'struct
+   copy_info') and AUTHZ_READ_FUNC. */
+static svn_error_t *
+was_readable(svn_boolean_t *readable,
+             svn_fs_root_t *root,
+             const char *path,
+             apr_array_header_t *copies,
+             svn_repos_authz_func_t authz_read_func,
+             void *authz_read_baton,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  svn_fs_root_t *inquire_root;
+  const char *inquire_path;
+  struct copy_info *info = NULL;
+  const char *relpath;
+
+  /* Short circuit. */
+  if (! authz_read_func)
+    {
+      *readable = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  if (copies->nelts != 0)
+    info = APR_ARRAY_IDX(copies, copies->nelts - 1, struct copy_info *);
+
+  /* Are we under a copy? */
+  if (info && (relpath = svn_relpath_skip_ancestor(info->path, path)))
+    {
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   info->copyfrom_rev, scratch_pool));
+      inquire_path = svn_fspath__join(info->copyfrom_path, relpath,
+                                      scratch_pool);
+    }
+  else
+    {
+      /* Compute the revision that ROOT is based on.  (Note that ROOT is not
+         r0's root, since this function is only called for deletions.)
+         ### Need a more succinct way to express this */
+      svn_revnum_t inquire_rev = SVN_INVALID_REVNUM;
+      if (svn_fs_is_txn_root(root))
+        inquire_rev = svn_fs_txn_root_base_revision(root);
+      if (svn_fs_is_revision_root(root))
+        inquire_rev =  svn_fs_revision_root_revision(root)-1;
+      SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(inquire_rev));
+
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   inquire_rev, scratch_pool));
+      inquire_path = path;
+    }
+
+  SVN_ERR(authz_read_func(readable, inquire_root, inquire_path,
+                          authz_read_baton, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Initialize COPYFROM_ROOT, COPYFROM_PATH, and COPYFROM_REV with the
+   revision root, fspath, and revnum of the copyfrom of CHANGE, which
+   corresponds to PATH under ROOT.  If the copyfrom info is valid
+   (i.e., is not (NULL, SVN_INVALID_REVNUM)), then initialize SRC_READABLE
+   too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided. */
+static svn_error_t *
+fill_copyfrom(svn_fs_root_t **copyfrom_root,
+              const char **copyfrom_path,
+              svn_revnum_t *copyfrom_rev,
+              svn_boolean_t *src_readable,
+              svn_fs_root_t *root,
+              svn_fs_path_change2_t *change,
+              svn_repos_authz_func_t authz_read_func,
+              void *authz_read_baton,
+              const char *path,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
+{
+  if (! change->copyfrom_known)
+    {
+      SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
+                                 &(change->copyfrom_path),
+                                 root, path, result_pool));
+      change->copyfrom_known = TRUE;
+    }
+  *copyfrom_rev = change->copyfrom_rev;
+  *copyfrom_path = change->copyfrom_path;
+
+  if (*copyfrom_path && SVN_IS_VALID_REVNUM(*copyfrom_rev))
+    {
+      SVN_ERR(svn_fs_revision_root(copyfrom_root,
+                                   svn_fs_root_fs(root),
+                                   *copyfrom_rev, result_pool));
+
+      if (authz_read_func)
+        {
+          SVN_ERR(authz_read_func(src_readable, *copyfrom_root,
+                                  *copyfrom_path,
+                                  authz_read_baton, result_pool));
+        }
+      else
+        *src_readable = TRUE;
+    }
+  else
+    {
+      *copyfrom_root = NULL;
+      /* SRC_READABLE left uninitialized */
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 path_driver_cb_func(void **dir_baton,
                     void *parent_baton,
@@ -368,7 +478,6 @@ path_driver_cb_func(void **dir_baton,
   void *file_baton = NULL;
   svn_revnum_t copyfrom_rev;
   const char *copyfrom_path;
-  svn_boolean_t src_readable = TRUE;
   svn_fs_root_t *source_root = cb->compare_root;
   const char *source_fspath = NULL;
   const char *base_path = cb->base_path;
@@ -384,9 +493,9 @@ path_driver_cb_func(void **dir_baton,
   while (cb->copies->nelts > 0
          && ! svn_dirent_is_ancestor(APR_ARRAY_IDX(cb->copies,
                                                    cb->copies->nelts - 1,
-                                                   struct copy_info).path,
+                                                   struct copy_info *)->path,
                                      edit_path))
-    cb->copies->nelts--;
+    apr_array_pop(cb->copies);
 
   change = apr_hash_get(cb->changed_paths, edit_path, APR_HASH_KEY_STRING);
   if (! change)
@@ -419,8 +528,18 @@ path_driver_cb_func(void **dir_baton,
 
   /* Handle any deletions. */
   if (do_delete)
-    SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
-                                 parent_baton, pool));
+    {
+      svn_boolean_t readable;
+
+      /* Issue #4121: delete under under a copy, of a path that was unreadable
+         at its pre-copy location. */
+      SVN_ERR(was_readable(&readable, root, edit_path, cb->copies,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            pool, pool));
+      if (readable)
+        SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
+                                     parent_baton, pool));
+    }
 
   /* Fetch the node kind if it makes sense to do so. */
   if (! do_delete || do_add)
@@ -437,31 +556,14 @@ path_driver_cb_func(void **dir_baton,
   /* Handle any adds/opens. */
   if (do_add)
     {
-      svn_fs_root_t *copyfrom_root = NULL;
-      /* Was this node copied? */
-      if (! change->copyfrom_known)
-        {
-          SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
-                                     &(change->copyfrom_path),
-                                     root, edit_path, pool));
-          change->copyfrom_known = TRUE;
-        }
-      copyfrom_rev = change->copyfrom_rev;
-      copyfrom_path = change->copyfrom_path;
+      svn_boolean_t src_readable;
+      svn_fs_root_t *copyfrom_root;
 
-      if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev))
-        {
-          SVN_ERR(svn_fs_revision_root(&copyfrom_root,
-                                       svn_fs_root_fs(root),
-                                       copyfrom_rev, pool));
-
-          if (cb->authz_read_func)
-            {
-              SVN_ERR(cb->authz_read_func(&src_readable, copyfrom_root,
-                                          copyfrom_path,
-                                          cb->authz_read_baton, pool));
-            }
-        }
+      /* Was this node copied? */
+      SVN_ERR(fill_copyfrom(&copyfrom_root, &copyfrom_path, &copyfrom_rev,
+                            &src_readable, root, change,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            edit_path, pool, pool));
 
       /* If we have a copyfrom path, and we can't read it or we're just
          ignoring it, or the copyfrom rev is prior to the low water mark
@@ -511,11 +613,13 @@ path_driver_cb_func(void **dir_baton,
              (possibly nested) copy operation. */
           if (change->node_kind == svn_node_dir)
             {
-              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
-                                                       struct copy_info);
+              struct copy_info *info = apr_pcalloc(cb->pool, sizeof(*info));
+
               info->path = apr_pstrdup(cb->pool, edit_path);
               info->copyfrom_path = apr_pstrdup(cb->pool, copyfrom_path);
               info->copyfrom_rev = copyfrom_rev;
+
+              APR_ARRAY_PUSH(cb->copies, struct copy_info *) = info;
             }
 
           /* Save the source so that we can use it later, when we
@@ -531,11 +635,13 @@ path_driver_cb_func(void **dir_baton,
              past... */
           if (change->node_kind == svn_node_dir && cb->copies->nelts > 0)
             {
-              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
-                                                       struct copy_info);
+              struct copy_info *info = apr_pcalloc(cb->pool, sizeof(*info));
+
               info->path = apr_pstrdup(cb->pool, edit_path);
               info->copyfrom_path = NULL;
               info->copyfrom_rev = SVN_INVALID_REVNUM;
+
+              APR_ARRAY_PUSH(cb->copies, struct copy_info *) = info;
             }
           source_root = NULL;
           source_fspath = NULL;
@@ -568,9 +674,9 @@ path_driver_cb_func(void **dir_baton,
          delta source. */
       if (cb->copies->nelts > 0)
         {
-          struct copy_info *info = &APR_ARRAY_IDX(cb->copies,
-                                                  cb->copies->nelts - 1,
-                                                  struct copy_info);
+          struct copy_info *info = APR_ARRAY_IDX(cb->copies,
+                                                 cb->copies->nelts - 1,
+                                                 struct copy_info *);
           if (info->copyfrom_path)
             {
               const char *relpath = svn_relpath_skip_ancestor(info->path,
@@ -597,45 +703,31 @@ path_driver_cb_func(void **dir_baton,
     {
       if (change->prop_mod)
         {
-          if (cb->compare_root)
-            {
-              apr_array_header_t *prop_diffs;
-              apr_hash_t *old_props;
-              apr_hash_t *new_props;
-              int i;
-
-              if (source_root)
-                SVN_ERR(svn_fs_node_proplist(&old_props, source_root,
-                                             source_fspath, pool));
-              else
-                old_props = apr_hash_make(pool);
-
-              SVN_ERR(svn_fs_node_proplist(&new_props, root, edit_path, pool));
-
-              SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, old_props,
-                                     pool));
-
-              for (i = 0; i < prop_diffs->nelts; ++i)
-                {
-                  svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
-                   if (change->node_kind == svn_node_dir)
-                     SVN_ERR(editor->change_dir_prop(*dir_baton, pc->name,
-                                                     pc->value, pool));
-                   else if (change->node_kind == svn_node_file)
-                     SVN_ERR(editor->change_file_prop(file_baton, pc->name,
-                                                      pc->value, pool));
-                }
-            }
+          apr_array_header_t *prop_diffs;
+          apr_hash_t *old_props;
+          apr_hash_t *new_props;
+          int i;
+
+          if (source_root)
+            SVN_ERR(svn_fs_node_proplist(&old_props, source_root,
+                                         source_fspath, pool));
           else
+            old_props = apr_hash_make(pool);
+
+          SVN_ERR(svn_fs_node_proplist(&new_props, root, edit_path, pool));
+
+          SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, old_props,
+                                 pool));
+
+          for (i = 0; i < prop_diffs->nelts; ++i)
             {
-              /* Just do a dummy prop change to signal that there are *any*
-                 propmods. */
-              if (change->node_kind == svn_node_dir)
-                SVN_ERR(editor->change_dir_prop(*dir_baton, "", NULL,
-                                                pool));
-              else if (change->node_kind == svn_node_file)
-                SVN_ERR(editor->change_file_prop(file_baton, "", NULL,
-                                                 pool));
+              svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
+               if (change->node_kind == svn_node_dir)
+                 SVN_ERR(editor->change_dir_prop(*dir_baton, pc->name,
+                                                 pc->value, pool));
+               else if (change->node_kind == svn_node_file)
+                 SVN_ERR(editor->change_file_prop(file_baton, pc->name,
+                                                  pc->value, pool));
             }
         }
 
@@ -806,7 +898,7 @@ svn_repos_replay2(svn_fs_root_t *root,
                                    pool));
     }
 
-  cb_baton.copies = apr_array_make(pool, 4, sizeof(struct copy_info));
+  cb_baton.copies = apr_array_make(pool, 4, sizeof(struct copy_info *));
   cb_baton.pool = pool;
 
   /* Determine the revision to use throughout the edit, and call