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

svn commit: r1542685 [4/5] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ subversion/bindin...

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_wc/wc_db_update_move.c Sun Nov 17 10:02:39 2013
@@ -91,7 +91,6 @@
 #include "private/svn_skel.h"
 #include "private/svn_sqlite.h"
 #include "private/svn_wc_private.h"
-#include "private/svn_editor.h"
 
 #include "wc.h"
 #include "props.h"
@@ -114,7 +113,7 @@
  * be made at the move destination.
  */
 
-struct tc_editor_baton {
+typedef struct update_move_baton_t {
   svn_wc__db_t *db;
   svn_wc__db_wcroot_t *wcroot;
   const char *move_root_dst_relpath;
@@ -127,7 +126,7 @@ struct tc_editor_baton {
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
   apr_pool_t *result_pool;  /* For things that live as long as the baton. */
-};
+} update_move_baton_t;
 
 /*
  * Notifications are delayed until the entire update-move transaction
@@ -369,6 +368,35 @@ mark_tree_conflict(const char *local_rel
   return SVN_NO_ERROR;
 }
 
+/* Checks if a specific local path is shadowed as seen from the move root */
+static svn_error_t *
+check_node_shadowed(svn_boolean_t *shadowed,
+                    update_move_baton_t *b,
+                    const char *local_relpath,
+                    apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  int op_depth = -1;
+  *shadowed = FALSE;
+
+  /* ### This should really be optimized by using something smart
+         in the baton */
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (have_row)
+    op_depth = svn_sqlite__column_int(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  *shadowed = (op_depth > relpath_depth(b->move_root_dst_relpath));
+
+  return SVN_NO_ERROR;
+}
+
 /* If LOCAL_RELPATH is a child of the most recently raised
    tree-conflict or is shadowed then set *IS_CONFLICTED to TRUE and
    raise a tree-conflict on the root of the obstruction if such a
@@ -377,7 +405,7 @@ mark_tree_conflict(const char *local_rel
    drive. */
 static svn_error_t *
 check_tree_conflict(svn_boolean_t *is_conflicted,
-                    struct tc_editor_baton *b,
+                    update_move_baton_t *b,
                     const char *local_relpath,
                     svn_node_kind_t old_kind,
                     svn_node_kind_t new_kind,
@@ -455,15 +483,12 @@ check_tree_conflict(svn_boolean_t *is_co
 }
 
 static svn_error_t *
-tc_editor_add_directory(void *baton,
+tc_editor_add_directory(update_move_baton_t *b,
                         const char *relpath,
-                        const apr_array_header_t *children,
                         apr_hash_t *props,
-                        svn_revnum_t replaces_rev,
+                        svn_boolean_t shadowed,
                         apr_pool_t *scratch_pool)
 {
-  struct tc_editor_baton *b = baton;
-  int op_depth = relpath_depth(b->move_root_dst_relpath);
   const char *move_dst_repos_relpath;
   svn_node_kind_t move_dst_kind;
   svn_boolean_t is_conflicted;
@@ -475,9 +500,6 @@ tc_editor_add_directory(void *baton,
 
   /* Update NODES, only the bits not covered by the later call to
      replace_moved_layer. */
-  SVN_ERR(svn_wc__db_extend_parent_delete(b->wcroot, relpath, svn_node_dir,
-                                          op_depth, scratch_pool));
-
   err = svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL,
                                   &move_dst_repos_relpath, NULL, NULL, NULL,
                                   NULL, NULL, NULL, NULL, NULL, NULL,
@@ -502,7 +524,7 @@ tc_editor_add_directory(void *baton,
                               move_dst_repos_relpath,
                               svn_wc_conflict_action_add,
                               scratch_pool));
-  if (is_conflicted)
+  if (is_conflicted || shadowed)
     return SVN_NO_ERROR;
 
   /* Check for unversioned tree-conflict */
@@ -546,16 +568,13 @@ tc_editor_add_directory(void *baton,
 }
 
 static svn_error_t *
-tc_editor_add_file(void *baton,
+tc_editor_add_file(update_move_baton_t *b,
                    const char *relpath,
                    const svn_checksum_t *checksum,
-                   svn_stream_t *contents,
                    apr_hash_t *props,
-                   svn_revnum_t replaces_rev,
+                   svn_boolean_t shadowed,
                    apr_pool_t *scratch_pool)
 {
-  struct tc_editor_baton *b = baton;
-  int op_depth = relpath_depth(b->move_root_dst_relpath);
   const char *move_dst_repos_relpath;
   svn_node_kind_t move_dst_kind;
   svn_node_kind_t old_kind;
@@ -566,9 +585,6 @@ tc_editor_add_file(void *baton,
 
   /* Update NODES, only the bits not covered by the later call to
      replace_moved_layer. */
-  SVN_ERR(svn_wc__db_extend_parent_delete(b->wcroot, relpath, svn_node_file,
-                                          op_depth, scratch_pool));
-
   err = svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL,
                                   &move_dst_repos_relpath, NULL, NULL, NULL,
                                   NULL, NULL, NULL, NULL, NULL, NULL,
@@ -592,7 +608,7 @@ tc_editor_add_file(void *baton,
                               old_kind, svn_node_file, move_dst_repos_relpath,
                               svn_wc_conflict_action_add,
                               scratch_pool));
-  if (is_conflicted)
+  if (is_conflicted || shadowed)
     return SVN_NO_ERROR;
 
   /* Check for unversioned tree-conflict */
@@ -633,27 +649,6 @@ tc_editor_add_file(void *baton,
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-tc_editor_add_symlink(void *baton,
-                      const char *relpath,
-                      const char *target,
-                      apr_hash_t *props,
-                      svn_revnum_t replaces_rev,
-                      apr_pool_t *scratch_pool)
-{
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
-}
-
-static svn_error_t *
-tc_editor_add_absent(void *baton,
-                     const char *relpath,
-                     svn_node_kind_t kind,
-                     svn_revnum_t replaces_rev,
-                     apr_pool_t *scratch_pool)
-{
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
-}
-
 /* All the info we need about one version of a working node. */
 typedef struct working_node_version_t
 {
@@ -724,8 +719,8 @@ update_working_props(svn_wc_notify_state
                      svn_skel_t **conflict_skel,
                      apr_array_header_t **propchanges,
                      apr_hash_t **actual_props,
-                     svn_wc__db_t *db,
-                     const char *local_abspath,
+                     update_move_baton_t *b,
+                     const char *local_relpath,
                      const struct working_node_version_t *old_version,
                      const struct working_node_version_t *new_version,
                      apr_pool_t *result_pool,
@@ -740,49 +735,47 @@ update_working_props(svn_wc_notify_state
    * merge-left version, and the current props of the
    * moved-here working file as the merge-right version.
    */
-  SVN_ERR(svn_wc__db_read_props(actual_props,
-                                db, local_abspath,
-                                result_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_read_props_internal(actual_props,
+                                         b->wcroot, local_relpath,
+                                         result_pool, scratch_pool));
   SVN_ERR(svn_prop_diffs(propchanges, new_version->props, old_version->props,
                          result_pool));
   SVN_ERR(svn_wc__merge_props(conflict_skel, prop_state,
                               &new_actual_props,
-                              db, local_abspath,
+                              b->db, svn_dirent_join(b->wcroot->abspath,
+                                                     local_relpath,
+                                                     scratch_pool),
                               old_version->props, old_version->props,
                               *actual_props, *propchanges,
                               result_pool, scratch_pool));
 
-  /* Setting properties in ACTUAL_NODE with svn_wc__db_op_set_props
-     relies on NODES row having been updated first which we don't do
-     at present. So this extra property diff has the same effect.
+  /* Setting properties in ACTUAL_NODE with svn_wc__db_op_set_props_internal
+     relies on NODES row being updated via a different route .
 
-     ### Perhaps we should update NODES first (but after
-     ### svn_wc__db_read_props above)?  */
+     This extra property diff makes sure we clear the actual row when
+     the final result is unchanged properties. */
   SVN_ERR(svn_prop_diffs(&new_propchanges, new_actual_props, new_version->props,
                          scratch_pool));
   if (!new_propchanges->nelts)
     new_actual_props = NULL;
 
-  /* Install the new actual props. Don't set the conflict_skel yet, because
-     we might need to add a text conflict to it as well. */
-  SVN_ERR(svn_wc__db_op_set_props(db, local_abspath,
-                                  new_actual_props,
-                                  svn_wc__has_magic_property(*propchanges),
-                                  NULL/*conflict_skel*/, NULL/*work_items*/,
-                                  scratch_pool));
+  /* Install the new actual props. */
+  SVN_ERR(svn_wc__db_op_set_props_internal(b->wcroot, local_relpath,
+                                           new_actual_props,
+                                           svn_wc__has_magic_property(
+                                                    *propchanges),
+                                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-tc_editor_alter_directory(void *baton,
+tc_editor_alter_directory(update_move_baton_t *b,
                           const char *dst_relpath,
-                          svn_revnum_t expected_move_dst_revision,
-                          const apr_array_header_t *children,
                           apr_hash_t *new_props,
+                          svn_boolean_t shadowed,
                           apr_pool_t *scratch_pool)
 {
-  struct tc_editor_baton *b = baton;
   const char *move_dst_repos_relpath;
   svn_revnum_t move_dst_revision;
   svn_node_kind_t move_dst_kind;
@@ -790,8 +783,6 @@ tc_editor_alter_directory(void *baton,
   svn_wc__db_status_t status;
   svn_boolean_t is_conflicted;
 
-  SVN_ERR_ASSERT(expected_move_dst_revision == b->old_version->peg_rev);
-
   SVN_ERR(svn_wc__db_depth_get_info(&status, &move_dst_kind, &move_dst_revision,
                                     &move_dst_repos_relpath, NULL, NULL, NULL,
                                     NULL, NULL, &old_version.checksum, NULL,
@@ -800,17 +791,10 @@ tc_editor_alter_directory(void *baton,
                                     relpath_depth(b->move_root_dst_relpath),
                                     scratch_pool, scratch_pool));
 
-  /* If the node would be recorded as svn_wc__db_status_base_deleted it
-     wouldn't have a repos_relpath */
-  /* ### Can svn_wc__db_depth_get_info() do this for us without this hint? */
-  if (status == svn_wc__db_status_deleted && move_dst_repos_relpath)
-    status = svn_wc__db_status_not_present;
 
   /* There might be not-present nodes of a different revision as the same
      depth as a copy. This is commonly caused by copying/moving mixed revision
      directories */
-  SVN_ERR_ASSERT(move_dst_revision == expected_move_dst_revision
-                 || status == svn_wc__db_status_not_present);
   SVN_ERR_ASSERT(move_dst_kind == svn_node_dir);
 
   SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath,
@@ -819,7 +803,7 @@ tc_editor_alter_directory(void *baton,
                               move_dst_repos_relpath,
                               svn_wc_conflict_action_edit,
                               scratch_pool));
-  if (is_conflicted)
+  if (is_conflicted || shadowed)
     return SVN_NO_ERROR;
 
   old_version.location_and_kind = b->old_version;
@@ -841,7 +825,7 @@ tc_editor_alter_directory(void *baton,
       /* ### TODO: Only do this when there is no higher WORKING layer */
       SVN_ERR(update_working_props(&prop_state, &conflict_skel,
                                    &propchanges, &actual_props,
-                                   b->db, dst_abspath,
+                                   b, dst_relpath,
                                    &old_version, &new_version,
                                    scratch_pool, scratch_pool));
 
@@ -888,16 +872,15 @@ tc_editor_alter_directory(void *baton,
  * Set *WORK_ITEMS to any required work items, allocated in RESULT_POOL.
  * Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
-update_working_file(const char *local_relpath,
+update_working_file(update_move_baton_t *b,
+                    const char *local_relpath,
                     const char *repos_relpath,
                     svn_wc_operation_t operation,
                     const working_node_version_t *old_version,
                     const working_node_version_t *new_version,
-                    svn_wc__db_wcroot_t *wcroot,
-                    svn_wc__db_t *db,
                     apr_pool_t *scratch_pool)
 {
-  const char *local_abspath = svn_dirent_join(wcroot->abspath,
+  const char *local_abspath = svn_dirent_join(b->wcroot->abspath,
                                               local_relpath,
                                               scratch_pool);
   const char *old_pristine_abspath;
@@ -911,7 +894,7 @@ update_working_file(const char *local_re
 
   /* ### TODO: Only do this when there is no higher WORKING layer */
   SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges,
-                               &actual_props, db, local_abspath,
+                               &actual_props, b, local_relpath,
                                old_version, new_version,
                                scratch_pool, scratch_pool));
 
@@ -920,12 +903,12 @@ update_working_file(const char *local_re
       svn_boolean_t is_locally_modified;
 
       SVN_ERR(svn_wc__internal_file_modified_p(&is_locally_modified,
-                                               db, local_abspath,
+                                               b->db, local_abspath,
                                                FALSE /* exact_comparison */,
                                                scratch_pool));
       if (!is_locally_modified)
         {
-          SVN_ERR(svn_wc__wq_build_file_install(&work_item, db,
+          SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db,
                                                 local_abspath,
                                                 NULL,
                                                 FALSE /* FIXME: use_commit_times? */,
@@ -945,15 +928,15 @@ update_working_file(const char *local_re
            * moved-here working file as the merge-right version.
            */
           SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath,
-                                               db, wcroot->abspath,
+                                               b->db, b->wcroot->abspath,
                                                old_version->checksum,
                                                scratch_pool, scratch_pool));
           SVN_ERR(svn_wc__db_pristine_get_path(&new_pristine_abspath,
-                                               db, wcroot->abspath,
+                                               b->db, b->wcroot->abspath,
                                                new_version->checksum,
                                                scratch_pool, scratch_pool));
           SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel,
-                                         &merge_outcome, db,
+                                         &merge_outcome, b->db,
                                          old_pristine_abspath,
                                          new_pristine_abspath,
                                          local_abspath,
@@ -982,22 +965,23 @@ update_working_file(const char *local_re
    * too. */
   if (conflict_skel)
     {
-      SVN_ERR(create_conflict_markers(&work_item, local_abspath, db,
+      SVN_ERR(create_conflict_markers(&work_item, local_abspath, b->db,
                                       repos_relpath, conflict_skel,
                                       operation, old_version, new_version,
                                       svn_node_file,
                                       scratch_pool, scratch_pool));
 
-      SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
+      SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, local_relpath,
                                                 conflict_skel,
                                                 scratch_pool));
 
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
     }
 
-  SVN_ERR(svn_wc__db_wq_add(db, wcroot->abspath, work_items, scratch_pool));
+  SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
+                            scratch_pool));
 
-  SVN_ERR(update_move_list_add(wcroot, local_relpath,
+  SVN_ERR(update_move_list_add(b->wcroot, local_relpath,
                                svn_wc_notify_update_update,
                                svn_node_file,
                                content_state,
@@ -1011,15 +995,13 @@ update_working_file(const char *local_re
  * the old state.  Merge the changes into the "working"/"actual" file.
  */
 static svn_error_t *
-tc_editor_alter_file(void *baton,
+tc_editor_alter_file(update_move_baton_t *b, 
                      const char *dst_relpath,
-                     svn_revnum_t expected_move_dst_revision,
                      const svn_checksum_t *new_checksum,
-                     svn_stream_t *new_contents,
                      apr_hash_t *new_props,
+                     svn_boolean_t shadowed,
                      apr_pool_t *scratch_pool)
 {
-  struct tc_editor_baton *b = baton;
   const char *move_dst_repos_relpath;
   svn_revnum_t move_dst_revision;
   svn_node_kind_t move_dst_kind;
@@ -1035,14 +1017,6 @@ tc_editor_alter_file(void *baton,
                                     relpath_depth(b->move_root_dst_relpath),
                                     scratch_pool, scratch_pool));
 
-  /* If the node would be recorded as svn_wc__db_status_base_deleted it
-     wouldn't have a repos_relpath */
-  /* ### Can svn_wc__db_depth_get_info() do this for us without this hint? */
-  if (status == svn_wc__db_status_deleted && move_dst_repos_relpath)
-    status = svn_wc__db_status_not_present;
-
-  SVN_ERR_ASSERT(move_dst_revision == expected_move_dst_revision
-                 || status == svn_wc__db_status_not_present);
   SVN_ERR_ASSERT(move_dst_kind == svn_node_file);
 
   SVN_ERR(check_tree_conflict(&is_conflicted, b, dst_relpath,
@@ -1051,7 +1025,7 @@ tc_editor_alter_file(void *baton,
                               move_dst_repos_relpath,
                               svn_wc_conflict_action_edit,
                               scratch_pool));
-  if (is_conflicted)
+  if (is_conflicted || shadowed)
     return SVN_NO_ERROR;
 
   old_version.location_and_kind = b->old_version;
@@ -1064,9 +1038,8 @@ tc_editor_alter_file(void *baton,
   /* Update file and prop contents if the update has changed them. */
   if (!svn_checksum_match(new_checksum, old_version.checksum) || new_props)
     {
-      SVN_ERR(update_working_file(dst_relpath, move_dst_repos_relpath,
+      SVN_ERR(update_working_file(b, dst_relpath, move_dst_repos_relpath,
                                   b->operation, &old_version, &new_version,
-                                  b->wcroot, b->db,
                                   scratch_pool));
     }
 
@@ -1074,40 +1047,25 @@ tc_editor_alter_file(void *baton,
 }
 
 static svn_error_t *
-tc_editor_alter_symlink(void *baton,
-                        const char *relpath,
-                        svn_revnum_t revision,
-                        const char *target,
-                        apr_hash_t *props,
-                        apr_pool_t *scratch_pool)
-{
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
-}
-
-static svn_error_t *
-tc_editor_delete(void *baton,
+tc_editor_delete(update_move_baton_t *b,
                  const char *relpath,
-                 svn_revnum_t revision,
+                 svn_boolean_t shadowed,
                  apr_pool_t *scratch_pool)
 {
-  struct tc_editor_baton *b = baton;
   svn_sqlite__stmt_t *stmt;
   int op_depth = relpath_depth(b->move_root_dst_relpath);
   const char *move_dst_repos_relpath;
   svn_node_kind_t move_dst_kind;
   svn_boolean_t is_conflicted;
   svn_boolean_t must_delete_working_nodes = FALSE;
-  const char *local_abspath = svn_dirent_join(b->wcroot->abspath, relpath,
-                                              scratch_pool);
-  const char *parent_relpath = svn_relpath_dirname(relpath, scratch_pool);
-  int op_depth_below;
+  const char *local_abspath;
   svn_boolean_t have_row;
+  svn_boolean_t is_modified, is_all_deletes;
 
   SVN_ERR(svn_wc__db_depth_get_info(NULL, &move_dst_kind, NULL,
                                     &move_dst_repos_relpath, NULL, NULL, NULL,
                                     NULL, NULL, NULL, NULL, NULL, NULL,
-                                    b->wcroot, relpath,
-                                    relpath_depth(b->move_root_dst_relpath),
+                                    b->wcroot, relpath, op_depth,
                                     scratch_pool, scratch_pool));
 
   /* Check before retracting delete to catch delete-delete
@@ -1120,52 +1078,51 @@ tc_editor_delete(void *baton,
                               svn_wc_conflict_action_delete,
                               scratch_pool));
 
-  if (!is_conflicted)
+  if (shadowed || is_conflicted)
+    return SVN_NO_ERROR;
+
+  local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool);
+  SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, b->db,
+                                      local_abspath,
+                                      NULL, NULL, scratch_pool));
+  if (is_modified)
     {
-      svn_boolean_t is_modified, is_all_deletes;
+      svn_wc_conflict_reason_t reason;
 
-      SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, b->db,
-                                          local_abspath,
-                                          NULL, NULL, scratch_pool));
-      if (is_modified)
+      if (!is_all_deletes)
         {
-          svn_wc_conflict_reason_t reason;
+          /* No conflict means no NODES rows at the relpath op-depth
+             so it's easy to convert the modified tree into a copy. */
+          SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                          STMT_UPDATE_OP_DEPTH_RECURSIVE));
+          SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
+                                    op_depth, relpath_depth(relpath)));
+          SVN_ERR(svn_sqlite__step_done(stmt));
 
-          if (!is_all_deletes)
-            {
-              /* No conflict means no NODES rows at the relpath op-depth
-                 so it's easy to convert the modified tree into a copy. */
-              SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
-                                              STMT_UPDATE_OP_DEPTH_RECURSIVE));
-              SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
-                                        op_depth, relpath_depth(relpath)));
-              SVN_ERR(svn_sqlite__step_done(stmt));
-
-              reason = svn_wc_conflict_reason_edited;
-            }
-          else
-            {
+          reason = svn_wc_conflict_reason_edited;
+        }
+      else
+        {
 
-              SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
-                                          STMT_DELETE_WORKING_OP_DEPTH_ABOVE));
-              SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
-                                        op_depth));
-              SVN_ERR(svn_sqlite__step_done(stmt));
+          SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                      STMT_DELETE_WORKING_OP_DEPTH_ABOVE));
+          SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+                                    op_depth));
+          SVN_ERR(svn_sqlite__step_done(stmt));
 
-              reason = svn_wc_conflict_reason_deleted;
-              must_delete_working_nodes = TRUE;
-            }
-          is_conflicted = TRUE;
-          SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version,
-                                     b->new_version, b->move_root_dst_relpath,
-                                     b->operation,
-                                     move_dst_kind,
-                                     svn_node_none,
-                                     move_dst_repos_relpath, reason,
-                                     svn_wc_conflict_action_delete, NULL,
-                                     scratch_pool));
-          b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath);
+          reason = svn_wc_conflict_reason_deleted;
+          must_delete_working_nodes = TRUE;
         }
+      is_conflicted = TRUE;
+      SVN_ERR(mark_tree_conflict(relpath, b->wcroot, b->db, b->old_version,
+                                 b->new_version, b->move_root_dst_relpath,
+                                 b->operation,
+                                 move_dst_kind,
+                                 svn_node_none,
+                                 move_dst_repos_relpath, reason,
+                                 svn_wc_conflict_action_delete, NULL,
+                                 scratch_pool));
+      b->conflict_root_relpath = apr_pstrdup(b->result_pool, relpath);
     }
 
   if (!is_conflicted || must_delete_working_nodes)
@@ -1234,6 +1191,20 @@ tc_editor_delete(void *baton,
                                      svn_wc_notify_state_inapplicable));
       svn_pool_destroy(iterpool);
     }
+  return SVN_NO_ERROR;
+}
+
+/* Delete handling for both WORKING and shadowed nodes */
+static svn_error_t *
+delete_move_leaf(update_move_baton_t *b,
+                 const char *relpath,
+                 apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  int op_depth = relpath_depth(b->move_root_dst_relpath);
+  const char *parent_relpath = svn_relpath_dirname(relpath, scratch_pool);
+  svn_boolean_t have_row;
+  int op_depth_below;
 
   /* Deleting the ROWS is valid so long as we update the parent before
      committing the transaction.  The removed rows could have been
@@ -1279,58 +1250,6 @@ tc_editor_delete(void *baton,
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-tc_editor_copy(void *baton,
-               const char *src_relpath,
-               svn_revnum_t src_revision,
-               const char *dst_relpath,
-               svn_revnum_t replaces_rev,
-               apr_pool_t *scratch_pool)
-{
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
-}
-
-static svn_error_t *
-tc_editor_move(void *baton,
-               const char *src_relpath,
-               svn_revnum_t src_revision,
-               const char *dst_relpath,
-               svn_revnum_t replaces_rev,
-               apr_pool_t *scratch_pool)
-{
-  return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL);
-}
-
-static svn_error_t *
-tc_editor_complete(void *baton,
-                   apr_pool_t *scratch_pool)
-{
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-tc_editor_abort(void *baton,
-                apr_pool_t *scratch_pool)
-{
-  return SVN_NO_ERROR;
-}
-
-/* The editor callback table implementing the receiver. */
-static const svn_editor_cb_many_t editor_ops = {
-  tc_editor_add_directory,
-  tc_editor_add_file,
-  tc_editor_add_symlink,
-  tc_editor_add_absent,
-  tc_editor_alter_directory,
-  tc_editor_alter_file,
-  tc_editor_alter_symlink,
-  tc_editor_delete,
-  tc_editor_copy,
-  tc_editor_move,
-  tc_editor_complete,
-  tc_editor_abort
-};
-
 
 /*
  * Driver code.
@@ -1532,14 +1451,14 @@ props_match(svn_boolean_t *match,
 /* ### Drive TC_EDITOR so as to ...
  */
 static svn_error_t *
-update_moved_away_node(svn_editor_t *tc_editor,
+update_moved_away_node(update_move_baton_t *b,
+                       svn_wc__db_wcroot_t *wcroot,
                        const char *src_relpath,
                        const char *dst_relpath,
                        int src_op_depth,
                        const char *move_root_dst_relpath,
-                       svn_revnum_t move_root_dst_revision,
+                       svn_boolean_t shadowed,
                        svn_wc__db_t *db,
-                       svn_wc__db_wcroot_t *wcroot,
                        apr_pool_t *scratch_pool)
 {
   svn_node_kind_t src_kind, dst_kind;
@@ -1559,28 +1478,33 @@ update_moved_away_node(svn_editor_t *tc_
   if (src_kind == svn_node_none
       || (dst_kind != svn_node_none && src_kind != dst_kind))
     {
-      SVN_ERR(svn_editor_delete(tc_editor, dst_relpath,
-                                move_root_dst_revision));
+      SVN_ERR(tc_editor_delete(b, dst_relpath, shadowed,
+                               scratch_pool));
+
+      /* And perform some work that in some ways belongs in
+         replace_moved_layer() after creating all conflicts */
+      SVN_ERR(delete_move_leaf(b, dst_relpath, scratch_pool));
     }
 
   if (src_kind != svn_node_none && src_kind != dst_kind)
     {
+      if (shadowed)
+        {
+          SVN_ERR(svn_wc__db_extend_parent_delete(
+                        b->wcroot, dst_relpath, src_kind,
+                        relpath_depth(b->move_root_dst_relpath), 
+                        scratch_pool));
+        }
       if (src_kind == svn_node_file || src_kind == svn_node_symlink)
         {
-          svn_stream_t *contents;
-
-          SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
-                                           wcroot->abspath, src_checksum,
-                                           scratch_pool, scratch_pool));
-          SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
-                                      src_checksum, contents, src_props,
-                                      move_root_dst_revision));
+          SVN_ERR(tc_editor_add_file(b, dst_relpath,
+                                     src_checksum, src_props,
+                                     shadowed, scratch_pool));
         }
       else if (src_kind == svn_node_dir)
         {
-          SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
-                                           src_children, src_props,
-                                           move_root_dst_revision));
+          SVN_ERR(tc_editor_add_directory(b, dst_relpath, src_props,
+                                          shadowed, scratch_pool));
         }
     }
   else if (src_kind != svn_node_none)
@@ -1594,22 +1518,14 @@ update_moved_away_node(svn_editor_t *tc_
 
       if (src_kind == svn_node_file || src_kind == svn_node_symlink)
         {
-          svn_stream_t *contents;
-
           if (svn_checksum_match(src_checksum, dst_checksum))
             src_checksum = NULL;
 
-          if (src_checksum)
-            SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
-                                             wcroot->abspath, src_checksum,
-                                             scratch_pool, scratch_pool));
-          else
-            contents = NULL;
-
           if (props || src_checksum)
-            SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
-                                          move_root_dst_revision,
-                                          src_checksum, contents, props));
+            SVN_ERR(tc_editor_alter_file(b, dst_relpath,
+                                         src_checksum, props,
+                                         shadowed,
+                                         scratch_pool));
         }
       else if (src_kind == svn_node_dir)
         {
@@ -1617,9 +1533,9 @@ update_moved_away_node(svn_editor_t *tc_
             = children_match(src_children, dst_children) ? NULL : src_children;
 
           if (props || children)
-            SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
-                                               move_root_dst_revision,
-                                               children, props));
+            SVN_ERR(tc_editor_alter_directory(b, dst_relpath, props,
+                                              shadowed,
+                                              scratch_pool));
         }
     }
 
@@ -1633,6 +1549,7 @@ update_moved_away_node(svn_editor_t *tc_
           const char *child_name;
           const char *src_child_relpath, *dst_child_relpath;
           svn_boolean_t src_only = FALSE, dst_only = FALSE;
+          svn_boolean_t child_shadowed = shadowed;
 
           svn_pool_clear(iterpool);
           if (i >= src_children->nelts)
@@ -1666,11 +1583,14 @@ update_moved_away_node(svn_editor_t *tc_
           dst_child_relpath = svn_relpath_join(dst_relpath, child_name,
                                                iterpool);
 
-          SVN_ERR(update_moved_away_node(tc_editor, src_child_relpath,
+          if (!child_shadowed)
+            SVN_ERR(check_node_shadowed(&child_shadowed, b, dst_child_relpath,
+                                        iterpool));
+
+          SVN_ERR(update_moved_away_node(b, wcroot, src_child_relpath,
                                          dst_child_relpath, src_op_depth,
-                                         move_root_dst_relpath,
-                                         move_root_dst_revision,
-                                         db, wcroot, scratch_pool));
+                                         move_root_dst_relpath, child_shadowed,
+                                         db, iterpool));
 
           if (!dst_only)
             ++i;
@@ -1735,7 +1655,7 @@ replace_moved_layer(const char *src_relp
 
 /* Transfer changes from the move source to the move destination.
  *
- * Drive the editor TC_EDITOR with the difference between DST_RELPATH
+ * Drive the editor with the difference between DST_RELPATH
  * (at its own op-depth) and SRC_RELPATH (at op-depth zero).
  *
  * Then update the single op-depth layer in the move destination subtree
@@ -1745,7 +1665,7 @@ replace_moved_layer(const char *src_relp
  * ### And the other params?
  */
 static svn_error_t *
-drive_tree_conflict_editor(svn_editor_t *tc_editor,
+drive_tree_conflict_editor(update_move_baton_t *b,
                            const char *src_relpath,
                            const char *dst_relpath,
                            int src_op_depth,
@@ -1776,16 +1696,14 @@ drive_tree_conflict_editor(svn_editor_t 
   /* We walk the move source (i.e. the post-update tree), comparing each node
    * with the equivalent node at the move destination and applying the update
    * to nodes at the move destination. */
-  SVN_ERR(update_moved_away_node(tc_editor, src_relpath, dst_relpath,
+  SVN_ERR(update_moved_away_node(b, wcroot, src_relpath, dst_relpath,
                                  src_op_depth,
-                                 dst_relpath, old_version->peg_rev,
-                                 db, wcroot, scratch_pool));
+                                 dst_relpath, FALSE /* never shadowed */,
+                                 db, scratch_pool));
 
   SVN_ERR(replace_moved_layer(src_relpath, dst_relpath, src_op_depth,
                               wcroot, scratch_pool));
 
-  SVN_ERR(svn_editor_complete(tc_editor));
-
   return SVN_NO_ERROR;
 }
 
@@ -1804,14 +1722,13 @@ suitable_for_move(svn_wc__db_wcroot_t *w
                                     STMT_SELECT_BASE_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  if (have_row)
-    {
-      revision = svn_sqlite__column_revnum(stmt, 4);
-      repos_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
   if (!have_row)
-    return SVN_NO_ERROR; /* Return an error? */
+    return svn_error_trace(svn_sqlite__reset(stmt));
+
+  revision = svn_sqlite__column_revnum(stmt, 4);
+  repos_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
+
+  SVN_ERR(svn_sqlite__reset(stmt));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_REPOS_PATH_REVISION));
@@ -1874,8 +1791,7 @@ update_moved_away_conflict_victim(svn_wc
                                   void *cancel_baton,
                                   apr_pool_t *scratch_pool)
 {
-  svn_editor_t *tc_editor;
-  struct tc_editor_baton *tc_editor_baton;
+  update_move_baton_t umb;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   const char *dummy1, *dummy2, *dummy3;
@@ -1885,12 +1801,12 @@ update_moved_away_conflict_victim(svn_wc
   /* ### assumes wc write lock already held */
 
   /* Construct editor baton. */
-  tc_editor_baton = apr_pcalloc(scratch_pool, sizeof(*tc_editor_baton));
+  memset(&umb, 0, sizeof(umb));
   SVN_ERR(svn_wc__db_op_depth_moved_to(
-            &dummy1, &tc_editor_baton->move_root_dst_relpath, &dummy2, &dummy3,
+            &dummy1, &umb.move_root_dst_relpath, &dummy2, &dummy3,
             relpath_depth(move_src_op_root_relpath) - 1,
             wcroot, victim_relpath, scratch_pool, scratch_pool));
-  if (tc_editor_baton->move_root_dst_relpath == NULL)
+  if (umb.move_root_dst_relpath == NULL)
     return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                              _("The node '%s' has not been moved away"),
                              svn_dirent_local_style(
@@ -1899,16 +1815,16 @@ update_moved_away_conflict_victim(svn_wc
                                scratch_pool));
 
   move_root_dst_abspath
-    = svn_dirent_join(wcroot->abspath, tc_editor_baton->move_root_dst_relpath,
+    = svn_dirent_join(wcroot->abspath, umb.move_root_dst_relpath,
                       scratch_pool);
   SVN_ERR(svn_wc__write_check(db, move_root_dst_abspath, scratch_pool));
 
-  tc_editor_baton->operation = operation;
-  tc_editor_baton->old_version= old_version;
-  tc_editor_baton->new_version= new_version;
-  tc_editor_baton->db = db;
-  tc_editor_baton->wcroot = wcroot;
-  tc_editor_baton->result_pool = scratch_pool;
+  umb.operation = operation;
+  umb.old_version= old_version;
+  umb.new_version= new_version;
+  umb.db = db;
+  umb.wcroot = wcroot;
+  umb.result_pool = scratch_pool;
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_HIGHEST_WORKING_NODE));
@@ -1934,20 +1850,16 @@ update_moved_away_conflict_victim(svn_wc
   SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
                                       STMT_CREATE_UPDATE_MOVE_LIST));
   /* Create the editor... */
-  SVN_ERR(svn_editor_create(&tc_editor, tc_editor_baton,
-                            cancel_func, cancel_baton,
-                            scratch_pool, scratch_pool));
-  SVN_ERR(svn_editor_setcb_many(tc_editor, &editor_ops, scratch_pool));
 
   /* ... and drive it. */
-  SVN_ERR(drive_tree_conflict_editor(tc_editor,
+  SVN_ERR(drive_tree_conflict_editor(&umb,
                                      victim_relpath,
-                                     tc_editor_baton->move_root_dst_relpath,
+                                     umb.move_root_dst_relpath,
                                      src_op_depth,
                                      operation,
                                      local_change, incoming_change,
-                                     tc_editor_baton->old_version,
-                                     tc_editor_baton->new_version,
+                                     umb.old_version,
+                                     umb.new_version,
                                      db, wcroot,
                                      cancel_func, cancel_baton,
                                      scratch_pool));
@@ -2033,11 +1945,12 @@ svn_wc__db_update_moved_away_conflict_vi
 }
 
 /* Set *CAN_BUMP to TRUE if DEPTH is sufficient to cover the entire
-   BASE tree at LOCAL_RELPATH, to FALSE otherwise. */
+   tree  LOCAL_RELPATH at OP_DEPTH, to FALSE otherwise. */
 static svn_error_t *
 depth_sufficient_to_bump(svn_boolean_t *can_bump,
-                         const char *local_relpath,
                          svn_wc__db_wcroot_t *wcroot,
+                         const char *local_relpath,
+                         int op_depth,
                          svn_depth_t depth,
                          apr_pool_t *scratch_pool)
 {
@@ -2054,21 +1967,21 @@ depth_sufficient_to_bump(svn_boolean_t *
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_SELECT_OP_DEPTH_CHILDREN));
       SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
-                                local_relpath, 0));
+                                local_relpath, op_depth));
       break;
 
     case svn_depth_files:
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_SELECT_HAS_NON_FILE_CHILDREN));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
-                                local_relpath));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                                local_relpath, op_depth));
       break;
 
     case svn_depth_immediates:
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_SELECT_HAS_GRANDCHILDREN));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
-                                local_relpath));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                                local_relpath, op_depth));
       break;
     default:
       SVN_ERR_MALFUNCTION();
@@ -2140,10 +2053,149 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
   return SVN_NO_ERROR;
 }
 
-/* Bump LOCAL_RELPATH, and all the children of LOCAL_RELPATH, that are
-   moved-to at op-depth greater than OP_DEPTH.  SRC_DONE is a hash
-   with keys that are 'const char *' relpaths that have already been
-   bumped.  Any bumped paths are added to SRC_DONE. */
+/* Checks if SRC_RELPATH is within BUMP_DEPTH from BUMP_ROOT. Sets
+ * *SKIP to TRUE if the node should be skipped, otherwise to FALSE.
+ * Sets *SRC_DEPTH to the remaining depth at SRC_RELPATH.
+ */
+static svn_error_t *
+check_bump_layer(svn_boolean_t *skip,
+                 svn_depth_t *src_depth,
+                 const char *bump_root,
+                 svn_depth_t bump_depth,
+                 const char *src_relpath,
+                 svn_node_kind_t src_kind,
+                 apr_pool_t *scratch_pool)
+{
+  const char *relpath;
+
+  *skip = FALSE;
+  *src_depth = bump_depth;
+
+  relpath = svn_relpath_skip_ancestor(bump_root, src_relpath);
+
+  if (!relpath)
+    *skip = TRUE;
+
+  if (bump_depth == svn_depth_infinity)
+    return SVN_NO_ERROR;
+
+  if (relpath && *relpath == '\0')
+    return SVN_NO_ERROR;
+
+  switch (bump_depth)
+    {
+      case svn_depth_empty:
+        *skip = TRUE;
+        break;
+
+      case svn_depth_files:
+        if (src_kind != svn_node_file)
+          {
+            *skip = TRUE;
+            break;
+          }
+        /* Fallthrough */
+      case svn_depth_immediates:
+        if (!relpath || relpath_depth(relpath) > 1)
+          *skip = TRUE;
+
+        *src_depth = svn_depth_empty;
+        break;
+      default:
+        SVN_ERR_MALFUNCTION();
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* The guts of bump_moved_away: Determines if a move can be bumped to match
+ * the move origin and if so performs this bump.
+ */
+static svn_error_t *
+bump_moved_layer(svn_boolean_t *recurse,
+                 svn_wc__db_wcroot_t *wcroot,
+                 const char *local_relpath,
+                 int op_depth,
+                 const char *src_relpath,
+                 int src_op_depth,
+                 svn_node_kind_t src_kind,
+                 svn_depth_t src_depth,
+                 const char *dst_relpath,
+                 apr_hash_t *src_done,
+                 svn_wc__db_t *db,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  svn_skel_t *conflict;
+  svn_boolean_t can_bump;
+  const char *src_root_relpath = src_relpath;
+
+  *recurse = FALSE;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_HAS_LAYER_BETWEEN));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath,
+                            op_depth, src_op_depth));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  if (have_row)
+    return SVN_NO_ERROR;
+
+  if (op_depth == 0)
+    SVN_ERR(depth_sufficient_to_bump(&can_bump, wcroot, src_relpath,
+                                     op_depth, src_depth, scratch_pool));
+  else
+    /* Having chosen to bump an entire BASE tree move we
+       always have sufficient depth to bump subtree moves. */
+    can_bump = TRUE;
+
+  if (!can_bump)
+    {
+      SVN_ERR(bump_mark_tree_conflict(wcroot, src_relpath,
+                                      src_root_relpath, dst_relpath,
+                                      db, scratch_pool));
+
+      return SVN_NO_ERROR;
+    }
+
+  while (relpath_depth(src_root_relpath) > src_op_depth)
+    src_root_relpath = svn_relpath_dirname(src_root_relpath, scratch_pool);
+
+
+  if (svn_hash_gets(src_done, src_relpath))
+    return SVN_NO_ERROR;
+
+  svn_hash_sets(src_done, apr_pstrdup(result_pool, src_relpath), "");
+
+  SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, wcroot,
+                                            src_root_relpath,
+                                            scratch_pool, scratch_pool));
+
+  /* ### TODO: check this is the right sort of tree-conflict? */
+  if (!conflict)
+    {
+      /* ### TODO: verify moved_here? */
+      SVN_ERR(replace_moved_layer(src_relpath, dst_relpath,
+                                 op_depth, wcroot, scratch_pool));
+
+      *recurse = TRUE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Bump moves of LOCAL_RELPATH and all its descendants that were
+   originally below LOCAL_RELPATH at op-depth OP_DEPTH.
+
+   SRC_DONE is a hash with keys that are 'const char *' relpaths
+   that have already been bumped.  Any bumped paths are added to
+   SRC_DONE. */
 static svn_error_t *
 bump_moved_away(svn_wc__db_wcroot_t *wcroot,
                 const char *local_relpath,
@@ -2157,6 +2209,7 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   apr_pool_t *iterpool;
+  svn_error_t *err = NULL;
 
   iterpool = svn_pool_create(scratch_pool);
 
@@ -2167,130 +2220,51 @@ bump_moved_away(svn_wc__db_wcroot_t *wcr
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   while(have_row)
     {
-      svn_sqlite__stmt_t *stmt2;
       const char *src_relpath, *dst_relpath;
-      int src_op_depth = svn_sqlite__column_int(stmt, 2);
-      svn_error_t *err;
-      svn_skel_t *conflict;
-      svn_depth_t src_depth = depth;
+      int src_op_depth;
+      svn_node_kind_t src_kind;
+      svn_depth_t src_depth;
+      svn_boolean_t skip;
 
       svn_pool_clear(iterpool);
 
       src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
       dst_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+      src_op_depth = svn_sqlite__column_int(stmt, 2);
+      src_kind = svn_sqlite__column_token(stmt, 3, kind_map);
 
-      if (depth != svn_depth_infinity)
-        {
-          svn_boolean_t skip_this_src = FALSE;
-          svn_node_kind_t src_kind;
+      err = check_bump_layer(&skip, &src_depth, local_relpath, depth,
+          src_relpath, src_kind, iterpool);
 
-          if (strcmp(src_relpath, local_relpath))
-            {
-              switch (depth)
-                {
-                case svn_depth_empty:
-                  skip_this_src = TRUE;
-                  break;
-                case svn_depth_files:
-                  src_kind = svn_sqlite__column_token(stmt, 3, kind_map);
-                  if (src_kind != svn_node_file)
-                    {
-                      skip_this_src = TRUE;
-                      break;
-                    }
-                  /* Fallthrough */
-                case svn_depth_immediates:
-                  if (strcmp(svn_relpath_dirname(src_relpath, scratch_pool),
-                             local_relpath))
-                    skip_this_src = TRUE;
-                  src_depth = svn_depth_empty;
-                  break;
-                default:
-                  SVN_ERR_MALFUNCTION();
-                }
-            }
-
-          if (skip_this_src)
-            {
-              SVN_ERR(svn_sqlite__step(&have_row, stmt));
-              continue;
-            }
-        }
+      if (err)
+        break;
 
-      err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
-                                      STMT_HAS_LAYER_BETWEEN);
-      if (!err)
-       err = svn_sqlite__bindf(stmt2, "isdd", wcroot->wc_id, local_relpath,
-                               op_depth, src_op_depth);
-      if (!err)
-        err = svn_sqlite__step(&have_row, stmt2);
-      if (!err)
-        err = svn_sqlite__reset(stmt2);
-      if (!err && !have_row)
+      if (!skip)
         {
-          svn_boolean_t can_bump;
-          const char *src_root_relpath = src_relpath;
+          svn_boolean_t recurse;
 
-          if (op_depth == 0)
-            err = depth_sufficient_to_bump(&can_bump, src_relpath, wcroot,
-                                           src_depth, scratch_pool);
-          else
-            /* Having chosen to bump an entire BASE tree move we
-               always have sufficient depth to bump subtree moves. */
-            can_bump = TRUE;
-
-          if (!err)
-            {
-              if (!can_bump)
-                {
-                  err = bump_mark_tree_conflict(wcroot, src_relpath,
-                                                src_root_relpath, dst_relpath,
-                                                db, scratch_pool);
-                  if (err)
-                    return svn_error_compose_create(err,
-                                                    svn_sqlite__reset(stmt));
-                  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-                  continue;
-                }
-
-              while (relpath_depth(src_root_relpath) > src_op_depth)
-                src_root_relpath = svn_relpath_dirname(src_root_relpath,
-                                                       iterpool);
-
-              if (!svn_hash_gets(src_done, src_relpath))
-                {
-                  svn_hash_sets(src_done,
-                                apr_pstrdup(result_pool, src_relpath), "");
-                  err = svn_wc__db_read_conflict_internal(&conflict, wcroot,
-                                                          src_root_relpath,
-                                                          iterpool, iterpool);
-                  /* ### TODO: check this is the right sort of tree-conflict? */
-                  if (!err && !conflict)
-                    {
-                      /* ### TODO: verify moved_here? */
-                      err = replace_moved_layer(src_relpath, dst_relpath,
-                                                op_depth, wcroot, iterpool);
-
-                      if (!err)
-                        err = bump_moved_away(wcroot, dst_relpath,
-                                              relpath_depth(dst_relpath),
-                                              src_done, depth, db,
-                                              result_pool, iterpool);
-                    }
-                }
-            }
+          err = bump_moved_layer(&recurse, wcroot,
+                                 local_relpath, op_depth,
+                                 src_relpath, src_op_depth, src_kind, src_depth,
+                                 dst_relpath,
+                                 src_done, db, result_pool, iterpool);
+
+          if (!err && recurse)
+            err = bump_moved_away(wcroot, dst_relpath, relpath_depth(dst_relpath),
+                                  src_done, depth, db, result_pool, iterpool);
         }
 
       if (err)
-        return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+        break;
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
-  SVN_ERR(svn_sqlite__reset(stmt));
+
+  err = svn_error_compose_create(err, svn_sqlite__reset(stmt));
 
   svn_pool_destroy(iterpool);
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(err);
 }
 
 svn_error_t *
@@ -2502,7 +2476,7 @@ break_moved_away_children_internal(svn_w
                                       STMT_CREATE_UPDATE_MOVE_LIST));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_MOVED_PAIRS_DEPTH));
+                                    STMT_SELECT_MOVED_DESCENDANTS));
   SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
                             relpath_depth(local_relpath)));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_authz_svn/mod_authz_svn.c Sun Nov 17 10:02:39 2013
@@ -91,7 +91,8 @@ create_authz_svn_dir_config(apr_pool_t *
 /* canonicalize ACCESS_FILE based on the type of argument.
  * If SERVER_RELATIVE is true, ACCESS_FILE is a relative
  * path then ACCESS_FILE is converted to an absolute
- * path rooted at the server root. */
+ * path rooted at the server root.
+ * Returns NULL if path is not valid.*/
 static const char *
 canonicalize_access_file(const char *access_file,
                          svn_boolean_t server_relative,
@@ -104,7 +105,11 @@ canonicalize_access_file(const char *acc
   else if (!svn_path_is_repos_relative_url(access_file))
     {
       if (server_relative)
-        access_file = ap_server_root_relative(pool, access_file);
+        {
+          access_file = ap_server_root_relative(pool, access_file);
+          if (access_file == NULL)
+            return NULL;
+        }
 
       access_file = svn_dirent_internal_style(access_file, pool);
     }
@@ -126,6 +131,8 @@ AuthzSVNAccessFile_cmd(cmd_parms *cmd, v
            "directives are mutually exclusive.";
 
   conf->access_file = canonicalize_access_file(arg1, TRUE, cmd->pool);
+  if (!conf->access_file)
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
 
   return NULL;
 }
@@ -145,6 +152,9 @@ AuthzSVNReposRelativeAccessFile_cmd(cmd_
   conf->repo_relative_access_file = canonicalize_access_file(arg1, FALSE,
                                                              cmd->pool);
 
+  if (!conf->repo_relative_access_file)
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
+
   return NULL;
 }
 
@@ -155,6 +165,9 @@ AuthzSVNGroupsFile_cmd(cmd_parms *cmd, v
 
   conf->groups_file = canonicalize_access_file(arg1, TRUE, cmd->pool);
 
+  if (!conf->groups_file)
+    return apr_pstrcat(cmd->pool, "Invalid file path ", arg1, NULL);
+
   return NULL;
 }
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/dav_svn.h Sun Nov 17 10:02:39 2013
@@ -900,6 +900,12 @@ dav_svn__simple_parse_uri(dav_svn__uri_i
                           const char *uri,
                           apr_pool_t *pool);
 
+/* Test the request R to determine if we should return the list of
+ * repositories at the parent path.  Only true if SVNListParentPath directive
+ * is 'on' and the request is for our configured root path. */
+svn_boolean_t
+dav_svn__is_parentpath_list(request_rec *r);
+
 
 int dav_svn__find_ns(const apr_array_header_t *namespaces, const char *uri);
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/mod_dav_svn.c Sun Nov 17 10:02:39 2013
@@ -1103,21 +1103,35 @@ static int dav_svn__translate_name(reque
   const char *fs_path, *repos_basename, *repos_path;
   const char *ignore_cleaned_uri, *ignore_relative_path;
   int ignore_had_slash;
-  dav_error *err;
   dir_conf_t *conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
 
   /* module is not configured, bail out early */
   if (!conf->fs_path && !conf->fs_parent_path)
     return DECLINED;
 
-  /* Retrieve path to repo and within repo for the request */
-  if ((err = dav_svn_split_uri(r, r->uri, conf->root_dir, &ignore_cleaned_uri,
-                               &ignore_had_slash, &repos_basename,
-                               &ignore_relative_path, &repos_path)))
+  if (dav_svn__is_parentpath_list(r))
     {
-      dav_svn__log_err(r, err, APLOG_ERR);
-      return HTTP_INTERNAL_SERVER_ERROR;
+      /* SVNListParentPath is on and the request is for the conf->root_dir,
+       * so just set the repos_basename to an empty string and the repos_path
+       * to NULL so we end up just reporting our parent path as the bogus
+       * path. */
+      repos_basename = "";
+      repos_path = NULL;
     }
+  else
+    {
+      /* Retrieve path to repo and within repo for the request */
+      dav_error *err = dav_svn_split_uri(r, r->uri, conf->root_dir,
+                                         &ignore_cleaned_uri,
+                                         &ignore_had_slash, &repos_basename,
+                                         &ignore_relative_path, &repos_path);
+      if (err)
+        {
+          dav_svn__log_err(r, err, APLOG_ERR);
+          return err->status;
+        }
+    }
+
   if (conf->fs_parent_path)
     {
       fs_path = svn_dirent_join(conf->fs_parent_path, repos_basename,

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/repos.c Sun Nov 17 10:02:39 2013
@@ -1348,7 +1348,7 @@ dav_svn_split_uri(request_rec *r,
         if (ch == '\0')
           {
             /* relative is just "!svn", which is malformed. */
-            return dav_svn__new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
+            return dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
                                       SVN_ERR_APMOD_MALFORMED_URI,
                                       "Nothing follows the svn special_uri.");
           }
@@ -1375,7 +1375,7 @@ dav_svn_split_uri(request_rec *r,
                           *repos_path = NULL;
                         else
                           return dav_svn__new_error(
-                                     r->pool, HTTP_INTERNAL_SERVER_ERROR,
+                                     r->pool, HTTP_NOT_FOUND,
                                      SVN_ERR_APMOD_MALFORMED_URI,
                                      "Missing info after special_uri.");
                       }
@@ -1399,7 +1399,7 @@ dav_svn_split_uri(request_rec *r,
                             /* Did we break from the loop prematurely? */
                             if (j != (defn->numcomponents - 1))
                               return dav_svn__new_error(
-                                         r->pool, HTTP_INTERNAL_SERVER_ERROR,
+                                         r->pool, HTTP_NOT_FOUND,
                                          SVN_ERR_APMOD_MALFORMED_URI,
                                          "Not enough components after "
                                          "special_uri.");
@@ -1419,7 +1419,7 @@ dav_svn_split_uri(request_rec *r,
                     else
                       {
                         return
-                          dav_svn__new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
+                          dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
                                         SVN_ERR_APMOD_MALFORMED_URI,
                                         "Unknown data after special_uri.");
                       }
@@ -1430,7 +1430,7 @@ dav_svn_split_uri(request_rec *r,
 
             if (defn->name == NULL)
               return
-                dav_svn__new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
+                dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
                                    SVN_ERR_APMOD_MALFORMED_URI,
                                    "Couldn't match subdir after special_uri.");
           }
@@ -1970,26 +1970,12 @@ get_resource(request_rec *r,
 
   /* Special case: detect and build the SVNParentPath as a unique type
      of private resource, iff the SVNListParentPath directive is 'on'. */
-  if (fs_parent_path && dav_svn__get_list_parentpath_flag(r))
+  if (dav_svn__is_parentpath_list(r))
     {
-      char *uri = apr_pstrdup(r->pool, r->uri);
-      char *parentpath = apr_pstrdup(r->pool, root_path);
-      apr_size_t uri_len = strlen(uri);
-      apr_size_t parentpath_len = strlen(parentpath);
-
-      if (uri[uri_len-1] == '/')
-        uri[uri_len-1] = '\0';
-
-      if (parentpath[parentpath_len-1] == '/')
-        parentpath[parentpath_len-1] = '\0';
-
-      if (strcmp(parentpath, uri) == 0)
-        {
-          err = get_parentpath_resource(r, resource);
-          if (err)
-            return err;
-          return NULL;
-        }
+      err = get_parentpath_resource(r, resource);
+      if (err)
+        return err;
+      return NULL;
     }
 
   /* This does all the work of interpreting/splitting the request uri. */
@@ -2456,9 +2442,12 @@ get_parent_resource(const dav_resource *
       parent->info = parentinfo;
 
       parentinfo->uri_path =
-        svn_stringbuf_create(get_parent_path(resource->info->uri_path->data,
-                                             TRUE, resource->pool),
-                             resource->pool);
+        svn_stringbuf_create(
+               get_parent_path(
+                   svn_urlpath__canonicalize(resource->info->uri_path->data,
+                                            resource->pool),
+                   TRUE, resource->pool),
+               resource->pool);
       parentinfo->repos = resource->info->repos;
       parentinfo->root = resource->info->root;
       parentinfo->r = resource->info->r;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/util.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/mod_dav_svn/util.c Sun Nov 17 10:02:39 2013
@@ -425,6 +425,32 @@ dav_svn__simple_parse_uri(dav_svn__uri_i
                           "Unsupported URI form");
 }
 
+svn_boolean_t
+dav_svn__is_parentpath_list(request_rec *r)
+{
+  const char *fs_parent_path = dav_svn__get_fs_parent_path(r);
+
+  if (fs_parent_path && dav_svn__get_list_parentpath_flag(r))
+    {
+      const char *root_path = dav_svn__get_root_dir(r);
+      char *uri = apr_pstrdup(r->pool, r->uri);
+      char *parentpath = apr_pstrdup(r->pool, root_path);
+      apr_size_t uri_len = strlen(uri);
+      apr_size_t parentpath_len = strlen(parentpath);
+
+      if (uri[uri_len-1] == '/')
+        uri[uri_len-1] = '\0';
+
+      if (parentpath[parentpath_len-1] == '/')
+        parentpath[parentpath_len-1] = '\0';
+
+      if (strcmp(parentpath, uri) == 0)
+        {
+          return TRUE;
+        }
+    }
+  return FALSE;
+}
 
 /* ### move this into apr_xml */
 int

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/serve.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/serve.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/serve.c Sun Nov 17 10:02:39 2013
@@ -202,12 +202,13 @@ log_authz_denied(const char *path,
   return logger__write(b->logger, line, strlen(line));
 }
 
-/* If CFG specifies a path to the password DB, read that DB and store it
- * in REPOSITORY->PWDB.
+/* If CFG specifies a path to the password DB, read that DB through
+ * CONFIG_POOL and store it in REPOSITORY->PWDB.
  */
 static svn_error_t *
 load_pwdb_config(repository_t *repository,
                  svn_config_t *cfg,
+                 svn_repos__config_pool_t *config_pool,
                  apr_pool_t *pool)
 {
   const char *pwdb_path;
@@ -223,8 +224,9 @@ load_pwdb_config(repository_t *repositor
       pwdb_path = svn_dirent_internal_style(pwdb_path, pool);
       pwdb_path = svn_dirent_join(repository->base, pwdb_path, pool);
 
-      err = svn_config_read3(&repository->pwdb, pwdb_path, TRUE,
-                             FALSE, FALSE, pool);
+      err = svn_repos__config_pool_get(&repository->pwdb, NULL, config_pool,
+                                       pwdb_path, TRUE, FALSE,
+                                       repository->repos, pool);
       if (err)
         {
           /* Because it may be possible to read the pwdb file with some
@@ -281,8 +283,8 @@ canonicalize_access_file(const char **ac
   return SVN_NO_ERROR;
 }
 
-/* Load the authz database for the listening server based on the
-   entries in the SERVER struct.
+/* Load the authz database for the listening server through AUTHZ_POOL
+   based on the entries in the SERVER struct.
 
    SERVER and CONN must not be NULL. The real errors will be logged with
    SERVER and CONN but return generic errors to the client. */
@@ -290,6 +292,7 @@ static svn_error_t *
 load_authz_config(repository_t *repository,
                   const char *repos_root,
                   svn_config_t *cfg,
+                  svn_repos__authz_pool_t *authz_pool,
                   apr_pool_t *pool)
 {
   const char *authzdb_path;
@@ -317,8 +320,9 @@ load_authz_config(repository_t *reposito
                                        repos_root, pool);
 
       if (!err)
-        err = svn_repos_authz_read2(&repository->authzdb, authzdb_path,
-                                    groupsdb_path, TRUE, pool);
+        err = svn_repos__authz_pool_get(&repository->authzdb, authz_pool,
+                                        authzdb_path, groupsdb_path, TRUE,
+                                        repository->repos, pool);
 
       if (err)
         return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL);
@@ -3264,11 +3268,17 @@ repos_path_valid(const char *path)
  * capabilities to CAPABILITIES, which must be at least as long-lived
  * as POOL, and whose elements are SVN_RA_CAPABILITY_*.  VHOST and
  * READ_ONLY flags are the same as in the server baton.
+ *
+ * CONFIG_POOL, AUTHZ_POOL and REPOS_POOL shall be used to load any
+ * object of the respective type.
  */
 static svn_error_t *find_repos(const char *url, const char *root,
                                svn_boolean_t vhost, svn_boolean_t read_only,
                                svn_config_t *cfg, repository_t *repository,
                                const apr_array_header_t *capabilities,
+                               svn_repos__config_pool_t *config_pool,
+                               svn_repos__authz_pool_t *authz_pool,
+                               svn_repos__repos_pool_t *repos_pool,
                                apr_pool_t *pool)
 {
   const char *path, *full_path, *repos_root, *fs_path, *hooks_env, *val;
@@ -3306,8 +3316,8 @@ static svn_error_t *find_repos(const cha
                              "No repository found in '%s'", url);
 
   /* Open the repository and fill in b with the resulting information. */
-  SVN_ERR(svn_repos_open2(&repository->repos, repos_root,
-                          repository->fs_config, pool));
+  SVN_ERR(svn_repos__repos_pool_get(&repository->repos, repos_pool,
+                                    repos_root, "", pool));
   SVN_ERR(svn_repos_remember_client_capabilities(repository->repos,
                                                  capabilities));
   repository->fs = svn_repos_fs(repository->repos);
@@ -3330,17 +3340,15 @@ static svn_error_t *find_repos(const cha
     {
       repository->base = svn_repos_conf_dir(repository->repos, pool);
 
-      SVN_ERR(svn_config_read3(&cfg,
-                               svn_repos_svnserve_conf(repository->repos,
-                                                       pool),
-                               FALSE, /* must_exist */
-                               FALSE, /* section_names_case_sensitive */
-                               FALSE, /* option_names_case_sensitive */
-                               pool));
+      SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+                                         svn_repos_svnserve_conf
+                                            (repository->repos, pool), 
+                                         FALSE, FALSE, repository->repos,
+                                         pool));
     }
 
-  SVN_ERR(load_pwdb_config(repository, cfg, pool));
-  SVN_ERR(load_authz_config(repository, repos_root, cfg, pool));
+  SVN_ERR(load_pwdb_config(repository, cfg, config_pool, pool));
+  SVN_ERR(load_authz_config(repository, repos_root, cfg, authz_pool, pool));
 
 #ifdef SVN_HAVE_SASL
   /* Should we use Cyrus SASL? */
@@ -3573,15 +3581,6 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
   b.logger = params->logger;
   b.client_info = get_client_info(conn, params, pool);
 
-  /* construct FS configuration parameters */
-  repository.fs_config = apr_hash_make(pool);
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
-                params->cache_txdeltas ? "1" :"0");
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
-                params->cache_fulltexts ? "1" :"0");
-  svn_hash_sets(repository.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                params->cache_revprops ? "1" :"0");
-
   /* Send greeting.  We don't support version 1 any more, so we can
    * send an empty mechlist. */
   if (params->compression_level > 0)
@@ -3665,7 +3664,10 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
   err = handle_config_error(find_repos(client_url, params->root,
                                        b.vhost, b.read_only,
                                        params->cfg, b.repository,
-                                       cap_words, pool), &b);
+                                       cap_words, params->config_pool,
+                                       params->authz_pool, params->repos_pool,
+                                       pool),
+                            &b);
   if (!err)
     {
       if (repository.anon_access == NO_ACCESS

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/server.h?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/server.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/server.h Sun Nov 17 10:02:39 2013
@@ -37,7 +37,8 @@ extern "C" {
 #include "svn_ra_svn.h"
 
 #include "private/svn_mutex.h"
-
+#include "private/svn_repos_private.h"
+  
 enum username_case_type { CASE_FORCE_UPPER, CASE_FORCE_LOWER, CASE_ASIS };
 
 enum authn_type { UNAUTHENTICATED, AUTHENTICATED };
@@ -54,7 +55,6 @@ typedef struct repository_t {
   const char *realm;       /* Authentication realm */
   const char *repos_url;   /* URL to base of repository */
   svn_stringbuf_t *fs_path;/* Decoded base in-repos path (w/ leading slash) */
-  apr_hash_t *fs_config;   /* Additional FS configuration parameters */
   enum username_case_type username_case; /* Case-normalize the username? */
   svn_boolean_t use_sasl;  /* Use Cyrus SASL for authentication;
                               always false if SVN_HAVE_SASL not defined */
@@ -115,17 +115,17 @@ typedef struct serve_params_t {
   /* logging data structure; possibly NULL. */
   struct logger_t *logger;
 
-  /* Username case normalization style. */
-  enum username_case_type username_case;
+  /* all configurations should be opened through this factory */
+  svn_repos__config_pool_t *config_pool;
 
-  /* Enable text delta caching for all FSFS repositories. */
-  svn_boolean_t cache_txdeltas;
+  /* all authz data should be opened through this factory */
+  svn_repos__authz_pool_t *authz_pool;
 
-  /* Enable full-text caching for all FSFS repositories. */
-  svn_boolean_t cache_fulltexts;
+  /* all repositories should be opened through this factory */
+  svn_repos__repos_pool_t *repos_pool;
 
-  /* Enable revprop caching for all FSFS repositories. */
-  svn_boolean_t cache_revprops;
+  /* Username case normalization style. */
+  enum username_case_type username_case;
 
   /* Size of the in-memory cache (used by FSFS only). */
   apr_uint64_t memory_cache_size;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c Sun Nov 17 10:02:39 2013
@@ -48,6 +48,7 @@
 #include "svn_cache_config.h"
 #include "svn_version.h"
 #include "svn_io.h"
+#include "svn_hash.h"
 
 #include "svn_private_config.h"
 
@@ -616,7 +617,12 @@ int main(int argc, const char *argv[])
   apr_thread_t *tid;
 #endif
 #endif
+  svn_boolean_t is_multi_threaded;
   enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
+  apr_hash_t *fs_config = NULL;
+  svn_boolean_t cache_fulltexts = TRUE;
+  svn_boolean_t cache_txdeltas = TRUE;
+  svn_boolean_t cache_revprops = FALSE;
   apr_uint16_t port = SVN_RA_SVN_PORT;
   const char *host = NULL;
   int family = APR_INET;
@@ -667,12 +673,12 @@ int main(int argc, const char *argv[])
   params.cfg = NULL;
   params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
   params.logger = NULL;
+  params.config_pool = NULL;
+  params.authz_pool = NULL;
+  params.repos_pool = NULL;
   params.vhost = FALSE;
   params.username_case = CASE_ASIS;
   params.memory_cache_size = (apr_uint64_t)-1;
-  params.cache_fulltexts = TRUE;
-  params.cache_txdeltas = TRUE;
-  params.cache_revprops = FALSE;
   params.zero_copy_limit = 0;
   params.error_check_interval = 4096;
 
@@ -809,18 +815,15 @@ int main(int argc, const char *argv[])
           break;
 
         case SVNSERVE_OPT_CACHE_TXDELTAS:
-          params.cache_txdeltas
-             = svn_tristate__from_word(arg) == svn_tristate_true;
+          cache_txdeltas = svn_tristate__from_word(arg) == svn_tristate_true;
           break;
 
         case SVNSERVE_OPT_CACHE_FULLTEXTS:
-          params.cache_fulltexts
-             = svn_tristate__from_word(arg) == svn_tristate_true;
+          cache_fulltexts = svn_tristate__from_word(arg) == svn_tristate_true;
           break;
 
         case SVNSERVE_OPT_CACHE_REVPROPS:
-          params.cache_revprops
-             = svn_tristate__from_word(arg) == svn_tristate_true;
+          cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true;
           break;
 
         case SVNSERVE_OPT_CLIENT_SPEED:
@@ -908,17 +911,41 @@ int main(int argc, const char *argv[])
       usage(argv[0], pool);
     }
 
+  /* construct object pools */
+  is_multi_threaded = handling_mode == connection_mode_thread;
+  fs_config = apr_hash_make(pool);
+  svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
+                cache_txdeltas ? "1" :"0");
+  svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
+                cache_fulltexts ? "1" :"0");
+  svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+                cache_revprops ? "1" :"0");
+
+  SVN_INT_ERR(svn_repos__config_pool_create(&params.config_pool,
+                                            is_multi_threaded,
+                                            pool));
+  SVN_INT_ERR(svn_repos__authz_pool_create(&params.authz_pool,
+                                           params.config_pool,
+                                           is_multi_threaded,
+                                           pool));
+  SVN_INT_ERR(svn_repos__repos_pool_create(&params.repos_pool,
+                                           fs_config,
+                                           is_multi_threaded,
+                                           pool));
+  
   /* If a configuration file is specified, load it and any referenced
    * password and authorization files. */
   if (config_filename)
     {
       params.base = svn_dirent_dirname(config_filename, pool);
 
-      SVN_INT_ERR(svn_config_read3(&params.cfg, config_filename,
-                                   TRUE, /* must_exist */
-                                   FALSE, /* section_names_case_sensitive */
-                                   FALSE, /* option_names_case_sensitive */
-                                   pool));
+      SVN_INT_ERR(svn_repos__config_pool_get(&params.cfg, NULL,
+                                             params.config_pool,
+                                             config_filename, 
+                                             TRUE, /* must_exist */
+                                             FALSE, /* names_case_sensitive */
+                                             NULL,
+                                             pool));
     }
 
   if (log_filename)

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/checkout_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/checkout_tests.py?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/checkout_tests.py (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/checkout_tests.py Sun Nov 17 10:02:39 2013
@@ -1116,8 +1116,25 @@ def checkout_wc_from_drive(sbox):
       'B/F'               : Item(status='A '),
       'B/lambda'          : Item(status='A '),
     })
+
+    expected_wc = wc.State('', {
+      'C'         : Item(),
+      'B/E/beta'  : Item(contents="This is the file 'beta'.\n"),
+      'B/E/alpha' : Item(contents="This is the file 'alpha'.\n"),
+      'B/lambda'  : Item(contents="This is the file 'lambda'.\n"),
+      'B/F'       : Item(),
+      'D/H/omega' : Item(contents="This is the file 'omega'.\n"),
+      'D/H/psi'   : Item(contents="This is the file 'psi'.\n"),
+      'D/H/chi'   : Item(contents="This is the file 'chi'.\n"),
+      'D/G/rho'   : Item(contents="This is the file 'rho'.\n"),
+      'D/G/tau'   : Item(contents="This is the file 'tau'.\n"),
+      'D/G/pi'    : Item(contents="This is the file 'pi'.\n"),
+      'D/gamma'   : Item(contents="This is the file 'gamma'.\n"),
+      'mu'        : Item(contents="This is the file 'mu'.\n"),    
+    })
+    
     svntest.actions.run_and_verify_checkout(repo_url + '/A', wc2_dir,
-                                            expected_output, None,
+                                            expected_output, expected_wc,
                                             None, None, None, None)
 
     wc3_dir = sbox.add_wc_path('3')
@@ -1133,8 +1150,18 @@ def checkout_wc_from_drive(sbox):
       'gamma'             : Item(status='A '),
     })
 
+    expected_wc = wc.State('', {
+      'H/chi'   : Item(contents="This is the file 'chi'.\n"),
+      'H/psi'   : Item(contents="This is the file 'psi'.\n"),
+      'H/omega' : Item(contents="This is the file 'omega'.\n"),
+      'G/pi'    : Item(contents="This is the file 'pi'.\n"),
+      'G/tau'   : Item(contents="This is the file 'tau'.\n"),
+      'G/rho'   : Item(contents="This is the file 'rho'.\n"),
+      'gamma'   : Item(contents="This is the file 'gamma'.\n"),    
+    })
+
     svntest.actions.run_and_verify_checkout(repo_url + '/A/D', wc3_dir,
-                                            expected_output, None,
+                                            expected_output, expected_wc,
                                             None, None, None, None)
 
   finally:

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py Sun Nov 17 10:02:39 2013
@@ -1433,7 +1433,6 @@ def move_many_update_delete(sbox):
   # Would be nice if we could run the resolver as a separate step, 
   # but 'svn resolve' just fails for any value but working
 
-@XFail()
 def move_many_update_add(sbox):
   "move many and add-on-update"
 
@@ -1457,7 +1456,7 @@ def move_many_update_add(sbox):
      'B/A/A'             : Item(status='  ', treeconflict='U'),
      'B/A/A/BB'          : Item(status='  ', treeconflict='A'),
      # And while resolving
-     'A/A/'              : Item(status='  ', treeconflict='C')
+     'A/A'               : Item(status='  ', treeconflict='C')
     })
 
   expected_status.tweak('',
@@ -1485,9 +1484,17 @@ def move_many_update_add(sbox):
   expected_status.tweak('',
                         'B', 'B/A', 'B/A/A', 'B/A/A/A',
                         'C', 'C/A', 'C/A/A', 'C/A/A/A',
+                        'B/A/A/BB',
                         wc_rev='4')
 
+  expected_status.add({
+        'C/A/A/BB'          : Item(status='D ', wc_rev='4'),
+    })
+
+  expected_status.tweak('A/A/A', treeconflict='C')
+
   expected_output = svntest.wc.State(wc_dir, {
+     'A/A/A'             : Item(status='  ', treeconflict='C'),
      'C/A'               : Item(status='  ', treeconflict='C'),
      'C/A/A'             : Item(status='  ', treeconflict='U'),
      'C/A/A/BB'          : Item(status='  ', treeconflict='A'),

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/redirect_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/redirect_tests.py?rev=1542685&r1=1542684&r2=1542685&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/redirect_tests.py (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/redirect_tests.py Sun Nov 17 10:02:39 2013
@@ -140,6 +140,45 @@ def redirected_update(sbox):
   verify_url(wc_dir, sbox.repo_url)
 
 #----------------------------------------------------------------------
+@XFail()
+@SkipUnless(svntest.main.is_ra_type_dav)
+def redirected_nonroot_update(sbox):
+  "redirected update of non-repos-root wc"
+
+  sbox.build(create_wc=False)
+  wc_dir = sbox.wc_dir
+  checkout_url = sbox.repo_url + '/A'
+  relocate_url = sbox.redirected_root_url() + '/A'
+
+  # Checkout a subdir of the repository root.
+  exit_code, out, err = svntest.main.run_svn(None, 'co',
+                                             checkout_url, wc_dir)
+  if err:
+    raise svntest.Failure
+  
+  # Relocate (by cheating) the working copy to the redirect URL.  When
+  # we then update, we'll expect to find ourselves automagically back
+  # to the original URL.  (This is because we can't easily introduce a
+  # redirect to the Apache configuration from the test suite here.)
+  svntest.actions.no_relocate_validation()
+  exit_code, out, err = svntest.main.run_svn(None, 'sw', '--relocate',
+                                             checkout_url, relocate_url,
+                                             wc_dir)
+  svntest.actions.do_relocate_validation()
+
+  # Now update the working copy.
+  exit_code, out, err = svntest.main.run_svn(None, 'up', wc_dir)
+  if err:
+    raise svntest.Failure
+  if not re.match("^Updating '.*':", out[0]):
+    raise svntest.Failure
+  if not redirect_regex.match(out[1]):
+    raise svntest.Failure
+
+  # Verify that we have the expected URL.
+  verify_url(wc_dir, checkout_url)
+
+#----------------------------------------------------------------------
 
 ########################################################################
 # Run the tests
@@ -149,6 +188,7 @@ test_list = [ None,
               temporary_redirect,
               redirected_checkout,
               redirected_update,
+              redirected_nonroot_update,
              ]
 
 if __name__ == '__main__':