You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/01/20 18:52:21 UTC

svn commit: r1653314 [16/20] - in /subversion/branches/move-tracking-2: ./ notes/ subversion/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/perl/native/ subversion/bindings/swig/perl/native/t/ subversion/bindings/...

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_update_move.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db_update_move.c Tue Jan 20 17:52:18 2015
@@ -101,6 +101,20 @@
 #include "token-map.h"
 
 /* Helper functions */
+/* Return the absolute path, in local path style, of LOCAL_RELPATH
+   in WCROOT.  */
+static const char *
+path_for_error_message(const svn_wc__db_wcroot_t *wcroot,
+                       const char *local_relpath,
+                       apr_pool_t *result_pool)
+{
+  const char *local_abspath
+    = svn_dirent_join(wcroot->abspath, local_relpath, result_pool);
+
+  return svn_dirent_local_style(local_abspath, result_pool);
+}
+
+/* Ensure that there is a working copy lock for LOCAL_RELPATH in WCROOT */
 static svn_error_t *
 verify_write_lock(svn_wc__db_wcroot_t *wcroot,
                   const char *local_relpath,
@@ -114,11 +128,8 @@ verify_write_lock(svn_wc__db_wcroot_t *w
     {
       return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
                                _("No write-lock in '%s'"),
-                               svn_dirent_local_style(
-                                            svn_dirent_join(wcroot->abspath,
-                                                            local_relpath,
-                                                            scratch_pool),
-                                            scratch_pool));
+                               path_for_error_message(wcroot, local_relpath,
+                                                      scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -308,7 +319,7 @@ mark_tree_conflict(const char *local_rel
           && conflict_operation != svn_wc_operation_switch)
         return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                                  _("'%s' already in conflict"),
-                                 svn_dirent_local_style(local_relpath,
+                                 path_for_error_message(wcroot, local_relpath,
                                                         scratch_pool));
 
       if (tree_conflicted)
@@ -332,7 +343,8 @@ mark_tree_conflict(const char *local_rel
                                                      existing_abspath))))
             return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
                                      _("'%s' already in conflict"),
-                                     svn_dirent_local_style(local_relpath,
+                                     path_for_error_message(wcroot,
+                                                            local_relpath,
                                                             scratch_pool));
 
           /* Already a suitable tree-conflict. */
@@ -396,28 +408,33 @@ mark_tree_conflict(const char *local_rel
 /* 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,
+                    svn_wc__db_wcroot_t *wcroot,
                     const char *local_relpath,
+                    const char *move_root_dst_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,
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", 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));
+    {
+      int op_depth = -1;
 
-  *shadowed = (op_depth > relpath_depth(b->move_root_dst_relpath));
+      *shadowed = (op_depth > relpath_depth(move_root_dst_relpath));
+    }
+  else
+    *shadowed = FALSE;
+  SVN_ERR(svn_sqlite__reset(stmt));
 
   return SVN_NO_ERROR;
 }
@@ -576,8 +593,7 @@ tc_editor_add_directory(update_move_bato
       SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, abspath,
                                            scratch_pool, scratch_pool));
 
-      SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
-                                scratch_pool));
+      SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool));
       /* Fall through */
     case svn_node_dir:
       break;
@@ -663,8 +679,7 @@ tc_editor_add_file(update_move_baton_t *
                                         TRUE  /* record_file_info */,
                                         scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
-                            scratch_pool));
+  SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool));
 
   SVN_ERR(update_move_list_add(b->wcroot, relpath,
                                svn_wc_notify_update_add,
@@ -867,8 +882,8 @@ tc_editor_alter_directory(update_move_ba
           SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath,
                                                     conflict_skel,
                                                     scratch_pool));
-          SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
-                                    scratch_pool));
+          SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items,
+                                             scratch_pool));
         }
 
     SVN_ERR(update_move_list_add(b->wcroot, dst_relpath,
@@ -1003,8 +1018,7 @@ update_working_file(update_move_baton_t
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
     }
 
-  SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items,
-                            scratch_pool));
+  SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, scratch_pool));
 
   SVN_ERR(update_move_list_add(b->wcroot, local_relpath,
                                svn_wc_notify_update_update,
@@ -1182,8 +1196,7 @@ tc_editor_delete(update_move_baton_t *b,
                                                b->wcroot->abspath, del_abspath,
                                                iterpool, iterpool);
           if (!err)
-            err = svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
-                                    iterpool);
+            err = svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool);
           if (err)
             return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 
@@ -1205,8 +1218,7 @@ tc_editor_delete(update_move_baton_t *b,
         SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db,
                                              b->wcroot->abspath, local_abspath,
                                              iterpool, iterpool));
-      SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item,
-                                iterpool));
+      SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool));
 
       if (!is_conflicted)
         SVN_ERR(update_move_list_add(b->wcroot, relpath,
@@ -1221,23 +1233,23 @@ tc_editor_delete(update_move_baton_t *b,
 
 /* Delete handling for both WORKING and shadowed nodes */
 static svn_error_t *
-delete_move_leaf(update_move_baton_t *b,
-                 const char *relpath,
+delete_move_leaf(svn_wc__db_wcroot_t *wcroot,
+                 const char *local_relpath,
+                 int op_depth,
                  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
+  /* Deleting the ROWS is valid as long as we update the parent before
      committing the transaction.  The removed rows could have been
      replacing a lower layer in which case we need to add base-deleted
      rows. */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_HIGHEST_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, parent_relpath,
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            svn_relpath_dirname(local_relpath, scratch_pool),
                             op_depth));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (have_row)
@@ -1246,30 +1258,38 @@ delete_move_leaf(update_move_baton_t *b,
   if (have_row)
     {
       /* Remove non-shadowing nodes. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_DELETE_NO_LOWER_LAYER));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
+      SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath,
                                 op_depth, op_depth_below));
       SVN_ERR(svn_sqlite__step_done(stmt));
 
       /* Convert remaining shadowing nodes to presence='base-deleted'. */
-      SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_REPLACE_WITH_BASE_DELETED));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
                                 op_depth));
       SVN_ERR(svn_sqlite__step_done(stmt));
     }
   else
     {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_DELETE_WORKING_OP_DEPTH));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
                                 op_depth));
       SVN_ERR(svn_sqlite__step_done(stmt));
     }
 
-  /* Retract any base-delete. */
-  SVN_ERR(svn_wc__db_retract_parent_delete(b->wcroot, relpath, op_depth,
+  /* Retract any base-delete for descendants. */
+  {
+    SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_DELETE_WORKING_BASE_DELETE));
+    SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
+                              op_depth));
+    SVN_ERR(svn_sqlite__step_done(stmt));
+  }
+  /* And for the node itself */
+  SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, op_depth,
                                            scratch_pool));
 
   return SVN_NO_ERROR;
@@ -1492,6 +1512,9 @@ update_moved_away_node(update_move_baton
   apr_array_header_t *src_children, *dst_children;
   int dst_op_depth = relpath_depth(move_root_dst_relpath);
 
+  SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool));
+  SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
+
   SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind,
                    src_relpath, src_op_depth,
                    wcroot, scratch_pool, scratch_pool));
@@ -1508,7 +1531,9 @@ update_moved_away_node(update_move_baton
 
       /* 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));
+      SVN_ERR(delete_move_leaf(b->wcroot, dst_relpath,
+                               relpath_depth(b->move_root_dst_relpath),
+                               scratch_pool));
     }
 
   if (src_kind != svn_node_none && src_kind != dst_kind)
@@ -1609,8 +1634,8 @@ update_moved_away_node(update_move_baton
                                                iterpool);
 
           if (!child_shadowed)
-            SVN_ERR(check_node_shadowed(&child_shadowed, b, dst_child_relpath,
-                                        iterpool));
+            SVN_ERR(check_node_shadowed(&child_shadowed, wcroot, dst_child_relpath,
+                                        b->move_root_dst_relpath, iterpool));
 
           SVN_ERR(update_moved_away_node(b, wcroot, src_child_relpath,
                                          dst_child_relpath, src_op_depth,
@@ -1641,6 +1666,9 @@ replace_moved_layer(const char *src_relp
   svn_boolean_t have_row;
   int dst_op_depth = relpath_depth(dst_relpath);
 
+  SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool));
+  SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
+
   /* Replace entire subtree at one op-depth. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_LOCAL_RELPATH_OP_DEPTH));
@@ -1719,10 +1747,8 @@ drive_tree_conflict_editor(update_move_b
       operation != svn_wc_operation_switch)
     return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                             _("Cannot auto-resolve tree-conflict on '%s'"),
-                            svn_dirent_local_style(
-                              svn_dirent_join(wcroot->abspath,
-                                              src_relpath, scratch_pool),
-                              scratch_pool));
+                            path_for_error_message(wcroot, src_relpath,
+                                                   scratch_pool));
 
   /* 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
@@ -1780,22 +1806,17 @@ suitable_for_move(svn_wc__db_wcroot_t *w
                                  svn_sqlite__reset(stmt),
                                  _("Cannot apply update because move source "
                                    "%s' is a mixed-revision working copy"),
-                                 svn_dirent_local_style(svn_dirent_join(
-                                                          wcroot->abspath,
-                                                          local_relpath,
-                                                          scratch_pool),
-                                 scratch_pool));
+                                 path_for_error_message(wcroot, local_relpath,
+                                                        scratch_pool));
 
       if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL)))
         return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
                                  svn_sqlite__reset(stmt),
                                  _("Cannot apply update because move source "
                                    "'%s' is a switched subtree"),
-                                 svn_dirent_local_style(svn_dirent_join(
-                                                          wcroot->abspath,
-                                                          local_relpath,
-                                                          scratch_pool),
-                                 scratch_pool));
+                                 path_for_error_message(wcroot,
+                                                        local_relpath,
+                                                        scratch_pool));
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
@@ -1840,10 +1861,8 @@ update_moved_away_conflict_victim(svn_wc
   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(
-                               svn_dirent_join(wcroot->abspath, victim_relpath,
-                                               scratch_pool),
-                               scratch_pool));
+                             path_for_error_message(wcroot, victim_relpath,
+                                                    scratch_pool));
 
   move_root_dst_abspath
     = svn_dirent_join(wcroot->abspath, umb.move_root_dst_relpath,
@@ -1869,10 +1888,8 @@ update_moved_away_conflict_victim(svn_wc
   if (!have_row)
     return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                              _("'%s' is not deleted"),
-                             svn_dirent_local_style(
-                               svn_dirent_join(wcroot->abspath, victim_relpath,
-                                               scratch_pool),
-                               scratch_pool));
+                             path_for_error_message(wcroot, victim_relpath,
+                                                    scratch_pool));
 
   if (src_op_depth == 0)
     SVN_ERR(suitable_for_move(wcroot, victim_relpath, scratch_pool));
@@ -2045,8 +2062,8 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
 
-  SVN_ERR(verify_write_lock(wcroot, move_src_op_root_relpath, scratch_pool));
-  SVN_ERR(verify_write_lock(wcroot, move_dst_op_root_relpath, scratch_pool));
+  /* Verify precondition: We are allowed to set a tree conflict here. */
+  SVN_ERR(verify_write_lock(wcroot, move_src_root_relpath, scratch_pool));
 
   /* Read new (post-update) information from the new move source BASE node. */
   SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev,
@@ -2058,7 +2075,14 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
   SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid,
                                       wcroot->sdb, repos_id, scratch_pool));
 
-  /* Read old (pre-update) information from the move destination node. */
+  /* Read old (pre-update) information from the move destination node.
+
+     This potentially touches nodes that aren't locked by us, but that is not
+     a problem because we have a SQLite write lock here, and all sqlite
+     operations that affect move stability use a sqlite lock as well.
+     (And affecting the move itself requires a write lock on the node that
+      we do own the lock for: the move source)
+  */
   SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_kind, &old_rev,
                                     &old_repos_relpath, NULL, NULL, NULL,
                                     NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2066,6 +2090,21 @@ bump_mark_tree_conflict(svn_wc__db_wcroo
                                     relpath_depth(move_dst_op_root_relpath),
                                     scratch_pool, scratch_pool));
 
+  if (strcmp(move_src_root_relpath, move_src_op_root_relpath))
+    {
+      /* We have information for the op-root, but need it for the node that
+         we are putting the tree conflict on. Luckily we know that we have
+         a clean BASE */
+
+      const char *rpath = svn_relpath_skip_ancestor(move_src_op_root_relpath,
+                                                    move_src_root_relpath);
+
+      old_repos_relpath = svn_relpath_join(old_repos_relpath, rpath,
+                                           scratch_pool);
+      new_repos_relpath = svn_relpath_join(new_repos_relpath, rpath,
+                                           scratch_pool);
+    }
+
   old_version = svn_wc_conflict_version_create2(
                   repos_root_url, repos_uuid, old_repos_relpath, old_rev,
                   old_kind, scratch_pool);
@@ -2332,10 +2371,26 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc
         {
           if (strcmp(move_src_root_relpath, local_relpath))
             {
-              SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath,
-                                              move_src_op_root_relpath,
-                                              move_dst_op_root_relpath,
-                                              db, scratch_pool));
+              /* An ancestor of the path that was updated is moved away.
+
+                 If we have a lock on that ancestor, we can mark a tree
+                 conflict on it, if we don't we ignore this case. A future
+                 update of the ancestor will handle this. */
+              svn_boolean_t locked;
+
+              SVN_ERR(svn_wc__db_wclock_owns_lock_internal(
+                                &locked, wcroot,
+                                move_src_root_relpath,
+                                FALSE, scratch_pool));
+
+              if (locked)
+                {
+                  SVN_ERR(bump_mark_tree_conflict(wcroot,
+                                                  move_src_root_relpath,
+                                                  move_src_op_root_relpath,
+                                                  move_dst_op_root_relpath,
+                                                  db, scratch_pool));
+                }
               return SVN_NO_ERROR;
             }
         }
@@ -2524,16 +2579,29 @@ break_moved_away_children_internal(svn_w
       const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL);
       const char *dst_relpath = svn_sqlite__column_text(stmt, 1, NULL);
       int src_op_depth = svn_sqlite__column_int(stmt, 2);
+      svn_error_t *err;
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
-                         iterpool));
-      SVN_ERR(update_move_list_add(wcroot, src_relpath,
-                                   svn_wc_notify_move_broken,
-                                   svn_node_unknown,
-                                   svn_wc_notify_state_inapplicable,
-                                   svn_wc_notify_state_inapplicable));
+      err = break_move(wcroot, src_relpath, src_op_depth, dst_relpath,
+                       iterpool);
+
+      if (! err)
+        {
+          err = update_move_list_add(wcroot, src_relpath,
+                                     svn_wc_notify_move_broken,
+                                     svn_node_unknown,
+                                     svn_wc_notify_state_inapplicable,
+                                     svn_wc_notify_state_inapplicable);
+        }
+
+      if (err)
+        {
+          return svn_error_trace(
+                          svn_error_compose_create(err,
+                                                   svn_sqlite__reset(stmt)));
+        }
+
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
   svn_pool_destroy(iterpool);
@@ -2546,21 +2614,26 @@ break_moved_away_children_internal(svn_w
 svn_error_t *
 svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db,
                                     const char *local_abspath,
+                                    const char *src_op_root_abspath,
                                     svn_wc_notify_func2_t notify_func,
                                     void *notify_baton,
                                     apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
+  const char *src_relpath;
 
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
                                                 db, local_abspath,
                                                 scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
+  src_relpath = svn_dirent_skip_ancestor(wcroot->abspath, src_op_root_abspath);
+  SVN_ERR_ASSERT(src_relpath != NULL);
+
   SVN_WC__DB_WITH_TXN(
     svn_wc__db_resolve_break_moved_away_internal(wcroot, local_relpath,
-                                                 relpath_depth(local_relpath),
+                                                 relpath_depth(src_relpath),
                                                  scratch_pool),
     wcroot);
 
@@ -2586,6 +2659,7 @@ svn_wc__db_resolve_break_moved_away(svn_
 svn_error_t *
 svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db,
                                              const char *local_abspath,
+                                             const char *src_op_root_abspath,
                                              svn_wc_notify_func2_t notify_func,
                                              void *notify_baton,
                                              apr_pool_t *scratch_pool)

Modified: subversion/branches/move-tracking-2/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_authz_svn/mod_authz_svn.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_authz_svn/mod_authz_svn.c Tue Jan 20 17:52:18 2015
@@ -244,15 +244,26 @@ static const command_rec authz_svn_cmds[
  * per-module loglevel configuration.  It expands to FILE and LINE
  * in older server versions.  ALLOWED is boolean.
  * REPOS_PATH and DEST_REPOS_PATH are information
- * about the request.  DEST_REPOS_PATH may be NULL. */
+ * about the request.  DEST_REPOS_PATH may be NULL.
+ * Non-zero IS_SUBREQ_BYPASS means that this authorization check was
+ * implicitly requested using 'subrequest bypass' callback from
+ * mod_dav_svn.
+ */
 static void
 log_access_verdict(LOG_ARGS_SIGNATURE,
-                   const request_rec *r, int allowed,
+                   const request_rec *r, int allowed, int is_subreq_bypass,
                    const char *repos_path, const char *dest_repos_path)
 {
-  int level = allowed ? APLOG_INFO : APLOG_WARNING;
+  int level = allowed ? APLOG_INFO : APLOG_ERR;
   const char *verdict = allowed ? "granted" : "denied";
 
+  /* Use less important log level for implicit sub-request authorization
+     checks. */
+  if (is_subreq_bypass)
+    level = APLOG_INFO;
+  else if (r->main && r->method_number == M_GET)
+    level = APLOG_INFO;
+
   if (r->user)
     {
       if (dest_repos_path)
@@ -361,7 +372,7 @@ get_access_conf(request_rec *r, authz_sv
   svn_error_t *svn_err = SVN_NO_ERROR;
   dav_error *dav_err;
 
-  dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path);
+  dav_err = dav_svn_get_repos_path2(r, conf->base_path, &repos_path, scratch_pool);
   if (dav_err)
     {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc);
@@ -749,7 +760,7 @@ subreq_bypass2(request_rec *r,
   if (!conf->anonymous
       || (! (conf->access_file || conf->repo_relative_access_file)))
     {
-      log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+      log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
       return HTTP_FORBIDDEN;
     }
 
@@ -778,12 +789,12 @@ subreq_bypass2(request_rec *r,
         }
       if (!authz_access_granted)
         {
-          log_access_verdict(APLOG_MARK, r, 0, repos_path, NULL);
+          log_access_verdict(APLOG_MARK, r, 0, TRUE, repos_path, NULL);
           return HTTP_FORBIDDEN;
         }
     }
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, NULL);
+  log_access_verdict(APLOG_MARK, r, 1, TRUE, repos_path, NULL);
 
   return OK;
 }
@@ -858,7 +869,7 @@ access_checker(request_rec *r)
         return DECLINED;
 
       if (!authn_required)
-        log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+        log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
 
       return HTTP_FORBIDDEN;
     }
@@ -866,7 +877,7 @@ access_checker(request_rec *r)
   if (status != OK)
     return status;
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+  log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
 
   return OK;
 }
@@ -893,7 +904,7 @@ check_user_id(request_rec *r)
   if (status == OK)
     {
       apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1);
-      log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+      log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
       return OK;
     }
 
@@ -923,7 +934,7 @@ auth_checker(request_rec *r)
     {
       if (conf->authoritative)
         {
-          log_access_verdict(APLOG_MARK, r, 0, repos_path, dest_repos_path);
+          log_access_verdict(APLOG_MARK, r, 0, FALSE, repos_path, dest_repos_path);
           ap_note_auth_failure(r);
           return HTTP_FORBIDDEN;
         }
@@ -933,7 +944,7 @@ auth_checker(request_rec *r)
   if (status != OK)
     return status;
 
-  log_access_verdict(APLOG_MARK, r, 1, repos_path, dest_repos_path);
+  log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
 
   return OK;
 }

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/merge.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/merge.c Tue Jan 20 17:52:18 2015
@@ -136,12 +136,13 @@ do_resources(const dav_svn_repos *repos,
       const void *key;
       void *val;
       const char *path;
+      apr_ssize_t path_len;
       svn_fs_path_change2_t *change;
       svn_boolean_t send_self;
       svn_boolean_t send_parent;
 
       svn_pool_clear(subpool);
-      apr_hash_this(hi, &key, NULL, &val);
+      apr_hash_this(hi, &key, &path_len, &val);
       path = key;
       change = val;
 
@@ -170,14 +171,14 @@ do_resources(const dav_svn_repos *repos,
         {
           /* If we haven't already sent this path, send it (and then
              remember that we sent it). */
-          if (! svn_hash_gets(sent, path))
+          if (! apr_hash_get(sent, path, path_len))
             {
               svn_node_kind_t kind;
               SVN_ERR(svn_fs_check_path(&kind, root, path, subpool));
               SVN_ERR(send_response(repos, root, path,
                                     kind == svn_node_dir,
                                     output, bb, subpool));
-              svn_hash_sets(sent, path, (void *)1);
+              apr_hash_set(sent, path, path_len, (void *)1);
             }
         }
       if (send_parent)

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/mod_dav_svn.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/mod_dav_svn.c Tue Jan 20 17:52:18 2015
@@ -662,9 +662,10 @@ dav_svn__get_fs_parent_path(request_rec
 
 
 AP_MODULE_DECLARE(dav_error *)
-dav_svn_get_repos_path(request_rec *r,
-                       const char *root_path,
-                       const char **repos_path)
+dav_svn_get_repos_path2(request_rec *r,
+                        const char *root_path,
+                        const char **repos_path,
+                        apr_pool_t *pool)
 {
 
   const char *fs_path;
@@ -692,19 +693,26 @@ dav_svn_get_repos_path(request_rec *r,
 
   /* Split the svn URI to get the name of the repository below
      the parent path. */
-  derr = dav_svn_split_uri(r, r->uri, root_path,
-                           &ignored_cleaned_uri, &ignored_had_slash,
-                           &repos_name,
-                           &ignored_relative, &ignored_path_in_repos);
+  derr = dav_svn_split_uri2(r, r->uri, root_path,
+                            &ignored_cleaned_uri, &ignored_had_slash,
+                            &repos_name,
+                            &ignored_relative, &ignored_path_in_repos, pool);
   if (derr)
     return derr;
 
   /* Construct the full path from the parent path base directory
      and the repository name. */
-  *repos_path = svn_dirent_join(fs_parent_path, repos_name, r->pool);
+  *repos_path = svn_dirent_join(fs_parent_path, repos_name, pool);
   return NULL;
 }
 
+AP_MODULE_DECLARE(dav_error *)
+dav_svn_get_repos_path(request_rec *r,
+                       const char *root_path,
+                       const char **repos_path)
+{
+  return dav_svn_get_repos_path2(r, root_path, repos_path, r->pool);
+}
 
 const char *
 dav_svn__get_repo_name(request_rec *r)
@@ -1324,8 +1332,8 @@ static const command_rec cmds[] =
   AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL,
                 RSRC_CONF,
                 "specifies the maximum size in kB per process of Subversion's "
-                "in-memory object cache (default value is 16384; 0 deactivates "
-                "the cache)."),
+                "in-memory object cache (default value is 16384; 0 switches "
+                "to dynamically sized caches)."),
   /* per server */
   AP_INIT_TAKE1("SVNCompressionLevel", SVNCompressionLevel_cmd, NULL,
                 RSRC_CONF,

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/deleted-rev.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/deleted-rev.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/deleted-rev.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/deleted-rev.c Tue Jan 20 17:52:18 2015
@@ -56,6 +56,9 @@ dav_svn__get_deleted_rev_report(const da
   dav_error *derr = NULL;
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0,

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/file-revs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/file-revs.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/file-revs.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/file-revs.c Tue Jan 20 17:52:18 2015
@@ -149,7 +149,7 @@ file_rev_handler(void *baton,
                  apr_pool_t *pool)
 {
   struct file_rev_baton *frb = baton;
-  apr_pool_t *subpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(pool);
   apr_hash_index_t *hi;
   int i;
 
@@ -169,11 +169,11 @@ file_rev_handler(void *baton,
       const char *pname;
       const svn_string_t *pval;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
       apr_hash_this(hi, &key, NULL, &val);
       pname = key;
       pval = val;
-      SVN_ERR(send_prop(frb, "rev-prop", pname, pval, subpool));
+      SVN_ERR(send_prop(frb, "rev-prop", pname, pval, iterpool));
     }
 
   /* Send file prop changes. */
@@ -181,17 +181,17 @@ file_rev_handler(void *baton,
     {
       const svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
       if (prop->value)
         SVN_ERR(send_prop(frb, "set-prop", prop->name, prop->value,
-                          subpool));
+                          iterpool));
       else
         {
           /* Property was removed. */
           SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output,
                                           "<S:remove-prop name=\"%s\"/>"
                                           DEBUG_CR,
-                                          apr_xml_quote_string(subpool,
+                                          apr_xml_quote_string(iterpool,
                                                                prop->name,
                                                                1)));
         }
@@ -223,7 +223,7 @@ file_rev_handler(void *baton,
     SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output,
                                   "</S:file-rev>" DEBUG_CR));
 
-  svn_pool_destroy(subpool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -254,6 +254,9 @@ dav_svn__file_revs_report(const dav_reso
   arb.repos = resource->info->repos;
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   /* ### This is done on other places, but the document element is
      in this namespace, so is this necessary at all? */

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-location-segments.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-location-segments.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-location-segments.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-location-segments.c Tue Jan 20 17:52:18 2015
@@ -123,6 +123,9 @@ dav_svn__get_location_segments_report(co
   struct location_segment_baton location_segment_baton;
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     {

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locations.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locations.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locations.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locations.c Tue Jan 20 17:52:18 2015
@@ -106,6 +106,9 @@ dav_svn__get_locations_report(const dav_
                                       sizeof(svn_revnum_t));
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     {

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locks.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locks.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/get-locks.c Tue Jan 20 17:52:18 2015
@@ -66,7 +66,7 @@ send_get_lock_response(apr_hash_t *locks
                        apr_bucket_brigade *bb,
                        apr_pool_t *pool)
 {
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
   apr_hash_index_t *hi;
 
   /* start sending report */
@@ -76,15 +76,13 @@ send_get_lock_response(apr_hash_t *locks
                          "\" xmlns:D=\"DAV:\">" DEBUG_CR));
 
   /* stream the locks */
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(pool);
   for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi))
     {
-      void *val;
       const svn_lock_t *lock;
 
-      svn_pool_clear(subpool);
-      apr_hash_this(hi, NULL, NULL, &val);
-      lock = val;
+      svn_pool_clear(iterpool);
+      lock = apr_hash_this_val(hi);
 
       /* Begin the <S:lock> tag, transmitting the path, token, and
          creation date. */
@@ -93,10 +91,10 @@ send_get_lock_response(apr_hash_t *locks
                              "<S:path>%s</S:path>" DEBUG_CR
                              "<S:token>%s</S:token>" DEBUG_CR
                              "<S:creationdate>%s</S:creationdate>" DEBUG_CR,
-                             apr_xml_quote_string(subpool, lock->path, 1),
-                             apr_xml_quote_string(subpool, lock->token, 1),
+                             apr_xml_quote_string(iterpool, lock->path, 1),
+                             apr_xml_quote_string(iterpool, lock->token, 1),
                              svn_time_to_cstring(lock->creation_date,
-                                                 subpool)));
+                                                 iterpool)));
 
       /* Got expiration date?  Tell the client. */
       if (lock->expiration_date)
@@ -104,7 +102,7 @@ send_get_lock_response(apr_hash_t *locks
                                "<S:expirationdate>%s</S:expirationdate>"
                                DEBUG_CR,
                                svn_time_to_cstring(lock->expiration_date,
-                                                   subpool)));
+                                                   iterpool)));
 
       /* Transmit the lock ownership information. */
       if (lock->owner)
@@ -114,7 +112,7 @@ send_get_lock_response(apr_hash_t *locks
 
           if (svn_xml_is_xml_safe(lock->owner, strlen(lock->owner)))
             {
-              owner = apr_xml_quote_string(subpool, lock->owner, 1);
+              owner = apr_xml_quote_string(iterpool, lock->owner, 1);
             }
           else
             {
@@ -124,7 +122,7 @@ send_get_lock_response(apr_hash_t *locks
               owner_string.data = lock->owner;
               owner_string.len = strlen(lock->owner);
               encoded_owner = svn_base64_encode_string2(&owner_string, TRUE,
-                                                        subpool);
+                                                        iterpool);
               owner = encoded_owner->data;
               owner_base64 = TRUE;
             }
@@ -142,7 +140,7 @@ send_get_lock_response(apr_hash_t *locks
 
           if (svn_xml_is_xml_safe(lock->comment, strlen(lock->comment)))
             {
-              comment = apr_xml_quote_string(subpool, lock->comment, 1);
+              comment = apr_xml_quote_string(iterpool, lock->comment, 1);
             }
           else
             {
@@ -152,7 +150,7 @@ send_get_lock_response(apr_hash_t *locks
               comment_string.data = lock->comment;
               comment_string.len = strlen(lock->comment);
               encoded_comment = svn_base64_encode_string2(&comment_string,
-                                                          TRUE, subpool);
+                                                          TRUE, iterpool);
               comment = encoded_comment->data;
               comment_base64 = TRUE;
             }
@@ -165,7 +163,7 @@ send_get_lock_response(apr_hash_t *locks
       /* Okay, finish up this lock by closing the <S:lock> tag. */
       SVN_APR_ERR(ap_fprintf(output, bb, "</S:lock>" DEBUG_CR));
     }
-  svn_pool_destroy(subpool);
+  svn_pool_destroy(iterpool);
 
   /* Finish the report */
   SVN_APR_ERR(ap_fprintf(output, bb, "</S:get-locks-report>" DEBUG_CR));

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/inherited-props.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/inherited-props.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/inherited-props.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/inherited-props.c Tue Jan 20 17:52:18 2015
@@ -63,6 +63,9 @@ dav_svn__get_inherited_props_report(cons
   apr_pool_t *iterpool;
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     {

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/log.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/log.c Tue Jan 20 17:52:18 2015
@@ -315,6 +315,9 @@ dav_svn__log_report(const dav_resource *
     = apr_array_make(resource->pool, 1, sizeof(const char *));
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     {

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/reports/mergeinfo.c Tue Jan 20 17:52:18 2015
@@ -67,6 +67,9 @@ dav_svn__get_mergeinfo_report(const dav_
     = apr_array_make(resource->pool, 0, sizeof(const char *));
 
   /* Sanity check. */
+  if (!resource->info->repos_path)
+    return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                              "The request does not specify a repository path");
   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
   if (ns == -1)
     {

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/repos.c Tue Jan 20 17:52:18 2015
@@ -509,6 +509,9 @@ parse_vtxnstub_uri(dav_resource_combined
   if (parse_txnstub_uri(comb, path, label, use_checked_in))
     return TRUE;
 
+  if (!comb->priv.root.txn_name)
+    return TRUE;
+
   comb->priv.root.vtxn_name = comb->priv.root.txn_name;
   comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos,
                                               comb->priv.root.vtxn_name);
@@ -577,6 +580,9 @@ parse_vtxnroot_uri(dav_resource_combined
   if (parse_txnroot_uri(comb, path, label, use_checked_in))
     return TRUE;
 
+  if (!comb->priv.root.txn_name)
+    return TRUE;
+
   comb->priv.root.vtxn_name = comb->priv.root.txn_name;
   comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos,
                                               comb->priv.root.vtxn_name);
@@ -922,6 +928,10 @@ prep_working(dav_resource_combined *comb
      point. */
   if (txn_name == NULL)
     {
+      if (!comb->priv.root.activity_id)
+        return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0,
+                                  "The request did not specify an activity ID");
+
       txn_name = dav_svn__get_txn(comb->priv.repos,
                                   comb->priv.root.activity_id);
       if (txn_name == NULL)
@@ -1032,8 +1042,13 @@ prep_working(dav_resource_combined *comb
 static dav_error *
 prep_activity(dav_resource_combined *comb)
 {
-  const char *txn_name = dav_svn__get_txn(comb->priv.repos,
-                                          comb->priv.root.activity_id);
+  const char *txn_name;
+
+  if (!comb->priv.root.activity_id)
+    return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0,
+                              "The request did not specify an activity ID");
+
+  txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id);
 
   comb->priv.root.txn_name = txn_name;
   comb->res.exists = txn_name != NULL;
@@ -1194,14 +1209,15 @@ static void log_warning(void *baton, svn
 
 
 AP_MODULE_DECLARE(dav_error *)
-dav_svn_split_uri(request_rec *r,
-                  const char *uri_to_split,
-                  const char *root_path,
-                  const char **cleaned_uri,
-                  int *trailing_slash,
-                  const char **repos_basename,
-                  const char **relative_path,
-                  const char **repos_path)
+dav_svn_split_uri2(request_rec *r,
+                   const char *uri_to_split,
+                   const char *root_path,
+                   const char **cleaned_uri,
+                   int *trailing_slash,
+                   const char **repos_basename,
+                   const char **relative_path,
+                   const char **repos_path,
+                   apr_pool_t *pool)
 {
   apr_size_t len1;
   int had_slash;
@@ -1217,7 +1233,7 @@ dav_svn_split_uri(request_rec *r,
   if ((fs_path == NULL) && (fs_parent_path == NULL))
     {
       /* ### are SVN_ERR_APMOD codes within the right numeric space? */
-      return dav_svn__new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
+      return dav_svn__new_error(pool, HTTP_INTERNAL_SERVER_ERROR,
                                 SVN_ERR_APMOD_MISSING_PATH_TO_FS,
                                 "The server is misconfigured: "
                                 "either an SVNPath or SVNParentPath "
@@ -1226,7 +1242,7 @@ dav_svn_split_uri(request_rec *r,
     }
 
   /* make a copy so that we can do some work on it */
-  uri = apr_pstrdup(r->pool, uri_to_split);
+  uri = apr_pstrdup(pool, uri_to_split);
 
   /* remove duplicate slashes, and make sure URI has no trailing '/' */
   ap_no2slash(uri);
@@ -1241,7 +1257,7 @@ dav_svn_split_uri(request_rec *r,
     *trailing_slash = FALSE;
 
   /* return the first item.  */
-  *cleaned_uri = apr_pstrdup(r->pool, uri);
+  *cleaned_uri = apr_pstrdup(pool, uri);
 
   /* The URL space defined by the SVN provider is always a virtual
      space. Construct the path relative to the configured Location
@@ -1282,7 +1298,7 @@ dav_svn_split_uri(request_rec *r,
   if (fs_path != NULL)
     {
       /* the repos_basename is the last component of root_path. */
-      *repos_basename = svn_dirent_basename(root_path, r->pool);
+      *repos_basename = svn_dirent_basename(root_path, pool);
 
       /* 'relative' is already correct for SVNPath; the root_path
          already contains the name of the repository, so relative is
@@ -1300,7 +1316,7 @@ dav_svn_split_uri(request_rec *r,
       if (relative[1] == '\0')
         {
           /* ### are SVN_ERR_APMOD codes within the right numeric space? */
-          return dav_svn__new_error(r->pool, HTTP_FORBIDDEN,
+          return dav_svn__new_error(pool, HTTP_FORBIDDEN,
                                     SVN_ERR_APMOD_MALFORMED_URI,
                                     "The URI does not contain the name "
                                     "of a repository.");
@@ -1317,7 +1333,7 @@ dav_svn_split_uri(request_rec *r,
         }
       else
         {
-          magic_component = apr_pstrndup(r->pool, relative + 1,
+          magic_component = apr_pstrndup(pool, relative + 1,
                                          magic_end - relative - 1);
           relative = magic_end;
         }
@@ -1327,7 +1343,7 @@ dav_svn_split_uri(request_rec *r,
     }
 
   /* We can return 'relative' at this point too. */
-  *relative_path = apr_pstrdup(r->pool, relative);
+  *relative_path = apr_pstrdup(pool, relative);
 
   /* Code to remove the !svn junk from the front of the relative path,
      mainly stolen from parse_uri().  This code assumes that
@@ -1348,7 +1364,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_NOT_FOUND,
+            return dav_svn__new_error(pool, HTTP_NOT_FOUND,
                                       SVN_ERR_APMOD_MALFORMED_URI,
                                       "Nothing follows the svn special_uri.");
           }
@@ -1375,7 +1391,7 @@ dav_svn_split_uri(request_rec *r,
                           *repos_path = NULL;
                         else
                           return dav_svn__new_error(
-                                     r->pool, HTTP_NOT_FOUND,
+                                     pool, HTTP_NOT_FOUND,
                                      SVN_ERR_APMOD_MALFORMED_URI,
                                      "Missing info after special_uri.");
                       }
@@ -1399,7 +1415,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_NOT_FOUND,
+                                         pool, HTTP_NOT_FOUND,
                                          SVN_ERR_APMOD_MALFORMED_URI,
                                          "Not enough components after "
                                          "special_uri.");
@@ -1413,13 +1429,13 @@ dav_svn_split_uri(request_rec *r,
                         else
                           {
                             /* Found a slash after the special components. */
-                            *repos_path = apr_pstrdup(r->pool, start - 1);
+                            *repos_path = apr_pstrdup(pool, start - 1);
                           }
                       }
                     else
                       {
                         return
-                          dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
+                          dav_svn__new_error(pool, HTTP_NOT_FOUND,
                                         SVN_ERR_APMOD_MALFORMED_URI,
                                         "Unknown data after special_uri.");
                       }
@@ -1430,7 +1446,7 @@ dav_svn_split_uri(request_rec *r,
 
             if (defn->name == NULL)
               return
-                dav_svn__new_error(r->pool, HTTP_NOT_FOUND,
+                dav_svn__new_error(pool, HTTP_NOT_FOUND,
                                    SVN_ERR_APMOD_MALFORMED_URI,
                                    "Couldn't match subdir after special_uri.");
           }
@@ -1439,13 +1455,27 @@ 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 - 1);
+        *repos_path = apr_pstrdup(pool, relative - 1);
       }
   }
 
   return NULL;
 }
 
+AP_MODULE_DECLARE(dav_error *)
+dav_svn_split_uri(request_rec *r,
+                  const char *uri_to_split,
+                  const char *root_path,
+                  const char **cleaned_uri,
+                  int *trailing_slash,
+                  const char **repos_basename,
+                  const char **relative_path,
+                  const char **repos_path)
+{
+  return dav_svn_split_uri2(r, uri_to_split, root_path, cleaned_uri,
+                            trailing_slash, repos_basename, relative_path,
+                            repos_path, r->pool);
+}
 
 /* Context for cleanup handler. */
 struct cleanup_fs_access_baton
@@ -4169,9 +4199,16 @@ typedef struct walker_ctx_t {
 
 } walker_ctx_t;
 
-
+/* Recursively walk a resource for walk().  When DEPTH != 0, recurse with
+   DEPTH-1 on child nodes. WALK_ROOT should be TRUE for the root and will be
+   FALSE for any descendants, to avoid unneeded work for every descendant
+   node.
+   */
 static dav_error *
-do_walk(walker_ctx_t *ctx, int depth)
+do_walk(walker_ctx_t *ctx,
+        int depth,
+        svn_boolean_t walk_root,
+        apr_pool_t *scratch_pool)
 {
   const dav_walk_params *params = ctx->params;
   int isdir = ctx->res.collection;
@@ -4235,28 +4272,31 @@ do_walk(walker_ctx_t *ctx, int depth)
   uri_len = ctx->uri->len;
   repos_len = ctx->repos_path->len;
 
-  /* Tell our logging subsystem that we're listing a directory.
+  if (walk_root)
+    {
+      /* Tell our logging subsystem that we're listing a directory.
 
-     Note: if we cared, we could look at the 'User-Agent:' request
-     header and distinguish an svn client ('svn ls') from a generic
-     DAV client.  */
-  dav_svn__operational_log(&ctx->info,
-                           svn_log__get_dir(ctx->info.repos_path,
-                                            ctx->info.root.rev,
-                                            TRUE, FALSE, SVN_DIRENT_ALL,
-                                            params->pool));
+      Note: if we cared, we could look at the 'User-Agent:' request
+         header and distinguish an svn client ('svn ls') from a generic
+         DAV client.  */
+      dav_svn__operational_log(&ctx->info,
+                               svn_log__get_dir(ctx->info.repos_path,
+                                                ctx->info.root.rev,
+                                                TRUE, FALSE, SVN_DIRENT_ALL,
+                                                scratch_pool));
+    }
 
   /* fetch this collection's children */
   serr = svn_fs_dir_entries(&children, ctx->info.root.root,
-                            ctx->info.repos_path, params->pool);
+                            ctx->info.repos_path, scratch_pool);
   if (serr != NULL)
     return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "could not fetch collection members",
                                 params->pool);
 
   /* iterate over the children in this collection */
-  iterpool = svn_pool_create(params->pool);
-  for (hi = apr_hash_first(params->pool, children); hi; hi = apr_hash_next(hi))
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, children); hi; hi = apr_hash_next(hi))
     {
       const void *key;
       apr_ssize_t klen;
@@ -4297,7 +4337,10 @@ do_walk(walker_ctx_t *ctx, int depth)
         {
           err = (*params->func)(&ctx->wres, DAV_CALLTYPE_MEMBER);
           if (err != NULL)
-            return err;
+            {
+              svn_pool_destroy(iterpool);
+              return err;
+            }
         }
       else
         {
@@ -4309,9 +4352,12 @@ do_walk(walker_ctx_t *ctx, int depth)
           ctx->res.uri = ctx->uri->data;
 
           /* recurse on this collection */
-          err = do_walk(ctx, depth - 1);
+          err = do_walk(ctx, depth - 1, FALSE, iterpool);
           if (err != NULL)
-            return err;
+            {
+              svn_pool_destroy(iterpool);
+              return err;
+            }
 
           /* restore the data */
           ctx->res.collection = FALSE;
@@ -4391,7 +4437,7 @@ walk(const dav_walk_params *params, int
   /* ### is the root already/always open? need to verify */
 
   /* always return the error, and any/all multistatus responses */
-  err = do_walk(&ctx, depth);
+  err = do_walk(&ctx, depth, TRUE, params->pool);
   *response = ctx.wres.response;
 
   return err;

Modified: subversion/branches/move-tracking-2/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/mod_dav_svn/version.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/move-tracking-2/subversion/mod_dav_svn/version.c Tue Jan 20 17:52:18 2015
@@ -1381,20 +1381,10 @@ release_locks(apr_hash_t *locks,
               request_rec *r,
               apr_pool_t *pool)
 {
-  apr_hash_index_t *hi;
   apr_pool_t *subpool = svn_pool_create(pool);
-  apr_hash_t *targets = apr_hash_make(subpool);
   svn_error_t *err;
 
-  for (hi = apr_hash_first(subpool, locks); hi; hi = apr_hash_next(hi))
-    {
-      const char *path = apr_hash_this_key(hi);
-      const char *token = apr_hash_this_val(hi);
-
-      svn_hash_sets(targets, path, token);
-    }
-
-  err = svn_repos_fs_unlock_many(repos, targets, FALSE, unlock_many_cb, r,
+  err = svn_repos_fs_unlock_many(repos, locks, FALSE, unlock_many_cb, r,
                                  subpool, subpool);
 
   if (err) /* If we got an error, just log it and move along. */