You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by jc...@apache.org on 2010/12/29 01:10:29 UTC

svn commit: r1053489 [4/7] - in /subversion/branches/diff-optimizations-bytes: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ contrib/client-side/svn_load_dirs/ notes/ subversion/bindings/javahl/native/ subversion/bindings/swig/ subv...

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.c Wed Dec 29 00:10:25 2010
@@ -277,13 +277,6 @@ read_info(svn_wc__db_status_t *status,
           apr_pool_t *result_pool,
           apr_pool_t *scratch_pool);
 
-#ifndef SVN_WC__OP_DEPTH
-static svn_error_t *
-elide_copyfrom(svn_wc__db_pdh_t *pdh,
-               const char *local_relpath,
-               apr_pool_t *scratch_pool);
-#endif
-
 static svn_error_t *
 scan_addition(svn_wc__db_status_t *status,
               const char **op_root_relpath,
@@ -310,6 +303,14 @@ static svn_error_t *
 convert_to_working_status(svn_wc__db_status_t *working_status,
                           svn_wc__db_status_t status);
 
+static svn_error_t *
+wclock_owns_lock(svn_boolean_t *own_lock,
+                 svn_wc__db_pdh_t *pdh,
+                 const char *local_relpath,
+                 svn_boolean_t exact,
+                 apr_pool_t *scratch_pool);
+
+
 /* 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,
@@ -1251,73 +1252,6 @@ which_trees_exist(svn_boolean_t *base_ex
 }
 
 
-/* Determine which trees' nodes exist for a given LOCAL_RELPATH in the
-   specified SDB.
-
-   Note: this is VERY similar to the above which_trees_exist() except that
-   we return a WC_ID and verify some additional constraints.  */
-static svn_error_t *
-prop_upgrade_trees(svn_boolean_t *base_exists,
-                   svn_wc__db_status_t *base_presence,
-                   svn_boolean_t *working_exists,
-                   svn_wc__db_status_t *work_presence,
-                   apr_int64_t *wc_id,
-                   svn_sqlite__db_t *sdb,
-                   const char *local_relpath)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  *base_exists = FALSE;
-  *working_exists = FALSE;
-
-  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));
-
-  /* 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.  */
-  SVN_ERR_ASSERT(have_row);
-
-  /* Use the first column to detect which table this row came from.  */
-  if (svn_sqlite__column_int(stmt, 0))
-    {
-      *working_exists = TRUE;  /* value == 1  */
-      *work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
-    }
-  else
-    {
-      *base_exists = TRUE;  /* value == 0  */
-      *base_presence = svn_sqlite__column_token(stmt, 1, presence_map);
-    }
-
-  /* Return the WC_ID that was assigned.  */
-  *wc_id = svn_sqlite__column_int64(stmt, 2);
-
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  if (have_row)
-    {
-      /* If both rows, then both tables.  */
-      *base_exists = TRUE;
-      *working_exists = TRUE;
-
-      /* If the second row came from WORKING_NODE, then we should also
-         fetch the 'presence' column value.  */
-      if (svn_sqlite__column_int(stmt, 0))
-        *work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
-      else
-        *base_presence = svn_sqlite__column_token(stmt, 1, presence_map);
-
-      /* During an upgrade, there should be just one working copy, so both
-         rows should refer to the same value.  */
-      SVN_ERR_ASSERT(*wc_id == svn_sqlite__column_int64(stmt, 2));
-    }
-
-  return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
 /* */
 static svn_error_t *
 create_db(svn_sqlite__db_t **sdb,
@@ -3127,11 +3061,6 @@ db_op_copy(svn_wc__db_pdh_t *src_pdh,
                             scratch_pool));
     }
 
-#ifndef SVN_WC__OP_DEPTH
-  /* ### Should do this earlier and insert the node with the right values. */
-  SVN_ERR(elide_copyfrom(dst_pdh, dst_relpath, scratch_pool));
-#endif
-
   SVN_ERR(add_work_items(dst_pdh->wcroot->sdb, work_items, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -3238,7 +3167,6 @@ op_depth_for_copy(apr_int64_t *op_depth,
                   const char *local_relpath,
                   apr_pool_t *scratch_pool)
 {
-#ifdef SVN_WC__OP_DEPTH
   const char *parent_relpath, *name;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
@@ -3294,9 +3222,6 @@ op_depth_for_copy(apr_int64_t *op_depth,
     }
   SVN_ERR(svn_sqlite__reset(stmt));
   
-#else
-  *op_depth = 2; /* temporary op_depth */
-#endif
   return SVN_NO_ERROR;
 }
 
@@ -3547,11 +3472,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;
-#ifdef SVN_WC__OP_DEPTH
   iwb.op_depth = relpath_depth(local_relpath);
-#else
-  iwb.op_depth = 2;  /* ### temporary op_depth */
-#endif
 
   iwb.work_items = work_items;
 
@@ -3587,11 +3508,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;
-#ifdef SVN_WC__OP_DEPTH
   iwb.op_depth = relpath_depth(local_relpath);
-#else
-  iwb.op_depth = 2;  /* ### temporary op_depth */
-#endif
 
   iwb.work_items = work_items;
 
@@ -3629,11 +3546,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;
-#ifdef SVN_WC__OP_DEPTH
   iwb.op_depth = relpath_depth(local_relpath);
-#else
-  iwb.op_depth = 2;  /* ### temporary op_depth */
-#endif
 
   iwb.target = target;
 
@@ -4487,7 +4400,6 @@ db_working_update_presence(apr_int64_t o
     {
       /* Switching to base-deleted is undoing an add/copy.  By this
          stage an add will have no children. */
-#ifdef SVN_WC__OP_DEPTH
       const apr_array_header_t *children;
       apr_pool_t *iterpool;
       int i;
@@ -4526,14 +4438,6 @@ db_working_update_presence(apr_int64_t o
             SVN_ERR(db_working_actual_remove(pdh, child_relpath, iterpool));
         }
       svn_pool_destroy(iterpool);
-#else
-      /* If this was a copy then any children of the copy will now be
-         not-present and should be removed. */
-      SVN_ERR(remove_children(pdh, local_relpath,
-                              svn_wc__db_status_not_present,
-                              2 /* ### temporary op_depth */,
-                              scratch_pool));
-#endif
 
       /* Reset the copyfrom in case this was a copy.
          ### What else should be reset? Properties? Or copy the node again? */
@@ -4589,10 +4493,6 @@ db_working_actual_remove(svn_wc__db_pdh_
   SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-#ifndef SVN_WC__OP_DEPTH
-  SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_not_present,
-                          2 /* ### temporary op_depth */, scratch_pool));
-#else
   SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_base_deleted,
                           op_depth + 1, scratch_pool));
   SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_normal,
@@ -4601,7 +4501,6 @@ db_working_actual_remove(svn_wc__db_pdh_
                           op_depth, scratch_pool));
   SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_incomplete,
                           op_depth, scratch_pool));
-#endif
 
   /* Postcondition: There are no NODES rows in this subtree, at same or
    * greater op_depth. */
@@ -4645,25 +4544,15 @@ db_working_insert(svn_wc__db_status_t st
                   apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
-#ifdef SVN_WC__OP_DEPTH
   const char *like_arg = construct_like_arg(local_relpath, scratch_pool);
   apr_int64_t op_depth = relpath_depth(local_relpath);
-#else
-  apr_int64_t op_depth = 2; /* ### temporary op_depth */
-#endif
 
-#ifdef SVN_WC__OP_DEPTH
   SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
                                     STMT_INSERT_WORKING_NODE_FROM_NODE));
-#else
-  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_INSERT_WORKING_NODE_FROM_BASE));
-#endif
   SVN_ERR(svn_sqlite__bindf(stmt, "isit", pdh->wcroot->wc_id,
                             local_relpath, op_depth, presence_map, status));
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
-#ifdef SVN_WC__OP_DEPTH
   /* Need to update the op_depth of all deleted child trees -- this
      relies on the recursion having already deleted the trees so
      that they are all at op_depth+1.
@@ -4678,7 +4567,6 @@ db_working_insert(svn_wc__db_status_t st
   SVN_ERR(svn_sqlite__bindf(stmt, "isi",
                             pdh->wcroot->wc_id, like_arg, op_depth));
   SVN_ERR(svn_sqlite__update(NULL, stmt));
-#endif
 
   return SVN_NO_ERROR;
 }
@@ -4867,9 +4755,6 @@ temp_op_delete_txn(void *baton, svn_sqli
   struct temp_op_delete_baton *b = baton;
   svn_wc__db_status_t status, new_working_status;
   svn_boolean_t have_work, add_work = FALSE, del_work = FALSE, mod_work = FALSE;
-#ifndef SVN_WC__OP_DEPTH
-  svn_boolean_t new_have_work;
-#endif
 
   SVN_ERR(read_info(&status,
                     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -4879,23 +4764,13 @@ temp_op_delete_txn(void *baton, svn_sqli
                     b->pdh, b->local_relpath,
                     scratch_pool, scratch_pool));
 
-#ifndef SVN_WC__OP_DEPTH
-  new_have_work = have_work;
-  new_working_status = status;
-#endif
-
   if (!have_work)
     {
       /* No structural changes  */
       if (status == svn_wc__db_status_normal
           || status == svn_wc__db_status_incomplete)
         {
-#ifdef SVN_WC__OP_DEPTH
           add_work = TRUE;
-#else
-          new_have_work = TRUE;
-          new_working_status = svn_wc__db_status_base_deleted;
-#endif
         }
     }
   else if (status == svn_wc__db_status_added)
@@ -4913,26 +4788,15 @@ temp_op_delete_txn(void *baton, svn_sqli
           SVN_ERR(info_below_working(&below_base, &below_work, &below_status,
                                      b->pdh, b->local_relpath, scratch_pool));
 
-#ifdef SVN_WC__OP_DEPTH
           if ((below_base || below_work)
               && below_status != svn_wc__db_status_not_present)
             mod_work = TRUE;
           else
             del_work = TRUE;
-#else
-          if (below_base && below_status != svn_wc__db_status_not_present)
-            new_working_status = svn_wc__db_status_base_deleted;
-          else
-            new_have_work = FALSE;
-#endif
         }
       else
         {
-#ifdef SVN_WC__OP_DEPTH
           add_work = TRUE;
-#else
-          new_working_status = svn_wc__db_status_not_present;
-#endif
         }
     }
   else if (status == svn_wc__db_status_incomplete)
@@ -4940,23 +4804,12 @@ temp_op_delete_txn(void *baton, svn_sqli
       svn_boolean_t add_or_root_of_copy;
       SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
                                      b->pdh, b->local_relpath, scratch_pool));
-#ifdef SVN_WC__OP_DEPTH
       if (add_or_root_of_copy)
         del_work = TRUE;
       else
         add_work = TRUE;
-#else
-      if (add_or_root_of_copy)
-        new_have_work = FALSE;
-#endif
     }
 
-#ifndef SVN_WC__OP_DEPTH
-  del_work = !new_have_work && have_work;
-  add_work = new_have_work && !have_work;
-  mod_work = new_have_work && have_work && new_working_status != status;
-#endif
-
   if (del_work)
     {
       SVN_ERR(db_working_actual_remove(b->pdh, b->local_relpath, scratch_pool));
@@ -4967,17 +4820,13 @@ temp_op_delete_txn(void *baton, svn_sqli
     }
   else if (add_work)
     {
-#ifdef SVN_WC__OP_DEPTH
       new_working_status = svn_wc__db_status_base_deleted;
-#endif
       SVN_ERR(db_working_insert(new_working_status, b->pdh, b->local_relpath,
                                 scratch_pool));
     }
   else if (mod_work)
     {
-#ifdef SVN_WC__OP_DEPTH
       new_working_status = svn_wc__db_status_base_deleted;
-#endif
       SVN_ERR(db_working_update_presence(relpath_depth(b->local_relpath),
                                          new_working_status, b->pdh,
                                          b->local_relpath, scratch_pool));
@@ -5253,8 +5102,7 @@ read_info(svn_wc__db_status_t *status,
               op_depth = svn_sqlite__column_int64(stmt_info, 0);
             }
 
-          if (have_base)
-            *have_base = (op_depth == 0);
+          *have_base = (op_depth == 0);
         }
     }
   else if (have_act)
@@ -5605,6 +5453,61 @@ svn_wc__db_read_children_info(apr_hash_t
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__db_read_children_walker_info(apr_hash_t **nodes,
+                                     svn_wc__db_t *db,
+                                     const char *dir_abspath,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *dir_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_int64_t op_depth;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &dir_relpath, db,
+                                             dir_abspath,
+                                             svn_sqlite__mode_readonly,
+                                             scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_SELECT_NODE_CHILDREN_WALKER_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, dir_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  *nodes = apr_hash_make(result_pool);
+  while (have_row)
+    {
+      struct svn_wc__db_walker_info_t *child;
+      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *name = svn_relpath_basename(child_relpath, NULL);
+      svn_error_t *err;
+
+      child = apr_hash_get(*nodes, name, APR_HASH_KEY_STRING);
+      if (child == NULL)
+        child = apr_palloc(result_pool, sizeof(*child));
+
+      op_depth = svn_sqlite__column_int(stmt, 1);
+      child->status = svn_sqlite__column_token(stmt, 2, presence_map);
+      if (op_depth > 0)
+        SVN_ERR(convert_to_working_status(&child->status, child->status));
+      child->kind = svn_sqlite__column_token(stmt, 3, kind_map);
+      apr_hash_set(*nodes, apr_pstrdup(result_pool, name),
+                   APR_HASH_KEY_STRING, child);
+
+      err = svn_sqlite__step(&have_row, stmt);
+      if (err)
+        SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+    }
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc__db_read_prop(const svn_string_t **propval,
@@ -6403,35 +6306,15 @@ struct record_baton {
 };
 
 
-/* Record TRANSLATED_SIZE and LAST_MOD_TIME into the WORKING tree if a
-   node is present; otherwise, record it into the BASE tree. One of them
-   must exist.  */
+/* Record TRANSLATED_SIZE and LAST_MOD_TIME into top layer in NODES */
 static svn_error_t *
 record_fileinfo(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
 {
   struct record_baton *rb = baton;
-  svn_boolean_t base_exists;
-  svn_boolean_t working_exists;
   svn_sqlite__stmt_t *stmt;
   int affected_rows;
 
-  SVN_ERR(which_trees_exist(&base_exists, &working_exists,
-                            sdb, rb->wcroot->wc_id, rb->local_relpath));
-  if (!base_exists && !working_exists)
-    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                             _("Could not find node '%s' for recording file "
-                               "information."),
-                             path_for_error_message(rb->wcroot,
-                                                    rb->local_relpath,
-                                                    scratch_pool));
-
-  /* ### Instead of doing it this way, we just ought to update the highest
-     op_depth level. That way, there's no need to find out which
-     tree to update first */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                    working_exists
-                                      ? STMT_UPDATE_WORKING_NODE_FILEINFO
-                                      : STMT_UPDATE_BASE_NODE_FILEINFO));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_NODE_FILEINFO));
   SVN_ERR(svn_sqlite__bindf(stmt, "isii",
                             rb->wcroot->wc_id, rb->local_relpath,
                             rb->translated_size, rb->last_mod_time));
@@ -6610,10 +6493,6 @@ scan_addition(svn_wc__db_status_t *statu
   const char *current_relpath = local_relpath;
   const char *build_relpath = "";
   svn_wc__db_wcroot_t *wcroot = pdh->wcroot;
-#ifndef SVN_WC__OP_DEPTH
-  svn_boolean_t found_info = FALSE;
-  const char *child_relpath = NULL;
-#endif
 
   /* Initialize most of the OUT parameters. Generally, we'll only be filling
      in a subset of these, so it is easier to init all up front. Note that
@@ -6628,125 +6507,6 @@ scan_addition(svn_wc__db_status_t *statu
   if (original_revision)
     *original_revision = SVN_INVALID_REVNUM;
 
-
-#ifndef SVN_WC__OP_DEPTH
-  while (TRUE)
-    {
-      svn_sqlite__stmt_t *stmt;
-      svn_boolean_t have_row;
-      svn_wc__db_status_t presence;
-
-      /* ### is it faster to fetch fewer columns? */
-      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));
-
-      if (!have_row)
-        {
-          /* Reset statement before (optionally) returning */
-          SVN_ERR(svn_sqlite__reset(stmt));
-
-          if (current_relpath == local_relpath)
-            /* ### maybe we should return a usage error instead?  */
-            return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                                     _("The node '%s' was not found."),
-                                     path_for_error_message(wcroot,
-                                                            local_relpath,
-                                                            scratch_pool));
-
-          /* We just fell off the top of the WORKING tree. If we haven't
-             found the operation root, then the child node that we just
-             left was that root.  */
-          if (op_root_relpath && *op_root_relpath == NULL)
-            {
-              SVN_ERR_ASSERT(child_relpath != NULL);
-              *op_root_relpath = apr_pstrdup(result_pool, child_relpath);
-            }
-
-          /* This node was added/copied/moved and has an implicit location
-             in the repository. We now need to traverse BASE nodes looking
-             for repository info.  */
-          break;
-        }
-
-      presence = svn_sqlite__column_token(stmt, 1, presence_map);
-
-      /* Record information from the starting node.  */
-      if (current_relpath == local_relpath)
-        {
-          /* The starting node should exist normally.  */
-          if (presence != svn_wc__db_status_normal)
-            return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
-                                     svn_sqlite__reset(stmt),
-                                     _("Expected node '%s' to be added."),
-                                     path_for_error_message(wcroot,
-                                                            local_relpath,
-                                                            scratch_pool));
-
-          /* Provide the default status; we'll override as appropriate. */
-          if (status)
-            *status = svn_wc__db_status_added;
-        }
-
-      /* We want the operation closest to the start node, and then we
-         ignore any operations on its ancestors.  */
-      if (!found_info
-          && presence == svn_wc__db_status_normal
-          && !svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
-        {
-          if (status)
-            {
-              if (svn_sqlite__column_boolean(stmt, 13 /* moved_here */))
-                *status = svn_wc__db_status_moved_here;
-              else
-                *status = svn_wc__db_status_copied;
-            }
-          if (op_root_relpath)
-            *op_root_relpath = apr_pstrdup(result_pool, current_relpath);
-          if (original_repos_relpath)
-            *original_repos_relpath = svn_sqlite__column_text(stmt, 11,
-                                                              result_pool);
-          if (original_repos_id)
-            *original_repos_id = svn_sqlite__column_int64(stmt, 10);
-          if (original_revision)
-            *original_revision = svn_sqlite__column_revnum(stmt, 12);
-
-          /* We may have to keep tracking upwards for REPOS_* values.
-             If they're not needed, then just return.  */
-          if (repos_relpath == NULL
-              && repos_id == NULL)
-            return svn_error_return(svn_sqlite__reset(stmt));
-
-          /* We've found the info we needed. Scan for the top of the
-             WORKING tree, and then the REPOS_* information.  */
-          found_info = TRUE;
-        }
-
-      SVN_ERR(svn_sqlite__reset(stmt));
-
-      /* If the caller wants to know the starting node's REPOS_RELPATH,
-         then keep track of what we're stripping off the ABSPATH as we
-         traverse up the tree.  */
-      if (repos_relpath)
-        {
-          build_relpath = svn_relpath_join(svn_dirent_basename(current_relpath,
-                                                               NULL),
-                                           build_relpath,
-                                           scratch_pool);
-        }
-
-      /* Move to the parent node. Remember the abspath to this node, since
-         it could be the root of an add/delete.  */
-      child_relpath = current_relpath;
-
-      /* The wcroot can't have a restructuring operation; make sure we don't
-         loop on invalid data */
-      SVN_ERR_ASSERT(current_relpath[0] != '\0');
-
-      current_relpath = svn_relpath_dirname(current_relpath, scratch_pool);
-    }
-#else  /* ifdef SVN_WC__OP_DEPTH */
   {
     svn_sqlite__stmt_t *stmt;
     svn_boolean_t have_row;
@@ -6910,7 +6670,7 @@ scan_addition(svn_wc__db_status_t *statu
 
     build_relpath = repos_prefix_path;
   }
-#endif
+
   /* If we're here, then we have an added/copied/moved (start) node, and
      CURRENT_ABSPATH now points to a BASE node. Figure out the repository
      information for the current node, and use that to compute the start
@@ -7031,9 +6791,7 @@ scan_deletion(const char **base_del_relp
   svn_boolean_t child_has_base = FALSE;
   svn_boolean_t found_moved_to = FALSE;
   svn_wc__db_wcroot_t *wcroot = pdh->wcroot;
-#ifdef SVN_WC__OP_DEPTH
   apr_int64_t local_op_depth, op_depth;
-#endif
 
   /* Initialize all the OUT parameters.  */
   if (base_del_relpath != NULL)
@@ -7181,7 +6939,6 @@ scan_deletion(const char **base_del_relp
                                     svn_sqlite__column_text(stmt, 2, NULL));
         }
 
-#ifdef SVN_WC__OP_DEPTH
       op_depth = svn_sqlite__column_int64(stmt, 3);
       if (current_relpath == local_relpath)
         local_op_depth = op_depth;
@@ -7189,13 +6946,6 @@ scan_deletion(const char **base_del_relp
       if (work_del_relpath && !work_del_relpath[0]
           && ((op_depth < local_op_depth && op_depth > 0)
               || child_presence == svn_wc__db_status_not_present))
-#else
-      if (work_del_relpath != NULL
-          && work_presence == svn_wc__db_status_normal
-          && child_presence == svn_wc__db_status_not_present)
-          /* Parent is normal, but child was deleted. Therefore, the child
-             is the root of a WORKING subtree deletion.  */
-#endif
         {
           *work_del_relpath = apr_pstrdup(result_pool, child_relpath);
         }
@@ -7340,12 +7090,10 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
                                int original_format,
                                apr_pool_t *scratch_pool)
 {
-  svn_boolean_t have_base;
-  svn_wc__db_status_t base_presence;
-  svn_boolean_t have_work;
-  svn_wc__db_status_t work_presence;
-  apr_int64_t wc_id;
   svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_int64_t wc_id, top_op_depth = -1, below_op_depth = -1;
+  svn_wc__db_status_t top_presence, below_presence;
   int affected_rows;
 
   /* ### working_props: use set_props_txn.
@@ -7375,19 +7123,31 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
      the handling of our inputs, relative to the state of this node.
   */
 
-  /* Collect information about this node.  */
-  SVN_ERR(prop_upgrade_trees(&have_base, &base_presence,
-                             &have_work, &work_presence,
-                             &wc_id, sdb, local_relpath));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_UPGRADE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "s", local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    {
+      top_op_depth = svn_sqlite__column_int64(stmt, 0);
+      top_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+      wc_id = svn_sqlite__column_int64(stmt, 2);
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+      if (have_row)
+        {
+          below_op_depth = svn_sqlite__column_int64(stmt, 0);
+          below_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+        }
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
 
   /* Detect the buggy scenario described above. We cannot upgrade this
      working copy if we have no idea where BASE_PROPS should go.  */
   if (original_format > SVN_WC__NO_REVERT_FILES
       && revert_props == NULL
-      && have_work
-      && work_presence == svn_wc__db_status_normal
-      && have_base
-      && base_presence != svn_wc__db_status_not_present)
+      && top_op_depth != -1
+      && top_presence == svn_wc__db_status_normal
+      && below_op_depth != -1
+      && below_presence != svn_wc__db_status_not_present)
     {
       /* There should be REVERT_PROPS, so it appears that we just ran into
          the described bug. Sigh.  */
@@ -7400,48 +7160,45 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
                                                  scratch_pool), scratch_pool));
     }
 
-  if (have_base
-      && (base_presence == svn_wc__db_status_normal
-          || base_presence == svn_wc__db_status_incomplete))
-    {
-      apr_hash_t *props = revert_props ? revert_props : base_props;
+  /* Need at least one row, or two rows if there are revert props */
+  if (top_op_depth == -1
+      || (below_op_depth == -1 && revert_props))
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                             _("Insufficient NODES rows for '%s'"),
+                             svn_dirent_local_style(
+                               svn_dirent_join(dir_abspath, local_relpath,
+                                               scratch_pool), scratch_pool));
+
+  /* one row, base props only: upper row gets base props
+     two rows, base props only: lower row gets base props
+     two rows, revert props only: lower row gets revert props
+     two rows, base and revert props: upper row gets base, lower gets revert */
+
 
+  if (revert_props || below_op_depth == -1)
+    {
       SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                        STMT_UPDATE_NODE_BASE_PROPS));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
-      SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
+                                        STMT_UPDATE_NODE_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isi",
+                                wc_id, local_relpath, top_op_depth));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool));
       SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
-      /* ### should we provide a nicer error message?  */
       SVN_ERR_ASSERT(affected_rows == 1);
     }
 
-  if (have_work)
+  if (below_op_depth != -1)
     {
-      /* WORKING_NODE has very limited 'presence' values.  */
-      SVN_ERR_ASSERT(work_presence == svn_wc__db_status_normal
-                     || work_presence == svn_wc__db_status_not_present
-                     || work_presence == svn_wc__db_status_base_deleted
-                     || work_presence == svn_wc__db_status_incomplete);
+      apr_hash_t *props = revert_props ? revert_props : base_props;
 
-      /* Do we have a replaced node? It has properties: an empty set for
-         adds, and a non-empty set for copies/moves.  */
-      if (original_format > SVN_WC__NO_REVERT_FILES
-          && (work_presence == svn_wc__db_status_normal
-              || work_presence == svn_wc__db_status_incomplete))
-        {
-          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                            STMT_UPDATE_NODE_WORKING_PROPS));
-          SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
-          SVN_ERR(svn_sqlite__bind_properties(stmt, 3, base_props,
-                                              scratch_pool));
-          SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                        STMT_UPDATE_NODE_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "isi",
+                                wc_id, local_relpath, below_op_depth));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
+      SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
-          /* ### should we provide a nicer error message?  */
-          SVN_ERR_ASSERT(affected_rows == 1);
-        }
-      /* else other states should have no properties.  */
-      /* ### should we insert empty props for <= SVN_WC__NO_REVERT_FILES?  */
+      SVN_ERR_ASSERT(affected_rows == 1);
     }
 
   /* If there are WORKING_PROPS, then they always go into ACTUAL_NODE.  */
@@ -8195,7 +7952,6 @@ svn_wc__db_temp_wcroot_tempdir(const cha
 /* Baton for wclock_obtain_cb() */
 struct wclock_obtain_baton
 {
-  svn_wc__db_t *db;
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
   int levels_to_lock;
@@ -8269,7 +8025,6 @@ wclock_obtain_cb(void *baton,
 
   while (got_row)
     {
-      const char *lock_abspath;
       svn_boolean_t own_lock;
 
       lock_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
@@ -8283,13 +8038,10 @@ wclock_obtain_cb(void *baton,
           continue;
         }
 
-      lock_abspath = svn_dirent_join(wcroot->abspath,
-                                     lock_relpath, scratch_pool);
-
       /* Check if we are the lock owner, because we should be able to
          extend our lock. */
-      err = svn_wc__db_wclock_owns_lock(&own_lock, bt->db, lock_abspath,
-                                        TRUE, scratch_pool);
+      err = wclock_owns_lock(&own_lock, bt->pdh, lock_relpath,
+                             TRUE, scratch_pool);
 
       if (err)
         SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
@@ -8299,7 +8051,7 @@ wclock_obtain_cb(void *baton,
           SVN_ERR(svn_sqlite__reset(stmt));
           err = svn_error_createf(SVN_ERR_WC_LOCKED, NULL,
                                    _("'%s' is already locked."),
-                                   svn_dirent_local_style(lock_abspath,
+                                   path_for_error_message(wcroot, lock_relpath,
                                                           scratch_pool));
           return svn_error_createf(SVN_ERR_WC_LOCKED, err,
                                    _("Working copy '%s' locked."),
@@ -8426,22 +8178,16 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
                   || (lock->levels + relpath_depth(lock->local_relpath))
                             >= depth))
             {
-              const char *lock_abspath
-                  = svn_dirent_join(baton.pdh->wcroot->abspath,
-                                    lock->local_relpath,
-                                    scratch_pool);
-
-              return svn_error_createf(SVN_ERR_WC_LOCKED, NULL,
-                                       _("'%s' is already locked via '%s'."),
-                                       svn_dirent_local_style(local_abspath,
-                                                              scratch_pool),
-                                       svn_dirent_local_style(lock_abspath,
-                                                              scratch_pool));
+              return svn_error_createf(
+                SVN_ERR_WC_LOCKED, NULL,
+                _("'%s' is already locked via '%s'."),
+                svn_dirent_local_style(local_abspath, scratch_pool),
+                path_for_error_message(baton.pdh->wcroot, lock->local_relpath,
+                                       scratch_pool));
             }
         }
     }
 
-  baton.db = db;
   baton.steal_lock = steal_lock;
   baton.levels_to_lock = levels_to_lock;
 
@@ -8570,29 +8316,18 @@ svn_wc__db_wclock_release(svn_wc__db_t *
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_wc__db_wclock_owns_lock(svn_boolean_t *own_lock,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            svn_boolean_t exact,
-                            apr_pool_t *scratch_pool)
+/* Like svn_wc__db_wclock_owns_lock() but taking PDH+LOCAL_RELPATH instead
+ * of DB+LOCAL_ABSPATH. */
+static svn_error_t *
+wclock_owns_lock(svn_boolean_t *own_lock,
+                 svn_wc__db_pdh_t *pdh,
+                 const char *local_relpath,
+                 svn_boolean_t exact,
+                 apr_pool_t *scratch_pool)
 {
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
   apr_array_header_t *owned_locks;
   int lock_level, i;
 
-  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
-                              local_abspath, svn_sqlite__mode_readwrite,
-                              scratch_pool, scratch_pool));
-
-  if (!pdh->wcroot)
-    return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
-                             _("The node '%s' was not found."),
-                             svn_dirent_local_style(local_abspath,
-                                                    scratch_pool));
-
-  VERIFY_USABLE_PDH(pdh);
   *own_lock = FALSE;
   owned_locks = pdh->wcroot->owned_locks;
   lock_level = relpath_depth(local_relpath);
@@ -8629,6 +8364,33 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
 }
 
 svn_error_t *
+svn_wc__db_wclock_owns_lock(svn_boolean_t *own_lock,
+                            svn_wc__db_t *db,
+                            const char *local_abspath,
+                            svn_boolean_t exact,
+                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              local_abspath, svn_sqlite__mode_readwrite,
+                              scratch_pool, scratch_pool));
+
+  if (!pdh->wcroot)
+    return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+                             _("The node '%s' was not found."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  VERIFY_USABLE_PDH(pdh);
+
+  SVN_ERR(wclock_owns_lock(own_lock, pdh, local_relpath, exact, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_wc__db_temp_op_set_base_incomplete(svn_wc__db_t *db,
                                        const char *local_dir_abspath,
                                        svn_boolean_t incomplete,
@@ -8792,11 +8554,7 @@ make_copy_txn(void *baton,
   struct make_copy_baton *mcb = baton;
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-#ifdef SVN_WC__OP_DEPTH
   svn_boolean_t add_working_base_deleted = FALSE;
-#else
-  svn_boolean_t add_working = TRUE;
-#endif
   svn_boolean_t remove_working = FALSE;
   const apr_array_header_t *children;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -8824,11 +8582,7 @@ make_copy_txn(void *baton,
         /* Make existing deletions of BASE_NODEs remove WORKING_NODEs */
         remove_working = TRUE;
 
-#ifdef SVN_WC__OP_DEPTH
       add_working_base_deleted = TRUE;
-#else
-      add_working = FALSE;
-#endif
     }
   else
     SVN_ERR(svn_sqlite__reset(stmt));
@@ -8869,7 +8623,6 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__step_done(stmt));
     }
 
-#ifdef SVN_WC__OP_DEPTH
   if (add_working_base_deleted)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
@@ -8882,9 +8635,6 @@ make_copy_txn(void *baton,
       SVN_ERR(svn_sqlite__step_done(stmt));
     }
   else
-#else
-  if (add_working)
-#endif
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                       STMT_INSERT_WORKING_NODE_FROM_BASE_COPY));
@@ -8940,11 +8690,7 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
 
   mcb.db = db;
   mcb.local_abspath = local_abspath;
-#ifdef SVN_WC__OP_DEPTH
   mcb.op_depth = relpath_depth(mcb.local_relpath);
-#else
-  mcb.op_depth = 2;  /* ### temporary op_depth */
-#endif
 
   SVN_ERR(svn_sqlite__with_transaction(mcb.pdh->wcroot->sdb,
                                        make_copy_txn, &mcb,
@@ -8953,168 +8699,6 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
   return SVN_NO_ERROR;
 }
 
-#ifndef SVN_WC__OP_DEPTH
-/* Return the copyfrom info for LOCAL_ABSPATH resolving inheritance. */
-static svn_error_t *
-get_copyfrom(apr_int64_t *copyfrom_repos_id,
-             const char **copyfrom_relpath,
-             svn_revnum_t *copyfrom_revnum,
-             svn_wc__db_pdh_t *pdh,
-             const char *local_relpath,
-             apr_pool_t *result_pool,
-             apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  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));
-  if (!have_row)
-    {
-      *copyfrom_repos_id = INVALID_REPOS_ID;
-      *copyfrom_relpath = NULL;
-      *copyfrom_revnum = SVN_INVALID_REVNUM;
-      SVN_ERR(svn_sqlite__reset(stmt));
-      return SVN_NO_ERROR;
-    }
-
-  if (svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
-    {
-      /* Resolve inherited copyfrom */
-      const char *parent_relpath, *name, *parent_copyfrom_relpath;
-
-      SVN_ERR(svn_sqlite__reset(stmt));
-      svn_relpath_split(&parent_relpath, &name, local_relpath, scratch_pool);
-      SVN_ERR(get_copyfrom(copyfrom_repos_id, &parent_copyfrom_relpath,
-                           copyfrom_revnum,
-                           pdh, parent_relpath, scratch_pool, scratch_pool));
-      if (parent_copyfrom_relpath)
-        *copyfrom_relpath = svn_relpath_join(parent_copyfrom_relpath, name,
-                                             result_pool);
-      else
-        *copyfrom_relpath = NULL;
-      return SVN_NO_ERROR;
-    }
-
-  *copyfrom_repos_id = svn_sqlite__column_int64(stmt, 10);
-  *copyfrom_relpath = svn_sqlite__column_text(stmt, 11, result_pool);
-  *copyfrom_revnum = svn_sqlite__column_revnum(stmt, 12);
-
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  return SVN_NO_ERROR;
-}
-#endif
-
-
-#ifndef SVN_WC__OP_DEPTH
-static svn_error_t *
-elide_copyfrom(svn_wc__db_pdh_t *pdh,
-               const char *local_relpath,
-               apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-  apr_int64_t original_repos_id;
-  const char *original_repos_relpath;
-  svn_revnum_t original_revision;
-  const char *parent_local_relpath;
-  const char *name;
-  apr_int64_t parent_repos_id;
-  const char *parent_repos_relpath;
-  svn_revnum_t parent_revision;
-  const char *implied_relpath;
-
-  /* Examine the current WORKING_NODE row's copyfrom information. If there
-     is no WORKING node, then simply exit.  */
-  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));
-
-  if (!have_row)
-    return svn_error_return(svn_sqlite__reset(stmt));
-
-  /* Already inheriting copyfrom information?  */
-  if (svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
-    return svn_error_return(svn_sqlite__reset(stmt));
-
-  original_repos_id = svn_sqlite__column_int64(stmt, 10);
-  original_repos_relpath = svn_sqlite__column_text(stmt, 11, scratch_pool);
-  original_revision = svn_sqlite__column_revnum(stmt, 12);
-
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  svn_dirent_split(&parent_local_relpath, &name, local_relpath, scratch_pool);
-
-  SVN_ERR(get_copyfrom(&parent_repos_id, &parent_repos_relpath,
-                       &parent_revision,
-                       pdh, parent_local_relpath, scratch_pool, scratch_pool));
-  if (parent_revision == SVN_INVALID_REVNUM)
-    return SVN_NO_ERROR;
-
-  /* Now we need to determine if the child's values are derivable from
-     the parent values.  */
-
-  /* If the revision numbers are not the same, then easy exit.
-
-     Note that we *can* have a mixed-rev copied subtree. We don't want
-     to elide the copyfrom information for these cases.  */
-  if (original_revision != parent_revision)
-    return SVN_NO_ERROR;
-
-  /* The child repos_relpath should be under the parent's.  */
-  if (svn_relpath_is_child(parent_repos_relpath,
-                           original_repos_relpath,
-                           NULL) == NULL)
-    return SVN_NO_ERROR;
-
-  /* Given the relpath from OP_ROOT_ABSPATH down to LOCAL_ABSPATH, compute
-     an implied REPOS_RELPATH. If that does not match the RELPATH we found,
-     then we can exit (the child is a new copy root).  */
-  implied_relpath = svn_relpath_join(parent_repos_relpath, name, scratch_pool);
-  if (strcmp(implied_relpath, original_repos_relpath) != 0)
-    return SVN_NO_ERROR;
-
-  if (original_repos_id != parent_repos_id)
-    return SVN_NO_ERROR;
-
-  /* The child's copyfrom information is derivable from the parent.
-     The data should be reset to null, indicating the derivation.  */
-  /* Should probably use the op_depth from query above and simplify this
-     query. */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_UPDATE_COPYFROM_TO_INHERIT));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__update(NULL, stmt));
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_temp_elide_copyfrom(svn_wc__db_t *db,
-                               const char *local_abspath,
-                               apr_pool_t *scratch_pool)
-{
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
-                              local_abspath, svn_sqlite__mode_readwrite,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(pdh);
-
-  SVN_ERR(elide_copyfrom(pdh, local_relpath, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-#endif
-
 
 svn_error_t *
 svn_wc__db_temp_get_file_external(const char **serialized_file_external,
@@ -9538,3 +9122,25 @@ svn_wc__db_temp_op_set_new_dir_to_incomp
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__db_temp_below_work(svn_boolean_t *have_work,
+                           svn_wc__db_t *db,
+                           const char *local_abspath,
+                           apr_pool_t *scratch_pool)
+{
+  svn_boolean_t have_base;
+  svn_wc__db_status_t status;
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              local_abspath, svn_sqlite__mode_readwrite,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+  SVN_ERR(info_below_working(&have_base, have_work, &status,
+                             pdh, local_relpath, scratch_pool));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/wc_db.h Wed Dec 29 00:10:25 2010
@@ -972,7 +972,7 @@ svn_wc__db_pristine_remove(svn_wc__db_t 
                            apr_pool_t *scratch_pool);
 
 
-/* Remove all unreferenced pristines belonging to WRI_ABSPATH in DB. */
+/* Remove all unreferenced pristines in the WC of WRI_ABSPATH in DB. */
 svn_error_t *
 svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
                             const char *wri_abspath,
@@ -1518,6 +1518,25 @@ svn_wc__db_read_children_info(apr_hash_t
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
+
+/* Structure returned by svn_wc__db_read_walker_info.  Only has the
+   fields needed by svn_wc__internal_walk_children(). */
+struct svn_wc__db_walker_info_t {
+  svn_wc__db_status_t status;
+  svn_wc__db_kind_t kind;
+};
+
+/* Return in *NODES a hash mapping name->struct svn_wc__db_walker_info_t for
+   the children of DIR_ABSPATH. "name" is the child's name relatve to
+   DIR_ABSPATH, not an absolute path. */
+svn_error_t *
+svn_wc__db_read_children_walker_info(apr_hash_t **nodes,
+                                     svn_wc__db_t *db,
+                                     const char *dir_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 ACTUAL tree (looking through to the WORKING or BASE
    tree as required).
@@ -2336,16 +2355,6 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
                              apr_pool_t *scratch_pool);
 
 
-#ifndef SVN_WC__OP_DEPTH
-/* Elide the copyfrom information for LOCAL_ABSPATH if it can be derived
-   from the parent node.  */
-svn_error_t *
-svn_wc__db_temp_elide_copyfrom(svn_wc__db_t *db,
-                               const char *local_abspath,
-                               apr_pool_t *scratch_pool);
-#endif
-
-
 /* Return the serialized file external info (from BASE) for LOCAL_ABSPATH.
    Stores NULL into SERIALIZED_FILE_EXTERNAL if this node is NOT a file
    external. If a BASE node does not exist: SVN_ERR_WC_PATH_NOT_FOUND.  */
@@ -2430,6 +2439,14 @@ svn_wc__db_drop_root(svn_wc__db_t *db,
 /* Return the OP_DEPTH for LOCAL_RELPATH. */
 int svn_wc__db_op_depth_for_upgrade(const char *local_relpath);
 
+/* Set *HAVE_WORK TRUE if there is a working layer below the top layer */
+svn_error_t *
+svn_wc__db_temp_below_work(svn_boolean_t *have_work,
+                           svn_wc__db_t *db,
+                           const char *local_abspath,
+                           apr_pool_t *scratch_pool);
+
+
 /* @} */
 
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/workqueue.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/libsvn_wc/workqueue.c Wed Dec 29 00:10:25 2010
@@ -1515,15 +1515,6 @@ run_file_install(svn_wc__db_t *db,
       SVN_ERR(get_and_record_fileinfo(db, local_abspath,
                                       FALSE /* ignore_enoent */,
                                       scratch_pool));
-
-#ifndef SVN_WC__OP_DEPTH
-      /* ### there used to be a call to entry_modify() above, to set the
-         ### TRANSLATED_SIZE and LAST_MOD_TIME values. that function elided
-         ### copyfrom information that snuck into the database. it should
-         ### not be there in the first place, but we can manually get rid
-         ### of the erroneous, inheritable copyfrom data.  */
-      SVN_ERR(svn_wc__db_temp_elide_copyfrom(db, local_abspath, scratch_pool));
-#endif
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_authz_svn/mod_authz_svn.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_authz_svn/mod_authz_svn.c Wed Dec 29 00:10:25 2010
@@ -170,7 +170,7 @@ get_access_conf(request_rec *r, authz_sv
     {
       dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path);
       if (dav_err) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, dav_err->desc);
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc);
         return NULL;
       }
       access_file = svn_dirent_join_many(r->pool, repos_path, "conf",

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/dav_svn.h?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/dav_svn.h Wed Dec 29 00:10:25 2010
@@ -572,7 +572,7 @@ dav_error *
 dav_svn__merge_response(ap_filter_t *output,
                         const dav_svn_repos *repos,
                         svn_revnum_t new_rev,
-                        char *post_commit_err,
+                        const char *post_commit_err,
                         apr_xml_elem *prop_elem,
                         svn_boolean_t disable_merge_response,
                         apr_pool_t *pool);
@@ -748,9 +748,9 @@ dav_svn__new_error(apr_pool_t *pool,
    string constant. */
 dav_error *
 dav_svn__convert_err(svn_error_t *serr,
-                    int status,
-                    const char *message,
-                    apr_pool_t *pool);
+                     int status,
+                     const char *message,
+                     apr_pool_t *pool);
 
 
 /* Compare (PATH in ROOT) to (PATH in ROOT/PATH's created_rev).

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/deadprops.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/deadprops.c Wed Dec 29 00:10:25 2010
@@ -222,17 +222,21 @@ save_value(dav_db *db, const dav_prop_na
                                                resource->pool);
 
           /* Prepare any hook failure message to get sent over the wire */
-          serr = svn_error_purge_tracing(serr);
-          if (serr && serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE)
-            serr->message = apr_xml_quote_string(serr->pool, serr->message, 1);
-
-          /* mod_dav doesn't handle the returned error very well, it
-             generates its own generic error that will be returned to
-             the client.  Cache the detailed error here so that it can
-             be returned a second time when the rollback mechanism
-             triggers. */
           if (serr)
-            resource->info->revprop_error = svn_error_dup(serr);
+            {
+              svn_error_t *purged_serr = svn_error_purge_tracing(serr);
+              if (purged_serr->apr_err == SVN_ERR_REPOS_HOOK_FAILURE)
+                purged_serr->message = apr_xml_quote_string
+                                         (purged_serr->pool,
+                                          purged_serr->message, 1);
+
+              /* mod_dav doesn't handle the returned error very well, it
+                 generates its own generic error that will be returned to
+                 the client.  Cache the detailed error here so that it can
+                 be returned a second time when the rollback mechanism
+                 triggers. */
+              resource->info->revprop_error = svn_error_dup(purged_serr);
+            }
 
           /* Tell the logging subsystem about the revprop change. */
           dav_svn__operational_log(resource->info,

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/lock.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/lock.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/lock.c Wed Dec 29 00:10:25 2010
@@ -713,15 +713,28 @@ append_locks(dav_lockdb *lockdb,
                                     "Could not create empty file.",
                                     resource->pool);
 
-      if ((serr = svn_repos_fs_commit_txn(&conflict_msg, repos->repos,
-                                          &new_rev, txn, resource->pool)))
+      serr = svn_repos_fs_commit_txn(&conflict_msg, repos->repos,
+                                     &new_rev, txn, resource->pool);
+      if (SVN_IS_VALID_REVNUM(new_rev))
+        {
+          svn_error_clear(serr);
+        }
+      else
         {
           svn_error_clear(svn_fs_abort_txn(txn, resource->pool));
-          return dav_svn__convert_err(serr, HTTP_CONFLICT,
-                                      apr_psprintf(resource->pool,
-                                                   "Conflict when committing "
-                                                   "'%s'.", conflict_msg),
-                                      resource->pool);
+          if (serr)
+            return dav_svn__convert_err(serr, HTTP_CONFLICT,
+                                        apr_psprintf(resource->pool,
+                                                     "Conflict when "
+                                                     "committing '%s'.",
+                                                     conflict_msg),
+                                        resource->pool);
+          else
+            return dav_svn__new_error(resource->pool,
+                                      HTTP_INTERNAL_SERVER_ERROR,
+                                      0,
+                                      "Commit failed but there was no error "
+                                      "provided.");
         }
     }
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/merge.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/merge.c Wed Dec 29 00:10:25 2010
@@ -209,7 +209,7 @@ dav_error *
 dav_svn__merge_response(ap_filter_t *output,
                         const dav_svn_repos *repos,
                         svn_revnum_t new_rev,
-                        char *post_commit_err,
+                        const char *post_commit_err,
                         apr_xml_elem *prop_elem,
                         svn_boolean_t disable_merge_response,
                         apr_pool_t *pool)

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/repos.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/repos.c Wed Dec 29 00:10:25 2010
@@ -279,7 +279,7 @@ parse_vcc_uri(dav_resource_combined *com
     {
       /* a specific Version Resource; in this case, a Baseline */
 
-      int revnum;
+      svn_revnum_t revnum;
 
       if (label != NULL)
         {
@@ -347,7 +347,7 @@ parse_baseline_coll_uri(dav_resource_com
                         int use_checked_in)
 {
   const char *slash;
-  int revnum;
+  svn_revnum_t revnum;
 
   /* format: REVISION/REPOS_PATH */
 
@@ -385,7 +385,7 @@ parse_baseline_uri(dav_resource_combined
                    const char *label,
                    int use_checked_in)
 {
-  int revnum;
+  svn_revnum_t revnum;
 
   /* format: REVISION */
 

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/util.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/util.c Wed Dec 29 00:10:25 2010
@@ -111,7 +111,7 @@ dav_svn__convert_err(svn_error_t *serr,
     /* Remove the trace-only error chain links.  We need predictable
        protocol behavior regardless of whether or not we're in a
        debugging build. */
-    serr = svn_error_purge_tracing(serr);
+    svn_error_t *purged_serr = svn_error_purge_tracing(serr);
 
     /* ### someday mod_dav_svn will send back 'rich' error tags, much
        finer grained than plain old svn_error_t's.  But for now, all
@@ -122,7 +122,7 @@ dav_svn__convert_err(svn_error_t *serr,
        appropriate HTTP status code.  If no more appropriate HTTP
        status code maps to the Subversion error code, use the one
        suggested status provided by the caller. */
-    switch (serr->apr_err)
+    switch (purged_serr->apr_err)
       {
       case SVN_ERR_FS_NOT_FOUND:
         status = HTTP_NOT_FOUND;
@@ -139,11 +139,12 @@ dav_svn__convert_err(svn_error_t *serr,
         /* add other mappings here */
       }
 
-    derr = build_error_chain(pool, serr, status);
+    derr = build_error_chain(pool, purged_serr, status);
     if (message != NULL
-        && serr->apr_err != SVN_ERR_REPOS_HOOK_FAILURE)
+        && purged_serr->apr_err != SVN_ERR_REPOS_HOOK_FAILURE)
       /* Don't hide hook failures; we might hide the error text */
-      derr = dav_push_error(pool, status, serr->apr_err, message, derr);
+      derr = dav_push_error(pool, status, purged_serr->apr_err,
+                            message, derr);
 
     /* Now, destroy the Subversion error. */
     svn_error_clear(serr);

Modified: subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/version.c?rev=1053489&r1=1053488&r2=1053489&view=diff
==============================================================================
--- subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/diff-optimizations-bytes/subversion/mod_dav_svn/version.c Wed Dec 29 00:10:25 2010
@@ -37,6 +37,7 @@
 #include "svn_props.h"
 #include "svn_dav.h"
 #include "svn_base64.h"
+#include "private/svn_repos_private.h"
 #include "private/svn_dav_protocol.h"
 #include "private/svn_log.h"
 
@@ -917,30 +918,57 @@ dav_svn__checkin(dav_resource *resource,
                                      resource->info->root.txn,
                                      resource->pool);
 
-      if (serr != NULL)
+      if (SVN_IS_VALID_REVNUM(new_rev))
+        {
+          if (serr)
+            {
+              const char *post_commit_err = svn_repos__post_commit_error_str
+                                              (serr, resource->pool);
+              ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err,
+                            resource->pool,
+                            "commit of r%ld succeeded, but an error occurred "
+                            "after the commit: '%s'",
+                            new_rev,
+                            post_commit_err);
+              svn_error_clear(serr);
+              serr = SVN_NO_ERROR;
+            }
+        }
+      else
         {
           const char *msg;
           svn_error_clear(svn_fs_abort_txn(resource->info->root.txn,
                                            resource->pool));
 
-          if (serr->apr_err == SVN_ERR_FS_CONFLICT)
-            {
-              msg = apr_psprintf(resource->pool,
-                                 "A conflict occurred during the CHECKIN "
-                                 "processing. The problem occurred with  "
-                                 "the \"%s\" resource.",
-                                 conflict_msg);
-            }
-          else
-            msg = "An error occurred while committing the transaction.";
-
           /* Attempt to destroy the shared activity. */
           dav_svn__delete_activity(resource->info->repos, shared_activity);
           apr_pool_userdata_set(NULL, DAV_SVN__AUTOVERSIONING_ACTIVITY,
                                 NULL, resource->info->r->pool);
 
-          return dav_svn__convert_err(serr, HTTP_CONFLICT, msg,
-                                      resource->pool);
+          if (serr)
+            {
+              if (serr->apr_err == SVN_ERR_FS_CONFLICT)
+                {
+                  msg = apr_psprintf(resource->pool,
+                                     "A conflict occurred during the CHECKIN "
+                                     "processing. The problem occurred with  "
+                                     "the \"%s\" resource.",
+                                     conflict_msg);
+                }
+              else
+                msg = "An error occurred while committing the transaction.";
+
+              return dav_svn__convert_err(serr, HTTP_CONFLICT, msg,
+                                          resource->pool);
+            }
+          else
+            {
+              return dav_svn__new_error(resource->pool,
+                                        HTTP_INTERNAL_SERVER_ERROR,
+                                        0,
+                                        "Commit failed but there was no error "
+                                        "provided.");
+            }
         }
 
       /* Attempt to destroy the shared activity. */
@@ -1322,7 +1350,7 @@ merge(dav_resource *target,
   svn_fs_txn_t *txn;
   const char *conflict;
   svn_error_t *serr;
-  char *post_commit_err = NULL;
+  const char *post_commit_err = NULL;
   svn_revnum_t new_rev;
   apr_hash_t *locks;
   svn_boolean_t disable_merge_response = FALSE;
@@ -1381,36 +1409,51 @@ merge(dav_resource *target,
   serr = svn_repos_fs_commit_txn(&conflict, source->info->repos->repos,
                                  &new_rev, txn, pool);
 
-  /* If the error was just a post-commit hook failure, we ignore it.
-     Otherwise, we deal with it.
-     ### TODO: Figure out if the MERGE response can grow a means by
+  /* ### TODO: Figure out if the MERGE response can grow a means by
      which to marshal back both the success of the commit (and its
      commit info) and the failure of the post-commit hook.  */
-  if (serr && (serr->apr_err != SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED))
+  if (SVN_IS_VALID_REVNUM(new_rev))
+    {
+      if (serr)
+        {
+          /* ### Any error from svn_fs_commit_txn() itself, and not
+             ### the post-commit script, should be reported to the
+             ### client some other way than hijacking the post-commit
+             ### error message.*/
+          post_commit_err = svn_repos__post_commit_error_str(serr, pool);
+          svn_error_clear(serr);
+          serr = SVN_NO_ERROR;
+        }
+    }
+  else
     {
-      const char *msg;
       svn_error_clear(svn_fs_abort_txn(txn, pool));
 
-      if (serr->apr_err == SVN_ERR_FS_CONFLICT)
+      if (serr)
         {
-          /* ### we need to convert the conflict path into a URI */
-          msg = apr_psprintf(pool,
-                             "A conflict occurred during the MERGE "
-                             "processing. The problem occurred with the "
-                             "\"%s\" resource.",
-                             conflict);
+          const char *msg;
+          if (serr->apr_err == SVN_ERR_FS_CONFLICT)
+            {
+              /* ### we need to convert the conflict path into a URI */
+              msg = apr_psprintf(pool,
+                                 "A conflict occurred during the MERGE "
+                                 "processing. The problem occurred with the "
+                                 "\"%s\" resource.",
+                                 conflict);
+            }
+          else
+            msg = "An error occurred while committing the transaction.";
+
+          return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, pool);
         }
       else
-        msg = "An error occurred while committing the transaction.";
-
-      return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, pool);
-    }
-  else if (serr)
-    {
-      serr = svn_error_purge_tracing(serr);
-      if (serr->child && serr->child->message)
-        post_commit_err = apr_pstrdup(pool, serr->child->message);
-      svn_error_clear(serr);
+        {
+          return dav_svn__new_error(pool,
+                                    HTTP_INTERNAL_SERVER_ERROR,
+                                    0,
+                                    "Commit failed but there was no error "
+                                    "provided.");
+        }
     }
 
   /* Commit was successful, so schedule deltification. */