You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/02/23 02:25:44 UTC

svn commit: r1449262 [7/25] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/ notes...

Modified: subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c Sat Feb 23 01:25:38 2013
@@ -27,6 +27,8 @@
 #include <apr_want.h>
 #include <apr_tables.h>
 
+#include <assert.h>
+
 #include "svn_diff.h"
 #include "svn_pools.h"
 #include "svn_types.h"
@@ -342,7 +344,8 @@ typedef enum unified_output_e
 {
   unified_output_context = 0,
   unified_output_delete,
-  unified_output_insert
+  unified_output_insert,
+  unified_output_skip
 } unified_output_e;
 
 /* Baton for generating unified diffs */
@@ -351,7 +354,7 @@ typedef struct unified_output_baton_t
   svn_stream_t *output_stream;
   const char *header_encoding;
   source_tokens_t sources[2]; /* 0 == original; 1 == modified */
-  apr_off_t next_token; /* next token in original source */
+  apr_off_t current_token[2]; /* current token per source */
 
   /* Cached markers, in header_encoding,
      indexed using unified_output_e */
@@ -382,31 +385,28 @@ static svn_error_t *
 output_unified_token_range(output_baton_t *btn,
                            int tokens,
                            unified_output_e type,
-                           apr_off_t first,
-                           apr_off_t past_last)
+                           apr_off_t until)
 {
   source_tokens_t *source = &btn->sources[tokens];
-  apr_off_t idx;
-
-  past_last = (past_last > source->tokens->nelts)
-    ? source->tokens->nelts : past_last;
 
-  if (tokens == 0)
-    /* We get context from the original source, don't expect
-       to be asked to output a block which starts before
-       what we already have written. */
-    first = (first < btn->next_token) ? btn->next_token : first;
+  if (until > source->tokens->nelts)
+    until = source->tokens->nelts;
 
-  if (first >= past_last)
+  if (until <= btn->current_token[tokens])
     return SVN_NO_ERROR;
 
   /* Do the loop with prefix and token */
-  for (idx = first; idx < past_last; idx++)
+  while (TRUE)
     {
-      svn_string_t *token
-        = APR_ARRAY_IDX(source->tokens, idx, svn_string_t *);
-      svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
-      svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+      svn_string_t *token =
+        APR_ARRAY_IDX(source->tokens, btn->current_token[tokens],
+                      svn_string_t *);
+
+      if (type != unified_output_skip)
+        {
+          svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
+          svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+        }
 
       if (type == unified_output_context)
         {
@@ -415,11 +415,18 @@ output_unified_token_range(output_baton_
         }
       else if (type == unified_output_delete)
         btn->hunk_length[0]++;
-      else
+      else if (type == unified_output_insert)
         btn->hunk_length[1]++;
 
+      /* ### TODO: Add skip processing for -p handling? */
+
+      btn->current_token[tokens]++;
+      if (btn->current_token[tokens] == until)
+        break;
     }
-  if (past_last == source->tokens->nelts && source->ends_without_eol)
+
+  if (btn->current_token[tokens] == source->tokens->nelts 
+      && source->ends_without_eol)
     {
       const char *out_str;
 
@@ -429,8 +436,7 @@ output_unified_token_range(output_baton_
       svn_stringbuf_appendcstr(btn->hunk, out_str);
     }
 
-  if (tokens == 0)
-    btn->next_token = past_last;
+  
 
   return SVN_NO_ERROR;
 }
@@ -445,6 +451,8 @@ output_unified_flush_hunk(output_baton_t
 {
   apr_off_t target_token;
   apr_size_t hunk_len;
+  apr_off_t old_start;
+  apr_off_t new_start;
 
   if (svn_stringbuf_isempty(baton->hunk))
     return SVN_NO_ERROR;
@@ -453,24 +461,28 @@ output_unified_flush_hunk(output_baton_t
 
   /* Write the trailing context */
   target_token = baton->hunk_start[0] + baton->hunk_length[0]
-    + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+                 + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
   SVN_ERR(output_unified_token_range(baton, 0 /*original*/,
                                      unified_output_context,
-                                     baton->next_token, target_token));
+                                     target_token));
   if (hunk_delimiter == NULL)
     hunk_delimiter = "@@";
 
-  /* Convert our 0-based line numbers into unidiff 1-based numbers */
-  if (baton->hunk_length[0] > 0)
-    baton->hunk_start[0]++;
-  if (baton->hunk_length[1] > 0)
-    baton->hunk_start[1]++;
+  old_start = baton->hunk_start[0];
+  new_start = baton->hunk_start[1];
+
+  /* If the file is non-empty, convert the line indexes from
+     zero based to one based */
+  if (baton->hunk_length[0])
+    old_start++;
+  if (baton->hunk_length[1])
+    new_start++;
 
   /* Write the hunk header */
   SVN_ERR(svn_diff__unified_write_hunk_header(
             baton->output_stream, baton->header_encoding, hunk_delimiter,
-            baton->hunk_start[0], baton->hunk_length[0],
-            baton->hunk_start[1], baton->hunk_length[1],
+            old_start, baton->hunk_length[0],
+            new_start, baton->hunk_length[1],
             NULL /* hunk_extra_context */,
             baton->pool));
 
@@ -478,7 +490,11 @@ output_unified_flush_hunk(output_baton_t
   SVN_ERR(svn_stream_write(baton->output_stream,
                            baton->hunk->data, &hunk_len));
 
-  baton->hunk_length[0] = baton->hunk_length[1] = 0;
+  /* Prepare for the next hunk */
+  baton->hunk_length[0] = 0;
+  baton->hunk_length[1] = 0;
+  baton->hunk_start[0] = 0;
+  baton->hunk_start[1] = 0;
   svn_stringbuf_setempty(baton->hunk);
 
   return SVN_NO_ERROR;
@@ -494,38 +510,91 @@ output_unified_diff_modified(void *baton
                              apr_off_t latest_start,
                              apr_off_t latest_length)
 {
-  output_baton_t *btn = baton;
-  apr_off_t targ_orig, targ_mod;
+  output_baton_t *output_baton = baton;
+  apr_off_t context_prefix_length;
+  apr_off_t prev_context_end;
+  svn_boolean_t init_hunk = FALSE;
+
+  if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
+    context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+  else
+    context_prefix_length = original_start;
 
-  targ_orig = original_start - SVN_DIFF__UNIFIED_CONTEXT_SIZE;
-  targ_orig = (targ_orig < 0) ? 0 : targ_orig;
-  targ_mod = modified_start;
-
-  /* If the changed ranges are far enough apart (no overlapping or
-   * connecting context), flush the current hunk. */
-  if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
-    SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
-  /* Adjust offset if it's not the first hunk. */
-  else if (btn->hunk_length[0] != 0)
-    targ_orig = btn->next_token;
+  /* Calculate where the previous hunk will end if we would write it now
+     (including the necessary context at the end) */
+  if (output_baton->hunk_length[0] > 0 || output_baton->hunk_length[1] > 0)
+    {
+      prev_context_end = output_baton->hunk_start[0]
+                         + output_baton->hunk_length[0]
+                         + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+    }
+  else
+    {
+      prev_context_end = -1;
+
+      if (output_baton->hunk_start[0] == 0
+          && (original_length > 0 || modified_length > 0))
+        init_hunk = TRUE;
+    }
 
-  if (btn->hunk_length[0] == 0
-      && btn->hunk_length[1] == 0)
+  /* If the changed range is far enough from the previous range, flush the current
+     hunk. */
+  {
+    apr_off_t new_hunk_start = (original_start - context_prefix_length);
+
+    if (output_baton->current_token[0] < new_hunk_start
+          && prev_context_end <= new_hunk_start)
+      {
+        SVN_ERR(output_unified_flush_hunk(output_baton,
+                                          output_baton->hunk_delimiter));
+        init_hunk = TRUE;
+      }
+    else if (output_baton->hunk_length[0] > 0
+             || output_baton->hunk_length[1] > 0)
+      {
+        /* We extend the current hunk */
+
+        /* Original: Output the context preceding the changed range */
+        SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+                                           unified_output_context,
+                                           original_start));
+      }
+  }
+
+  /* Original: Skip lines until we are at the beginning of the context we want
+     to display */
+  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+                                     unified_output_skip,
+                                     original_start - context_prefix_length));
+
+  if (init_hunk)
     {
-      btn->hunk_start[0] = targ_orig;
-      btn->hunk_start[1] = targ_mod + targ_orig - original_start;
+      SVN_ERR_ASSERT(output_baton->hunk_length[0] == 0
+                     && output_baton->hunk_length[1] == 0);
+
+      output_baton->hunk_start[0] = original_start - context_prefix_length;
+      output_baton->hunk_start[1] = modified_start - context_prefix_length;
     }
 
-  SVN_ERR(output_unified_token_range(btn, 0/*original*/,
-                                     unified_output_context,
-                                     targ_orig, original_start));
-  SVN_ERR(output_unified_token_range(btn, 0/*original*/,
+  /* Modified: Skip lines until we are at the start of the changed range */
+  SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+                                     unified_output_skip,
+                                     modified_start));
+
+  /* Original: Output the context preceding the changed range */
+  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+                                    unified_output_context,
+                                    original_start));
+
+  /* Both: Output the changed range */
+  SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
                                      unified_output_delete,
-                                     original_start,
                                      original_start + original_length));
-  return output_unified_token_range(btn, 1/*modified*/, unified_output_insert,
-                                    modified_start,
-                                    modified_start + modified_length);
+  SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+                                     unified_output_insert,
+                                     modified_start + modified_length));
+
+  return SVN_NO_ERROR;
 }
 
 static const svn_diff_output_fns_t mem_output_unified_vtable =
@@ -656,7 +725,7 @@ typedef struct merge_output_baton_t
 
   /* Tokenized source text */
   source_tokens_t sources[3];
-  apr_off_t next_token;
+  apr_off_t next_token[3];
 
   /* Markers for marking conflicted sections */
   const char *markers[4]; /* 0 = original, 1 = modified,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c Sat Feb 23 01:25:38 2013
@@ -483,12 +483,12 @@ svn_fs_upgrade(const char *path, apr_poo
 
 svn_error_t *
 svn_fs_verify(const char *path,
-              svn_cancel_func_t cancel_func,
-              void *cancel_baton,
-              svn_fs_progress_notify_func_t notify_func,
-              void *notify_baton,
               svn_revnum_t start,
               svn_revnum_t end,
+              svn_fs_progress_notify_func_t notify_func,
+              void *notify_baton,
+              svn_cancel_func_t cancel_func,
+              void *cancel_baton,
               apr_pool_t *pool)
 {
   fs_library_vtable_t *vtable;
@@ -498,9 +498,10 @@ svn_fs_verify(const char *path,
   fs = fs_new(NULL, pool);
 
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
-                       vtable->verify_fs(fs, path, cancel_func, cancel_baton,
-                                         notify_func, notify_baton, start,
-                                         end, pool, common_pool));
+                       vtable->verify_fs(fs, path, start, end,
+                                         notify_func, notify_baton,
+                                         cancel_func, cancel_baton,
+                                         pool, common_pool));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h Sat Feb 23 01:25:38 2013
@@ -88,11 +88,12 @@ typedef struct fs_library_vtable_t
   svn_error_t *(*upgrade_fs)(svn_fs_t *fs, const char *path, apr_pool_t *pool,
                              apr_pool_t *common_pool);
   svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
-                            svn_cancel_func_t cancel_func, void *cancel_baton,
-                            svn_fs_progress_notify_func_t notify_func,
-                            void *notify_baton,
                             svn_revnum_t start,
                             svn_revnum_t end,
+                            svn_fs_progress_notify_func_t notify_func,
+                            void *notify_baton,
+                            svn_cancel_func_t cancel_func,
+                            void *cancel_baton,
                             apr_pool_t *pool,
                             apr_pool_t *common_pool);
   svn_error_t *(*delete_fs)(const char *path, apr_pool_t *pool);

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c Sat Feb 23 01:25:38 2013
@@ -26,6 +26,7 @@
 #include "bdb_compat.h"
 
 #include "svn_pools.h"
+#include "svn_path.h"
 #include "private/svn_skel.h"
 
 #include "dbt.h"

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c Sat Feb 23 01:25:38 2013
@@ -902,12 +902,12 @@ base_upgrade(svn_fs_t *fs, const char *p
 
 static svn_error_t *
 base_verify(svn_fs_t *fs, const char *path,
-            svn_cancel_func_t cancel_func,
-            void *cancel_baton,
-            svn_fs_progress_notify_func_t notify_func,
-            void *notify_baton,
             svn_revnum_t start,
             svn_revnum_t end,
+            svn_fs_progress_notify_func_t notify_func,
+            void *notify_baton,
+            svn_cancel_func_t cancel_func,
+            void *cancel_baton,
             apr_pool_t *pool,
             apr_pool_t *common_pool)
 {

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c Sat Feb 23 01:25:38 2013
@@ -1464,14 +1464,16 @@ svn_fs_base__rep_deltify(svn_fs_t *fs,
                                                 TRUE, trail, pool));
 
   /* Setup a stream to convert the textdelta data into svndiff windows. */
-  svn_txdelta(&txdelta_stream, source_stream, target_stream, pool);
+  svn_txdelta2(&txdelta_stream, source_stream, target_stream, TRUE, pool);
 
   if (bfd->format >= SVN_FS_BASE__MIN_SVNDIFF1_FORMAT)
-    svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,
-                            new_target_stream, 1, pool);
+    svn_txdelta_to_svndiff3(&new_target_handler, &new_target_handler_baton,
+                            new_target_stream, 1,
+                            SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
   else
-    svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,
-                            new_target_stream, 0, pool);
+    svn_txdelta_to_svndiff3(&new_target_handler, &new_target_handler_baton,
+                            new_target_stream, 0,
+                            SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
 
   /* subpool for the windows */
   wpool = svn_pool_create(pool);

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c Sat Feb 23 01:25:38 2013
@@ -4024,7 +4024,7 @@ base_get_file_delta_stream(svn_txdelta_s
   SVN_ERR(base_file_contents(&target, target_root, target_path, pool));
 
   /* Create a delta stream that turns the ancestor into the target.  */
-  svn_txdelta(&delta_stream, source, target, pool);
+  svn_txdelta2(&delta_stream, source, target, TRUE, pool);
 
   *stream_p = delta_stream;
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c Sat Feb 23 01:25:38 2013
@@ -1095,7 +1095,7 @@ svn_fs_fs__dag_serialize(void **data,
   svn_temp_serializer__context_t *context =
       svn_temp_serializer__init(node,
                                 sizeof(*node),
-                                503,
+                                1024 - SVN_TEMP_SERIALIZER__OVERHEAD,
                                 pool);
 
   /* for mutable nodes, we will _never_ cache the noderev */

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Sat Feb 23 01:25:38 2013
@@ -284,12 +284,12 @@ fs_upgrade(svn_fs_t *fs, const char *pat
 
 static svn_error_t *
 fs_verify(svn_fs_t *fs, const char *path,
-          svn_cancel_func_t cancel_func,
-          void *cancel_baton,
-          svn_fs_progress_notify_func_t notify_func,
-          void *notify_baton,
           svn_revnum_t start,
           svn_revnum_t end,
+          svn_fs_progress_notify_func_t notify_func,
+          void *notify_baton,
+          svn_cancel_func_t cancel_func,
+          void *cancel_baton,
           apr_pool_t *pool,
           apr_pool_t *common_pool)
 {
@@ -298,8 +298,8 @@ fs_verify(svn_fs_t *fs, const char *path
   SVN_ERR(svn_fs_fs__open(fs, path, pool));
   SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
   SVN_ERR(fs_serialized_init(fs, common_pool, pool));
-  return svn_fs_fs__verify(fs, cancel_func, cancel_baton, notify_func,
-                           notify_baton, start, end, pool);
+  return svn_fs_fs__verify(fs, start, end, notify_func, notify_baton,
+                           cancel_func, cancel_baton, pool);
 }
 
 static svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Sat Feb 23 01:25:38 2013
@@ -2244,7 +2244,7 @@ get_cached_node_revision_body(node_revis
     }
   else
     {
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = svn_fs_fs__id_rev(id);
       key.second = svn_fs_fs__id_offset(id);
@@ -2273,7 +2273,7 @@ set_cached_node_revision_body(node_revis
 
   if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id))
     {
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = svn_fs_fs__id_rev(id);
       key.second = svn_fs_fs__id_offset(id);
@@ -3536,7 +3536,7 @@ parse_revprop(apr_hash_t **properties,
   if (has_revprop_cache(fs, pool))
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = revision;
       key.second = generation;
@@ -3839,7 +3839,7 @@ get_revision_proplist(apr_hash_t **propl
   if (has_revprop_cache(fs, pool))
     {
       svn_boolean_t is_cached;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
@@ -4386,12 +4386,14 @@ create_rep_state_body(struct rep_state *
 
   /* If the hint is
    * - given,
+   * - refers to a valid revision,
    * - refers to a packed revision,
    * - as does the rep we want to read, and
    * - refers to the same pack file as the rep
    * ...
    */
   if (   file_hint && rev_hint && *file_hint
+      && SVN_IS_VALID_REVNUM(*rev_hint)
       && *rev_hint < ffd->min_unpacked_rev
       && rep->revision < ffd->min_unpacked_rev
       && (   (*rev_hint / ffd->max_files_per_dir)
@@ -5192,7 +5194,7 @@ read_representation(svn_stream_t **conte
   else
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key;
+      pair_cache_key_t fulltext_cache_key = { 0 };
       svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
       struct rep_read_baton *rb;
 
@@ -5366,7 +5368,7 @@ svn_fs_fs__try_process_file_contents(svn
   if (rep)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      pair_cache_key_t fulltext_cache_key;
+      pair_cache_key_t fulltext_cache_key = { 0 };
 
       fulltext_cache_key.revision = rep->revision;
       fulltext_cache_key.second = rep->offset;
@@ -5673,7 +5675,7 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
     {
       fs_fs_data_t *ffd = fs->fsap_data;
       representation_t *rep = noderev->prop_rep;
-      pair_cache_key_t key;
+      pair_cache_key_t key = { 0 };
 
       key.revision = rep->revision;
       key.second = rep->offset;
@@ -10301,6 +10303,15 @@ typedef struct verify_walker_baton_t
   /* number of files opened since the last clean */
   int file_count;
 
+  /* progress notification callback to invoke periodically (may be NULL) */
+  svn_fs_progress_notify_func_t notify_func;
+
+  /* baton to use with NOTIFY_FUNC */
+  void *notify_baton;
+
+  /* remember the last revision for which we called notify_func */
+  svn_revnum_t last_notified_revision;
+
   /* current file handle (or NULL) */
   apr_file_t *file_hint;
 
@@ -10327,10 +10338,19 @@ verify_walker(representation_t *rep,
       verify_walker_baton_t *walker_baton = baton;
       apr_file_t * previous_file;
 
-      /* free resources periodically */
+      /* notify and free resources periodically */
       if (   walker_baton->iteration_count > 1000
           || walker_baton->file_count > 16)
         {
+          if (   walker_baton->notify_func
+              && rep->revision != walker_baton->last_notified_revision)
+            {
+              walker_baton->notify_func(rep->revision,
+                                        walker_baton->notify_baton,
+                                        scratch_pool);
+              walker_baton->last_notified_revision = rep->revision;
+            }
+
           svn_pool_clear(walker_baton->pool);
           
           walker_baton->iteration_count = 0;
@@ -10362,12 +10382,12 @@ verify_walker(representation_t *rep,
 
 svn_error_t *
 svn_fs_fs__verify(svn_fs_t *fs,
-                  svn_cancel_func_t cancel_func,
-                  void *cancel_baton,
-                  svn_fs_progress_notify_func_t notify_func,
-                  void *notify_baton,
                   svn_revnum_t start,
                   svn_revnum_t end,
+                  svn_fs_progress_notify_func_t notify_func,
+                  void *notify_baton,
+                  svn_cancel_func_t cancel_func,
+                  void *cancel_baton,
                   apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -10394,14 +10414,20 @@ svn_fs_fs__verify(svn_fs_t *fs,
       verify_walker_baton_t *baton = apr_pcalloc(pool, sizeof(*baton));
       baton->rev_hint = SVN_INVALID_REVNUM;
       baton->pool = svn_pool_create(pool);
+      baton->last_notified_revision = SVN_INVALID_REVNUM;
+      baton->notify_func = notify_func;
+      baton->notify_baton = notify_baton;
       
+      /* tell the user that we are now read to do *something* */
+      if (notify_func)
+        notify_func(SVN_INVALID_REVNUM, notify_baton, baton->pool);
+
       /* 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, baton,
+      SVN_ERR(svn_fs_fs__walk_rep_reference(fs, start, end,
+                                            verify_walker, baton,
                                             cancel_func, cancel_baton,
-                                            notify_func, notify_baton,
-                                            start, end,
                                             pool));
 
       /* walker resource cleanup */

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h Sat Feb 23 01:25:38 2013
@@ -38,17 +38,22 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
 svn_error_t *svn_fs_fs__upgrade(svn_fs_t *fs,
                                 apr_pool_t *pool);
 
-/* Verify the fsfs filesystem FS.  Use POOL for temporary allocations. */
+/* Verify metadata in fsfs filesystem FS.  Limit the checks to revisions
+ * START to END where possible.  Indicate progress via the optional
+ * NOTIFY_FUNC callback using NOTIFY_BATON.  The optional CANCEL_FUNC
+ * will periodically be called with CANCEL_BATON to allow for preemption.
+ * Use POOL for temporary allocations. */
 svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
-                               svn_cancel_func_t cancel_func,
-                               void *cancel_baton,
-                               svn_fs_progress_notify_func_t notify_func,
-                               void *notify_baton,
                                svn_revnum_t start,
                                svn_revnum_t end,
+                               svn_fs_progress_notify_func_t notify_func,
+                               void *notify_baton,
+                               svn_cancel_func_t cancel_func,
+                               void *cancel_baton,
                                apr_pool_t *pool);
 
-/* Verify REVISION in filesystem FS.  Use POOL for temporary allocations. */
+/* Verify metadata of REVISION in filesystem FS.
+ * Use POOL for temporary allocations. */
 svn_error_t *
 svn_fs_fs__verify_rev(svn_fs_t *fs,
                       svn_revnum_t revision,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql Sat Feb 23 01:25:38 2013
@@ -22,8 +22,6 @@
  */
 
 -- STMT_CREATE_SCHEMA
-PRAGMA AUTO_VACUUM = 1;
-
 /* A table mapping representation hashes to locations in a rev file. */
 CREATE TABLE rep_cache (
   hash TEXT NOT NULL PRIMARY KEY,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c Sat Feb 23 01:25:38 2013
@@ -128,6 +128,8 @@ svn_fs_fs__exists_rep_cache(svn_boolean_
 
 svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               svn_error_t *(*walker)(representation_t *,
                                                      void *,
                                                      svn_fs_t *,
@@ -135,17 +137,12 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
-                              svn_fs_progress_notify_func_t notify_func,
-                              void *notify_baton,
-                              svn_revnum_t start,
-                              svn_revnum_t end,
                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   int iterations = 0;
-  svn_revnum_t last_notified_revision = SVN_INVALID_REVNUM;
 
   apr_pool_t *iterpool = svn_pool_create(pool);
 
@@ -167,9 +164,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
       SVN_ERR(svn_sqlite__reset(stmt));
       if (SVN_IS_VALID_REVNUM(max))  /* The rep-cache could be empty. */
         SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
-
-      if (notify_func)
-        notify_func(SVN_INVALID_REVNUM, notify_baton, iterpool);
     }
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
@@ -216,16 +210,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
         return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-      /* Notify (occasionally, because walking is fast and we can't
-         guarantee a properly ordered notification sequence anyway) */
-      if (   notify_func
-          && (iterations % 1024 == 0)
-          && (rep->revision != last_notified_revision))
-        {
-          notify_func(rep->revision, notify_baton, iterpool);
-          last_notified_revision = rep->revision;
-        }
     }
 
   SVN_ERR(svn_sqlite__reset(stmt));

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h Sat Feb 23 01:25:38 2013
@@ -48,6 +48,8 @@ svn_fs_fs__exists_rep_cache(svn_boolean_
 /* Iterate all representations currently in FS's cache. */
 svn_error_t *
 svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
+                              svn_revnum_t start,
+                              svn_revnum_t end,
                               svn_error_t *(*walker)(representation_t *rep,
                                                      void *walker_baton,
                                                      svn_fs_t *fs,
@@ -55,10 +57,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
                               void *walker_baton,
                               svn_cancel_func_t cancel_func,
                               void *cancel_baton,
-                              svn_fs_progress_notify_func_t notify_func,
-                              void *notify_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/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c Sat Feb 23 01:25:38 2013
@@ -739,9 +739,12 @@ svn_fs_fs__serialize_node_revision(void 
   svn_stringbuf_t *serialized;
   node_revision_t *noderev = item;
 
-  /* create an (empty) serialization context with plenty of buffer space */
+  /* create an (empty) serialization context with plenty of (initial)
+   * buffer space. */
   svn_temp_serializer__context_t *context =
-      svn_temp_serializer__init(NULL, 0, 503, pool);
+      svn_temp_serializer__init(NULL, 0,
+                                1024 - SVN_TEMP_SERIALIZER__OVERHEAD,
+                                pool);
 
   /* serialize the noderev */
   svn_fs_fs__noderev_serialize(context, &noderev);

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c Sat Feb 23 01:25:38 2013
@@ -497,6 +497,9 @@ dag_node_cache_set(svn_fs_root_t *root,
 
   SVN_ERR_ASSERT(*path == '/');
 
+  /* Do *not* attempt to dup and put the node into L1.
+   * dup() is twice as expensive as an L2 lookup (which will set also L1).
+   */
   locate_cache(&cache, &key, root, path, pool);
 
   return svn_cache__set(cache, key, node, pool);
@@ -847,20 +850,28 @@ typedef enum open_path_flags_t {
      directories must exist, as usual.)  If the last component doesn't
      exist, simply leave the `node' member of the bottom parent_path
      component zero.  */
-  open_path_last_optional = 1
+  open_path_last_optional = 1,
 
+  /* When this flag is set, don't bother to lookup the DAG node in
+     our caches because we already tried this.  Ignoring this flag
+     has no functional impact.  */
+  open_path_uncached = 2,
+
+  /* The caller does not care about the parent node chain but only
+     the final DAG node. */
+  open_path_node_only = 4
 } open_path_flags_t;
 
 
 /* Open the node identified by PATH in ROOT, allocating in POOL.  Set
    *PARENT_PATH_P to a path from the node up to ROOT.  The resulting
    **PARENT_PATH_P value is guaranteed to contain at least one
-   *element, for the root directory.
+   *element, for the root directory.  PATH must be in canonical form.
 
    If resulting *PARENT_PATH_P will eventually be made mutable and
    modified, or if copy ID inheritance information is otherwise
    needed, TXN_ID should be the ID of the mutability transaction.  If
-   TXN_ID is NULL, no copy ID in heritance information will be
+   TXN_ID is NULL, no copy ID inheritance information will be
    calculated for the *PARENT_PATH_P chain.
 
    If FLAGS & open_path_last_optional is zero, return the error
@@ -871,6 +882,11 @@ typedef enum open_path_flags_t {
    callers that create new nodes --- we find the parent directory for
    them, and tell them whether the entry exists already.
 
+   The remaining bits in FLAGS are hints that allow this function
+   to take shortcuts based on knowledge that the caller provides,
+   such as the caller is not actually being interested in PARENT_PATH_P,
+   but only in (*PARENT_PATH_P)->NODE.
+
    NOTE: Public interfaces which only *read* from the filesystem
    should not call this function directly, but should instead use
    get_dag().
@@ -884,23 +900,44 @@ open_path(parent_path_t **parent_path_p,
           apr_pool_t *pool)
 {
   svn_fs_t *fs = root->fs;
-  dag_node_t *here; /* The directory we're currently looking at.  */
-  parent_path_t *parent_path; /* The path from HERE up to the root.  */
+  dag_node_t *here = NULL; /* The directory we're currently looking at.  */
+  parent_path_t *parent_path; /* The path from HERE up to the root. */
   const char *rest; /* The portion of PATH we haven't traversed yet.  */
-  const char *canon_path = svn_fs__is_canonical_abspath(path)
-                         ? path
-                         : svn_fs__canonicalize_abspath(path, pool);
+
+  /* ensure a canonical path representation */
   const char *path_so_far = "/";
   apr_pool_t *iterpool = svn_pool_create(pool);
 
-  /* Make a parent_path item for the root node, using its own current
-     copy id.  */
-  SVN_ERR(root_node(&here, root, pool));
+  /* callers often traverse the tree in some path-based order.  That means
+     a sibling of PATH has been presently accessed.  Try to start the lookup
+     directly at the parent node, if the caller did not requested the full
+     parent chain. */
+  const char *directory;
+  assert(svn_fs__is_canonical_abspath(path));
+  if (flags & open_path_node_only)
+    {
+      directory = svn_dirent_dirname(path, pool);
+      if (directory[1] != 0) /* root nodes are covered anyway */
+        SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
+    }
+
+  /* did the shortcut work? */
+  if (here)
+    {
+      path_so_far = directory;
+      rest = path + strlen(directory) + 1;
+    }
+  else
+    {
+      /* Make a parent_path item for the root node, using its own current
+         copy id.  */
+      SVN_ERR(root_node(&here, root, pool));
+      rest = path + 1; /* skip the leading '/', it saves in iteration */
+    }
+ 
   parent_path = make_parent_path(here, 0, 0, pool);
   parent_path->copy_inherit = copy_id_inherit_self;
 
-  rest = canon_path + 1; /* skip the leading '/', it saves in iteration */
-
   /* Whenever we are at the top of this loop:
      - HERE is our current directory,
      - ID is the node revision ID of HERE,
@@ -933,13 +970,16 @@ open_path(parent_path_t **parent_path_p,
           copy_id_inherit_t inherit;
           const char *copy_path = NULL;
           svn_error_t *err = SVN_NO_ERROR;
-          dag_node_t *cached_node;
+          dag_node_t *cached_node = NULL;
 
           /* If we found a directory entry, follow it.  First, we
              check our node cache, and, failing that, we hit the DAG
-             layer. */
-          SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, TRUE,
-                                     pool));
+             layer.  Don't bother to contact the cache for the last
+             element if we already know the lookup to fail for the
+             complete path. */
+          if (next || !(flags & open_path_uncached))
+            SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far,
+                                       TRUE, pool));
           if (cached_node)
             child = cached_node;
           else
@@ -972,14 +1012,22 @@ open_path(parent_path_t **parent_path_p,
           /* Other errors we return normally.  */
           SVN_ERR(err);
 
-          /* Now, make a parent_path item for CHILD. */
-          parent_path = make_parent_path(child, entry, parent_path, pool);
-          if (txn_id)
+          if (flags & open_path_node_only)
             {
-              SVN_ERR(get_copy_inheritance(&inherit, &copy_path,
-                                           fs, parent_path, txn_id, iterpool));
-              parent_path->copy_inherit = inherit;
-              parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
+              /* Shortcut: the caller only wan'ts the final DAG node. */
+              parent_path->node = child;
+            }
+          else
+            {
+              /* Now, make a parent_path item for CHILD. */
+              parent_path = make_parent_path(child, entry, parent_path, pool);
+              if (txn_id)
+                {
+                  SVN_ERR(get_copy_inheritance(&inherit, &copy_path, fs,
+                                               parent_path, txn_id, iterpool));
+                  parent_path->copy_inherit = inherit;
+                  parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
+                }
             }
 
           /* Cache the node we found (if it wasn't already cached). */
@@ -1129,7 +1177,7 @@ get_dag(dag_node_t **dag_node_p,
   if (! node)
     {
       /* Canonicalize the input PATH. */
-      if (!svn_fs__is_canonical_abspath(path))
+      if (! svn_fs__is_canonical_abspath(path))
         {
           path = svn_fs__canonicalize_abspath(path, pool);
 
@@ -1142,7 +1190,9 @@ get_dag(dag_node_t **dag_node_p,
         {
           /* Call open_path with no flags, as we want this to return an
            * error if the node for which we are searching doesn't exist. */
-          SVN_ERR(open_path(&parent_path, root, path, 0, NULL, pool));
+          SVN_ERR(open_path(&parent_path, root, path,
+                            open_path_uncached | open_path_node_only,
+                            NULL, pool));
           node = parent_path->node;
 
           /* No need to cache our find -- open_path() will do that for us. */
@@ -1369,6 +1419,7 @@ fs_change_node_prop(svn_fs_root_t *root,
     return SVN_FS__NOT_TXN(root);
   txn_id = root->txn;
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, 0, txn_id, pool));
 
   /* Check (non-recursively) to see if path is locked; if so, check
@@ -2140,6 +2191,7 @@ fs_make_dir(svn_fs_root_t *root,
   dag_node_t *sub_dir;
   const char *txn_id = root->txn;
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
                     txn_id, pool));
 
@@ -2191,6 +2243,7 @@ fs_delete_node(svn_fs_root_t *root,
   if (! root->is_txn_root)
     return SVN_FS__NOT_TXN(root);
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, 0, txn_id, pool));
   kind = svn_fs_fs__dag_node_kind(parent_path->node);
 
@@ -2390,7 +2443,12 @@ fs_copy(svn_fs_root_t *from_root,
         const char *to_path,
         apr_pool_t *pool)
 {
-  return svn_error_trace(copy_helper(from_root, from_path, to_root, to_path,
+  return svn_error_trace(copy_helper(from_root,
+                                     svn_fs__canonicalize_abspath(from_path,
+                                                                  pool),
+                                     to_root,
+                                     svn_fs__canonicalize_abspath(to_path,
+                                                                  pool),
                                      TRUE, pool));
 }
 
@@ -2407,6 +2465,7 @@ fs_revision_link(svn_fs_root_t *from_roo
   if (! to_root->is_txn_root)
     return SVN_FS__NOT_TXN(to_root);
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   return svn_error_trace(copy_helper(from_root, path, to_root, path,
                                      FALSE, pool));
 }
@@ -2482,8 +2541,9 @@ fs_make_file(svn_fs_root_t *root,
   dag_node_t *child;
   const char *txn_id = root->txn;
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
-                    txn_id, pool));
+                   txn_id, pool));
 
   /* If there's already a file by that name, complain.
      This also catches the case of trying to make a file named `/'.  */
@@ -2791,7 +2851,7 @@ fs_apply_textdelta(svn_txdelta_window_ha
   txdelta_baton_t *tb = apr_pcalloc(pool, sizeof(*tb));
 
   tb->root = root;
-  tb->path = path;
+  tb->path = svn_fs__canonicalize_abspath(path, pool);
   tb->pool = pool;
   tb->base_checksum = svn_checksum_dup(base_checksum, pool);
   tb->result_checksum = svn_checksum_dup(result_checksum, pool);
@@ -2924,7 +2984,7 @@ fs_apply_text(svn_stream_t **contents_p,
   struct text_baton_t *tb = apr_pcalloc(pool, sizeof(*tb));
 
   tb->root = root;
-  tb->path = path;
+  tb->path = svn_fs__canonicalize_abspath(path, pool);
   tb->pool = pool;
   tb->result_checksum = svn_checksum_dup(result_checksum, pool);
 
@@ -3144,6 +3204,7 @@ static svn_error_t *fs_closest_copy(svn_
   *root_p = NULL;
   *path_p = NULL;
 
+  path = svn_fs__canonicalize_abspath(path, pool);
   SVN_ERR(open_path(&parent_path, root, path, 0, NULL, pool));
 
   /* Find the youngest copyroot in the path of this node-rev, which
@@ -3162,7 +3223,7 @@ static svn_error_t *fs_closest_copy(svn_
   if (kind == svn_node_none)
     return SVN_NO_ERROR;
   SVN_ERR(open_path(&copy_dst_parent_path, copy_dst_root, path,
-                    0, NULL, pool));
+                    open_path_node_only, NULL, pool));
   copy_dst_node = copy_dst_parent_path->node;
   if (! svn_fs_fs__id_check_related(svn_fs_fs__dag_get_id(copy_dst_node),
                                     svn_fs_fs__dag_get_id(parent_path->node)))
@@ -3622,7 +3683,7 @@ assemble_history(svn_fs_t *fs,
 {
   svn_fs_history_t *history = apr_pcalloc(pool, sizeof(*history));
   fs_history_data_t *fhd = apr_pcalloc(pool, sizeof(*fhd));
-  fhd->path = path;
+  fhd->path = svn_fs__canonicalize_abspath(path, pool);
   fhd->revision = revision;
   fhd->is_interesting = is_interesting;
   fhd->path_hint = path_hint;

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c Sat Feb 23 01:25:38 2013
@@ -35,26 +35,19 @@
 #include "private/svn_fspath.h"
 #include "../libsvn_fs/fs-loader.h"
 
-svn_boolean_t
-svn_fs__is_canonical_abspath(const char *path)
+/* Return TRUE, if PATH of PATH_LEN > 0 chars starts with a '/' and does
+ * not end with a '/' and does not contain duplicate '/'.
+ */
+static svn_boolean_t
+is_canonical_abspath(const char *path, size_t path_len)
 {
-  size_t path_len;
   const char *end;
 
-  /* No PATH?  No problem. */
-  if (! path)
-    return TRUE;
-
-  /* Empty PATH?  That's just "/". */
-  if (! *path)
-    return FALSE;
-
-  /* No leading slash?  Fix that. */
-  if (*path != '/')
+  /* check for leading '/' */
+  if (path[0] != '/')
     return FALSE;
 
   /* check for trailing '/' */
-  path_len = strlen(path);
   if (path_len == 1)
     return TRUE;
   if (path[path_len - 1] == '/')
@@ -69,6 +62,21 @@ svn_fs__is_canonical_abspath(const char 
   return TRUE;
 }
 
+svn_boolean_t
+svn_fs__is_canonical_abspath(const char *path)
+{
+  /* No PATH?  No problem. */
+  if (! path)
+    return TRUE;
+
+  /* Empty PATH?  That's just "/". */
+  if (! *path)
+    return FALSE;
+
+  /* detailed checks */
+  return is_canonical_abspath(path, strlen(path));
+}
+
 const char *
 svn_fs__canonicalize_abspath(const char *path, apr_pool_t *pool)
 {
@@ -83,12 +91,16 @@ svn_fs__canonicalize_abspath(const char 
 
   /* Empty PATH?  That's just "/". */
   if (! *path)
-    return apr_pstrdup(pool, "/");
+    return "/";
+
+  /* Non-trivial cases.  Maybe, the path already is canonical after all? */
+  path_len = strlen(path);
+  if (is_canonical_abspath(path, path_len))
+    return apr_pstrmemdup(pool, path, path_len);
 
   /* Now, the fun begins.  Alloc enough room to hold PATH with an
      added leading '/'. */
-  path_len = strlen(path);
-  newpath = apr_pcalloc(pool, path_len + 2);
+  newpath = apr_palloc(pool, path_len + 2);
 
   /* No leading slash?  Fix that. */
   if (*path != '/')
@@ -123,6 +135,8 @@ svn_fs__canonicalize_abspath(const char 
      the root directory case)? */
   if ((newpath[newpath_i - 1] == '/') && (newpath_i > 1))
     newpath[newpath_i - 1] = '\0';
+  else
+    newpath[newpath_i] = '\0';
 
   return newpath;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c Sat Feb 23 01:25:38 2013
@@ -848,10 +848,10 @@ svn_ra_local__do_switch(svn_ra_session_t
                        update_revision,
                        update_target,
                        switch_url,
-                       TRUE,
+                       TRUE /* text_deltas */,
                        depth,
-                       FALSE,   /* ### TODO(sussman): take new arg */
-                       TRUE,
+                       FALSE /* send_copyfrom_args */,
+                       TRUE /* ignore_ancestry */,
                        update_editor,
                        update_baton,
                        pool);
@@ -1513,7 +1513,10 @@ svn_ra_local__has_capability(svn_ra_sess
       || strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0
       || strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0
       || strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0
-      || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
+      || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0
+      || strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0
+      || strcmp(capability, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE) == 0
+      )
     {
       *has = TRUE;
     }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Sat Feb 23 01:25:38 2013
@@ -289,6 +289,8 @@ checkout_node(const char **working_url,
               apr_pool_t *scratch_pool)
 {
   svn_ra_serf__handler_t handler = { 0 };
+  apr_status_t status;
+  apr_uri_t uri;
 
   /* HANDLER_POOL is the scratch pool since we don't need to remember
      anything from the handler. We just want the working resource.  */
@@ -315,7 +317,17 @@ checkout_node(const char **working_url,
     return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                             _("No Location header received"));
 
-  *working_url = apr_pstrdup(result_pool, handler.location);
+  /* We only want the path portion of the Location header.
+     (code.google.com sometimes returns an 'http:' scheme for an
+     'https:' transaction ... we'll work around that by stripping the
+     scheme, host, and port here and re-adding the correct ones
+     later.  */
+  status = apr_uri_parse(scratch_pool, handler.location, &uri);
+  if (status)
+    return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                            _("Error parsing Location header value"));
+
+  *working_url = svn_urlpath__canonicalize(uri.path, result_pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c Sat Feb 23 01:25:38 2013
@@ -28,6 +28,7 @@
 #include <serf.h>
 
 #include "svn_dirent_uri.h"
+#include "svn_hash.h"
 #include "svn_pools.h"
 #include "svn_ra.h"
 #include "svn_dav.h"
@@ -169,47 +170,50 @@ capabilities_headers_iterator_callback(v
 
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING,
-                       capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_DEPTH, capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
         {
           /* The server doesn't know what repository we're referring
              to, so it can't just say capability_yes. */
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
-                       capability_server_yes);
+          if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO))
+            {
+              svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                            capability_server_yes);
+            }
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING,
-                       capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_LOG_REVPROPS, capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING,
-                       capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_ATOMIC_REVPROPS, capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
-                       capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_PARTIAL_REPLAY, capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_INHERITED_PROPS,
-                       APR_HASH_KEY_STRING, capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_INHERITED_PROPS, capability_yes);
+        }
+      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_GET_FILE_REVS_REVERSE,
+                                 vals))
+        {
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+                        capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
         {
-          apr_hash_set(session->capabilities,
-                       SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, APR_HASH_KEY_STRING,
-                       capability_yes);
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, capability_yes);
         }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INLINE_PROPS, vals))
         {
@@ -303,8 +307,20 @@ capabilities_headers_iterator_callback(v
             {
               const char *post_val = APR_ARRAY_IDX(vals, i, const char *);
 
-              apr_hash_set(session->supported_posts, post_val,
-                           APR_HASH_KEY_STRING, (void *)1);
+              svn_hash_sets(session->supported_posts, post_val, (void *)1);
+            }
+        }
+      else if (svn_cstring_casecmp(key, SVN_DAV_REPOSITORY_MERGEINFO) == 0)
+        {
+          if (svn_cstring_casecmp(val, "yes") == 0)
+            {
+              svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                            capability_yes);
+            }
+          else if (svn_cstring_casecmp(val, "no") == 0)
+            {
+              svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                            capability_no);
             }
         }
     }
@@ -331,25 +347,31 @@ options_response_handler(serf_request_t 
       serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
 
       /* Start out assuming all capabilities are unsupported. */
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_DEPTH,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
-                   APR_HASH_KEY_STRING, capability_no);
-      apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
-                   APR_HASH_KEY_STRING, capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
+                    capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_DEPTH,
+                    capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                    NULL);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
+                    capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                    capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
+                    capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+                    capability_no);
 
       /* Then see which ones we can discover. */
       serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
                              opt_ctx);
 
+      /* Assume mergeinfo capability unsupported, if didn't recieve information
+         about server or repository mergeinfo capability. */
+      if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO))
+        svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+                      capability_no);
+
       opt_ctx->headers_processed = TRUE;
     }
 
@@ -548,9 +570,8 @@ svn_ra_serf__has_capability(svn_ra_sessi
           else
             cap_result = capability_yes;
 
-          apr_hash_set(serf_sess->capabilities,
-                       SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
-                       cap_result);
+          svn_hash_sets(serf_sess->capabilities,
+                        SVN_RA_CAPABILITY_MERGEINFO,  cap_result);
         }
       else
         {

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c Sat Feb 23 01:25:38 2013
@@ -637,7 +637,7 @@ svn_ra_serf__wait_for_props(svn_ra_serf_
 
   err2 = svn_ra_serf__error_on_status(handler->sline.code,
                                       handler->path,
-                                      NULL);
+                                      handler->location);
   if (err2)
     {
       svn_error_clear(err);

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Sat Feb 23 01:25:38 2013
@@ -3485,7 +3485,9 @@ try_get_wc_contents(svn_boolean_t *found
   
   if (wc_stream)
     {
-      SVN_ERR(svn_stream_copy3(wc_stream, dst_stream, NULL, NULL, pool));
+        SVN_ERR(svn_stream_copy3(wc_stream,
+                                 svn_stream_disown(dst_stream, pool),
+                                 NULL, NULL, pool));
       *found_p = TRUE;
     }
 

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Sat Feb 23 01:25:38 2013
@@ -41,6 +41,7 @@
 #include "svn_string.h"
 #include "svn_xml.h"
 #include "svn_props.h"
+#include "svn_dirent_uri.h"
 
 #include "../libsvn_ra/ra_loader.h"
 #include "private/svn_dep_compat.h"
@@ -987,27 +988,51 @@ svn_ra_serf__response_discard_handler(se
 
 
 /* Return the value of the RESPONSE's Location header if any, or NULL
-   otherwise.  All allocations will be made in POOL.  */
+   otherwise.  */
 static const char *
 response_get_location(serf_bucket_t *response,
-                      apr_pool_t *pool)
+                      const char *base_url,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
   serf_bucket_t *headers;
   const char *location;
-  apr_status_t status;
-  apr_uri_t uri;
 
   headers = serf_bucket_response_get_headers(response);
   location = serf_bucket_headers_get(headers, "Location");
   if (location == NULL)
     return NULL;
 
-  /* Ignore the scheme/host/port. Or just return as-is if we can't parse.  */
-  status = apr_uri_parse(pool, location, &uri);
-  if (!status)
-    location = uri.path;
+  /* The RFCs say we should have received a full url in LOCATION, but
+     older apache versions and many custom web handlers just return a
+     relative path here...
+
+     And we can't trust anything because it is network data.
+   */
+  if (*location == '/')
+    {
+      apr_uri_t uri;
+      apr_status_t status;
+
+      status = apr_uri_parse(scratch_pool, base_url, &uri);
+
+      if (status != APR_SUCCESS)
+        return NULL;
+
+      /* Replace the path path with what we got */
+      uri.path = (char*)svn_urlpath__canonicalize(location, scratch_pool);
+
+      /* And make APR produce a proper full url for us */
+      location = apr_uri_unparse(scratch_pool, &uri, 0);
+
+      /* Fall through to ensure our canonicalization rules */
+    }
+  else if (!svn_path_is_url(location))
+    {
+      return NULL; /* Any other formats we should support? */
+    }
 
-  return svn_urlpath__canonicalize(location, pool);
+  return svn_uri_canonicalize(location, result_pool);
 }
 
 
@@ -1896,7 +1921,10 @@ handle_response(serf_request_t *request,
     }
 
   /* ... and set up the header fields in HANDLER.  */
-  handler->location = response_get_location(response, handler->handler_pool);
+  handler->location = response_get_location(response,
+                                            handler->session->session_url_str,
+                                            handler->handler_pool,
+                                            scratch_pool);
 
   /* On the last request, we failed authentication. We succeeded this time,
      so let's save away these credentials.  */

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c Sat Feb 23 01:25:38 2013
@@ -2589,43 +2589,46 @@ ra_svn_replay_range(svn_ra_session_t *se
 }
 
 
-static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
-                                          svn_boolean_t *has,
-                                          const char *capability,
-                                          apr_pool_t *pool)
+static svn_error_t *
+ra_svn_has_capability(svn_ra_session_t *session,
+                      svn_boolean_t *has,
+                      const char *capability,
+                      apr_pool_t *pool)
 {
   svn_ra_svn__session_baton_t *sess = session->priv;
+  static const char* capabilities[][2] =
+  {
+      /* { ra capability string, svn:// wire capability string} */
+      {SVN_RA_CAPABILITY_DEPTH, SVN_RA_SVN_CAP_DEPTH},
+      {SVN_RA_CAPABILITY_MERGEINFO, SVN_RA_SVN_CAP_MERGEINFO},
+      {SVN_RA_CAPABILITY_LOG_REVPROPS, SVN_RA_SVN_CAP_LOG_REVPROPS},
+      {SVN_RA_CAPABILITY_PARTIAL_REPLAY, SVN_RA_SVN_CAP_PARTIAL_REPLAY},
+      {SVN_RA_CAPABILITY_COMMIT_REVPROPS, SVN_RA_SVN_CAP_COMMIT_REVPROPS},
+      {SVN_RA_CAPABILITY_ATOMIC_REVPROPS, SVN_RA_SVN_CAP_ATOMIC_REVPROPS},
+      {SVN_RA_CAPABILITY_INHERITED_PROPS, SVN_RA_SVN_CAP_INHERITED_PROPS},
+      {SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+                                          SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS},
+      {SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+                                       SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE},
+
+      {NULL, NULL} /* End of list marker */
+  };
+  int i;
 
   *has = FALSE;
 
-  if (strcmp(capability, SVN_RA_CAPABILITY_DEPTH) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_DEPTH);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_MERGEINFO);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_LOG_REVPROPS);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_PARTIAL_REPLAY);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn,
-                                     SVN_RA_SVN_CAP_COMMIT_REVPROPS);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn,
-                                     SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn,
-                                     SVN_RA_SVN_CAP_INHERITED_PROPS);
-  else if (strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0)
-    *has = svn_ra_svn_has_capability(sess->conn,
-                                     SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS);
-  else  /* Don't know any other capabilities, so error. */
+  for (i = 0; capabilities[i][0]; i++)
     {
-      return svn_error_createf
-        (SVN_ERR_UNKNOWN_CAPABILITY, NULL,
-         _("Don't know anything about capability '%s'"), capability);
+      if (strcmp(capability, capabilities[i][0]))
+        {
+          *has = svn_ra_svn_has_capability(sess->conn, capabilities[i][1]);
+          return SVN_NO_ERROR;
+        }
     }
 
-  return SVN_NO_ERROR;
+  return svn_error_createf(SVN_ERR_UNKNOWN_CAPABILITY, NULL,
+                           _("Don't know anything about capability '%s'"),
+                           capability);
 }
 
 static svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/authz.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/authz.c Sat Feb 23 01:25:38 2013
@@ -771,9 +771,9 @@ authz_validate(svn_authz_t *authz, apr_p
 /* Retrieve the file at DIRENT (contained in a repo) then parse it as a config
  * file placing the result into CFG_P allocated in POOL.
  *
- * If DIRENT is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
- * as the error.  The contents of CFG_P is then undefined.  If MUST_EXIST is
- * TRUE, a missing authz file is also an error.
+ * If DIRENT cannot be parsed as a config file then an error is returned.  The
+ * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
  *
  * SCRATCH_POOL will be used for temporary allocations. */
 static svn_error_t *
@@ -794,7 +794,7 @@ authz_retrieve_config_repo(svn_config_t 
   /* Search for a repository in the full path. */
   repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
   if (!repos_root_dirent)
-    return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+    return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL,
                              "Unable to find repository at '%s'", dirent);
 
   /* Attempt to open a repository at repos_root_dirent. */
@@ -804,7 +804,7 @@ authz_retrieve_config_repo(svn_config_t 
 
   /* Root path is always a directory so no reason to go any further */
   if (*fs_path == '\0')
-    return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                              "'/' is not a file in repo '%s'",
                              repos_root_dirent);
 
@@ -826,19 +826,19 @@ authz_retrieve_config_repo(svn_config_t 
     {
       if (!must_exist)
         {
-          SVN_ERR(svn_config_create(cfg_p, TRUE, scratch_pool));
+          SVN_ERR(svn_config_create(cfg_p, TRUE, result_pool));
           return SVN_NO_ERROR;
         }
       else
         {
-          return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                    "'%s' path not found in repo '%s'", fs_path,
                                    repos_root_dirent);
         }
     }
   else if (node_kind != svn_node_file)
     {
-      return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+      return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                "'%s' is not a file in repo '%s'", fs_path,
                                repos_root_dirent);
     }
@@ -849,22 +849,22 @@ authz_retrieve_config_repo(svn_config_t 
   /* Add the URL to the error stack since the parser doesn't have it. */
   if (err != SVN_NO_ERROR)
     return svn_error_createf(err->apr_err, err, 
-                             "Error parsing config file: '%s' in repo '%s':",
+                             "Error while parsing config file: '%s' in repo '%s':",
                              fs_path, repos_root_dirent);
 
   return SVN_NO_ERROR;
 }
 
-/* Given a PATH which might be a realative repo URL (^/), an absolute
+/* Given a PATH which might be a relative repo URL (^/), an absolute
  * local repo URL (file://), an absolute path outside of the repo
  * or a location in the Windows registry.
  *
  * Retrieve the configuration data that PATH points at and parse it into
  * CFG_P allocated in POOL.
  *
- * If PATH is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
- * as the error.  The contents of CFG_P is then undefined.  If MUST_EXIST is
- * TRUE, a missing authz file is also an error.
+ * If PATH cannot be parsed as a config file then an error is returned.  The
+ * contents of CFG_P is then undefined.  If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
  *
  * REPOS_ROOT points at the root of the repos you are
  * going to apply the authz against, can be NULL if you are sure that you
@@ -919,20 +919,81 @@ authz_retrieve_config(svn_config_t **cfg
   return SVN_NO_ERROR;
 }
 
+
+/* Callback to copy (name, value) group into the "groups" section
+   of another configuration. */
+static svn_boolean_t
+authz_copy_group(const char *name, const char *value,
+                 void *baton, apr_pool_t *pool)
+{
+  svn_config_t *authz_cfg = baton;
+
+  svn_config_set(authz_cfg, SVN_CONFIG_SECTION_GROUPS, name, value);
+
+  return TRUE;
+}
+
+/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ.
+ * If AUTHZ already contains any group definition, report an error.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg,
+                  apr_pool_t *pool)
+{
+  /* Easy out: we prohibit local groups in the authz file when global
+     groups are being used. */
+  if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS))
+    {
+      return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+                              "Authz file cannot contain any groups "
+                              "when global groups are being used.");
+    }
+
+  svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS,
+                        authz_copy_group, authz->cfg, pool);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_repos__authz_read(svn_authz_t **authz_p, const char *path,
-                      svn_boolean_t must_exist, svn_boolean_t accept_urls,
-                      const char *repos_root, apr_pool_t *pool)
+                      const char *groups_path, svn_boolean_t must_exist,
+                      svn_boolean_t accept_urls, const char *repos_root,
+                      apr_pool_t *pool)
 {
   svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
 
-  /* Load the rule file */
+  /* Load the authz file */
   if (accept_urls)
     SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, repos_root,
                                   pool));
   else
     SVN_ERR(svn_config_read2(&authz->cfg, path, must_exist, TRUE, pool));
 
+  if (groups_path)
+    {
+      svn_config_t *groups_cfg;
+      svn_error_t *err;
+
+      /* Load the groups file */
+      if (accept_urls)
+        SVN_ERR(authz_retrieve_config(&groups_cfg, groups_path, must_exist,
+                                      repos_root, pool));
+      else
+        SVN_ERR(svn_config_read2(&groups_cfg, groups_path, must_exist,
+                                 TRUE, pool));
+
+      /* Copy the groups from groups_cfg into authz. */
+      err = authz_copy_groups(authz, groups_cfg, pool);
+
+      /* Add the paths to the error stack since the authz_copy_groups
+         routine knows nothing about them. */
+      if (err != SVN_NO_ERROR)
+        return svn_error_createf(err->apr_err, err,
+                                 "Error reading authz file '%s' with "
+                                 "groups file '%s':", path, groups_path);
+    }
+
   /* Make sure there are no errors in the configuration. */
   SVN_ERR(authz_validate(authz, pool));
 
@@ -946,23 +1007,33 @@ svn_repos__authz_read(svn_authz_t **auth
 
 svn_error_t *
 svn_repos_authz_read2(svn_authz_t **authz_p, const char *path,
-                      svn_boolean_t must_exist, const char *repos_root,
-                      apr_pool_t *pool)
+                      const char *groups_path, svn_boolean_t must_exist,
+                      const char *repos_root, apr_pool_t *pool)
 {
-  return svn_repos__authz_read(authz_p, path, must_exist, TRUE, repos_root,
-                               pool);
+  return svn_repos__authz_read(authz_p, path, groups_path, must_exist,
+                               TRUE, repos_root, pool);
 }
 
 
 svn_error_t *
 svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream, 
-                      apr_pool_t *pool)
+                      svn_stream_t *groups_stream, apr_pool_t *pool)
 {
   svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
 
-  /* Parse the stream */
+  /* Parse the authz stream */
   SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, pool));
 
+  if (groups_stream)
+    {
+      svn_config_t *groups_cfg;
+
+      /* Parse the groups stream */
+      SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, pool));
+
+      SVN_ERR(authz_copy_groups(authz, groups_cfg, pool));
+    }
+
   /* Make sure there are no errors in the configuration. */
   SVN_ERR(authz_validate(authz, pool));
 

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c Sat Feb 23 01:25:38 2013
@@ -1013,5 +1013,6 @@ svn_error_t *
 svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
                      svn_boolean_t must_exist, apr_pool_t *pool)
 {
-  return svn_repos__authz_read(authz_p, file, must_exist, FALSE, NULL, pool);
+  return svn_repos__authz_read(authz_p, file, NULL, must_exist,
+                               FALSE, NULL, pool);
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/dump.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Sat Feb 23 01:25:38 2013
@@ -1442,10 +1442,10 @@ svn_repos_verify_fs2(svn_repos_t *repos,
         = svn_repos_notify_create(svn_repos_notify_verify_struc_rev, pool);
     }
 
-  /* Verify global/auxiliary data and backend-specific data first. */
-  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+  /* Verify global metadata and backend-specific data first. */
+  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), start_rev, end_rev,
                         verify_notify, verify_notify_baton,
-                        start_rev, end_rev, pool));
+                        cancel_func, cancel_baton, pool));
 
   for (rev = start_rev; rev <= end_rev; rev++)
     {

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c Sat Feb 23 01:25:38 2013
@@ -687,18 +687,13 @@ delta_files(report_baton_t *b, void *fil
     {
       SVN_ERR(get_source_root(b, &s_root, s_rev));
 
-      /* Is this delta calculation worth our time?  If we are ignoring
-         ancestry, then our editor implementor isn't concerned by the
-         theoretical differences between "has contents which have not
-         changed with respect to" and "has the same actual contents
-         as".  We'll do everything we can to avoid transmitting even
-         an empty text-delta in that case.  */
-      if (b->ignore_ancestry)
-        SVN_ERR(svn_repos__compare_files(&changed, b->t_root, t_path,
-                                         s_root, s_path, pool));
-      else
-        SVN_ERR(svn_fs_contents_changed(&changed, b->t_root, t_path, s_root,
-                                        s_path, pool));
+      /* We're not interested in the theoretical difference between "has
+         contents which have not changed with respect to" and "has the same
+         actual contents as" when sending text-deltas.  If we know the
+         delta is an empty one, we avoiding sending it in either case. */
+      SVN_ERR(svn_repos__compare_files(&changed, b->t_root, t_path,
+                                       s_root, s_path, pool));
+
       if (!changed)
         return SVN_NO_ERROR;
 

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.c Sat Feb 23 01:25:38 2013
@@ -1025,6 +1025,12 @@ create_conf(svn_repos_t *repos, apr_pool
 "### no path-based access control is done."                                  NL
 "### Uncomment the line below to use the default authorization file."        NL
 "# authz-db = " SVN_REPOS__CONF_AUTHZ                                        NL
+"### The groups-db option controls the location of the groups file."         NL
+"### Unless you specify a path starting with a /, the file's location is"    NL
+"### relative to the directory containing this file.  The specified path"    NL
+"### may be a repository relative URL (^/) or an absolute file:// URL to a"  NL
+"### text file in a Subversion repository."                                  NL
+"# groups-db = " SVN_REPOS__CONF_GROUPS                                      NL
 "### This option specifies the authentication realm of the repository."      NL
 "### If two repositories have the same authentication realm, they should"    NL
 "### have the same password database, and vice versa.  The default realm"    NL
@@ -1825,6 +1831,62 @@ svn_repos_recover4(const char *path,
   return SVN_NO_ERROR;
 }
 
+struct freeze_baton_t {
+  apr_array_header_t *paths;
+  int counter;
+  svn_error_t *(*freeze_body)(void *, apr_pool_t *);
+  void *baton;
+};
+
+static svn_error_t *
+multi_freeze(void *baton,
+             apr_pool_t *pool)
+{
+  struct freeze_baton_t *fb = baton;
+
+  if (fb->counter == fb->paths->nelts)
+    {
+      SVN_ERR(fb->freeze_body(fb->baton, pool));
+      return SVN_NO_ERROR;
+    }
+  else
+    {
+      /* Using a subpool as the only way to unlock the repos lock used
+         by BDB is to clear the pool used to take the lock. */
+      apr_pool_t *subpool = svn_pool_create(pool);
+      const char *path = APR_ARRAY_IDX(fb->paths, fb->counter, const char *);
+      svn_repos_t *repos;
+
+      ++fb->counter;
+
+      SVN_ERR(get_repos(&repos, path,
+                        TRUE  /* exclusive (only applies to BDB) */,
+                        FALSE /* non-blocking */,
+                        FALSE /* open-fs */,
+                        NULL, subpool));
+
+
+      if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0)
+        {
+          svn_error_t *err = multi_freeze(fb, subpool);
+
+          svn_pool_destroy(subpool);
+
+          return err;
+        }
+      else
+        {
+          SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, NULL, subpool));
+          SVN_ERR(svn_fs_freeze(svn_repos_fs(repos), multi_freeze, fb,
+                                subpool));
+        }
+
+      svn_pool_destroy(subpool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* For BDB we fall back on BDB's repos layer lock which means that the
    repository is unreadable while frozen.
 
@@ -1832,36 +1894,19 @@ svn_repos_recover4(const char *path,
    and an SQLite reserved lock which means the repository is readable
    while frozen. */
 svn_error_t *
-svn_repos_freeze(const char *path,
+svn_repos_freeze(apr_array_header_t *paths,
                  svn_error_t *(*freeze_body)(void *, apr_pool_t *),
                  void *baton,
                  apr_pool_t *pool)
 {
-  svn_repos_t *repos;
+  struct freeze_baton_t fb;
 
-  /* Using a subpool as the only way to unlock the repos lock used by
-     BDB is to clear the pool used to take the lock. */
-  apr_pool_t *subpool = svn_pool_create(pool);
-
-  SVN_ERR(get_repos(&repos, path,
-                    TRUE  /* exclusive */,
-                    FALSE /* non-blocking */,
-                    FALSE /* open-fs */,
-                    NULL, subpool));
+  fb.paths = paths;
+  fb.counter = 0;
+  fb.freeze_body = freeze_body;
+  fb.baton = baton;
 
-  if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0)
-    {
-      svn_error_t *err = freeze_body(baton, subpool);
-      svn_pool_destroy(subpool);
-      return err;
-    }
-  else
-    {
-      SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, NULL, subpool));
-      SVN_ERR(svn_fs_freeze(svn_repos_fs(repos), freeze_body, baton, subpool));
-    }
-
-  svn_pool_destroy(subpool);
+  SVN_ERR(multi_freeze(&fb, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.h Sat Feb 23 01:25:38 2013
@@ -95,10 +95,11 @@ extern "C" {
 #define SVN_REPOS__CONF_SVNSERVE_CONF "svnserve.conf"
 
 /* In the svnserve default configuration, these are the suggested
-   locations for the passwd and authz files (in the repository conf
-   directory), and we put example templates there. */
+   locations for the passwd, authz and groups files (in the repository
+   conf directory), and we put example templates there. */
 #define SVN_REPOS__CONF_PASSWD "passwd"
 #define SVN_REPOS__CONF_AUTHZ "authz"
+#define SVN_REPOS__CONF_GROUPS "groups"
 
 /* The Repository object, created by svn_repos_open2() and
    svn_repos_create(). */
@@ -307,22 +308,24 @@ svn_repos__hooks_post_unlock(svn_repos_t
 /*** Authz Functions ***/
 
 /* Read authz configuration data from PATH into *AUTHZ_P, allocated
-   in POOL.
-  
-   PATH may be a file or a registry path and iff ACCEPT_URLS is set
-   it may also be a repos relative url or an absolute file url.  When
+   in POOL.  If GROUPS_PATH is set, use the global groups parsed from it.
+
+   PATH and GROUPS_PATH may be a file or a registry path and iff ACCEPT_URLS
+   is set it may also be a repos relative url or an absolute file url.  When
    ACCEPT_URLS is FALSE REPOS_ROOT can be NULL.
-  
-   If PATH is not a valid authz rule file, then return 
+
+   If PATH or GROUPS_PATH is not a valid authz rule file, then return 
    SVN_AUTHZ_INVALID_CONFIG.  The contents of *AUTHZ_P is then
-   undefined.  If MUST_EXIST is TRUE, a missing authz file is also
-   an error.
-  
+   undefined.  If MUST_EXIST is TRUE, a missing authz or global groups file
+   is also an error.
+
    If PATH is a repos relative URL then REPOS_ROOT must be set to
-   the root of the repository the authz configuration will be used with. */
+   the root of the repository the authz configuration will be used with.
+   The same applies to GROUPS_PATH if it is being used. */
 svn_error_t *
 svn_repos__authz_read(svn_authz_t **authz_p,
                       const char *path,
+                      const char *groups_path,
                       svn_boolean_t must_exist,
                       svn_boolean_t accept_urls,
                       const char *repos_root,