You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/12/01 19:51:28 UTC

svn commit: r1546837 [1/2] - in /subversion/branches/fsfs-improvements: ./ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_...

Author: stefan2
Date: Sun Dec  1 18:51:26 2013
New Revision: 1546837

URL: http://svn.apache.org/r1546837
Log:
On the fsfs-improvements branch: sync with trunk up to and including r1546835.
There were no conflicts.

Added:
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.h
      - copied unchanged from r1546835, subversion/trunk/subversion/libsvn_subr/checksum.h
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/fnv1a.c
      - copied unchanged from r1546835, subversion/trunk/subversion/libsvn_subr/fnv1a.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/fnv1a.h
      - copied unchanged from r1546835, subversion/trunk/subversion/libsvn_subr/fnv1a.h
Removed:
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.h
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/sha1.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/sha1.h
Modified:
    subversion/branches/fsfs-improvements/   (props changed)
    subversion/branches/fsfs-improvements/CHANGES
    subversion/branches/fsfs-improvements/build.conf
    subversion/branches/fsfs-improvements/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
    subversion/branches/fsfs-improvements/subversion/include/private/svn_fs_util.h
    subversion/branches/fsfs-improvements/subversion/include/private/svn_io_private.h
    subversion/branches/fsfs-improvements/subversion/include/private/svn_subr_private.h
    subversion/branches/fsfs-improvements/subversion/include/svn_checksum.h
    subversion/branches/fsfs-improvements/subversion/include/svn_fs.h
    subversion/branches/fsfs-improvements/subversion/libsvn_client/merge.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs/editor.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs/fs-loader.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.h
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/recovery.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/revprops.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_util/fs-util.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/   (props changed)
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/fs_x.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/transaction.c
    subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c
    subversion/branches/fsfs-improvements/subversion/libsvn_repos/fs-wrap.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_win.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.c
    subversion/branches/fsfs-improvements/subversion/libsvn_subr/stream.c
    subversion/branches/fsfs-improvements/subversion/svn/mergeinfo-cmd.c
    subversion/branches/fsfs-improvements/subversion/svnadmin/svnadmin.c
    subversion/branches/fsfs-improvements/subversion/tests/cmdline/mergeinfo_tests.py
    subversion/branches/fsfs-improvements/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/fsfs-improvements/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
    subversion/branches/fsfs-improvements/subversion/tests/cmdline/svntest/main.py
    subversion/branches/fsfs-improvements/subversion/tests/libsvn_fs/fs-test.c
    subversion/branches/fsfs-improvements/subversion/tests/libsvn_fs_x/   (props changed)
    subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/checksum-test.c
    subversion/branches/fsfs-improvements/subversion/tests/svn_test_fs.c
    subversion/branches/fsfs-improvements/subversion/tests/svn_test_main.c

Propchange: subversion/branches/fsfs-improvements/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1545955-1546835
  Merged /subversion/branches/verify-keep-going:r1492640-1546110
  Merged /subversion/branches/log-addressing:r1511324,1511346,1511363-1511364,1515049,1515088,1516315,1516322,1516665,1532410,1533539,1533543,1533816,1533819,1535668,1545968

Modified: subversion/branches/fsfs-improvements/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/CHANGES?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/CHANGES (original)
+++ subversion/branches/fsfs-improvements/CHANGES Sun Dec  1 18:51:26 2013
@@ -10,6 +10,7 @@ http://svn.apache.org/repos/asf/subversi
   - Minor new features and improvements:
     * new 'diff-ignore-content-type' runtime configuration option.
     * new option for 'svnadmin verify': --check-ucs-normalization.
+    * new option for 'svnadmin verify': --keep-going.
 
   - Client-side bugfixes:
 

Modified: subversion/branches/fsfs-improvements/build.conf
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/build.conf?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/build.conf (original)
+++ subversion/branches/fsfs-improvements/build.conf Sun Dec  1 18:51:26 2013
@@ -837,7 +837,7 @@ path = subversion/tests/libsvn_fs
 sources = fs-test.c
 install = test
 libs = libsvn_test libsvn_fs libsvn_delta
-       libsvn_subr aprutil apriconv apr
+       libsvn_fs_util libsvn_subr aprutil apriconv apr
 
 # ----------------------------------------------------------------------------
 # Tests for libsvn_repos

Modified: subversion/branches/fsfs-improvements/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/fsfs-improvements/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Sun Dec  1 18:51:26 2013
@@ -670,14 +670,17 @@ public class SVNRemoteTests extends SVNT
         ISVNRemote session = getSession();
 
         byte[] ignoreval = "*.pyc\n.gitignore\n".getBytes(UTF8);
+        byte[] binaryval = new byte[]{(byte)0, (byte)13, (byte)255, (byte)8,
+                                      (byte)127, (byte)128, (byte)129};
         HashMap<String, byte[]> props = new HashMap<String, byte[]>();
         props.put("svn:ignore", ignoreval);
+        props.put("binaryprop", binaryval);
 
         CommitContext cc =
             (cb != null
-             ? new CommitContext(session, "Add svn:ignore",
+             ? new CommitContext(session, "Add svn:ignore and binaryprop",
                                  cb.getBase, cb.getProps, cb.getKind)
-             : new CommitContext(session, "Add svn:ignore"));
+             : new CommitContext(session, "Add svn:ignore and binaryprop"));
         try {
             cc.editor.alterDirectory("", 1, null, props);
             cc.editor.complete();
@@ -692,6 +695,11 @@ public class SVNRemoteTests extends SVNT
                                                     "svn:ignore",
                                                     Revision.HEAD,
                                                     Revision.HEAD)));
+        assertTrue(Arrays.equals(binaryval,
+                                 client.propertyGet(session.getSessionUrl(),
+                                                    "binaryprop",
+                                                    Revision.HEAD,
+                                                    Revision.HEAD)));
     }
 
     public void testEditorSetDirProps() throws Exception

Modified: subversion/branches/fsfs-improvements/subversion/include/private/svn_fs_util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/include/private/svn_fs_util.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/include/private/svn_fs_util.h (original)
+++ subversion/branches/fsfs-improvements/subversion/include/private/svn_fs_util.h Sun Dec  1 18:51:26 2013
@@ -210,6 +210,17 @@ svn_fs__append_to_merged_froms(svn_merge
                                const char *rel_path,
                                apr_pool_t *pool);
 
+/* Given the FS creation options in CONFIG, return the oldest version that
+   we shall be compatible with in *COMPATIBLE_VERSION.  The patch level
+   is always set to 0 and the tag to "".   Allocate the result in POOL.
+
+   Note that the result will always be compatible to the current tool
+   version, i.e. will be a version number not more recent than this tool. */
+svn_error_t *
+svn_fs__compatible_version(svn_version_t **compatible_version,
+                           apr_hash_t *config,
+                           apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/fsfs-improvements/subversion/include/private/svn_io_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/include/private/svn_io_private.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/include/private/svn_io_private.h (original)
+++ subversion/branches/fsfs-improvements/subversion/include/private/svn_io_private.h Sun Dec  1 18:51:26 2013
@@ -44,6 +44,15 @@ extern "C" {
 #define SVN__APR_FINFO_MASK_OUT (0)
 #endif
 
+/* 90% of the lines we encounter will be less than this many chars.
+ *
+ * Line-based functions like svn_stream_readline should fetch data in
+ * blocks no longer than this.  Although using a larger prefetch size is
+ * not illegal and must not break any functionality, it may be
+ * significantly less efficient in certain situations.
+ */
+#define SVN__LINE_CHUNK_SIZE 80
+
 
 /** Set @a *executable TRUE if @a file_info is executable for the
  * user, FALSE otherwise.

Modified: subversion/branches/fsfs-improvements/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/include/private/svn_subr_private.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/include/private/svn_subr_private.h (original)
+++ subversion/branches/fsfs-improvements/subversion/include/private/svn_subr_private.h Sun Dec  1 18:51:26 2013
@@ -221,6 +221,13 @@ svn_stream__from_spillbuf(svn_spillbuf_t
 
 /** @} */
 
+/*----------------------------------------------------*/
+
+/**
+ * @defgroup svn_checksum_private Checksumming helper APIs
+ * @{
+ */
+
 /**
  * Internal function for creating a MD5 checksum from a binary digest.
  *
@@ -240,6 +247,51 @@ svn_checksum_t *
 svn_checksum__from_digest_sha1(const unsigned char *digest,
                                apr_pool_t *result_pool);
 
+/**
+ * Internal function for creating a 32 bit FNV-1a checksum from a binary
+ * digest.
+ *
+ * @since New in 1.9
+ */
+svn_checksum_t *
+svn_checksum__from_digest_fnv1a_32(const unsigned char *digest,
+                                   apr_pool_t *result_pool);
+
+/**
+ * Internal function for creating a modified 32 bit FNV-1a checksum from
+ * a binary digest.
+ *
+ * @since New in 1.9
+ */
+svn_checksum_t *
+svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest,
+                                     apr_pool_t *result_pool);
+
+
+/**
+ * Return a 32 bit FNV-1a checksum for the first @a len bytes in @a input.
+ * The representation is in Big Endian.
+ *
+ * @since New in 1.9
+ */
+apr_uint32_t
+svn__fnv1a_32(const void *input, apr_size_t len);
+
+/**
+ * Return a 32 bit modified FNV-1a checksum for the first @a len bytes in
+ * @a input.  The representation is in Big Endian.
+ * 
+ * @note This is a proprietary checksumming algorithm based FNV-1a with
+ *       approximately the same strength.  It is up to 4 times faster
+ *       than plain FNV-1a for longer data blocks.
+ *
+ * @since New in 1.9
+ */
+apr_uint32_t
+svn__fnv1a_32x4(const void *input, apr_size_t len);
+
+/** @} */
+
 
 /**
  * @defgroup svn_hash_support Hash table serialization support

Modified: subversion/branches/fsfs-improvements/subversion/include/svn_checksum.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/include/svn_checksum.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/include/svn_checksum.h (original)
+++ subversion/branches/fsfs-improvements/subversion/include/svn_checksum.h Sun Dec  1 18:51:26 2013
@@ -48,7 +48,17 @@ typedef enum svn_checksum_kind_t
   svn_checksum_md5,
 
   /** The checksum is (or should be set to) a SHA1 checksum. */
-  svn_checksum_sha1
+  svn_checksum_sha1,
+
+  /** The checksum is (or should be set to) a FNV-1a 32 bit checksum,
+   * in big endian byte order.
+   * @since New in 1.9. */
+  svn_checksum_fnv1a_32,
+
+  /** The checksum is (or should be set to) a modified FNV-1a 32 bit,
+   * in big endian byte order.
+   * @since New in 1.9. */
+  svn_checksum_fnv1a_32x4
 } svn_checksum_kind_t;
 
 /**

Modified: subversion/branches/fsfs-improvements/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/include/svn_fs.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/include/svn_fs.h (original)
+++ subversion/branches/fsfs-improvements/subversion/include/svn_fs.h Sun Dec  1 18:51:26 2013
@@ -908,10 +908,9 @@ svn_fs_unparse_id(const svn_fs_id_t *id,
  * pairs.  When you commit a transaction, all of its properties become
  * unversioned revision properties of the new revision.  (There is one
  * exception: the svn:date property will be automatically set on new
- * transactions to the date that the transaction was created, and will
+ * transactions to the date that the transaction was created, and can
  * be overwritten when the transaction is committed by the current
- * time; changes to a transaction's svn:date property will not affect
- * its committed value.)
+ * time; see svn_fs_commit_txn2.)
  *
  * Transaction names are guaranteed to contain only letters (upper-
  * and lower-case), digits, `-', and `.', from the ASCII character
@@ -1006,6 +1005,16 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p,
  * a new filesystem revision containing the changes made in @a txn,
  * storing that new revision number in @a *new_rev, and return zero.
  *
+ * If @a set_timestamp is FALSE any svn:date on the transaction will
+ * be become the unversioned property svn:date on the revision.
+ * svn:date can have any value, it does not have to be a timestamp.
+ * If the transaction has no svn:date the revision will have no
+ * svn:date.
+ *
+ * If @a set_timestamp is TRUE the new revision will have svn:date set
+ * to the current time at some point during the commit and any
+ * svn:date on the transaction will be lost.
+ * 
  * If @a conflict_p is non-zero, use it to provide details on any
  * conflicts encountered merging @a txn with the most recent committed
  * revisions.  If a conflict occurs, set @a *conflict_p to the path of
@@ -1056,7 +1065,10 @@ svn_fs_commit_txn2(const char **conflict
 /*
  * Same as svn_fs_commit_txn2(), but with @a set_timestamp
  * always set to @c TRUE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.8 API.
  */
+SVN_DEPRECATED
 svn_error_t *
 svn_fs_commit_txn(const char **conflict_p,
                   svn_revnum_t *new_rev,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_client/merge.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_client/merge.c Sun Dec  1 18:51:26 2013
@@ -12681,7 +12681,8 @@ svn_client_get_merging_summary(svn_boole
 
   target_is_wc = (! svn_path_is_url(target_path_or_url))
                  && (target_revision->kind == svn_opt_revision_unspecified
-                     || target_revision->kind == svn_opt_revision_working);
+                     || target_revision->kind == svn_opt_revision_working
+                     || target_revision->kind == svn_opt_revision_base);
   if (target_is_wc)
     {
       const char *target_abspath;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs/editor.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs/editor.c Sun Dec  1 18:51:26 2013
@@ -789,10 +789,11 @@ svn_fs__editor_commit(svn_revnum_t *revi
      it placed into RESULT_POOL.  */
 
   if (!err)
-    err = svn_fs_commit_txn(&inner_conflict_path,
-                            revision,
-                            eb->txn,
-                            scratch_pool);
+    err = svn_fs_commit_txn2(&inner_conflict_path,
+                             revision,
+                             eb->txn,
+                             TRUE,
+                             scratch_pool);
   if (SVN_IS_VALID_REVNUM(*revision))
     {
       if (err)

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs/fs-loader.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs/fs-loader.c Sun Dec  1 18:51:26 2013
@@ -44,6 +44,7 @@
 #include "svn_string.h"
 #include "svn_sorts.h"
 
+#include "private/svn_atomic.h"
 #include "private/svn_fs_private.h"
 #include "private/svn_fs_util.h"
 #include "private/svn_utf_private.h"
@@ -62,8 +63,9 @@
 
 /* A pool common to all FS objects.  See the documentation on the
    open/create functions in fs-loader.h and for svn_fs_initialize(). */
-static apr_pool_t *common_pool;
-svn_mutex__t *common_pool_lock;
+static apr_pool_t *common_pool = NULL;
+static svn_mutex__t *common_pool_lock = NULL;
+static svn_atomic_t common_pool_initialized = FALSE;
 
 
 /* --- Utility functions for the loader --- */
@@ -196,8 +198,7 @@ get_library_vtable_direct(fs_library_vta
        unloaded.  This function makes a best effort by creating the
        common pool as a child of the global pool; the window of failure
        due to thread collision is small. */
-    if (!common_pool)
-      SVN_ERR(svn_fs_initialize(NULL));
+    SVN_ERR(svn_fs_initialize(NULL));
 
     /* Invoke the FS module's initfunc function with the common
        pool protected by a lock. */
@@ -280,8 +281,8 @@ get_library_vtable(fs_library_vtable_t *
   if (!known)
     {
       fst = &(*fst)->next;
-      if (!common_pool)  /* Best-effort init, see get_library_vtable_direct. */
-        SVN_ERR(svn_fs_initialize(NULL));
+      /* Best-effort init, see get_library_vtable_direct. */
+      SVN_ERR(svn_fs_initialize(NULL));
       SVN_MUTEX__WITH_LOCK(common_pool_lock,
                            get_or_allocate_third(fst, fs_type));
       known = TRUE;
@@ -371,16 +372,15 @@ write_fs_type(const char *path, const ch
 static apr_status_t uninit(void *data)
 {
   common_pool = NULL;
+  common_pool_lock = NULL;
+  common_pool_initialized = 0;
+
   return APR_SUCCESS;
 }
 
-svn_error_t *
-svn_fs_initialize(apr_pool_t *pool)
+static svn_error_t *
+synchronized_initialize(void *baton, apr_pool_t *pool)
 {
-  /* Protect against multiple calls. */
-  if (common_pool)
-    return SVN_NO_ERROR;
-
   common_pool = svn_pool_create(pool);
   base_defn.next = NULL;
   SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, common_pool));
@@ -395,6 +395,15 @@ svn_fs_initialize(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_initialize(apr_pool_t *pool)
+{
+  /* Protect against multiple calls. */
+  return svn_error_trace(svn_atomic__init_once(&common_pool_initialized,
+                                               synchronized_initialize,
+                                               NULL, pool));
+}
+
 /* A default warning handling function.  */
 static void
 default_warning_func(void *baton, svn_error_t *err)

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.c Sun Dec  1 18:51:26 2013
@@ -741,12 +741,27 @@ base_create(svn_fs_t *fs,
   /* See if compatibility with older versions was explicitly requested. */
   if (fs->config)
     {
-      if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE))
-        format = 1;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE))
-        format = 2;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE))
-        format = 3;
+      svn_version_t *compatible_version;
+      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+                                         pool));
+
+      /* select format number */
+      switch(compatible_version->minor)
+        {
+          case 0:
+          case 1:
+          case 2:
+          case 3: format = 1;
+                  break;
+
+          case 4: format = 2;
+                  break;
+
+          case 5: format = 3;
+                  break;
+
+          default:format = SVN_FS_BASE__FORMAT_NUMBER;
+        }
     }
 
   /* Create the environment and databases. */

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_base/fs.h Sun Dec  1 18:51:26 2013
@@ -43,7 +43,11 @@ extern "C" {
    repository format number, and independent of any other FS back
    ends.  See the SVN_FS_BASE__MIN_*_FORMAT defines to get a sense of
    what changes and features were added in which versions of this
-   back-end's format.  */
+   back-end's format.
+
+   Note: If you bump this, please update the switch statement in
+         base_create() as well.
+ */
 #define SVN_FS_BASE__FORMAT_NUMBER                4
 
 /* Minimum format number that supports representation sharing.  This

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c Sun Dec  1 18:51:26 2013
@@ -42,7 +42,6 @@
 
 #include "private/svn_fs_util.h"
 #include "private/svn_string_private.h"
-#include "private/svn_subr_private.h"
 #include "../libsvn_fs/fs-loader.h"
 
 /* The default maximum number of files per directory to store in the
@@ -988,14 +987,36 @@ svn_fs_fs__create(svn_fs_t *fs,
   /* See if compatibility with older versions was explicitly requested. */
   if (fs->config)
     {
-      if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE))
-        format = 1;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE))
-        format = 2;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE))
-        format = 3;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE))
-        format = 4;
+      svn_version_t *compatible_version;
+      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+                                         pool));
+
+      /* select format number */
+      switch(compatible_version->minor)
+        {
+          case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
+                 _("FSFS is not compatible with Subversion prior to 1.1"));
+
+          case 1:
+          case 2:
+          case 3: format = 1;
+                  break;
+
+          case 4: format = 2;
+                  break;
+
+          case 5: format = 3;
+                  break;
+
+          case 6:
+          case 7: format = 4;
+                  break;
+
+          case 8: format = 6;
+                  break;
+
+          default:format = SVN_FS_FS__FORMAT_NUMBER;
+        }
     }
   ffd->format = format;
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/recovery.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/recovery.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/recovery.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/recovery.c Sun Dec  1 18:51:26 2013
@@ -54,10 +54,9 @@ recover_get_largest_revision(svn_fs_t *f
     {
       svn_error_t *err;
       apr_file_t *file;
-
-      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, right, iterpool);
       svn_pool_clear(iterpool);
 
+      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, right, iterpool);
       if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
         {
           svn_error_clear(err);
@@ -78,10 +77,9 @@ recover_get_largest_revision(svn_fs_t *f
       svn_revnum_t probe = left + ((right - left) / 2);
       svn_error_t *err;
       apr_file_t *file;
-
-      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, probe, iterpool);
       svn_pool_clear(iterpool);
 
+      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, probe, iterpool);
       if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
         {
           svn_error_clear(err);

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/revprops.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/revprops.c Sun Dec  1 18:51:26 2013
@@ -72,6 +72,8 @@ svn_fs_fs__upgrade_pack_revprops(svn_fs_
   /* first, pack all revprops shards to match the packed revision shards */
   for (shard = 0; shard < first_unpacked_shard; ++shard)
     {
+      svn_pool_clear(iterpool);
+
       revprops_pack_file_dir = svn_dirent_join(revsprops_dir,
                    apr_psprintf(iterpool,
                                 "%" APR_INT64_T_FMT PATH_EXT_PACKED_SHARD,
@@ -91,8 +93,6 @@ svn_fs_fs__upgrade_pack_revprops(svn_fs_
       if (notify_func)
         SVN_ERR(notify_func(notify_baton, shard,
                             svn_fs_upgrade_pack_revprops, iterpool));
-
-      svn_pool_clear(iterpool);
     }
 
   svn_pool_destroy(iterpool);
@@ -121,6 +121,8 @@ svn_fs_fs__upgrade_cleanup_pack_revprops
   /* delete the non-packed revprops shards afterwards */
   for (shard = 0; shard < first_unpacked_shard; ++shard)
     {
+      svn_pool_clear(iterpool);
+
       revprops_shard_path = svn_dirent_join(revsprops_dir,
                        apr_psprintf(iterpool, "%" APR_INT64_T_FMT, shard),
                        iterpool);
@@ -132,8 +134,6 @@ svn_fs_fs__upgrade_cleanup_pack_revprops
       if (notify_func)
         SVN_ERR(notify_func(notify_baton, shard,
                             svn_fs_upgrade_cleanup_revprops, iterpool));
-
-      svn_pool_clear(iterpool);
     }
 
   svn_pool_destroy(iterpool);
@@ -819,6 +819,7 @@ parse_packed_revprops(svn_fs_t *fs,
       svn_string_t serialized;
       apr_hash_t *properties;
       svn_revnum_t revision = (svn_revnum_t)(first_rev + i);
+      svn_pool_clear(iterpool);
 
       /* read & check the serialized size */
       SVN_ERR(svn_fs_fs__read_number_from_stream(&size, NULL, stream,
@@ -854,8 +855,6 @@ parse_packed_revprops(svn_fs_t *fs,
       revprops->total_size += serialized.len;
 
       offset += serialized.len;
-
-      svn_pool_clear(iterpool);
     }
 
   return SVN_NO_ERROR;
@@ -898,6 +897,7 @@ read_pack_revprop(packed_revprops_t **re
        ++i)
     {
       const char *file_path;
+      svn_pool_clear(iterpool);
 
       /* there might have been concurrent writes.
        * Re-read the manifest and the pack file.
@@ -919,8 +919,6 @@ read_pack_revprop(packed_revprops_t **re
        */
       if (missing && has_revprop_cache(fs, pool))
         SVN_ERR(read_revprop_generation(&result->generation, fs, pool));
-
-      svn_pool_clear(iterpool);
     }
 
   /* the file content should be available now */
@@ -1081,8 +1079,9 @@ switch_to_new_revprop(svn_fs_t *fs,
       for (i = 0; i < files_to_delete->nelts; ++i)
         {
           const char *path = APR_ARRAY_IDX(files_to_delete, i, const char*);
-          SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool));
+
           svn_pool_clear(iterpool);
+          SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool));
         }
 
       svn_pool_destroy(iterpool);
@@ -1113,6 +1112,11 @@ serialize_revprops_header(svn_stream_t *
   /* the sizes array */
   for (i = start; i < end; ++i)
     {
+      /* Non-standard pool usage.
+       *
+       * We only allocate a few bytes each iteration -- even with a
+       * million iterations we would still be in good shape memory-wise.
+       */
       apr_off_t size = APR_ARRAY_IDX(sizes, i, apr_off_t);
       SVN_ERR(svn_stream_printf(stream, iterpool, "%" APR_OFF_T_FMT "\n",
                                 size));
@@ -1121,7 +1125,7 @@ serialize_revprops_header(svn_stream_t *
   /* the double newline char indicates the end of the header */
   SVN_ERR(svn_stream_printf(stream, iterpool, "\n"));
 
-  svn_pool_clear(iterpool);
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -1739,14 +1743,16 @@ svn_fs_fs__delete_revprops_shard(const c
       /* delete all files except the one for revision 0 */
       for (i = 1; i < max_files_per_dir; ++i)
         {
-          const char *path = svn_dirent_join(shard_path,
-                                       apr_psprintf(iterpool, "%d", i),
-                                       iterpool);
+          const char *path;
+          svn_pool_clear(iterpool);
+
+          path = svn_dirent_join(shard_path,
+                                 apr_psprintf(iterpool, "%d", i),
+                                 iterpool);
           if (cancel_func)
             SVN_ERR((*cancel_func)(cancel_baton));
 
           SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool));
-          svn_pool_clear(iterpool);
         }
 
       svn_pool_destroy(iterpool);

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.c Sun Dec  1 18:51:26 2013
@@ -779,6 +779,9 @@ process_changes(apr_hash_t *changed_path
 
   for (i = 0; i < changes->nelts; ++i)
     {
+      /* The ITERPOOL will be cleared at the end of this function
+       * since it is only used rarely and for a single hash iterator.
+       */
       change_t *change = APR_ARRAY_IDX(changes, i, change_t *);
 
       SVN_ERR(fold_change(changed_paths, change));
@@ -2935,7 +2938,7 @@ verify_moves(svn_fs_t *fs,
 {
   apr_hash_t *source_paths = apr_hash_make(pool);
   svn_revnum_t revision;
-  apr_pool_t *iter_pool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
   apr_hash_index_t *hi;
   int i;
   apr_array_header_t *moves
@@ -3018,8 +3021,8 @@ verify_moves(svn_fs_t *fs,
       apr_array_header_t *changes;
       change_t **changes_p;
 
-      svn_pool_clear(iter_pool);
-      svn_fs_fs__get_changes(&changes, fs, revision, iter_pool);
+      svn_pool_clear(iterpool);
+      svn_fs_fs__get_changes(&changes, fs, revision, iterpool);
 
       changes_p = (change_t **)&changes->elts;
       for (i = 0; i < changes->nelts; ++i)
@@ -3053,7 +3056,7 @@ verify_moves(svn_fs_t *fs,
         }
     }
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -3158,7 +3161,11 @@ commit_body(void *baton, apr_pool_t *poo
      race with another caller writing to the prototype revision file
      before we commit it. */
 
-  /* Remove any temporary txn props representing 'flags'. */
+  /* Remove any temporary txn props representing 'flags'. 
+
+     ### This is a permanent change to the transaction.  If this
+     ### commit does not complete for any reason the transaction will
+     ### still exist but will have lost these properties. */
   SVN_ERR(svn_fs_fs__txn_proplist(&txnprops, cb->txn, pool));
   txnprop_list = apr_array_make(pool, 3, sizeof(svn_prop_t));
   prop.value = NULL;
@@ -3215,7 +3222,11 @@ commit_body(void *baton, apr_pool_t *poo
         }
     }
 
-  /* Move the finished rev file into place. */
+  /* Move the finished rev file into place.
+
+     ### This "breaks" the transaction by removing the protorev file
+     ### but the revision is not yet complete.  If this commit does
+     ### not complete for any reason the transaction will be lost. */
   old_rev_filename = svn_fs_fs__path_rev_absolute(cb->fs, old_rev, pool);
   rev_filename = svn_fs_fs__path_rev(cb->fs, new_rev, pool);
   proto_filename = svn_fs_fs__path_txn_proto_rev(cb->fs, txn_id, pool);

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_util/fs-util.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_util/fs-util.c Sun Dec  1 18:51:26 2013
@@ -31,9 +31,11 @@
 #include "svn_fs.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
+#include "svn_version.h"
 
 #include "private/svn_fs_util.h"
 #include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
 #include "../libsvn_fs/fs-loader.h"
 
 /* Return TRUE, if PATH of PATH_LEN > 0 chars starts with a '/' and does
@@ -221,3 +223,65 @@ svn_fs__append_to_merged_froms(svn_merge
 
   return SVN_NO_ERROR;
 }
+
+/* Set the version info in *VERSION to COMPAT_MAJOR and COMPAT_MINOR, if
+   the current value refers to a newer version than that.
+ */
+static void
+add_compatility(svn_version_t *version,
+                int compat_major,
+                int compat_minor)
+{
+  if (   version->major > compat_major
+      || (version->major == compat_major && version->minor > compat_minor))
+    {
+      version->major = compat_major;
+      version->minor = compat_minor;
+    }
+}
+
+svn_error_t *
+svn_fs__compatible_version(svn_version_t **compatible_version,
+                           apr_hash_t *config,
+                           apr_pool_t *pool)
+{
+  svn_version_t *version;
+  const char *compatible;
+
+  /* set compatible version according to generic option.
+     Make sure, we are always compatible to the current SVN version
+     (or older). */
+  compatible = svn_hash_gets(config, SVN_FS_CONFIG_COMPATIBLE_VERSION);
+  if (compatible)
+    {
+      SVN_ERR(svn_version__parse_version_string(&version,
+                                                compatible, pool));
+      add_compatility(version,
+                      svn_subr_version()->major,
+                      svn_subr_version()->minor);
+    }
+  else
+    {
+      version = apr_pmemdup(pool, svn_subr_version(), sizeof(*version));
+    }
+
+  /* specific options take precedence.
+     Let the lowest version compatibility requirement win */
+  if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE))
+    add_compatility(version, 1, 3);
+  else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE))
+    add_compatility(version, 1, 4);
+  else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE))
+    add_compatility(version, 1, 5);
+  else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE))
+    add_compatility(version, 1, 7);
+
+  /* we ignored the patch level and tag so far.
+   * Give them a defined value. */
+  version->patch = 0;
+  version->tag = "";
+
+  /* done here */
+  *compatible_version = version;
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/branches/log-addressing/subversion/libsvn_fs_x:r1511324
  Merged /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:r1546002-1546110
  Merged /subversion/trunk/subversion/libsvn_fs_x:r1545955-1546835

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/fs_x.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/fs_x.c Sun Dec  1 18:51:26 2013
@@ -785,19 +785,25 @@ svn_fs_x__create(svn_fs_t *fs,
   if (fs->config)
     {
       svn_version_t *compatible_version;
-      const char *compatible;
-      compatible = svn_hash_gets(fs->config, SVN_FS_CONFIG_COMPATIBLE_VERSION);
-      if (compatible)
-        SVN_ERR(svn_version__parse_version_string(&compatible_version,
-                                                  compatible, pool));
-      if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE)
-          || svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE)
-          || svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE)
-          || svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE)
-          || (compatible && compatible_version->major == SVN_VER_MAJOR
-              && compatible_version->minor <= 8))
-        return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
-                 _("FSX is not compatible with Subversion prior to 1.9"));
+      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+                                         pool));
+
+      /* select format number */
+      switch(compatible_version->minor)
+        {
+          case 0:
+          case 1:
+          case 2:
+          case 3:
+          case 4:
+          case 5:
+          case 6:
+          case 7:
+          case 8: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
+                  _("FSX is not compatible with Subversion prior to 1.9"));
+
+          default:format = SVN_FS_X__FORMAT_NUMBER;
+        }
     }
   ffd->format = format;
   ffd->max_files_per_dir = SVN_FS_X_DEFAULT_MAX_FILES_PER_DIR;

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/transaction.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_x/transaction.c Sun Dec  1 18:51:26 2013
@@ -2852,23 +2852,27 @@ verify_locks(svn_fs_t *fs,
 
 /* If CHANGE is move, verify that there is no other move with the same
    copy-from path in SOURCE_PATHS already (parent or sub-node moves are fine).
-   Add the source path to SOURCE_PATHS after successful verification. */
+   Add the source path to SOURCE_PATHS after successful verification.
+   Allocate the hashed strings in POOL. */
 static svn_error_t *
 check_for_duplicate_move_source(apr_hash_t *source_paths,
-                                change_t *change)
+                                svn_fs_path_change2_t *change,
+                                apr_pool_t *pool)
 {
-  if (   change->info.change_kind == svn_fs_path_change_move
-      || change->info.change_kind == svn_fs_path_change_movereplace)
-    if (change->info.copyfrom_path)
+  if (   change->change_kind == svn_fs_path_change_move
+      || change->change_kind == svn_fs_path_change_movereplace)
+    if (change->copyfrom_path)
       {
-        if (apr_hash_get(source_paths, change->info.copyfrom_path,
-                         APR_HASH_KEY_STRING))
+        apr_size_t len = strlen(change->copyfrom_path);
+        if (apr_hash_get(source_paths, change->copyfrom_path, len))
           return svn_error_createf(SVN_ERR_FS_AMBIGUOUS_MOVE, NULL,
                       _("Path '%s' has been moved to more than one target"),
-                                   change->info.copyfrom_path);
+                                   change->copyfrom_path);
 
-        apr_hash_set(source_paths, change->info.copyfrom_path,
-                     APR_HASH_KEY_STRING, change->info.copyfrom_path);
+        apr_hash_set(source_paths,
+                     apr_pstrmemdup(pool, change->copyfrom_path, len),
+                     len,
+                     change->copyfrom_path);
       }
 
   return SVN_NO_ERROR;
@@ -2887,7 +2891,7 @@ verify_moves(svn_fs_t *fs,
 {
   apr_hash_t *source_paths = apr_hash_make(pool);
   svn_revnum_t revision;
-  apr_pool_t *iter_pool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
   apr_hash_index_t *hi;
   int i;
   apr_array_header_t *moves
@@ -2901,12 +2905,12 @@ verify_moves(svn_fs_t *fs,
     {
       const char *path;
       apr_ssize_t len;
-      change_t *change;
+      svn_fs_path_change2_t *change;
       apr_hash_this(hi, (const void**)&path, &len, (void**)&change);
 
-      if (   change->info.copyfrom_path
-          && (   change->info.change_kind == svn_fs_path_change_move
-              || change->info.change_kind == svn_fs_path_change_movereplace))
+      if (   change->copyfrom_path
+          && (   change->change_kind == svn_fs_path_change_move
+              || change->change_kind == svn_fs_path_change_movereplace))
         {
           svn_sort__item_t *item = apr_array_push(moves);
           item->key = path;
@@ -2914,9 +2918,9 @@ verify_moves(svn_fs_t *fs,
           item->value = change;
         }
 
-      if (   change->info.change_kind == svn_fs_path_change_delete
-          || change->info.change_kind == svn_fs_path_change_replace
-          || change->info.change_kind == svn_fs_path_change_movereplace)
+      if (   change->change_kind == svn_fs_path_change_delete
+          || change->change_kind == svn_fs_path_change_replace
+          || change->change_kind == svn_fs_path_change_movereplace)
         APR_ARRAY_PUSH(deletions, const char *) = path;
     }
 
@@ -2947,10 +2951,9 @@ verify_moves(svn_fs_t *fs,
                                        deleted_path);
           if (relpath)
             {
-              change_t *closed_move = closest_move_item->value;
+              svn_fs_path_change2_t *closed_move = closest_move_item->value;
               APR_ARRAY_IDX(deletions, i, const char*)
-                = svn_dirent_join(closed_move->info.copyfrom_path, relpath,
-                                  pool);
+                = svn_dirent_join(closed_move->copyfrom_path, relpath, pool);
             }
         }
     }
@@ -2963,46 +2966,50 @@ verify_moves(svn_fs_t *fs,
 
   for (i = 0; moves->nelts; ++i)
     SVN_ERR(check_for_duplicate_move_source (source_paths,
-                          APR_ARRAY_IDX(moves, i, svn_sort__item_t).value));
+                          APR_ARRAY_IDX(moves, i, svn_sort__item_t).value,
+                          pool));
 
   for (revision = txn_id->revision + 1; revision <= old_rev; ++revision)
     {
       apr_array_header_t *changes;
       change_t **changes_p;
 
-      svn_pool_clear(iter_pool);
-      svn_fs_x__get_changes(&changes, fs, revision, iter_pool);
+      svn_pool_clear(iterpool);
+      svn_fs_x__get_changes(&changes, fs, revision, iterpool);
 
       changes_p = (change_t **)&changes->elts;
       for (i = 0; i < changes->nelts; ++i)
-        SVN_ERR(check_for_duplicate_move_source(source_paths, changes_p[i]));
+        SVN_ERR(check_for_duplicate_move_source(source_paths,
+                                                &changes_p[i]->info,
+                                                pool));
     }
 
   /* The move source paths must been deleted in this txn. */
 
   for (i = 0; i < moves->nelts; ++i)
     {
-      change_t *change = APR_ARRAY_IDX(moves, i, svn_sort__item_t).value;
+      svn_fs_path_change2_t *change
+        = APR_ARRAY_IDX(moves, i, svn_sort__item_t).value;
 
       /* there must be a deletion of move's copy-from path
          (or any of its parents) */
 
       int closest_deletion_idx
-        = svn_sort__bsearch_lower_bound(change->info.copyfrom_path, deletions,
+        = svn_sort__bsearch_lower_bound(change->copyfrom_path, deletions,
                                         svn_sort_compare_paths);
       if (closest_deletion_idx < deletions->nelts)
         {
           const char *closest_deleted_path
             = APR_ARRAY_IDX(deletions, closest_deletion_idx, const char *);
           if (!svn_dirent_is_ancestor(closest_deleted_path,
-                                      change->info.copyfrom_path))
+                                      change->copyfrom_path))
             return svn_error_createf(SVN_ERR_FS_INCOMPLETE_MOVE, NULL,
                         _("Path '%s' has been moved without being deleted"),
-                                     change->info.copyfrom_path);
+                                     change->copyfrom_path);
         }
     }
 
-  svn_pool_destroy(iter_pool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/dump.c Sun Dec  1 18:51:26 2013
@@ -593,12 +593,15 @@ node_must_not_exist(struct edit_baton *e
 }
 
 
+static const char normalized_unique[] = "normalized_unique";
+static const char normalized_collision[] = "normalized_collision";
+
 static svn_error_t *
-check_ucs_normalization(const char *path,
-                        svn_node_kind_t kind,
-                        svn_repos_notify_func_t notify_func,
-                        void *notify_baton,
-                        apr_pool_t *scratch_pool)
+check_path_normalization(const char *path,
+                         svn_node_kind_t kind,
+                         svn_repos_notify_func_t notify_func,
+                         void *notify_baton,
+                         apr_pool_t *scratch_pool)
 {
   const char *const name = svn_relpath_basename(path, scratch_pool);
   if (!svn_utf__is_normalized(name, scratch_pool))
@@ -626,11 +629,62 @@ check_ucs_normalization(const char *path
 }
 
 
+/* Baton for extract_mergeinfo_paths */
+struct extract_mergeinfo_paths_baton
+{
+  apr_hash_t *result;
+  svn_boolean_t normalize;
+  svn_membuf_t buffer;
+};
+
+/* Hash iterator that uniquifies all keys into a single hash table,
+   optionally normalizing them first. */
+static svn_error_t *
+extract_mergeinfo_paths(void *baton, const void *key, apr_ssize_t klen,
+                         void *val, apr_pool_t *iterpool)
+{
+  struct extract_mergeinfo_paths_baton *const xb = baton;
+  if (xb->normalize)
+    {
+      const char *normkey;
+      SVN_ERR(svn_utf__normalize(&normkey, key, klen, &xb->buffer));
+      svn_hash_sets(xb->result,
+                    apr_pstrdup(xb->buffer.pool, normkey),
+                    normalized_unique);
+    }
+  else
+    apr_hash_set(xb->result,
+                 apr_pmemdup(xb->buffer.pool, key, klen + 1), klen,
+                 normalized_unique);
+  return SVN_NO_ERROR;
+}
+
+/* Baton for filter_mergeinfo_paths */
+struct filter_mergeinfo_paths_baton
+{
+  apr_hash_t *paths;
+  svn_membuf_t buffer;
+};
+
+/* Compare two sets of denormalized paths from mergeinfo entries,
+   removing duplicates. */
+static svn_error_t *
+filter_mergeinfo_paths(void *baton, const void *key, apr_ssize_t klen,
+                       void *val, apr_pool_t *iterpool)
+{
+  struct filter_mergeinfo_paths_baton *const fb = baton;
+
+  if (apr_hash_get(fb->paths, key, klen))
+    apr_hash_set(fb->paths, key, klen, NULL);
+
+  return SVN_NO_ERROR;
+}
+
 /* Baton used by the check_mergeinfo_normalization hash iterator. */
-struct check_mergeinfo_normalization_baton
+struct verify_mergeinfo_normalization_baton
 {
   const char* path;
-  apr_hash_t *normalized;
+  apr_hash_t *normalized_paths;
   svn_membuf_t buffer;
   svn_repos_notify_func_t notify_func;
   void *notify_baton;
@@ -639,53 +693,116 @@ struct check_mergeinfo_normalization_bat
 /* Hash iterator that verifies normalization and collision of paths in
    an svn:mergeinfo property. */
 static svn_error_t *
-check_mergeinfo_normalization(void *baton, const void *key, apr_ssize_t klen,
-                              void *val, apr_pool_t *pool)
+verify_mergeinfo_normalization(void *baton, const void *key, apr_ssize_t klen,
+                               void *val, apr_pool_t *iterpool)
 {
-  static const char unique[] = "unique";
-  static const char collision[] = "collision";
-
-  struct check_mergeinfo_normalization_baton *const check_baton = baton;
+  struct verify_mergeinfo_normalization_baton *const vb = baton;
 
   const char *const path = key;
   const char *normpath;
   const char *found;
 
-  SVN_ERR(svn_utf__normalize(&normpath, path, klen, &check_baton->buffer));
-
-  found = svn_hash_gets(check_baton->normalized, normpath);
-  if (!found)
+  SVN_ERR(svn_utf__normalize(&normpath, path, klen, &vb->buffer));
+  if (0 != strcmp(path, normpath))
     {
-      if (0 != strcmp(path, normpath))
-        {
-          /* Report denormlized mergeinfo path */
-          svn_repos_notify_t *const notify =
-            svn_repos_notify_create(svn_repos_notify_warning, pool);
-          notify->warning = svn_repos_notify_warning_denormalized_mergeinfo;
-          notify->warning_str = apr_psprintf(
-              pool, _("Denormalized path '%s' in %s property of '%s'"),
-              path, SVN_PROP_MERGEINFO, check_baton->path);
-          check_baton->notify_func(check_baton->notify_baton, notify, pool);
-        }
-      svn_hash_sets(check_baton->normalized,
-                    apr_pstrdup(pool, normpath), unique);
+      /* Report denormlized mergeinfo path */
+      svn_repos_notify_t *const notify =
+        svn_repos_notify_create(svn_repos_notify_warning, iterpool);
+      notify->warning = svn_repos_notify_warning_denormalized_mergeinfo;
+      notify->warning_str = apr_psprintf(
+          iterpool, _("Denormalized path '%s' in %s property of '%s'"),
+          path, SVN_PROP_MERGEINFO, vb->path);
+      vb->notify_func(vb->notify_baton, notify, iterpool);
     }
-  else if (found == collision)
+
+  found = svn_hash_gets(vb->normalized_paths, normpath);
+  if (!found)
+      svn_hash_sets(vb->normalized_paths,
+                    apr_pstrdup(vb->buffer.pool, normpath),
+                    normalized_unique);
+  else if (found == normalized_collision)
     /* Skip already reported collision */;
   else
     {
       /* Report path collision in mergeinfo */
-      svn_repos_notify_t *const notify =
-        svn_repos_notify_create(svn_repos_notify_warning, pool);
+      svn_repos_notify_t *notify;
+
+      svn_hash_sets(vb->normalized_paths,
+                    apr_pstrdup(vb->buffer.pool, normpath),
+                    normalized_collision);
+
+      notify = svn_repos_notify_create(svn_repos_notify_warning, iterpool);
       notify->warning = svn_repos_notify_warning_mergeinfo_collision;
       notify->warning_str = apr_psprintf(
-          pool, _("Duplicate representation of path '%s'"
+          iterpool, _("Duplicate representation of path '%s'"
                   " in %s property of '%s'"),
-          normpath, SVN_PROP_MERGEINFO, check_baton->path);
-      check_baton->notify_func(check_baton->notify_baton, notify, pool);
-      svn_hash_sets(check_baton->normalized,
-                    apr_pstrdup(pool, normpath), collision);
+          normpath, SVN_PROP_MERGEINFO, vb->path);
+      vb->notify_func(vb->notify_baton, notify, iterpool);
+    }
+  return SVN_NO_ERROR;
+}
+
+/* Check UCS normalization of mergeinfo for PATH. NEW_MERGEINFO is the
+   svn:mergeinfo property value being set; OLD_MERGEINFO is the
+   previous property value, which may be NULL. Only the paths that
+   were added in are checked, including collision checks. This
+   minimizes the number of notifications we generate for a given
+   mergeinfo property. */
+static svn_error_t *
+check_mergeinfo_normalization(const char *path,
+                              const char *new_mergeinfo,
+                              const char *old_mergeinfo,
+                              svn_repos_notify_func_t notify_func,
+                              void *notify_baton,
+                              apr_pool_t *pool)
+{
+  svn_mergeinfo_t mergeinfo;
+  apr_hash_t *normalized_paths;
+  apr_hash_t *added_paths;
+  struct extract_mergeinfo_paths_baton extract_baton;
+  struct verify_mergeinfo_normalization_baton verify_baton;
+
+  SVN_ERR(svn_mergeinfo_parse(&mergeinfo, new_mergeinfo, pool));
+
+  extract_baton.result = apr_hash_make(pool);
+  extract_baton.normalize = FALSE;
+  svn_membuf__create(&extract_baton.buffer, 0, pool);
+  SVN_ERR(svn_iter_apr_hash(NULL, mergeinfo,
+                            extract_mergeinfo_paths,
+                            &extract_baton, pool));
+  added_paths = extract_baton.result;
+
+  if (old_mergeinfo)
+    {
+      struct filter_mergeinfo_paths_baton filter_baton;
+      svn_mergeinfo_t oldinfo;
+
+      extract_baton.result = apr_hash_make(pool);
+      extract_baton.normalize = TRUE;
+      SVN_ERR(svn_mergeinfo_parse(&oldinfo, old_mergeinfo, pool));
+      SVN_ERR(svn_iter_apr_hash(NULL, oldinfo,
+                                extract_mergeinfo_paths,
+                                &extract_baton, pool));
+      normalized_paths = extract_baton.result;
+
+      filter_baton.paths = added_paths;
+      filter_baton.buffer = extract_baton.buffer;
+      SVN_ERR(svn_iter_apr_hash(NULL, oldinfo,
+                                filter_mergeinfo_paths,
+                                &filter_baton, pool));
     }
+  else
+      normalized_paths = apr_hash_make(pool);
+
+  verify_baton.path = path;
+  verify_baton.normalized_paths = normalized_paths;
+  verify_baton.buffer = extract_baton.buffer;
+  verify_baton.notify_func = notify_func;
+  verify_baton.notify_baton = notify_baton;
+  SVN_ERR(svn_iter_apr_hash(NULL, added_paths,
+                            verify_mergeinfo_normalization,
+                            &verify_baton, pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -1047,18 +1164,18 @@ dump_node(struct edit_baton *eb,
                                                       SVN_PROP_MERGEINFO);
           if (mergeinfo_str)
             {
-              svn_mergeinfo_t mergeinfo;
-              struct check_mergeinfo_normalization_baton check_baton;
-              check_baton.path = path;
-              check_baton.normalized = apr_hash_make(pool);
-              svn_membuf__create(&check_baton.buffer, 0, pool);
-              check_baton.notify_func = eb->notify_func;
-              check_baton.notify_baton = eb->notify_baton;
-              SVN_ERR(svn_mergeinfo_parse(&mergeinfo,
-                                          mergeinfo_str->data, pool));
-              SVN_ERR(svn_iter_apr_hash(NULL, mergeinfo,
-                                        check_mergeinfo_normalization,
-                                        &check_baton, pool));
+              svn_string_t *oldinfo_str = NULL;
+              if (compare_root)
+                {
+                  SVN_ERR(svn_fs_node_proplist(&oldhash,
+                                               compare_root, compare_path,
+                                               pool));
+                  oldinfo_str = svn_hash_gets(oldhash, SVN_PROP_MERGEINFO);
+                }
+              SVN_ERR(check_mergeinfo_normalization(
+                          path, mergeinfo_str->data,
+                          (oldinfo_str ? oldinfo_str->data : NULL),
+                          eb->notify_func, eb->notify_baton, pool));
             }
         }
 
@@ -1066,8 +1183,9 @@ dump_node(struct edit_baton *eb,
         {
           /* Fetch the old property hash to diff against and output a header
              saying that our property contents are a delta. */
-          SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
-                                       pool));
+          if (!oldhash)         /* May have been set for normalization check */
+            SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
+                                         pool));
           SVN_ERR(svn_stream_puts(eb->stream,
                                   SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n"));
         }
@@ -1257,7 +1375,7 @@ add_directory(const char *path,
   if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
     {
       pb->check_name_collision = TRUE;
-      SVN_ERR(check_ucs_normalization(
+      SVN_ERR(check_path_normalization(
                   path, svn_node_dir,
                   eb->notify_func, eb->notify_baton, pool));
     }
@@ -1366,7 +1484,7 @@ add_file(const char *path,
   if (!val && eb->verify && eb->check_ucs_norm && eb->notify_func)
     {
       pb->check_name_collision = TRUE;
-      SVN_ERR(check_ucs_normalization(
+      SVN_ERR(check_path_normalization(
                   path, svn_node_file,
                   eb->notify_func, eb->notify_baton, pool));
     }
@@ -1960,40 +2078,38 @@ struct check_name_collision_baton
    Unicode character representaiton. */
 static svn_error_t *
 check_name_collision(void *baton, const void *key, apr_ssize_t klen,
-                     void *val, apr_pool_t *pool)
+                     void *val, apr_pool_t *iterpool)
 {
-  static const char unique[] = "unique";
-  static const char collision[] = "collision";
-
-  struct check_name_collision_baton *const check_baton = baton;
+  struct check_name_collision_baton *const cb = baton;
   const char *name;
   const char *found;
 
-  SVN_ERR(svn_utf__normalize(&name, key, klen, &check_baton->buffer));
+  SVN_ERR(svn_utf__normalize(&name, key, klen, &cb->buffer));
 
-  found = svn_hash_gets(check_baton->normalized, name);
+  found = svn_hash_gets(cb->normalized, name);
   if (!found)
-    svn_hash_sets(check_baton->normalized,
-                  apr_pstrdup(pool, name), unique);
-  else if (found == collision)
+    svn_hash_sets(cb->normalized, apr_pstrdup(cb->buffer.pool, name),
+                  normalized_unique);
+  else if (found == normalized_collision)
     /* Skip already reported collision */;
   else
     {
-      struct dir_baton *const db = check_baton->dir_baton;
+      struct dir_baton *const db = cb->dir_baton;
       struct edit_baton *const eb = db->edit_baton;
       svn_repos_notify_t *notify;
       const char* normpath;
 
-      svn_hash_sets(check_baton->normalized,
-                    apr_pstrdup(pool, name), collision);
+      svn_hash_sets(cb->normalized, apr_pstrdup(cb->buffer.pool, name),
+                    normalized_collision);
+
       SVN_ERR(svn_utf__normalize(
-                  &normpath, svn_relpath_join(db->path, name, pool),
-                  SVN_UTF__UNKNOWN_LENGTH, &check_baton->buffer));
-      notify = svn_repos_notify_create(svn_repos_notify_warning, pool);
+                  &normpath, svn_relpath_join(db->path, name, iterpool),
+                  SVN_UTF__UNKNOWN_LENGTH, &cb->buffer));
+      notify = svn_repos_notify_create(svn_repos_notify_warning, iterpool);
       notify->warning = svn_repos_notify_warning_name_collision;
       notify->warning_str = apr_psprintf(
-          pool, _("Duplicate representation of path '%s'"), normpath);
-      eb->notify_func(eb->notify_baton, notify, pool);
+          iterpool, _("Duplicate representation of path '%s'"), normpath);
+      eb->notify_func(eb->notify_baton, notify, iterpool);
     }
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/fs-wrap.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/fs-wrap.c Sun Dec  1 18:51:26 2013
@@ -67,7 +67,9 @@ svn_repos_fs_commit_txn(const char **con
   SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
   SVN_ERR(svn_repos__hooks_pre_commit(repos, hooks_env, txn_name, pool));
 
-  /* Remove any ephemeral transaction properties. */
+  /* Remove any ephemeral transaction properties.  If the commit fails
+     we will attempt to restore the properties but if that fails, or
+     the process is killed, the properties will be lost. */
   SVN_ERR(svn_fs_txn_proplist(&props, txn, pool));
   iterpool = svn_pool_create(pool);
   for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
@@ -86,9 +88,27 @@ svn_repos_fs_commit_txn(const char **con
   svn_pool_destroy(iterpool);
 
   /* Commit. */
-  err = svn_fs_commit_txn(conflict_p, new_rev, txn, pool);
+  err = svn_fs_commit_txn2(conflict_p, new_rev, txn, TRUE, pool);
   if (! SVN_IS_VALID_REVNUM(*new_rev))
-    return err;
+    {
+      /* The commit failed, try to restore the ephemeral properties. */
+      iterpool = svn_pool_create(pool);
+      for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
+        {
+          const void *key;
+          void *val;
+          apr_hash_this(hi, &key, NULL, &val);
+
+          svn_pool_clear(iterpool);
+
+          if (strncmp(key, SVN_PROP_TXN_PREFIX,
+                      (sizeof(SVN_PROP_TXN_PREFIX) - 1)) == 0)
+            svn_error_clear(svn_fs_change_txn_prop(txn, key, val, iterpool));
+        }
+      svn_pool_destroy(iterpool);
+      
+      return err;
+    }
 
   /* Run post-commit hooks. */
   if ((err2 = svn_repos__hooks_post_commit(repos, hooks_env,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c Sun Dec  1 18:51:26 2013
@@ -27,7 +27,6 @@
 
 #include "svn_pools.h"
 #include "svn_checksum.h"
-#include "md5.h"
 #include "svn_private_config.h"
 #include "cache.h"
 #include "svn_string.h"

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/checksum.c Sun Dec  1 18:51:26 2013
@@ -21,7 +21,6 @@
  * ====================================================================
  */
 
-
 #include <ctype.h>
 
 #include <apr_md5.h>
@@ -30,9 +29,10 @@
 #include "svn_checksum.h"
 #include "svn_error.h"
 #include "svn_ctype.h"
+#include "svn_sorts.h"
 
-#include "sha1.h"
-#include "md5.h"
+#include "checksum.h"
+#include "fnv1a.h"
 
 #include "private/svn_subr_private.h"
 
@@ -40,17 +40,109 @@
 
 
 
+/* The MD5 digest for the empty string. */
+static const unsigned char md5_empty_string_digest_array[] = {
+  0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
+  0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
+};
+
+/* The SHA1 digest for the empty string. */
+static const unsigned char sha1_empty_string_digest_array[] = {
+  0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
+  0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
+};
+
+/* The FNV-1a digest for the empty string. */
+static const unsigned char fnv1a_32_empty_string_digest_array[] = {
+  0x81, 0x1c, 0x9d, 0xc5
+};
+
+/* The FNV-1a digest for the empty string. */
+static const unsigned char fnv1a_32x4_empty_string_digest_array[] = {
+  0xcd, 0x6d, 0x9a, 0x85
+};
+
+/* Digests for an empty string, indexed by checksum type */
+static const unsigned char * empty_string_digests[] = {
+  md5_empty_string_digest_array,
+  sha1_empty_string_digest_array,
+  fnv1a_32_empty_string_digest_array,
+  fnv1a_32x4_empty_string_digest_array
+};
+
+/* Digest sizes in bytes, indexed by checksum type */
+static const apr_size_t digest_sizes[] = {
+  APR_MD5_DIGESTSIZE,
+  APR_SHA1_DIGESTSIZE,
+  sizeof(apr_uint32_t),
+  sizeof(apr_uint32_t)
+};
+
 /* Returns the digest size of it's argument. */
-#define DIGESTSIZE(k) ((k) == svn_checksum_md5 ? APR_MD5_DIGESTSIZE : \
-                       (k) == svn_checksum_sha1 ? APR_SHA1_DIGESTSIZE : 0)
+#define DIGESTSIZE(k) \
+  (((k) < svn_checksum_md5 || (k) > svn_checksum_fnv1a_32x4) ? 0 : digest_sizes[k])
+
+/* Largest supported digest size */
+#define MAX_DIGESTSIZE (MAX(APR_MD5_DIGESTSIZE,APR_SHA1_DIGESTSIZE))
+
+const unsigned char *
+svn__empty_string_digest(svn_checksum_kind_t kind)
+{
+  return empty_string_digests[kind];
+}
 
+const char *
+svn__digest_to_cstring_display(const unsigned char digest[],
+                               apr_size_t digest_size,
+                               apr_pool_t *pool)
+{
+  static const char *hex = "0123456789abcdef";
+  char *str = apr_palloc(pool, (digest_size * 2) + 1);
+  int i;
+
+  for (i = 0; i < digest_size; i++)
+    {
+      str[i*2]   = hex[digest[i] >> 4];
+      str[i*2+1] = hex[digest[i] & 0x0f];
+    }
+  str[i*2] = '\0';
+
+  return str;
+}
+
+
+const char *
+svn__digest_to_cstring(const unsigned char digest[],
+                       apr_size_t digest_size,
+                       apr_pool_t *pool)
+{
+  static const unsigned char zeros_digest[MAX_DIGESTSIZE] = { 0 };
+
+  if (memcmp(digest, zeros_digest, digest_size) != 0)
+    return svn__digest_to_cstring_display(digest, digest_size, pool);
+  else
+    return NULL;
+}
+
+
+svn_boolean_t
+svn__digests_match(const unsigned char d1[],
+                   const unsigned char d2[],
+                   apr_size_t digest_size)
+{
+  static const unsigned char zeros[MAX_DIGESTSIZE] = { 0 };
+
+  return ((memcmp(d1, d2, digest_size) == 0)
+          || (memcmp(d2, zeros, digest_size) == 0)
+          || (memcmp(d1, zeros, digest_size) == 0));
+}
 
 /* Check to see if KIND is something we recognize.  If not, return
  * SVN_ERR_BAD_CHECKSUM_KIND */
 static svn_error_t *
 validate_kind(svn_checksum_kind_t kind)
 {
-  if (kind == svn_checksum_md5 || kind == svn_checksum_sha1)
+  if (kind >= svn_checksum_md5 && kind <= svn_checksum_fnv1a_32x4)
     return SVN_NO_ERROR;
   else
     return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -93,11 +185,12 @@ svn_checksum_create(svn_checksum_kind_t 
   switch (kind)
     {
       case svn_checksum_md5:
-        digest_size = APR_MD5_DIGESTSIZE;
-        break;
       case svn_checksum_sha1:
-        digest_size = APR_SHA1_DIGESTSIZE;
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        digest_size = digest_sizes[kind];
         break;
+
       default:
         return NULL;
     }
@@ -123,6 +216,22 @@ svn_checksum__from_digest_sha1(const uns
                          result_pool);
 }
 
+svn_checksum_t *
+svn_checksum__from_digest_fnv1a_32(const unsigned char *digest,
+                                   apr_pool_t *result_pool)
+{
+  return checksum_create(svn_checksum_fnv1a_32, sizeof(digest), digest,
+                         result_pool);
+}
+
+svn_checksum_t *
+svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest,
+                                     apr_pool_t *result_pool)
+{
+  return checksum_create(svn_checksum_fnv1a_32x4, sizeof(digest), digest,
+                         result_pool);
+}
+
 svn_error_t *
 svn_checksum_clear(svn_checksum_t *checksum)
 {
@@ -145,9 +254,13 @@ svn_checksum_match(const svn_checksum_t 
   switch (checksum1->kind)
     {
       case svn_checksum_md5:
-        return svn_md5__digests_match(checksum1->digest, checksum2->digest);
       case svn_checksum_sha1:
-        return svn_sha1__digests_match(checksum1->digest, checksum2->digest);
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return svn__digests_match(checksum1->digest,
+                                  checksum2->digest,
+                                  digest_sizes[checksum1->kind]);
+
       default:
         /* We really shouldn't get here, but if we do... */
         return FALSE;
@@ -161,9 +274,13 @@ svn_checksum_to_cstring_display(const sv
   switch (checksum->kind)
     {
       case svn_checksum_md5:
-        return svn_md5__digest_to_cstring_display(checksum->digest, pool);
       case svn_checksum_sha1:
-        return svn_sha1__digest_to_cstring_display(checksum->digest, pool);
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return svn__digest_to_cstring_display(checksum->digest,
+                                              digest_sizes[checksum->kind],
+                                              pool);
+
       default:
         /* We really shouldn't get here, but if we do... */
         return NULL;
@@ -180,9 +297,13 @@ svn_checksum_to_cstring(const svn_checks
   switch (checksum->kind)
     {
       case svn_checksum_md5:
-        return svn_md5__digest_to_cstring(checksum->digest, pool);
       case svn_checksum_sha1:
-        return svn_sha1__digest_to_cstring(checksum->digest, pool);
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return svn__digest_to_cstring(checksum->digest,
+                                      digest_sizes[checksum->kind],
+                                      pool);
+
       default:
         /* We really shouldn't get here, but if we do... */
         return NULL;
@@ -197,8 +318,8 @@ svn_checksum_serialize(const svn_checksu
 {
   const char *ckind_str;
 
-  SVN_ERR_ASSERT_NO_RETURN(checksum->kind == svn_checksum_md5
-                           || checksum->kind == svn_checksum_sha1);
+  SVN_ERR_ASSERT_NO_RETURN(checksum->kind >= svn_checksum_md5
+                           || checksum->kind <= svn_checksum_fnv1a_32x4);
   ckind_str = (checksum->kind == svn_checksum_md5 ? "$md5 $" : "$sha1$");
   return apr_pstrcat(result_pool,
                      ckind_str,
@@ -302,11 +423,14 @@ svn_checksum_dup(const svn_checksum_t *c
   switch (checksum->kind)
     {
       case svn_checksum_md5:
-        return svn_checksum__from_digest_md5(checksum->digest, pool);
-        break;
       case svn_checksum_sha1:
-        return svn_checksum__from_digest_sha1(checksum->digest, pool);
-        break;
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return checksum_create(checksum->kind,
+                               digest_sizes[checksum->kind],
+                               checksum->digest,
+                               pool);
+
       default:
         SVN_ERR_MALFUNCTION_NO_RETURN();
         break;
@@ -337,6 +461,14 @@ svn_checksum(svn_checksum_t **checksum,
         apr_sha1_final((unsigned char *)(*checksum)->digest, &sha1_ctx);
         break;
 
+      case svn_checksum_fnv1a_32:
+        *(apr_uint32_t *)(*checksum)->digest = svn__fnv1a_32(data, len);
+        break;
+
+      case svn_checksum_fnv1a_32x4:
+        *(apr_uint32_t *)(*checksum)->digest = svn__fnv1a_32x4(data, len);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -353,12 +485,13 @@ svn_checksum_empty_checksum(svn_checksum
   switch (kind)
     {
       case svn_checksum_md5:
-        return svn_checksum__from_digest_md5(svn_md5__empty_string_digest(),
-                                             pool);
-
       case svn_checksum_sha1:
-        return svn_checksum__from_digest_sha1(svn_sha1__empty_string_digest(),
-                                              pool);
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return checksum_create(kind,
+                               digest_sizes[kind],
+                               empty_string_digests[kind],
+                               pool);
 
       default:
         /* We really shouldn't get here, but if we do... */
@@ -391,6 +524,14 @@ svn_checksum_ctx_create(svn_checksum_kin
         apr_sha1_init(ctx->apr_ctx);
         break;
 
+      case svn_checksum_fnv1a_32:
+        ctx->apr_ctx = svn_fnv1a_32__context_create(pool);
+        break;
+
+      case svn_checksum_fnv1a_32x4:
+        ctx->apr_ctx = svn_fnv1a_32x4__context_create(pool);
+        break;
+
       default:
         SVN_ERR_MALFUNCTION_NO_RETURN();
     }
@@ -413,6 +554,14 @@ svn_checksum_update(svn_checksum_ctx_t *
         apr_sha1_update(ctx->apr_ctx, data, (unsigned int)len);
         break;
 
+      case svn_checksum_fnv1a_32:
+        svn_fnv1a_32__update(ctx->apr_ctx, data, len);
+        break;
+
+      case svn_checksum_fnv1a_32x4:
+        svn_fnv1a_32x4__update(ctx->apr_ctx, data, len);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -438,6 +587,16 @@ svn_checksum_final(svn_checksum_t **chec
         apr_sha1_final((unsigned char *)(*checksum)->digest, ctx->apr_ctx);
         break;
 
+      case svn_checksum_fnv1a_32:
+        *(apr_uint32_t *)(*checksum)->digest
+          = svn_fnv1a_32__finalize(ctx->apr_ctx);
+        break;
+
+      case svn_checksum_fnv1a_32x4:
+        *(apr_uint32_t *)(*checksum)->digest
+          = svn_fnv1a_32x4__finalize(ctx->apr_ctx);
+        break;
+
       default:
         /* We really shouldn't get here, but if we do... */
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, NULL);
@@ -486,12 +645,12 @@ svn_checksum_is_empty_checksum(svn_check
   switch (checksum->kind)
     {
       case svn_checksum_md5:
-        return svn_md5__digests_match(checksum->digest,
-                                      svn_md5__empty_string_digest());
-
       case svn_checksum_sha1:
-        return svn_sha1__digests_match(checksum->digest,
-                                       svn_sha1__empty_string_digest());
+      case svn_checksum_fnv1a_32:
+      case svn_checksum_fnv1a_32x4:
+        return svn__digests_match(checksum->digest,
+                                  svn__empty_string_digest(checksum->kind),
+                                  digest_sizes[checksum->kind]);
 
       default:
         /* We really shouldn't get here, but if we do... */

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_file.c Sun Dec  1 18:51:26 2013
@@ -412,7 +412,7 @@ svn_config__sys_config_path(const char *
 #ifdef WIN32
   {
     const char *folder;
-    SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool));
+    SVN_ERR(svn_config__win_config_path(&folder, TRUE, pool, pool));
     *path_p = svn_dirent_join_many(pool, folder,
                                    SVN_CONFIG__SUBDIRECTORY, fname,
                                    SVN_VA_NULL);
@@ -1370,7 +1370,11 @@ svn_config_get_user_config_path(const ch
 #ifdef WIN32
   {
     const char *folder;
-    SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool));
+    SVN_ERR(svn_config__win_config_path(&folder, FALSE, pool, pool));
+
+    if (! folder)
+      return SVN_NO_ERROR;
+
     *path = svn_dirent_join_many(pool, folder,
                                  SVN_CONFIG__SUBDIRECTORY, fname, SVN_VA_NULL);
   }

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_impl.h Sun Dec  1 18:51:26 2013
@@ -96,8 +96,9 @@ svn_error_t *svn_config__parse_stream(sv
 #ifdef WIN32
 /* Get the common or user-specific AppData folder */
 svn_error_t *svn_config__win_config_path(const char **folder,
-                                         int system_path,
-                                         apr_pool_t *pool);
+                                         svn_boolean_t system_path,
+                                         apr_pool_t *scratch_pool,
+                                         apr_pool_t *result_pool);
 
 /* Read sections and options from the Windows Registry. */
 svn_error_t *svn_config__parse_registry(svn_config_t *cfg,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_win.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/config_win.c Sun Dec  1 18:51:26 2013
@@ -46,8 +46,12 @@
 #include "svn_utf.h"
 #include "private/svn_utf_private.h"
 
+#include "config_impl.h"
+
 svn_error_t *
-svn_config__win_config_path(const char **folder, int system_path,
+svn_config__win_config_path(const char **folder,
+                            svn_boolean_t system_path,
+                            apr_pool_t *scratch_pool,
                             apr_pool_t *result_pool)
 {
   /* ### Adding CSIDL_FLAG_CREATE here, because those folders really
@@ -57,6 +61,30 @@ svn_config__win_config_path(const char *
                      | CSIDL_FLAG_CREATE);
 
   WCHAR folder_ucs2[MAX_PATH];
+  const char *folder_utf8;
+
+  if (! system_path)
+    {
+      HKEY hkey_tmp;
+
+      /* Verify if we actually have a *per user* profile to read from */
+      if (ERROR_SUCCESS == RegOpenCurrentUser(KEY_SET_VALUE, &hkey_tmp))
+        RegCloseKey(hkey_tmp); /* We have a profile */
+      else
+        {
+          /* The user is not properly logged in. (Most likely we are running
+             in a service process). In this case Windows will return a default
+             read only 'roaming profile' directory, which we assume to be
+             writable. We will then spend many seconds trying to create a
+             configuration and then fail, because we are not allowed to write
+             there, but the retry loop in io.c doesn't know that.
+
+             We just answer that there is no user configuration directory. */
+
+          *folder = NULL;
+          return SVN_NO_ERROR;
+        }
+    }
 
   if (S_OK != SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT,
                                folder_ucs2))
@@ -65,16 +93,17 @@ svn_config__win_config_path(const char *
                            ? "Can't determine the system config path"
                            : "Can't determine the user's config path"));
 
-  return svn_error_trace(svn_utf__win32_utf16_to_utf8(folder, folder_ucs2,
-                                                      NULL, result_pool));
+  SVN_ERR(svn_utf__win32_utf16_to_utf8(&folder_utf8, folder_ucs2,
+                                       NULL, scratch_pool));
+  *folder = svn_dirent_internal_style(folder_utf8, result_pool);
+
+  return SVN_NO_ERROR;
 }
 
 
-#include "config_impl.h"
 
-/* ### These constants are insanely large, but (a) we want to avoid
-   reallocating strings if possible, and (b) the realloc logic might
-   not actually work -- you never know with Win32 ... */
+/* ### These constants are insanely large, but we want to avoid
+   reallocating strings if possible. */
 #define SVN_REG_DEFAULT_NAME_SIZE  2048
 #define SVN_REG_DEFAULT_VALUE_SIZE 8192
 

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.c?rev=1546837&r1=1546836&r2=1546837&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/md5.c Sun Dec  1 18:51:26 2013
@@ -23,88 +23,36 @@
 
 
 #include <apr_md5.h>
-#include "md5.h"
+
+#include "svn_checksum.h"
 #include "svn_md5.h"
+#include "checksum.h"
 
 
 
-/* The MD5 digest for the empty string. */
-static const unsigned char svn_md5__empty_string_digest_array[] = {
-  0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
-  0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
-};
-
-const unsigned char *
-svn_md5__empty_string_digest(void)
-{
-  return svn_md5__empty_string_digest_array;
-}
-
-
-const char *
-svn_md5__digest_to_cstring_display(const unsigned char digest[],
-                                   apr_pool_t *pool)
-{
-  static const char *hex = "0123456789abcdef";
-  char *str = apr_palloc(pool, (APR_MD5_DIGESTSIZE * 2) + 1);
-  int i;
-
-  for (i = 0; i < APR_MD5_DIGESTSIZE; i++)
-    {
-      str[i*2]   = hex[digest[i] >> 4];
-      str[i*2+1] = hex[digest[i] & 0x0f];
-    }
-  str[i*2] = '\0';
-
-  return str;
-}
-
-
-const char *
-svn_md5__digest_to_cstring(const unsigned char digest[], apr_pool_t *pool)
-{
-  static const unsigned char zeros_digest[APR_MD5_DIGESTSIZE] = { 0 };
-
-  if (memcmp(digest, zeros_digest, APR_MD5_DIGESTSIZE) != 0)
-    return svn_md5__digest_to_cstring_display(digest, pool);
-  else
-    return NULL;
-}
-
-
-svn_boolean_t
-svn_md5__digests_match(const unsigned char d1[], const unsigned char d2[])
-{
-  static const unsigned char zeros[APR_MD5_DIGESTSIZE] = { 0 };
-
-  return ((memcmp(d1, zeros, APR_MD5_DIGESTSIZE) == 0)
-          || (memcmp(d2, zeros, APR_MD5_DIGESTSIZE) == 0)
-          || (memcmp(d1, d2, APR_MD5_DIGESTSIZE) == 0));
-}
-
 /* These are all deprecated, and just wrap the internal functions defined
    above. */
 const unsigned char *
 svn_md5_empty_string_digest(void)
 {
-  return svn_md5__empty_string_digest();
+  return svn__empty_string_digest(svn_checksum_md5);
 }
 
 const char *
 svn_md5_digest_to_cstring_display(const unsigned char digest[],
                                   apr_pool_t *pool)
 {
-  return svn_md5__digest_to_cstring_display(digest, pool);
+  return svn__digest_to_cstring_display(digest, APR_MD5_DIGESTSIZE, pool);
 }
 
 const char *
 svn_md5_digest_to_cstring(const unsigned char digest[], apr_pool_t *pool)
 {
-  return svn_md5__digest_to_cstring(digest, pool);
+  return svn__digest_to_cstring(digest, APR_MD5_DIGESTSIZE, pool);
 }
 
 svn_boolean_t
 svn_md5_digests_match(const unsigned char d1[], const unsigned char d2[])
 {
-  return svn_md5__digests_match(d1, d2);
+  return svn__digests_match(d1, d2, APR_MD5_DIGESTSIZE);
 }