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/08/11 00:07:31 UTC

svn commit: r984234 [8/20] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/ac-macros/ build/generator/ notes/ notes/api-errata/ notes/obliterate/ notes/obliterate/fspec-cc1/ notes/rename-tracking/ notes/svnpatch/ notes/tree-conflicts/ notes...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_crawler.c Tue Aug 10 22:07:24 2010
@@ -45,8 +45,6 @@
 #include "adm_files.h"
 #include "props.h"
 #include "translate.h"
-#include "entries.h"
-#include "lock.h"
 #include "workqueue.h"
 #include "conflicts.h"
 
@@ -265,44 +263,8 @@ report_revisions_and_depths(svn_wc__db_t
   /* If "this dir" has "svn:externals" property set on it,
    * call the external_func callback. */
   if (external_func)
-    {
-      const apr_array_header_t *all_children;
-
-      SVN_ERR(read_externals_info(db, dir_abspath, external_func,
-                                  external_baton, dir_depth, iterpool));
-
-      /* Also do this for added children. They aren't part of the base
-       * tree so we don't recurse into them. But our caller might still
-       * want to pull externals into them as part of the update operation. */
-      SVN_ERR(svn_wc__db_read_children(&all_children, db, dir_abspath,
-                                       scratch_pool, iterpool));
-      for (i = 0; i < all_children->nelts; ++i)
-        {
-          const char *child = APR_ARRAY_IDX(all_children, i, const char *);
-          const char *this_abspath;
-          svn_wc__db_status_t this_status;
-          svn_wc__db_kind_t this_kind;
-          svn_depth_t this_depth;
-
-          svn_pool_clear(iterpool);
-
-          this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
-          SVN_ERR(svn_wc__db_read_info(&this_status, &this_kind, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       &this_depth, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL,
-                                       db, this_abspath, iterpool, iterpool));
-          if (this_kind == svn_wc__db_kind_dir &&
-              this_status == svn_wc__db_status_added)
-            {
-              SVN_ERR(read_externals_info(db, this_abspath, external_func,
-                                          external_baton, this_depth,
-                                          iterpool));
-            }
-        }
-    }
-
+    SVN_ERR(read_externals_info(db, dir_abspath, external_func,
+                                external_baton, dir_depth, iterpool));
 
   /* Looping over current directory's BASE children: */
   for (i = 0; i < base_children->nelts; ++i)
@@ -682,18 +644,18 @@ find_base_rev(svn_revnum_t *base_rev,
 {
   const char *op_root_abspath;
   svn_wc__db_status_t status;
-  svn_boolean_t base_shadowed;
+  svn_boolean_t have_base;
 
   SVN_ERR(svn_wc__db_read_info(&status, NULL, base_rev, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL,
-                               &base_shadowed, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL,
+                               &have_base, NULL, NULL, NULL,
                                db, local_abspath, pool, pool));
 
   if (SVN_IS_VALID_REVNUM(*base_rev))
       return SVN_NO_ERROR;
 
-  if (base_shadowed)
+  if (have_base)
     return svn_error_return(
         svn_wc__db_base_get_info(NULL, NULL, base_rev, NULL, NULL, NULL, NULL,
                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -966,7 +928,7 @@ svn_wc_crawl_revisions5(svn_wc_context_t
       svn_wc__db_status_t parent_status;
       const char *parent_repos_relpath;
 
-      svn_dirent_split(local_abspath, &parent_abspath, &base,
+      svn_dirent_split(&parent_abspath, &base, local_abspath,
                        scratch_pool);
 
       /* We can assume a file is in the same repository as its parent

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c Tue Aug 10 22:07:24 2010
@@ -217,7 +217,7 @@ svn_wc__text_base_path(const char **resu
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  svn_dirent_split(local_abspath, &newpath, &base_name, pool);
+  svn_dirent_split(&newpath, &base_name, local_abspath, pool);
   *result_abspath = simple_extend(newpath,
                                   FALSE,
                                   SVN_WC__ADM_TEXT_BASE,
@@ -239,7 +239,7 @@ svn_wc__text_base_deterministic_tmp_path
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  svn_dirent_split(local_abspath, &newpath, &base_name, pool);
+  svn_dirent_split(&newpath, &base_name, local_abspath, pool);
   *result_abspath = simple_extend(newpath, TRUE, SVN_WC__ADM_TEXT_BASE,
                                   base_name, SVN_WC__BASE_EXT, pool);
 
@@ -257,7 +257,7 @@ svn_wc__text_revert_path(const char **re
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  svn_dirent_split(local_abspath, &newpath, &base_name, pool);
+  svn_dirent_split(&newpath, &base_name, local_abspath, pool);
   *result_abspath = simple_extend(newpath,
                                   FALSE,
                                   SVN_WC__ADM_TEXT_BASE,
@@ -589,29 +589,89 @@ svn_wc__get_pristine_contents(svn_stream
 
 
 svn_error_t *
-svn_wc__get_ultimate_base_md5_checksum(const svn_checksum_t **md5_checksum,
-                                       svn_wc__db_t *db,
-                                       const char *local_abspath,
-                                       apr_pool_t *result_pool,
-                                       apr_pool_t *scratch_pool)
+svn_wc__get_ultimate_base_checksums(const svn_checksum_t **sha1_checksum,
+                                    const svn_checksum_t **md5_checksum,
+                                    svn_wc__db_t *db,
+                                    const char *local_abspath,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
+  const svn_checksum_t *checksum;
 
   err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
-                                 NULL, NULL, NULL, NULL, NULL, md5_checksum,
+                                 NULL, NULL, NULL, NULL, NULL, &checksum,
                                  NULL, NULL, NULL,
                                  db, local_abspath,
-                                 scratch_pool, scratch_pool);
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+                                 result_pool, scratch_pool);
+  if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+      || checksum == NULL)
     {
       svn_error_clear(err);
-      *md5_checksum = NULL;
+      if (sha1_checksum)
+        *sha1_checksum = NULL;
+      if (md5_checksum)
+        *md5_checksum = NULL;
       return SVN_NO_ERROR;
     }
-  if (*md5_checksum && (*md5_checksum)->kind != svn_checksum_md5)
-    SVN_ERR(svn_wc__db_pristine_get_md5(md5_checksum, db, local_abspath,
-                                        *md5_checksum,
-                                        scratch_pool, scratch_pool));
+
+  if (checksum->kind == svn_checksum_sha1)
+    {
+      if (sha1_checksum)
+        *sha1_checksum = checksum;
+      if (md5_checksum)
+        SVN_ERR(svn_wc__db_pristine_get_md5(md5_checksum, db, local_abspath,
+                                            checksum,
+                                            result_pool, scratch_pool));
+    }
+  else
+    {
+      if (sha1_checksum)
+        SVN_ERR(svn_wc__db_pristine_get_sha1(sha1_checksum, db, local_abspath,
+                                             checksum,
+                                             result_pool, scratch_pool));
+      if (md5_checksum)
+        *md5_checksum = checksum;
+    }
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__get_working_checksums(const svn_checksum_t **sha1_checksum,
+                              const svn_checksum_t **md5_checksum,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  const svn_checksum_t *checksum;
+
+  SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, &checksum,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               db, local_abspath,
+                               result_pool, scratch_pool));
+
+  if (checksum->kind == svn_checksum_sha1)
+    {
+      if (sha1_checksum)
+        *sha1_checksum = checksum;
+      if (md5_checksum)
+        SVN_ERR(svn_wc__db_pristine_get_md5(md5_checksum, db, local_abspath,
+                                            checksum,
+                                            result_pool, scratch_pool));
+    }
+  else
+    {
+      if (sha1_checksum)
+        SVN_ERR(svn_wc__db_pristine_get_sha1(sha1_checksum, db, local_abspath,
+                                             checksum,
+                                             result_pool, scratch_pool));
+      if (md5_checksum)
+        *md5_checksum = checksum;
+    }
   return SVN_NO_ERROR;
 }
 
@@ -669,7 +729,7 @@ svn_wc__prop_path(const char **prop_path
 
       const char *base_name;
 
-      svn_dirent_split(path, prop_path, &base_name, pool);
+      svn_dirent_split(prop_path, &base_name, path, pool);
       *prop_path = simple_extend(*prop_path, FALSE, dirs[props_kind],
                                  base_name, extensions[props_kind], pool);
     }
@@ -771,8 +831,14 @@ init_adm(svn_wc__db_t *db,
 
   /** Make subdirectories. ***/
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+  /* ### The absence of this directory is used to indicate to the
+     ### regression tests that SHA1 pristines are enabled.  This is a
+     ### temporary hack, to avoid bumping the wc format. */
+
   /* SVN_WC__ADM_TEXT_BASE */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_TEXT_BASE, FALSE, pool));
+#endif
 
   /* SVN_WC__ADM_PROP_BASE */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_PROP_BASE, FALSE, pool));

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h Tue Aug 10 22:07:24 2010
@@ -221,15 +221,29 @@ svn_wc__ultimate_base_text_path_to_read(
                                         apr_pool_t *result_pool,
                                         apr_pool_t *scratch_pool);
 
-/* Set *MD5_CHECKSUM to the MD-5 checksum of the BASE_NODE pristine text
- * of LOCAL_ABSPATH in DB, or to NULL if it has no BASE_NODE.
- * Allocate *MD5_CHECKSUM in RESULT_POOL. */
+/* Set *SHA1_CHECKSUM and *MD5_CHECKSUM to the SHA-1 and MD-5 checksums of
+ * the BASE_NODE pristine text of LOCAL_ABSPATH in DB, or to NULL if it has
+ * no BASE_NODE.  SHA1_CHECKSUM or MD5_CHECKSUM may be NULL if not required.
+ * Allocate the checksums in RESULT_POOL. */
 svn_error_t *
-svn_wc__get_ultimate_base_md5_checksum(const svn_checksum_t **md5_checksum,
-                                       svn_wc__db_t *db,
-                                       const char *local_abspath,
-                                       apr_pool_t *result_pool,
-                                       apr_pool_t *scratch_pool);
+svn_wc__get_ultimate_base_checksums(const svn_checksum_t **sha1_checksum,
+                                    const svn_checksum_t **md5_checksum,
+                                    svn_wc__db_t *db,
+                                    const char *local_abspath,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool);
+
+/* Set *SHA1_CHECKSUM and *MD5_CHECKSUM to the SHA-1 and MD-5 checksums of
+ * the WORKING_NODE pristine text of LOCAL_ABSPATH in DB, or to NULL if it has
+ * no WORKING_NODE.  SHA1_CHECKSUM or MD5_CHECKSUM may be NULL if not required.
+ * Allocate the checksums in RESULT_POOL. */
+svn_error_t *
+svn_wc__get_working_checksums(const svn_checksum_t **sha1_checksum,
+                              const svn_checksum_t **md5_checksum,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
 
 
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_ops.c?rev=984234&r1=984233&r2=984234&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_ops.c Tue Aug 10 22:07:24 2010
@@ -54,7 +54,6 @@
 #include "wc.h"
 #include "log.h"
 #include "adm_files.h"
-#include "adm_ops.h"
 #include "entries.h"
 #include "lock.h"
 #include "props.h"
@@ -102,232 +101,6 @@ svn_wc__get_committed_queue_pool(const s
 
 /*** Finishing updates and commits. ***/
 
-
-/* The main body of svn_wc__do_update_cleanup. */
-static svn_error_t *
-tweak_entries(svn_wc__db_t *db,
-              const char *dir_abspath,
-              const char *base_url,
-              svn_revnum_t new_rev,
-              svn_wc_notify_func2_t notify_func,
-              void *notify_baton,
-              svn_depth_t depth,
-              apr_hash_t *exclude_paths,
-              apr_pool_t *pool)
-{
-  apr_pool_t *iterpool;
-  svn_wc_notify_t *notify;
-  const apr_array_header_t *children;
-  int i;
-
-  /* Skip an excluded path and its descendants. */
-  if (apr_hash_get(exclude_paths, dir_abspath, APR_HASH_KEY_STRING))
-    return SVN_NO_ERROR;
-
-  iterpool = svn_pool_create(pool);
-
-  /* Tweak "this_dir" */
-  SVN_ERR(svn_wc__tweak_entry(db, dir_abspath, svn_node_dir, FALSE,
-                              base_url, new_rev,
-                              FALSE /* allow_removal */, iterpool));
-
-  if (depth == svn_depth_unknown)
-    depth = svn_depth_infinity;
-
-  /* Early out */
-  if (depth <= svn_depth_empty)
-    return SVN_NO_ERROR;
-
-  SVN_ERR(svn_wc__db_base_get_children(&children, db, dir_abspath,
-                                       pool, iterpool));
-  for (i = 0; i < children->nelts; i++)
-    {
-      const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-      svn_wc__db_kind_t kind;
-      svn_wc__db_status_t status;
-
-      const char *child_url = NULL;
-      svn_boolean_t excluded;
-
-      svn_pool_clear(iterpool);
-
-      /* Derive the new URL for the current (child) entry */
-      if (base_url)
-        child_url = svn_path_url_add_component2(base_url, child_basename,
-                                                iterpool);
-
-      child_abspath = svn_dirent_join(dir_abspath, child_basename, iterpool);
-      excluded = (apr_hash_get(exclude_paths, child_abspath,
-                               APR_HASH_KEY_STRING) != NULL);
-
-      SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL,
-                                   db, child_abspath, iterpool, iterpool));
-
-      /* If a file, or deleted, excluded or absent dir, then tweak the
-         entry but don't recurse.
-
-         ### how does this translate into wc_db land? */
-      if (kind == svn_wc__db_kind_file
-            || status == svn_wc__db_status_not_present
-            || status == svn_wc__db_status_absent
-            || status == svn_wc__db_status_excluded)
-        {
-          if (excluded)
-            continue;
-
-          if (kind == svn_wc__db_kind_dir)
-            SVN_ERR(svn_wc__tweak_entry(db, child_abspath, svn_node_dir, TRUE,
-                                        child_url, new_rev,
-                                        TRUE /* allow_removal */,
-                                        iterpool));
-          else
-            SVN_ERR(svn_wc__tweak_entry(db, child_abspath, svn_node_file, FALSE,
-                                        child_url, new_rev,
-                                        TRUE /* allow_removal */,
-                                        iterpool));
-        }
-
-      /* If a directory and recursive... */
-      else if ((depth == svn_depth_infinity
-                || depth == svn_depth_immediates)
-               && (kind == svn_wc__db_kind_dir))
-        {
-          svn_depth_t depth_below_here = depth;
-
-          if (depth == svn_depth_immediates)
-            depth_below_here = svn_depth_empty;
-
-          /* If the directory is 'missing', remove it.  This is safe as
-             long as this function is only called as a helper to
-             svn_wc__do_update_cleanup, since the update will already have
-             restored any missing items that it didn't want to delete. */
-          if (svn_wc__adm_missing(db, child_abspath, iterpool))
-            {
-              if ( (status == svn_wc__db_status_added
-                    || status == svn_wc__db_status_obstructed_add)
-                  && !excluded)
-                {
-                  SVN_ERR(svn_wc__db_temp_op_remove_entry(db, child_abspath,
-                                                          iterpool));
-
-                  if (notify_func)
-                    {
-                      notify = svn_wc_create_notify(child_abspath,
-                                                    svn_wc_notify_delete,
-                                                    iterpool);
-
-                      if (kind == svn_wc__db_kind_dir)
-                        notify->kind = svn_node_dir;
-                      else if (kind == svn_wc__db_kind_file)
-                        notify->kind = svn_node_file;
-                      else
-                        notify->kind = svn_node_unknown;
-
-                      (* notify_func)(notify_baton, notify, iterpool);
-                    }
-                }
-              /* Else if missing item is schedule-add, do nothing. */
-            }
-
-          /* Not missing, deleted, or absent, so recurse. */
-          else
-            {
-              SVN_ERR(tweak_entries(db, child_abspath, child_url,
-                                    new_rev, notify_func, notify_baton,
-                                    depth_below_here,
-                                    exclude_paths, iterpool));
-            }
-        }
-    }
-
-  /* Cleanup */
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__do_update_cleanup(svn_wc__db_t *db,
-                          const char *local_abspath,
-                          svn_depth_t depth,
-                          const char *base_url,
-                          const char *repos,
-                          svn_revnum_t new_revision,
-                          svn_wc_notify_func2_t notify_func,
-                          void *notify_baton,
-                          apr_hash_t *exclude_paths,
-                          apr_pool_t *pool)
-{
-  svn_wc__db_status_t status;
-  svn_wc__db_kind_t kind;
-  svn_error_t *err;
-
-  if (apr_hash_get(exclude_paths, local_abspath, APR_HASH_KEY_STRING))
-    return SVN_NO_ERROR;
-
-  err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL,
-                             db, local_abspath, pool, pool);
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-    {
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
-    }
-  else
-    SVN_ERR(err);
-
-  switch (status)
-    {
-      case svn_wc__db_status_excluded:
-      case svn_wc__db_status_absent:
-      case svn_wc__db_status_not_present:
-        return SVN_NO_ERROR;
-      case svn_wc__db_status_obstructed:
-      case svn_wc__db_status_obstructed_add:
-      case svn_wc__db_status_obstructed_delete:
-        /* There is only a parent stub. That's fine... just tweak it
-           and avoid directory recursion.  */
-        SVN_ERR(svn_wc__tweak_entry(db, local_abspath, svn_node_dir, TRUE,
-                                    base_url, new_revision,
-                                    FALSE /* allow_removal */,
-                                    pool));
-        return SVN_NO_ERROR;
-
-      /* Explicitly ignore other statii */
-      default:
-        break;
-    }
-
-  if (kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink)
-    {
-      /* Parent not updated so don't remove PATH entry.  */
-      SVN_ERR(svn_wc__tweak_entry(db, local_abspath, svn_node_file, FALSE,
-                                  base_url, new_revision,
-                                  FALSE /* allow_removal */,
-                                  pool));
-    }
-  else if (kind == svn_wc__db_kind_dir)
-    {
-      SVN_ERR(tweak_entries(db, local_abspath, base_url, new_revision,
-                            notify_func, notify_baton,
-                            depth, exclude_paths, pool));
-    }
-  else
-    return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-                             _("Unrecognized node kind: '%s'"),
-                             svn_dirent_local_style(local_abspath, pool));
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Queue work items that will finish a commit of the file or directory
  * LOCAL_ABSPATH in DB:
  *   - queue the removal of any "revert-base" props and text files;
@@ -456,15 +229,6 @@ process_committed_leaf(svn_wc__db_t *db,
         }
     }
 
-  if (!no_unlock)
-    {
-      svn_skel_t *work_item;
-
-      SVN_ERR(svn_wc__loggy_delete_lock(&work_item, db, adm_abspath,
-                                        local_abspath, scratch_pool));
-      SVN_ERR(svn_wc__db_wq_add(db, adm_abspath, work_item, scratch_pool));
-    }
-
 #ifdef SVN_EXPERIMENTAL_PRISTINE
   /* Set TMP_TEXT_BASE_ABSPATH to NULL.  The new text base will be found in
      the pristine store by its checksum. */
@@ -489,7 +253,7 @@ process_committed_leaf(svn_wc__db_t *db,
   SVN_ERR(svn_wc__wq_add_postcommit(db, local_abspath, tmp_text_base_abspath,
                                     new_revnum,
                                     new_date, rev_author, checksum,
-                                    new_dav_cache, keep_changelist,
+                                    new_dav_cache, keep_changelist, no_unlock,
                                     scratch_pool));
 
   return SVN_NO_ERROR;
@@ -1057,12 +821,12 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_wc__db_kind_t kind;
-  svn_boolean_t base_shadowed;
+  svn_boolean_t have_base;
 
   err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             &base_shadowed, NULL, NULL,
+                             NULL, NULL, NULL, NULL, NULL, NULL,
+                             &have_base, NULL, NULL, NULL,
                              db, local_abspath, pool, pool);
 
   if (delete_unversioned_target &&
@@ -1103,10 +867,21 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
       was_copied = (status == svn_wc__db_status_copied ||
                     status == svn_wc__db_status_moved_here);
 
-      if (!base_shadowed)
+      if (!have_base)
         was_add = strcmp(op_root_abspath, local_abspath) == 0;
       else
-        was_replace = TRUE;
+        {
+          svn_wc__db_status_t base_status;
+          SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL,
+                                           db, local_abspath, pool, pool));
+
+          if (base_status != svn_wc__db_status_not_present)
+            was_replace = TRUE;
+          else
+            was_add = TRUE;
+        }
     }
 
   /* ### Maybe we should disallow deleting switched nodes here? */
@@ -1212,176 +987,6 @@ svn_wc_delete4(svn_wc_context_t *wc_ctx,
   return SVN_NO_ERROR;
 }
 
-
-svn_error_t *
-svn_wc__internal_get_ancestry(const char **url,
-                              svn_revnum_t *rev,
-                              svn_wc__db_t *db,
-                              const char *local_abspath,
-                              apr_pool_t *result_pool,
-                              apr_pool_t *scratch_pool)
-{
-  const svn_wc_entry_t *ent;
-
-  SVN_ERR(svn_wc__get_entry(&ent, db, local_abspath, FALSE,
-                            svn_node_unknown, FALSE,
-                            scratch_pool, scratch_pool));
-
-  if (url)
-    *url = apr_pstrdup(result_pool, ent->url);
-
-  if (rev)
-    *rev = ent->revision;
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Helper for mark_tree_copied(), handling the property juggling and
-   state changes for a single item LOCAL_ABSPATH (of kind LOCAL_KIND). */
-static svn_error_t *
-mark_item_copied(svn_wc__db_t *db,
-                 const char *local_abspath,
-                 svn_wc__db_kind_t local_kind,
-                 apr_pool_t *scratch_pool)
-{
-  apr_hash_t *props;
-  svn_wc_entry_t tmp_entry;
-  svn_node_kind_t kind = 
-    local_kind == svn_wc__db_kind_dir ? svn_node_dir : svn_node_unknown;
-
-  /* Squirrel away the pristine properties to install them on
-     working, because we might delete the base table */
-  SVN_ERR(svn_wc__db_read_pristine_props(&props, db, local_abspath,
-                                         scratch_pool, scratch_pool));
-  tmp_entry.copied = TRUE;
-  SVN_ERR(svn_wc__entry_modify(db, local_abspath, kind, &tmp_entry,
-                               SVN_WC__ENTRY_MODIFY_COPIED, scratch_pool));
-
-  /* Reinstall the pristine properties on WORKING */
-  /* ### this is all pretty crappy code anyways. not much of a problem
-     ### to pile on here.
-     ### thus... the node's original state may suggest there are no
-     ### pristine properties. in this case, we should say this (copied)
-     ### node has an empty set of properties.  */
-  if (props == NULL)
-    props = apr_hash_make(scratch_pool);
-  SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath, props,
-                                            scratch_pool));
-
-  /* Remove now obsolete dav cache values.  */
-  SVN_ERR(svn_wc__db_base_set_dav_cache(db, local_abspath, NULL,
-                                        scratch_pool));
-  
-  return SVN_NO_ERROR;
-}
-
-/* Recursively mark a tree DIR_ABSPATH (whose status is DIR_STATUS)
-   with a COPIED flag, skip items scheduled for deletion. */
-static svn_error_t *
-mark_tree_copied(svn_wc__db_t *db,
-                 const char *dir_abspath,
-                 svn_wc__db_status_t dir_status,
-                 const char *base_url,
-                 apr_pool_t *pool)
-{
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  const apr_array_header_t *children;
-  int i;
-
-  /* Tweak "this_dir" */
-  SVN_ERR(svn_wc__tweak_entry(db, dir_abspath, svn_node_dir, FALSE,
-                              base_url, SVN_INVALID_REVNUM,
-                              FALSE /* allow_removal */, iterpool));
-
-  /* Read the entries file for this directory. */
-  SVN_ERR(svn_wc__db_read_children(&children, db, dir_abspath,
-                                   pool, iterpool));
-
-  /* Mark each entry in the entries file. */
-  for (i = 0; i < children->nelts; i++)
-    {
-      const char *child_basename = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-      svn_wc__db_status_t child_status;
-      svn_wc__db_kind_t child_kind;
-      const char *child_url = NULL;
-
-      /* Clear our per-iteration pool. */
-      svn_pool_clear(iterpool);
-
-      /* Derive the new URL for the current (child) entry */
-      if (base_url)
-        child_url = svn_path_url_add_component2(base_url, child_basename,
-                                                iterpool);
-
-      child_abspath = svn_dirent_join(dir_abspath, child_basename, iterpool);
-
-      SVN_ERR(svn_wc__db_read_info(&child_status, &child_kind, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                   NULL, NULL, NULL, NULL, NULL, NULL,
-                                   db, child_abspath, iterpool, iterpool));
-
-      /* ### "svn add" won't create excluded nodes, but "svn copy" will.
-         ### it copies all metadata, carrying over the excluded nodes.  */
-
-      /* If a file, or deleted, excluded or absent dir, then tweak the
-         entry but don't recurse.
-
-         ### how does this translate into wc_db land? */
-      if (child_kind == svn_wc__db_kind_file
-          || child_status == svn_wc__db_status_not_present
-          || child_status == svn_wc__db_status_absent
-          || child_status == svn_wc__db_status_excluded)
-        {
-          if (child_kind == svn_wc__db_kind_dir)
-            SVN_ERR(svn_wc__tweak_entry(db, child_abspath, svn_node_dir,
-                                        TRUE /* parent_stub */,
-                                        child_url, SVN_INVALID_REVNUM,
-                                        TRUE /* allow_removal */,
-                                        iterpool));
-          else
-            SVN_ERR(svn_wc__tweak_entry(db, child_abspath, svn_node_file,
-                                        FALSE /* parent_stub */,
-                                        child_url, SVN_INVALID_REVNUM,
-                                        TRUE /* allow_removal */,
-                                        iterpool));
-        }
-
-      /* Skip deleted items, or otherwise "not really here" nodes.  */
-      if (child_status == svn_wc__db_status_deleted
-          || child_status == svn_wc__db_status_obstructed_delete
-          || child_status == svn_wc__db_status_not_present
-          || child_status == svn_wc__db_status_absent
-          || child_status == svn_wc__db_status_excluded)
-        continue;
-
-      /* If this is a directory, recurse; otherwise, do real work. */
-      if (child_kind == svn_wc__db_kind_dir)
-        {
-          SVN_ERR(mark_tree_copied(db, child_abspath, child_status, child_url,
-                                   iterpool));
-        }
-      else
-        {
-          SVN_ERR(mark_item_copied(db, child_abspath, child_kind, iterpool));
-        }
-    }
-
-  /* Here's where we handle directories. */
-  if (dir_status != svn_wc__db_status_deleted
-      && dir_status != svn_wc__db_status_obstructed_delete)
-    {
-      SVN_ERR(mark_item_copied(db, dir_abspath, svn_wc__db_kind_dir,
-                               iterpool));
-    }
-
-  /* Destroy our per-iteration pool. */
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_wc_add4(svn_wc_context_t *wc_ctx,
             const char *local_abspath,
@@ -1392,338 +997,406 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
             void *cancel_baton,
             svn_wc_notify_func2_t notify_func,
             void *notify_baton,
-            apr_pool_t *pool)
+            apr_pool_t *scratch_pool)
 {
   const char *parent_abspath;
   const char *base_name;
-  const svn_wc_entry_t *parent_entry;
-  svn_wc_entry_t tmp_entry;
+  const char *parent_repos_relpath;
+  const char *repos_root_url, *repos_uuid;
   svn_boolean_t is_replace = FALSE;
+  svn_boolean_t is_wc_root = FALSE;
   svn_node_kind_t kind;
-  int modify_flags;
+  svn_boolean_t node_exists;
   svn_wc__db_t *db = wc_ctx->db;
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_wc__db_kind_t db_kind;
   svn_boolean_t exists;
-  apr_hash_t *props;
 
-  svn_dirent_split(local_abspath, &parent_abspath, &base_name, pool);
-  if (svn_wc_is_adm_dir(base_name, pool))
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+  SVN_ERR_ASSERT(!copyfrom_url || (svn_uri_is_canonical(copyfrom_url,
+                                                        scratch_pool)
+                                   && SVN_IS_VALID_REVNUM(copyfrom_rev)));
+
+  svn_dirent_split(&parent_abspath, &base_name, local_abspath, scratch_pool);
+  if (svn_wc_is_adm_dir(base_name, scratch_pool))
     return svn_error_createf
       (SVN_ERR_ENTRY_FORBIDDEN, NULL,
        _("Can't create an entry with a reserved name while trying to add '%s'"),
-       svn_dirent_local_style(local_abspath, pool));
+       svn_dirent_local_style(local_abspath, scratch_pool));
 
-  SVN_ERR(svn_path_check_valid(local_abspath, pool));
+  SVN_ERR(svn_path_check_valid(local_abspath, scratch_pool));
 
   /* Make sure something's there. */
-  SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
+  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
   if (kind == svn_node_none)
     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
                              _("'%s' not found"),
-                             svn_dirent_local_style(local_abspath, pool));
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
   if (kind == svn_node_unknown)
     return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                              _("Unsupported node kind for path '%s'"),
-                             svn_dirent_local_style(local_abspath, pool));
-
-  /* Get the original entry for this path if one exists (perhaps
-     this is actually a replacement of a previously deleted thing).
-
-     Note that this is one of the few functions that is allowed to see
-     'deleted' entries;  it's totally fine to have an entry that is
-     scheduled for addition and still previously 'deleted'.  */
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
 
+  /* Get the node information for this path if one exists (perhaps
+     this is actually a replacement of a previously deleted thing). */
   err = svn_wc__db_read_info(&status, &db_kind, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL,
-                             db, local_abspath, pool, pool);
+                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                             NULL, NULL, NULL,
+                             db, local_abspath,
+                             scratch_pool, scratch_pool);
 
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+  if (err)
     {
+      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_return(err);
+
       svn_error_clear(err);
       exists = FALSE;
+      is_wc_root = FALSE;
+      node_exists = FALSE;
     }
   else
     {
-      svn_wc__db_kind_t on_disk;
-
-      SVN_ERR(err);
+      is_wc_root = FALSE;
       exists = TRUE;
-
-      on_disk = ((kind == svn_node_dir)
-                   ? svn_wc__db_kind_dir
-                   : svn_wc__db_kind_file);
-
+      node_exists = TRUE;
       switch (status)
         {
           case svn_wc__db_status_not_present:
-            exists = TRUE; /* ### Make FALSE once we use SHA1 based pristine */
-            break; /* Already gone */
+            node_exists = FALSE;
+            break;
           case svn_wc__db_status_deleted:
           case svn_wc__db_status_obstructed_delete:
-            exists = TRUE; /* ### Make FALSE once we use SHA1 based pristine */
+            /* A working copy root should never have a WORKING_NODE */
+            SVN_ERR_ASSERT(!is_wc_root);
+            node_exists = FALSE;
             is_replace = TRUE;
-            break; /* Safe to add */
+            break;
+          case svn_wc__db_status_normal:
+            if (copyfrom_url)
+              {
+                SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
+                                              db, local_abspath,
+                                              scratch_pool));
 
-          default:
-            if (copyfrom_url != NULL)
-              break; /* Just register as copied */
-            /* else fall through */
+                if (is_wc_root)
+                  break;
+              }
+            /* else: Fall through in default error */
 
-          case svn_wc__db_status_excluded:
-          case svn_wc__db_status_absent:
+          default:
             return svn_error_createf(
                              SVN_ERR_ENTRY_EXISTS, NULL,
                              _("'%s' is already under version control"),
-                             svn_dirent_local_style(local_abspath, pool));
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
         }
+    } /* err */
 
-      /* ### Remove this check once we are fully switched to one wcroot db */
-      if (exists && db_kind != on_disk)
-        {
-          /* ### todo: At some point, we obviously don't want to block
-             replacements where the node kind changes.  When this
-             happens, svn_wc_revert3() needs to learn how to revert
-             this situation.  At present we are using a specific node-change
-             error so that clients can detect it. */
-          return svn_error_createf
-            (SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
-             _("Can't replace '%s' with a node of a differing type; "
-               "the deletion must be committed and the parent updated "
-               "before adding '%s'"),
-             svn_dirent_local_style(local_abspath, pool),
-             svn_dirent_local_style(local_abspath, pool));
-        }
-    }
+#ifndef SINGLE_DB
+    if (exists 
+        && ((kind == svn_node_dir && db_kind != svn_wc__db_kind_dir)
+            || (kind == svn_node_file && db_kind != svn_wc__db_kind_file)))
+      return svn_error_createf(
+                 SVN_ERR_WC_NODE_KIND_CHANGE, NULL,
+                 _("Can't replace '%s' with a node of a differing type; "
+                   "the deletion must be committed and the parent updated "
+                   "before adding '%s'"),
+                 svn_dirent_local_style(local_abspath, scratch_pool),
+                 svn_dirent_local_style(local_abspath, scratch_pool));
+#endif
 
-  SVN_ERR(svn_wc__get_entry(&parent_entry, db, parent_abspath,
-                            TRUE /* allow_unversioned */,
-                            svn_node_dir,
-                            FALSE /* need_parent_stub */,
-                            pool, pool));
-  if (! parent_entry)
-    return svn_error_createf
-      (SVN_ERR_ENTRY_NOT_FOUND, NULL,
-       _("Can't find parent directory's entry while trying to add '%s'"),
-       svn_dirent_local_style(local_abspath, pool));
+  {
+    svn_wc__db_status_t parent_status;
+    svn_wc__db_kind_t parent_kind;
 
-  if (parent_entry->schedule == svn_wc_schedule_delete)
-    return svn_error_createf
-      (SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
-       _("Can't add '%s' to a parent directory scheduled for deletion"),
-       svn_dirent_local_style(local_abspath, pool));
+    err = svn_wc__db_read_info(&parent_status, &parent_kind, NULL,
+                               &parent_repos_relpath, &repos_root_url,
+                               &repos_uuid, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL,
+                               db, parent_abspath, scratch_pool, scratch_pool);
 
-  /* Init the modify flags. */
-  tmp_entry.schedule = svn_wc_schedule_add;
-  tmp_entry.kind = kind;
-  modify_flags = SVN_WC__ENTRY_MODIFY_SCHEDULE | SVN_WC__ENTRY_MODIFY_KIND;
+    if (err
+        || parent_status == svn_wc__db_status_not_present
+        || parent_status == svn_wc__db_status_excluded
+        || parent_status == svn_wc__db_status_absent
+        || parent_status == svn_wc__db_status_obstructed
+        || parent_status == svn_wc__db_status_obstructed_add)
+      {
+        return
+          svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, err,
+                            _("Can't find parent directory's entry while"
+                              " trying to add '%s'"),
+                            svn_dirent_local_style(local_abspath,
+                                                   scratch_pool));
+      }
+    else if (parent_status == svn_wc__db_status_deleted
+             || parent_status == svn_wc__db_status_obstructed_delete)
+      {
+        return
+          svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
+                            _("Can't add '%s' to a parent directory"
+                              " scheduled for deletion"),
+                            svn_dirent_local_style(local_abspath,
+                                                   scratch_pool));
+      }
+    else if (parent_kind != svn_wc__db_kind_dir)
+      /* Can't happen until single db; but then it causes serious
+         trouble if we allow this. */
+      return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                               _("Can't schedule an addition of '%s'"
+                                 " below a not-directory node"),
+                               svn_dirent_local_style(local_abspath,
+                                                   scratch_pool));
 
-  if (! (is_replace || copyfrom_url))
-    {
-      tmp_entry.revision = 0;
-      modify_flags |= SVN_WC__ENTRY_MODIFY_REVISION;
-    }
+    if (!repos_root_url)
+      {
+        if (parent_status == svn_wc__db_status_added)
+          SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &parent_repos_relpath,
+                                           &repos_root_url, &repos_uuid, NULL,
+                                           NULL, NULL, NULL,
+                                           db, parent_abspath,
+                                           scratch_pool, scratch_pool));
+        else
+          SVN_ERR(svn_wc__db_scan_base_repos(&parent_repos_relpath,
+                                             &repos_root_url, &repos_uuid,
+                                             db, parent_abspath,
+                                             scratch_pool, scratch_pool));
+      }
+
+    if (copyfrom_url
+        && !svn_uri_is_ancestor(repos_root_url, copyfrom_url))
+      return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                               _("The URL '%s' has a different repository "
+                                 "root than its parent"), copyfrom_url);
+  }
 
-  /* If a copy ancestor was given, make sure the copyfrom URL is in the same
-     repository (if possible) and put the proper ancestry info in the new
-     entry */
-  if (copyfrom_url)
+  /* Verify that we can actually integrate the inner working copy */
+  if (is_wc_root)
     {
-      if (parent_entry->repos
-          && ! svn_uri_is_ancestor(parent_entry->repos, copyfrom_url))
+      const char *repos_relpath, *inner_repos_root_url, *inner_repos_uuid;
+      const char *inner_url;
+
+      SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
+                                         &inner_repos_root_url,
+                                         &inner_repos_uuid,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+
+      if (strcmp(inner_repos_uuid, repos_uuid)
+          || strcmp(repos_root_url, inner_repos_root_url))
         return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                                 _("The URL '%s' has a different repository "
-                                   "root than its parent"), copyfrom_url);
-      tmp_entry.copyfrom_url = copyfrom_url;
-      tmp_entry.copyfrom_rev = copyfrom_rev;
-      tmp_entry.copied = TRUE;
-      modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL;
-      modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_REV;
-      modify_flags |= SVN_WC__ENTRY_MODIFY_COPIED;
-    }
-
-  /* If this is a replacement we want to remove the checksum and the property
-     flags so they are not set to their respective old values. */
-  if (is_replace)
-    {
-      tmp_entry.checksum = NULL;
-      modify_flags |= SVN_WC__ENTRY_MODIFY_CHECKSUM;
-    }
+                                 _("Can't schedule the working copy at '%s' "
+                                   "from repository '%s' with uuid '%s' "
+                                   "for addition under a working copy from "
+                                   "repository '%s' with uuid '%s'."),
+                                 svn_dirent_local_style(local_abspath,
+                                                        scratch_pool),
+                                 inner_repos_root_url, inner_repos_uuid,
+                                 repos_root_url, repos_uuid);
 
+      if (!svn_uri_is_ancestor(repos_root_url, copyfrom_url))
+        return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                 _("The URL '%s' is not in repository '%s'"),
+                                 copyfrom_url, repos_root_url);
 
-  /* Store the pristine properties to install them on working, because
-     we might delete the base table */
-  if ((exists && status != svn_wc__db_status_not_present)
-      && !is_replace && copyfrom_url != NULL)
-    {
-      /* NOTE: the conditions to reach here *exactly* match the
-         conditions used below when PROPS is referenced.
-         Be careful to keep these sets of conditionals aligned to avoid
-         an uninitialized PROPS value.  */
-      SVN_ERR(svn_wc__db_read_pristine_props(&props, db, local_abspath,
-                                             pool, pool));
+      inner_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+                                             scratch_pool);
+
+      if (strcmp(copyfrom_url, inner_url))
+        return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                                 _("Can't add '%s' with URL '%s', but with "
+                                   "the data from '%s'"),
+                                 svn_dirent_local_style(local_abspath,
+                                                        scratch_pool),
+                                 copyfrom_url, inner_url);
+    }
+#ifndef SINGLE_DB
+  else if (kind == svn_node_dir && !node_exists && !is_replace)
+    {
+      svn_wc__db_status_t absent_status;
+      svn_wc__db_kind_t absent_kind;
+      const char *absent_repos_relpath, *absent_repos_root_url;
+      const char *absent_repos_uuid;
+      svn_revnum_t absent_revision;
+
+      /* Read the not present status from the parent working copy,
+         to reinsert it after hooking up the child working copy */
+
+      err = svn_wc__db_base_get_info(&absent_status,
+                                     &absent_kind,
+                                     &absent_revision,
+                                     &absent_repos_relpath,
+                                     &absent_repos_root_url,
+                                     &absent_repos_uuid,
+                                     NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL,
+                                     db, local_abspath,
+                                     scratch_pool, scratch_pool);
+
+      if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_return(err);
+      else
+        svn_error_clear(err);
+
+      /* Make sure this new directory has an admistrative subdirectory
+         created inside of it.
+
+         This creates a BASE_NODE for an added directory, really
+         it should create a WORKING_NODE.  We just remove the
+         node directly (without touching a possible not-present
+         node in the parent stub) */
+      SVN_ERR(svn_wc__internal_ensure_adm(db, local_abspath,
+                                          repos_root_url, repos_root_url,
+                                          repos_uuid, 0,
+                                          depth, scratch_pool));
+
+      if (!err && absent_status == svn_wc__db_status_not_present)
+        SVN_ERR(svn_wc__db_base_add_absent_node(db, local_abspath,
+                                                absent_repos_relpath,
+                                                absent_repos_root_url,
+                                                absent_repos_uuid,
+                                                absent_revision,
+                                                absent_kind,
+                                                absent_status,
+                                                NULL,
+                                                NULL,
+                                                scratch_pool));
+      else
+        SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
     }
+#endif
 
-  if (modify_flags)
+  if (kind == svn_node_dir && !exists)
     {
-      if (kind == svn_node_dir)
-        SVN_ERR(svn_wc__entry_modify_stub(db, local_abspath,
-                                          &tmp_entry, modify_flags, pool));
-      else
-        SVN_ERR(svn_wc__entry_modify(db, local_abspath, kind,
-                                     &tmp_entry, modify_flags, pool));
+      /* Lock on parent needs to be propogated into the child db. */
+      SVN_ERR(svn_wc__db_wclock_set(db, local_abspath, 0, scratch_pool));
+      SVN_ERR(svn_wc__db_temp_mark_locked(db, local_abspath, scratch_pool));
     }
 
 #if (SVN_WC__VERSION < SVN_WC__PROPS_IN_DB)
-  /* If this is a replacement without history, we need to reset the
-     properties for PATH. */
   /* ### this is totally bogus. we clear these cuz turds might have been
-     ### left around. thankfully, this will be properly managed during the
-     ### wc-ng upgrade process. for now, we try to compensate... */
-  if (((exists && status != svn_wc__db_status_not_present) || is_replace)
-      && copyfrom_url == NULL)
+     ### left around. Thankfully, this will gone soon... */
+  if (!is_wc_root && (node_exists || is_replace))
     SVN_ERR(svn_wc__props_delete(db, local_abspath, svn_wc__props_working,
-                                 pool));
+                                 scratch_pool));
+#endif
+
+#if !defined(SVN_EXPERIMENTAL_PRISTINE) || (SVN_WC__VERSION < SVN_WC__PROPS_IN_DB)
+    if (is_replace)
+      {
+        /* We don't want the old base text (if any) and base props to be
+           mistakenly used as the bases for the new, replacement object.
+           So, move them out of the way. */
+
+        /* ### TODO: In an ideal world, this whole function would be loggy.
+           ### Thankfully this code will be gone soon. */
+        SVN_ERR(svn_wc__wq_prepare_revert_files(db, local_abspath,
+                                                scratch_pool));
+        SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                               cancel_func, cancel_baton, scratch_pool));
+      }
 #endif
 
-  if (is_replace)
+  if (kind == svn_node_file)
     {
-      /* We don't want the old base text (if any) and base props to be
-         mistakenly used as the bases for the new, replacement object.
-         So, move them out of the way. */
-
-      /* ### TODO: In an ideal world, this whole function would be loggy.
-       * ### But the directory recursion code below is already tangled
-       * ### enough, and re-doing the code above would require setting
-       * ### up more of tmp_entry.  It's more than a SMOP.  For now,
-       * ### I'm leaving it be, though we set up the revert base(s)
-       * ### loggily because that's Just How It's Done.
-       */
-      SVN_ERR(svn_wc__wq_prepare_revert_files(db, local_abspath, pool));
-      SVN_ERR(svn_wc__wq_run(db, local_abspath,
-                             cancel_func, cancel_baton, pool));
-    }
-
-  if (kind == svn_node_dir) /* scheduling a directory for addition */
-    {
-      if (! copyfrom_url)
-        {
-          const char *new_url;
-
-          /* Derive the parent path for our new addition here. */
-          new_url = svn_path_url_add_component2(parent_entry->url, base_name,
-                                                pool);
-
-          /* Make sure this new directory has an admistrative subdirectory
-             created inside of it.
-
-             This creates a BASE_NODE for an added directory, really
-             it should create a WORKING_NODE.  It gets removed by the
-             next modify2 call. */
-          SVN_ERR(svn_wc__internal_ensure_adm(db, local_abspath,
-                                              new_url, parent_entry->repos,
-                                              parent_entry->uuid, 0,
-                                              depth, pool));
-        }
+      if (!copyfrom_url)
+        SVN_ERR(svn_wc__db_op_add_file(db, local_abspath, NULL, scratch_pool));
       else
         {
-          /* When we are called with the copyfrom arguments set and with
-             the admin directory already in existence, then the dir will
-             contain the copyfrom settings.  So we need to pass the
-             copyfrom arguments to the ensure call. */
-          SVN_ERR(svn_wc__internal_ensure_adm(db, local_abspath,
-                                              copyfrom_url,
-                                              parent_entry->repos,
-                                              parent_entry->uuid,
-                                              copyfrom_rev, depth, pool));
-        }
-
-      /* ### This block can be removed after we centralise the db and have
-         ### infinite depth admin locks. */
-      if (! exists)
-        {
-          /* Lock on parent needs to be propogated into the child db. */
-          SVN_ERR(svn_wc__db_wclock_set(db, local_abspath, 0, pool));
-          SVN_ERR(svn_wc__db_temp_mark_locked(db, local_abspath, pool));
-        }
-
-      /* We're making the same mods we made above, but this time we'll
-         force the scheduling.  Also make sure to undo the
-         'incomplete' flag which svn_wc__internal_ensure_adm() sets by
-         default.
-
-         This deletes the erroneous BASE_NODE for added directories and
-         adds a WORKING_NODE. */
-      if (modify_flags)
-        {
-          modify_flags |= SVN_WC__ENTRY_MODIFY_FORCE;
-          tmp_entry.schedule = (is_replace
-                                ? svn_wc_schedule_replace
-                                : svn_wc_schedule_add);
-          SVN_ERR(svn_wc__entry_modify(db, local_abspath, svn_node_dir,
-                                       &tmp_entry, modify_flags, pool));
-        }
-
-      SVN_ERR(svn_wc__db_temp_op_set_working_incomplete(
-                db, local_abspath, FALSE, pool));
-
-      if (copyfrom_url)
-        {
-          /* If this new directory has ancestry, it's not enough to
-             schedule it for addition with copyfrom args.  We also
-             need to rewrite its ancestor-url, and rewrite the
-             ancestor-url of ALL its children!
-
-             We're doing this because our current commit model (for
-             hysterical raisins, presumably) assumes an entry's URL is
-             correct before commit -- i.e. the URL is not tweaked in
-             the post-commit bumping process.  We might want to change
-             this model someday. */
-
-          /* Figure out what the new url should be. */
-          const char *new_url =
-            svn_path_url_add_component2(parent_entry->url, base_name, pool);
-
-          /* ### copy.c will copy .svn subdirs, which means the whole
-             ### subtree is already "versioned". we now need to rejigger
-             ### the metadata to make it Proper for this location.  */
-
-          /* Recursively add the 'copied' existence flag as well!  */
-          SVN_ERR(mark_tree_copied(db, local_abspath,
-                                   exists ? status : svn_wc__db_status_added,
-                                   new_url,
-                                   pool));
-
-          /* Clean out the now-obsolete dav cache values.  */
-          /* ### put this into above walk. clear all cached values.  */
-          SVN_ERR(svn_wc__db_base_set_dav_cache(db, local_abspath, NULL,
-                                                pool));
-        }
-    }
-
-  /* Set the pristine properties in WORKING_NODE, by copying them from the
-     deleted BASE_NODE record. Or set them to empty to make sure we don't
-     inherit wrong properties from BASE */
-  if (exists && status != svn_wc__db_status_not_present)
-    {
-      if (!is_replace && copyfrom_url != NULL)
-        {
-          /* NOTE: the conditions to reach here *exactly* match the
-             conditions that were used to initialize the PROPS localvar.
-             Be careful to keep these sets of conditionals aligned to avoid
-             an uninitialized PROPS value.  */
-          SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath, props,
-                                                    pool));
+          /* This code should never be used, as it doesn't install proper
+             pristine and/or properties. But it was not an error in the old
+             version of this function. 
+
+             ===> Use svn_wc_add_repos_file4() directly! */
+          svn_stream_t *content = svn_stream_empty(scratch_pool);
+
+          SVN_ERR(svn_wc_add_repos_file4(wc_ctx, local_abspath,
+                                         content, NULL,
+                                         NULL, NULL,
+                                         copyfrom_url, copyfrom_rev,
+                                         cancel_func, cancel_baton,
+                                         NULL, NULL,
+                                         scratch_pool));
         }
+    }
+  else if (!copyfrom_url)
+    SVN_ERR(svn_wc__db_op_add_directory(db, local_abspath, NULL,
+                                        scratch_pool));
+  else if (!is_wc_root)
+    SVN_ERR(svn_wc__db_op_copy_dir(db,
+                                   local_abspath,
+                                   apr_hash_make(scratch_pool),
+                                   copyfrom_rev,
+                                   0,
+                                   NULL,
+                                   svn_path_uri_decode(
+                                        svn_uri_skip_ancestor(repos_root_url,
+                                                              copyfrom_url),
+                                        scratch_pool),
+                                   repos_root_url,
+                                   repos_uuid,
+                                   copyfrom_rev,
+                                   NULL,
+                                   depth,
+                                   NULL,
+                                   NULL,
+                                   scratch_pool));
+  else
+    {
+      svn_wc__db_status_t absent_status;
+      svn_wc__db_kind_t absent_kind;
+      const char *absent_repos_relpath, *absent_repos_root_url;
+      const char *absent_repos_uuid;
+      svn_revnum_t absent_revision;
+
+      /* Read the not present status from the parent working copy,
+         to reinsert it after hooking up the child working copy */
+
+      err = svn_wc__db_base_get_info_from_parent(&absent_status,
+                                                 &absent_kind,
+                                                 &absent_revision,
+                                                 &absent_repos_relpath,
+                                                 &absent_repos_root_url,
+                                                 &absent_repos_uuid,
+                                                 db, local_abspath,
+                                                 scratch_pool, scratch_pool);
+
+      if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+        return svn_error_return(err);
       else
-        {
-          SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath,
-                                                    apr_hash_make(pool),
-                                                    pool));
-        }
+        svn_error_clear(err);
+
+      /* ### Temporary hack: Hook the inner working copy to the parent
+             working copy to work around that temp_op_make_copy() doesn't
+             add a working_node stub for its root if there is no base_node
+             stub. */
+      SVN_ERR(svn_wc__db_temp_set_parent_stub_to_normal(db, local_abspath,
+                                                        FALSE, scratch_pool));
+
+      /* Transfer all nodes below LOCAL_ABSPATH from BASE_NODE to
+         WORKING_NODE */
+      SVN_ERR(svn_wc__db_temp_op_make_copy(db, local_abspath, TRUE,
+                                           scratch_pool));
+
+      if (!err && absent_status == svn_wc__db_status_not_present)
+        SVN_ERR(svn_wc__db_base_add_absent_node(db, local_abspath,
+                                                absent_repos_relpath,
+                                                absent_repos_root_url,
+                                                absent_repos_uuid,
+                                                absent_revision,
+                                                absent_kind,
+                                                absent_status,
+                                                NULL,
+                                                NULL,
+                                                scratch_pool));
+      else
+        SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
     }
 
   /* Report the addition to the caller. */
@@ -1731,33 +1404,33 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
     {
       svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath,
                                                      svn_wc_notify_add,
-                                                     pool);
+                                                     scratch_pool);
       notify->kind = kind;
-      (*notify_func)(notify_baton, notify, pool);
+      (*notify_func)(notify_baton, notify, scratch_pool);
     }
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_wc_register_file_external(svn_wc_context_t *wc_ctx,
-                              const char *local_abspath,
-                              const char *external_url,
-                              const svn_opt_revision_t *external_peg_rev,
-                              const svn_opt_revision_t *external_rev,
-                              apr_pool_t *scratch_pool)
+svn_wc__register_file_external(svn_wc_context_t *wc_ctx,
+                               const char *local_abspath,
+                               const char *external_url,
+                               const svn_opt_revision_t *external_peg_rev,
+                               const svn_opt_revision_t *external_rev,
+                               apr_pool_t *scratch_pool)
 {
   svn_wc__db_t *db = wc_ctx->db;
   const char *parent_abspath, *base_name, *repos_root_url;
 
-  svn_dirent_split(local_abspath, &parent_abspath, &base_name, scratch_pool);
+  svn_dirent_split(&parent_abspath, &base_name, local_abspath, scratch_pool);
 
-  SVN_ERR(svn_wc_add4(wc_ctx, local_abspath, svn_depth_infinity,
-                      NULL, SVN_INVALID_REVNUM, NULL, NULL, NULL, NULL,
-                      scratch_pool));
   SVN_ERR(svn_wc__db_scan_base_repos(NULL, &repos_root_url, NULL, db,
                                      parent_abspath, scratch_pool,
                                      scratch_pool));
+
+  SVN_ERR(svn_wc__db_op_add_file(wc_ctx->db, local_abspath, NULL, scratch_pool));
+
   SVN_ERR(svn_wc__set_file_external_location(wc_ctx, local_abspath,
                                              external_url, external_peg_rev,
                                              external_rev, repos_root_url,
@@ -1857,6 +1530,7 @@ revert_entry(svn_depth_t *depth,
   svn_wc__db_status_t status;
   svn_wc__db_kind_t kind;
   svn_boolean_t replaced;
+  svn_boolean_t have_base;
 
   /* Initialize this even though revert_admin_things() is guaranteed
      to set it, because we don't know that revert_admin_things() will
@@ -1866,8 +1540,8 @@ revert_entry(svn_depth_t *depth,
   SVN_ERR(svn_wc__db_read_info(&status, &kind,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL,
+                               NULL, NULL, NULL, NULL, &have_base, NULL,
+                               NULL, NULL,
                                db, local_abspath, pool, pool));
 
   SVN_ERR(svn_wc__internal_is_replaced(&replaced, db, local_abspath, pool));
@@ -1882,14 +1556,39 @@ revert_entry(svn_depth_t *depth,
       const char *repos_root_url;
       const char *repos_uuid;
       /* Before removing item from revision control, notice if the
-         entry is in a 'deleted' state; this is critical for
-         directories, where this state only exists in its parent's
-         entry. */
-      svn_boolean_t was_deleted = FALSE;
-
-      /* NOTE: if WAS_DELETED gets set, then we have BASE nodes. The code
-         below will then figure out the repository information, so that
-         we can later insert a node for the same repository.  */
+         BASE_NODE is in a 'not-present' state. */
+      svn_boolean_t was_not_present = FALSE;
+
+      /* NOTE: if WAS_NOT_PRESENT gets set, then we have BASE nodes.
+         The code below will then figure out the repository information, so
+         that we can later insert a node for the same repository. */
+
+      if (have_base)
+        {
+            svn_wc__db_status_t base_status;
+            SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
+                                             &base_revision, &repos_relpath,
+                                             &repos_root_url, &repos_uuid,
+                                             NULL, NULL, NULL, NULL, NULL,
+                                             NULL, NULL, NULL, NULL,
+                                             db, local_abspath,
+                                             pool, pool));
+
+            if (base_status == svn_wc__db_status_not_present)
+            {
+                /* Remember the BASE revision.  */
+                /* Remember the repository this node is associated with.  */
+
+                was_not_present = TRUE;
+
+                if (!repos_root_url)
+                  SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
+                                                     &repos_root_url,
+                                                     &repos_uuid,
+                                                     db, local_abspath,
+                                                     pool, pool));
+            }
+        }
 
       /* ### much of this is probably bullshit. we should be able to just
          ### remove the WORKING and ACTUAL rows, and be done. but we're
@@ -1899,25 +1598,6 @@ revert_entry(svn_depth_t *depth,
 
       if (kind == svn_wc__db_kind_file)
         {
-          was_deleted = (status == svn_wc__db_status_not_present);
-          if (was_deleted)
-            {
-              /* Remember the BASE revision.  */
-              SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &base_revision,
-                                               NULL, NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL,
-                                               db, local_abspath,
-                                               pool, pool));
-
-              /* Remember the repository this node is associated with.  */
-              SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
-                                                 &repos_root_url,
-                                                 &repos_uuid,
-                                                 db, local_abspath,
-                                                 pool, pool));
-            }
-
           SVN_ERR(svn_wc__internal_remove_from_revision_control(db,
                                                                 local_abspath,
                                                                 FALSE, FALSE,
@@ -1927,29 +1607,6 @@ revert_entry(svn_depth_t *depth,
         }
       else if (kind == svn_wc__db_kind_dir)
         {
-          /* We don't need to check for excluded item, since we won't fall
-             into this code path in that case. */
-
-          SVN_ERR(svn_wc__node_is_deleted(&was_deleted, db, local_abspath,
-                                          pool));
-          if (was_deleted)
-            {
-              /* Remember the BASE revision.  */
-              SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &base_revision,
-                                               NULL, NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL, NULL,
-                                               NULL, NULL, NULL,
-                                               db, local_abspath,
-                                               pool, pool));
-
-              /* Remember the repository this node is associated with.  */
-              SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath,
-                                                 &repos_root_url,
-                                                 &repos_uuid,
-                                                 db, local_abspath,
-                                                 pool, pool));
-            }
-
           if (disk_kind == svn_node_none
               || svn_wc__adm_missing(db, local_abspath, pool))
             {
@@ -1987,10 +1644,9 @@ revert_entry(svn_depth_t *depth,
       *depth = svn_depth_empty;
       reverted = TRUE;
 
-      /* If the removed item was *also* in a 'deleted' state, make
-         sure we leave just a plain old 'deleted' entry behind in the
-         parent. */
-      if (was_deleted)
+      /* If the removed item was *also* in a 'not-present' state, make
+         sure we leave a not-present node behind */
+      if (was_not_present)
         {
           SVN_ERR(svn_wc__db_base_add_absent_node(
                     db, local_abspath,
@@ -2388,7 +2044,7 @@ svn_wc__internal_remove_from_revision_co
 
 #ifdef SVN_EXPERIMENTAL_PRISTINE
       /* Find the checksum(s) of the node's one or two pristine texts.  Note
-         that read_info() may give us the one from WORKING_NODE again. */
+         that read_info() may give us the one from BASE_NODE again. */
       err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
                                      NULL, NULL, NULL, NULL, NULL,
                                      &base_sha1_checksum,
@@ -2724,22 +2380,6 @@ svn_wc_set_changelist2(svn_wc_context_t 
       && strcmp(existing_changelist, changelist) == 0)
     return SVN_NO_ERROR;
 
-  /* If the path is already a member of a changelist, warn the
-     user about this, but still allow the reassignment to happen. */
-  if (existing_changelist && changelist && notify_func)
-    {
-      svn_error_t *reassign_err =
-        svn_error_createf(SVN_ERR_WC_CHANGELIST_MOVE, NULL,
-                          _("Removing '%s' from changelist '%s'."),
-                          local_abspath, existing_changelist);
-      notify = svn_wc_create_notify(local_abspath,
-                                    svn_wc_notify_changelist_moved,
-                                    scratch_pool);
-      notify->err = reassign_err;
-      notify_func(notify_baton, notify, scratch_pool);
-      svn_error_clear(notify->err);
-    }
-
   /* Set the changelist. */
   SVN_ERR(svn_wc__db_op_set_changelist(wc_ctx->db, local_abspath, changelist,
                                        scratch_pool));
@@ -2747,13 +2387,23 @@ svn_wc_set_changelist2(svn_wc_context_t 
   /* And tell someone what we've done. */
   if (notify_func)
     {
-      notify = svn_wc_create_notify(local_abspath,
-                                    changelist
-                                    ? svn_wc_notify_changelist_set
-                                    : svn_wc_notify_changelist_clear,
-                                    scratch_pool);
-      notify->changelist_name = changelist;
-      notify_func(notify_baton, notify, scratch_pool);
+      if (existing_changelist)
+        {
+          notify = svn_wc_create_notify(local_abspath,
+                                        svn_wc_notify_changelist_clear,
+                                        scratch_pool);
+          notify->changelist_name = existing_changelist;
+          notify_func(notify_baton, notify, scratch_pool);
+        }
+
+      if (changelist)
+        {
+          notify = svn_wc_create_notify(local_abspath,
+                                        svn_wc_notify_changelist_set,
+                                        scratch_pool);
+          notify->changelist_name = changelist;
+          notify_func(notify_baton, notify, scratch_pool);
+        }
     }
 
   return SVN_NO_ERROR;