subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1673997 [2/4] - in /subversion/branches/javahl-1.8-extensions: ./ build/ac-macros/ build/win32/ subversion/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_fs/ subversion/libsvn_ra_serf/ subve...
Date Thu, 16 Apr 2015 03:46:22 GMT
Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_fs_fs/tree.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_fs_fs/tree.c Thu Apr 16 03:46:20 2015
@@ -127,7 +127,6 @@ typedef struct fs_txn_root_data_t
 static svn_error_t * get_dag(dag_node_t **dag_node_p,
                              svn_fs_root_t *root,
                              const char *path,
-                             svn_boolean_t needs_lock_cache,
                              apr_pool_t *pool);
 
 static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev,
@@ -178,34 +177,10 @@ typedef struct cache_entry_t
  */
 enum { BUCKET_COUNT = 256 };
 
-/* Each pool that has received a DAG node, will hold at least on lock on
-   our cache to ensure that the node remains valid despite being allocated
-   in the cache's pool.  This is the structure to represent the lock.
- */
-typedef struct cache_lock_t
-{
-  /* pool holding the lock */
-  apr_pool_t *pool;
-
-  /* cache being locked */
-  fs_fs_dag_cache_t *cache;
-
-  /* next lock. NULL at EOL */
-  struct cache_lock_t *next;
-
-  /* previous lock. NULL at list head. Only then this==cache->first_lock */
-  struct cache_lock_t *prev;
-} cache_lock_t;
-
 /* The actual cache structure.  All nodes will be allocated in POOL.
    When the number of INSERTIONS (i.e. objects created form that pool)
    exceeds a certain threshold, the pool will be cleared and the cache
    with it.
-
-   To ensure that nodes returned from this structure remain valid, the
-   cache will get locked for the lifetime of the _receiving_ pools (i.e.
-   those in which we would allocate the node if there was no cache.).
-   The cache will only be cleared FIRST_LOCK is 0.
  */
 struct fs_fs_dag_cache_t
 {
@@ -221,106 +196,23 @@ struct fs_fs_dag_cache_t
   /* Property lookups etc. have a very high locality (75% re-hit).
      Thus, remember the last hit location for optimistic lookup. */
   apr_size_t last_hit;
-
-  /* List of receiving pools that are still alive. */
-  cache_lock_t *first_lock;
 };
 
-/* Cleanup function to be called when a receiving pool gets cleared.
-   Unlocks the cache once.
- */
-static apr_status_t
-unlock_cache(void *baton_void)
-{
-  cache_lock_t *lock = baton_void;
-
-  /* remove lock from chain. Update the head */
-  if (lock->next)
-    lock->next->prev = lock->prev;
-  if (lock->prev)
-    lock->prev->next = lock->next;
-  else
-    lock->cache->first_lock = lock->next;
-
-  return APR_SUCCESS;
-}
-
-/* Cleanup function to be called when the cache itself gets destroyed.
-   In that case, we must unregister all unlock requests.
- */
-static apr_status_t
-unregister_locks(void *baton_void)
-{
-  fs_fs_dag_cache_t *cache = baton_void;
-  cache_lock_t *lock;
-
-  for (lock = cache->first_lock; lock; lock = lock->next)
-    apr_pool_cleanup_kill(lock->pool,
-                          lock,
-                          unlock_cache);
-
-  return APR_SUCCESS;
-}
-
 fs_fs_dag_cache_t*
 svn_fs_fs__create_dag_cache(apr_pool_t *pool)
 {
   fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result));
   result->pool = svn_pool_create(pool);
 
-  apr_pool_cleanup_register(pool,
-                            result,
-                            unregister_locks,
-                            apr_pool_cleanup_null);
-
   return result;
 }
 
-/* Prevent the entries in CACHE from being destroyed, for as long as the
-   POOL lives.
- */
-static void
-lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool)
-{
-  /* we only need to lock / unlock once per pool.  Since we will often ask
-     for multiple nodes with the same pool, we can reduce the overhead.
-     However, if e.g. pools are being used in an alternating pattern,
-     we may lock the cache more than once for the same pool (and register
-     just as many cleanup actions).
-   */
-  cache_lock_t *lock = cache->first_lock;
-
-  /* try to find an existing lock for POOL.
-     But limit the time spent on chasing pointers.  */
-  int limiter = 8;
-  while (lock && --limiter)
-      if (lock->pool == pool)
-        return;
-
-  /* create a new lock and put it at the beginning of the lock chain */
-  lock = apr_palloc(pool, sizeof(*lock));
-  lock->cache = cache;
-  lock->pool = pool;
-  lock->next = cache->first_lock;
-  lock->prev = NULL;
-
-  if (cache->first_lock)
-    cache->first_lock->prev = lock;
-  cache->first_lock = lock;
-
-  /* instruct POOL to remove the look upon cleanup */
-  apr_pool_cleanup_register(pool,
-                            lock,
-                            unlock_cache,
-                            apr_pool_cleanup_null);
-}
-
 /* Clears the CACHE at regular intervals (destroying all cached nodes)
  */
 static void
 auto_clear_dag_cache(fs_fs_dag_cache_t* cache)
 {
-  if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT)
+  if (cache->insertions > BUCKET_COUNT)
     {
       svn_pool_clear(cache->pool);
 
@@ -433,18 +325,12 @@ locate_cache(svn_cache__t **cache,
     }
 }
 
-/* Return NODE for PATH from ROOT's node cache, or NULL if the node
-   isn't cached; read it from the FS. *NODE remains valid until either
-   POOL or the FS gets cleared or destroyed (whichever comes first).
-
-   Since locking can be expensive and POOL may be long-living, for
-   nodes that will not need to survive the next call to this function,
-   set NEEDS_LOCK_CACHE to FALSE. */
+/* Return NODE_P for PATH from ROOT's node cache, or NULL if the node
+   isn't cached; read it from the FS. *NODE_P is allocated in POOL. */
 static svn_error_t *
 dag_node_cache_get(dag_node_t **node_p,
                    svn_fs_root_t *root,
                    const char *path,
-                   svn_boolean_t needs_lock_cache,
                    apr_pool_t *pool)
 {
   svn_boolean_t found;
@@ -466,25 +352,23 @@ dag_node_cache_get(dag_node_t **node_p,
       if (bucket->node == NULL)
         {
           locate_cache(&cache, &key, root, path, pool);
-          SVN_ERR(svn_cache__get((void **)&node, &found, cache, key,
-                                 ffd->dag_node_cache->pool));
+          SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool));
           if (found && node)
             {
               /* Patch up the FS, since this might have come from an old FS
               * object. */
               svn_fs_fs__dag_set_fs(node, root->fs);
-              bucket->node = node;
+
+              /* Retain the DAG node in L1 cache. */
+              bucket->node = svn_fs_fs__dag_dup(node,
+                                                ffd->dag_node_cache->pool);
             }
         }
       else
         {
-          node = bucket->node;
+          /* Copy the node from L1 cache into the passed-in POOL. */
+          node = svn_fs_fs__dag_dup(bucket->node, pool);
         }
-
-      /* if we found a node, make sure it remains valid at least as long
-         as it would when allocated in POOL. */
-      if (node && needs_lock_cache)
-        lock_cache(ffd->dag_node_cache, pool);
     }
   else
     {
@@ -822,7 +706,7 @@ get_copy_inheritance(copy_id_inherit_t *
   SVN_ERR(svn_fs_fs__dag_get_copyroot(&copyroot_rev, &copyroot_path,
                                       child->node));
   SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev, pool));
-  SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, FALSE, pool));
+  SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
   copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
 
   if (svn_fs_fs__id_compare(copyroot_id, child_id) == -1)
@@ -938,7 +822,7 @@ open_path(parent_path_t **parent_path_p,
     {
       directory = svn_dirent_dirname(path, pool);
       if (directory[1] != 0) /* root nodes are covered anyway */
-        SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
+        SVN_ERR(dag_node_cache_get(&here, root, directory, pool));
     }
 
   /* did the shortcut work? */
@@ -998,8 +882,8 @@ open_path(parent_path_t **parent_path_p,
              element if we already know the lookup to fail for the
              complete path. */
           if (next || !(flags & open_path_uncached))
-            SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far,
-                                       TRUE, pool));
+            SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, pool));
+
           if (cached_node)
             child = cached_node;
           else
@@ -1136,8 +1020,7 @@ make_path_mutable(svn_fs_root_t *root,
                                           parent_path->node));
       SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, root->fs,
                                        copyroot_rev, pool));
-      SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path,
-                      FALSE, pool));
+      SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
 
       child_id = svn_fs_fs__dag_get_id(parent_path->node);
       copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
@@ -1174,16 +1057,11 @@ make_path_mutable(svn_fs_root_t *root,
 
 /* Open the node identified by PATH in ROOT.  Set DAG_NODE_P to the
    node we find, allocated in POOL.  Return the error
-   SVN_ERR_FS_NOT_FOUND if this node doesn't exist.
-
-   Since locking can be expensive and POOL may be long-living, for
-   nodes that will not need to survive the next call to this function,
-   set NEEDS_LOCK_CACHE to FALSE. */
+   SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
 static svn_error_t *
 get_dag(dag_node_t **dag_node_p,
         svn_fs_root_t *root,
         const char *path,
-        svn_boolean_t needs_lock_cache,
         apr_pool_t *pool)
 {
   parent_path_t *parent_path;
@@ -1192,7 +1070,7 @@ get_dag(dag_node_t **dag_node_p,
   /* First we look for the DAG in our cache
      (if the path may be canonical). */
   if (*path == '/')
-    SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool));
+    SVN_ERR(dag_node_cache_get(&node, root, path, pool));
 
   if (! node)
     {
@@ -1202,8 +1080,7 @@ get_dag(dag_node_t **dag_node_p,
           path = svn_fs__canonicalize_abspath(path, pool);
 
           /* Try again with the corrected path. */
-          SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache,
-                                     pool));
+          SVN_ERR(dag_node_cache_get(&node, root, path, pool));
         }
 
       if (! node)
@@ -1281,7 +1158,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **i
     {
       dag_node_t *node;
 
-      SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+      SVN_ERR(get_dag(&node, root, path, pool));
       *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool);
     }
   return SVN_NO_ERROR;
@@ -1296,7 +1173,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t
 {
   dag_node_t *node;
 
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
   return svn_fs_fs__dag_get_revision(revision, node, pool);
 }
 
@@ -1311,7 +1188,7 @@ fs_node_created_path(const char **create
 {
   dag_node_t *node;
 
-  SVN_ERR(get_dag(&node, root, path, TRUE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
   *created_path = svn_fs_fs__dag_get_created_path(node);
 
   return SVN_NO_ERROR;
@@ -1375,7 +1252,7 @@ fs_node_prop(svn_string_t **value_p,
   dag_node_t *node;
   apr_hash_t *proplist;
 
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
   SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool));
   *value_p = NULL;
   if (proplist)
@@ -1398,7 +1275,7 @@ fs_node_proplist(apr_hash_t **table_p,
   apr_hash_t *table;
   dag_node_t *node;
 
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
   SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool));
   *table_p = table ? table : apr_hash_make(pool);
 
@@ -1515,8 +1392,8 @@ fs_props_changed(svn_boolean_t *changed_
       (SVN_ERR_FS_GENERAL, NULL,
        _("Cannot compare property value between two different filesystems"));
 
-  SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
-  SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
+  SVN_ERR(get_dag(&node1, root1, path1, pool));
+  SVN_ERR(get_dag(&node2, root2, path2, pool));
   return svn_fs_fs__dag_things_different(changed_p, NULL,
                                          node1, node2);
 }
@@ -1529,7 +1406,7 @@ fs_props_changed(svn_boolean_t *changed_
 static svn_error_t *
 get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
 {
-  return get_dag(node, root, "/", TRUE, pool);
+  return get_dag(node, root, "/", pool);
 }
 
 
@@ -2193,7 +2070,7 @@ fs_dir_entries(apr_hash_t **table_p,
   dag_node_t *node;
 
   /* Get the entries for this path in the caller's pool. */
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
   return svn_fs_fs__dag_dir_entries(table_p, node, pool);
 }
 
@@ -2365,7 +2242,7 @@ copy_helper(svn_fs_root_t *from_root,
        _("Copy from mutable tree not currently supported"));
 
   /* Get the NODE for FROM_PATH in FROM_ROOT.*/
-  SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));
+  SVN_ERR(get_dag(&from_node, from_root, from_path, pool));
 
   /* Build up the parent path from TO_PATH in TO_ROOT.  If the last
      component does not exist, it's not that big a deal.  We'll just
@@ -2442,7 +2319,7 @@ copy_helper(svn_fs_root_t *from_root,
                                             pool));
 
       /* Make a record of this modification in the changes table. */
-      SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool));
+      SVN_ERR(get_dag(&new_node, to_root, to_path, pool));
       SVN_ERR(add_change(to_root->fs, txn_id, to_path,
                          svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE,
                          svn_fs_fs__dag_node_kind(from_node),
@@ -2553,7 +2430,7 @@ fs_copied_from(svn_revnum_t *rev_p,
     {
       /* There is no cached entry, look it up the old-fashioned
          way. */
-      SVN_ERR(get_dag(&node, root, path, TRUE, pool));
+      SVN_ERR(get_dag(&node, root, path, pool));
       SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&copyfrom_rev, node));
       SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copyfrom_path, node));
     }
@@ -2628,7 +2505,7 @@ fs_file_length(svn_filesize_t *length_p,
   dag_node_t *file;
 
   /* First create a dag_node_t from the root/path pair. */
-  SVN_ERR(get_dag(&file, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&file, root, path, pool));
 
   /* Now fetch its length */
   return svn_fs_fs__dag_file_length(length_p, file, pool);
@@ -2647,7 +2524,7 @@ fs_file_checksum(svn_checksum_t **checks
 {
   dag_node_t *file;
 
-  SVN_ERR(get_dag(&file, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&file, root, path, pool));
   return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool);
 }
 
@@ -2666,7 +2543,7 @@ fs_file_contents(svn_stream_t **contents
   svn_stream_t *file_stream;
 
   /* First create a dag_node_t from the root/path pair. */
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
 
   /* Then create a readable stream from the dag_node_t. */
   SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool));
@@ -2689,7 +2566,7 @@ fs_try_process_file_contents(svn_boolean
                              apr_pool_t *pool)
 {
   dag_node_t *node;
-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+  SVN_ERR(get_dag(&node, root, path, pool));
 
   return svn_fs_fs__dag_try_process_file_contents(success, node,
                                                   processor, baton, pool);
@@ -3071,8 +2948,8 @@ fs_contents_changed(svn_boolean_t *chang
         (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2);
   }
 
-  SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
-  SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
+  SVN_ERR(get_dag(&node1, root1, path1, pool));
+  SVN_ERR(get_dag(&node2, root2, path2, pool));
   return svn_fs_fs__dag_things_different(NULL, changed_p,
                                          node1, node2);
 }
@@ -3092,10 +2969,10 @@ fs_get_file_delta_stream(svn_txdelta_str
   dag_node_t *source_node, *target_node;
 
   if (source_root && source_path)
-    SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool));
+    SVN_ERR(get_dag(&source_node, source_root, source_path, pool));
   else
     source_node = NULL;
-  SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool));
+  SVN_ERR(get_dag(&target_node, target_root, target_path, pool));
 
   /* Create a delta stream that turns the source into the target.  */
   return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node,
@@ -3588,7 +3465,7 @@ history_prev(void *baton, apr_pool_t *po
 
       SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev,
                                        pool));
-      SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, pool));
+      SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, pool));
       copy_dst = svn_fs_fs__dag_get_created_path(node);
 
       /* If our current path was the very destination of the copy,
@@ -3785,7 +3662,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
       svn_pool_clear(iterpool);
 
       kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
-      SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool));
+      SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
 
       SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
       SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
@@ -4031,7 +3908,7 @@ add_descendant_mergeinfo(svn_mergeinfo_c
   dag_node_t *this_dag;
   svn_boolean_t go_down;
 
-  SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool));
+  SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
   SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
                                                         this_dag));
   if (go_down)

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/commit.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/commit.c Thu Apr 16 03:46:20 2015
@@ -2234,6 +2234,7 @@ close_edit(void *edit_baton,
     ctx->activity_url ? ctx->activity_url : ctx->txn_url;
   const svn_commit_info_t *commit_info;
   int response_code;
+  svn_error_t *err = NULL;
 
   /* MERGE our activity */
   SVN_ERR(svn_ra_serf__run_merge(&commit_info, &response_code,
@@ -2252,9 +2253,11 @@ close_edit(void *edit_baton,
                                response_code);
     }
 
+  ctx->txn_url = NULL; /* If HTTPv2, the txn is now done */
+
   /* Inform the WC that we did a commit.  */
   if (ctx->callback)
-    SVN_ERR(ctx->callback(commit_info, ctx->callback_baton, pool));
+    err = ctx->callback(commit_info, ctx->callback_baton, pool);
 
   /* If we're using activities, DELETE our completed activity.  */
   if (ctx->activity_url)
@@ -2271,11 +2274,17 @@ close_edit(void *edit_baton,
       handler->response_handler = svn_ra_serf__expect_empty_body;
       handler->response_baton = handler;
 
-      SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
+      ctx->activity_url = NULL; /* Don't try again in abort_edit() on fail */
+
+      SVN_ERR(svn_error_compose_create(
+                  err,
+                  svn_ra_serf__context_run_one(handler, pool)));
 
       SVN_ERR_ASSERT(handler->sline.code == 204);
     }
 
+  SVN_ERR(err);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/options.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_ra_serf/options.c Thu Apr 16 03:46:20 2015
@@ -33,6 +33,7 @@
 #include "svn_ra.h"
 #include "svn_dav.h"
 #include "svn_xml.h"
+#include "svn_ctype.h"
 
 #include "../libsvn_ra/ra_loader.h"
 #include "svn_private_config.h"
@@ -227,7 +228,9 @@ capabilities_headers_iterator_callback(v
     }
 
   /* SVN-specific headers -- if present, server supports HTTP protocol v2 */
-  else if (strncmp(key, "SVN", 3) == 0)
+  else if (!svn_ctype_casecmp(key[0], 'S')
+           && !svn_ctype_casecmp(key[1], 'V')
+           && !svn_ctype_casecmp(key[2], 'N'))
     {
       /* If we've not yet seen any information about supported POST
          requests, we'll initialize the list/hash with "create-txn"

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/commit.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/commit.c Thu Apr 16 03:46:20 2015
@@ -777,6 +777,13 @@ close_edit(void *edit_baton,
           post_commit_err = svn_repos__post_commit_error_str(err, pool);
           svn_error_clear(err);
         }
+
+      /* Make sure a future abort doesn't perform
+         any work. This may occur if the commit
+         callback returns an error! */
+
+      eb->txn = NULL;
+      eb->txn_root = NULL;
     }
   else
     {

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/load-fs-vtable.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_repos/load-fs-vtable.c Thu Apr 16 03:46:20 2015
@@ -40,6 +40,7 @@
 
 #include <apr_lib.h>
 
+#include "private/svn_repos_private.h"
 #include "private/svn_fspath.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_mergeinfo_private.h"
@@ -329,16 +330,7 @@ renumber_mergeinfo_revs(svn_string_t **f
       SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
                                    subpool, subpool));
 
-  SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
-
-  /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
-     or r1.  However, svndumpfilter can be abused to produce r1 merge source
-     revs.  So if we encounter any, then strip them out, no need to put them
-     into the load target. */
-  SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
-                                                    final_mergeinfo,
-                                                    1, 0, FALSE,
-                                                    subpool, subpool));
+  SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
 
   SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
   svn_pool_destroy(subpool);
@@ -745,6 +737,67 @@ set_revision_property(void *baton,
 }
 
 
+/* Adjust mergeinfo:
+ *   - normalize line endings (if all CRLF, change to LF; but error if mixed);
+ *   - adjust revision numbers (see renumber_mergeinfo_revs());
+ *   - adjust paths (see prefix_mergeinfo_paths()).
+ */
+static svn_error_t *
+adjust_mergeinfo_property(struct revision_baton *rb,
+                          svn_string_t **new_value_p,
+                          const svn_string_t *old_value,
+                          apr_pool_t *result_pool)
+{
+  struct parse_baton *pb = rb->pb;
+  svn_string_t prop_val = *old_value;
+
+  /* Tolerate mergeinfo with "\r\n" line endings because some
+     dumpstream sources might contain as much.  If so normalize
+     the line endings to '\n' and make a notification to
+     PARSE_BATON->FEEDBACK_STREAM that we have made this
+     correction. */
+  if (strstr(prop_val.data, "\r"))
+    {
+      const char *prop_eol_normalized;
+
+      SVN_ERR(svn_subst_translate_cstring2(prop_val.data,
+                                           &prop_eol_normalized,
+                                           "\n",  /* translate to LF */
+                                           FALSE, /* no repair */
+                                           NULL,  /* no keywords */
+                                           FALSE, /* no expansion */
+                                           result_pool));
+      prop_val.data = prop_eol_normalized;
+      prop_val.len = strlen(prop_eol_normalized);
+
+      if (pb->notify_func)
+        {
+          /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
+          svn_repos_notify_t *notify
+                  = svn_repos_notify_create(
+                                svn_repos_notify_load_normalized_mergeinfo,
+                                pb->notify_pool);
+
+          pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
+          svn_pool_clear(pb->notify_pool);
+        }
+    }
+
+  /* Renumber mergeinfo as appropriate. */
+  SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rb,
+                                  result_pool));
+  if (pb->parent_dir)
+    {
+      /* Prefix the merge source paths with PB->parent_dir. */
+      /* ASSUMPTION: All source paths are included in the dump stream. */
+      SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p,
+                                     pb->parent_dir, result_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
 static svn_error_t *
 set_node_property(void *baton,
                   const char *name,
@@ -758,57 +811,42 @@ set_node_property(void *baton,
   if (rb->skipped)
     return SVN_NO_ERROR;
 
+  /* Adjust mergeinfo. If this fails, presumably because the mergeinfo
+     property has an ill-formed value, then we must not fail to load
+     the repository (at least if it's a simple load with no revision
+     offset adjustments, path changes, etc.) so just warn and leave it
+     as it is. */
   if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
     {
-      svn_string_t *renumbered_mergeinfo;
-      /* ### Need to cast away const. We cannot change the declaration of
-       * ### this function since it is part of svn_repos_parse_fns2_t. */
-      svn_string_t *prop_val = (svn_string_t *)value;
-
-      /* Tolerate mergeinfo with "\r\n" line endings because some
-         dumpstream sources might contain as much.  If so normalize
-         the line endings to '\n' and make a notification to
-         PARSE_BATON->FEEDBACK_STREAM that we have made this
-         correction. */
-      if (strstr(prop_val->data, "\r"))
-        {
-          const char *prop_eol_normalized;
-
-          SVN_ERR(svn_subst_translate_cstring2(prop_val->data,
-                                               &prop_eol_normalized,
-                                               "\n",  /* translate to LF */
-                                               FALSE, /* no repair */
-                                               NULL,  /* no keywords */
-                                               FALSE, /* no expansion */
-                                               nb->pool));
-          prop_val->data = prop_eol_normalized;
-          prop_val->len = strlen(prop_eol_normalized);
+      svn_string_t *new_value;
+      svn_error_t *err;
 
+      err = adjust_mergeinfo_property(rb, &new_value, value, nb->pool);
+      if (err)
+        {
+          if (pb->validate_props)
+            {
+              return svn_error_quick_wrap(
+                       err,
+                       _("Invalid svn:mergeinfo value"));
+            }
           if (pb->notify_func)
             {
-              /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
               svn_repos_notify_t *notify
-                      = svn_repos_notify_create(
-                                    svn_repos_notify_load_normalized_mergeinfo,
-                                    pb->notify_pool);
+                = svn_repos_notify_create(svn_repos_notify_warning,
+                                          pb->notify_pool);
 
+              notify->warning = svn_repos__notify_warning_invalid_mergeinfo;
+              notify->warning_str = _("Invalid svn:mergeinfo value; "
+                                      "leaving unchanged");
               pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
               svn_pool_clear(pb->notify_pool);
             }
+          svn_error_clear(err);
         }
-
-      /* Renumber mergeinfo as appropriate. */
-      SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, prop_val, rb,
-                                      nb->pool));
-      value = renumbered_mergeinfo;
-      if (pb->parent_dir)
+      else
         {
-          /* Prefix the merge source paths with PB->parent_dir. */
-          /* ASSUMPTION: All source paths are included in the dump stream. */
-          svn_string_t *mergeinfo_val;
-          SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value,
-                                         pb->parent_dir, nb->pool));
-          value = mergeinfo_val;
+          value = new_value;
         }
     }
 

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/cache-membuffer.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/cache-membuffer.c Thu Apr 16 03:46:20 2015
@@ -101,6 +101,21 @@
  * on their hash key.
  */
 
+/* APR's read-write lock implementation on Windows is horribly inefficient.
+ * Even with very low contention a runtime overhead of 35% percent has been
+ * measured for 'svn-bench null-export' over ra_serf.
+ *
+ * Use a simple mutex on Windows.  Because there is one mutex per segment,
+ * large machines should (and usually can) be configured with large caches
+ * such that read contention is kept low.  This is basically the situation
+ * we head before 1.8.
+ */
+#ifdef WIN32
+#  define USE_SIMPLE_MUTEX 1
+#else
+#  define USE_SIMPLE_MUTEX 0
+#endif
+
 /* A 16-way associative cache seems to be a good compromise between
  * performance (worst-case lookups) and efficiency-loss due to collisions.
  *
@@ -465,11 +480,15 @@ struct svn_membuffer_t
    * the cache's creator doesn't feel the cache needs to be
    * thread-safe.
    */
+#  if USE_SIMPLE_MUTEX
+  svn_mutex__t *lock;
+#  else
   apr_thread_rwlock_t *lock;
+#  endif
 
   /* If set, write access will wait until they get exclusive access.
    * Otherwise, they will become no-ops if the segment is currently
-   * read-locked.
+   * read-locked.  Only used when LOCK is an r/w lock.
    */
   svn_boolean_t allow_blocking_writes;
 #endif
@@ -489,12 +508,16 @@ static svn_error_t *
 read_lock_cache(svn_membuffer_t *cache)
 {
 #if APR_HAS_THREADS
+#  if USE_SIMPLE_MUTEX
+  return svn_mutex__lock(cache->lock);
+#  else
   if (cache->lock)
   {
     apr_status_t status = apr_thread_rwlock_rdlock(cache->lock);
     if (status)
       return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
   }
+#  endif
 #endif
   return SVN_NO_ERROR;
 }
@@ -505,6 +528,12 @@ static svn_error_t *
 write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
 {
 #if APR_HAS_THREADS
+#  if USE_SIMPLE_MUTEX
+
+  return svn_mutex__lock(cache->lock);
+
+#  else
+
   if (cache->lock)
     {
       apr_status_t status;
@@ -526,6 +555,8 @@ write_lock_cache(svn_membuffer_t *cache,
         return svn_error_wrap_apr(status,
                                   _("Can't write-lock cache mutex"));
     }
+
+#  endif
 #endif
   return SVN_NO_ERROR;
 }
@@ -537,10 +568,18 @@ static svn_error_t *
 force_write_lock_cache(svn_membuffer_t *cache)
 {
 #if APR_HAS_THREADS
+#  if USE_SIMPLE_MUTEX
+
+  return svn_mutex__lock(cache->lock);
+
+#  else
+
   apr_status_t status = apr_thread_rwlock_wrlock(cache->lock);
   if (status)
     return svn_error_wrap_apr(status,
                               _("Can't write-lock cache mutex"));
+
+#  endif
 #endif
   return SVN_NO_ERROR;
 }
@@ -552,6 +591,12 @@ static svn_error_t *
 unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
 {
 #if APR_HAS_THREADS
+#  if USE_SIMPLE_MUTEX
+
+  return svn_mutex__unlock(cache->lock, err);
+
+#  else
+
   if (cache->lock)
   {
     apr_status_t status = apr_thread_rwlock_unlock(cache->lock);
@@ -561,6 +606,8 @@ unlock_cache(svn_membuffer_t *cache, svn
     if (status)
       return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
   }
+
+#  endif
 #endif
   return err;
 }
@@ -1290,6 +1337,12 @@ svn_cache__membuffer_cache_create(svn_me
        * the cache's creator doesn't feel the cache needs to be
        * thread-safe.
        */
+#  if USE_SIMPLE_MUTEX
+
+      SVN_ERR(svn_mutex__init(&c[seg].lock, thread_safe, pool));
+
+#  else
+
       c[seg].lock = NULL;
       if (thread_safe)
         {
@@ -1299,6 +1352,8 @@ svn_cache__membuffer_cache_create(svn_me
             return svn_error_wrap_apr(status, _("Can't create cache mutex"));
         }
 
+#  endif
+
       /* Select the behavior of write operations.
        */
       c[seg].allow_blocking_writes = allow_blocking_writes;

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/config.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/config.c Thu Apr 16 03:46:20 2015
@@ -487,14 +487,15 @@ make_string_from_option(const char **val
           expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);
           opt->expanded = TRUE;
 
-          if (!x_pool)
+          if (x_pool != cfg->x_pool)
             {
               /* Grab the fully expanded value from tmp_pool before its
                  disappearing act. */
               if (opt->x_value)
                 opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value,
                                               strlen(opt->x_value));
-              svn_pool_destroy(tmp_pool);
+              if (!x_pool)
+                svn_pool_destroy(tmp_pool);
             }
         }
       else

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/dso.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/dso.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/dso.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/dso.c Thu Apr 16 03:46:20 2015
@@ -28,6 +28,7 @@
 #include "svn_private_config.h"
 
 #include "private/svn_mutex.h"
+#include "private/svn_atomic.h"
 
 /* A mutex to protect our global pool and cache. */
 static svn_mutex__t *dso_mutex = NULL;
@@ -41,18 +42,18 @@ static apr_hash_t *dso_cache;
 /* Just an arbitrary location in memory... */
 static int not_there_sentinel;
 
+static volatile svn_atomic_t atomic_init_status = 0;
+
 /* A specific value we store in the dso_cache to indicate that the
    library wasn't found.  This keeps us from allocating extra memory
    from dso_pool when trying to find libraries we already know aren't
    there.  */
 #define NOT_THERE ((void *) &not_there_sentinel)
 
-svn_error_t *
-svn_dso_initialize2(void)
+static svn_error_t *
+atomic_init_func(void *baton,
+                 apr_pool_t *pool)
 {
-  if (dso_pool)
-    return SVN_NO_ERROR;
-
   dso_pool = svn_pool_create(NULL);
 
   SVN_ERR(svn_mutex__init(&dso_mutex, TRUE, dso_pool));
@@ -61,6 +62,15 @@ svn_dso_initialize2(void)
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_dso_initialize2(void)
+{
+  SVN_ERR(svn_atomic__init_once(&atomic_init_status, atomic_init_func,
+                                NULL, NULL));
+
+  return SVN_NO_ERROR;
+}
+
 #if APR_HAS_DSO
 static svn_error_t *
 svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname)
@@ -107,8 +117,7 @@ svn_dso_load_internal(apr_dso_handle_t *
 svn_error_t *
 svn_dso_load(apr_dso_handle_t **dso, const char *fname)
 {
-  if (! dso_pool)
-    SVN_ERR(svn_dso_initialize2());
+  SVN_ERR(svn_dso_initialize2());
 
   SVN_MUTEX__WITH_LOCK(dso_mutex, svn_dso_load_internal(dso, fname));
 

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/error.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/error.c Thu Apr 16 03:46:20 2015
@@ -289,6 +289,8 @@ svn_error_compose(svn_error_t *chain, sv
       *chain = *new_err;
       if (chain->message)
         chain->message = apr_pstrdup(pool, new_err->message);
+      if (chain->file)
+        chain->file = apr_pstrdup(pool, new_err->file);
       chain->pool = pool;
 #if defined(SVN_DEBUG)
       if (! new_err->child)
@@ -358,6 +360,8 @@ svn_error_dup(svn_error_t *err)
       tmp_err->pool = pool;
       if (tmp_err->message)
         tmp_err->message = apr_pstrdup(pool, tmp_err->message);
+      if (tmp_err->file)
+        tmp_err->file = apr_pstrdup(pool, tmp_err->file);
     }
 
 #if defined(SVN_DEBUG)

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/mergeinfo.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/mergeinfo.c Thu Apr 16 03:46:20 2015
@@ -611,6 +611,43 @@ svn_rangelist__parse(svn_rangelist_t **r
   return SVN_NO_ERROR;
 }
 
+/* Return TRUE, if all ranges in RANGELIST are in ascending order and do
+ * not overlap and are not adjacent.
+ *
+ * ### Can yield false negatives: ranges of differing inheritance are
+ * allowed to be adjacent.
+ *
+ * If this returns FALSE, you probaly want to qsort() the
+ * ranges and then call svn_rangelist__combine_adjacent_ranges().
+ */
+static svn_boolean_t
+is_rangelist_normalized(svn_rangelist_t *rangelist)
+{
+  int i;
+  svn_merge_range_t **ranges = (svn_merge_range_t **)rangelist->elts;
+
+  for (i = 0; i < rangelist->nelts-1; ++i)
+    if (ranges[i]->end >= ranges[i+1]->start)
+      return FALSE;
+
+  return TRUE;
+}
+
+svn_error_t *
+svn_rangelist__canonicalize(svn_rangelist_t *rangelist,
+                            apr_pool_t *scratch_pool)
+{
+  if (! is_rangelist_normalized(rangelist))
+    {
+      qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
+                  svn_sort_compare_ranges);
+
+      SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
                                        apr_pool_t *scratch_pool)
@@ -692,15 +729,11 @@ parse_revision_line(const char **input,
   if (*input != end)
     *input = *input + 1;
 
-  /* Sort the rangelist, combine adjacent ranges into single ranges,
-     and make sure there are no overlapping ranges. */
-  if (rangelist->nelts > 1)
-    {
-      qsort(rangelist->elts, rangelist->nelts, rangelist->elt_size,
-            svn_sort_compare_ranges);
-
-      SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool));
-    }
+  /* Sort the rangelist, combine adjacent ranges into single ranges, and
+     make sure there are no overlapping ranges.  Luckily, most data in
+     svn:mergeinfo will already be in normalized form and this will be quick.
+   */
+  SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool));
 
   /* Handle any funky mergeinfo with relative merge source paths that
      might exist due to issue #3547.  It's possible that this issue allowed
@@ -1973,6 +2006,22 @@ svn_mergeinfo_sort(svn_mergeinfo_t input
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo,
+                                   apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, mergeinfo); hi; hi = apr_hash_next(hi))
+    {
+      apr_array_header_t *rl = svn__apr_hash_index_val(hi);
+
+      SVN_ERR(svn_rangelist__canonicalize(rl, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_mergeinfo_catalog_t
 svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog,
                           apr_pool_t *pool)

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/sqlite3wrapper.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/sqlite3wrapper.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/sqlite3wrapper.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/sqlite3wrapper.c Thu Apr 16 03:46:20 2015
@@ -24,7 +24,7 @@
 
 /* Include sqlite3 inline, making all symbols private. */
 #ifdef SVN_SQLITE_INLINE
-#  define SQLITE_OMIT_DEPRECATED
+#  define SQLITE_OMIT_DEPRECATED 1
 #  define SQLITE_API static
 #  if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6 || __APPLE_CC__))
 #    if !__APPLE_CC__ || __GNUC_MINOR__ >= 6

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/string.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_subr/string.c Thu Apr 16 03:46:20 2015
@@ -619,7 +619,7 @@ svn_stringbuf_insert(svn_stringbuf_t *st
   if (bytes + count > str->data && bytes < str->data + str->blocksize)
     {
       /* special case: BYTES overlaps with this string -> copy the source */
-      const char *temp = apr_pstrndup(str->pool, bytes, count);
+      const char *temp = apr_pmemdup(str->pool, bytes, count);
       svn_stringbuf_insert(str, pos, temp, count);
     }
   else
@@ -659,7 +659,7 @@ svn_stringbuf_replace(svn_stringbuf_t *s
   if (bytes + new_count > str->data && bytes < str->data + str->blocksize)
     {
       /* special case: BYTES overlaps with this string -> copy the source */
-      const char *temp = apr_pstrndup(str->pool, bytes, new_count);
+      const char *temp = apr_pmemdup(str->pool, bytes, new_count);
       svn_stringbuf_replace(str, pos, old_count, temp, new_count);
     }
   else

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/adm_ops.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/adm_ops.c Thu Apr 16 03:46:20 2015
@@ -965,7 +965,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
                                          repos_relpath,
                                          repos_root_url, repos_uuid,
                                          copyfrom_rev,
-                                         NULL /* children */, FALSE, depth,
+                                         NULL /* children */, depth,
+                                         FALSE /* is_move */,
                                          NULL /* conflicts */,
                                          NULL /* work items */,
                                          scratch_pool));

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/conflicts.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/conflicts.c Thu Apr 16 03:46:20 2015
@@ -2913,6 +2913,13 @@ conflict_status_walker(void *baton,
 
       cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
 
+      if ((cd->kind == svn_wc_conflict_kind_property && !cswb->resolve_prop)
+          || (cd->kind == svn_wc_conflict_kind_text && !cswb->resolve_text)
+          || (cd->kind == svn_wc_conflict_kind_tree && !cswb->resolve_tree))
+        {
+          continue; /* Easy out. Don't call resolver func and ignore result */
+        }
+
       svn_pool_clear(iterpool);
 
       if (my_choice == svn_wc_conflict_choose_unspecified)

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/copy.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/copy.c Thu Apr 16 03:46:20 2015
@@ -891,18 +891,18 @@ remove_node_conflict_markers(svn_wc__db_
         {
           const char *marker_abspath;
           const char *child_relpath;
-          const char *child_abpath;
+          const char *child_abspath;
 
           marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
 
-          child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL);
+          child_relpath = svn_dirent_skip_ancestor(src_dir, marker_abspath);
 
           if (child_relpath)
             {
-              child_abpath = svn_dirent_join(dst_dir, child_relpath,
-                                             scratch_pool);
+              child_abspath = svn_dirent_join(dst_dir, child_relpath,
+                                              scratch_pool);
 
-              SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool));
+              SVN_ERR(svn_io_remove_file2(child_abspath, TRUE, scratch_pool));
             }
         }
     }
@@ -922,7 +922,7 @@ remove_node_conflict_markers(svn_wc__db_
 static svn_error_t *
 remove_all_conflict_markers(svn_wc__db_t *db,
                             const char *src_dir_abspath,
-                            const char *wc_dir_abspath,
+                            const char *dst_dir_abspath,
                             apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -951,7 +951,7 @@ remove_all_conflict_markers(svn_wc__db_t
           SVN_ERR(remove_node_conflict_markers(
                             db,
                             svn_dirent_join(src_dir_abspath, name, iterpool),
-                            svn_dirent_join(wc_dir_abspath, name, iterpool),
+                            svn_dirent_join(dst_dir_abspath, name, iterpool),
                             iterpool));
         }
       if (info->kind == svn_node_dir)
@@ -960,7 +960,7 @@ remove_all_conflict_markers(svn_wc__db_t
           SVN_ERR(remove_all_conflict_markers(
                             db,
                             svn_dirent_join(src_dir_abspath, name, iterpool),
-                            svn_dirent_join(wc_dir_abspath, name, iterpool),
+                            svn_dirent_join(dst_dir_abspath, name, iterpool),
                             iterpool));
         }
     }
@@ -1033,8 +1033,16 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
                                         scratch_pool));
 
   if (conflicted)
-    SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath,
-                                         scratch_pool));
+    {
+      /* When we moved a directory, we moved the conflict markers
+         with the target... if we moved a file we only moved the
+         file itself and the markers are still in the old location */
+      SVN_ERR(remove_node_conflict_markers(db, src_abspath,
+                                           (kind == svn_node_dir)
+                                             ? dst_abspath
+                                             : src_abspath,
+                                           scratch_pool));
+    }
 
   SVN_ERR(svn_wc__db_op_delete(db, src_abspath,
                                move_degraded_to_copy ? NULL : dst_abspath,

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/diff_editor.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/diff_editor.c Thu Apr 16 03:46:20 2015
@@ -1026,6 +1026,14 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             void *cancel_baton,
                             apr_pool_t *scratch_pool)
 {
+  svn_wc__db_status_t status;
+  svn_node_kind_t kind;
+  svn_boolean_t had_props;
+  svn_boolean_t props_mod;
+  const char *original_repos_relpath;
+  svn_revnum_t original_revision;
+  svn_diff_source_t *copyfrom_src = NULL;
+  apr_hash_t *pristine_props;
   const apr_array_header_t *children;
   int i;
   apr_pool_t *iterpool;
@@ -1038,6 +1046,47 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
   apr_hash_t *nodes;
   apr_hash_t *conflicts;
 
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               &original_repos_relpath, NULL, NULL,
+                               &original_revision, NULL, NULL, NULL,
+                               NULL, NULL, NULL, &had_props,
+                               &props_mod, NULL, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
+  if (original_repos_relpath)
+    {
+      copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
+      copyfrom_src->repos_relpath = original_repos_relpath;
+    }
+
+  /* svn_wc__db_status_incomplete should never happen, as the result won't be
+     stable or guaranteed related to what is in the repository for this
+     revision, but without this it would be hard to diagnose that status... */
+  assert(kind == svn_node_dir
+         && (status == svn_wc__db_status_normal
+             || status == svn_wc__db_status_incomplete
+             || status == svn_wc__db_status_added
+             || (status == svn_wc__db_status_deleted && diff_pristine)));
+
+  if (status == svn_wc__db_status_deleted)
+    {
+      assert(diff_pristine);
+
+      SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, &had_props,
+                                            &pristine_props,
+                                            db, local_abspath,
+                                            scratch_pool, scratch_pool));
+      props_mod = FALSE;
+    }
+  else if (!had_props)
+    pristine_props = apr_hash_make(scratch_pool);
+  else
+    SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
+                                           db, local_abspath,
+                                           scratch_pool, scratch_pool));
+
   /* Report the addition of the directory's contents. */
   iterpool = svn_pool_create(scratch_pool);
 
@@ -1045,7 +1094,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                                 relpath,
                                 NULL,
                                 right_src,
-                                NULL /* copyfrom_src */,
+                                copyfrom_src,
                                 processor_parent_baton,
                                 processor,
                                 scratch_pool, iterpool));
@@ -1119,17 +1168,19 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
   if (!skip)
     {
       apr_hash_t *right_props;
-      if (diff_pristine)
-        SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath,
-                                               scratch_pool, scratch_pool));
+
+      if (props_mod && !diff_pristine)
+        SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath,
+                                      scratch_pool, scratch_pool));
       else
-        SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath,
-                                         scratch_pool, scratch_pool));
+        right_props = svn_prop_hash_dup(pristine_props, scratch_pool);
 
       SVN_ERR(processor->dir_added(relpath,
-                                   NULL /* copyfrom_src */,
+                                   copyfrom_src,
                                    right_src,
-                                   NULL,
+                                   copyfrom_src
+                                     ? pristine_props
+                                     : NULL,
                                    right_props,
                                    pdb,
                                    processor,
@@ -2362,8 +2413,8 @@ wrap_dir_opened(void **new_dir_baton,
   wc_diff_wrap_baton_t *wb = processor->baton;
   svn_boolean_t tree_conflicted = FALSE;
 
-  assert(left_source || right_source);
-  assert(!copyfrom_source || !right_source);
+  assert(left_source || right_source);      /* Must exist at one point. */
+  assert(!left_source || !copyfrom_source); /* Either existed or added. */
 
   /* Maybe store state and tree_conflicted in baton? */
   if (left_source != NULL)

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/entries.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/entries.c Thu Apr 16 03:46:20 2015
@@ -2140,17 +2140,18 @@ write_entry(struct write_baton **entry_n
       below_working_node->presence = svn_wc__db_status_normal;
       below_working_node->kind = entry->kind;
       below_working_node->repos_id = work->repos_id;
+      below_working_node->revision = work->revision;
 
       /* This is just guessing. If the node below would have been switched
          or if it was updated to a different version, the guess would
          fail. But we don't have better information pre wc-ng :( */
       if (work->repos_relpath)
         below_working_node->repos_relpath
-          = svn_relpath_join(work->repos_relpath, entry->name,
+          = svn_relpath_join(work->repos_relpath,
+                             svn_relpath_basename(local_relpath, NULL),
                              result_pool);
       else
         below_working_node->repos_relpath = NULL;
-      below_working_node->revision = parent_node->work->revision;
 
       /* The revert_base checksum isn't available in the entry structure,
          so the caller provides it. */

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/externals.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/externals.c Thu Apr 16 03:46:20 2015
@@ -945,28 +945,62 @@ close_edit(void *edit_baton,
 {
   struct edit_baton *eb = edit_baton;
 
-  if (!eb->file_closed
-      || eb->iprops)
+  if (!eb->file_closed)
     {
-      apr_hash_t *wcroot_iprops = NULL;
+      /* The file wasn't updated, but its url or revision might have...
+         e.g. switch between branches for relative externals.
 
-      if (eb->iprops)
-        {
-          wcroot_iprops = apr_hash_make(pool);
-          svn_hash_sets(wcroot_iprops, eb->local_abspath, eb->iprops);
-        }
-
-      /* The node wasn't updated, so we just have to bump its revision */
-      SVN_ERR(svn_wc__db_op_bump_revisions_post_update(eb->db,
-                                                       eb->local_abspath,
-                                                       svn_depth_infinity,
-                                                       NULL, NULL, NULL,
-                                                       *eb->target_revision,
-                                                       apr_hash_make(pool),
-                                                       wcroot_iprops,
-                                                       eb->notify_func,
-                                                       eb->notify_baton,
-                                                       pool));
+         Just bump the information as that is just as expensive as
+         investigating when we should and shouldn't update it...
+         and avoid hard to debug edge cases */
+
+      svn_node_kind_t kind;
+      const char *old_repos_relpath;
+      svn_revnum_t changed_rev;
+      apr_time_t changed_date;
+      const char *changed_author;
+      const svn_checksum_t *checksum;
+      apr_hash_t *pristine_props;
+      const char *repos_relpath = svn_uri_skip_ancestor(eb->repos_root_url,
+                                                        eb->url, pool);
+
+      SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, NULL, &old_repos_relpath,
+                                       NULL, NULL, &changed_rev, &changed_date,
+                                       &changed_author, NULL, &checksum, NULL,
+                                       NULL, NULL, &pristine_props, NULL,
+                                       eb->db, eb->local_abspath,
+                                       pool, pool));
+
+      if (kind != svn_node_file)
+        return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                                   _("Node '%s' is no existing file external"),
+                                   svn_dirent_local_style(eb->local_abspath,
+                                                          pool));
+
+      SVN_ERR(svn_wc__db_external_add_file(
+                    eb->db,
+                    eb->local_abspath,
+                    eb->wri_abspath,
+                    repos_relpath,
+                    eb->repos_root_url,
+                    eb->repos_uuid,
+                    *eb->target_revision,
+                    pristine_props,
+                    eb->iprops,
+                    eb->changed_rev,
+                    eb->changed_date,
+                    eb->changed_author,
+                    checksum,
+                    NULL /* clear dav props */,
+                    eb->record_ancestor_abspath,
+                    eb->recorded_repos_relpath,
+                    eb->recorded_peg_revision,
+                    eb->recorded_revision,
+                    FALSE, NULL,
+                    TRUE /* keep_recorded_info */,
+                    NULL /* conflict_skel */,
+                    NULL /* work_items */,
+                    pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/update_editor.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/update_editor.c Thu Apr 16 03:46:20 2015
@@ -2125,13 +2125,12 @@ add_directory(const char *path,
       if (tree_conflict)
         {
           svn_wc_conflict_reason_t reason;
+          const char *move_src_op_root_abspath;
           /* So this deletion wasn't just a deletion, it is actually a
              replacement. Let's install a better tree conflict. */
 
-          /* ### Should store the conflict in DB to allow reinstalling
-             ### with theoretically more data in close_directory() */
-
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                      &move_src_op_root_abspath,
                                                       eb->db,
                                                       db->local_abspath,
                                                       tree_conflict,
@@ -2143,7 +2142,7 @@ add_directory(const char *path,
                                         tree_conflict,
                                         eb->db, db->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
-                                        NULL,
+                                        move_src_op_root_abspath,
                                         db->pool, db->pool));
 
           /* And now stop checking for conflicts here and just perform
@@ -3266,13 +3265,12 @@ add_file(const char *path,
       if (tree_conflict)
         {
           svn_wc_conflict_reason_t reason;
+          const char *move_src_op_root_abspath;
           /* So this deletion wasn't just a deletion, it is actually a
              replacement. Let's install a better tree conflict. */
 
-          /* ### Should store the conflict in DB to allow reinstalling
-             ### with theoretically more data in close_directory() */
-
-          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
+          SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL,
+                                                      &move_src_op_root_abspath,
                                                       eb->db,
                                                       fb->local_abspath,
                                                       tree_conflict,
@@ -3284,7 +3282,7 @@ add_file(const char *path,
                                         tree_conflict,
                                         eb->db, fb->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
-                                        NULL,
+                                        move_src_op_root_abspath,
                                         fb->pool, fb->pool));
 
           /* And now stop checking for conflicts here and just perform
@@ -5553,8 +5551,8 @@ svn_wc__complete_directory_add(svn_wc_co
                                    original_repos_relpath, original_root_url,
                                    original_uuid, original_revision,
                                    NULL /* children */,
-                                   FALSE /* is_move */,
                                    svn_depth_infinity,
+                                   FALSE /* is_move */,
                                    NULL /* conflict */,
                                    NULL /* work_items */,
                                    scratch_pool));

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc-queries.sql?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc-queries.sql Thu Apr 16 03:46:20 2015
@@ -1716,6 +1716,10 @@ WHERE wc_id = ?1
   AND op_depth = 0
   AND (inherited_props not null)
 
+-- STMT_HAVE_STAT1_TABLE
+SELECT 1 FROM sqlite_master WHERE name='sqlite_stat1' AND type='table'
+LIMIT 1
+
 /* ------------------------------------------------------------------------- */
 
 /* Grab all the statements related to the schema.  */

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc.h?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc.h Thu Apr 16 03:46:20 2015
@@ -190,6 +190,10 @@ extern "C" {
 /* A version < this has no work queue (see workqueue.h).  */
 #define SVN_WC__HAS_WORK_QUEUE 13
 
+/* While we still have this DB version we should verify if there is
+   sqlite_stat1 table on opening */
+#define SVN_WC__ENSURE_STAT1_TABLE 31
+
 /* Return a string indicating the released version (or versions) of
  * Subversion that used WC format number WC_FORMAT, or some other
  * suitable string if no released version used WC_FORMAT.

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.c?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.c Thu Apr 16 03:46:20 2015
@@ -708,6 +708,7 @@ insert_base_node(const insert_base_baton
   svn_sqlite__stmt_t *stmt;
   svn_filesize_t recorded_size = SVN_INVALID_FILESIZE;
   apr_int64_t recorded_time;
+  svn_boolean_t present;
 
   /* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
      bind the appropriate parent_relpath. */
@@ -738,6 +739,9 @@ insert_base_node(const insert_base_baton
       SVN_ERR(svn_sqlite__reset(stmt));
     }
 
+  present = (pibb->status == svn_wc__db_status_normal
+             || pibb->status == svn_wc__db_status_incomplete);
+
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "isdsisr"
                             "tstr"               /* 8 - 11 */
@@ -750,15 +754,16 @@ insert_base_node(const insert_base_baton
                             pibb->repos_relpath,
                             pibb->revision,
                             presence_map, pibb->status, /* 8 */
-                            (pibb->kind == svn_node_dir) ? /* 9 */
-                             svn_token__to_word(depth_map, pibb->depth) : NULL,
+                            (pibb->kind == svn_node_dir && present) /* 9 */
+                              ? svn_token__to_word(depth_map, pibb->depth)
+                              : NULL,
                             kind_map, pibb->kind, /* 10 */
                             pibb->changed_rev,    /* 11 */
                             pibb->changed_date,   /* 12 */
                             pibb->changed_author, /* 13 */
-                            (pibb->kind == svn_node_symlink) ?
+                            (pibb->kind == svn_node_symlink && present) ?
                                 pibb->target : NULL)); /* 19 */
-  if (pibb->kind == svn_node_file)
+  if (pibb->kind == svn_node_file && present)
     {
       if (!pibb->checksum
           && pibb->status != svn_wc__db_status_not_present
@@ -783,11 +788,14 @@ insert_base_node(const insert_base_baton
   assert(pibb->status == svn_wc__db_status_normal
          || pibb->status == svn_wc__db_status_incomplete
          || pibb->props == NULL);
-  SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
-                                      scratch_pool));
+  if (present)
+    {
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
+                                          scratch_pool));
 
-  SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, pibb->iprops,
+      SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, pibb->iprops,
                                       scratch_pool));
+    }
 
   if (pibb->dav_cache)
     SVN_ERR(svn_sqlite__bind_properties(stmt, 18, pibb->dav_cache,
@@ -992,6 +1000,7 @@ insert_working_node(const insert_working
   const char *moved_to_relpath = NULL;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+  svn_boolean_t present;
 
   SVN_ERR_ASSERT(piwb->op_depth > 0);
 
@@ -1010,6 +1019,9 @@ insert_working_node(const insert_working
     moved_to_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
   SVN_ERR(svn_sqlite__reset(stmt));
 
+  present = (piwb->presence == svn_wc__db_status_normal
+             || piwb->presence == svn_wc__db_status_incomplete);
+
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_INSERT_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnntstrisn"
                 "nnnn" /* properties translated_size last_mod_time dav_cache */
@@ -1018,14 +1030,14 @@ insert_working_node(const insert_working
                 piwb->op_depth,
                 parent_relpath,
                 presence_map, piwb->presence,
-                (piwb->kind == svn_node_dir)
+                (piwb->kind == svn_node_dir && present)
                             ? svn_token__to_word(depth_map, piwb->depth) : NULL,
                 kind_map, piwb->kind,
                 piwb->changed_rev,
                 piwb->changed_date,
                 piwb->changed_author,
                 /* Note: incomplete nodes may have a NULL target.  */
-                (piwb->kind == svn_node_symlink)
+                (piwb->kind == svn_node_symlink && present)
                             ? piwb->target : NULL,
                 moved_to_relpath));
 
@@ -1034,7 +1046,7 @@ insert_working_node(const insert_working
       SVN_ERR(svn_sqlite__bind_int(stmt, 8, TRUE));
     }
 
-  if (piwb->kind == svn_node_file)
+  if (piwb->kind == svn_node_file && present)
     {
       SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, piwb->checksum,
                                         scratch_pool));
@@ -1051,7 +1063,8 @@ insert_working_node(const insert_working
   assert(piwb->presence == svn_wc__db_status_normal
          || piwb->presence == svn_wc__db_status_incomplete
          || piwb->props == NULL);
-  SVN_ERR(svn_sqlite__bind_properties(stmt, 15, piwb->props, scratch_pool));
+  if (present && piwb->original_repos_relpath)
+    SVN_ERR(svn_sqlite__bind_properties(stmt, 15, piwb->props, scratch_pool));
 
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
@@ -2615,17 +2628,21 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(svn_wc__db_base_get_info_internal(status, kind, revision,
+  SVN_WC__DB_WITH_TXN4(
+          svn_wc__db_base_get_info_internal(status, kind, revision,
                                             repos_relpath, &repos_id,
                                             changed_rev, changed_date,
                                             changed_author, depth,
                                             checksum, target, lock,
                                             had_props, props, update_root,
                                             wcroot, local_relpath,
-                                            result_pool, scratch_pool));
+                                            result_pool, scratch_pool),
+          svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
+                                      wcroot->sdb, repos_id, result_pool),
+          SVN_NO_ERROR,
+          SVN_NO_ERROR,
+          wcroot);
   SVN_ERR_ASSERT(repos_id != INVALID_REPOS_ID);
-  SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool));
 
   return SVN_NO_ERROR;
 }
@@ -5339,8 +5356,8 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
                        const char *original_uuid,
                        svn_revnum_t original_revision,
                        const apr_array_header_t *children,
-                       svn_boolean_t is_move,
                        svn_depth_t depth,
+                       svn_boolean_t is_move,
                        const svn_skel_t *conflict,
                        const svn_skel_t *work_items,
                        apr_pool_t *scratch_pool)
@@ -5367,11 +5384,6 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_node_dir;
 
-  iwb.props = props;
-  iwb.changed_rev = changed_rev;
-  iwb.changed_date = changed_date;
-  iwb.changed_author = changed_author;
-
   if (original_root_url != NULL)
     {
       SVN_ERR(create_repos_id(&iwb.original_repos_id,
@@ -5379,6 +5391,11 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
                               wcroot->sdb, scratch_pool));
       iwb.original_repos_relpath = original_repos_relpath;
       iwb.original_revnum = original_revision;
+
+      iwb.props = props;
+      iwb.changed_rev = changed_rev;
+      iwb.changed_date = changed_date;
+      iwb.changed_author = changed_author;
     }
 
   /* ### Should we do this inside the transaction? */
@@ -5447,11 +5464,6 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_node_file;
 
-  iwb.props = props;
-  iwb.changed_rev = changed_rev;
-  iwb.changed_date = changed_date;
-  iwb.changed_author = changed_author;
-
   if (original_root_url != NULL)
     {
       SVN_ERR(create_repos_id(&iwb.original_repos_id,
@@ -5459,6 +5471,11 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
                               wcroot->sdb, scratch_pool));
       iwb.original_repos_relpath = original_repos_relpath;
       iwb.original_revnum = original_revision;
+
+      iwb.props = props;
+      iwb.changed_rev = changed_rev;
+      iwb.changed_date = changed_date;
+      iwb.changed_author = changed_author;
     }
 
   /* ### Should we do this inside the transaction? */
@@ -5501,6 +5518,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
                            const char *original_uuid,
                            svn_revnum_t original_revision,
                            const char *target,
+                           svn_boolean_t is_move,
                            const svn_skel_t *conflict,
                            const svn_skel_t *work_items,
                            apr_pool_t *scratch_pool)
@@ -5525,11 +5543,6 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
   iwb.presence = svn_wc__db_status_normal;
   iwb.kind = svn_node_symlink;
 
-  iwb.props = props;
-  iwb.changed_rev = changed_rev;
-  iwb.changed_date = changed_date;
-  iwb.changed_author = changed_author;
-  iwb.moved_here = FALSE;
 
   if (original_root_url != NULL)
     {
@@ -5538,6 +5551,11 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
                               wcroot->sdb, scratch_pool));
       iwb.original_repos_relpath = original_repos_relpath;
       iwb.original_revnum = original_revision;
+
+      iwb.props = props;
+      iwb.changed_rev = changed_rev;
+      iwb.changed_date = changed_date;
+      iwb.changed_author = changed_author;
     }
 
   /* ### Should we do this inside the transaction? */
@@ -5547,6 +5565,8 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
                             wcroot, local_relpath, scratch_pool));
 
   iwb.target = target;
+  iwb.moved_here = is_move && (parent_op_depth == 0 ||
+                               iwb.op_depth == parent_op_depth);
 
   iwb.work_items = work_items;
   iwb.conflict = conflict;
@@ -7518,7 +7538,11 @@ delete_update_movedto(svn_wc__db_wcroot_
                             op_depth,
                             new_moved_to_relpath));
   SVN_ERR(svn_sqlite__update(&affected, stmt));
-  assert(affected == 1);
+#ifdef SVN_DEBUG
+  /* Not fatal in release mode. The move recording is broken,
+     but the rest of the working copy can handle this. */
+  SVN_ERR_ASSERT(affected == 1);
+#endif
 
   return SVN_NO_ERROR;
 }
@@ -7908,7 +7932,12 @@ delete_node(void *baton,
                                                         child_relpath))
                         child_op_depth = delete_op_depth;
                       else
-                        child_op_depth = relpath_depth(child_relpath);
+                        {
+                          /* Calculate depth of the shadowing at the new location */
+                          child_op_depth = child_op_depth
+                                                - relpath_depth(local_relpath)
+                                                + relpath_depth(b->moved_to_relpath);
+                        }
 
                       fixup = TRUE;
                     }
@@ -8734,19 +8763,22 @@ svn_wc__db_read_info(svn_wc__db_status_t
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(read_info(status, kind, revision, repos_relpath, &repos_id,
+  SVN_WC__DB_WITH_TXN4(
+          read_info(status, kind, revision, repos_relpath, &repos_id,
                     changed_rev, changed_date, changed_author,
                     depth, checksum, target, original_repos_relpath,
                     &original_repos_id, original_revision, lock,
                     recorded_size, recorded_time, changelist, conflicted,
                     op_root, have_props, props_mod,
                     have_base, have_more_work, have_work,
-                    wcroot, local_relpath, result_pool, scratch_pool));
-  SVN_ERR(svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
-                                      wcroot->sdb, repos_id, result_pool));
-  SVN_ERR(svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
+                    wcroot, local_relpath, result_pool, scratch_pool),
+          svn_wc__db_fetch_repos_info(repos_root_url, repos_uuid,
+                                      wcroot->sdb, repos_id, result_pool),
+          svn_wc__db_fetch_repos_info(original_root_url, original_uuid,
                                       wcroot->sdb, original_repos_id,
-                                      result_pool));
+                                      result_pool),
+        SVN_NO_ERROR,
+        wcroot);
 
   return SVN_NO_ERROR;
 }
@@ -10865,59 +10897,86 @@ svn_wc__db_global_relocate(svn_wc__db_t
 }
 
 
-/* Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
+/* Helper for commit_node()
+   Set *REPOS_ID and *REPOS_RELPATH to the BASE repository location of
    (WCROOT, LOCAL_RELPATH), directly if its BASE row exists or implied from
    its parent's BASE row if not. In the latter case, error if the parent
    BASE row does not exist.  */
 static svn_error_t *
-determine_repos_info(apr_int64_t *repos_id,
-                     const char **repos_relpath,
-                     svn_wc__db_wcroot_t *wcroot,
-                     const char *local_relpath,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
+determine_commit_repos_info(apr_int64_t *repos_id,
+                            const char **repos_relpath,
+                            svn_wc__db_wcroot_t *wcroot,
+                            const char *local_relpath,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  const char *repos_parent_relpath;
-  const char *local_parent_relpath, *name;
-
-  /* ### is it faster to fetch fewer columns? */
+  int op_depth;
 
   /* Prefer the current node's repository information.  */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_BASE_NODE));
+                                    STMT_SELECT_NODE_INFO));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
-  if (have_row)
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                             svn_sqlite__reset(stmt),
+                             _("The node '%s' was not found."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+  op_depth = svn_sqlite__column_int(stmt, 0);
+
+  if (op_depth > 0)
     {
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
-      SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+      svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 3,
+                                                              presence_map);
 
-      *repos_id = svn_sqlite__column_int64(stmt, 0);
-      *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+      if (presence == svn_wc__db_status_base_deleted)
+        {
+          SVN_ERR(svn_sqlite__step_row(stmt)); /* There must be a row */
+          op_depth = svn_sqlite__column_int(stmt, 0);
+        }
+      else
+        {
+          const char *parent_repos_relpath;
+          const char *parent_relpath;
+          const char *name;
 
-      return svn_error_trace(svn_sqlite__reset(stmt));
+          SVN_ERR(svn_sqlite__reset(stmt));
+
+          /* The repository relative path of an add/copy is based on its
+             ancestor, not on the shadowed base layer.
+
+             As this function is only used from the commit processing we know
+             the parent directory has only a BASE row, so we can just obtain
+             the information directly by recursing (once!)  */
+
+          svn_relpath_split(&parent_relpath, &name, local_relpath,
+                            scratch_pool);
+
+          SVN_ERR(determine_commit_repos_info(repos_id, &parent_repos_relpath,
+                                              wcroot, parent_relpath,
+                                              scratch_pool, scratch_pool));
+
+          *repos_relpath = svn_relpath_join(parent_repos_relpath, name,
+                                            result_pool);
+          return SVN_NO_ERROR;
+        }
     }
 
-  SVN_ERR(svn_sqlite__reset(stmt));
 
-  /* This was a child node within this wcroot. We want to look at the
-     BASE node of the directory.  */
-  svn_relpath_split(&local_parent_relpath, &name, local_relpath, scratch_pool);
-
-  /* The REPOS_ID will be the same (### until we support mixed-repos)  */
-  SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL,
-                                            &repos_parent_relpath, repos_id,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            NULL, NULL, NULL, NULL, NULL,
-                                            wcroot, local_parent_relpath,
-                                            scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(op_depth == 0); /* And that row must be BASE */
 
-  *repos_relpath = svn_relpath_join(repos_parent_relpath, name, result_pool);
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
+  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 2));
 
-  return SVN_NO_ERROR;
+  *repos_id = svn_sqlite__column_int64(stmt, 1);
+  *repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
+
+  return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
 /* Helper for svn_wc__db_global_commit()
@@ -11103,9 +11162,9 @@ commit_node(svn_wc__db_wcroot_t *wcroot,
 
      For existing nodes, we should retain the (potentially-switched)
      repository information.  */
-  SVN_ERR(determine_repos_info(&repos_id, &repos_relpath,
-                               wcroot, local_relpath,
-                               scratch_pool, scratch_pool));
+  SVN_ERR(determine_commit_repos_info(&repos_id, &repos_relpath,
+                                      wcroot, local_relpath,
+                                      scratch_pool, scratch_pool));
 
   /* ### is it better to select only the data needed?  */
   SVN_ERR(svn_sqlite__get_statement(&stmt_info, wcroot->sdb,

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.h?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db.h Thu Apr 16 03:46:20 2015
@@ -1361,8 +1361,8 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
                        const char *original_uuid,
                        svn_revnum_t original_revision,
                        const apr_array_header_t *children,
-                       svn_boolean_t is_move,
                        svn_depth_t depth,
+                       svn_boolean_t is_move,
                        const svn_skel_t *conflict,
                        const svn_skel_t *work_items,
                        apr_pool_t *scratch_pool);
@@ -1403,6 +1403,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
                            const char *original_uuid,
                            svn_revnum_t original_revision,
                            const char *target,
+                           svn_boolean_t is_move,
                            const svn_skel_t *conflict,
                            const svn_skel_t *work_items,
                            apr_pool_t *scratch_pool);

Modified: subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db_private.h?rev=1673997&r1=1673996&r2=1673997&view=diff
==============================================================================
--- subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/branches/javahl-1.8-extensions/subversion/libsvn_wc/wc_db_private.h Thu Apr 16 03:46:20 2015
@@ -358,6 +358,18 @@ svn_wc__db_with_txn(svn_wc__db_wcroot_t
   SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
 
 
+/* Evaluate the expressions EXPR1..EXPR4 within a transaction, returning the
+ * first error if an error occurs.
+ *
+ * Begin a transaction in WCROOT's DB; evaluate the expressions, which would
+ * typically be  function calls that do some work in DB; finally commit
+ * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
+ * the transaction.
+ */
+#define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
+  SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
+
+
 /* Return CHILDREN mapping const char * names to svn_node_kind_t * for the
    children of LOCAL_RELPATH at OP_DEPTH. */
 svn_error_t *



Mime
View raw message