You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/24 16:02:52 UTC

svn commit: r1000876 [3/4] - in /subversion/branches/object-model: ./ build/ notes/ notes/http-and-webdav/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs/ subversion/libsvn_ra/ sub...

Modified: subversion/branches/object-model/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/wc_db.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/wc_db.c Fri Sep 24 14:02:50 2010
@@ -111,7 +111,7 @@
 #define LIKE_ESCAPE_CHAR     "#"
 
 /* Calculates the depth of the relpath below "" */
-APR_INLINE static int relpath_op_depth(const char *relpath)
+APR_INLINE static int relpath_depth(const char *relpath)
 {
   int n = 1;
   if (*relpath == '\0')
@@ -636,8 +636,6 @@ scan_upwards_for_repos(apr_int64_t *repo
                 svn_dirent_local_style(local_abspath, scratch_pool));
             }
 
-#ifdef SVN_WC__NODES
-#endif
           return svn_error_compose_create(err, svn_sqlite__reset(stmt));
         }
 
@@ -659,9 +657,9 @@ scan_upwards_for_repos(apr_int64_t *repo
                                               result_pool);
           return svn_sqlite__reset(stmt);
         }
-#ifndef SVN_WC__NODES_ONLY
+
       SVN_ERR(svn_sqlite__reset(stmt));
-#endif
+
       if (*current_relpath == '\0')
         {
           /* We scanned all the way up, and did not find the information.
@@ -934,7 +932,9 @@ blank_iwb(insert_working_baton_t *piwb)
      value, but... meh. We'll avoid them if ORIGINAL_REPOS_RELPATH==NULL.  */
 }
 
-/* */
+
+/* Copy the row specified by BATON->(wc_id,local_relpath) from BASE to
+ * WORKING, changing its 'presence' and 'op_depth' to the values in BATON. */
 static svn_error_t *
 copy_working_from_base(void *baton,
                        svn_sqlite__db_t *sdb,
@@ -970,12 +970,15 @@ copy_working_from_base(void *baton,
 }
 
 
-
+/* Insert WORKING rows for each (const char *) child name in CHILDREN,
+   whose parent directory is LOCAL_RELPATH.  For each child, set
+   presence='incomplete', kind='unknown', op_depth=OP_DEPTH. */
 static svn_error_t *
 insert_incomplete_working_children(svn_sqlite__db_t *sdb,
                                    apr_int64_t wc_id,
                                    const char *local_relpath,
                                    const apr_array_header_t *children,
+                                   apr_int64_t op_depth,
                                    apr_pool_t *scratch_pool)
 {
 #ifndef SVN_WC__NODES_ONLY
@@ -1013,8 +1016,7 @@ insert_incomplete_working_children(svn_s
                                 wc_id,
                                 svn_relpath_join(local_relpath, name,
                                                  scratch_pool),
-                                (apr_int64_t) 2, /* ### op_depth
-                                                    non-THIS_DIR working */
+                                op_depth,
                                 local_relpath,
                                 "incomplete", /* 8, presence */
                                 "unknown"));  /* 10, kind */
@@ -1039,7 +1041,6 @@ insert_working_node(void *baton,
 #endif
 #ifdef SVN_WC__NODES
   svn_sqlite__stmt_t *stmt_node;
-  apr_int64_t op_depth;
 #endif
 
   /* We cannot insert a WORKING_NODE row at the wcroot.  */
@@ -1109,14 +1110,12 @@ insert_working_node(void *baton,
 #endif
 
 #ifdef SVN_WC__NODES
-  op_depth = (parent_relpath == NULL) ? 1   /* THIS_DIR */
-                                      : 2;  /* immediate children */
   SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb, STMT_INSERT_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt_node, "isisnnntstrisn"
                 "nnnn" /* properties translated_size last_mod_time dav_cache */
                 "s",
                 piwb->wc_id, piwb->local_relpath,
-                op_depth,
+                piwb->op_depth,
                 parent_relpath,
                 presence_map, piwb->presence,
                 (piwb->kind == svn_wc__db_kind_dir)
@@ -1157,10 +1156,15 @@ insert_working_node(void *baton,
 #endif
 
 
+  /* Insert incomplete children, if specified.
+     The children are part of the same op and so have the same op_depth.
+     (The only time we'd want a different depth is during a recursive
+     simple add, but we never insert children here during a simple add.) */
   if (piwb->kind == svn_wc__db_kind_dir && piwb->children)
     SVN_ERR(insert_incomplete_working_children(sdb, piwb->wc_id,
                                                piwb->local_relpath,
                                                piwb->children,
+                                               piwb->op_depth,
                                                scratch_pool));
 
   SVN_ERR(add_work_items(sdb, piwb->work_items, scratch_pool));
@@ -1231,6 +1235,9 @@ union_children(const apr_array_header_t 
 {
   /* ### it would be nice to pre-size this hash table.  */
   apr_hash_t *names = apr_hash_make(scratch_pool);
+#ifdef SVN_WC__NODES
+  apr_hash_t *names_nodes = apr_hash_make(scratch_pool);
+#endif
   apr_array_header_t *names_array;
 
   /* All of the names get allocated in RESULT_POOL.  */
@@ -1238,6 +1245,17 @@ union_children(const apr_array_header_t 
                                sdb, wc_id, parent_relpath, result_pool));
   SVN_ERR(add_children_to_hash(names, STMT_SELECT_WORKING_NODE_CHILDREN,
                                sdb, wc_id, parent_relpath, result_pool));
+#ifdef SVN_WC__NODES
+  SVN_ERR(add_children_to_hash(names_nodes, STMT_SELECT_BASE_NODE_CHILDREN_1,
+                               sdb, wc_id, parent_relpath, result_pool));
+  SVN_ERR(add_children_to_hash(names_nodes, STMT_SELECT_WORKING_NODE_CHILDREN_1,
+                               sdb, wc_id, parent_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR_ASSERT(apr_hash_count(names) == apr_hash_count(names_nodes));
+#else
+  names = names_nodes;
+#endif
+#endif
 
   SVN_ERR(svn_hash_keys(&names_array, names, result_pool));
   *children = names_array;
@@ -1306,6 +1324,10 @@ gather_children(const apr_array_header_t
   const char *local_relpath;
   int base_count;
   int working_count;
+#ifdef SVN_WC__NODES
+  int base_count_nodes, working_count_nodes;
+  const apr_array_header_t *children_nodes;
+#endif
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -1321,17 +1343,47 @@ gather_children(const apr_array_header_t
          directory in its repository.
 
          ### note "files". should redo count with subdirs included */
-      return svn_error_return(single_table_children(
-                                children, STMT_SELECT_BASE_NODE_CHILDREN,
-                                10 /* start_size */,
-                                pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                local_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
+                                    10 /* start_size */,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(single_table_children(&children_nodes,
+                                    STMT_SELECT_BASE_NODE_CHILDREN_1,
+                                    10 /* start_size */,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
+#else
+      *children = children_nodes;
+#endif
+#endif
+      return SVN_NO_ERROR;
     }
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(count_children(&base_count, STMT_COUNT_BASE_NODE_CHILDREN,
                          pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(count_children(&working_count, STMT_COUNT_WORKING_NODE_CHILDREN,
                          pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(count_children(&base_count_nodes, STMT_COUNT_BASE_NODE_CHILDREN_1,
+                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(count_children(&working_count_nodes,
+                         STMT_COUNT_WORKING_NODE_CHILDREN_1,
+                         pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR_ASSERT(base_count == base_count_nodes);
+  SVN_ERR_ASSERT(working_count == working_count_nodes);
+#else
+  base_count = base_count_nodes;
+  working_count = working_count_nodes;
+#endif
+#endif
 
   if (base_count == 0)
     {
@@ -1341,18 +1393,48 @@ gather_children(const apr_array_header_t
           return SVN_NO_ERROR;
         }
 
-      return svn_error_return(single_table_children(
-                                children, STMT_SELECT_WORKING_NODE_CHILDREN,
-                                working_count,
-                                pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                                local_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR(single_table_children(children, STMT_SELECT_WORKING_NODE_CHILDREN,
+                                    working_count,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(single_table_children(&children_nodes,
+                                    STMT_SELECT_WORKING_NODE_CHILDREN_1,
+                                    working_count,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
+#else
+      *children = children_nodes;
+#endif
+#endif
+      return SVN_NO_ERROR;
     }
   if (working_count == 0)
-    return svn_error_return(single_table_children(
-                              children, STMT_SELECT_BASE_NODE_CHILDREN,
-                              base_count,
-                              pdh->wcroot->sdb, pdh->wcroot->wc_id,
-                              local_relpath, result_pool));
+    {
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
+                                    base_count,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(single_table_children(&children_nodes,
+                                    STMT_SELECT_BASE_NODE_CHILDREN_1,
+                                    base_count,
+                                    pdh->wcroot->sdb, pdh->wcroot->wc_id,
+                                    local_relpath, result_pool));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
+#else
+      *children = children_nodes;
+#endif
+#endif
+      return SVN_NO_ERROR;
+    }
 
   /* ### it would be nice to pass BASE_COUNT and WORKING_COUNT, but there is
      ### nothing union_children() can do with those.  */
@@ -1523,15 +1605,32 @@ prop_upgrade_trees(svn_boolean_t *base_e
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
   *base_exists = FALSE;
   *working_exists = FALSE;
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PLAN_PROP_UPGRADE));
   SVN_ERR(svn_sqlite__bindf(stmt, "s", local_relpath));
-
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, sdb,
+                                    STMT_PLAN_PROP_UPGRADE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "s", local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR_ASSERT(have_row == have_nodes_row);
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
   /* During a property upgrade, there better be a row corresponding to
      the provided LOCAL_RELPATH. We shouldn't even be here without a
      query for available rows.  */
@@ -2383,95 +2482,6 @@ svn_wc__db_base_get_info(svn_wc__db_stat
   return svn_error_compose_create(err, svn_sqlite__reset(stmt));
 }
 
-svn_error_t *
-svn_wc__db_base_get_info_from_parent(svn_wc__db_status_t *status,
-                                     svn_wc__db_kind_t *kind,
-                                     svn_revnum_t *revision,
-                                     const char **repos_relpath,
-                                     const char **repos_root_url,
-                                     const char **repos_uuid,
-                                     svn_wc__db_t *db,
-                                     const char *local_abspath,
-                                     apr_pool_t *result_pool,
-                                     apr_pool_t *scratch_pool)
-{
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-  svn_error_t *err = SVN_NO_ERROR;
-  const char *parent_abspath;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
-  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
-                              parent_abspath, svn_sqlite__mode_readonly,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(pdh);
-
-  local_relpath = svn_relpath_join(local_relpath,
-                                   svn_dirent_basename(local_abspath, NULL),
-                                   scratch_pool);
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_SELECT_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-  if (have_row)
-    {
-      svn_wc__db_kind_t node_kind = svn_sqlite__column_token(stmt, 3,
-                                                             kind_map);
-
-      if (kind)
-        {
-          *kind = node_kind;
-        }
-      if (status)
-        {
-          *status = svn_sqlite__column_token(stmt, 2, presence_map);
-        }
-      if (revision)
-        {
-          *revision = svn_sqlite__column_revnum(stmt, 4);
-        }
-      if (repos_relpath)
-        {
-          *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
-        }
-      if (repos_root_url || repos_uuid)
-        {
-          /* Fetch repository information via REPOS_ID. */
-          if (svn_sqlite__column_is_null(stmt, 0))
-            {
-              if (repos_root_url)
-                *repos_root_url = NULL;
-              if (repos_uuid)
-                *repos_uuid = NULL;
-            }
-          else
-            {
-              err = fetch_repos_info(repos_root_url, repos_uuid,
-                                     pdh->wcroot->sdb,
-                                     svn_sqlite__column_int64(stmt, 0),
-                                     result_pool);
-            }
-        }
-    }
-  else
-    {
-      err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                              _("The node '%s' was not found."),
-                              svn_dirent_local_style(local_abspath,
-                                                     scratch_pool));
-    }
-
-  /* Note: given the composition, no need to wrap for tracing.  */
-  return svn_error_compose_create(err, svn_sqlite__reset(stmt));
-}
-
 
 svn_error_t *
 svn_wc__db_base_get_prop(const svn_string_t **propval,
@@ -3017,17 +3027,39 @@ svn_wc__db_pristine_remove(svn_wc__db_t 
   {
     const svn_checksum_t *md5_checksum;
     svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+    svn_sqlite__stmt_t *stmt_nodes;
+    svn_boolean_t is_referenced_nodes;
+#endif
 
     /* ### Transitional: look for references to its MD-5 as well. */
     SVN_ERR(svn_wc__db_pristine_get_md5(&md5_checksum, db, wri_abspath,
                                         sha1_checksum, scratch_pool,
                                         scratch_pool));
 
+#ifndef SVN_WC__NODES_ONLY
     SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                       STMT_SELECT_ANY_PRISTINE_REFERENCE));
     SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
     SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
     SVN_ERR(svn_sqlite__step(&is_referenced, stmt));
+#endif
+#ifdef SVN_WC__NODES
+    SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+                                      STMT_SELECT_ANY_PRISTINE_REFERENCE_1));
+    SVN_ERR(svn_sqlite__bind_checksum(stmt_nodes, 1, sha1_checksum,
+                                      scratch_pool));
+    SVN_ERR(svn_sqlite__bind_checksum(stmt_nodes, 2, md5_checksum,
+                                      scratch_pool));
+    SVN_ERR(svn_sqlite__step(&is_referenced_nodes, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+    SVN_ERR_ASSERT(is_referenced == is_referenced_nodes);
+    SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+    is_referenced = is_referenced_nodes;
+    stmt = stmt_nodes;
+#endif
+#endif
 
     SVN_ERR(svn_sqlite__reset(stmt));
   }
@@ -3245,6 +3277,8 @@ temp_cross_db_copy(svn_wc__db_t *db,
   iwb.original_revnum = copyfrom_rev;
   iwb.moved_here = FALSE;
 
+  iwb.op_depth = (*dst_relpath == '\0') ? 1 : 2;  /* ### temporary op_depth */
+
   iwb.checksum = checksum;
   iwb.children = children;
   iwb.depth = depth;
@@ -3466,6 +3500,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
   apr_int64_t copyfrom_id;
   svn_wc__db_kind_t kind;
   const apr_array_header_t *children;
+  apr_int64_t op_depth;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
@@ -3527,6 +3562,10 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
   else
     children = NULL;
 
+  /* ### temporary op_depth */
+  op_depth = (children == NULL) ? (apr_int64_t)2 :
+                                  (apr_int64_t)1; /* no directory or stub */
+
   if (!strcmp(src_pdh->local_abspath, dst_pdh->local_abspath))
     {
       svn_sqlite__stmt_t *stmt;
@@ -3567,8 +3606,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
       SVN_ERR(svn_sqlite__bindf(stmt, "issisnnnt",
                     src_pdh->wcroot->wc_id, src_relpath,
                     dst_relpath,
-                    (children == NULL) ? (apr_int64_t)2 :
-                                (apr_int64_t)1, /* no directory or stub */
+                    op_depth,
                     dst_parent_relpath,
                     presence_map, dst_status));
 
@@ -3595,6 +3633,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
                                                    dst_pdh->wcroot->wc_id,
                                                    dst_relpath,
                                                    children,
+                                                   op_depth,
                                                    scratch_pool));
     }
   else
@@ -3672,6 +3711,8 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
       iwb.original_revnum = original_revision;
     }
 
+  iwb.op_depth = (*local_relpath == '\0') ? 1 : 2;  /* ### temporary op_depth */
+
   iwb.children = children;
   iwb.depth = depth;
 
@@ -3744,6 +3785,8 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
       iwb.original_revnum = original_revision;
     }
 
+  iwb.op_depth = (*local_relpath == '\0') ? 1 : 2;  /* ### temporary op_depth */
+
   iwb.checksum = checksum;
 
   iwb.work_items = work_items;
@@ -3811,6 +3854,8 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t 
       iwb.original_revnum = original_revision;
     }
 
+  iwb.op_depth = (*local_relpath == '\0') ? 1 : 2;  /* ### temporary op_depth */
+
   iwb.target = target;
 
   iwb.work_items = work_items;
@@ -3847,6 +3892,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
   iwb.kind = svn_wc__db_kind_dir;
   iwb.wc_id = pdh->wcroot->wc_id;
   iwb.local_relpath = local_relpath;
+  iwb.op_depth = relpath_depth(local_relpath);
 
   iwb.work_items = work_items;
 
@@ -3882,6 +3928,7 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
   iwb.kind = svn_wc__db_kind_file;
   iwb.wc_id = pdh->wcroot->wc_id;
   iwb.local_relpath = local_relpath;
+  iwb.op_depth = relpath_depth(local_relpath);
 
   iwb.work_items = work_items;
 
@@ -3919,6 +3966,7 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
   iwb.kind = svn_wc__db_kind_symlink;
   iwb.wc_id = pdh->wcroot->wc_id;
   iwb.local_relpath = local_relpath;
+  iwb.op_depth = relpath_depth(local_relpath);
 
   iwb.target = target;
 
@@ -5050,6 +5098,7 @@ svn_wc__db_read_info(svn_wc__db_status_t
   if (!have_work)
     have_work = &local_have_work;
     
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt_base, pdh->wcroot->sdb,
                                     lock ? STMT_SELECT_BASE_NODE_WITH_LOCK
                                          : STMT_SELECT_BASE_NODE));
@@ -5062,6 +5111,7 @@ svn_wc__db_read_info(svn_wc__db_status_t
   SVN_ERR(svn_sqlite__bindf(stmt_work, "is",
                             pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(have_work, stmt_work));
+#endif
 
   SVN_ERR(svn_sqlite__get_statement(&stmt_act, pdh->wcroot->sdb,
                                     STMT_SELECT_ACTUAL_NODE));
@@ -5092,6 +5142,8 @@ svn_wc__db_read_info(svn_wc__db_status_t
   SVN_ERR(assert_working_rows_match(*have_work, local_have_nodes_work,
                                     stmt_work, stmt_nodes_work,
                                     local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes_base));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes_work));
 #else
   /* Lets assume the queries return compatible data */
   *have_base = local_have_nodes_base;
@@ -5402,13 +5454,6 @@ svn_wc__db_read_info(svn_wc__db_status_t
                                                      scratch_pool));
     }
 
-#ifdef SVN_WC__NODES
-#ifndef SVN_WC__NODES_ONLY
-  err = svn_error_compose_create(err, svn_sqlite__reset(stmt_nodes_base));
-  err = svn_error_compose_create(err, svn_sqlite__reset(stmt_nodes_work));
-#endif
-#endif
-
   err = svn_error_compose_create(err, svn_sqlite__reset(stmt_base));
   err = svn_error_compose_create(err, svn_sqlite__reset(stmt_work));
   SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt_act)));
@@ -5851,24 +5896,55 @@ commit_node(void *baton, svn_sqlite__db_
   svn_wc__db_kind_t new_kind;
   const char *new_depth_str = NULL;
   svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes_base, *stmt_nodes_work;
+  svn_boolean_t have_nodes_base, have_nodes_work;
+#endif
 
   /* ### is it better to select only the data needed?  */
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt_base, cb->pdh->wcroot->sdb,
                                     STMT_SELECT_BASE_NODE));
   SVN_ERR(svn_sqlite__get_statement(&stmt_work, cb->pdh->wcroot->sdb,
                                     STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__get_statement(&stmt_act, cb->pdh->wcroot->sdb,
-                                    STMT_SELECT_ACTUAL_NODE));
-
   SVN_ERR(svn_sqlite__bindf(stmt_base, "is",
                             cb->pdh->wcroot->wc_id, cb->local_relpath));
   SVN_ERR(svn_sqlite__bindf(stmt_work, "is",
                             cb->pdh->wcroot->wc_id, cb->local_relpath));
-  SVN_ERR(svn_sqlite__bindf(stmt_act, "is",
-                            cb->pdh->wcroot->wc_id, cb->local_relpath));
-
   SVN_ERR(svn_sqlite__step(&have_base, stmt_base));
   SVN_ERR(svn_sqlite__step(&have_work, stmt_work));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes_base, cb->pdh->wcroot->sdb,
+                                    STMT_SELECT_BASE_NODE_1));
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes_work, cb->pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes_base, "is",
+                            cb->pdh->wcroot->wc_id, cb->local_relpath));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes_work, "is",
+                            cb->pdh->wcroot->wc_id, cb->local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_base, stmt_nodes_base));
+  SVN_ERR(svn_sqlite__step(&have_nodes_work, stmt_nodes_work));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_base_rows_match(have_base, have_nodes_base,
+                                 stmt_base, stmt_nodes_base,
+                                 cb->local_relpath, scratch_pool));
+  SVN_ERR(assert_working_rows_match(have_work, have_nodes_work,
+                                    stmt_work, stmt_nodes_work,
+                                    cb->local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes_base));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes_work));
+#else
+  stmt_base = stmt_nodes_base;
+  stmt_work = stmt_nodes_work;
+  have_base = have_nodes_base;
+  have_work = have_nodes_work;
+#endif
+#endif
+  SVN_ERR(svn_sqlite__get_statement(&stmt_act, cb->pdh->wcroot->sdb,
+                                    STMT_SELECT_ACTUAL_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt_act, "is",
+                            cb->pdh->wcroot->wc_id, cb->local_relpath));
   SVN_ERR(svn_sqlite__step(&have_act, stmt_act));
 
   /* There should be something to commit!  */
@@ -6092,14 +6168,36 @@ determine_repos_info(apr_int64_t *repos_
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   const char *repos_parent_relpath;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
   /* ### is it faster to fetch fewer columns? */
 
   /* Prefer the current node's repository information.  */
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_BASE_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+                                    STMT_SELECT_BASE_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_base_rows_match(have_row, have_nodes_row,
+                                 stmt, stmt_nodes,
+                                 local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
 
   if (have_row && !svn_sqlite__column_is_null(stmt, 0))
     {
@@ -6566,12 +6664,34 @@ svn_wc__db_scan_addition(svn_wc__db_stat
       svn_sqlite__stmt_t *stmt;
       svn_boolean_t have_row;
       svn_wc__db_status_t presence;
+#ifdef SVN_WC__NODES
+      svn_sqlite__stmt_t *stmt_nodes;
+      svn_boolean_t have_nodes_row;
+#endif
 
       /* ### is it faster to fetch fewer columns? */
+#ifndef SVN_WC__NODES_ONLY
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_SELECT_WORKING_NODE));
       SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, wcroot->sdb,
+                                        STMT_SELECT_WORKING_NODE_1));
+      SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                                wcroot->wc_id, current_relpath));
+      SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR(assert_working_rows_match(have_row, have_nodes_row,
+                                        stmt, stmt_nodes,
+                                        current_relpath, scratch_pool));
+      SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+      stmt = stmt_nodes;
+      have_row = have_nodes_row;
+#endif
+#endif
 
       if (!have_row)
         {
@@ -6751,11 +6871,34 @@ svn_wc__db_scan_deletion(const char **ba
       svn_boolean_t have_row;
       svn_boolean_t have_base;
       svn_wc__db_status_t work_presence;
+#ifdef SVN_WC__NODES
+      svn_sqlite__stmt_t *stmt_nodes;
+      svn_boolean_t have_nodes_row;
+#endif
 
+#ifndef SVN_WC__NODES_ONLY
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                         STMT_SELECT_DELETION_INFO));
       SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, wcroot->sdb,
+                                        STMT_SELECT_DELETION_INFO_1));
+      SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                                wcroot->wc_id, current_relpath));
+      SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt, 0)
+                     == svn_sqlite__column_int64(stmt_nodes, 0));
+      SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt, 1)
+                     == svn_sqlite__column_int64(stmt_nodes, 1));
+      SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+      stmt = stmt_nodes;
+      have_row = have_nodes_row;
+#endif
+#endif
 
       if (!have_row)
         {
@@ -7801,6 +7944,10 @@ svn_wc__db_node_hidden(svn_boolean_t *hi
   svn_wc__db_status_t work_status, base_status;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
   /* This uses an optimisation that first reads the working node and
      then may read the base node.  It could call svn_wc__db_read_info
@@ -7814,10 +7961,27 @@ svn_wc__db_node_hidden(svn_boolean_t *hi
   VERIFY_USABLE_PDH(pdh);
 
   /* First check the working node. */
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_WORKING_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_working_rows_match(have_row, have_nodes_row, stmt, stmt_nodes,
+                                    local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
 
   if (have_row)
     {
@@ -7974,7 +8138,7 @@ wclock_obtain_cb(void *baton,
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_FIND_WC_LOCK));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, filter));
 
-  lock_depth = relpath_op_depth(bt->local_relpath);
+  lock_depth = relpath_depth(bt->local_relpath);
   max_depth = lock_depth + bt->levels_to_lock;
 
   SVN_ERR(svn_sqlite__step(&got_row, stmt));
@@ -7989,7 +8153,7 @@ wclock_obtain_cb(void *baton,
       /* If we are not locking with depth infinity, check if this lock
          voids our lock request */
       if (bt->levels_to_lock >= 0
-          && relpath_op_depth(lock_relpath) > max_depth)
+          && relpath_depth(lock_relpath) > max_depth)
         {
           SVN_ERR(svn_sqlite__step(&got_row, stmt));
           continue;
@@ -8047,7 +8211,7 @@ wclock_obtain_cb(void *baton,
         {
           int levels = svn_sqlite__column_int(stmt, 0);
           if (levels >= 0)
-            levels += relpath_op_depth(lock_relpath);
+            levels += relpath_depth(lock_relpath);
 
           SVN_ERR(svn_sqlite__reset(stmt));
 
@@ -8123,7 +8287,7 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
     {
       int i;
       svn_wc__db_wcroot_t *wcroot = baton.pdh->wcroot;
-      int depth = relpath_op_depth(baton.local_relpath);
+      int depth = relpath_depth(baton.local_relpath);
 
       for (i = 0; i < wcroot->owned_locks->nelts; i++)
         {
@@ -8132,7 +8296,7 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
 
           if (svn_relpath_is_ancestor(lock->local_relpath, baton.local_relpath)
               && (lock->levels == -1
-                  || (lock->levels + relpath_op_depth(lock->local_relpath)) 
+                  || (lock->levels + relpath_depth(lock->local_relpath))
                             >= depth))
             {
               const char *lock_abspath
@@ -8305,7 +8469,7 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
   VERIFY_USABLE_PDH(pdh);
   *own_lock = FALSE;
   owned_locks = pdh->wcroot->owned_locks;
-  lock_level = relpath_op_depth(local_relpath);
+  lock_level = relpath_depth(local_relpath);
 
   if (exact)
     for (i = 0; i < owned_locks->nelts; i++)
@@ -8327,7 +8491,7 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
 
         if (svn_relpath_is_ancestor(lock->local_relpath, local_relpath)
             && (lock->levels == -1
-                || ((relpath_op_depth(lock->local_relpath) + lock->levels)
+                || ((relpath_depth(lock->local_relpath) + lock->levels)
                             >= lock_level)))
           {
             *own_lock = TRUE;
@@ -8541,12 +8705,33 @@ make_copy_txn(void *baton,
   const apr_array_header_t *children;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   int i;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", mcb->pdh->wcroot->wc_id,
                             mcb->local_relpath));
-
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is", mcb->pdh->wcroot->wc_id,
+                            mcb->local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_working_rows_match(have_row, have_nodes_row,
+                                    stmt, stmt_nodes,
+                                    mcb->local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
 
   if (have_row)
     {
@@ -8576,11 +8761,28 @@ make_copy_txn(void *baton,
     {
       svn_wc__db_status_t base_status;
 
+#ifndef SVN_WC__NODES_ONLY
       SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_BASE_NODE));
       SVN_ERR(svn_sqlite__bindf(stmt, "is", mcb->pdh->wcroot->wc_id, 
                                 mcb->local_relpath));
-
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+      SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, sdb,
+                                        STMT_SELECT_BASE_NODE_1));
+      SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is", mcb->pdh->wcroot->wc_id, 
+                                mcb->local_relpath));
+      SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+      SVN_ERR(assert_base_rows_match(have_row, have_nodes_row,
+                                     stmt, stmt_nodes,
+                                     mcb->local_relpath, scratch_pool));
+      SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+      stmt = stmt_nodes;
+      have_row = have_nodes_row;
+#endif
+#endif
 
       /* If there is no BASE_NODE, we don't have to copy anything */
       if (!have_row)
@@ -8683,7 +8885,7 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__bindf(stmt, "isi",
                                 mcb->pdh->wcroot->wc_id,
                                 mcb->local_relpath,
-                                (*mcb->local_relpath == '\0'
+                                (*mcb->local_relpath == '\0' /* ### op_depth */
                                  ? (apr_int64_t)1 : (apr_int64_t)2)));
 
       SVN_ERR(svn_sqlite__step_done(stmt));
@@ -8714,7 +8916,7 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__bindf(stmt, "isi",
                                 mcb->pdh->wcroot->wc_id,
                                 mcb->local_relpath,
-                                (*mcb->local_relpath == '\0'
+                                (*mcb->local_relpath == '\0' /* ### op_depth */
                                  ? (apr_int64_t)1 : (apr_int64_t)2)));
 
       SVN_ERR(svn_sqlite__step_done(stmt));
@@ -8820,6 +9022,10 @@ get_copyfrom(apr_int64_t *copyfrom_repos
   const char *local_relpath;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -8829,10 +9035,27 @@ get_copyfrom(apr_int64_t *copyfrom_repos
                                              scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_WORKING_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+                                    STMT_SELECT_WORKING_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_working_rows_match(have_row, have_nodes_row, stmt, stmt_nodes,
+                                    local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
   if (!have_row)
     {
       *copyfrom_repos_id = 0;  /* What's a good value to return? */
@@ -9002,10 +9225,28 @@ svn_wc__db_temp_get_file_external(const 
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t have_nodes_row;
+#endif
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
                                  STMT_SELECT_FILE_EXTERNAL, scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(get_statement_for_path(&stmt_nodes, db, local_abspath,
+                                 STMT_SELECT_FILE_EXTERNAL_1, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_text_columns_equal(stmt, stmt_nodes, 0, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  have_row = have_nodes_row;
+#endif
+#endif
 
   /* ### file externals are pretty bogus right now. they have just a
      ### WORKING_NODE for a while, eventually settling into just a BASE_NODE.
@@ -9042,6 +9283,10 @@ svn_wc__db_temp_op_set_file_external(svn
   const char *local_relpath;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t got_row;
+#ifdef SVN_WC__NODES
+  svn_sqlite__stmt_t *stmt_nodes;
+  svn_boolean_t got_nodes_row;
+#endif
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(!repos_relpath 
@@ -9053,12 +9298,27 @@ svn_wc__db_temp_op_set_file_external(svn
                                              scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_SELECT_BASE_NODE));
-
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
-
   SVN_ERR(svn_sqlite__step(&got_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+                                    STMT_SELECT_BASE_NODE_1));
+  SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+                            pdh->wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&got_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+  SVN_ERR(assert_base_rows_match(got_row, got_nodes_row, stmt, stmt_nodes,
+                                 local_relpath, scratch_pool));
+  SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+  stmt = stmt_nodes;
+  got_row = got_nodes_row;
+#endif
+#endif
   SVN_ERR(svn_sqlite__reset(stmt));
 
   if (!got_row)
@@ -9116,12 +9376,30 @@ svn_wc__db_temp_op_set_file_external(svn
 #endif
     }
 
+#ifndef SVN_WC__NODES_ONLY
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_UPDATE_FILE_EXTERNAL));
-
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id,
-                          local_relpath));
+                            local_relpath));
+  if (repos_relpath)
+    {
+      const char *str;
+
+      SVN_ERR(svn_wc__serialize_file_external(&str,
+                                              repos_relpath,
+                                              peg_rev,
+                                              rev,
+                                              scratch_pool));
 
+      SVN_ERR(svn_sqlite__bind_text(stmt, 3, str));
+    }
+  SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+#ifdef SVN_WC__NODES
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_UPDATE_FILE_EXTERNAL_1));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id,
+                            local_relpath));
   if (repos_relpath)
     {
       const char *str;
@@ -9134,10 +9412,12 @@ svn_wc__db_temp_op_set_file_external(svn
 
       SVN_ERR(svn_sqlite__bind_text(stmt, 3, str));
     }
+  SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
 
   SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
 
-  return svn_error_return(svn_sqlite__step_done(stmt));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

Modified: subversion/branches/object-model/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/libsvn_wc/wc_db.h?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/object-model/subversion/libsvn_wc/wc_db.h Fri Sep 24 14:02:50 2010
@@ -757,27 +757,6 @@ svn_wc__db_base_get_info(svn_wc__db_stat
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
-/* Just like svn_wc__db_base_get_info, but always reads information
-   from inside the parent of LOCAL_ABSPATH, to allow reading the
-   information of a node that is obstructed by a separate working
-   copy.
-   
-   ### BH: This information is necessary for svn_wc_add3()'s
-   ###     checkout integration support. Even after we switch to
-   ###     a single db.
-   */
-svn_error_t *
-svn_wc__db_base_get_info_from_parent(svn_wc__db_status_t *status,
-                                     svn_wc__db_kind_t *kind,
-                                     svn_revnum_t *revision,
-                                     const char **repos_relpath,
-                                     const char **repos_root_url,
-                                     const char **repos_uuid,
-                                     svn_wc__db_t *db,
-                                     const char *local_abspath,
-                                     apr_pool_t *result_pool,
-                                     apr_pool_t *scratch_pool);
-
 
 /* Set *PROPVAL to the value of the property named PROPNAME of the node
    LOCAL_ABSPATH in the BASE tree.

Modified: subversion/branches/object-model/subversion/mod_dav_svn/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/authz.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/authz.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/authz.c Fri Sep 24 14:02:50 2010
@@ -60,7 +60,7 @@ dav_svn__allow_read(request_rec *r,
   allow_read_bypass = dav_svn__get_pathauthz_bypass(r);
   if (allow_read_bypass != NULL)
     {
-      if (allow_read_bypass(r,path, repos->repo_name) == OK)
+      if (allow_read_bypass(r, path, repos->repo_basename) == OK)
         return TRUE;
       else
         return FALSE;

Modified: subversion/branches/object-model/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/deadprops.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/deadprops.c Fri Sep 24 14:02:50 2010
@@ -161,7 +161,9 @@ get_value(dav_db *db, const dav_prop_nam
 
 
 static dav_error *
-save_value(dav_db *db, const dav_prop_name *name, const svn_string_t *value)
+save_value(dav_db *db, const dav_prop_name *name,
+           const svn_string_t *const *old_value_p,
+           const svn_string_t *value)
 {
   const char *propname;
   svn_error_t *serr;
@@ -210,10 +212,11 @@ save_value(dav_db *db, const dav_prop_na
         }
       else
         {
-          serr = svn_repos_fs_change_rev_prop3(resource->info->repos->repos,
+          serr = svn_repos_fs_change_rev_prop4(resource->info->repos->repos,
                                                resource->info->root.rev,
                                                resource->info->repos->username,
-                                               propname, value, TRUE, TRUE,
+                                               propname, old_value_p, value,
+                                               TRUE, TRUE,
                                                db->authz_read_func,
                                                db->authz_read_baton,
                                                resource->pool);
@@ -425,6 +428,7 @@ db_map_namespaces(dav_db *db,
 
 static dav_error *
 decode_property_value(const svn_string_t **out_propval_p,
+                      svn_boolean_t *absent,
                       const svn_string_t *maybe_encoded_propval,
                       const apr_xml_elem *elem,
                       apr_pool_t *pool)
@@ -432,6 +436,7 @@ decode_property_value(const svn_string_t
   apr_xml_attr *attr = elem->attr;
 
   /* Default: no "encoding" attribute. */
+  *absent = FALSE;
   *out_propval_p = maybe_encoded_propval;
 
   /* Check for special encodings of the property value. */
@@ -443,12 +448,21 @@ decode_property_value(const svn_string_t
 
           /* Handle known encodings here. */
           if (enc_type && (strcmp(enc_type, "base64") == 0))
-            *out_propval_p = svn_base64_decode_string(maybe_encoded_propval, pool);
+            *out_propval_p = svn_base64_decode_string(maybe_encoded_propval,
+                                                      pool);
           else
             return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                                  "Unknown property encoding");
           break;
         }
+
+      if (strcmp(attr->name, SVN_DAV__OLD_VALUE__ABSENT) == 0)
+        {
+          /* ### parse attr->value */
+          *absent = TRUE;
+          *out_propval_p = NULL;
+        }
+
       /* Next attribute, please. */
       attr = attr->next;
     }
@@ -462,7 +476,10 @@ db_store(dav_db *db,
          const apr_xml_elem *elem,
          dav_namespace_map *mapping)
 {
+  const svn_string_t *const *old_propval_p;
+  const svn_string_t *old_propval;
   const svn_string_t *propval;
+  svn_boolean_t absent;
   apr_pool_t *pool = db->p;
   dav_error *derr;
 
@@ -475,11 +492,41 @@ db_store(dav_db *db,
   propval = svn_string_create
     (dav_xml_get_cdata(elem, pool, 0 /* strip_white */), pool);
 
-  derr = decode_property_value(&propval, propval, elem, pool);
+  derr = decode_property_value(&propval, &absent, propval, elem, pool);
   if (derr)
     return derr;
 
-  return save_value(db, name, propval);
+  if (absent && ! elem->first_child)
+    /* ### better error check */
+    return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+                         apr_psprintf(pool, 
+                                      "'%s' cannot be specified on the value "
+                                      "without specifying an expectation",
+                                      SVN_DAV__OLD_VALUE__ABSENT));
+
+  /* ### namespace check? */
+  if (elem->first_child && !strcmp(elem->first_child->name, SVN_DAV__OLD_VALUE))
+    {
+      const char *propname;
+
+      get_repos_propname(db, name, &propname);
+
+      /* Parse OLD_PROPVAL. */
+      old_propval = svn_string_create(dav_xml_get_cdata(elem->first_child, pool,
+                                                        0 /* strip_white */),
+                                      pool);
+      derr = decode_property_value(&old_propval, &absent,
+                                   old_propval, elem->first_child, pool);
+      if (derr)
+        return derr;
+
+      old_propval_p = (const svn_string_t *const *) &old_propval;
+    }
+  else
+    old_propval_p = NULL;
+
+
+  return save_value(db, name, old_propval_p, propval);
 }
 
 
@@ -506,10 +553,10 @@ db_remove(dav_db *db, const dav_prop_nam
          not a working resource!  But this is how we currently
          (hackily) allow the svn client to change unversioned rev
          props.  See issue #916. */
-      serr = svn_repos_fs_change_rev_prop3(db->resource->info->repos->repos,
+      serr = svn_repos_fs_change_rev_prop4(db->resource->info->repos->repos,
                                            db->resource->info->root.rev,
                                            db->resource->info->repos->username,
-                                           propname, NULL, TRUE, TRUE,
+                                           propname, NULL, NULL, TRUE, TRUE,
                                            db->authz_read_func,
                                            db->authz_read_baton,
                                            db->resource->pool);

Modified: subversion/branches/object-model/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/mod_dav_svn.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/mod_dav_svn.c Fri Sep 24 14:02:50 2010
@@ -311,18 +311,24 @@ SVNPathAuthz_cmd(cmd_parms *cmd, void *c
   dir_conf_t *conf = config;
 
   if (apr_strnatcasecmp("off", arg1) == 0)
-    conf->path_authz_method = CONF_PATHAUTHZ_OFF;
-  else if (apr_strnatcasecmp(PATHAUTHZ_BYPASS_ARG,arg1) == 0)
+    {
+      conf->path_authz_method = CONF_PATHAUTHZ_OFF;
+    }
+  else if (apr_strnatcasecmp(PATHAUTHZ_BYPASS_ARG, arg1) == 0)
     {
       conf->path_authz_method = CONF_PATHAUTHZ_BYPASS;
       if (pathauthz_bypass_func == NULL)
-        pathauthz_bypass_func=ap_lookup_provider(
-                                          AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP,
-                                          AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME,
-                                          AUTHZ_SVN__SUBREQ_BYPASS_PROV_VER);
+        {
+          pathauthz_bypass_func =
+            ap_lookup_provider(AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP,
+                               AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME,
+                               AUTHZ_SVN__SUBREQ_BYPASS_PROV_VER);
+        }
     }
   else
-    conf->path_authz_method = CONF_PATHAUTHZ_ON;
+    {
+      conf->path_authz_method = CONF_PATHAUTHZ_ON;
+    }
 
   return NULL;
 }
@@ -608,7 +614,7 @@ dav_svn__get_pathauthz_bypass(request_re
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
 
-  if (conf->path_authz_method==CONF_PATHAUTHZ_BYPASS)
+  if (conf->path_authz_method == CONF_PATHAUTHZ_BYPASS)
     return pathauthz_bypass_func;
   return NULL;
 }

Modified: subversion/branches/object-model/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/repos.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/repos.c Fri Sep 24 14:02:50 2010
@@ -1140,7 +1140,7 @@ dav_svn_split_uri(request_rec *r,
                   const char *root_path,
                   const char **cleaned_uri,
                   int *trailing_slash,
-                  const char **repos_name,
+                  const char **repos_basename,
                   const char **relative_path,
                   const char **repos_path)
 {
@@ -1216,14 +1216,14 @@ dav_svn_split_uri(request_rec *r,
      ### slash. something about SVN-private-path */
 
   /* Depending on whether SVNPath or SVNParentPath was used, we need
-     to compute 'relative' and 'repos_name' differently.  */
+     to compute 'relative' and 'repos_basename' differently.  */
 
   /* Normal case:  the SVNPath command was used to specify a
      particular repository.  */
   if (fs_path != NULL)
     {
-      /* the repos_name is the last component of root_path. */
-      *repos_name = svn_dirent_basename(root_path, r->pool);
+      /* the repos_basename is the last component of root_path. */
+      *repos_basename = svn_dirent_basename(root_path, r->pool);
 
       /* 'relative' is already correct for SVNPath; the root_path
          already contains the name of the repository, so relative is
@@ -1264,7 +1264,7 @@ dav_svn_split_uri(request_rec *r,
         }
 
       /* return answer */
-      *repos_name = magic_component;
+      *repos_basename = magic_component;
     }
 
   /* We can return 'relative' at this point too. */
@@ -1882,7 +1882,7 @@ get_resource(request_rec *r,
   dav_resource_combined *comb;
   dav_svn_repos *repos;
   const char *cleaned_uri;
-  const char *repos_name;
+  const char *repo_basename;
   const char *relative;
   const char *repos_path;
   const char *repos_key;
@@ -1925,7 +1925,7 @@ get_resource(request_rec *r,
   /* This does all the work of interpreting/splitting the request uri. */
   err = dav_svn_split_uri(r, r->uri, root_path,
                           &cleaned_uri, &had_slash,
-                          &repos_name, &relative, &repos_path);
+                          &repo_basename, &relative, &repos_path);
   if (err)
     return err;
 
@@ -1938,9 +1938,9 @@ get_resource(request_rec *r,
     {
       /* ...then the URL to the repository is actually one implicit
          component longer... */
-      root_path = svn_uri_join(root_path, repos_name, r->pool);
+      root_path = svn_uri_join(root_path, repo_basename, r->pool);
       /* ...and we need to specify exactly what repository to open. */
-      fs_path = svn_dirent_join(fs_parent_path, repos_name, r->pool);
+      fs_path = svn_dirent_join(fs_parent_path, repo_basename, r->pool);
     }
 
   /* Start building and filling a 'combination' object. */
@@ -2011,7 +2011,7 @@ get_resource(request_rec *r,
   repos->repo_name = repo_name;
 
   /* The repository filesystem basename */
-  repos->repo_basename = repos_name;
+  repos->repo_basename = repo_basename;
 
   /* An XSL transformation */
   repos->xslt_uri = xslt_uri;

Modified: subversion/branches/object-model/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/util.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/util.c Fri Sep 24 14:02:50 2010
@@ -107,6 +107,9 @@ dav_svn__convert_err(svn_error_t *serr,
       case SVN_ERR_FS_PATH_ALREADY_LOCKED:
         status = HTTP_LOCKED;
         break;
+      case SVN_ERR_FS_PROP_BASEVALUE_MISMATCH:
+        status = HTTP_PRECONDITION_FAILED;
+        break;
         /* add other mappings here */
       }
 

Modified: subversion/branches/object-model/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/mod_dav_svn/version.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/object-model/subversion/mod_dav_svn/version.c Fri Sep 24 14:02:50 2010
@@ -41,7 +41,6 @@
 #include "private/svn_log.h"
 
 #include "dav_svn.h"
-#include "mod_dav_svn.h"
 
 
 svn_error_t *
@@ -143,6 +142,7 @@ get_vsn_options(apr_pool_t *p, apr_text_
   /* Send SVN_RA_CAPABILITY_* capabilities. */
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_DEPTH);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
+  apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY);
   /* Mergeinfo is a special case: here we merely say that the server
    * knows how to handle mergeinfo -- whether the repository does too
@@ -1015,22 +1015,6 @@ deliver_report(request_rec *r,
 
   if (doc->root->ns == ns)
     {
-      const char *cleaned_uri, *relative_path, *repos_path;
-      int trailing_slash;
-      /* During SVNPathAuthz short_circuit
-       * resource->info->repos->repo_name becomes NULL.*/
-      if (resource->info->repos->repo_name == NULL)
-        {
-          dav_error *err;
-          err = dav_svn_split_uri(r, r->uri, dav_svn__get_root_dir(r),
-                                  &cleaned_uri, &trailing_slash,
-                                  &(resource->info->repos->repo_name), 
-                                  &relative_path, &repos_path);
-          if (err)
-            {
-              return err;
-            }
-        }
       /* ### note that these report names should have symbols... */
 
       if (strcmp(doc->root->name, "update-report") == 0)

Modified: subversion/branches/object-model/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svn/main.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svn/main.c (original)
+++ subversion/branches/object-model/subversion/svn/main.c Fri Sep 24 14:02:50 2010
@@ -2087,12 +2087,24 @@ main(int argc, const char *argv[])
         }
     }
 
-  if (opt_state.relocate && (opt_state.depth != svn_depth_unknown))
+  /* Relocation is infinite-depth only. */
+  if (opt_state.relocate)
     {
-      err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
-                             _("--relocate and --depth are mutually "
-                               "exclusive"));
-      return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+      if (opt_state.depth != svn_depth_unknown)
+        {
+          err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                                 _("--relocate and --depth are mutually "
+                                   "exclusive"));
+          return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+        }
+      if (! descend)
+        {
+          err = svn_error_create(
+                    SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                    _("--relocate and --non-recursive (-N) are mutually "
+                      "exclusive"));
+          return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+        }
     }
 
   /* Only a few commands can accept a revision range; the rest can take at

Modified: subversion/branches/object-model/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svn/switch-cmd.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/object-model/subversion/svn/switch-cmd.c Fri Sep 24 14:02:50 2010
@@ -41,7 +41,6 @@
 
 static svn_error_t *
 rewrite_urls(const apr_array_header_t *targets,
-             svn_boolean_t recurse,
              svn_client_ctx_t *ctx,
              apr_pool_t *pool)
 {
@@ -67,7 +66,7 @@ rewrite_urls(const apr_array_header_t *t
 
   if (targets->nelts == 2)
     {
-      SVN_ERR(svn_client_relocate("", from, to, recurse, ctx, pool));
+      SVN_ERR(svn_client_relocate2("", from, to, ctx, pool));
     }
   else
     {
@@ -75,8 +74,7 @@ rewrite_urls(const apr_array_header_t *t
         {
           const char *target = APR_ARRAY_IDX(targets, i, const char *);
           svn_pool_clear(subpool);
-          SVN_ERR(svn_client_relocate(target, from, to, recurse,
-                                      ctx, subpool));
+          SVN_ERR(svn_client_relocate2(target, from, to, ctx, subpool));
         }
     }
 
@@ -109,9 +107,7 @@ svn_cl__switch(apr_getopt_t *os,
 
   /* handle only-rewrite case specially */
   if (opt_state->relocate)
-    return rewrite_urls(targets,
-                        SVN_DEPTH_IS_RECURSIVE(opt_state->depth),
-                        ctx, scratch_pool);
+    return rewrite_urls(targets, ctx, scratch_pool);
 
   if (targets->nelts < 1)
     return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);

Modified: subversion/branches/object-model/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svnrdump/dump_editor.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/object-model/subversion/svnrdump/dump_editor.c Fri Sep 24 14:02:50 2010
@@ -27,6 +27,7 @@
 #include "svn_repos.h"
 #include "svn_path.h"
 #include "svn_props.h"
+#include "svn_subst.h"
 #include "svn_dirent_uri.h"
 
 #include "dump_editor.h"
@@ -66,11 +67,41 @@ struct dump_edit_baton {
   const char *base_checksum;
 
   /* Flags to trigger dumping props and text */
-  svn_boolean_t dump_props;
   svn_boolean_t dump_text;
-  svn_boolean_t dump_props_pending;
+  svn_boolean_t dump_props;
+  svn_boolean_t dump_newlines;
 };
 
+/* Normalize the line ending style of the values of properties in PROPS
+ * that "need translation" (according to svn_prop_needs_translation(),
+ * currently all svn:* props) so that they contain only LF (\n) line endings.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+                apr_pool_t *pool)
+{
+  apr_hash_index_t *hi;
+  const char *key, *cstring;
+  const svn_string_t *value;
+
+  for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
+    {
+      key = svn__apr_hash_index_key(hi);
+      value = svn__apr_hash_index_val(hi);
+
+      if (svn_prop_needs_translation(key))
+        {
+          SVN_ERR(svn_subst_translate_cstring2(value->data, &cstring,
+                                               "\n", TRUE,
+                                               NULL, FALSE,
+                                               pool));
+          value = svn_string_create(cstring, pool);
+          apr_hash_set(props, key, APR_HASH_KEY_STRING, value);
+        }
+    }
+  return SVN_NO_ERROR;
+}
+
 /* Make a directory baton to represent the directory at path (relative
  * to the edit_baton).
  *
@@ -97,17 +128,15 @@ make_dir_baton(const char *path,
   struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
   const char *abspath;
 
-  /* Disallow a path relative to nothing. */
-  SVN_ERR_ASSERT_NO_RETURN(!path || pb);
-
   /* Construct the full path of this node. */
   if (pb)
     abspath = svn_uri_join("/", path, pool);
   else
-    abspath = "/";
+    abspath = apr_pstrdup(pool, "/");
 
-  /* Remove leading slashes from copyfrom paths. */
-  if (copyfrom_path && strcmp(copyfrom_path, "/"))
+  /* Strip leading slash from copyfrom_path so that the path is
+     canonical and svn_relpath_join can be used */
+  if (copyfrom_path)
     copyfrom_path = ((*copyfrom_path == '/') ?
                      copyfrom_path + 1 : copyfrom_path);
 
@@ -139,6 +168,7 @@ dump_props(struct dump_edit_baton *eb,
   if (trigger_var && !*trigger_var)
     return SVN_NO_ERROR;
 
+  SVN_ERR(normalize_props(eb->props, eb->pool));
   svn_stringbuf_setempty(eb->propstring);
   propstream = svn_stream_from_stringbuf(eb->propstring, eb->pool);
   SVN_ERR(svn_hash_write_incremental(eb->props, eb->deleted_props,
@@ -172,8 +202,8 @@ dump_props(struct dump_edit_baton *eb,
       SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
 
       /* Cleanup so that data is never dumped twice. */
-      svn_hash__clear(eb->props, pool);
-      svn_hash__clear(eb->deleted_props, pool);
+      svn_hash__clear(eb->props, eb->pool);
+      svn_hash__clear(eb->deleted_props, eb->pool);
       if (trigger_var)
         *trigger_var = FALSE;
     }
@@ -181,6 +211,19 @@ dump_props(struct dump_edit_baton *eb,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+dump_newlines(struct dump_edit_baton *eb,
+           svn_boolean_t *trigger_var,
+           apr_pool_t *pool)
+{
+  if (trigger_var && *trigger_var)
+    {
+      SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+      *trigger_var = FALSE;
+    }
+  return SVN_NO_ERROR;
+}
+
 /*
  * Write out a node record for PATH of type KIND under EB->FS_ROOT.
  * ACTION describes what is happening to the node (see enum
@@ -227,6 +270,9 @@ dump_node(struct dump_edit_baton *eb,
   switch (action)
     {
     case svn_node_action_change:
+      /* We are here after a change_file_prop or change_dir_prop. They
+         set up whatever dump_props they needed to- nothing to
+         do here but print node action information */
       SVN_ERR(svn_stream_printf(eb->stream, pool,
                                 SVN_REPOS_DUMPFILE_NODE_ACTION
                                 ": change\n"));
@@ -240,7 +286,9 @@ dump_node(struct dump_edit_baton *eb,
                                     SVN_REPOS_DUMPFILE_NODE_ACTION
                                     ": replace\n"));
 
-          eb->dump_props_pending = TRUE;
+          /* Wait for a change_*_prop to be called before dumping
+             anything */          
+          eb->dump_props = TRUE;
           break;
         }
       /* More complex case: is_copy is true, and copyfrom_path/
@@ -257,7 +305,6 @@ dump_node(struct dump_edit_baton *eb,
 
       /* We can leave this routine quietly now, don't need to dump any
          content; that was already done in the second record. */
-      eb->dump_props = FALSE;
       break;
 
     case svn_node_action_delete:
@@ -265,10 +312,10 @@ dump_node(struct dump_edit_baton *eb,
                                 SVN_REPOS_DUMPFILE_NODE_ACTION
                                 ": delete\n"));
 
-      /* We can leave this routine quietly now, don't need to dump
-         any content. */
+      /* We can leave this routine quietly now. Nothing more to do-
+         print a couple of newlines because we're not dumping props or
+         text. */      
       SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
-      eb->dump_props = FALSE;
       break;
 
     case svn_node_action_add:
@@ -277,15 +324,17 @@ dump_node(struct dump_edit_baton *eb,
 
       if (!is_copy)
         {
-          /* eb->dump_props_pending for files is handled in close_file
+          /* eb->dump_props for files is handled in close_file
              which is called immediately.  However, directories are not
              closed until all the work inside them has been done;
-             eb->dump_props_pending for directories is handled in all the
+             eb->dump_props for directories is handled in all the
              functions that can possibly be called after add_directory:
              add_directory, open_directory, delete_entry, close_directory,
              add_file, open_file. change_dir_prop is a special case. */
 
-          eb->dump_props_pending = TRUE;
+          /* Wait for a change_*_prop to be called before dumping
+             anything */          
+          eb->dump_props = TRUE;
           break;
         }
 
@@ -296,19 +345,18 @@ dump_node(struct dump_edit_baton *eb,
                                 ": %s\n",
                                 copyfrom_rev, copyfrom_path));
 
-      /* Ugly hack: If a directory was copied from a previous revision,
-         nothing else can be done, and close_file won't be called to
-         write two blank lines. Write them here otherwise the `svnadmin
-         load` parser will fail. */
+      /* Ugly hack: If a directory was copied from a previous
+         revision, nothing like close_file will be called to write two
+         blank lines. If change_dir_prop is called, props are dumped
+         (along with the necessary PROPS-END\n\n and we're good. So
+         set a dump_newlines here to print the newlines unless
+         change_dir_prop is called next otherwise the `svnadmin load`
+         parser will fail.  */ 
       if (kind == svn_node_dir)
-        SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+        eb->dump_newlines = TRUE;
 
       break;
     }
-
-  /* Dump property headers */
-  SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -345,11 +393,15 @@ delete_entry(const char *path,
   LDR_DBG(("delete_entry %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* Add this path to the deleted_entries of the parent directory
      baton. */
-  apr_hash_set(pb->deleted_entries, path, APR_HASH_KEY_STRING, pb);
+  apr_hash_set(pb->deleted_entries, apr_pstrdup(pb->eb->pool, path),
+               APR_HASH_KEY_STRING, pb);
 
   return SVN_NO_ERROR;
 }
@@ -371,7 +423,10 @@ add_directory(const char *path,
   LDR_DBG(("add_directory %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* This might be a replacement -- is the path already deleted? */
   val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -413,7 +468,10 @@ open_directory(const char *path,
   LDR_DBG(("open_directory %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* If the parent directory has explicit comparison path and rev,
      record the same for this one. */
@@ -442,12 +500,15 @@ close_directory(void *dir_baton,
 
   LDR_DBG(("close_directory %p\n", dir_baton));
 
+  /* Some pending properties to dump? */
+  SVN_ERR(dump_props(eb, &(eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(eb, &(eb->dump_newlines), pool));
+
   /* Create a pool just for iterations to allocate a loop variable */
   iterpool = svn_pool_create(pool);
 
-  /* Some pending properties to dump? */
-  SVN_ERR(dump_props(eb, &(eb->dump_props_pending), TRUE, pool));
-
   /* Dump the deleted directory entries */
   for (hi = apr_hash_first(iterpool, db->deleted_entries); hi;
        hi = apr_hash_next(hi))
@@ -481,7 +542,10 @@ add_file(const char *path,
   LDR_DBG(("add_file %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* This might be a replacement -- is the path already deleted? */
   val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -523,7 +587,10 @@ open_file(const char *path,
   LDR_DBG(("open_file %s\n", path));
 
   /* Some pending properties to dump? */
-  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+  SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+  /* Some pending newlines to dump? */
+  SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
 
   /* If the parent directory has explicit copyfrom path and rev,
      record the same for this one. */
@@ -558,8 +625,8 @@ change_dir_prop(void *parent_baton,
     return SVN_NO_ERROR;
 
   if (value)
-    apr_hash_set(db->eb->props, apr_pstrdup(pool, name),
-                 APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+    apr_hash_set(db->eb->props, apr_pstrdup(db->eb->pool, name),
+                 APR_HASH_KEY_STRING, svn_string_dup(value, db->eb->pool));
   else
     apr_hash_set(db->eb->deleted_props, apr_pstrdup(pool, name),
                  APR_HASH_KEY_STRING, "");
@@ -568,17 +635,21 @@ change_dir_prop(void *parent_baton,
     {
       /* If db->written_out is set, it means that the node information
          corresponding to this directory has already been written: don't
-         do anything; dump_props_pending will take care of dumping the
+         do anything; dump_props will take care of dumping the
          props. If it not, dump the node itself before dumping the
          props. */
 
       SVN_ERR(dump_node(db->eb, db->abspath, svn_node_dir,
                         svn_node_action_change, FALSE, db->copyfrom_path,
                         db->copyfrom_rev, pool));
-
-      SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
       db->written_out = TRUE;
     }
+
+  /* Dump props whether or not the directory has been written
+     out. Then disable printing a couple of extra newlines */
+  SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
+  db->eb->dump_newlines = FALSE;
+
   return SVN_NO_ERROR;
 }
 
@@ -596,16 +667,16 @@ change_file_prop(void *file_baton,
     return SVN_NO_ERROR;
 
   if (value)
-    apr_hash_set(eb->props, apr_pstrdup(pool, name),
-                 APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+    apr_hash_set(eb->props, apr_pstrdup(eb->pool, name),
+                 APR_HASH_KEY_STRING, svn_string_dup(value, eb->pool));
   else
-    apr_hash_set(eb->deleted_props, apr_pstrdup(pool, name),
+    apr_hash_set(eb->deleted_props, apr_pstrdup(eb->pool, name),
                  APR_HASH_KEY_STRING, "");
 
   /* Dump the property headers and wait; close_file might need
      to write text headers too depending on whether
      apply_textdelta is called */
-  eb->dump_props_pending = TRUE;
+  eb->dump_props = TRUE;
 
   return SVN_NO_ERROR;
 }
@@ -680,11 +751,11 @@ close_file(void *file_baton,
 
   LDR_DBG(("close_file %p\n", file_baton));
 
-  /* Some pending properties to dump? */
-  SVN_ERR(dump_props(eb, &(eb->dump_props_pending), FALSE, pool));
+  /* Some pending properties to dump? Dump just the headers- dump the
+     props only after dumping the text headers too (if present) */
+  SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
 
-  /* The prop headers have already been dumped in dump_node; now dump
-     the text headers. */
+  /* Dump the text headers */
   if (eb->dump_text)
     {
       /* Text-delta: true */
@@ -716,7 +787,7 @@ close_file(void *file_baton,
 
   /* Content-length: 1549 */
   /* If both text and props are absent, skip this header */
-  if (eb->dump_props || eb->dump_props_pending)
+  if (eb->dump_props)
     SVN_ERR(svn_stream_printf(eb->stream, pool,
                               SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                               ": %ld\n\n",
@@ -727,17 +798,16 @@ close_file(void *file_baton,
                               ": %ld\n\n",
                               (unsigned long)info->size));
 
-  /* Dump the props; the propstring should have already been
-     written in dump_node or above */
-  if (eb->dump_props || eb->dump_props_pending)
+  /* Dump the props now */
+  if (eb->dump_props)
     {
       SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
                                &(eb->propstring->len)));
 
       /* Cleanup */
-      eb->dump_props = eb->dump_props_pending = FALSE;
-      svn_hash__clear(eb->props, pool);
-      svn_hash__clear(eb->deleted_props, pool);
+      eb->dump_props = FALSE;
+      svn_hash__clear(eb->props, eb->pool);
+      svn_hash__clear(eb->deleted_props, eb->pool);
     }
 
   /* Dump the text */
@@ -758,6 +828,8 @@ close_file(void *file_baton,
       eb->dump_text = FALSE;
     }
 
+  /* Write a couple of blank lines for matching output with `svnadmin
+     dump` */
   SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
 
   return SVN_NO_ERROR;

Modified: subversion/branches/object-model/subversion/svnrdump/dump_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svnrdump/dump_editor.h?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svnrdump/dump_editor.h (original)
+++ subversion/branches/object-model/subversion/svnrdump/dump_editor.h Fri Sep 24 14:02:50 2010
@@ -87,4 +87,12 @@ get_dump_editor(const svn_delta_editor_t
                 svn_stream_t *stream,
                 apr_pool_t *pool);
 
+/**
+ * Normalize the line ending style of the values of properties in @a
+ * rev_props using @a pool for memory allocation.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+                apr_pool_t *pool);
+
 #endif

Modified: subversion/branches/object-model/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svnrdump/load_editor.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/object-model/subversion/svnrdump/load_editor.c Fri Sep 24 14:02:50 2010
@@ -56,6 +56,12 @@ commit_callback(const svn_commit_info_t 
   return SVN_NO_ERROR;
 }
 
+/* See subversion/svnsync/main.c for docstring */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+  return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
 /* Acquire a lock (of sorts) on the repository associated with the
  * given RA SESSION. This lock is just a revprop change attempt in a
  * time-delay loop. This function is duplicated by svnsync in main.c.
@@ -65,14 +71,36 @@ commit_callback(const svn_commit_info_t 
  * applications to avoid duplication.
  */
 static svn_error_t *
-get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+get_lock(const svn_string_t **lock_string_p,
+         svn_ra_session_t *session,
+         apr_pool_t *pool)
 {
   char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
   svn_string_t *mylocktoken, *reposlocktoken;
   apr_status_t apr_err;
+  svn_boolean_t be_atomic;
   apr_pool_t *subpool;
   int i;
 
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
+  if (! be_atomic)
+    {
+      /* Pre-1.7 server.  Can't lock without a race condition.
+         See issue #3546.
+       */
+      svn_error_t *err;
+
+      err = svn_error_create(
+              SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+              _("Target server does not support atomic revision property "
+                "edits; consider upgrading it to 1.7 or using an external "
+                "locking program"));
+      svn_handle_warning2(stderr, err, "svnrdump: ");
+      svn_error_clear(err);
+    }
+
   apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
   if (apr_err)
     return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
@@ -80,10 +108,15 @@ get_lock(svn_ra_session_t *session, apr_
   mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
                                    svn_uuid_generate(pool));
 
+  /* If we succeed, this is what the property will be set to. */
+  *lock_string_p = mylocktoken;
+
   subpool = svn_pool_create(pool);
 
   for (i = 0; i < LOCK_RETRIES; ++i)
     {
+      svn_error_t *err;
+
       svn_pool_clear(subpool);
 
       SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
@@ -106,9 +139,27 @@ get_lock(svn_ra_session_t *session, apr_
         }
       else if (i < LOCK_RETRIES - 1)
         {
+          const svn_string_t *unset = NULL;
+
           /* Except in the very last iteration, try to set the lock. */
-          SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK,
-                                         mylocktoken, subpool));
+          err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                        be_atomic ? &unset : NULL,
+                                        mylocktoken, subpool);
+
+          if (be_atomic && err && is_atomicity_error(err))
+            /* Someone else has the lock.  Let's loop. */
+            svn_error_clear(err);
+          else if (be_atomic && err == SVN_NO_ERROR)
+            /* We have the lock. 
+
+               However, for compatibility with concurrent svnsync's that don't
+               support atomicity, loop anyway to double-check that they haven't
+               overwritten our lock.
+             */
+            continue;
+          else
+            /* Genuine error, or we aren't atomic and need to loop. */
+            SVN_ERR(err);
         }
     }
 
@@ -182,6 +233,7 @@ new_node_record(void **node_baton,
   void *commit_edit_baton;
   char *ancestor_path;
   apr_array_header_t *residual_open_path;
+  char *relpath_compose;
   const char *nb_dirname;
   apr_size_t residual_close_count;
   int i;
@@ -304,8 +356,11 @@ new_node_record(void **node_baton,
         
       for (i = 0; i < residual_open_path->nelts; i ++)
         {
-          SVN_ERR(commit_editor->open_directory(APR_ARRAY_IDX(residual_open_path,
-                                                              i, const char *),
+          relpath_compose =
+            svn_relpath_join(rb->db->relpath,
+                             APR_ARRAY_IDX(residual_open_path, i, const char *),
+                             rb->pool);
+          SVN_ERR(commit_editor->open_directory(relpath_compose,
                                                 rb->db->baton,
                                                 rb->rev - 1,
                                                 rb->pool, &child_baton));
@@ -313,10 +368,7 @@ new_node_record(void **node_baton,
           child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
           child_db->baton = child_baton;
           child_db->depth = rb->db->depth + 1;
-          child_db->relpath = svn_relpath_join(rb->db->relpath,
-                                               APR_ARRAY_IDX(residual_open_path,
-                                                             i, const char *),
-                                               rb->pool);
+          child_db->relpath = relpath_compose;
           child_db->parent = rb->db;
           rb->db = child_db;
         }
@@ -394,8 +446,8 @@ set_revision_property(void *baton,
   else
     /* Special handling for revision 0; this is safe because the
        commit_editor hasn't been created yet. */
-    SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev, name, value,
-                                   rb->pool));
+    SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                    name, NULL, value, rb->pool));
 
   /* Remember any datestamp/ author that passes through (see comment
      in close_revision). */
@@ -419,14 +471,21 @@ set_node_property(void *baton,
   commit_editor = nb->rb->pb->commit_editor;
   pool = nb->rb->pool;
 
-  LDR_DBG(("Applying properties on %p\n", nb->file_baton));
-  if (nb->kind == svn_node_file)
-    SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
-                                            value, pool));
-  else
-    SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
-                                           value, pool));
-
+  switch (nb->kind)
+    {
+    case svn_node_file:
+      LDR_DBG(("Applying properties on %p\n", nb->file_baton));
+      SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
+                                              value, pool));
+      break;
+    case svn_node_dir:
+      LDR_DBG(("Applying properties on %p\n", nb->rb->db->baton));
+      SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
+                                             value, pool));
+      break;
+    default:
+      break;
+    }
   return SVN_NO_ERROR;
 }
 
@@ -552,12 +611,12 @@ close_revision(void *baton)
 
   /* svn_fs_commit_txn rewrites the datestamp/ author property-
      rewrite it by hand after closing the commit_editor. */
-  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
-                                 SVN_PROP_REVISION_DATE,
-                                 rb->datestamp, rb->pool));
-  SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
-                                 SVN_PROP_REVISION_AUTHOR,
-                                 rb->author, rb->pool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                  SVN_PROP_REVISION_DATE,
+                                  NULL, rb->datestamp, rb->pool));
+  SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+                                  SVN_PROP_REVISION_AUTHOR,
+                                  NULL, rb->author, rb->pool));
 
   svn_pool_destroy(rb->pool);
 
@@ -602,14 +661,25 @@ drive_dumpstream_loader(svn_stream_t *st
                         svn_ra_session_t *session,
                         apr_pool_t *pool)
 {
-  struct parse_baton *pb;
-  pb = parse_baton;
+  struct parse_baton *pb = parse_baton;
+  const svn_string_t *lock_string;
+  svn_boolean_t be_atomic;
+  svn_error_t *err;
+
+  SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+                                pool));
 
-  SVN_ERR(get_lock(session, pool));
+  SVN_ERR(get_lock(&lock_string, session, pool));
   SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
   SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
                                       NULL, NULL, pool));
-  SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, NULL, pool));
+  err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+                                 be_atomic ? &lock_string : NULL, NULL, pool);
+  if (is_atomicity_error(err))
+    return svn_error_quick_wrap(err,
+                                _("\"svnrdump load\"'s lock was stolen; "
+                                  "can't remove it"));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/object-model/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/svnrdump/svnrdump.c?rev=1000876&r1=1000875&r2=1000876&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/object-model/subversion/svnrdump/svnrdump.c Fri Sep 24 14:02:50 2010
@@ -137,6 +137,7 @@ replay_revstart(svn_revnum_t revision,
   SVN_ERR(svn_stream_printf(stdout_stream, pool,
                             SVN_REPOS_DUMPFILE_REVISION_NUMBER
                             ": %ld\n", revision));
+  SVN_ERR(normalize_props(rev_props, pool));
   propstring = svn_stringbuf_create_ensure(0, pool);
   revprop_stream = svn_stream_from_stringbuf(propstring, pool);
   SVN_ERR(svn_hash_write2(rev_props, revprop_stream, "PROPS-END", pool));