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 2012/11/23 02:12:45 UTC

svn commit: r1412731 [4/10] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ contrib/client-side/svnmerge/ contrib/server-side/svncutter/ notes/ subversion/ subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/ subver...

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=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c Fri Nov 23 01:12:18 2012
@@ -35,6 +35,7 @@
 #include "diff.h"
 #include "svn_private_config.h"
 #include "private/svn_adler32.h"
+#include "private/svn_diff_private.h"
 
 typedef struct source_tokens_t
 {
@@ -363,6 +364,9 @@ typedef struct unified_output_baton_t
   /* The delimiters of the hunk header, '@@' for text hunks and '##' for
    * property hunks. */
   const char *hunk_delimiter;
+  /* The string to print after a line that does not end with a newline.
+   * It must start with a '\'.  Typically "\ No newline at end of file". */
+  const char *no_newline_string;
 
   /* Pool for allocation of temporary memory in the callbacks
      Should be cleared on entry of each iteration of a callback */
@@ -418,13 +422,10 @@ output_unified_token_range(output_baton_
   if (past_last == source->tokens->nelts && source->ends_without_eol)
     {
       const char *out_str;
-      SVN_ERR(svn_utf_cstring_from_utf8_ex2
-              (&out_str,
-               /* The string below is intentionally not marked for translation:
-                  it's vital to correct operation of the diff(1)/patch(1)
-                  program pair. */
-               APR_EOL_STR "\\ No newline at end of file" APR_EOL_STR,
-               btn->header_encoding, btn->pool));
+
+      SVN_ERR(svn_utf_cstring_from_utf8_ex2(
+                &out_str, btn->no_newline_string,
+                btn->header_encoding, btn->pool));
       svn_stringbuf_appendcstr(btn->hunk, out_str);
     }
 
@@ -459,45 +460,19 @@ output_unified_flush_hunk(output_baton_t
   if (hunk_delimiter == NULL)
     hunk_delimiter = "@@";
 
-  /* Write the hunk header */
+  /* Convert our 0-based line numbers into unidiff 1-based numbers */
   if (baton->hunk_length[0] > 0)
-    /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[0]++;
-  SVN_ERR(svn_stream_printf_from_utf8(
-            baton->output_stream, baton->header_encoding,
-            baton->pool,
-            /* Hunk length 1 is implied, don't show the
-               length field if we have a hunk that long */
-            (baton->hunk_length[0] == 1)
-            ? ("%s -%" APR_OFF_T_FMT)
-            : ("%s -%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT),
-            hunk_delimiter,
-            baton->hunk_start[0], baton->hunk_length[0]));
-
   if (baton->hunk_length[1] > 0)
-    /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[1]++;
 
-
-  /* Hunk length 1 is implied, don't show the
-     length field if we have a hunk that long */
-  if (baton->hunk_length[1] == 1)
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(
-                baton->output_stream, baton->header_encoding,
-                baton->pool,
-                " +%" APR_OFF_T_FMT " %s" APR_EOL_STR,
-                baton->hunk_start[1], hunk_delimiter));
-    }
-  else
-    {
-      SVN_ERR(svn_stream_printf_from_utf8(
-                baton->output_stream, baton->header_encoding,
-                baton->pool,
-                " +%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT " %s" APR_EOL_STR,
-                baton->hunk_start[1], baton->hunk_length[1],
-                hunk_delimiter));
-    }
+  /* 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],
+            NULL /* hunk_extra_context */,
+            baton->pool));
 
   hunk_len = baton->hunk->len;
   SVN_ERR(svn_stream_write(baton->output_stream,
@@ -586,6 +561,10 @@ svn_diff_mem_string_output_unified2(svn_
       baton.header_encoding = header_encoding;
       baton.hunk = svn_stringbuf_create_empty(pool);
       baton.hunk_delimiter = hunk_delimiter;
+      baton.no_newline_string
+        = (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
+          ? APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR
+          : APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_PROPERTY APR_EOL_STR;
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_context]), " ",
@@ -602,12 +581,9 @@ svn_diff_mem_string_output_unified2(svn_
 
       if (with_diff_header)
         {
-          SVN_ERR(svn_stream_printf_from_utf8(output_stream,
-                                              header_encoding, pool,
-                                              "--- %s" APR_EOL_STR
-                                              "+++ %s" APR_EOL_STR,
-                                              original_header,
-                                              modified_header));
+          SVN_ERR(svn_diff__unidiff_write_header(
+                    output_stream, header_encoding,
+                    original_header, modified_header, pool));
         }
 
       SVN_ERR(svn_diff_output(diff, &baton,

Modified: subversion/branches/ev2-export/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_diff/parse-diff.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_diff/parse-diff.c Fri Nov 23 01:12:18 2012
@@ -555,15 +555,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
       pos = 0;
       SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
 
-      /* Lines starting with a backslash are comments, such as
-       * "\ No newline at end of file". */
+      /* Lines starting with a backslash indicate a missing EOL:
+       * "\ No newline at end of file" or "end of property". */
       if (line->data[0] == '\\')
         {
-          if (in_hunk &&
-              ((!*is_property &&
-                strcmp(line->data, "\\ No newline at end of file") == 0) ||
-               (*is_property &&
-                strcmp(line->data, "\\ No newline at end of property") == 0)))
+          if (in_hunk)
             {
               char eolbuf[2];
               apr_size_t len;

Modified: subversion/branches/ev2-export/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_diff/util.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_diff/util.c Fri Nov 23 01:12:18 2012
@@ -25,14 +25,23 @@
 #include <apr.h>
 #include <apr_general.h>
 
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_props.h"
+#include "svn_mergeinfo.h"
 #include "svn_error.h"
 #include "svn_diff.h"
 #include "svn_types.h"
 #include "svn_ctype.h"
+#include "svn_utf.h"
 #include "svn_version.h"
 
+#include "private/svn_diff_private.h"
 #include "diff.h"
 
+#include "svn_private_config.h"
+
+
 svn_boolean_t
 svn_diff_contains_conflicts(svn_diff_t *diff)
 {
@@ -332,6 +341,247 @@ svn_diff__normalize_buffer(char **tgt,
 #undef COPY_INCLUDED_SECTION
 }
 
+svn_error_t *
+svn_diff__unified_append_no_newline_msg(svn_stringbuf_t *stringbuf,
+                                        const char *header_encoding,
+                                        apr_pool_t *scratch_pool)
+{
+  const char *out_str;
+
+  SVN_ERR(svn_utf_cstring_from_utf8_ex2(
+            &out_str,
+            APR_EOL_STR
+            SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR,
+            header_encoding, scratch_pool));
+  svn_stringbuf_appendcstr(stringbuf, out_str);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__unified_write_hunk_header(svn_stream_t *output_stream,
+                                    const char *header_encoding,
+                                    const char *hunk_delimiter,
+                                    apr_off_t old_start,
+                                    apr_off_t old_length,
+                                    apr_off_t new_start,
+                                    apr_off_t new_length,
+                                    const char *hunk_extra_context,
+                                    apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      "%s -%" APR_OFF_T_FMT,
+                                      hunk_delimiter, old_start));
+  /* If the hunk length is 1, suppress the number of lines in the hunk
+   * (it is 1 implicitly) */
+  if (old_length != 1)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                          scratch_pool,
+                                          ",%" APR_OFF_T_FMT, old_length));
+    }
+
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      " +%" APR_OFF_T_FMT, new_start));
+  if (new_length != 1)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                          scratch_pool,
+                                          ",%" APR_OFF_T_FMT, new_length));
+    }
+
+  if (hunk_extra_context == NULL)
+      hunk_extra_context = "";
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      " %s%s%s" APR_EOL_STR,
+                                      hunk_delimiter,
+                                      hunk_extra_context[0] ? " " : "",
+                                      hunk_extra_context));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__unidiff_write_header(svn_stream_t *output_stream,
+                               const char *header_encoding,
+                               const char *old_header,
+                               const char *new_header,
+                               apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_stream_printf_from_utf8(output_stream, header_encoding,
+                                      scratch_pool,
+                                      "--- %s" APR_EOL_STR
+                                      "+++ %s" APR_EOL_STR,
+                                      old_header,
+                                      new_header));
+  return SVN_NO_ERROR;
+}
+
+/* A helper function for display_prop_diffs.  Output the differences between
+   the mergeinfo stored in ORIG_MERGEINFO_VAL and NEW_MERGEINFO_VAL in a
+   human-readable form to OUTSTREAM, using ENCODING.  Use POOL for temporary
+   allocations. */
+static svn_error_t *
+display_mergeinfo_diff(const char *old_mergeinfo_val,
+                       const char *new_mergeinfo_val,
+                       const char *encoding,
+                       svn_stream_t *outstream,
+                       apr_pool_t *pool)
+{
+  apr_hash_t *old_mergeinfo_hash, *new_mergeinfo_hash, *added, *deleted;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_hash_index_t *hi;
+
+  if (old_mergeinfo_val)
+    SVN_ERR(svn_mergeinfo_parse(&old_mergeinfo_hash, old_mergeinfo_val, pool));
+  else
+    old_mergeinfo_hash = NULL;
+
+  if (new_mergeinfo_val)
+    SVN_ERR(svn_mergeinfo_parse(&new_mergeinfo_hash, new_mergeinfo_val, pool));
+  else
+    new_mergeinfo_hash = NULL;
+
+  SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, old_mergeinfo_hash,
+                              new_mergeinfo_hash,
+                              TRUE, pool, pool));
+
+  for (hi = apr_hash_first(pool, deleted);
+       hi; hi = apr_hash_next(hi))
+    {
+      const char *from_path = svn__apr_hash_index_key(hi);
+      svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi);
+      svn_string_t *merge_revstr;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray,
+                                      iterpool));
+
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          _("   Reverse-merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
+    }
+
+  for (hi = apr_hash_first(pool, added);
+       hi; hi = apr_hash_next(hi))
+    {
+      const char *from_path = svn__apr_hash_index_key(hi);
+      svn_rangelist_t *merge_revarray = svn__apr_hash_index_val(hi);
+      svn_string_t *merge_revstr;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray,
+                                      iterpool));
+
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          _("   Merged %s:r%s%s"),
+                                          from_path, merge_revstr->data,
+                                          APR_EOL_STR));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff__display_prop_diffs(svn_stream_t *outstream,
+                             const char *encoding,
+                             const apr_array_header_t *propchanges,
+                             apr_hash_t *original_props,
+                             svn_boolean_t pretty_print_mergeinfo,
+                             apr_pool_t *pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  int i;
+
+  for (i = 0; i < propchanges->nelts; i++)
+    {
+      const char *action;
+      const svn_string_t *original_value;
+      const svn_prop_t *propchange
+        = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
+
+      if (original_props)
+        original_value = apr_hash_get(original_props,
+                                      propchange->name, APR_HASH_KEY_STRING);
+      else
+        original_value = NULL;
+
+      /* If the property doesn't exist on either side, or if it exists
+         with the same value, skip it.  This can happen if the client is
+         hitting an old mod_dav_svn server that doesn't understand the
+         "send-all" REPORT style. */
+      if ((! (original_value || propchange->value))
+          || (original_value && propchange->value
+              && svn_string_compare(original_value, propchange->value)))
+        continue;
+
+      svn_pool_clear(iterpool);
+
+      if (! original_value)
+        action = "Added";
+      else if (! propchange->value)
+        action = "Deleted";
+      else
+        action = "Modified";
+      SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, iterpool,
+                                          "%s: %s%s", action,
+                                          propchange->name, APR_EOL_STR));
+
+      if (pretty_print_mergeinfo
+          && strcmp(propchange->name, SVN_PROP_MERGEINFO) == 0)
+        {
+          const char *orig = original_value ? original_value->data : NULL;
+          const char *val = propchange->value ? propchange->value->data : NULL;
+          svn_error_t *err = display_mergeinfo_diff(orig, val, encoding,
+                                                    outstream, iterpool);
+
+          /* Issue #3896: If we can't pretty-print mergeinfo differences
+             because invalid mergeinfo is present, then don't let the diff
+             fail, just print the diff as any other property. */
+          if (err && err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
+            {
+              svn_error_clear(err);
+            }
+          else
+            {
+              SVN_ERR(err);
+              continue;
+            }
+        }
+
+      {
+        svn_diff_t *diff;
+        svn_diff_file_options_t options = { 0 };
+        const svn_string_t *orig
+          = original_value ? original_value
+                           : svn_string_create_empty(iterpool);
+        const svn_string_t *val
+          = propchange->value ? propchange->value
+                              : svn_string_create_empty(iterpool);
+
+        SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options,
+                                         iterpool));
+
+        /* UNIX patch will try to apply a diff even if the diff header
+         * is missing. It tries to be helpful by asking the user for a
+         * target filename when it can't determine the target filename
+         * from the diff header. But there usually are no files which
+         * UNIX patch could apply the property diff to, so we use "##"
+         * instead of "@@" as the default hunk delimiter for property diffs.
+         * We also supress the diff header. */
+        SVN_ERR(svn_diff_mem_string_output_unified2(
+                  outstream, diff, FALSE /* no header */, "##", NULL, NULL,
+                  encoding, orig, val, iterpool));
+      }
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Return the library version number. */
 const svn_version_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c Fri Nov 23 01:12:18 2012
@@ -83,11 +83,19 @@ read_config(svn_memcache_t **memcache_p,
    * Revprop caching significantly speeds up operations like
    * svn ls -v. However, it requires synchronization that may
    * not be available or efficient in the current server setup.
+   * 
+   * If the caller chose option "2", enable revprop caching if
+   * the required API support is there to make it efficient.
    */
-  *cache_revprops
-    = svn_hash__get_bool(fs->config,
-                         SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                         FALSE);
+  if (strcmp(svn_hash__get_cstring(fs->config,
+                                   SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+                                   ""), "2"))
+    *cache_revprops
+      = svn_hash__get_bool(fs->config,
+                          SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+                          FALSE);
+  else
+    *cache_revprops = svn_named_atomic__is_efficient();
 
   return svn_config_get_bool(ffd->config, fail_stop,
                              CONFIG_SECTION_CACHES, CONFIG_OPTION_FAIL_STOP,

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h Fri Nov 23 01:12:18 2012
@@ -180,6 +180,7 @@ typedef struct fs_fs_shared_txn_data_t
    per file.  On Windows apr implements the locking as per file handle
    locks, so we don't have to add our own mutex for just in-process
    synchronization. */
+/* Compare ../libsvn_subr/named_atomic.c:USE_THREAD_MUTEX */
 #if APR_HAS_THREADS && !defined(WIN32)
 #define SVN_FS_FS__USE_LOCK_MUTEX 1
 #else

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=1412731&r1=1412730&r2=1412731&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 Fri Nov 23 01:12:18 2012
@@ -360,6 +360,18 @@ path_txn_dir(svn_fs_t *fs, const char *t
                               NULL);
 }
 
+/* Return the name of the sha1->rep mapping file in transaction TXN_ID
+ * within FS for the given SHA1 checksum.  Use POOL for allocations.
+ */
+static APR_INLINE const char *
+path_txn_sha1(svn_fs_t *fs, const char *txn_id, svn_checksum_t *sha1,
+              apr_pool_t *pool)
+{
+  return svn_dirent_join(path_txn_dir(fs, txn_id, pool),
+                         svn_checksum_to_cstring(sha1, pool),
+                         pool);
+}
+
 static APR_INLINE const char *
 path_txn_changes(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
 {
@@ -1273,9 +1285,9 @@ write_config(svn_fs_t *fs,
 "###"                                                                        NL
 "### The following parameter enables deltification for properties on files"  NL
 "### and directories.  Overall, this is a minor tuning option but can save"  NL
-"### some disk space if frequently merge or if you frequently change node"   NL
+"### some disk space if you merge frequently or frequently change node"      NL
 "### properties.  You should not activate this if rep-sharing has been"      NL
-"### disabled."                                                              NL
+"### disabled because this may result in a net increase in repository size." NL
 "### property deltification is disabled by default."                         NL
 "# " CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION " = false"                     NL
 "###"                                                                        NL
@@ -2613,10 +2625,6 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_file_t *noderev_file;
   const char *txn_id = svn_fs_fs__id_txn_id(id);
-  const char *sha1 = ffd->rep_sharing_allowed && noderev->data_rep
-                   ? svn_checksum_to_cstring(noderev->data_rep->sha1_checksum,
-                                             pool)
-                   : NULL;
 
   noderev->is_fresh_txn_root = fresh_txn_root;
 
@@ -2637,13 +2645,31 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
 
   SVN_ERR(svn_io_file_close(noderev_file, pool));
 
+  return SVN_NO_ERROR;
+}
+
+/* For the in-transaction NODEREV within FS, write the sha1->rep mapping
+ * file in the respective transaction, if rep sharing has been enabled etc.
+ * Use POOL for temporary allocations.
+ */
+static svn_error_t *
+store_sha1_rep_mapping(svn_fs_t *fs,
+                       node_revision_t *noderev,
+                       apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
   /* if rep sharing has been enabled and the noderev has a data rep and
    * its SHA-1 is known, store the rep struct under its SHA1. */
-  if (sha1)
+  if (   ffd->rep_sharing_allowed
+      && noderev->data_rep
+      && noderev->data_rep->sha1_checksum)
     {
       apr_file_t *rep_file;
-      const char *file_name = svn_dirent_join(path_txn_dir(fs, txn_id, pool),
-                                              sha1, pool);
+      const char *file_name = path_txn_sha1(fs,
+                                            svn_fs_fs__id_txn_id(noderev->id),
+                                            noderev->data_rep->sha1_checksum,
+                                            pool);
       const char *rep_string = representation_string(noderev->data_rep,
                                                      ffd->format,
                                                      (noderev->kind
@@ -3667,7 +3693,7 @@ parse_packed_revprops(svn_fs_t *fs,
 
       /* read & check the serialized size */
       SVN_ERR(read_number_from_stream(&size, NULL, stream, iterpool));
-      if (size + offset > revprops->packed_revprops->len)
+      if (size + offset > (apr_int64_t)revprops->packed_revprops->len)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                         _("Packed revprop size exceeds pack file size"));
 
@@ -4822,8 +4848,8 @@ rep_read_get_baton(struct rep_read_baton
 /* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta
    window into *NWIN. */
 static svn_error_t *
-read_window(svn_txdelta_window_t **nwin, int this_chunk, struct rep_state *rs,
-            apr_pool_t *pool)
+read_delta_window(svn_txdelta_window_t **nwin, int this_chunk,
+                  struct rep_state *rs, apr_pool_t *pool)
 {
   svn_stream_t *stream;
   svn_boolean_t is_cached;
@@ -4870,6 +4896,27 @@ read_window(svn_txdelta_window_t **nwin,
   return set_cached_window(*nwin, rs, old_offset, pool);
 }
 
+/* Read SIZE bytes from the representation RS and return it in *NWIN. */
+static svn_error_t *
+read_plain_window(svn_stringbuf_t **nwin, struct rep_state *rs,
+                  apr_size_t size, apr_pool_t *pool)
+{
+  /* RS->FILE may be shared between RS instances -> make sure we point
+   * to the right data. */
+  SVN_ERR(svn_io_file_seek(rs->file, APR_SET, &rs->off, pool));
+
+  /* Read the plain data. */
+  *nwin = svn_stringbuf_create_ensure(size, pool);
+  SVN_ERR(svn_io_file_read_full2(rs->file, (*nwin)->data, size, NULL, NULL,
+                                 pool));
+  (*nwin)->data[size] = 0;
+
+  /* Update RS. */
+  rs->off += (apr_off_t)size;
+
+  return SVN_NO_ERROR;
+}
+
 /* Get the undeltified window that is a result of combining all deltas
    from the current desired representation identified in *RB with its
    base representation.  Store the window in *RESULT. */
@@ -4893,7 +4940,7 @@ get_combined_window(svn_stringbuf_t **re
   for (i = 0; i < rb->rs_list->nelts; ++i)
     {
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
-      SVN_ERR(read_window(&window, rb->chunk_index, rs, window_pool));
+      SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool));
 
       APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
       if (window->src_ops == 0)
@@ -4907,11 +4954,20 @@ get_combined_window(svn_stringbuf_t **re
   pool = svn_pool_create(rb->pool);
   for (--i; i >= 0; --i)
     {
+
       rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
       window = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
 
-      /* Combine this window with the current one. */
+      /* Maybe, we've got a PLAIN start representation.  If we do, read
+         as much data from it as the needed for the txdelta window's source
+         view.
+         Note that BUF / SOURCE may only be NULL in the first iteration. */
       source = buf;
+      if (source == NULL && rb->src_state != NULL)
+        SVN_ERR(read_plain_window(&source, rb->src_state, window->sview_len,
+                                  pool));
+
+      /* Combine this window with the current one. */
       new_pool = svn_pool_create(rb->pool);
       buf = svn_stringbuf_create_ensure(window->tview_len, new_pool);
       buf->len = window->tview_len;
@@ -4970,7 +5026,6 @@ get_contents(struct rep_read_baton *rb,
              apr_size_t *len)
 {
   apr_size_t copy_len, remaining = *len;
-  apr_off_t offset;
   char *cur = buf;
   struct rep_state *rs;
 
@@ -4986,10 +5041,10 @@ get_contents(struct rep_read_baton *rb,
           /* We got the desired rep directly from the cache.
              This is where we need the pseudo rep_state created
              by build_rep_list(). */
-          offset = rs->off - rs->start;
+          apr_size_t offset = (apr_size_t)(rs->off - rs->start);
           if (copy_len + offset > rb->base_window->len)
             copy_len = offset < rb->base_window->len
-                     ? (apr_size_t)(rb->base_window->len - offset)
+                     ? rb->base_window->len - offset
                      : 0ul;
 
           memcpy (cur, rb->base_window->data + offset, copy_len);
@@ -5188,7 +5243,7 @@ delta_read_next_window(svn_txdelta_windo
       return SVN_NO_ERROR;
     }
 
-  return read_window(window, drb->rs->chunk_index, drb->rs, pool);
+  return read_delta_window(window, drb->rs->chunk_index, drb->rs, pool);
 }
 
 /* This implements the svn_txdelta_md5_digest_fn_t interface. */
@@ -7101,22 +7156,14 @@ rep_write_cleanup(void *data)
   
   /* Truncate and close the protorevfile. */
   err = svn_io_file_trunc(b->file, b->rep_offset, b->pool);
-  if (err)
-    {
-      apr_status_t rc = err->apr_err;
-      svn_error_clear(err);
-      return rc;
-    }
-  err = svn_io_file_close(b->file, b->pool);
-  if (err)
-    {
-      apr_status_t rc = err->apr_err;
-      svn_error_clear(err);
-      return rc;
-    }
+  err = svn_error_compose_create(err, svn_io_file_close(b->file, b->pool));
 
-  /* Remove our lock */
-  err = unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->pool);
+  /* Remove our lock regardless of any preceeding errors so that the 
+     being_written flag is always removed and stays consistent with the
+     file lock which will be removed no matter what since the pool is
+     going away. */
+  err = svn_error_compose_create(err, unlock_proto_rev(b->fs, txn_id,
+                                                       b->lockcookie, b->pool));
   if (err)
     {
       apr_status_t rc = err->apr_err;
@@ -7280,9 +7327,7 @@ get_shared_rep(representation_t **old_re
     {
       svn_node_kind_t kind;
       const char *file_name
-        = svn_dirent_join(path_txn_dir(fs, rep->txn_id, pool),
-                          svn_checksum_to_cstring(rep->sha1_checksum, pool),
-                          pool);
+        = path_txn_sha1(fs, rep->txn_id, rep->sha1_checksum, pool);
 
       /* in our txn, is there a rep file named with the wanted SHA1?
          If so, read it and use that rep.
@@ -7372,6 +7417,8 @@ rep_write_contents_close(void *baton)
   /* Write out the new node-rev information. */
   SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev, FALSE,
                                        b->pool));
+  if (!old_rep)
+    SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->pool));
 
   SVN_ERR(svn_io_file_close(b->file, b->pool));
   SVN_ERR(unlock_proto_rev(b->fs, rep->txn_id, b->lockcookie, b->pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure Fri Nov 23 01:12:18 2012
@@ -526,6 +526,7 @@ A transaction directory has the followin
   node.<nid>.<cid>           New node-rev data for node
   node.<nid>.<cid>.props     Props for new node-rev, if changed
   node.<nid>.<cid>.children  Directory contents for node-rev
+  <sha1>                     Text representation of that sha1
 
 In FS formats 1 and 2, it also contains:
 
@@ -543,6 +544,11 @@ The two kinds of props files are all in 
 file will always be present.  The "node.<nid>.<cid>.props" file will
 only be present if the node-rev properties have been changed.
 
+The <sha1> files have been introduced in FS format 6. Their content
+is that of text rep references: "<rev> <offset> <length> <size> <digest>"
+They will be written for text reps in the current transaction and be
+used to eliminate duplicate reps within that transaction.
+
 The "next-ids" file contains a single line "<next-temp-node-id>
 <next-temp-copy-id>\n" giving the next temporary node-ID and copy-ID
 assignments (without the leading underscores).  The next node-ID is

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/split_url.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/split_url.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/split_url.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/split_url.c Fri Nov 23 01:12:18 2012
@@ -23,14 +23,13 @@
 
 #include "ra_local.h"
 #include <string.h>
-#include "svn_path.h"
 #include "svn_dirent_uri.h"
 #include "svn_private_config.h"
 
 
 svn_error_t *
 svn_ra_local__split_URL(svn_repos_t **repos,
-                        const char **repos_url,
+                        const char **repos_root_url,
                         const char **fs_path,
                         const char *URL,
                         apr_pool_t *pool)
@@ -38,7 +37,6 @@ svn_ra_local__split_URL(svn_repos_t **re
   svn_error_t *err = SVN_NO_ERROR;
   const char *repos_dirent;
   const char *repos_root_dirent;
-  svn_stringbuf_t *urlbuf;
 
   SVN_ERR(svn_uri_get_dirent_from_file_url(&repos_dirent, URL, pool));
 
@@ -61,18 +59,18 @@ svn_ra_local__split_URL(svn_repos_t **re
     SVN_ERR(svn_repos_remember_client_capabilities(*repos, caps));
   }
 
+  /* = apr_pstrcat(pool,
+                   "/",
+                   svn_dirent_skip_ancestor(repos_root_dirent, repos_dirent),
+                   (const char *)NULL */
   *fs_path = &repos_dirent[strlen(repos_root_dirent)];
 
   if (**fs_path == '\0')
     *fs_path = "/";
 
-  /* Remove the path components in *fs_path from the original URL, to get
-     the URL to the repository root. */
-  urlbuf = svn_stringbuf_create(URL, pool);
-  svn_path_remove_components(urlbuf,
-                             svn_path_component_count(repos_dirent)
-                             - svn_path_component_count(repos_root_dirent));
-  *repos_url = urlbuf->data;
+  /* Create a url to the repository root. */
+  SVN_ERR(svn_uri_get_file_url_from_dirent(repos_root_url, repos_root_dirent,
+                                           pool));
 
   /* Configure hook script environment variables. */
   SVN_ERR(svn_repos_hooks_setenv(*repos, NULL, pool, pool));

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=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c Fri Nov 23 01:12:18 2012
@@ -468,10 +468,6 @@ setup_propfind_headers(serf_bucket_t *he
 {
   propfind_context_t *ctx = setup_baton;
 
-  if (ctx->sess->using_compression)
-    {
-      serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
-    }
   serf_bucket_headers_setn(headers, "Depth", ctx->depth);
   if (ctx->label)
     {

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h Fri Nov 23 01:12:18 2012
@@ -57,7 +57,8 @@ extern "C" {
 #define UNUSED_CTX(x) ((void)(x))
 
 /** Our User-Agent string. */
-#define USER_AGENT "SVN/" SVN_VER_NUMBER " serf/" \
+#define USER_AGENT "SVN/" SVN_VER_NUMBER " (" SVN_BUILD_TARGET ")" \
+                   " serf/" \
                    APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
                    APR_STRINGIFY(SERF_MINOR_VERSION) "." \
                    APR_STRINGIFY(SERF_PATCH_VERSION)
@@ -188,7 +189,7 @@ struct svn_ra_serf__session_t {
   const char *uuid;
 
   /* Connection timeout value */
-  apr_short_interval_time_t timeout;
+  apr_interval_time_t timeout;
 
   /* HTTPv1 flags */
   svn_tristate_t supports_deadprop_count;
@@ -392,6 +393,11 @@ typedef struct svn_ra_serf__handler_t {
   /* The content-type of the request body. */
   const char *body_type;
 
+  /* If TRUE then default Accept-Encoding request header is not configured for
+     request. If FALSE then 'gzip' accept encoding will be used if compression
+     enabled. */
+  svn_boolean_t custom_accept_encoding;
+
   /* Has the request/response been completed?  */
   svn_boolean_t done;
 
@@ -953,6 +959,7 @@ svn_ra_serf__xml_pop_state(svn_ra_serf__
 
 svn_error_t *
 svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
+                             svn_boolean_t *network_eof,
                              apr_pool_t *scratch_pool);
 
 

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/replay.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/replay.c Fri Nov 23 01:12:18 2012
@@ -732,7 +732,7 @@ svn_ra_serf__replay_range(svn_ra_session
   svn_revnum_t rev = start_revision;
   const char *report_target;
   int active_reports = 0;
-  apr_short_interval_time_t waittime_left = session->timeout;
+  apr_interval_time_t waittime_left = session->timeout;
 
   SVN_ERR(svn_ra_serf__report_resource(&report_target, session, NULL, pool));
 
@@ -873,14 +873,17 @@ svn_ra_serf__replay_range(svn_ra_session
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+          if (session->timeout)
             {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c Fri Nov 23 01:12:18 2012
@@ -131,7 +131,11 @@ load_http_auth_types(apr_pool_t *pool, s
 
   return SVN_NO_ERROR;
 }
-#define DEFAULT_HTTP_TIMEOUT 3600
+
+/* Default HTTP timeout (in seconds); overridden by the 'http-timeout'
+   runtime configuration variable. */
+#define DEFAULT_HTTP_TIMEOUT 600
+
 static svn_error_t *
 load_config(svn_ra_serf__session_t *session,
             apr_hash_t *config_hash,
@@ -253,6 +257,7 @@ load_config(svn_ra_serf__session_t *sess
     }
 
   /* Parse the connection timeout value, if any. */
+  session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
   if (timeout_str)
     {
       char *endstr;
@@ -267,13 +272,7 @@ load_config(svn_ra_serf__session_t *sess
                                 _("Invalid config: negative timeout value"));
       session->timeout = apr_time_from_sec(timeout);
     }
-  else
-    session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT);
-
-  if (session->timeout < 0) /* Always true for DEFAULT_HTTP_TIMEOUT */
-    session->timeout = apr_time_from_sec(600); /* 10 min */
-
-  SVN_ERR_ASSERT(session->timeout > 0);
+  SVN_ERR_ASSERT(session->timeout >= 0);
 
   /* Convert the proxy port value, if any. */
   if (port_str)

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=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Fri Nov 23 01:12:18 2012
@@ -63,10 +63,15 @@
  */
 typedef enum report_state_e {
     NONE = 0,
+    INITIAL = 0,
+    UPDATE_REPORT,
+    TARGET_REVISION,
     OPEN_DIR,
     ADD_DIR,
+    ABSENT_DIR,
     OPEN_FILE,
     ADD_FILE,
+    ABSENT_FILE,
     PROP,
     IGNORE_PROP_NAME,
     NEED_PROP_NAME
@@ -85,8 +90,8 @@ typedef enum report_state_e {
    since network and parsing behavior (ie. it doesn't pause immediately)
    can make the measurements quite imprecise.
 
-   We measure outstanding requests as the sum of ACTIVE_FETCHES and
-   ACTIVE_PROPFINDS in the report_context_t structure.  */
+   We measure outstanding requests as the sum of NUM_ACTIVE_FETCHES and
+   NUM_ACTIVE_PROPFINDS in the report_context_t structure.  */
 #define REQUEST_COUNT_TO_PAUSE 1000
 #define REQUEST_COUNT_TO_RESUME 100
 
@@ -126,7 +131,7 @@ typedef struct report_dir_t
   /* Our base revision - SVN_INVALID_REVNUM if we're adding this dir. */
   svn_revnum_t base_rev;
 
-  /* controlling dir baton - this is only created in open_dir() */
+  /* controlling dir baton - this is only created in ensure_dir_opened() */
   void *dir_baton;
   apr_pool_t *dir_baton_pool;
 
@@ -342,13 +347,13 @@ struct report_context_t {
   report_dir_t *root_dir;
 
   /* number of pending GET requests */
-  unsigned int active_fetches;
+  unsigned int num_active_fetches;
 
   /* completed fetches (contains report_fetch_t) */
   svn_ra_serf__list_t *done_fetches;
 
   /* number of pending PROPFIND requests */
-  unsigned int active_propfinds;
+  unsigned int num_active_propfinds;
 
   /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
   svn_ra_serf__list_t *done_propfinds;
@@ -362,13 +367,155 @@ struct report_context_t {
   /* Are we done parsing the REPORT response? */
   svn_boolean_t done;
 
+  /* Did we receive all data from the network? */
+  svn_boolean_t report_received;
+
   /* Did we get a complete (non-truncated) report? */
   svn_boolean_t report_completed;
 
   /* The XML parser context for the REPORT response.  */
   svn_ra_serf__xml_parser_t *parser_ctx;
+
+  /* Did we close the root directory? */
+  svn_boolean_t closed_root;
 };
 
+
+#ifdef NOT_USED_YET
+
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t update_ttable[] = {
+  { INITIAL, S_, "update-report", UPDATE_REPORT,
+    FALSE, { NULL }, FALSE },
+
+  { UPDATE_REPORT, S_, "target-revision", TARGET_REVISION,
+    FALSE, { "rev", NULL }, TRUE },
+
+  { UPDATE_REPORT, S_, "open-directory", OPEN_DIR,
+    FALSE, { "rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "open-directory", OPEN_DIR,
+    FALSE, { "rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "add-directory", ADD_DIR,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { ADD_DIR, S_, "add-directory", ADD_DIR,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "open-file", OPEN_FILE,
+    FALSE, { "rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "add-file", ADD_FILE,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { ADD_DIR, S_, "add-file", ADD_FILE,
+    FALSE, { "rev", "name", "?copyfrom-path", "?copyfrom-rev", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "delete-entry", OPEN_FILE,
+    FALSE, { "?rev", "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "absent-directory", ABSENT_DIR,
+    FALSE, { "name", NULL }, TRUE },
+
+  { ADD_DIR, S_, "absent-directory", ABSENT_DIR,
+    FALSE, { "name", NULL }, TRUE },
+
+  { OPEN_DIR, S_, "absent-file", ABSENT_FILE,
+    FALSE, { "name", NULL }, TRUE },
+
+  { ADD_DIR, S_, "absent-file", ABSENT_FILE,
+    FALSE, { "name", NULL }, TRUE },
+
+  { 0 }
+};
+
+
+
+/* Conforms to svn_ra_serf__xml_opened_t  */
+static svn_error_t *
+update_opened(svn_ra_serf__xml_estate_t *xes,
+              void *baton,
+              int entered_state,
+              const svn_ra_serf__dav_props_t *tag,
+              apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  return SVN_NO_ERROR;
+}
+
+
+
+/* Conforms to svn_ra_serf__xml_closed_t  */
+static svn_error_t *
+update_closed(svn_ra_serf__xml_estate_t *xes,
+              void *baton,
+              int leaving_state,
+              const svn_string_t *cdata,
+              apr_hash_t *attrs,
+              apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  if (leaving_state == TARGET_REVISION)
+    {
+      const char *rev = apr_hash_get(attrs, "rev", APR_HASH_KEY_STRING);
+
+      SVN_ERR(ctx->update_editor->set_target_revision(ctx->update_baton,
+                                                      SVN_STR_TO_REV(rev),
+                                                      ctx->sess->pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Conforms to svn_ra_serf__xml_cdata_t  */
+static svn_error_t *
+update_cdata(svn_ra_serf__xml_estate_t *xes,
+             void *baton,
+             int current_state,
+             const char *data,
+             apr_size_t len,
+             apr_pool_t *scratch_pool)
+{
+  report_context_t *ctx = baton;
+
+  return SVN_NO_ERROR;
+}
+
+#endif /* NOT_USED_YET */
+
+
+/* Returns best connection for fetching files/properties. */
+static svn_ra_serf__connection_t *
+get_best_connection(report_context_t *ctx)
+{
+  svn_ra_serf__connection_t * conn;
+  int first_conn;
+
+  /* Skip the first connection if the REPORT response hasn't been completely
+     received yet. */
+  first_conn = ctx->report_received ? 0: 1;
+
+  if (ctx->sess->num_conns - first_conn == 1)
+    return ctx->sess->conns[first_conn];
+
+  /* Currently just cycle connections. In future we could store number of
+   * pending requests on each connection for better connection usage. */
+  conn = ctx->sess->conns[ctx->sess->cur_conn];
+
+  /* Switch our connection. */
+  ctx->sess->cur_conn++;
+
+  if (ctx->sess->cur_conn >= ctx->sess->num_conns)
+      ctx->sess->cur_conn = first_conn;
+
+  return conn;
+}
+
 
 /** Report state management helper **/
 
@@ -547,7 +694,7 @@ remove_dir_props(void *baton,
 /** Helpers to open and close directories */
 
 static svn_error_t*
-open_dir(report_dir_t *dir)
+ensure_dir_opened(report_dir_t *dir)
 {
   report_context_t *ctx = dir->report_context;
 
@@ -576,7 +723,7 @@ open_dir(report_dir_t *dir)
     }
   else
     {
-      SVN_ERR(open_dir(dir->parent_dir));
+      SVN_ERR(ensure_dir_opened(dir->parent_dir));
 
       dir->dir_baton_pool = svn_pool_create(dir->parent_dir->dir_baton_pool);
 
@@ -672,7 +819,7 @@ static svn_error_t *close_all_dirs(repor
 
   SVN_ERR_ASSERT(! dir->ref_count);
 
-  SVN_ERR(open_dir(dir));
+  SVN_ERR(ensure_dir_opened(dir));
 
   return close_dir(dir);
 }
@@ -817,7 +964,7 @@ open_updated_file(report_info_t *info,
   const svn_delta_editor_t *update_editor = ctx->update_editor;
 
   /* Ensure our parent is open. */
-  SVN_ERR(open_dir(info->dir));
+  SVN_ERR(ensure_dir_opened(info->dir));
   info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
 
   /* Expand our full name now if we haven't done so yet. */
@@ -1176,6 +1323,46 @@ handle_stream(serf_request_t *request,
   /* not reached */
 }
 
+/* Close the directory represented by DIR -- and any suitable parents
+   thereof -- if we are able to do so.  This is the case whenever:
+
+     - there are no remaining open items within the directory, and
+     - the directory's XML close tag has been processed (so we know
+       there are no more children to worry about in the future), and
+     - either:
+         - we aren't fetching properties for this directory, or
+         - we've already finished fetching those properties.
+*/
+static svn_error_t *
+maybe_close_dir_chain(report_dir_t *dir)
+{
+  report_dir_t *cur_dir = dir;
+
+  SVN_ERR(ensure_dir_opened(cur_dir));
+                  
+  while (cur_dir
+         && !cur_dir->ref_count
+         && cur_dir->tag_closed
+         && (!cur_dir->fetch_props || cur_dir->propfind_handler->done))
+    {
+      report_dir_t *parent = cur_dir->parent_dir;
+      report_context_t *report_context = cur_dir->report_context;
+
+      SVN_ERR(close_dir(cur_dir));
+      if (parent)
+        {
+          parent->ref_count--;
+        }
+      else
+        {
+          report_context->closed_root = TRUE;
+        }
+      cur_dir = parent;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Open the file associated with INFO for editing, pass along any
    propchanges we've recorded for it, and then close the file. */
 static svn_error_t *
@@ -1226,7 +1413,7 @@ fetch_file(report_context_t *ctx, report
   svn_ra_serf__handler_t *handler;
 
   /* What connection should we go on? */
-  conn = ctx->sess->conns[ctx->sess->cur_conn];
+  conn = get_best_connection(ctx);
 
   /* go fetch info->name from DAV:checked-in */
   info->url = svn_ra_serf__get_ver_prop(info->props, info->base_name,
@@ -1253,7 +1440,7 @@ fetch_file(report_context_t *ctx, report
       /* Create a serf request for the PROPFIND.  */
       svn_ra_serf__request_create(info->propfind_handler);
 
-      ctx->active_propfinds++;
+      ctx->num_active_propfinds++;
     }
 
   /* If we've been asked to fetch the file or it's an add, do so.
@@ -1350,6 +1537,7 @@ fetch_file(report_context_t *ctx, report
           handler->conn = conn;
           handler->session = ctx->sess;
 
+          handler->custom_accept_encoding = TRUE;
           handler->header_delegate = headers_fetch;
           handler->header_delegate_baton = fetch_ctx;
 
@@ -1363,7 +1551,7 @@ fetch_file(report_context_t *ctx, report
 
           svn_ra_serf__request_create(handler);
 
-          ctx->active_fetches++;
+          ctx->num_active_fetches++;
         }
     }
   else if (info->propfind_handler)
@@ -1386,7 +1574,8 @@ fetch_file(report_context_t *ctx, report
       SVN_ERR(handle_propchange_only(info, info->pool));
     }
 
-  if (ctx->active_fetches + ctx->active_propfinds > REQUEST_COUNT_TO_PAUSE)
+  if (ctx->num_active_fetches + ctx->num_active_propfinds
+      > REQUEST_COUNT_TO_PAUSE)
     ctx->parser_ctx->paused = TRUE;
 
   return SVN_NO_ERROR;
@@ -1657,7 +1846,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       tmppool = svn_pool_create(info->dir->dir_baton_pool);
 
@@ -1687,7 +1876,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       SVN_ERR(ctx->update_editor->absent_directory(
                                         svn_relpath_join(info->name, file_name,
@@ -1712,7 +1901,7 @@ start_report(svn_ra_serf__xml_parser_t *
 
       info = parser->state->private;
 
-      SVN_ERR(open_dir(info->dir));
+      SVN_ERR(ensure_dir_opened(info->dir));
 
       SVN_ERR(ctx->update_editor->absent_file(
                                         svn_relpath_join(info->name, file_name,
@@ -1937,12 +2126,9 @@ end_report(svn_ra_serf__xml_parser_t *pa
        */
       if (info->dir->fetch_props)
         {
-          /* Unconditionally set fetch_props now. */
-          info->dir->fetch_props = TRUE;
-
           SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind_handler,
                                              info->dir->props, ctx->sess,
-                                             ctx->sess->conns[ctx->sess->cur_conn],
+                                             get_best_connection(ctx),
                                              info->dir->url,
                                              ctx->target_rev, "0",
                                              all_props,
@@ -1953,9 +2139,9 @@ end_report(svn_ra_serf__xml_parser_t *pa
           /* Create a serf request for the PROPFIND.  */
           svn_ra_serf__request_create(info->dir->propfind_handler);
 
-          ctx->active_propfinds++;
+          ctx->num_active_propfinds++;
 
-          if (ctx->active_fetches + ctx->active_propfinds
+          if (ctx->num_active_fetches + ctx->num_active_propfinds
               > REQUEST_COUNT_TO_PAUSE)
             ctx->parser_ctx->paused = TRUE;
         }
@@ -2310,16 +2496,16 @@ link_path(void *report_baton,
 #define REQS_PER_CONN 8
 
 /** This function creates a new connection for this serf session, but only
- * if the number of ACTIVE_REQS > REQS_PER_CONN or if there currently is
+ * if the number of NUM_ACTIVE_REQS > REQS_PER_CONN or if there currently is
  * only one main connection open.
  */
 static svn_error_t *
-open_connection_if_needed(svn_ra_serf__session_t *sess, int active_reqs)
+open_connection_if_needed(svn_ra_serf__session_t *sess, int num_active_reqs)
 {
   /* For each REQS_PER_CONN outstanding requests open a new connection, with
    * a minimum of 1 extra connection. */
   if (sess->num_conns == 1 ||
-      ((active_reqs / REQS_PER_CONN) > sess->num_conns))
+      ((num_active_reqs / REQS_PER_CONN) > sess->num_conns))
     {
       int cur = sess->num_conns;
       apr_status_t status;
@@ -2365,21 +2551,6 @@ create_update_report_body(serf_bucket_t 
 }
 
 static svn_error_t *
-headers_report(serf_bucket_t *headers,
-               void *baton,
-               apr_pool_t *pool)
-{
-  report_context_t *report = baton;
-
-  if (report->sess->using_compression)
-    {
-      serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip");
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 finish_report(void *report_baton,
               apr_pool_t *pool)
 {
@@ -2388,11 +2559,10 @@ finish_report(void *report_baton,
   svn_ra_serf__handler_t *handler;
   svn_ra_serf__xml_parser_t *parser_ctx;
   const char *report_target;
-  svn_boolean_t closed_root;
   svn_stringbuf_t *buf = NULL;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_error_t *err;
-  apr_short_interval_time_t waittime_left = sess->timeout;
+  apr_interval_time_t waittime_left = sess->timeout;
 
   svn_xml_make_close_tag(&buf, iterpool, "S:update-report");
   SVN_ERR(svn_io_file_write_full(report->body_file, buf->data, buf->len,
@@ -2427,8 +2597,6 @@ finish_report(void *report_baton,
   handler->body_type = "text/xml";
   handler->conn = sess->conns[0];
   handler->session = sess;
-  handler->header_delegate = headers_report;
-  handler->header_delegate_baton = report;
 
   parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
 
@@ -2451,14 +2619,15 @@ finish_report(void *report_baton,
   SVN_ERR(open_connection_if_needed(sess, 0));
 
   sess->cur_conn = 1;
-  closed_root = FALSE;
 
   /* Note that we may have no active GET or PROPFIND requests, yet the
      processing has not been completed. This could be from a delay on the
      network or because we've spooled the entire response into our "pending"
      content of the XML parser. The DONE flag will get set when all the
      XML content has been received *and* parsed.  */
-  while (!report->done || report->active_fetches || report->active_propfinds)
+  while (!report->done
+         || report->num_active_fetches
+         || report->num_active_propfinds)
     {
       apr_pool_t *iterpool_inner;
       svn_ra_serf__list_t *done_list;
@@ -2497,14 +2666,17 @@ finish_report(void *report_baton,
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
-            {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
+          if (sess->timeout)
             {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else
@@ -2520,13 +2692,8 @@ finish_report(void *report_baton,
 
       /* Open extra connections if we have enough requests to send. */
       if (sess->num_conns < MAX_NR_OF_CONNS)
-        SVN_ERR(open_connection_if_needed(sess, report->active_fetches +
-                                          report->active_propfinds));
-
-      /* Switch our connection. */
-      if (!report->done)
-         if (++sess->cur_conn == sess->num_conns)
-             sess->cur_conn = 1;
+        SVN_ERR(open_connection_if_needed(sess, report->num_active_fetches +
+                                          report->num_active_propfinds));
 
       /* prune our propfind list if they are done. */
       done_list = report->done_propfinds;
@@ -2534,7 +2701,7 @@ finish_report(void *report_baton,
         {
           svn_pool_clear(iterpool_inner);
 
-          report->active_propfinds--;
+          report->num_active_propfinds--;
 
           /* If we have some files that we won't be fetching the content
            * for, ensure that we update the file with any altered props.
@@ -2594,54 +2761,33 @@ finish_report(void *report_baton,
         }
       report->done_propfinds = NULL;
 
-      /* prune our fetches list if they are done. */
+      /* Prune completely fetches from our list. */
       done_list = report->done_fetches;
       while (done_list)
         {
           report_fetch_t *done_fetch = done_list->data;
           report_dir_t *cur_dir;
 
-          /* decrease our parent's directory refcount. */
+          /* Decrease the refcount in the parent directory of the file
+             whose fetch has completed. */
           cur_dir = done_fetch->info->dir;
           cur_dir->ref_count--;
 
           /* Decrement our active fetch count. */
-          report->active_fetches--;
+          report->num_active_fetches--;
 
           done_list = done_list->next;
 
-          /* If we have a valid directory and
-           * we have no open items in this dir and
-           * we've closed the directory tag (no more children can be added)
-           * and either:
-           *   we know we won't be fetching props or
-           *   we've already completed the propfind
-           * then, we know it's time for us to close this directory.
-           */
-          while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
-                 && (!cur_dir->fetch_props
-                     || cur_dir->propfind_handler->done))
-            {
-              report_dir_t *parent = cur_dir->parent_dir;
-
-              SVN_ERR(close_dir(cur_dir));
-              if (parent)
-                {
-                  parent->ref_count--;
-                }
-              else
-                {
-                  closed_root = TRUE;
-                }
-              cur_dir = parent;
-            }
+          /* See if the parent directory of this fetched item (and
+             perhaps even parents of that) can be closed now. */
+          SVN_ERR(maybe_close_dir_chain(cur_dir));
         }
       report->done_fetches = NULL;
 
       /* If the parser is paused, and the number of active requests has
          dropped far enough, then resume parsing.  */
       if (parser_ctx->paused
-          && (report->active_fetches + report->active_propfinds
+          && (report->num_active_fetches + report->num_active_propfinds
               < REQUEST_COUNT_TO_RESUME))
         parser_ctx->paused = FALSE;
 
@@ -2649,25 +2795,29 @@ finish_report(void *report_baton,
          present (we can't know for sure because of the private structure),
          then go process the pending content.  */
       if (!parser_ctx->paused && parser_ctx->pending != NULL)
-        SVN_ERR(svn_ra_serf__process_pending(parser_ctx, iterpool_inner));
+        SVN_ERR(svn_ra_serf__process_pending(parser_ctx,
+                                             &report->report_received,
+                                             iterpool_inner));
 
       /* Debugging purposes only! */
       for (i = 0; i < sess->num_conns; i++)
         {
-         serf_debug__closed_conn(sess->conns[i]->bkt_alloc);
+          serf_debug__closed_conn(sess->conns[i]->bkt_alloc);
         }
     }
 
-  /* Ensure that we opened and closed our root dir and that we closed
-   * all of our children. */
-  if (closed_root == FALSE && report->root_dir != NULL)
-    {
-      SVN_ERR(close_all_dirs(report->root_dir));
-    }
-
   /* If we got a complete report, close the edit.  Otherwise, abort it. */
   if (report->report_completed)
-    err = report->update_editor->close_edit(report->update_baton, iterpool);
+    {
+      /* Ensure that we opened and closed our root dir and that we closed
+       * all of our children. */
+      if (report->closed_root == FALSE && report->root_dir != NULL)
+        {
+          SVN_ERR(close_all_dirs(report->root_dir));
+        }
+
+      err = report->update_editor->close_edit(report->update_baton, iterpool);
+    }
   else
     err = svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
                            _("Missing update-report close tag"));
@@ -3081,6 +3231,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
           handler->conn = conn;
           handler->session = session;
 
+          handler->custom_accept_encoding = TRUE;
           handler->header_delegate = headers_fetch;
           handler->header_delegate_baton = stream_ctx;
 

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=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Fri Nov 23 01:12:18 2012
@@ -636,6 +636,7 @@ setup_serf_req(serf_request_t *request,
                svn_ra_serf__session_t *session,
                const char *method, const char *url,
                serf_bucket_t *body_bkt, const char *content_type,
+               const char *accept_encoding,
                apr_pool_t *request_pool,
                apr_pool_t *scratch_pool)
 {
@@ -656,6 +657,10 @@ setup_serf_req(serf_request_t *request,
       SVN_ERR(svn_ra_serf__copy_into_spillbuf(&buf, body_bkt,
                                               request_pool,
                                               scratch_pool));
+      /* Destroy original bucket since it content is already copied 
+         to spillbuf. */
+      serf_bucket_destroy(body_bkt);
+
       body_bkt = svn_ra_serf__create_sb_bucket(buf, allocator,
                                                request_pool,
                                                scratch_pool);
@@ -696,6 +701,11 @@ setup_serf_req(serf_request_t *request,
       serf_bucket_headers_setn(*hdrs_bkt, "Connection", "keep-alive");
 #endif
 
+  if (accept_encoding)
+    {
+      serf_bucket_headers_setn(*hdrs_bkt, "Accept-Encoding", accept_encoding);
+    }
+
   /* These headers need to be sent with every request; see issue #3255
      ("mod_dav_svn does not pass client capabilities to start-commit
      hooks") for why. */
@@ -712,7 +722,7 @@ svn_ra_serf__context_run_wait(svn_boolea
                               apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool;
-  apr_short_interval_time_t waittime_left = sess->timeout;
+  apr_interval_time_t waittime_left = sess->timeout;
   
   assert(sess->pending_error == SVN_NO_ERROR);
 
@@ -745,14 +755,17 @@ svn_ra_serf__context_run_wait(svn_boolea
           err = SVN_NO_ERROR;
           status = 0;
 
-          if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+          if (sess->timeout)
             {
-              waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
-            }
-          else
-            {
-              return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
-                                      _("Connection timed out"));
+              if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+                {
+                  waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+                }
+              else 
+                {
+                  return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+                                          _("Connection timed out"));
+                }
             }
         }
       else
@@ -1389,45 +1402,65 @@ xml_parser_cleanup(void *baton)
   return APR_SUCCESS;
 }
 
+/* Limit the amount of pending content to parse at once to < 100KB per
+   iteration. This number is chosen somewhat arbitrarely. Making it lower
+   will have a drastical negative impact on performance, whereas increasing it
+   increases the risk for connection timeouts.
+ */
+#define PENDING_TO_PARSE PARSE_CHUNK_SIZE * 5
+
 svn_error_t *
 svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
+                             svn_boolean_t *network_eof,
                              apr_pool_t *scratch_pool)
 {
+  svn_boolean_t pending_empty = FALSE;
+  apr_size_t cur_read = 0;
+
   /* Fast path exit: already paused, nothing to do, or already done.  */
   if (parser->paused || parser->pending == NULL || *parser->done)
-    return SVN_NO_ERROR;
-
-  /* ### it is possible that the XML parsing of the pending content is
-     ### so slow, and that we don't return to reading the connection
-     ### fast enough... that the server will disconnect us. right now,
-     ### that is highly improbable, but is noted for future's sake.
-     ### should that ever happen, the loops in this function can simply
-     ### terminate after N seconds.  */
+    {
+      *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
+      return SVN_NO_ERROR;
+    }
 
-  /* Try to read everything from the spillbuf.  */
-  while (TRUE)
+  /* Parsing the pending conten in the spillbuf will result in many disc i/o
+     operations. This can be so slow that we don't run the network event
+     processing loop often enough, resulting in timed out connections.
+   
+     So we limit the amounts of bytes parsed per iteration.
+   */
+  while (cur_read < PENDING_TO_PARSE)
     {
       const char *data;
       apr_size_t len;
 
       /* Get a block of content, stopping the loop when we run out.  */
       SVN_ERR(svn_spillbuf__read(&data, &len, parser->pending->buf,
-                                 scratch_pool));
-      if (data == NULL)
-        break;
-
-      /* Inject the content into the XML parser.  */
-      SVN_ERR(inject_to_parser(parser, data, len, NULL));
-
-      /* If the XML parsing callbacks paused us, then we're done for now.  */
-      if (parser->paused)
-        return SVN_NO_ERROR;
+                             scratch_pool));
+      if (data)
+        {
+          /* Inject the content into the XML parser.  */
+          SVN_ERR(inject_to_parser(parser, data, len, NULL));
+
+          /* If the XML parsing callbacks paused us, then we're done for now.  */
+          if (parser->paused)
+            break;
+
+          cur_read += len;
+        }
+      else
+        {
+          /* The buffer is empty. */
+          pending_empty = TRUE;
+          break;
+        }
     }
-  /* All stored content (memory and file) has now been exhausted.  */
 
   /* If the PENDING structures are empty *and* we consumed all content from
      the network, then we're completely done with the parsing.  */
-  if (parser->pending->network_eof)
+  if (pending_empty &&
+      parser->pending->network_eof)
     {
       SVN_ERR_ASSERT(parser->xmlp != NULL);
 
@@ -1440,8 +1473,11 @@ svn_ra_serf__process_pending(svn_ra_serf
       add_done_item(parser);
     }
 
+  *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
+
   return SVN_NO_ERROR;
 }
+#undef PENDING_TO_PARSE
 
 
 /* ### this is still broken conceptually. just shifting incrementally... */
@@ -1874,10 +1910,12 @@ handle_response(serf_request_t *request,
   handler->conn->last_status_code = handler->sline.code;
 
   if (handler->sline.code == 405
+      || handler->sline.code == 408
       || handler->sline.code == 409
       || handler->sline.code >= 500)
     {
       /* 405 Method Not allowed.
+         408 Request Timeout
          409 Conflict: can indicate a hook error.
          5xx (Internal) Server error. */
       serf_bucket_t *hdrs;
@@ -2051,6 +2089,7 @@ setup_request(serf_request_t *request,
 {
   serf_bucket_t *body_bkt;
   serf_bucket_t *headers_bkt;
+  const char *accept_encoding;
 
   if (handler->body_delegate)
     {
@@ -2065,9 +2104,23 @@ setup_request(serf_request_t *request,
       body_bkt = NULL;
     }
 
+  if (handler->custom_accept_encoding)
+    {
+      accept_encoding = NULL;
+    }
+  else if (handler->session->using_compression)
+    {
+      /* Accept gzip compression if enabled. */
+      accept_encoding = "gzip";
+    }
+  else
+    {
+      accept_encoding = NULL;
+    }
+
   SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
                          handler->session, handler->method, handler->path,
-                         body_bkt, handler->body_type,
+                         body_bkt, handler->body_type, accept_encoding,
                          request_pool, scratch_pool));
 
   if (handler->header_delegate)

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=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c Fri Nov 23 01:12:18 2012
@@ -325,6 +325,11 @@ static svn_ra_reporter3_t ra_svn_reporte
   ra_svn_abort_report
 };
 
+/* Set *REPORTER and *REPORT_BATON to a new reporter which will drive
+ * EDITOR/EDIT_BATON when it gets the finish_report() call.
+ *
+ * Allocate the new reporter in POOL.
+ */
 static svn_error_t *
 ra_svn_get_reporter(svn_ra_svn__session_baton_t *sess_baton,
                     apr_pool_t *pool,

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/cyrus_auth.c Fri Nov 23 01:12:18 2012
@@ -871,12 +871,12 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__se
 
   /* The username callback. */
   callbacks[0].id = SASL_CB_AUTHNAME;
-  callbacks[0].proc = get_username_cb;
+  callbacks[0].proc = (void*)get_username_cb;
   callbacks[0].context = &cred_baton;
 
   /* The password callback. */
   callbacks[1].id = SASL_CB_PASS;
-  callbacks[1].proc = get_password_cb;
+  callbacks[1].proc = (void*)get_password_cb;
   callbacks[1].context = &cred_baton;
 
   /* Mark the end of the array. */

Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/ra_svn.h Fri Nov 23 01:12:18 2012
@@ -57,7 +57,8 @@ typedef svn_error_t *(*ra_svn_block_hand
                                                void *baton);
 
 /* The default "user agent". */
-#define SVN_RA_SVN__DEFAULT_USERAGENT  "SVN/" SVN_VER_NUMBER
+#define SVN_RA_SVN__DEFAULT_USERAGENT  "SVN/" SVN_VER_NUMBER\
+                                       " (" SVN_BUILD_TARGET ")"
 
 /* The size of our per-connection read and write buffers. */
 #define SVN_RA_SVN__PAGE_SIZE 4096

Modified: subversion/branches/ev2-export/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/load.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/load.c Fri Nov 23 01:12:18 2012
@@ -336,7 +336,7 @@ parse_text_block(svn_stream_t *stream,
      need to read it. */
   while (content_length)
     {
-      if (content_length >= buflen)
+      if (content_length >= (svn_filesize_t)buflen)
         rlen = buflen;
       else
         rlen = (apr_size_t) content_length;
@@ -659,7 +659,7 @@ svn_repos_parse_dumpstream3(svn_stream_t
           /* Consume remaining bytes in this content block */
           while (remaining > 0)
             {
-              if (remaining >= buflen)
+              if (remaining >= (svn_filesize_t)buflen)
                 rlen = buflen;
               else
                 rlen = (apr_size_t) remaining;

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache-membuffer.c Fri Nov 23 01:12:18 2012
@@ -362,7 +362,7 @@ typedef struct entry_t
 typedef struct entry_group_t
 {
   /* number of entries used [0 .. USED-1] */
-  apr_size_t used;
+  apr_uint32_t used;
 
   /* the actual entries */
   entry_t entries[GROUP_SIZE];
@@ -614,10 +614,10 @@ get_entry(svn_membuffer_t *cache, apr_ui
 static APR_INLINE apr_uint32_t
 get_index(svn_membuffer_t *cache, entry_t *entry)
 {
-  apr_uint32_t group_index
+  apr_size_t group_index
     = ((char *)entry - (char *)cache->directory) / sizeof(entry_group_t);
 
-  return group_index * GROUP_SIZE
+  return (apr_uint32_t)group_index * GROUP_SIZE
        + (apr_uint32_t)(entry - cache->directory[group_index].entries);
 }
 
@@ -1186,7 +1186,7 @@ svn_cache__membuffer_cache_create(svn_me
              < total_size)
         ++segment_count_shift;
 
-      segment_count = 1 << segment_count_shift;
+      segment_count = (apr_size_t)1 << segment_count_shift;
     }
 
   /* If we have an extremely large cache (>512 GB), the default segment
@@ -1249,7 +1249,7 @@ svn_cache__membuffer_cache_create(svn_me
     {
       /* allocate buffers and initialize cache members
        */
-      c[seg].segment_count = segment_count;
+      c[seg].segment_count = (apr_uint32_t)segment_count;
 
       c[seg].group_count = group_count;
       c[seg].directory = apr_pcalloc(pool,

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/cache_config.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/cache_config.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/cache_config.c Fri Nov 23 01:12:18 2012
@@ -124,7 +124,7 @@ svn_cache__get_global_membuffer_cache(vo
           FALSE,
           pool);
 
-      /* Some error occured. Most likely it's an OOM error but we don't
+      /* Some error occurred. Most likely it's an OOM error but we don't
        * really care. Simply release all cache memory and disable caching
        */
       if (err)

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config_win.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/config_win.c Fri Nov 23 01:12:18 2012
@@ -56,7 +56,7 @@ svn_config__win_config_path(const char *
                      | CSIDL_FLAG_CREATE);
 
   WCHAR folder_ucs2[MAX_PATH];
-  apr_size_t inwords, outbytes, outlength;
+  int inwords, outbytes, outlength;
   char *folder_utf8;
 
   if (S_OK != SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT,
@@ -109,7 +109,7 @@ parse_section(svn_config_t *cfg, HKEY hk
   svn_stringbuf_ensure(value, SVN_REG_DEFAULT_VALUE_SIZE);
   for (index = 0; ; ++index)
     {
-      option_len = option->blocksize;
+      option_len = (DWORD)option->blocksize;
       err = RegEnumValue(hkey, index, option->data, &option_len,
                          NULL, &type, NULL, NULL);
       if (err == ERROR_NO_MORE_ITEMS)
@@ -128,7 +128,7 @@ parse_section(svn_config_t *cfg, HKEY hk
          http://subversion.tigris.org/issues/show_bug.cgi?id=671 */
       if (type == REG_SZ && option->data[0] != '#')
         {
-          DWORD value_len = value->blocksize;
+          DWORD value_len = (DWORD)value->blocksize;
           err = RegQueryValueEx(hkey, option->data, NULL, NULL,
                                 (LPBYTE)value->data, &value_len);
           if (err == ERROR_MORE_DATA)
@@ -214,7 +214,7 @@ svn_config__parse_registry(svn_config_t 
   svn_stringbuf_ensure(section, SVN_REG_DEFAULT_NAME_SIZE);
   for (index = 0; ; ++index)
     {
-      DWORD section_len = section->blocksize;
+      DWORD section_len = (DWORD)section->blocksize;
       FILETIME last_write_time;
       HKEY sub_hkey;
 

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/dirent_uri.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/dirent_uri.c Fri Nov 23 01:12:18 2012
@@ -911,7 +911,7 @@ svn_dirent_is_root(const char *dirent, a
       && dirent[len - 1] != '/')
     {
       int segments = 0;
-      int i;
+      apr_size_t i;
       for (i = len; i >= 2; i--)
         {
           if (dirent[i] == '/')
@@ -2402,7 +2402,17 @@ svn_uri_get_file_url_from_dirent(const c
       *url = apr_pstrcat(pool, "file:", dirent, NULL);
     }
   else
-    *url = apr_pstrcat(pool, "file:///", dirent, NULL);
+    {
+      char *uri = apr_pstrcat(pool, "file:///", dirent, NULL);
+      apr_size_t len = 8 /* strlen("file:///") */ + strlen(dirent);
+
+      /* "C:/" is a canonical dirent on Windows,
+         but "file:///C:/" is not a canonical uri */
+      if (uri[len-1] == '/')
+        uri[len-1] = '\0';
+
+      *url = uri;
+    }
 #endif
 
   return SVN_NO_ERROR;

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/error.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/error.c Fri Nov 23 01:12:18 2012
@@ -250,7 +250,9 @@ svn_error_compose_create(svn_error_t *er
 {
   if (err1 && err2)
     {
-      svn_error_compose(err1, err2);
+      svn_error_compose(err1,
+                        svn_error_quick_wrap(err2,
+                                             _("Additional errors:")));
       return err1;
     }
   return err1 ? err1 : err2;

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/named_atomic.c Fri Nov 23 01:12:18 2012
@@ -80,12 +80,12 @@
 /* Particle that will be appended to the namespace name to form the
  * name of the mutex / lock file used for that namespace.
  */
-#define MUTEX_NAME_SUFFIX "Mutex"
+#define MUTEX_NAME_SUFFIX ".mutex"
 
 /* Particle that will be appended to the namespace name to form the
  * name of the shared memory file that backs that namespace.
  */
-#define SHM_NAME_SUFFIX "Shm"
+#define SHM_NAME_SUFFIX ".shm"
 
 /* Platform-dependent implementations of our basic atomic operations.
  * NA_SYNCHRONIZE(op) will ensure that the OP gets executed atomically.
@@ -162,9 +162,11 @@ synched_cmpxchg(volatile apr_int64_t *me
 }
 
 #define NA_SYNCHRONIZE(_atomic,op)\
+  do{\
   SVN_ERR(lock(_atomic->mutex));\
   op;\
-  SVN_ERR(unlock(_atomic->mutex,SVN_NO_ERROR));
+  SVN_ERR(unlock(_atomic->mutex,SVN_NO_ERROR));\
+  }while(0)
 
 #define NA_SYNCHRONIZE_IS_FAST FALSE
 
@@ -238,6 +240,7 @@ struct svn_atomic_namespace__t
 /* On most operating systems APR implements file locks per process, not
  * per file. I.e. the lock file will only sync. among processes but within
  * a process, we must use a mutex to sync the threads. */
+/* Compare ../libsvn_fs_fs/fs.h:SVN_FS_FS__USE_LOCK_MUTEX */
 #if APR_HAS_THREADS && !defined(WIN32)
 #define USE_THREAD_MUTEX 1
 #else
@@ -462,10 +465,12 @@ svn_atomic_namespace__create(svn_atomic_
 
   if (!err && new_ns->data)
     {
-      /* Sanitize (in case of data corruption)
+      /* Detect severe cases of corruption (i.e. when some outsider messed
+       * with our data file)
        */
       if (new_ns->data->count > MAX_ATOMIC_COUNT)
-        new_ns->data->count = MAX_ATOMIC_COUNT;
+        return svn_error_create(SVN_ERR_CORRUPTED_ATOMIC_STORAGE, 0,
+                       _("Number of atomics in namespace is too large."));
 
       /* Cache the number of existing, complete entries.  There can't be
        * incomplete ones from other processes because we hold the mutex.

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/spillbuf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/spillbuf.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/spillbuf.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/spillbuf.c Fri Nov 23 01:12:18 2012
@@ -290,7 +290,7 @@ read_data(struct memblock_t **mem,
   *mem = get_buffer(buf);
   /* NOTE: mem's size/next are uninitialized.  */
 
-  if (buf->spill_size < buf->blocksize)
+  if ((apr_uint64_t)buf->spill_size < (apr_uint64_t)buf->blocksize)
     (*mem)->size = (apr_size_t)buf->spill_size;
   else
     (*mem)->size = buf->blocksize;  /* The size of (*mem)->data  */

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/string.c?rev=1412731&r1=1412730&r2=1412731&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/string.c Fri Nov 23 01:12:18 2012
@@ -37,6 +37,53 @@
 #include "svn_private_config.h"
 
 
+
+void
+svn_membuf__create(svn_membuf_t *membuf, apr_size_t size, apr_pool_t *pool)
+{
+  membuf->pool = pool;
+  membuf->size = (size ? APR_ALIGN_DEFAULT(size) : 0);
+  membuf->data = (!membuf->size ? NULL : apr_palloc(pool, membuf->size));
+}
+
+void
+svn_membuf__ensure(svn_membuf_t *membuf, apr_size_t size)
+{
+  if (size > membuf->size)
+    {
+      membuf->size = APR_ALIGN_DEFAULT(size);
+      membuf->data = (!membuf->size ? NULL
+                      : apr_palloc(membuf->pool, membuf->size));
+    }
+}
+
+void
+svn_membuf__resize(svn_membuf_t *membuf, apr_size_t size)
+{
+  const void *const old_data = membuf->data;
+  const apr_size_t old_size = membuf->size;
+
+  svn_membuf__ensure(membuf, size);
+  if (old_data && old_data != membuf->data)
+    memcpy(membuf->data, old_data, old_size);
+}
+
+/* Always provide an out-of-line implementation of svn_membuf__zero */
+#undef svn_membuf__zero
+void
+svn_membuf__zero(svn_membuf_t *membuf)
+{
+  SVN_MEMBUF__ZERO(membuf);
+}
+
+/* Always provide an out-of-line implementation of svn_membuf__nzero */
+#undef svn_membuf__nzero
+void
+svn_membuf__nzero(svn_membuf_t *membuf, apr_size_t size)
+{
+  SVN_MEMBUF__NZERO(membuf, size);
+}
+
 /* Our own realloc, since APR doesn't have one.  Note: this is a
    generic realloc for memory pools, *not* for strings. */
 static void *
@@ -1134,3 +1181,104 @@ svn__i64toa_sep(apr_int64_t number, char
   return apr_pstrdup(pool, buffer);
 }
 
+unsigned int
+svn_cstring__similarity(const char *stra, const char *strb,
+                        svn_membuf_t *buffer, apr_size_t *rlcs)
+{
+  const svn_string_t stringa = {stra, strlen(stra)};
+  const svn_string_t stringb = {strb, strlen(strb)};
+  return svn_string__similarity(&stringa, &stringb, buffer, rlcs);
+}
+
+unsigned int
+svn_string__similarity(const svn_string_t *stringa,
+                       const svn_string_t *stringb,
+                       svn_membuf_t *buffer, apr_size_t *rlcs)
+{
+  const char *stra = stringa->data;
+  const char *strb = stringb->data;
+  const apr_size_t lena = stringa->len;
+  const apr_size_t lenb = stringb->len;
+  const apr_size_t total = lena + lenb;
+  const char *enda = stra + lena;
+  const char *endb = strb + lenb;
+  apr_size_t lcs = 0;
+
+  /* Skip the common prefix ... */
+  while (stra < enda && strb < endb && *stra == *strb)
+    {
+      ++stra; ++strb;
+      ++lcs;
+    }
+
+  /* ... and the common suffix */
+  if (stra < enda && strb < endb)
+    do
+      {
+        --enda; --endb;
+        ++lcs;
+      }
+    while (stra < enda && strb < endb && *enda == *endb);
+
+  if (stra < enda && strb < endb)
+    {
+      /* Move the end pointers past the non-matching part */
+      const apr_size_t resta = ++enda - stra;
+      const apr_size_t restb = ++endb - strb;
+      const apr_size_t slots = (resta > restb ? restb : resta);
+      apr_size_t *curr, *prev;
+      const char *pstr;
+
+      /* The outer loop must iterate on the longer string. */
+      if (resta < restb)
+        {
+          pstr = stra;
+          stra = strb;
+          strb = pstr;
+
+          pstr = enda;
+          enda = endb;
+          endb = pstr;
+        }
+
+      /* Allocate two columns in the LCS matrix
+         ### Optimize this to (slots + 2) instesd of 2 * (slots + 1) */
+      svn_membuf__ensure(buffer, 2 * (slots + 1) * sizeof(apr_size_t));
+      svn_membuf__zero(buffer);
+      curr = buffer->data;
+      prev = curr + slots + 1;
+
+      /* Calculate LCS length of the remainder */
+      for (pstr = stra; pstr < enda; ++pstr)
+        {
+          int i;
+          for (i = 1; i <= slots; ++i)
+            {
+              if (*pstr == strb[i])
+                curr[i] = prev[i-1] + 1;
+              else
+                curr[i] = (curr[i-1] > prev[i] ? curr[i-1] : prev[i]);
+            }
+
+          /* Swap the buffers, making the previous one current */
+          {
+            apr_size_t *const temp = prev;
+            prev = curr;
+            curr = temp;
+          }
+        }
+
+      /* The common suffix matcher always increments the lcs
+         so subtract 1 from the result. */
+      lcs += prev[slots] - 1;
+    }
+
+  if (rlcs)
+    *rlcs = lcs;
+
+  /* Return similarity ratio rounded to 4 significant digits */
+  if (total)
+    return(unsigned int)((2000 * lcs + total/2) / total);
+  else
+    return 1000;
+}