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 20:37:31 UTC

svn commit: r1546842 - in /subversion/branches/log-addressing: ./ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/include/ subversion/libsvn_client/ subversion/libsvn_fs/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_x/ subver...

Author: stefan2
Date: Sun Dec  1 19:37:30 2013
New Revision: 1546842

URL: http://svn.apache.org/r1546842
Log:
On the log-addressing branch: sync with the parent branch and
resolve a few trivial conflicts.

Modified:
    subversion/branches/log-addressing/   (props changed)
    subversion/branches/log-addressing/CHANGES
    subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
    subversion/branches/log-addressing/subversion/include/svn_fs.h
    subversion/branches/log-addressing/subversion/libsvn_client/merge.c
    subversion/branches/log-addressing/subversion/libsvn_fs/editor.c
    subversion/branches/log-addressing/subversion/libsvn_fs/fs-loader.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/transaction.c
    subversion/branches/log-addressing/subversion/libsvn_fs_x/   (props changed)
    subversion/branches/log-addressing/subversion/libsvn_fs_x/fs_x.c
    subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c
    subversion/branches/log-addressing/subversion/libsvn_repos/dump.c
    subversion/branches/log-addressing/subversion/libsvn_repos/fs-wrap.c
    subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c
    subversion/branches/log-addressing/subversion/libsvn_subr/config_impl.h
    subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c
    subversion/branches/log-addressing/subversion/svn/mergeinfo-cmd.c
    subversion/branches/log-addressing/subversion/svnadmin/svnadmin.c
    subversion/branches/log-addressing/subversion/tests/cmdline/mergeinfo_tests.py
    subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
    subversion/branches/log-addressing/subversion/tests/cmdline/svntest/main.py
    subversion/branches/log-addressing/subversion/tests/libsvn_fs/fs-test.c
    subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/   (props changed)
    subversion/branches/log-addressing/subversion/tests/libsvn_repos/repos-test.c
    subversion/branches/log-addressing/subversion/tests/libsvn_subr/checksum-test.c
    subversion/branches/log-addressing/subversion/tests/svn_test_main.c

Propchange: subversion/branches/log-addressing/
------------------------------------------------------------------------------
  Merged /subversion/branches/fsfs-improvements:r1545956-1546837
  Merged /subversion/trunk:r1545955-1546835
  Merged /subversion/branches/verify-keep-going:r1492640-1546110

Modified: subversion/branches/log-addressing/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/CHANGES?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/CHANGES (original)
+++ subversion/branches/log-addressing/CHANGES Sun Dec  1 19:37:30 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/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/branches/log-addressing/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Sun Dec  1 19:37:30 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/log-addressing/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/include/svn_fs.h?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/include/svn_fs.h (original)
+++ subversion/branches/log-addressing/subversion/include/svn_fs.h Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_client/merge.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_client/merge.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs/editor.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs/editor.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs/fs-loader.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs/fs-loader.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_fs_fs/recovery.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c Sun Dec  1 19:37:30 2013
@@ -56,6 +56,7 @@ recover_get_largest_revision(svn_fs_t *f
       svn_error_t *err;
       svn_fs_fs__revision_file_t *file;
       svn_pool_clear(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)
@@ -79,6 +80,7 @@ recover_get_largest_revision(svn_fs_t *f
       svn_error_t *err;
       svn_fs_fs__revision_file_t *file;
       svn_pool_clear(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)

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/transaction.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/transaction.c Sun Dec  1 19:37:30 2013
@@ -3736,7 +3736,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;
@@ -3807,7 +3811,11 @@ commit_body(void *baton, apr_pool_t *poo
                       new_rev, pool));
     }
 
-  /* 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);

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

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/fs_x.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/fs_x.c Sun Dec  1 19:37:30 2013
@@ -800,7 +800,7 @@ svn_fs_x__create(svn_fs_t *fs,
           case 6:
           case 7:
           case 8: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
-                  _("FSFS is not compatible with Subversion prior to 1.9"));
+                  _("FSX is not compatible with Subversion prior to 1.9"));
 
           default:format = SVN_FS_X__FORMAT_NUMBER;
         }

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_x/transaction.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/dump.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/dump.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_repos/fs-wrap.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_repos/fs-wrap.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config_file.c Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_subr/config_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config_impl.h?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config_impl.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config_impl.h Sun Dec  1 19:37:30 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/log-addressing/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_subr/config_win.c Sun Dec  1 19:37:30 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/log-addressing/subversion/svn/mergeinfo-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svn/mergeinfo-cmd.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svn/mergeinfo-cmd.c (original)
+++ subversion/branches/log-addressing/subversion/svn/mergeinfo-cmd.c Sun Dec  1 19:37:30 2013
@@ -275,7 +275,8 @@ mergeinfo_summary(
 
   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);
   SVN_ERR(svn_client_get_merging_summary(
             &is_reintegration,
             &yca_url, &yca_rev,

Modified: subversion/branches/log-addressing/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnadmin/svnadmin.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/log-addressing/subversion/svnadmin/svnadmin.c Sun Dec  1 19:37:30 2013
@@ -805,6 +805,34 @@ subcommand_deltify(apr_getopt_t *os, voi
   return SVN_NO_ERROR;
 }
 
+/* Structure for errors encountered during 'svnadmin verify --keep-going'. */
+struct verification_error
+{
+  svn_revnum_t rev;
+  svn_error_t *err;
+};
+
+/* Pool cleanup function to clear an svn_error_t *. */
+static apr_status_t
+err_cleanup(void *data)
+{
+  svn_error_t *err = data;
+
+  svn_error_clear(err);
+
+  return APR_SUCCESS;
+}
+
+struct repos_notify_handler_baton {
+  /* Stream to write progress and other non-error output to. */
+  svn_stream_t *feedback_stream;
+
+  /* List of errors encountered during 'svnadmin verify --keep-going'. */
+  apr_array_header_t *error_summary;
+
+  /* Pool for data collected during notifications. */
+  apr_pool_t *result_pool;
+};
 
 /* Implementation of svn_repos_notify_func_t to wrap the output to a
    response stream for svn_repos_dump_fs2() and svn_repos_verify_fs() */
@@ -813,7 +841,8 @@ repos_notify_handler(void *baton,
                      const svn_repos_notify_t *notify,
                      apr_pool_t *scratch_pool)
 {
-  svn_stream_t *feedback_stream = baton;
+  struct repos_notify_handler_baton *b = baton;
+  svn_stream_t *feedback_stream = b->feedback_stream;
 
   switch (notify->action)
   {
@@ -829,8 +858,22 @@ repos_notify_handler(void *baton,
                                     _("* Error verifying revision %ld.\n"),
                                     notify->revision));
       if (notify->err)
-        svn_handle_error2(notify->err, stderr, FALSE /* non-fatal */,
-                          "svnadmin: ");
+        {
+          svn_handle_error2(notify->err, stderr, FALSE /* non-fatal */,
+                            "svnadmin: ");
+          if (b->error_summary && notify->revision != SVN_INVALID_REVNUM)
+            {
+              struct verification_error *verr;
+              
+              verr = apr_palloc(b->result_pool, sizeof(*verr));
+              verr->rev = notify->revision;
+              verr->err = svn_error_dup(notify->err);
+              apr_pool_cleanup_register(b->result_pool, verr->err, err_cleanup,
+                                        apr_pool_cleanup_null);
+              APR_ARRAY_PUSH(b->error_summary,
+                             struct verification_error *) = verr;
+            }
+        }
       return;
 
     case svn_repos_notify_dump_rev_end:
@@ -1065,7 +1108,7 @@ subcommand_dump(apr_getopt_t *os, void *
   svn_stream_t *stdout_stream;
   svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
   svn_revnum_t youngest;
-  svn_stream_t *progress_stream = NULL;
+  struct repos_notify_handler_baton notify_baton = { 0 };
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
@@ -1099,12 +1142,12 @@ subcommand_dump(apr_getopt_t *os, void *
 
   /* Progress feedback goes to STDERR, unless they asked to suppress it. */
   if (! opt_state->quiet)
-    progress_stream = recode_stream_create(stderr, pool);
+    notify_baton.feedback_stream = recode_stream_create(stderr, pool);
 
   SVN_ERR(svn_repos_dump_fs3(repos, stdout_stream, lower, upper,
                              opt_state->incremental, opt_state->use_deltas,
                              !opt_state->quiet ? repos_notify_handler : NULL,
-                             progress_stream, check_cancel, NULL, pool));
+                             &notify_baton, check_cancel, NULL, pool));
 
   return SVN_NO_ERROR;
 }
@@ -1251,7 +1294,8 @@ subcommand_load(apr_getopt_t *os, void *
   struct svnadmin_opt_state *opt_state = baton;
   svn_repos_t *repos;
   svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
-  svn_stream_t *stdin_stream, *stdout_stream = NULL;
+  svn_stream_t *stdin_stream;
+  struct repos_notify_handler_baton notify_baton = { 0 };
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
@@ -1285,7 +1329,7 @@ subcommand_load(apr_getopt_t *os, void *
 
   /* Progress feedback goes to STDOUT, unless they asked to suppress it. */
   if (! opt_state->quiet)
-    stdout_stream = recode_stream_create(stdout, pool);
+    notify_baton.feedback_stream = recode_stream_create(stdout, pool);
 
   err = svn_repos_load_fs4(repos, stdin_stream, lower, upper,
                            opt_state->uuid_action, opt_state->parent_dir,
@@ -1293,7 +1337,7 @@ subcommand_load(apr_getopt_t *os, void *
                            opt_state->use_post_commit_hook,
                            !opt_state->bypass_prop_validation,
                            opt_state->quiet ? NULL : repos_notify_handler,
-                           stdout_stream, check_cancel, NULL, pool);
+                           &notify_baton, check_cancel, NULL, pool);
   if (err && err->apr_err == SVN_ERR_BAD_PROPERTY_VALUE)
     return svn_error_quick_wrap(err,
                                 _("Invalid property value found in "
@@ -1340,12 +1384,12 @@ subcommand_recover(apr_getopt_t *os, voi
   svn_repos_t *repos;
   svn_error_t *err;
   struct svnadmin_opt_state *opt_state = baton;
-  svn_stream_t *stdout_stream;
+  struct repos_notify_handler_baton notify_baton = { 0 };
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
 
-  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
+  SVN_ERR(svn_stream_for_stdout(&notify_baton.feedback_stream, pool));
 
   /* Restore default signal handlers until after we have acquired the
    * exclusive lock so that the user interrupt before we actually
@@ -1353,7 +1397,7 @@ subcommand_recover(apr_getopt_t *os, voi
   setup_cancellation_signals(SIG_DFL);
 
   err = svn_repos_recover4(opt_state->repository_path, TRUE,
-                           repos_notify_handler, stdout_stream,
+                           repos_notify_handler, &notify_baton,
                            check_cancel, NULL, pool);
   if (err)
     {
@@ -1371,7 +1415,7 @@ subcommand_recover(apr_getopt_t *os, voi
                                    " another process has it open?\n")));
       SVN_ERR(svn_cmdline_fflush(stdout));
       SVN_ERR(svn_repos_recover4(opt_state->repository_path, FALSE,
-                                 repos_notify_handler, stdout_stream,
+                                 repos_notify_handler, &notify_baton,
                                  check_cancel, NULL, pool));
     }
 
@@ -1626,7 +1670,7 @@ subcommand_pack(apr_getopt_t *os, void *
 {
   struct svnadmin_opt_state *opt_state = baton;
   svn_repos_t *repos;
-  svn_stream_t *progress_stream = NULL;
+  struct repos_notify_handler_baton notify_baton = { 0 };
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
@@ -1635,11 +1679,11 @@ subcommand_pack(apr_getopt_t *os, void *
 
   /* Progress feedback goes to STDOUT, unless they asked to suppress it. */
   if (! opt_state->quiet)
-    progress_stream = recode_stream_create(stdout, pool);
+    notify_baton.feedback_stream = recode_stream_create(stdout, pool);
 
   return svn_error_trace(
     svn_repos_fs_pack2(repos, !opt_state->quiet ? repos_notify_handler : NULL,
-                       progress_stream, check_cancel, NULL, pool));
+                       &notify_baton, check_cancel, NULL, pool));
 }
 
 
@@ -1651,7 +1695,8 @@ subcommand_verify(apr_getopt_t *os, void
   svn_repos_t *repos;
   svn_fs_t *fs;
   svn_revnum_t youngest, lower, upper;
-  svn_stream_t *progress_stream = NULL;
+  struct repos_notify_handler_baton notify_baton = { 0 };
+  svn_error_t *verify_err;
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
@@ -1696,15 +1741,79 @@ subcommand_verify(apr_getopt_t *os, void
     }
 
   if (! opt_state->quiet)
-    progress_stream = recode_stream_create(stdout, pool);
+    notify_baton.feedback_stream = recode_stream_create(stdout, pool);
 
-  return svn_error_trace(svn_repos_verify_fs3(repos, lower, upper,
-                                              opt_state->keep_going,
-                                              opt_state->check_ucs_norm,
-                                              !opt_state->quiet
-                                              ? repos_notify_handler : NULL,
-                                              progress_stream, check_cancel,
-                                              NULL, pool));
+  if (opt_state->keep_going)
+    notify_baton.error_summary =
+      apr_array_make(pool, 0, sizeof(struct verification_error *));
+
+  notify_baton.result_pool = pool;
+
+  verify_err = svn_repos_verify_fs3(repos, lower, upper,
+                                    opt_state->keep_going,
+                                    opt_state->check_ucs_norm,
+                                    !opt_state->quiet
+                                    ? repos_notify_handler : NULL,
+                                    &notify_baton, check_cancel,
+                                    NULL, pool);
+
+  /* Show the --keep-going error summary. */
+  if (opt_state->keep_going && notify_baton.error_summary->nelts > 0)
+    {
+      int rev_maxlength;
+      svn_revnum_t end_revnum;
+      apr_pool_t *iterpool;
+      int i;
+
+      svn_error_clear(
+        svn_stream_puts(notify_baton.feedback_stream,
+                          _("\n-----Summary of corrupt revisions-----\n")));
+
+      /* The standard column width for the revision number is 6 characters.
+         If the revision number can potentially be larger (i.e. if end_revnum
+         is larger than 1000000), we increase the column width as needed. */
+      rev_maxlength = 6;
+      end_revnum = APR_ARRAY_IDX(notify_baton.error_summary,
+                                 notify_baton.error_summary->nelts - 1,
+                                 struct verification_error *)->rev;
+      while (end_revnum >= 1000000)
+        {
+          rev_maxlength++;
+          end_revnum = end_revnum / 10;
+        }
+
+      iterpool = svn_pool_create(pool);
+      for (i = 0; i < notify_baton.error_summary->nelts; i++)
+        {
+          struct verification_error *verr;
+          svn_error_t *err;
+          const char *rev_str;
+          
+          svn_pool_clear(iterpool);
+
+          verr = APR_ARRAY_IDX(notify_baton.error_summary, i,
+                               struct verification_error *);
+          rev_str = apr_psprintf(iterpool, "r%ld", verr->rev);
+          rev_str = apr_psprintf(iterpool, "%*s", rev_maxlength, rev_str);
+          for (err = svn_error_purge_tracing(verr->err);
+               err != SVN_NO_ERROR; err = err->child)
+            {
+              char buf[512];
+              const char *message;
+              
+              message = svn_err_best_message(err, buf, sizeof(buf));
+              svn_error_clear(svn_stream_printf(notify_baton.feedback_stream,
+                                                iterpool,
+                                                "%s: E%06d: %s\n",
+                                                rev_str, err->apr_err,
+                                                message));
+            }
+        }
+
+       svn_pool_destroy(iterpool);
+    }
+
+  return svn_error_trace(verify_err);
 }
 
 /* This implements `svn_opt_subcommand_t'. */
@@ -2091,18 +2200,18 @@ subcommand_upgrade(apr_getopt_t *os, voi
 {
   svn_error_t *err;
   struct svnadmin_opt_state *opt_state = baton;
-  svn_stream_t *stdout_stream;
+  struct repos_notify_handler_baton notify_baton = { 0 };
 
   /* Expect no more arguments. */
   SVN_ERR(parse_args(NULL, os, 0, 0, pool));
 
-  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
+  SVN_ERR(svn_stream_for_stdout(&notify_baton.feedback_stream, pool));
 
   /* Restore default signal handlers. */
   setup_cancellation_signals(SIG_DFL);
 
   err = svn_repos_upgrade2(opt_state->repository_path, TRUE,
-                           repos_notify_handler, stdout_stream, pool);
+                           repos_notify_handler, &notify_baton, pool);
   if (err)
     {
       if (APR_STATUS_IS_EAGAIN(err->apr_err))
@@ -2120,7 +2229,7 @@ subcommand_upgrade(apr_getopt_t *os, voi
                                        " another process has it open?\n")));
           SVN_ERR(svn_cmdline_fflush(stdout));
           SVN_ERR(svn_repos_upgrade2(opt_state->repository_path, FALSE,
-                                     repos_notify_handler, stdout_stream,
+                                     repos_notify_handler, &notify_baton,
                                      pool));
         }
       else if (err->apr_err == SVN_ERR_FS_UNSUPPORTED_UPGRADE)

Modified: subversion/branches/log-addressing/subversion/tests/cmdline/mergeinfo_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/mergeinfo_tests.py?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/mergeinfo_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/mergeinfo_tests.py Sun Dec  1 19:37:30 2013
@@ -803,6 +803,20 @@ def mergeinfo_log(sbox):
                                      '--log', sbox.repo_url + '/A',
                                      sbox.ospath('A2'))
 
+@SkipUnless(server_has_mergeinfo)
+@Issue(4301)
+def mergeinfo_local_move(sbox):
+  "'mergeinfo' on a locally moved path"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_move('A', 'A2')
+  svntest.actions.run_and_verify_svn(None,
+                                     None, [],
+                                     'mergeinfo', sbox.repo_url + '/A',
+                                     sbox.ospath('A2'))
+
 
 ########################################################################
 # Run the tests
@@ -822,6 +836,7 @@ test_list = [ None,
               natural_history_is_not_eligible_nor_merged,
               noninheritable_mergeinfo_not_always_eligible,
               mergeinfo_log,
+              mergeinfo_local_move,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests.py?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests.py Sun Dec  1 19:37:30 2013
@@ -1964,21 +1964,26 @@ def verify_keep_going(sbox):
                                                         "--keep-going",
                                                         sbox.repo_dir)
 
-  if (svntest.main.options.server_minor_version < 9):
-    exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
-                                             ".*Verified revision 0.",
-                                             ".*Verified revision 1.",
-                                             ".*Error verifying revision 2.",
-                                             ".*Error verifying revision 3."])
-    exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*",
-                                             "svnadmin: E165011:.*"], False)
-  else:
+  if svntest.main.is_fs_log_addressing():
     exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at revision 0",
                                              ".*Verified revision 0.",
                                              ".*Verified revision 1.",
                                              ".*Verified revision 2.",
                                              ".*Verified revision 3."])
     exp_err = svntest.verify.RegexListOutput(["svnadmin: E165011:.*"], False)
+  else:
+    exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+                                              ".*Verified revision 0.",
+                                              ".*Verified revision 1.",
+                                              ".*Error verifying revision 2.",
+                                              ".*Error verifying revision 3.",
+                                              ".*",
+                                              ".*Summary.*",
+                                              ".*r2: E160004:.*",
+                                              ".*r3: E160004:.*",
+                                              ".*r3: E160004:.*"])
+    exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*",
+                                              "svnadmin: E165011:.*"], False)
 
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
@@ -2095,10 +2100,28 @@ def verify_invalid_path_changes(sbox):
                                            ".*Error verifying revision 16.",
                                            ".*Verified revision 17.",
                                            ".*Error verifying revision 18.",
-                                           ".*Verified revision 19."])
+                                           ".*Verified revision 19.",
+                                           ".*",
+                                           ".*Summary.*",
+                                           ".*r2: E160020:.*",
+                                           ".*r2: E160020:.*",
+                                           ".*r4: E160013:.*",
+                                           ".*r6: E160013:.*",
+                                           ".*r6: E160013:.*",
+                                           ".*r10: E160013:.*",
+                                           ".*r10: E160013:.*",
+                                           ".*r12: E145001:.*",
+                                           ".*r12: E145001:.*",
+                                           ".*r14: E160013:.*",
+                                           ".*r14: E160013:.*",
+                                           ".*r16: E145001:.*",
+                                           ".*r16: E145001:.*",
+                                           ".*r18: E160013:.*",
+                                           ".*r18: E160013:.*"])
 
   exp_err = svntest.verify.RegexListOutput(["svnadmin: E160020:.*",
-                                            "svnadmin: E165011:.*"], False)
+                                            "svnadmin: E145001:.*",
+                                            "svnadmin: E160013:.*"], False)
 
 
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
@@ -2108,15 +2131,17 @@ def verify_invalid_path_changes(sbox):
   exit_code, output, errput = svntest.main.run_svnadmin("verify",
                                                         sbox.repo_dir)
 
-  if repo_format(sbox) < 7:
-    exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
-                                            ".*Verified revision 0.",
-                                            ".*Verified revision 1.",
-                                            ".*Error verifying revision 2."])
-  else:
+  if svntest.main.is_fs_log_addressing():
     exp_out = svntest.verify.RegexListOutput([first_line])
     exp_err = svntest.verify.RegexListOutput(["svnadmin: E160058:.*",
                                               "svnadmin: E165011:.*"], False)
+  else:
+    exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+                                              ".*Verified revision 0.",
+                                              ".*Verified revision 1.",
+                                              ".*Error verifying revision 2."])
+    exp_err = svntest.verify.RegexListOutput(["svnadmin: E160020:.*",
+                                              "svnadmin: E165011:.*"], False)
 
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
@@ -2169,7 +2194,8 @@ def verify_denormalized_names(sbox):
     "WARNING 0x0006: Duplicate representation of path '/Q/.*lpha'"
                                   # A/{Eacute}
     " in svn:mergeinfo property of 'A/.*'",
-    ".*Verified revision 6."]
+    ".*Verified revision 6.",
+    ".*Verified revision 7."]
 
   # The BDB backend doesn't do global metadata verification.
   if not svntest.main.is_fs_type_bdb():
@@ -2179,11 +2205,11 @@ def verify_denormalized_names(sbox):
       expected_output_regex_list.insert(0, ".* Verifying metadata at revision 0 ...")
 
   exp_out = svntest.verify.RegexListOutput(expected_output_regex_list)
+  exp_err = svntest.verify.ExpectedOutput([])
 
-  if svntest.verify.verify_outputs(
-      "Unexpected error while running 'svnadmin verify'.",
-      output, errput, exp_out, None):
-    raise svntest.Failure
+  svntest.verify.verify_outputs(
+    "Unexpected error while running 'svnadmin verify'.",
+    output, errput, exp_out, exp_err)
 
 
 ########################################################################

Modified: subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump [UTF-8] (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/svnadmin_tests_data/normalization_check.dump [UTF-8] Sun Dec  1 19:37:30 2013
@@ -225,3 +225,35 @@ V 26
 PROPS-END
 
 
+Revision-number: 7
+Prop-content-length: 130
+Content-length: 130
+
+K 10
+svn:author
+V 7
+jrandom
+K 8
+svn:date
+V 27
+2013-11-24T18:04:51.128158Z
+K 7
+svn:log
+V 25
+Update mergeinfo on A/É
+PROPS-END
+
+Node-path: A/É
+Node-kind: dir
+Node-action: change
+Prop-content-length: 64
+Content-length: 64
+
+K 13
+svn:mergeinfo
+V 29
+/Q/ålpha:71
+/Q/ålpha:69,71
+PROPS-END
+
+

Modified: subversion/branches/log-addressing/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/svntest/main.py?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/svntest/main.py Sun Dec  1 19:37:30 2013
@@ -1337,7 +1337,7 @@ def is_fs_type_bdb():
   return options.fs_type == 'bdb'
 
 def is_fs_log_addressing():
-  return options.fs_type == 'fsx' or \
+  return is_fs_type_fsx() or \
         (is_fs_type_fsfs() and options.server_minor_version >= 9)
 
 def is_os_windows():

Modified: subversion/branches/log-addressing/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_fs/fs-test.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_fs/fs-test.c Sun Dec  1 19:37:30 2013
@@ -5076,6 +5076,76 @@ test_fs_info_format(const svn_test_opts_
 }
 
 static svn_error_t *
+commit_timestamp(const svn_test_opts_t *opts,
+                 apr_pool_t *pool)
+{
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  svn_string_t *date = svn_string_create("Yesterday", pool);
+  svn_revnum_t rev = 0;
+  apr_hash_t *proplist;
+  svn_string_t *svn_date;
+
+  SVN_ERR(svn_test__create_fs(&fs, "test-commit-timestamp",
+                              opts, pool));
+
+  /* Commit with a specified svn:date. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/foo", pool));
+  SVN_ERR(svn_fs_change_txn_prop(txn, SVN_PROP_REVISION_DATE, date, pool));
+  SVN_ERR(svn_fs_commit_txn2(NULL, &rev, txn, FALSE, pool));
+
+  SVN_ERR(svn_fs_revision_proplist(&proplist, fs, rev, pool));
+  svn_date = apr_hash_get(proplist, SVN_PROP_REVISION_DATE,
+                          APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(svn_date && !strcmp(svn_date->data, date->data));
+
+  /* Commit that overwrites the specified svn:date. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/bar", pool));
+  SVN_ERR(svn_fs_change_txn_prop(txn, SVN_PROP_REVISION_DATE, date, pool));
+  SVN_ERR(svn_fs_commit_txn2(NULL, &rev, txn, TRUE, pool));
+
+  SVN_ERR(svn_fs_revision_proplist(&proplist, fs, rev, pool));
+  svn_date = apr_hash_get(proplist, SVN_PROP_REVISION_DATE,
+                          APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(svn_date && strcmp(svn_date->data, date->data));
+
+  /* Commit with a missing svn:date. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/zag", pool));
+  SVN_ERR(svn_fs_change_txn_prop(txn, SVN_PROP_REVISION_DATE, NULL, pool));
+  SVN_ERR(svn_fs_txn_prop(&svn_date, txn, SVN_PROP_REVISION_DATE, pool));
+  SVN_TEST_ASSERT(!svn_date);
+  SVN_ERR(svn_fs_commit_txn2(NULL, &rev, txn, FALSE, pool));
+
+  SVN_ERR(svn_fs_revision_proplist(&proplist, fs, rev, pool));
+  svn_date = apr_hash_get(proplist, SVN_PROP_REVISION_DATE,
+                          APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(!svn_date);
+
+  /* Commit that overwites a missing svn:date. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_dir(txn_root, "/zig", pool));
+  SVN_ERR(svn_fs_change_txn_prop(txn, SVN_PROP_REVISION_DATE, NULL, pool));
+  SVN_ERR(svn_fs_txn_prop(&svn_date, txn, SVN_PROP_REVISION_DATE, pool));
+  SVN_TEST_ASSERT(!svn_date);
+  SVN_ERR(svn_fs_commit_txn2(NULL, &rev, txn, TRUE, pool));
+
+  SVN_ERR(svn_fs_revision_proplist(&proplist, fs, rev, pool));
+  svn_date = apr_hash_get(proplist, SVN_PROP_REVISION_DATE,
+                          APR_HASH_KEY_STRING);
+  SVN_TEST_ASSERT(svn_date);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 test_compat_version(const svn_test_opts_t *opts,
                     apr_pool_t *pool)
 {
@@ -5217,6 +5287,8 @@ struct svn_test_descriptor_t test_funcs[
                        "filenames with trailing \\n might be rejected"),
     SVN_TEST_OPTS_PASS(test_fs_info_format,
                        "test svn_fs_info_format"),
+    SVN_TEST_OPTS_PASS(commit_timestamp,
+                       "commit timestamp"),
     SVN_TEST_OPTS_PASS(test_compat_version,
                        "test svn_fs__compatible_version"),
     SVN_TEST_NULL

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

Modified: subversion/branches/log-addressing/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_repos/repos-test.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_repos/repos-test.c Sun Dec  1 19:37:30 2013
@@ -3545,7 +3545,7 @@ test_repos_fs_type(const svn_test_opts_t
 
 /* The test table.  */
 
-int svn_test_max_threads = 4;
+int svn_test_max_threads = 2;
 
 struct svn_test_descriptor_t test_funcs[] =
   {

Modified: subversion/branches/log-addressing/subversion/tests/libsvn_subr/checksum-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_subr/checksum-test.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_subr/checksum-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_subr/checksum-test.c Sun Dec  1 19:37:30 2013
@@ -303,5 +303,7 @@ struct svn_test_descriptor_t test_funcs[
                    "zero checksum cross-type matching"),
     SVN_TEST_OPTS_PASS(zlib_expansion_test,
                        "zlib expansion test (zlib regression)"),
+    SVN_TEST_PASS2(zero_cross_match,
+                   "zero checksum cross-type matching"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/log-addressing/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/svn_test_main.c?rev=1546842&r1=1546841&r2=1546842&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/svn_test_main.c (original)
+++ subversion/branches/log-addressing/subversion/tests/svn_test_main.c Sun Dec  1 19:37:30 2013
@@ -52,11 +52,8 @@
 
 #include "svn_private_config.h"
 
-#if APR_HAS_THREADS && APR_VERSION_AT_LEAST(1,3,0)
-#  include <apr_thread_pool.h>
-#  define HAVE_THREADPOOLS 1
-#else
-#  define HAVE_THREADPOOLS 0
+#if APR_HAS_THREADS
+#  include <apr_thread_proc.h>
 #endif
 
 /* Some Subversion test programs may want to parse options in the
@@ -420,7 +417,7 @@ do_test_num(const char *progname,
   return skip_cleanup;
 }
 
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
 
 /* Per-test parameters used by test_thread */
 typedef struct test_params_t
@@ -428,67 +425,86 @@ typedef struct test_params_t
   /* Name of the application */
   const char *progname;
 
-  /* Number / index of the test to execute */
-  int test_num;
+  /* Total number of tests to execute */
+  svn_atomic_t test_count;
 
   /* Global test options as provided by main() */
   svn_test_opts_t *opts;
 
-  /* Thread-safe parent pool for the test-specific pool.  We expect the
-     test thread to create a sub-pool and destroy it after test completion. */
-  apr_pool_t *pool;
-
   /* Reference to the global failure flag.  Set this if any test failed. */
-  svn_atomic_t *got_error;
+  svn_atomic_t got_error;
 
-  /* Reference to the global completed test counter. */
-  svn_atomic_t *run_count;
+  /* Test to execute next. */
+  svn_atomic_t test_num;
 } test_params_t;
 
 /* Thread function similar to do_test_num() but with fewer options.  We do
    catch segfaults.  All parameters are given as a test_params_t in DATA.
  */
 static void * APR_THREAD_FUNC
-test_thread(apr_thread_t *tid, void *data)
+test_thread(apr_thread_t *thread, void *data)
 {
   svn_boolean_t skip, xfail, wimp;
   svn_error_t *err = NULL;
   const struct svn_test_descriptor_t *desc;
   svn_boolean_t run_this_test; /* This test's mode matches DESC->MODE. */
   test_params_t *params = data;
+  svn_atomic_t test_num;
 
-  apr_pool_t *test_pool = svn_pool_create(params->pool);
+  apr_pool_t *pool
+    = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
 
-  desc = &test_funcs[params->test_num];
-  skip = desc->mode == svn_test_skip;
-  xfail = desc->mode == svn_test_xfail;
-  wimp = xfail && desc->wip;
-  run_this_test = mode_filter == svn_test_all || mode_filter == desc->mode;
+  for (test_num = svn_atomic_inc(&params->test_num);
+       test_num <= params->test_count;
+       test_num = svn_atomic_inc(&params->test_num))
+    {
+      svn_pool_clear(pool);
+
+      desc = &test_funcs[test_num];
+      skip = desc->mode == svn_test_skip;
+      xfail = desc->mode == svn_test_xfail;
+      wimp = xfail && desc->wip;
+      run_this_test = mode_filter == svn_test_all
+                   || mode_filter == desc->mode;
 
-  /* Do test */
-  if (skip || !run_this_test)
-    ; /* pass */
-  else if (desc->func2)
-    err = (*desc->func2)(test_pool);
-  else
-    err = (*desc->func_opts)(params->opts, test_pool);
+      /* Do test */
+      if (skip || !run_this_test)
+        ; /* pass */
+      else if (desc->func2)
+        err = (*desc->func2)(pool);
+      else
+        err = (*desc->func_opts)(params->opts, pool);
 
-  /* Write results to console */
-  svn_error_clear(svn_mutex__lock(log_mutex));
-  if (log_results(params->progname, params->test_num, FALSE, run_this_test,
-                  skip, xfail, wimp, err, desc->msg, desc))
-    svn_atomic_set(params->got_error, TRUE);
-  svn_error_clear(svn_mutex__unlock(log_mutex, NULL));
+      /* Write results to console */
+      svn_error_clear(svn_mutex__lock(log_mutex));
+      if (log_results(params->progname, test_num, FALSE, run_this_test,
+                      skip, xfail, wimp, err, desc->msg, desc))
+        svn_atomic_set(&params->got_error, TRUE);
+      svn_error_clear(svn_mutex__unlock(log_mutex, NULL));
+    }
 
   /* release all test memory */
-  svn_pool_destroy(test_pool);
+  svn_pool_destroy(pool);
 
-  /* one more test completed */
-  svn_atomic_inc(params->run_count);
-    
+  /* End thread explicitly to prevent APR_INCOMPLETE return codes in
+     apr_thread_join(). */
+  apr_thread_exit(thread, 0);
   return NULL;
 }
 
+/* Log an error with message MSG if the APR status of EXPR is not 0.
+ */
+#define CHECK_STATUS(expr,msg) \
+  do { \
+    apr_status_t rv = (expr); \
+    if (rv) \
+      { \
+        svn_error_t *svn_err__temp = svn_error_wrap_apr(rv, msg); \
+        svn_handle_error2(svn_err__temp, stdout, FALSE, "svn_tests: "); \
+        svn_error_clear(svn_err__temp); \
+      } \
+  } while (0);
+
 /* Execute all ARRAY_SIZE tests concurrently using MAX_THREADS threads.
    Pass PROGNAME and OPTS to the individual tests.  Return TRUE if at least
    one of the tests failed.  Allocate all data in POOL.
@@ -502,56 +518,37 @@ do_tests_concurrently(const char *progna
                       svn_test_opts_t *opts,
                       apr_pool_t *pool)
 {
-  apr_thread_pool_t *threads;
-  apr_status_t status;
-  svn_atomic_t got_error = FALSE;
   int i;
-  svn_atomic_t run_count = 0;
-
-  /* Create the thread pool. */
-  status = apr_thread_pool_create(&threads, max_threads, max_threads, pool);
-  if (status)
-    {
-      printf("apr_thread_pool_create() failed.\n");
-      return TRUE;
-    }
-
-  /* Don't queue requests unless we reached the worker thread limit. */
-  apr_thread_pool_threshold_set(threads, 0);
-
-  /* Generate one task per test and queue them in the thread pool. */
-  for (i = 1; i <= array_size; i++)
-    {
-      test_params_t *params = apr_pcalloc(pool, sizeof(*params));
-      params->got_error = &got_error;
-      params->opts = opts;
-      params->pool = pool;
-      params->progname = progname;
-      params->test_num = i;
-      params->run_count = &run_count;
+  apr_thread_t **threads;
 
-      apr_thread_pool_push(threads, test_thread, params, 0, NULL);
+  /* Prepare thread parameters. */
+  test_params_t params;
+  params.got_error = FALSE;
+  params.opts = opts;
+  params.progname = progname;
+  params.test_num = 1;
+  params.test_count = array_size;
+
+  /* Start all threads. */
+  threads = apr_pcalloc(pool, max_threads * sizeof(*threads));
+  for (i = 0; i < max_threads; ++i)
+    {
+      CHECK_STATUS(apr_thread_create(&threads[i], NULL, test_thread, &params,
+                                     pool),
+                   "creating test thread failed.\n");
+    }
+
+  /* Wait for all tasks (tests) to complete. */
+  for (i = 0; i < max_threads; ++i)
+    {
+      apr_status_t result = 0;
+      CHECK_STATUS(apr_thread_join(&result, threads[i]),
+                   "Waiting for test thread to finish failed.");
+      CHECK_STATUS(result,
+                   "Test thread returned an error.");
     }
-
-  /* Wait for all tasks (tests) to complete.  As it turns out, this is the
-     variant with the least run-time overhead to the test threads. */
-  while (   apr_thread_pool_tasks_count(threads)
-         || apr_thread_pool_busy_count(threads))
-    apr_thread_yield();
   
-  /* For some unknown reason, cleaning POOL (TEST_POOL in main()) does not
-     call the following reliably for all users. */
-  apr_thread_pool_destroy(threads);
-
-  /* Verify that we didn't skip any tasks. */
-  if (run_count != array_size)
-    {
-      printf("Parallel test failure: only %d of %d tests executed.\n",
-             (int)run_count, array_size);
-      return TRUE;
-    }
-
-  return got_error != FALSE;
+  return params.got_error != FALSE;
 }
 
 #endif
@@ -798,7 +795,7 @@ main(int argc, const char *argv[])
               }
             break;
           }
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
         case parallel_opt:
           parallel = TRUE;
           break;
@@ -888,7 +885,7 @@ main(int argc, const char *argv[])
               svn_pool_clear(cleanup_pool);
             }
         }
-#if HAVE_THREADPOOLS
+#if APR_HAS_THREADS
       else
         {
           got_error = do_tests_concurrently(prog_name, array_size,