subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1545955 [9/15] - in /subversion/branches/fsfs-improvements: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/ subversion/bindings/javahl/native/ s...
Date Wed, 27 Nov 2013 07:53:35 GMT
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db_update_move.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db_update_move.c Wed Nov 27 07:53:29 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
@@ -251,11 +250,14 @@ mark_tree_conflict(const char *local_rel
     : NULL;
 
   if (!new_repos_relpath)
-    new_repos_relpath
-      = svn_relpath_join(new_version->path_in_repos,
-                         svn_relpath_skip_ancestor(move_root_dst_relpath,
-                                                   local_relpath),
-                         scratch_pool);
+    {
+      const char *child_relpath = svn_relpath_skip_ancestor(
+                                            move_root_dst_relpath,
+                                            local_relpath);
+      SVN_ERR_ASSERT(child_relpath != NULL);
+      new_repos_relpath = svn_relpath_join(new_version->path_in_repos,
+                                           child_relpath, scratch_pool);
+    }
 
   err = svn_wc__db_read_conflict_internal(&conflict, wcroot, local_relpath,
                                           scratch_pool, scratch_pool);
@@ -303,7 +305,7 @@ mark_tree_conflict(const char *local_rel
                   && strcmp(move_src_op_root_relpath,
                             svn_dirent_skip_ancestor(wcroot->abspath,
                                                      existing_abspath))))
-            return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+            return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
                                      _("'%s' already in conflict"),
                                      svn_dirent_local_style(local_relpath,
                                                             scratch_pool));
@@ -366,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
@@ -374,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,
@@ -452,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;
@@ -472,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,
@@ -499,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 */
@@ -543,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;
@@ -563,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,
@@ -589,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 */
@@ -630,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
 {
@@ -721,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,
@@ -737,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;
@@ -787,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,
@@ -797,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,
@@ -816,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;
@@ -835,9 +822,10 @@ tc_editor_alter_directory(void *baton,
       apr_hash_t *actual_props;
       apr_array_header_t *propchanges;
 
+      /* ### 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));
 
@@ -884,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;
@@ -905,8 +892,9 @@ update_working_file(const char *local_re
   svn_wc_notify_state_t prop_state, content_state;
   svn_skel_t *work_item, *work_items = NULL;
 
+  /* ### 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));
 
@@ -915,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? */,
@@ -940,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,
@@ -977,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,
@@ -1006,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;
@@ -1030,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,
@@ -1046,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;
@@ -1059,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));
     }
 
@@ -1069,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
@@ -1115,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;
-
-          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));
+          /* 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)
@@ -1229,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
@@ -1274,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.
@@ -1407,9 +1331,9 @@ get_tc_info(svn_wc_operation_t *operatio
 
 /* Return *PROPS, *CHECKSUM, *CHILDREN and *KIND for LOCAL_RELPATH at
    OP_DEPTH provided the row exists.  Return *KIND of svn_node_none if
-   the row does not exist. *CHILDREN is a sorted array of basenames of
-   type 'const char *', rather than a hash, to allow the driver to
-   process children in a defined order. */
+   the row does not exist, or only describes a delete of a lower op-depth.
+   *CHILDREN is a sorted array of basenames of type 'const char *', rather
+   than a hash, to allow the driver to process children in a defined order. */
 static svn_error_t *
 get_info(apr_hash_t **props,
          const svn_checksum_t **checksum,
@@ -1424,16 +1348,36 @@ get_info(apr_hash_t **props,
   apr_hash_t *hash_children;
   apr_array_header_t *sorted_children;
   svn_error_t *err;
+  svn_wc__db_status_t status;
+  const char *repos_relpath;
   int i;
 
-  err = svn_wc__db_depth_get_info(NULL, kind, NULL, NULL, NULL, NULL, NULL,
-                                  NULL, NULL, checksum, NULL, NULL, props,
+  err = svn_wc__db_depth_get_info(&status, kind, NULL, &repos_relpath, NULL,
+                                  NULL, NULL, NULL, NULL, checksum, NULL,
+                                  NULL, props,
                                   wcroot, local_relpath, op_depth,
                                   result_pool, scratch_pool);
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+
+  /* If there is no node at this depth, or only a node that describes a delete
+     of a lower layer we report this node as not existing.
+
+     But when a node is reported as DELETED, but has a repository location it
+     is really a not-present node that must be reported as being there */
+  if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+      || (!err && status == svn_wc__db_status_deleted))
     {
       svn_error_clear(err);
-      *kind = svn_node_none;
+
+      if (kind && (err || !repos_relpath))
+        *kind = svn_node_none;
+      if (checksum)
+        *checksum = NULL;
+      if (props)
+        *props = NULL;
+      if (children)
+        *children = apr_array_make(result_pool, 0, sizeof(const char *));
+
+      return SVN_NO_ERROR;
     }
   else
     SVN_ERR(err);
@@ -1507,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;
@@ -1534,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)
@@ -1569,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)
         {
@@ -1592,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));
         }
     }
 
@@ -1608,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)
@@ -1641,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;
@@ -1710,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
@@ -1720,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,
@@ -1751,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;
 }
 
@@ -1779,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));
@@ -1849,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;
@@ -1860,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(
@@ -1874,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));
@@ -1909,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));
@@ -2008,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)
 {
@@ -2029,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();
@@ -2115,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,
@@ -2132,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);
 
@@ -2142,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;
-
-          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();
-                }
-            }
+      err = check_bump_layer(&skip, &src_depth, local_relpath, depth,
+          src_relpath, src_kind, iterpool);
 
-          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 *
@@ -2324,7 +2323,6 @@ resolve_delete_raise_moved_away(svn_wc__
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-  int op_depth = relpath_depth(local_relpath);
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
@@ -2333,26 +2331,31 @@ resolve_delete_raise_moved_away(svn_wc__
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_OP_DEPTH_MOVED_PAIR));
   SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
-                            op_depth));
+                            relpath_depth(local_relpath)));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   while(have_row)
     {
-      const char *moved_relpath = svn_sqlite__column_text(stmt, 0, NULL);
-      const char *move_root_dst_relpath = svn_sqlite__column_text(stmt, 1,
-                                                                  NULL);
-      const char *moved_dst_repos_relpath = svn_sqlite__column_text(stmt, 2,
-                                                                    NULL);
+      svn_error_t *err;
+      const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      svn_node_kind_t src_kind = svn_sqlite__column_token(stmt, 1, kind_map);
+      const char *dst_relpath = svn_sqlite__column_text(stmt, 2, NULL);
+      const char *src_repos_relpath = svn_sqlite__column_text(stmt, 3, NULL);
       svn_pool_clear(iterpool);
 
-      SVN_ERR(mark_tree_conflict(moved_relpath,
-                                 wcroot, db, old_version, new_version,
-                                 move_root_dst_relpath, operation,
-                                 svn_node_dir /* ### ? */,
-                                 svn_node_dir /* ### ? */,
-                                 moved_dst_repos_relpath,
-                                 svn_wc_conflict_reason_moved_away,
-                                 action, local_relpath,
-                                 iterpool));
+      SVN_ERR_ASSERT(src_repos_relpath != NULL);
+
+      err = mark_tree_conflict(src_relpath,
+                               wcroot, db, old_version, new_version,
+                               dst_relpath, operation,
+                               src_kind /* ### old kind */,
+                               src_kind /* ### new kind */,
+                               src_repos_relpath,
+                               svn_wc_conflict_reason_moved_away,
+                               action, local_relpath,
+                               iterpool);
+
+      if (err)
+        return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
@@ -2411,7 +2414,6 @@ break_move(svn_wc__db_wcroot_t *wcroot,
            const char *src_relpath,
            int src_op_depth,
            const char *dst_relpath,
-           int dst_op_depth,
            apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
@@ -2422,11 +2424,12 @@ break_move(svn_wc__db_wcroot_t *wcroot,
                             src_op_depth));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-  /* This statement clears moved_here. */
+  /* The destination is always an op-root, so we can calculate the depth
+     from there. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_UPDATE_OP_DEPTH_RECURSIVE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id,
-                            dst_relpath, dst_op_depth, dst_op_depth));
+                                    STMT_CLEAR_MOVED_HERE_RECURSIVE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            dst_relpath, relpath_depth(dst_relpath)));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
   return SVN_NO_ERROR;
@@ -2455,7 +2458,6 @@ svn_wc__db_resolve_break_moved_away_inte
   SVN_ERR(break_move(wcroot, local_relpath,
                      relpath_depth(move_src_op_root_relpath),
                      move_dst_op_root_relpath,
-                     relpath_depth(move_dst_op_root_relpath),
                      scratch_pool));
 
   return SVN_NO_ERROR;
@@ -2474,8 +2476,9 @@ break_moved_away_children_internal(svn_w
                                       STMT_CREATE_UPDATE_MOVE_LIST));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_MOVED_PAIR2));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+                                    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));
 
   iterpool = svn_pool_create(scratch_pool);
@@ -2488,7 +2491,7 @@ break_moved_away_children_internal(svn_w
       svn_pool_clear(iterpool);
 
       SVN_ERR(break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
-                         relpath_depth(dst_relpath), iterpool));
+                         iterpool));
       SVN_ERR(update_move_list_add(wcroot, src_relpath,
                                    svn_wc_notify_move_broken,
                                    svn_node_unknown,

Modified: subversion/branches/fsfs-improvements/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_authz_svn/mod_authz_svn.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_authz_svn/mod_authz_svn.c Wed Nov 27 07:53:29 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, SVN_VA_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, SVN_VA_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, SVN_VA_NULL);
+
   return NULL;
 }
 

Modified: subversion/branches/fsfs-improvements/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/dav_svn.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/dav_svn.h Wed Nov 27 07:53:29 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/fsfs-improvements/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/mod_dav_svn.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/mod_dav_svn.c Wed Nov 27 07:53:29 2013
@@ -1095,30 +1095,77 @@ static int dav_svn__handler(request_rec 
 
 #define NO_MAP_TO_STORAGE_NOTE "dav_svn-no-map-to-storage"
 
-/* Prevent filename on the request from being set since we aren't serving a
- * file off the disk.  This means that <Directory> blocks will not match and
- * that * %f in logging formats will show as "-". */
+/* Fill the filename on the request with a bogus path since we aren't serving
+ * a file off the disk.  This means that <Directory> blocks will not match and
+ * %f in logging formats will show as "dav_svn:/path/to/repo/path/in/repo".
+ */
 static int dav_svn__translate_name(request_rec *r)
 {
+  const char *fs_path, *repos_basename, *repos_path;
+  const char *ignore_cleaned_uri, *ignore_relative_path;
+  int ignore_had_slash;
   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;
 
-  /* Be paranoid and set it to NULL just in case some other module set it
-   * before we got called. */ 
-  r->filename = NULL;
+  if (dav_svn__is_parentpath_list(r))
+    {
+      /* 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,
+                                r->pool);
+    }
+  else
+    {
+      fs_path = conf->fs_path;
+    }
+
+  /* Avoid a trailing slash on the bogus path when repos_path is just "/" */
+  if (repos_path && '/' == repos_path[0] && '\0' == repos_path[1])
+    repos_path = NULL;
+
+  /* Combine 'dav_svn:', fs_path and repos_path to produce the bogus path we're
+   * placing in r->filename.  We can't use our standard join helpers such
+   * as svn_dirent_join.  fs_path is a dirent and repos_path is a fspath
+   * (that can be trivially converted to a relpath by skipping the leading
+   * slash).  In general it is safe to join these, but when a path in a
+   * repository is 'trunk/c:hi' this results in a non canonical dirent on
+   * Windows. Instead we just cat them together. */
+  r->filename = apr_pstrcat(r->pool,
+                            "dav_svn:", fs_path, repos_path, SVN_VA_NULL);
 
-  /* Leave a note to ourselves so that we know not to decline in the 
+  /* Leave a note to ourselves so that we know not to decline in the
    * map_to_storage hook. */
-  apr_table_setn(r->notes, NO_MAP_TO_STORAGE_NOTE, (const char*)1); 
+  apr_table_setn(r->notes, NO_MAP_TO_STORAGE_NOTE, (const char*)1);
   return OK;
 }
 
 /* Prevent core_map_to_storage from running if we prevented the r->filename
  * from being set since core_map_to_storage doesn't like r->filename being
- * NULL. */
+ * bogus. */
 static int dav_svn__map_to_storage(request_rec *r)
 {
   /* Check a note we left in translate_name since map_to_storage doesn't

Modified: subversion/branches/fsfs-improvements/subversion/mod_dav_svn/reports/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/reports/update.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/reports/update.c Wed Nov 27 07:53:29 2013
@@ -934,7 +934,7 @@ validate_input_revision(svn_revnum_t rev
                         const dav_resource *resource)
 {
   if (! SVN_IS_VALID_REVNUM(revision))
-    return SVN_NO_ERROR;
+    return NULL;
 
   if (revision > youngest)
     {
@@ -958,7 +958,7 @@ validate_input_revision(svn_revnum_t rev
                                   "Invalid revision found in update report "
                                   "request.", resource->pool);
     }
-  return SVN_NO_ERROR;
+  return NULL;
 }
 
 

Modified: subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c Wed Nov 27 07:53:29 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.");
@@ -1413,13 +1413,13 @@ dav_svn_split_uri(request_rec *r,
                         else
                           {
                             /* Found a slash after the special components. */
-                            *repos_path = apr_pstrdup(r->pool, start);
+                            *repos_path = apr_pstrdup(r->pool, start - 1);
                           }
                       }
                     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.");
           }
@@ -1439,7 +1439,7 @@ dav_svn_split_uri(request_rec *r,
       {
         /* There's no "!svn/" at all, so the relative path is already
            a valid path within the repository.  */
-        *repos_path = apr_pstrdup(r->pool, relative);
+        *repos_path = apr_pstrdup(r->pool, relative - 1);
       }
   }
 
@@ -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. */
@@ -2173,7 +2159,7 @@ get_resource(request_rec *r,
       svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                     dav_svn__get_fulltext_cache_flag(r) ? "1" :"0");
       svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                    dav_svn__get_revprop_cache_flag(r) ? "1" :"0");
+                    dav_svn__get_revprop_cache_flag(r) ? "2" :"0");
 
       /* Disallow BDB/event until issue 4157 is fixed. */
       if (!strcmp(ap_show_mpm(), "event"))
@@ -2205,9 +2191,16 @@ get_resource(request_rec *r,
              leak that path back to the client, because that would be
              a security risk, but we do want to log the real error on
              the server side. */
-          return dav_svn__sanitize_error(serr, "Could not open the requested "
-                                         "SVN filesystem",
-                                         HTTP_INTERNAL_SERVER_ERROR, r);
+
+          apr_status_t cause = svn_error_root_cause(serr)->apr_err;
+          if (APR_STATUS_IS_ENOENT(cause) || APR_STATUS_IS_ENOTDIR(cause))
+            return dav_svn__sanitize_error(
+                serr, "Could not find the requested SVN filesystem",
+                HTTP_NOT_FOUND, r);
+          else
+            return dav_svn__sanitize_error(
+                serr, "Could not open the requested SVN filesystem",
+                HTTP_INTERNAL_SERVER_ERROR, r);
         }
 
       /* Cache the open repos for the next request on this connection */
@@ -2456,9 +2449,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;
@@ -3799,23 +3795,29 @@ copy_resource(const dav_resource *src,
         return err;
     }
 
-  serr = svn_dirent_get_absolute(&src_repos_path,
-                                 svn_repos_path(src->info->repos->repos,
-                                                src->pool),
-                                 src->pool);
-  if (!serr)
-    serr = svn_dirent_get_absolute(&dst_repos_path,
-                                   svn_repos_path(dst->info->repos->repos,
-                                                  dst->pool),
-                                   dst->pool);
+  src_repos_path = svn_repos_path(src->info->repos->repos, src->pool);
+  dst_repos_path = svn_repos_path(dst->info->repos->repos, dst->pool);
+
+  if (strcmp(src_repos_path, dst_repos_path) != 0)
+    {
+      /* Perhaps the source and dst repos use different path formats? */
+      serr = svn_error_compose_create(
+                svn_dirent_get_absolute(&src_repos_path, src_repos_path,
+                                        src->pool),
+                svn_dirent_get_absolute(&dst_repos_path, dst_repos_path,
+                                        dst->pool));
+
+      if (!serr && (strcmp(src_repos_path, dst_repos_path) != 0))
+          return dav_svn__new_error_tag(
+                dst->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+                "Copy source and destination are in different repositories.",
+                SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);
+    }
+  else
+      serr = SVN_NO_ERROR;
 
   if (!serr)
     {
-      if (strcmp(src_repos_path, dst_repos_path) != 0)
-        return dav_svn__new_error_tag
-          (dst->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
-           "Copy source and destination are in different repositories.",
-           SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);
       serr = svn_fs_copy(src->info->root.root,  /* root object of src rev*/
                          src->info->repos_path, /* relative path of src */
                          dst->info->root.root,  /* root object of dst txn*/

Modified: subversion/branches/fsfs-improvements/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/util.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/util.c Wed Nov 27 07:53:29 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/fsfs-improvements/subversion/svn/add-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/add-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/add-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/add-cmd.c Wed Nov 27 07:53:29 2013
@@ -83,7 +83,7 @@ svn_cl__add(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_ENTRY_EXISTS,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
 
   svn_pool_destroy(iterpool);

Modified: subversion/branches/fsfs-improvements/subversion/svn/blame-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/blame-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/blame-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/blame-cmd.c Wed Nov 27 07:53:29 2013
@@ -74,7 +74,7 @@ blame_receiver_xml(void *baton,
                         "line-number",
                         apr_psprintf(pool, "%" APR_INT64_T_FMT,
                                      line_no + 1),
-                        NULL);
+                        SVN_VA_NULL);
 
   if (SVN_IS_VALID_REVNUM(revision))
     svn_cl__print_xml_commit(&sb, revision,
@@ -88,7 +88,7 @@ blame_receiver_xml(void *baton,
     {
       /* "<merged>" */
       svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "merged",
-                            "path", merged_path, NULL);
+                            "path", merged_path, SVN_VA_NULL);
 
       svn_cl__print_xml_commit(&sb, merged_revision,
                              svn_prop_get_value(merged_rev_props,
@@ -350,7 +350,7 @@ svn_cl__blame(apr_getopt_t *os,
           if (! svn_path_is_url(target))
             outpath = svn_dirent_local_style(truepath, subpool);
           svn_xml_make_open_tag(&bl.sbuf, pool, svn_xml_normal, "target",
-                                "path", outpath, NULL);
+                                "path", outpath, SVN_VA_NULL);
 
           receiver = blame_receiver_xml;
         }

Modified: subversion/branches/fsfs-improvements/subversion/svn/cat-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/cat-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/cat-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/cat-cmd.c Wed Nov 27 07:53:29 2013
@@ -84,7 +84,7 @@ svn_cl__cat(apr_getopt_t *os,
                            SVN_ERR_ENTRY_NOT_FOUND,
                            SVN_ERR_CLIENT_IS_DIRECTORY,
                            SVN_ERR_FS_NOT_FOUND,
-                           SVN_NO_ERROR));
+                           0));
     }
   svn_pool_destroy(subpool);
 

Modified: subversion/branches/fsfs-improvements/subversion/svn/changelist-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/changelist-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/changelist-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/changelist-cmd.c Wed Nov 27 07:53:29 2013
@@ -106,7 +106,7 @@ svn_cl__changelist(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_UNVERSIONED_RESOURCE,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
   else
     {
@@ -117,7 +117,7 @@ svn_cl__changelist(apr_getopt_t *os,
                errors, opt_state->quiet,
                SVN_ERR_UNVERSIONED_RESOURCE,
                SVN_ERR_WC_PATH_NOT_FOUND,
-               SVN_NO_ERROR));
+               0));
     }
 
   if (errors->nelts > 0)

Modified: subversion/branches/fsfs-improvements/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/cl.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/cl.h (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/cl.h Wed Nov 27 07:53:29 2013
@@ -320,7 +320,7 @@ extern const apr_getopt_option_t svn_cl_
  *
  * Typically, error codes like SVN_ERR_UNVERSIONED_RESOURCE,
  * SVN_ERR_ENTRY_NOT_FOUND, etc, are supplied in varargs.  Don't
- * forget to terminate the argument list with SVN_NO_ERROR.
+ * forget to terminate the argument list with 0 (or APR_SUCCESS).
  */
 svn_error_t *
 svn_cl__try(svn_error_t *err,

Modified: subversion/branches/fsfs-improvements/subversion/svn/diff-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/diff-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/diff-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/diff-cmd.c Wed Nov 27 07:53:29 2013
@@ -117,7 +117,7 @@ summarize_xml(const svn_client_diff_summ
                         "kind", svn_cl__node_kind_str_xml(summary->node_kind),
                         "item", kind_to_word(summary->summarize_kind),
                         "props", summary->prop_changed ? "modified" : "none",
-                        NULL);
+                        SVN_VA_NULL);
 
   svn_xml_escape_cdata_cstring(&sb, path, pool);
   svn_xml_make_close_tag(&sb, pool, "path");
@@ -212,7 +212,7 @@ svn_cl__diff(apr_getopt_t *os,
       SVN_ERR(svn_cl__xml_print_header("diff", pool));
 
       sb = svn_stringbuf_create_empty(pool);
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", SVN_VA_NULL);
       SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
     }
 

Modified: subversion/branches/fsfs-improvements/subversion/svn/info-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/svn/info-cmd.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/svn/info-cmd.c (original)
+++ subversion/branches/fsfs-improvements/subversion/svn/info-cmd.c Wed Nov 27 07:53:29 2013
@@ -100,7 +100,7 @@ print_info_xml(void *baton,
                                   path_prefix, target, pool),
                         "kind", svn_cl__node_kind_str_xml(info->kind),
                         "revision", rev_str,
-                        NULL);
+                        SVN_VA_NULL);
 
   /* "<url> xx </url>" */
   svn_cl__xml_tagged_cdata(&sb, pool, "url", info->URL);
@@ -121,7 +121,8 @@ print_info_xml(void *baton,
   if (info->repos_root_URL || info->repos_UUID)
     {
       /* "<repository>" */
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository",
+                            SVN_VA_NULL);
 
       /* "<root> xx </root>" */
       svn_cl__xml_tagged_cdata(&sb, pool, "root", info->repos_root_URL);
@@ -136,7 +137,8 @@ print_info_xml(void *baton,
   if (info->wc_info)
     {
       /* "<wc-info>" */
-      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);
+      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info",
+                            SVN_VA_NULL);
 
       /* "<wcroot-abspath> xx </wcroot-abspath>" */
       if (info->wc_info->wcroot_abspath)



Mime
View raw message