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/10 22:56:05 UTC

svn commit: r984206 [25/35] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hudson/jobs/subvers...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c Tue Aug 10 20:55:56 2010
@@ -21,6 +21,8 @@
  * ====================================================================
  */
 
+#define SVN_WC__I_AM_WC_DB
+
 #include <assert.h>
 #include <apr_pools.h>
 #include <apr_hash.h>
@@ -40,6 +42,8 @@
 #include "entries.h"
 #include "lock.h"
 #include "tree_conflicts.h"
+#include "wc_db_private.h"
+#include "workqueue.h"
 
 #include "svn_private_config.h"
 #include "private/svn_sqlite.h"
@@ -102,80 +106,6 @@
 #define FORMAT_FROM_SDB (-1)
 
 
-struct svn_wc__db_t {
-  /* What's the appropriate mode for this datastore? */
-  svn_wc__db_openmode_t mode;
-
-  /* We need the config whenever we run into a new WC directory, in order
-     to figure out where we should look for the corresponding datastore. */
-  svn_config_t *config;
-
-  /* Should we attempt to automatically upgrade the database when it is
-     opened, and found to be not-current?  */
-  svn_boolean_t auto_upgrade;
-
-  /* Should we ensure the WORK_QUEUE is empty when a WCROOT is opened?  */
-  svn_boolean_t enforce_empty_wq;
-
-  /* Map a given working copy directory to its relevant data.
-     const char *local_abspath -> svn_wc__db_pdh_t *pdh  */
-  apr_hash_t *dir_data;
-
-  /* As we grow the state of this DB, allocate that state here. */
-  apr_pool_t *state_pool;
-};
-
-/** Hold information about a WCROOT.
- *
- * This structure is referenced by all per-directory handles underneath it.
- */
-typedef struct {
-  /* Location of this wcroot in the filesystem.  */
-  const char *abspath;
-
-  /* The SQLite database containing the metadata for everything in
-     this wcroot.  */
-  svn_sqlite__db_t *sdb;
-
-  /* The WCROOT.id for this directory (and all its children).  */
-  apr_int64_t wc_id;
-
-  /* The format of this wcroot's metadata storage (see wc.h). If the
-     format has not (yet) been determined, this will be UNKNOWN_FORMAT.  */
-  int format;
-
-} wcroot_t;
-
-/**  Pristine Directory Handle
- *
- * This structure records all the information that we need to deal with
- * a given working copy directory.
- */
-typedef struct svn_wc__db_pdh_t {
-  /* This (versioned) working copy directory is obstructing what *should*
-     be a file in the parent directory (according to its metadata).
-
-     Note: this PDH should probably be ignored (or not created).
-
-     ### obstruction is only possible with per-dir wc.db databases.  */
-  svn_boolean_t obstructed_file;
-
-  /* The absolute path to this working copy directory. */
-  const char *local_abspath;
-
-  /* What wcroot does this directory belong to?  */
-  wcroot_t *wcroot;
-
-  /* The parent directory's per-dir information. */
-  struct svn_wc__db_pdh_t *parent;
-
-  /* Whether this process owns a write-lock on this directory. */
-  svn_boolean_t locked;
-
-  /* Hold onto the old-style access baton that corresponds to this PDH.  */
-  svn_wc_adm_access_t *adm_access;
-} svn_wc__db_pdh_t;
-
 /* Assert that the given PDH is usable.
    NOTE: the expression is multiply-evaluated!!  */
 #define VERIFY_USABLE_PDH(pdh) SVN_ERR_ASSERT(  \
@@ -183,19 +113,6 @@ typedef struct svn_wc__db_pdh_t {
     && (pdh)->wcroot->format == SVN_WC__VERSION)
 
 
-/* Verify the checksum kind for pristine storage.  */
-#define VERIFY_CHECKSUM_KIND(checksum)                                     \
-  do {                                                                     \
-    if ((checksum)->kind != svn_checksum_sha1)                             \
-      return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL,             \
-                              _("Only SHA1 checksums can be used as keys " \
-                                "in the pristine file storage.\n"));       \
-  } while (0)
-/* ### not ready to enforce SHA1 yet. disable the check.  */
-#undef VERIFY_CHECKSUM_KIND
-#define VERIFY_CHECKSUM_KIND(checksum) ((void)0)
-
-
 /* ### since we're putting the pristine files per-dir, then we don't need
    ### to create subdirectories in order to keep the directory size down.
    ### when we can aggregate pristine files across dirs/wcs, then we will
@@ -239,9 +156,48 @@ typedef struct {
   /* for inserting symlinks */
   const char *target;
 
+  /* may need to insert/update ACTUAL to record a conflict  */
+  const svn_skel_t *conflict;
+
+  /* may have work items to queue in this transaction  */
+  const svn_skel_t *work_items;
+
 } insert_base_baton_t;
 
 
+typedef struct {
+  /* common to all insertions into WORKING */
+  svn_wc__db_status_t presence;
+  svn_wc__db_kind_t kind;
+  apr_int64_t wc_id;
+  const char *local_relpath;
+
+  /* common to all "normal" presence insertions */
+  const apr_hash_t *props;
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+  apr_int64_t original_repos_id;
+  const char *original_repos_relpath;
+  svn_revnum_t original_revnum;
+  svn_boolean_t moved_here;
+
+  /* for inserting directories */
+  const apr_array_header_t *children;
+  svn_depth_t depth;
+
+  /* for inserting (copied/moved-here) files */
+  const svn_checksum_t *checksum;
+
+  /* for inserting symlinks */
+  const char *target;
+
+  /* may have work items to queue in this transaction  */
+  const svn_skel_t *work_items;
+
+} insert_working_baton_t;
+
+
 static const svn_token_map_t kind_map[] = {
   { "file", svn_wc__db_kind_file },
   { "dir", svn_wc__db_kind_dir },
@@ -264,6 +220,13 @@ static const svn_token_map_t presence_ma
 };
 
 
+/* Forward declarations  */
+static svn_error_t *
+add_work_items(svn_sqlite__db_t *sdb,
+               const svn_skel_t *skel,
+               apr_pool_t *scratch_pool);
+
+
 /* */
 static svn_filesize_t
 get_translated_size(svn_sqlite__stmt_t *stmt, int slot)
@@ -313,138 +276,6 @@ escape_sqlite_like(const char * const st
 }
 
 
-/* */
-static svn_error_t *
-verify_no_work(svn_sqlite__db_t *sdb)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_LOOK_FOR_WORK));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  if (have_row)
-    return svn_error_create(SVN_ERR_WC_CLEANUP_REQUIRED, NULL,
-                            NULL /* nothing to add.  */);
-
-  return SVN_NO_ERROR;
-}
-
-
-/* */
-static apr_status_t
-close_wcroot(void *data)
-{
-  wcroot_t *wcroot = data;
-  svn_error_t *err;
-
-  SVN_ERR_ASSERT_NO_RETURN(wcroot->sdb != NULL);
-
-  err = svn_sqlite__close(wcroot->sdb);
-  wcroot->sdb = NULL;
-  if (err)
-    {
-      apr_status_t result = err->apr_err;
-      svn_error_clear(err);
-      return result;
-    }
-
-  return APR_SUCCESS;
-}
-
-
-/* */
-static svn_error_t *
-close_many_wcroots(apr_hash_t *roots,
-                   apr_pool_t *state_pool,
-                   apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(scratch_pool, roots); hi; hi = apr_hash_next(hi))
-    {
-      wcroot_t *wcroot = svn__apr_hash_index_val(hi);
-      apr_status_t result;
-
-      result = apr_pool_cleanup_run(state_pool, wcroot, close_wcroot);
-      if (result != APR_SUCCESS)
-        return svn_error_wrap_apr(result, NULL);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Construct a new wcroot_t. The WCROOT_ABSPATH and SDB parameters must
-   have lifetime of at least RESULT_POOL.  */
-static svn_error_t *
-create_wcroot(wcroot_t **wcroot,
-              const char *wcroot_abspath,
-              svn_sqlite__db_t *sdb,
-              apr_int64_t wc_id,
-              int format,
-              svn_boolean_t auto_upgrade,
-              svn_boolean_t enforce_empty_wq,
-              apr_pool_t *result_pool,
-              apr_pool_t *scratch_pool)
-{
-  if (sdb != NULL)
-    SVN_ERR(svn_sqlite__read_schema_version(&format, sdb, scratch_pool));
-
-  /* If we construct a wcroot, then we better have a format.  */
-  SVN_ERR_ASSERT(format >= 1);
-
-  /* If this working copy is PRE-1.0, then simply bail out.  */
-  if (format < 4)
-    {
-      return svn_error_createf(
-        SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
-        _("Working copy format of '%s' is too old (%d); "
-          "please check out your working copy again"),
-        svn_dirent_local_style(wcroot_abspath, scratch_pool), format);
-    }
-
-  /* If this working copy is from a future version, then bail out.  */
-  if (format > SVN_WC__VERSION)
-    {
-      return svn_error_createf(
-        SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
-        _("This client is too old to work with the working copy at\n"
-          "'%s' (format %d).\n"
-          "You need to get a newer Subversion client. For more details, see\n"
-          "  http://subversion.apache.org/faq.html#working-copy-format-change\n"
-          ),
-        svn_dirent_local_style(wcroot_abspath, scratch_pool),
-        format);
-    }
-
-  /* Auto-upgrade the SDB if possible.  */
-  if (format < SVN_WC__VERSION && auto_upgrade)
-    SVN_ERR(svn_wc__upgrade_sdb(&format, wcroot_abspath, sdb, format,
-                                scratch_pool));
-
-  /* Verify that no work items exists. If they do, then our integrity is
-     suspect and, thus, we cannot use this database.  */
-  if (format >= SVN_WC__HAS_WORK_QUEUE && enforce_empty_wq)
-    SVN_ERR(verify_no_work(sdb));
-
-  *wcroot = apr_palloc(result_pool, sizeof(**wcroot));
-
-  (*wcroot)->abspath = wcroot_abspath;
-  (*wcroot)->sdb = sdb;
-  (*wcroot)->wc_id = wc_id;
-  (*wcroot)->format = format;
-
-  /* SDB will be NULL for pre-NG working copies. We only need to run a
-     cleanup when the SDB is present.  */
-  if (sdb != NULL)
-    apr_pool_cleanup_register(result_pool, *wcroot, close_wcroot,
-                              apr_pool_cleanup_null);
-  return SVN_NO_ERROR;
-}
-
-
 /* Returns in PRISTINE_ABSPATH a new string allocated from RESULT_POOL,
    holding the local absolute path to the file location that is dedicated
    to hold CHECKSUM's pristine file, relating to the pristine store
@@ -459,22 +290,22 @@ create_wcroot(wcroot_t **wcroot,
 static svn_error_t *
 get_pristine_fname(const char **pristine_abspath,
                    svn_wc__db_pdh_t *pdh,
-                   const svn_checksum_t *checksum,
-#ifndef SVN__SKIP_SUBDIR
+                   const svn_checksum_t *sha1_checksum,
                    svn_boolean_t create_subdir,
-#endif
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
 {
   const char *base_dir_abspath;
-  const char *hexdigest = svn_checksum_to_cstring(checksum, scratch_pool);
+  const char *hexdigest = svn_checksum_to_cstring(sha1_checksum, scratch_pool);
 #ifndef SVN__SKIP_SUBDIR
   char subdir[3];
 #endif
 
   /* ### code is in transition. make sure we have the proper data.  */
+  SVN_ERR_ASSERT(pristine_abspath != NULL);
   SVN_ERR_ASSERT(pdh->wcroot != NULL);
-  SVN_ERR_ASSERT(checksum->kind == svn_checksum_sha1);
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
 
   /* ### need to fix this to use a symbol for ".svn". we don't need
      ### to use join_many since we know "/" is the separator for
@@ -538,7 +369,7 @@ fetch_repos_info(const char **repos_root
   SVN_ERR(svn_sqlite__bindf(stmt, "i", repos_id));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (!have_row)
-    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+    return svn_error_createf(SVN_ERR_WC_CORRUPT, svn_sqlite__reset(stmt),
                              _("No REPOSITORY table entry for id '%ld'"),
                              (long int)repos_id);
 
@@ -558,7 +389,7 @@ fetch_repos_info(const char **repos_root
 static svn_error_t *
 scan_upwards_for_repos(apr_int64_t *repos_id,
                        const char **repos_relpath,
-                       const wcroot_t *wcroot,
+                       const svn_wc__db_wcroot_t *wcroot,
                        const char *local_abspath,
                        const char *local_relpath,
                        apr_pool_t *result_pool,
@@ -656,759 +487,312 @@ scan_upwards_for_repos(apr_int64_t *repo
 }
 
 
-/* Get the format version from a wc-1 directory. If it is not a working copy
-   directory, then it sets VERSION to zero and returns no error.  */
+/* Get the statement given by STMT_IDX, and bind the appropriate wc_id and
+   local_relpath based upon LOCAL_ABSPATH.  Store it in *STMT, and use
+   SCRATCH_POOL for temporary allocations.
+
+   Note: WC_ID and LOCAL_RELPATH must be arguments 1 and 2 in the statement. */
 static svn_error_t *
-get_old_version(int *version,
-                const char *abspath,
-                apr_pool_t *scratch_pool)
+get_statement_for_path(svn_sqlite__stmt_t **stmt,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       int stmt_idx,
+                       apr_pool_t *scratch_pool)
 {
-  svn_error_t *err;
-  const char *format_file_path;
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
 
-  /* Try reading the format number from the entries file.  */
-  format_file_path = svn_wc__adm_child(abspath, SVN_WC__ADM_ENTRIES,
-                                       scratch_pool);
-  err = svn_io_read_version_file(version, format_file_path, scratch_pool);
-  if (err == NULL)
-    return SVN_NO_ERROR;
-  if (err->apr_err != SVN_ERR_BAD_VERSION_FILE_FORMAT
-      && !APR_STATUS_IS_ENOENT(err->apr_err)
-      && !APR_STATUS_IS_ENOTDIR(err->apr_err))
-    return svn_error_createf(SVN_ERR_WC_MISSING, err, _("'%s' does not exist"),
-                             svn_dirent_local_style(abspath, scratch_pool));
-  svn_error_clear(err);
-
-  /* This must be a really old working copy!  Fall back to reading the
-     format file.
-
-     Note that the format file might not exist in newer working copies
-     (format 7 and higher), but in that case, the entries file should
-     have contained the format number. */
-  format_file_path = svn_wc__adm_child(abspath, SVN_WC__ADM_FORMAT,
-                                       scratch_pool);
-  err = svn_io_read_version_file(version, format_file_path, scratch_pool);
-  if (err == NULL)
-    return SVN_NO_ERROR;
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  /* Whatever error may have occurred... we can just ignore. This is not
-     a working copy directory. Signal the caller.  */
-  svn_error_clear(err);
+  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(svn_sqlite__get_statement(stmt, pdh->wcroot->sdb, stmt_idx));
+  SVN_ERR(svn_sqlite__bindf(*stmt, "is", pdh->wcroot->wc_id, local_relpath));
 
-  *version = 0;
   return SVN_NO_ERROR;
 }
 
 
 /* */
-static svn_wc__db_pdh_t *
-get_or_create_pdh(svn_wc__db_t *db,
-                  const char *local_dir_abspath,
-                  svn_boolean_t create_allowed,
-                  apr_pool_t *scratch_pool)
+static svn_error_t *
+navigate_to_parent(svn_wc__db_pdh_t **parent_pdh,
+                   svn_wc__db_t *db,
+                   svn_wc__db_pdh_t *child_pdh,
+                   svn_sqlite__mode_t smode,
+                   apr_pool_t *scratch_pool)
 {
-  svn_wc__db_pdh_t *pdh = apr_hash_get(db->dir_data,
-                                       local_dir_abspath, APR_HASH_KEY_STRING);
-
-  if (pdh == NULL && create_allowed)
-    {
-      pdh = apr_pcalloc(db->state_pool, sizeof(*pdh));
-
-      /* Copy the path for the proper lifetime.  */
-      pdh->local_abspath = apr_pstrdup(db->state_pool, local_dir_abspath);
-
-      /* We don't know anything about this directory, so we cannot construct
-         a wcroot_t for it (yet).  */
-
-      /* ### parent */
+  const char *parent_abspath;
+  const char *local_relpath;
 
-      apr_hash_set(db->dir_data, pdh->local_abspath, APR_HASH_KEY_STRING, pdh);
-    }
+  if ((*parent_pdh = child_pdh->parent) != NULL
+      && (*parent_pdh)->wcroot != NULL)
+    return SVN_NO_ERROR;
 
-  return pdh;
-}
+  parent_abspath = svn_dirent_dirname(child_pdh->local_abspath, scratch_pool);
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(parent_pdh, &local_relpath, db,
+                              parent_abspath, smode,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(*parent_pdh);
 
+  child_pdh->parent = *parent_pdh;
 
-/* POOL may be NULL if the lifetime of LOCAL_ABSPATH is sufficient.  */
-static const char *
-compute_pdh_relpath(const svn_wc__db_pdh_t *pdh,
-                    apr_pool_t *result_pool)
-{
-  const char *relpath = svn_dirent_is_child(pdh->wcroot->abspath,
-                                            pdh->local_abspath,
-                                            result_pool);
-  if (relpath == NULL)
-    return "";
-  return relpath;
+  return SVN_NO_ERROR;
 }
 
 
-/* The filesystem has a directory at LOCAL_RELPATH. Examine the metadata
-   to determine if a *file* was supposed to be there.
-
-   ### this function is only required for per-dir .svn support. once all
-   ### metadata is collected in a single wcroot, then we won't need to
-   ### look in subdirs for other metadata.  */
+/* For a given REPOS_ROOT_URL/REPOS_UUID pair, return the existing REPOS_ID
+   value. If one does not exist, then create a new one. */
 static svn_error_t *
-determine_obstructed_file(svn_boolean_t *obstructed_file,
-                          const wcroot_t *wcroot,
-                          const char *local_relpath,
-                          apr_pool_t *scratch_pool)
+create_repos_id(apr_int64_t *repos_id,
+                const char *repos_root_url,
+                const char *repos_uuid,
+                svn_sqlite__db_t *sdb,
+                apr_pool_t *scratch_pool)
 {
-  svn_sqlite__stmt_t *stmt;
+  svn_sqlite__stmt_t *get_stmt;
+  svn_sqlite__stmt_t *insert_stmt;
   svn_boolean_t have_row;
 
-  SVN_ERR_ASSERT(wcroot->sdb != NULL && wcroot->wc_id != UNKNOWN_WC_ID);
+  SVN_ERR(svn_sqlite__get_statement(&get_stmt, sdb, STMT_SELECT_REPOSITORY));
+  SVN_ERR(svn_sqlite__bindf(get_stmt, "s", repos_root_url));
+  SVN_ERR(svn_sqlite__step(&have_row, get_stmt));
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_WORKING_IS_FILE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is",
-                            wcroot->wc_id,
-                            local_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (have_row)
     {
-      *obstructed_file = svn_sqlite__column_boolean(stmt, 0);
+      *repos_id = svn_sqlite__column_int64(get_stmt, 0);
+      return svn_error_return(svn_sqlite__reset(get_stmt));
     }
-  else
-    {
-      SVN_ERR(svn_sqlite__reset(stmt));
+  SVN_ERR(svn_sqlite__reset(get_stmt));
 
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_BASE_IS_FILE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "is",
-                                wcroot->wc_id,
-                                local_relpath));
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-      if (have_row)
-        *obstructed_file = svn_sqlite__column_boolean(stmt, 0);
-    }
+  /* NOTE: strictly speaking, there is a race condition between the
+     above query and the insertion below. We're simply going to ignore
+     that, as it means two processes are *modifying* the working copy
+     at the same time, *and* new repositores are becoming visible.
+     This is rare enough, let alone the miniscule chance of hitting
+     this race condition. Further, simply failing out will leave the
+     database in a consistent state, and the user can just re-run the
+     failed operation. */
 
-  return svn_sqlite__reset(stmt);
+  SVN_ERR(svn_sqlite__get_statement(&insert_stmt, sdb,
+                                    STMT_INSERT_REPOSITORY));
+  SVN_ERR(svn_sqlite__bindf(insert_stmt, "ss", repos_root_url, repos_uuid));
+  return svn_error_return(svn_sqlite__insert(repos_id, insert_stmt));
 }
 
 
-/* */
-static svn_error_t *
-fetch_wc_id(apr_int64_t *wc_id,
-            svn_sqlite__db_t *sdb,
-            apr_pool_t *scratch_pool)
+/* Initialize the baton with appropriate "blank" values. This allows the
+   insertion function to leave certain columns null.  */
+static void
+blank_ibb(insert_base_baton_t *pibb)
 {
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  /* ### cheat. we know there is just one WORKING_COPY row, and it has a
-     ### NULL value for local_abspath. */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WCROOT_NULL));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  if (!have_row)
-    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
-                             _("Missing a row in WCROOT."));
-
-  SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
-  *wc_id = svn_sqlite__column_int64(stmt, 0);
-
-  return svn_error_return(svn_sqlite__reset(stmt));
+  memset(pibb, 0, sizeof(*pibb));
+  pibb->revision = SVN_INVALID_REVNUM;
+  pibb->changed_rev = SVN_INVALID_REVNUM;
+  pibb->depth = svn_depth_infinity;
+  pibb->translated_size = SVN_INVALID_FILESIZE;
 }
 
 
 /* */
 static svn_error_t *
-open_db(svn_sqlite__db_t **sdb,
-        const char *dir_abspath,
-        const char *sdb_fname,
-        svn_sqlite__mode_t smode,
-        apr_pool_t *result_pool,
-        apr_pool_t *scratch_pool)
-{
-  const char *sdb_abspath = svn_wc__adm_child(dir_abspath, sdb_fname,
-                                              scratch_pool);
-
-  return svn_error_return(svn_sqlite__open(sdb, sdb_abspath,
-                                           smode, statements,
-                                           0, NULL,
-                                           result_pool, scratch_pool));
-}
-
-
-/* For a given LOCAL_ABSPATH, figure out what sqlite database (PDH) to
-   use and the RELPATH within that wcroot.  If a sqlite database needs
-   to be opened, then use SMODE for it. */
-static svn_error_t *
-parse_local_abspath(svn_wc__db_pdh_t **pdh,
-                    const char **local_relpath,
-                    svn_wc__db_t *db,
-                    const char *local_abspath,
-                    svn_sqlite__mode_t smode,
-                    apr_pool_t *result_pool,
-                    apr_pool_t *scratch_pool)
+insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
 {
-  const char *original_abspath = local_abspath;
-  svn_node_kind_t kind;
-  svn_boolean_t special;
-  const char *build_relpath;
-  svn_wc__db_pdh_t *found_pdh = NULL;
-  svn_wc__db_pdh_t *child_pdh;
-  svn_boolean_t obstruction_possible = FALSE;
-  svn_sqlite__db_t *sdb;
-  svn_boolean_t moved_upwards = FALSE;
-  svn_boolean_t always_check = FALSE;
-  int wc_format = 0;
-
-  /* ### we need more logic for finding the database (if it is located
-     ### outside of the wcroot) and then managing all of that within DB.
-     ### for now: play quick & dirty. */
-
-  /* ### for now, overwrite the provided mode.  We currently cache the
-     ### sdb handles, which is great but for the occasion where we
-     ### initially open the sdb in readonly mode and then later want
-     ### to write to it.  The solution is to reopen the db in readwrite
-     ### mode, but that assumes we can track the fact that it was
-     ### originally opened readonly.  So for now, just punt and open
-     ### everything in readwrite mode.  */
-  smode = svn_sqlite__mode_readwrite;
-
-  *pdh = apr_hash_get(db->dir_data, local_abspath, APR_HASH_KEY_STRING);
-  if (*pdh != NULL && (*pdh)->wcroot != NULL)
-    {
-      /* We got lucky. Just return the thing BEFORE performing any I/O.  */
-      /* ### validate SMODE against how we opened wcroot->sdb? and against
-         ### DB->mode? (will we record per-dir mode?)  */
-
-      /* ### for most callers, we could pass NULL for result_pool.  */
-      *local_relpath = compute_pdh_relpath(*pdh, result_pool);
+  const insert_base_baton_t *pibb = baton;
+  svn_sqlite__stmt_t *stmt;
 
-      return SVN_NO_ERROR;
-    }
+  /* ### we can't handle this right now  */
+  SVN_ERR_ASSERT(pibb->conflict == NULL);
 
-  /* ### at some point in the future, we may need to find a way to get
-     ### rid of this stat() call. it is going to happen for EVERY call
-     ### into wc_db which references a file. calls for directories could
-     ### get an early-exit in the hash lookup just above.  */
-  SVN_ERR(svn_io_check_special_path(local_abspath, &kind,
-                                    &special /* unused */, scratch_pool));
-  if (kind != svn_node_dir)
-    {
-      /* If the node specified by the path is NOT present, then it cannot
-         possibly be a directory containing ".svn/wc.db".
-
-         If it is a file, then it cannot contain ".svn/wc.db".
-
-         For both of these cases, strip the basename off of the path and
-         move up one level. Keep record of what we strip, though, since
-         we'll need it later to construct local_relpath.  */
-      svn_dirent_split(local_abspath, &local_abspath, &build_relpath,
-                       scratch_pool);
-
-      /* ### if *pdh != NULL (from further above), then there is (quite
-         ### probably) a bogus value in the DIR_DATA hash table. maybe
-         ### clear it out? but what if there is an access baton?  */
-
-      /* Is this directory in our hash?  */
-      *pdh = apr_hash_get(db->dir_data, local_abspath, APR_HASH_KEY_STRING);
-      if (*pdh != NULL && (*pdh)->wcroot != NULL)
-        {
-          const char *dir_relpath;
-
-          /* Stashed directory's local_relpath + basename. */
-          dir_relpath = compute_pdh_relpath(*pdh, NULL);
-          *local_relpath = svn_relpath_join(dir_relpath,
-                                            build_relpath,
-                                            result_pool);
-          return SVN_NO_ERROR;
-        }
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_BASE_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", pibb->wc_id, pibb->local_relpath));
 
-      /* If the requested path is not on the disk, then we don't know how
-         many ancestors need to be scanned until we start hitting content
-         on the disk. Set ALWAYS_CHECK to keep looking for .svn/entries
-         rather than bailing out after the first check.  */
-      if (kind == svn_node_none)
-        always_check = TRUE;
-    }
-  else
+  if (TRUE /* maybe_bind_repos() */)
     {
-      /* Start the local_relpath empty. If *this* directory contains the
-         wc.db, then relpath will be the empty string.  */
-      build_relpath = "";
-
-      /* It is possible that LOCAL_ABSPATH was *intended* to be a file,
-         but we just found a directory in its place. After we build
-         the PDH, then we'll examine the parent to see how it describes
-         this particular path.
-
-         ### this is only possible with per-dir wc.db databases.  */
-      obstruction_possible = TRUE;
+      SVN_ERR(svn_sqlite__bind_int64(stmt, 3, pibb->repos_id));
+      SVN_ERR(svn_sqlite__bind_text(stmt, 4, pibb->repos_relpath));
     }
 
-  /* LOCAL_ABSPATH refers to a directory at this point. The PDH corresponding
-     to that directory is what we need to return. At this point, we've
-     determined that a PDH with a discovered WCROOT is NOT in the DB's hash
-     table of wcdirs. Let's fill in an existing one, or create one. Then
-     go figure out where the WCROOT is.  */
+  /* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
+     bind the appropriate parent_relpath. */
+  if (*pibb->local_relpath != '\0')
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5,
+                                  svn_relpath_dirname(pibb->local_relpath,
+                                                      scratch_pool)));
 
-  if (*pdh == NULL)
-    {
-      *pdh = apr_pcalloc(db->state_pool, sizeof(**pdh));
-      (*pdh)->local_abspath = apr_pstrdup(db->state_pool, local_abspath);
-    }
-  else
-    {
-      /* The PDH should have been built correctly (so far).  */
-      SVN_ERR_ASSERT(strcmp((*pdh)->local_abspath, local_abspath) == 0);
-    }
-
-  /* Assume that LOCAL_ABSPATH is a directory, and look for the SQLite
-     database in the right place. If we find it... great! If not, then
-     peel off some components, and try again. */
-
-  while (TRUE)
-    {
-      svn_error_t *err;
-
-      err = open_db(&sdb, local_abspath, SDB_FILE, smode,
-                    db->state_pool, scratch_pool);
-      if (err == NULL)
-        break;
-      if (err->apr_err != SVN_ERR_SQLITE_ERROR
-          && !APR_STATUS_IS_ENOENT(err->apr_err))
-        return svn_error_return(err);
-      svn_error_clear(err);
-
-      /* If we have not moved upwards, then check for a wc-1 working copy.
-         Since wc-1 has a .svn in every directory, and we didn't find one
-         in the original directory, then we aren't looking at a wc-1.
-
-         If the original path is not present, then we have to check on every
-         iteration. The content may be the immediate parent, or possibly
-         five ancetors higher. We don't test for directory presence (just
-         for the presence of subdirs/files), so we don't know when we can
-         stop checking ... so just check always.  */
-      if (!moved_upwards || always_check)
-        {
-          SVN_ERR(get_old_version(&wc_format, local_abspath, scratch_pool));
-          if (wc_format != 0)
-            break;
-        }
-
-      /* We couldn't open the SDB within the specified directory, so
-         move up one more directory. */
-      if (svn_dirent_is_root(local_abspath, strlen(local_abspath)))
-        {
-          /* Hit the root without finding a wcroot. */
-          return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
-                                   _("'%s' is not a working copy"),
-                                   svn_dirent_local_style(original_abspath,
-                                                          scratch_pool));
-        }
-
-      local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
-      moved_upwards = TRUE;
-
-      /* An obstruction is no longer possible.
-
-         Example: we were given "/some/file" and "file" turned out to be
-         a directory. We did not find an SDB at "/some/file/.svn/wc.db",
-         so we are now going to look at "/some/.svn/wc.db". That SDB will
-         contain the correct information for "file".
+  SVN_ERR(svn_sqlite__bind_token(stmt, 6, presence_map, pibb->status));
+  SVN_ERR(svn_sqlite__bind_token(stmt, 7, kind_map, pibb->kind));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 8, pibb->revision));
 
-         ### obstruction is only possible with per-dir wc.db databases.  */
-      obstruction_possible = FALSE;
+  SVN_ERR(svn_sqlite__bind_properties(stmt, 9, pibb->props, scratch_pool));
 
-      /* Is the parent directory recorded in our hash?  */
-      found_pdh = apr_hash_get(db->dir_data,
-                               local_abspath, APR_HASH_KEY_STRING);
-      if (found_pdh != NULL)
-        {
-          if (found_pdh->wcroot != NULL)
-            break;
-          found_pdh = NULL;
-        }
-    }
+  if (SVN_IS_VALID_REVNUM(pibb->changed_rev))
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 10, pibb->changed_rev));
+  if (pibb->changed_date)
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 11, pibb->changed_date));
+  if (pibb->changed_author)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 12, pibb->changed_author));
 
-  if (found_pdh != NULL)
+  if (pibb->kind == svn_wc__db_kind_dir)
     {
-      /* We found a PDH with data in it. We can now construct the child
-         from this, rather than continuing to scan upwards.  */
-
-      /* The subdirectory uses the same WCROOT as the parent dir.  */
-      (*pdh)->wcroot = found_pdh->wcroot;
+      SVN_ERR(svn_sqlite__bind_text(stmt, 13, svn_depth_to_word(pibb->depth)));
     }
-  else if (wc_format == 0)
+  else if (pibb->kind == svn_wc__db_kind_file)
     {
-      /* We finally found the database. Construct the PDH record.  */
-
-      apr_int64_t wc_id;
-      svn_error_t *err;
-
-      err = fetch_wc_id(&wc_id, sdb, scratch_pool);
-      if (err)
-        {
-          if (err->apr_err == SVN_ERR_WC_CORRUPT)
-            return svn_error_quick_wrap(
-              err, apr_psprintf(scratch_pool,
-                                _("Missing a row in WCROOT for '%s'."),
-                                svn_dirent_local_style(original_abspath,
-                                                       scratch_pool)));
-          return svn_error_return(err);
-        }
-
-      /* WCROOT.local_abspath may be NULL when the database is stored
-         inside the wcroot, but we know the abspath is this directory
-         (ie. where we found it).  */
-
-      SVN_ERR(create_wcroot(&(*pdh)->wcroot,
-                            apr_pstrdup(db->state_pool, local_abspath),
-                            sdb, wc_id, FORMAT_FROM_SDB,
-                            db->auto_upgrade, db->enforce_empty_wq,
-                            db->state_pool, scratch_pool));
+      SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, pibb->checksum,
+                                        scratch_pool));
+      if (pibb->translated_size != SVN_INVALID_FILESIZE)
+        SVN_ERR(svn_sqlite__bind_int64(stmt, 15, pibb->translated_size));
     }
-  else
+  else if (pibb->kind == svn_wc__db_kind_symlink)
     {
-      /* We found a wc-1 working copy directory.  */
-      SVN_ERR(create_wcroot(&(*pdh)->wcroot,
-                            apr_pstrdup(db->state_pool, local_abspath),
-                            NULL, UNKNOWN_WC_ID, wc_format,
-                            db->auto_upgrade, db->enforce_empty_wq,
-                            db->state_pool, scratch_pool));
-
-      /* Don't test for a directory obstructing a versioned file. The wc-1
-         code can manage that itself.  */
-      obstruction_possible = FALSE;
+      /* Note: incomplete nodes may have a NULL target.  */
+      if (pibb->target)
+        SVN_ERR(svn_sqlite__bind_text(stmt, 16, pibb->target));
     }
 
-  {
-    const char *dir_relpath;
-
-    /* The subdirectory's relpath is easily computed relative to the
-       wcroot that we just found.  */
-    dir_relpath = compute_pdh_relpath(*pdh, NULL);
-
-    /* And the result local_relpath may include a filename.  */
-    *local_relpath = svn_relpath_join(dir_relpath, build_relpath, result_pool);
-  }
-
-  /* Check to see if this (versioned) directory is obstructing what should
-     be a file in the parent directory.
+  SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
-     ### obstruction is only possible with per-dir wc.db databases.  */
-  if (obstruction_possible)
+  if (pibb->kind == svn_wc__db_kind_dir && pibb->children)
     {
-      const char *parent_dir;
-      svn_wc__db_pdh_t *parent_pdh;
-
-      /* We should NOT have moved up a directory.  */
-      assert(!moved_upwards);
-
-      /* Get/make a PDH for the parent.  */
-      parent_dir = svn_dirent_dirname(local_abspath, scratch_pool);
-      parent_pdh = apr_hash_get(db->dir_data, parent_dir, APR_HASH_KEY_STRING);
-      if (parent_pdh == NULL || parent_pdh->wcroot == NULL)
-        {
-          svn_error_t *err = open_db(&sdb, parent_dir, SDB_FILE, smode,
-                                     db->state_pool, scratch_pool);
-          if (err)
-            {
-              if (err->apr_err != SVN_ERR_SQLITE_ERROR
-                  && !APR_STATUS_IS_ENOENT(err->apr_err))
-                return svn_error_return(err);
-              svn_error_clear(err);
-
-              /* No parent, so we're at a wcroot apparently. An obstruction
-                 is (therefore) not possible.  */
-              parent_pdh = NULL;
-            }
-          else
-            {
-              /* ### construct this according to per-dir semantics.  */
-              if (parent_pdh == NULL)
-                {
-                  parent_pdh = apr_pcalloc(db->state_pool,
-                                           sizeof(*parent_pdh));
-                  parent_pdh->local_abspath = apr_pstrdup(db->state_pool,
-                                                          parent_dir);
-                }
-              else
-                {
-                  /* The PDH should have been built correctly (so far).  */
-                  SVN_ERR_ASSERT(strcmp(parent_pdh->local_abspath,
-                                        parent_dir) == 0);
-                }
-
-              SVN_ERR(create_wcroot(&parent_pdh->wcroot,
-                                    parent_pdh->local_abspath,
-                                    sdb,
-                                    1 /* ### hack.  */,
-                                    FORMAT_FROM_SDB,
-                                    db->auto_upgrade, db->enforce_empty_wq,
-                                    db->state_pool, scratch_pool));
-
-              apr_hash_set(db->dir_data,
-                           parent_pdh->local_abspath, APR_HASH_KEY_STRING,
-                           parent_pdh);
+      int i;
 
-              (*pdh)->parent = parent_pdh;
-            }
-        }
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                        STMT_INSERT_BASE_NODE_INCOMPLETE));
 
-      if (parent_pdh)
+      for (i = pibb->children->nelts; i--; )
         {
-          const char *lookfor_relpath = svn_dirent_basename(local_abspath,
-                                                            scratch_pool);
+          const char *name = APR_ARRAY_IDX(pibb->children, i, const char *);
 
-          /* Was there supposed to be a file sitting here?  */
-          SVN_ERR(determine_obstructed_file(&(*pdh)->obstructed_file,
-                                            parent_pdh->wcroot,
-                                            lookfor_relpath,
-                                            scratch_pool));
-
-          /* If we determined that a file was supposed to be at the
-             LOCAL_ABSPATH requested, then return the PDH and LOCAL_RELPATH
-             which describes that file.  */
-          if ((*pdh)->obstructed_file)
-            {
-              *pdh = parent_pdh;
-              *local_relpath = apr_pstrdup(result_pool, lookfor_relpath);
-              return SVN_NO_ERROR;
-            }
+          SVN_ERR(svn_sqlite__bindf(stmt, "issi",
+                                    pibb->wc_id,
+                                    svn_dirent_join(pibb->local_relpath,
+                                                    name,
+                                                    scratch_pool),
+                                    pibb->local_relpath,
+                                    (apr_int64_t)pibb->revision));
+          SVN_ERR(svn_sqlite__insert(NULL, stmt));
         }
     }
 
-  /* The PDH is complete. Stash it into DB.  */
-  apr_hash_set(db->dir_data,
-               (*pdh)->local_abspath, APR_HASH_KEY_STRING,
-               *pdh);
-
-  /* Did we traverse up to parent directories?  */
-  if (!moved_upwards)
-    {
-      /* We did NOT move to a parent of the original requested directory.
-         We've constructed and filled in a PDH for the request, so we
-         are done.  */
-      return SVN_NO_ERROR;
-    }
-
-  /* The PDH that we just built was for the LOCAL_ABSPATH originally passed
-     into this function. We stepped *at least* one directory above that.
-     We should now create PDH records for each parent directory that does
-     not (yet) have one.  */
-
-  child_pdh = *pdh;
-
-  do
-    {
-      const char *parent_dir = svn_dirent_dirname(child_pdh->local_abspath,
-                                                  scratch_pool);
-      svn_wc__db_pdh_t *parent_pdh;
-
-      parent_pdh = apr_hash_get(db->dir_data, parent_dir, APR_HASH_KEY_STRING);
-      if (parent_pdh == NULL)
-        {
-          parent_pdh = apr_pcalloc(db->state_pool, sizeof(*parent_pdh));
-          parent_pdh->local_abspath = apr_pstrdup(db->state_pool, parent_dir);
-
-          /* All the PDHs have the same wcroot.  */
-          parent_pdh->wcroot = (*pdh)->wcroot;
-
-          apr_hash_set(db->dir_data,
-                       parent_pdh->local_abspath, APR_HASH_KEY_STRING,
-                       parent_pdh);
-        }
-      else if (parent_pdh->wcroot == NULL)
-        {
-          parent_pdh->wcroot = (*pdh)->wcroot;
-        }
-
-      /* Point the child PDH at this (new) parent PDH. This will allow for
-         easy traversals without path munging.  */
-      child_pdh->parent = parent_pdh;
-      child_pdh = parent_pdh;
-
-      /* Loop if we haven't reached the PDH we found, or the abspath
-         where we terminated the search (when we found wc.db). Note that
-         if we never located a PDH in our ancestry, then FOUND_PDH will
-         be NULL and that portion of the test will always be TRUE.  */
-    }
-  while (child_pdh != found_pdh
-         && strcmp(child_pdh->local_abspath, local_abspath) != 0);
+  SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 
-/* Get the statement given by STMT_IDX, and bind the appropriate wc_id and
-   local_relpath based upon LOCAL_ABSPATH.  Store it in *STMT, and use
-   SCRATCH_POOL for temporary allocations.
-
-   Note: WC_ID and LOCAL_RELPATH must be arguments 1 and 2 in the statement. */
-static svn_error_t *
-get_statement_for_path(svn_sqlite__stmt_t **stmt,
-                       svn_wc__db_t *db,
-                       const char *local_abspath,
-                       int stmt_idx,
-                       apr_pool_t *scratch_pool)
+static void
+blank_iwb(insert_working_baton_t *piwb)
 {
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+  memset(piwb, 0, sizeof(*piwb));
+  piwb->changed_rev = SVN_INVALID_REVNUM;
+  piwb->depth = svn_depth_infinity;
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(pdh);
-
-  SVN_ERR(svn_sqlite__get_statement(stmt, pdh->wcroot->sdb, stmt_idx));
-  SVN_ERR(svn_sqlite__bindf(*stmt, "is", pdh->wcroot->wc_id, local_relpath));
-
-  return SVN_NO_ERROR;
+  /* ORIGINAL_REPOS_ID and ORIGINAL_REVNUM could use some kind of "nil"
+     value, but... meh. We'll avoid them if ORIGINAL_REPOS_RELPATH==NULL.  */
 }
 
 
 /* */
 static svn_error_t *
-navigate_to_parent(svn_wc__db_pdh_t **parent_pdh,
-                   svn_wc__db_t *db,
-                   svn_wc__db_pdh_t *child_pdh,
-                   svn_sqlite__mode_t smode,
-                   apr_pool_t *scratch_pool)
+insert_working_node(void *baton,
+                    svn_sqlite__db_t *sdb,
+                    apr_pool_t *scratch_pool)
 {
-  const char *parent_abspath;
-  const char *local_relpath;
-
-  if ((*parent_pdh = child_pdh->parent) != NULL
-      && (*parent_pdh)->wcroot != NULL)
-    return SVN_NO_ERROR;
-
-  parent_abspath = svn_dirent_dirname(child_pdh->local_abspath, scratch_pool);
-  SVN_ERR(parse_local_abspath(parent_pdh, &local_relpath, db,
-                              parent_abspath, smode,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(*parent_pdh);
-
-  child_pdh->parent = *parent_pdh;
-
-  return SVN_NO_ERROR;
-}
-
+  const insert_working_baton_t *piwb = baton;
+  const char *parent_relpath;
+  svn_sqlite__stmt_t *stmt;
 
-/* For a given REPOS_ROOT_URL/REPOS_UUID pair, return the existing REPOS_ID
-   value. If one does not exist, then create a new one. */
-static svn_error_t *
-create_repos_id(apr_int64_t *repos_id,
-                const char *repos_root_url,
-                const char *repos_uuid,
-                svn_sqlite__db_t *sdb,
-                apr_pool_t *scratch_pool)
-{
-  svn_sqlite__stmt_t *get_stmt;
-  svn_sqlite__stmt_t *insert_stmt;
-  svn_boolean_t have_row;
+  /* We cannot insert a WORKING_NODE row at the wcroot.  */
+  /* ### actually, with per-dir DB, we can... */
+#if 0
+  SVN_ERR_ASSERT(*piwb->local_relpath != '\0');
+#endif
+  if (*piwb->local_relpath == '\0')
+    parent_relpath = NULL;
+  else
+    parent_relpath = svn_relpath_dirname(piwb->local_relpath, scratch_pool);
 
-  SVN_ERR(svn_sqlite__get_statement(&get_stmt, sdb, STMT_SELECT_REPOSITORY));
-  SVN_ERR(svn_sqlite__bindf(get_stmt, "s", repos_root_url));
-  SVN_ERR(svn_sqlite__step(&have_row, get_stmt));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_WORKING_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isstt",
+                            piwb->wc_id, piwb->local_relpath,
+                            parent_relpath,
+                            presence_map, piwb->presence,
+                            kind_map, piwb->kind));
 
-  if (have_row)
+  if (piwb->original_repos_relpath != NULL)
     {
-      *repos_id = svn_sqlite__column_int64(get_stmt, 0);
-      return svn_error_return(svn_sqlite__reset(get_stmt));
-    }
-  SVN_ERR(svn_sqlite__reset(get_stmt));
-
-  /* NOTE: strictly speaking, there is a race condition between the
-     above query and the insertion below. We're simply going to ignore
-     that, as it means two processes are *modifying* the working copy
-     at the same time, *and* new repositores are becoming visible.
-     This is rare enough, let alone the miniscule chance of hitting
-     this race condition. Further, simply failing out will leave the
-     database in a consistent state, and the user can just re-run the
-     failed operation. */
-
-  SVN_ERR(svn_sqlite__get_statement(&insert_stmt, sdb,
-                                    STMT_INSERT_REPOSITORY));
-  SVN_ERR(svn_sqlite__bindf(insert_stmt, "ss", repos_root_url, repos_uuid));
-  return svn_error_return(svn_sqlite__insert(repos_id, insert_stmt));
-}
-
-
-/* */
-static svn_error_t *
-insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
-  const insert_base_baton_t *pibb = baton;
-  svn_sqlite__stmt_t *stmt;
+      SVN_ERR_ASSERT(piwb->original_repos_id > 0);
+      SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(piwb->original_revnum));
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", pibb->wc_id, pibb->local_relpath));
-
-  if (TRUE /* maybe_bind_repos() */)
-    {
-      SVN_ERR(svn_sqlite__bind_int64(stmt, 3, pibb->repos_id));
-      SVN_ERR(svn_sqlite__bind_text(stmt, 4, pibb->repos_relpath));
+      SVN_ERR(svn_sqlite__bind_int64(stmt, 6, piwb->original_repos_id));
+      SVN_ERR(svn_sqlite__bind_text(stmt, 7, piwb->original_repos_relpath));
+      SVN_ERR(svn_sqlite__bind_int64(stmt, 8, piwb->original_revnum));
     }
 
-  /* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
-     bind the appropriate parent_relpath. */
-  if (*pibb->local_relpath != '\0')
-    SVN_ERR(svn_sqlite__bind_text(stmt, 5,
-                                  svn_dirent_dirname(pibb->local_relpath,
-                                                     scratch_pool)));
+  /* Do not bind 'moved_here' (9), nor 'moved_to' (10).  */
 
-  SVN_ERR(svn_sqlite__bind_token(stmt, 6, presence_map, pibb->status));
-  SVN_ERR(svn_sqlite__bind_token(stmt, 7, kind_map, pibb->kind));
-  SVN_ERR(svn_sqlite__bind_int64(stmt, 8, pibb->revision));
+  /* 'checksum' (11) is bound below.  */
 
-  SVN_ERR(svn_sqlite__bind_properties(stmt, 9, pibb->props, scratch_pool));
+  /* Do not bind 'translated_size' (12).  */
 
-  if (SVN_IS_VALID_REVNUM(pibb->changed_rev))
-    SVN_ERR(svn_sqlite__bind_int64(stmt, 10, pibb->changed_rev));
-  if (pibb->changed_date)
-    SVN_ERR(svn_sqlite__bind_int64(stmt, 11, pibb->changed_date));
-  if (pibb->changed_author)
-    SVN_ERR(svn_sqlite__bind_text(stmt, 12, pibb->changed_author));
+  if (SVN_IS_VALID_REVNUM(piwb->changed_rev))
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 13, piwb->changed_rev));
+  if (piwb->changed_date)
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 14, piwb->changed_date));
+  if (piwb->changed_author)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 15, piwb->changed_author));
 
-  if (pibb->kind == svn_wc__db_kind_dir)
+  if (piwb->kind == svn_wc__db_kind_dir)
     {
-      SVN_ERR(svn_sqlite__bind_text(stmt, 13, svn_depth_to_word(pibb->depth)));
+      SVN_ERR(svn_sqlite__bind_text(stmt, 16, svn_depth_to_word(piwb->depth)));
     }
-  else if (pibb->kind == svn_wc__db_kind_file)
+  else if (piwb->kind == svn_wc__db_kind_file)
     {
-      SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, pibb->checksum,
+      SVN_ERR(svn_sqlite__bind_checksum(stmt, 11, piwb->checksum,
                                         scratch_pool));
-      if (pibb->translated_size != SVN_INVALID_FILESIZE)
-        SVN_ERR(svn_sqlite__bind_int64(stmt, 15, pibb->translated_size));
     }
-  else if (pibb->kind == svn_wc__db_kind_symlink)
+  else if (piwb->kind == svn_wc__db_kind_symlink)
     {
-      if (pibb->target)
-        SVN_ERR(svn_sqlite__bind_text(stmt, 16, pibb->target));
+      SVN_ERR_ASSERT(piwb->target != NULL);
+
+      SVN_ERR(svn_sqlite__bind_text(stmt, 20, piwb->target));
     }
 
+  /* Do not bind 'last_mod_time' (17).  */
+
+  SVN_ERR(svn_sqlite__bind_properties(stmt, 18, piwb->props, scratch_pool));
+
+  /* Do not bind 'keep_local' (19).  */
+  /* 'symlink_target' (20) is bound above.  */
+
   SVN_ERR(svn_sqlite__insert(NULL, stmt));
 
-  if (pibb->kind == svn_wc__db_kind_dir && pibb->children)
+  if (piwb->kind == svn_wc__db_kind_dir && piwb->children)
     {
       int i;
 
       SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                        STMT_INSERT_BASE_NODE_INCOMPLETE));
+                                        STMT_INSERT_WORKING_NODE_INCOMPLETE));
 
-      for (i = pibb->children->nelts; i--; )
+      for (i = piwb->children->nelts; i--; )
         {
-          const char *name = APR_ARRAY_IDX(pibb->children, i, const char *);
+          const char *name = APR_ARRAY_IDX(piwb->children, i, const char *);
 
-          SVN_ERR(svn_sqlite__bindf(stmt, "issi",
-                                    pibb->wc_id,
-                                    svn_dirent_join(pibb->local_relpath,
-                                                    name,
-                                                    scratch_pool),
-                                    pibb->local_relpath,
-                                    (apr_int64_t)pibb->revision));
+          SVN_ERR(svn_sqlite__bindf(stmt, "iss",
+                                    piwb->wc_id,
+                                    svn_relpath_join(piwb->local_relpath,
+                                                     name,
+                                                     scratch_pool),
+                                    piwb->local_relpath));
           SVN_ERR(svn_sqlite__insert(NULL, stmt));
         }
     }
 
+  SVN_ERR(add_work_items(sdb, piwb->work_items, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -1430,8 +814,8 @@ gather_children(const apr_array_header_t
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readonly,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              local_abspath, svn_sqlite__mode_readonly,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
@@ -1510,9 +894,8 @@ add_work_items(svn_sqlite__db_t *sdb,
   /* Should have a list.  */
   SVN_ERR_ASSERT(!skel->is_atom);
 
-  /* If SKEL has an atom as its first child, then this is a work item
-     (and that atom is one of the OP_* values).  */
-  if (skel->children->is_atom)
+  /* Is the list a single work item? Or a list of work items?  */
+  if (SVN_WC__SINGLE_WORK_ITEM(skel))
     return svn_error_return(add_single_work_item(sdb, skel, scratch_pool));
 
   /* SKEL is a list-of-lists, aka list of work items.  */
@@ -1586,9 +969,9 @@ create_db(svn_sqlite__db_t **sdb,
 {
   svn_sqlite__stmt_t *stmt;
 
-  SVN_ERR(open_db(sdb, dir_abspath, sdb_fname,
-                  svn_sqlite__mode_rwcreate,
-                  result_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_util_open_db(sdb, dir_abspath, sdb_fname,
+                                  svn_sqlite__mode_rwcreate, result_pool,
+                                  scratch_pool));
 
   /* Create the database's schema.  */
   SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_CREATE_SCHEMA));
@@ -1607,60 +990,6 @@ create_db(svn_sqlite__db_t **sdb,
 
 
 svn_error_t *
-svn_wc__db_open(svn_wc__db_t **db,
-                svn_wc__db_openmode_t mode,
-                svn_config_t *config,
-                svn_boolean_t auto_upgrade,
-                svn_boolean_t enforce_empty_wq,
-                apr_pool_t *result_pool,
-                apr_pool_t *scratch_pool)
-{
-  *db = apr_pcalloc(result_pool, sizeof(**db));
-  (*db)->mode = mode;
-  (*db)->config = config;
-  (*db)->auto_upgrade = auto_upgrade;
-  (*db)->enforce_empty_wq = enforce_empty_wq;
-  (*db)->dir_data = apr_hash_make(result_pool);
-  (*db)->state_pool = result_pool;
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_close(svn_wc__db_t *db)
-{
-  apr_pool_t *scratch_pool = db->state_pool;
-  apr_hash_t *roots = apr_hash_make(scratch_pool);
-  apr_hash_index_t *hi;
-
-  /* Collect all the unique WCROOT structures, and empty out DIR_DATA.  */
-  for (hi = apr_hash_first(scratch_pool, db->dir_data);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *key;
-      apr_ssize_t klen;
-      void *val;
-      svn_wc__db_pdh_t *pdh;
-
-      apr_hash_this(hi, &key, &klen, &val);
-      pdh = val;
-
-      if (pdh->wcroot && pdh->wcroot->sdb)
-        apr_hash_set(roots, pdh->wcroot->abspath, APR_HASH_KEY_STRING,
-                     pdh->wcroot);
-
-      apr_hash_set(db->dir_data, key, klen, NULL);
-    }
-
-  /* Run the cleanup for each WCROOT.  */
-  return svn_error_return(close_many_wcroots(roots, db->state_pool,
-                                             scratch_pool));
-}
-
-
-svn_error_t *
 svn_wc__db_init(svn_wc__db_t *db,
                 const char *local_abspath,
                 const char *repos_relpath,
@@ -1694,7 +1023,7 @@ svn_wc__db_init(svn_wc__db_t *db,
   pdh->local_abspath = apr_pstrdup(db->state_pool, local_abspath);
 
   /* Create the WCROOT for this directory.  */
-  SVN_ERR(create_wcroot(&pdh->wcroot, pdh->local_abspath,
+  SVN_ERR(svn_wc__db_pdh_create_wcroot(&pdh->wcroot, pdh->local_abspath,
                         sdb, wc_id, FORMAT_FROM_SDB,
                         FALSE /* auto-upgrade */,
                         FALSE /* enforce_empty_wq */,
@@ -1703,6 +1032,8 @@ svn_wc__db_init(svn_wc__db_t *db,
   /* The PDH is complete. Stash it into DB.  */
   apr_hash_set(db->dir_data, pdh->local_abspath, APR_HASH_KEY_STRING, pdh);
 
+  blank_ibb(&ibb);
+
   if (initial_rev > 0)
     ibb.status = svn_wc__db_status_incomplete;
   else
@@ -1714,19 +1045,64 @@ svn_wc__db_init(svn_wc__db_t *db,
   ibb.repos_relpath = repos_relpath;
   ibb.revision = initial_rev;
 
-  ibb.props = NULL;
-  ibb.changed_rev = SVN_INVALID_REVNUM;
-  ibb.changed_date = 0;
-  ibb.changed_author = NULL;
-
+  /* ### what about the children?  */
   ibb.children = NULL;
   ibb.depth = depth;
 
+  /* ### no children, conflicts, or work items to install in a txn... */
+
   return svn_error_return(insert_base_node(&ibb, sdb, scratch_pool));
 }
 
 
 svn_error_t *
+svn_wc__db_to_relpath(const char **local_relpath,
+                      svn_wc__db_t *db,
+                      const char *local_abspath,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+
+  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_readonly,
+                              result_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_from_relpath(const char **local_abspath,
+                        svn_wc__db_t *db,
+                        const char *wri_abspath,
+                        const char *local_relpath,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *unused_relpath;
+
+#if 0
+  SVN_ERR_ASSERT(svn_relpath_is_canonical(local_abspath));
+#endif
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &unused_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readonly,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  *local_abspath = svn_dirent_join(pdh->wcroot->abspath,
+                                   local_relpath,
+                                   result_pool);
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_wc__db_base_add_directory(svn_wc__db_t *db,
                               const char *local_abspath,
                               const char *repos_relpath,
@@ -1739,6 +1115,8 @@ svn_wc__db_base_add_directory(svn_wc__db
                               const char *changed_author,
                               const apr_array_header_t *children,
                               svn_depth_t depth,
+                              const svn_skel_t *conflict,
+                              const svn_skel_t *work_items,
                               apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
@@ -1753,16 +1131,20 @@ svn_wc__db_base_add_directory(svn_wc__db
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
   SVN_ERR_ASSERT(props != NULL);
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
+#if 0
   SVN_ERR_ASSERT(children != NULL);
+#endif
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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(create_repos_id(&repos_id, repos_root_url, repos_uuid,
                           pdh->wcroot->sdb, scratch_pool));
 
+  blank_ibb(&ibb);
+
   ibb.status = svn_wc__db_status_normal;
   ibb.kind = svn_wc__db_kind_dir;
   ibb.wc_id = pdh->wcroot->wc_id;
@@ -1779,13 +1161,20 @@ svn_wc__db_base_add_directory(svn_wc__db
   ibb.children = children;
   ibb.depth = depth;
 
+  ibb.conflict = conflict;
+  ibb.work_items = work_items;
+
   /* Insert the directory and all its children transactionally.
 
      Note: old children can stick around, even if they are no longer present
      in this directory's revision.  */
-  return svn_sqlite__with_transaction(pdh->wcroot->sdb,
-                                      insert_base_node, &ibb,
-                                      scratch_pool);
+  SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+                                       insert_base_node, &ibb,
+                                       scratch_pool));
+
+  /* ### worry about flushing child subdirs?  */
+  flush_entries(pdh);
+  return SVN_NO_ERROR;
 }
 
 
@@ -1802,6 +1191,8 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
                          const char *changed_author,
                          const svn_checksum_t *checksum,
                          svn_filesize_t translated_size,
+                         const svn_skel_t *conflict,
+                         const svn_skel_t *work_items,
                          apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
@@ -1818,14 +1209,16 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
   SVN_ERR_ASSERT(checksum != NULL);
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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(create_repos_id(&repos_id, repos_root_url, repos_uuid,
                           pdh->wcroot->sdb, scratch_pool));
 
+  blank_ibb(&ibb);
+
   ibb.status = svn_wc__db_status_normal;
   ibb.kind = svn_wc__db_kind_file;
   ibb.wc_id = pdh->wcroot->wc_id;
@@ -1842,11 +1235,19 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
   ibb.checksum = checksum;
   ibb.translated_size = translated_size;
 
+  ibb.conflict = conflict;
+  ibb.work_items = work_items;
+
   /* ### hmm. if this used to be a directory, we should remove children.
      ### or maybe let caller deal with that, if there is a possibility
      ### of a node kind change (rather than eat an extra lookup here).  */
 
-  return insert_base_node(&ibb, pdh->wcroot->sdb, scratch_pool);
+  SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+                                       insert_base_node, &ibb,
+                                       scratch_pool));
+
+  flush_entries(pdh);
+  return SVN_NO_ERROR;
 }
 
 
@@ -1862,6 +1263,8 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
                             apr_time_t changed_date,
                             const char *changed_author,
                             const char *target,
+                            const svn_skel_t *conflict,
+                            const svn_skel_t *work_items,
                             apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
@@ -1878,14 +1281,16 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
   SVN_ERR_ASSERT(target != NULL);
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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(create_repos_id(&repos_id, repos_root_url, repos_uuid,
                           pdh->wcroot->sdb, scratch_pool));
 
+  blank_ibb(&ibb);
+
   ibb.status = svn_wc__db_status_normal;
   ibb.kind = svn_wc__db_kind_symlink;
   ibb.wc_id = pdh->wcroot->wc_id;
@@ -1901,11 +1306,19 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
 
   ibb.target = target;
 
+  ibb.conflict = conflict;
+  ibb.work_items = work_items;
+
   /* ### hmm. if this used to be a directory, we should remove children.
      ### or maybe let caller deal with that, if there is a possibility
      ### of a node kind change (rather than eat an extra lookup here).  */
 
-  return insert_base_node(&ibb, pdh->wcroot->sdb, scratch_pool);
+  SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+                                       insert_base_node, &ibb,
+                                       scratch_pool));
+
+  flush_entries(pdh);
+  return SVN_NO_ERROR;
 }
 
 
@@ -1918,6 +1331,8 @@ svn_wc__db_base_add_absent_node(svn_wc__
                                 svn_revnum_t revision,
                                 svn_wc__db_kind_t kind,
                                 svn_wc__db_status_t status,
+                                const svn_skel_t *conflict,
+                                const svn_skel_t *work_items,
                                 apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
@@ -1934,14 +1349,16 @@ svn_wc__db_base_add_absent_node(svn_wc__
                  || status == svn_wc__db_status_excluded
                  || status == svn_wc__db_status_not_present);
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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(create_repos_id(&repos_id, repos_root_url, repos_uuid,
                           pdh->wcroot->sdb, scratch_pool));
 
+  blank_ibb(&ibb);
+
   ibb.status = status;
   ibb.kind = kind;
   ibb.wc_id = pdh->wcroot->wc_id;
@@ -1950,11 +1367,6 @@ svn_wc__db_base_add_absent_node(svn_wc__
   ibb.repos_relpath = repos_relpath;
   ibb.revision = revision;
 
-  ibb.props = NULL;
-  ibb.changed_rev = SVN_INVALID_REVNUM;
-  ibb.changed_date = 0;
-  ibb.changed_author = NULL;
-
   /* Depending upon KIND, any of these might get used. */
   ibb.children = NULL;
   ibb.depth = svn_depth_unknown;
@@ -1962,13 +1374,18 @@ svn_wc__db_base_add_absent_node(svn_wc__
   ibb.translated_size = SVN_INVALID_FILESIZE;
   ibb.target = NULL;
 
+  ibb.conflict = conflict;
+  ibb.work_items = work_items;
+
   /* ### hmm. if this used to be a directory, we should remove children.
      ### or maybe let caller deal with that, if there is a possibility
      ### of a node kind change (rather than eat an extra lookup here).  */
 
-  SVN_ERR(insert_base_node(&ibb, pdh->wcroot->sdb, scratch_pool));
-  flush_entries(pdh);
+  SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+                                       insert_base_node, &ibb,
+                                       scratch_pool));
 
+  flush_entries(pdh);
   return SVN_NO_ERROR;
 }
 
@@ -2001,8 +1418,8 @@ svn_wc__db_temp_base_add_subdir(svn_wc__
   SVN_ERR_ASSERT(props != NULL);
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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);
 
@@ -2025,7 +1442,10 @@ svn_wc__db_temp_base_add_subdir(svn_wc__
   ibb.children = NULL;
   ibb.depth = depth;
 
-  return insert_base_node(&ibb, pdh->wcroot->sdb, scratch_pool);
+  /* ### no children, conflicts, or work items to install in a txn... */
+
+  return svn_error_return(insert_base_node(&ibb, pdh->wcroot->sdb,
+                                           scratch_pool));
 }
 
 
@@ -2040,8 +1460,8 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readwrite,
+  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);
 
@@ -2086,8 +1506,8 @@ svn_wc__db_base_get_info(svn_wc__db_stat
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readonly,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              local_abspath, svn_sqlite__mode_readonly,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
@@ -2244,70 +1664,6 @@ svn_wc__db_base_get_info(svn_wc__db_stat
 }
 
 
-/* A WORKING version of svn_wc__db_base_get_info, stripped down to
-   just the status column.
-
-   ### This function should not exist!  What I really want is presence
-   ### not status, and so it's a mistake to return an
-   ### svn_wc__db_status_t here as it doesn't have quite the same
-   ### meaning as status returned by other functions.  I think I need
-   ### to abandon this function and work out how to decode status back
-   ### into presence :(
-*/
-static svn_error_t *
-db_working_get_status(svn_wc__db_status_t *status,
-                      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_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-  svn_error_t *err = SVN_NO_ERROR;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_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_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)
-    {
-      svn_wc__db_kind_t node_kind = svn_sqlite__column_token(stmt, 1,
-                                                             kind_map);
-
-      *status = svn_sqlite__column_token(stmt, 0, presence_map);
-
-      if (node_kind == svn_wc__db_kind_subdir
-          && *status == svn_wc__db_status_normal)
-        {
-          /* We're looking at the subdir record in the *parent* directory,
-             which implies per-dir .svn subdirs. We should be looking
-             at the subdir itself; therefore, it is missing or obstructed
-             in some way. Inform the caller.  */
-          *status = svn_wc__db_status_obstructed;
-        }
-    }
-  else
-    {
-      err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                              _("The node '%s' was not found."),
-                              svn_dirent_local_style(local_abspath,
-                                                     scratch_pool));
-    }
-
-
-  return svn_error_compose_create(err, svn_sqlite__reset(stmt));
-}
-
-
 svn_error_t *
 svn_wc__db_base_get_prop(const svn_string_t **propval,
                          svn_wc__db_t *db,
@@ -2414,13 +1770,11 @@ svn_wc__db_base_get_dav_cache(apr_hash_t
                                  STMT_SELECT_BASE_DAV_CACHE, scratch_pool));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (!have_row)
-    {
-      SVN_ERR(svn_sqlite__reset(stmt));
-      return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                               _("The node '%s' was not found."),
-                               svn_dirent_local_style(local_abspath,
-                                                      scratch_pool));
-    }
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                             svn_sqlite__reset(stmt),
+                             _("The node '%s' was not found."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
 
   SVN_ERR(svn_sqlite__column_properties(props, stmt, 0, result_pool,
                                         scratch_pool));
@@ -2429,38 +1783,76 @@ svn_wc__db_base_get_dav_cache(apr_hash_t
 
 
 svn_error_t *
+svn_wc__db_pristine_get_path(const char **pristine_abspath,
+                             svn_wc__db_t *db,
+                             const char *wri_abspath,
+                             const svn_checksum_t *sha1_checksum,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+
+  SVN_ERR_ASSERT(pristine_abspath != NULL);
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  /* ### Transitional: accept MD-5 and look up the SHA-1.  Return an error
+   * if the pristine text is not in the store. */
+  if (sha1_checksum->kind != svn_checksum_sha1)
+    SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
+                                         sha1_checksum,
+                                         scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath,
+                                             db, wri_abspath,
+                                             svn_sqlite__mode_readonly,
+                                             scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  /* ### should we look in the PRISTINE table for anything?  */
+
+  SVN_ERR(get_pristine_fname(pristine_abspath, pdh, sha1_checksum,
+                             FALSE /* create_subdir */,
+                             scratch_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_wc__db_pristine_read(svn_stream_t **contents,
                          svn_wc__db_t *db,
                          const char *wri_abspath,
-                         const svn_checksum_t *checksum,
+                         const svn_checksum_t *sha1_checksum,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
   svn_wc__db_pdh_t *pdh;
   const char *local_relpath;
   const char *pristine_abspath;
-  svn_error_t *err;
 
   SVN_ERR_ASSERT(contents != NULL);
   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
-  SVN_ERR_ASSERT(checksum != NULL);
-
-  VERIFY_CHECKSUM_KIND(checksum);
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  /* ### Transitional: accept MD-5 and look up the SHA-1.  Return an error
+   * if the pristine text is not in the store. */
+  if (sha1_checksum->kind != svn_checksum_sha1)
+    SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
+                                         sha1_checksum,
+                                         scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, wri_abspath,
-                              svn_sqlite__mode_readonly,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readonly,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
   /* ### should we look in the PRISTINE table for anything?  */
 
-  err = get_pristine_fname(&pristine_abspath, pdh, checksum,
-#ifndef SVN__SKIP_SUBDIR
-                           FALSE /* create_subdir */,
-#endif
-                           scratch_pool, scratch_pool);
-  SVN_ERR(err);
-
+  SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+                             FALSE /* create_subdir */,
+                             scratch_pool, scratch_pool));
   return svn_error_return(svn_stream_open_readonly(
                             contents, pristine_abspath,
                             result_pool, scratch_pool));
@@ -2480,8 +1872,8 @@ svn_wc__db_pristine_get_tempdir(const ch
   SVN_ERR_ASSERT(temp_dir_abspath != NULL);
   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, wri_abspath,
-                              svn_sqlite__mode_readonly,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readonly,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
@@ -2507,13 +1899,12 @@ svn_wc__db_pristine_install(svn_wc__db_t
   const char *pristine_abspath;
   apr_finfo_t finfo;
   svn_sqlite__stmt_t *stmt;
-  svn_error_t *err;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
   SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
   SVN_ERR_ASSERT(md5_checksum != NULL);
-
-  VERIFY_CHECKSUM_KIND(checksum);
+  SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
 
   /* ### this logic assumes that TEMPFILE_ABSPATH follows this pattern:
      ###   WCROOT_ABSPATH/COMPONENT/TEMPFNAME
@@ -2523,17 +1914,14 @@ svn_wc__db_pristine_install(svn_wc__db_t
                                                       scratch_pool),
                                    scratch_pool);
 
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, wri_abspath,
-                              svn_sqlite__mode_readonly,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readonly,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_PDH(pdh);
 
-  err = get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
-#ifndef SVN__SKIP_SUBDIR
-                           TRUE /* create_subdir */,
-#endif
-                           scratch_pool, scratch_pool);
-  SVN_ERR(err);
+  SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+                             TRUE /* create_subdir */,
+                             scratch_pool, scratch_pool));
 
   /* Put the file into its target location.  */
   SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
@@ -2554,111 +1942,834 @@ svn_wc__db_pristine_install(svn_wc__db_t
 
 
 svn_error_t *
+svn_wc__db_pristine_get_md5(const svn_checksum_t **md5_checksum,
+                            svn_wc__db_t *db,
+                            const char *wri_abspath,
+                            const svn_checksum_t *sha1_checksum,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_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_PRISTINE_MD5_CHECKSUM));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
+                             _("The pristine text with checksum '%s' was "
+                               "not found"),
+                             svn_checksum_to_cstring_display(sha1_checksum,
+                                                             scratch_pool));
+
+  SVN_ERR(svn_sqlite__column_checksum(md5_checksum, stmt, 0, result_pool));
+  SVN_ERR_ASSERT((*md5_checksum)->kind == svn_checksum_md5);
+
+  return svn_error_return(svn_sqlite__reset(stmt));
+}
+
+
+svn_error_t *
+svn_wc__db_pristine_get_sha1(const svn_checksum_t **sha1_checksum,
+                             svn_wc__db_t *db,
+                             const char *wri_abspath,
+                             const svn_checksum_t *md5_checksum,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(md5_checksum->kind == svn_checksum_md5);
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_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_PRISTINE_SHA1_CHECKSUM));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, md5_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
+                             _("The pristine text with MD5 checksum '%s' was "
+                               "not found"),
+                             svn_checksum_to_cstring_display(md5_checksum,
+                                                             scratch_pool));
+
+  SVN_ERR(svn_sqlite__column_checksum(sha1_checksum, stmt, 0, result_pool));
+  SVN_ERR_ASSERT((*sha1_checksum)->kind == svn_checksum_sha1);
+
+  return svn_error_return(svn_sqlite__reset(stmt));
+}
+
+
+svn_error_t *
+svn_wc__db_pristine_remove(svn_wc__db_t *db,
+                           const char *wri_abspath,
+                           const svn_checksum_t *sha1_checksum,
+                           apr_pool_t *scratch_pool)
+{
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+  svn_boolean_t is_referenced;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  /* ### Transitional: accept MD-5 and look up the SHA-1.  Return an error
+   * if the pristine text is not in the store. */
+  if (sha1_checksum->kind != svn_checksum_sha1)
+    SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
+                                         sha1_checksum,
+                                         scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
+
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readwrite,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  /* Find whether the SHA-1 (or the MD-5) is referenced; set IS_REFERENCED. */
+  {
+    const svn_checksum_t *md5_checksum;
+    svn_sqlite__stmt_t *stmt;
+
+    /* ### Transitional: look for references to its MD-5 as well. */
+    SVN_ERR(svn_wc__db_pristine_get_md5(&md5_checksum, db, wri_abspath,
+                                        sha1_checksum, scratch_pool,
+                                        scratch_pool));
+
+    SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                      STMT_SELECT_ANY_PRISTINE_REFERENCE));
+    SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+    SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool));
+    SVN_ERR(svn_sqlite__step(&is_referenced, stmt));
+
+    SVN_ERR(svn_sqlite__reset(stmt));
+  }
+
+  /* If not referenced, remove first the PRISTINE table row, then the file. */
+  if (! is_referenced)
+    {
+      svn_sqlite__stmt_t *stmt;
+      const char *pristine_abspath;
+
+      /* Remove the DB row. */
+      SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                        STMT_DELETE_PRISTINE));
+      SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+      SVN_ERR(svn_sqlite__update(NULL, stmt));
+
+      /* Remove the file */
+      SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+                                 TRUE /* create_subdir */,
+                                 scratch_pool, scratch_pool));
+      SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_wc__db_pristine_check(svn_boolean_t *present,
                           svn_wc__db_t *db,
                           const char *wri_abspath,
-                          const svn_checksum_t *checksum,
+                          const svn_checksum_t *sha1_checksum,
                           svn_wc__db_checkmode_t mode,
                           apr_pool_t *scratch_pool)
 {
+  svn_wc__db_pdh_t *pdh;
+  const char *local_relpath;
+  const char *pristine_abspath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  svn_node_kind_t kind_on_disk;
+
   SVN_ERR_ASSERT(present != NULL);
   SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
-  SVN_ERR_ASSERT(checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  /* ### Transitional: accept MD-5 and look up the SHA-1.  Return an error
+   * if the pristine text is not in the store. */
+  if (sha1_checksum->kind != svn_checksum_sha1)
+    SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db, wri_abspath,
+                                         sha1_checksum,
+                                         scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
 
-  VERIFY_CHECKSUM_KIND(checksum);
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+                              wri_abspath, svn_sqlite__mode_readonly,
+                              scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  /* Check that there is an entry in the PRISTINE table. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+                                    STMT_SELECT_PRISTINE_MD5_CHECKSUM));
+  SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* Check that the pristine text file exists. */
+  SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+                             FALSE /* create_subdir */,
+                             scratch_pool, scratch_pool));
+  SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
+
+  if (kind_on_disk != (have_row ? svn_node_file : svn_node_none))
+    return svn_error_createf(SVN_ERR_WC_DB_ERROR, svn_sqlite__reset(stmt),
+                             _("The pristine text with checksum '%s' was "
+                               "found in the DB or on disk but not both"),
+                             svn_checksum_to_cstring_display(sha1_checksum,
+                                                             scratch_pool));
+
+  *present = have_row;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_pristine_repair(svn_wc__db_t *db,
+                           const char *wri_abspath,
+                           const svn_checksum_t *sha1_checksum,
+                           apr_pool_t *scratch_pool)
+{
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+  SVN_ERR_ASSERT(sha1_checksum != NULL);
+  SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
 
   NOT_IMPLEMENTED();
 }
 
 
-svn_error_t *
-svn_wc__db_pristine_repair(svn_wc__db_t *db,
-                           const char *wri_abspath,
-                           const svn_checksum_t *checksum,
-                           apr_pool_t *scratch_pool)
-{
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
-  SVN_ERR_ASSERT(checksum != NULL);
+svn_error_t *
+svn_wc__db_repos_ensure(apr_int64_t *repos_id,
+                        svn_wc__db_t *db,
+                        const char *local_abspath,
+                        const char *repos_root_url,
+                        const char *repos_uuid,
+                        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));
+  VERIFY_USABLE_PDH(pdh);
+
+  return svn_error_return(create_repos_id(repos_id, repos_root_url,
+                                          repos_uuid, pdh->wcroot->sdb,
+                                          scratch_pool));
+}
+
+/* Temporary helper for svn_wc__db_op_copy to handle copying from one
+   db to another, it becomes redundant when we centralise. */
+static svn_error_t *
+temp_cross_db_copy(svn_wc__db_t *db,
+                   const char *src_abspath,
+                   svn_wc__db_pdh_t *src_pdh,
+                   const char *src_relpath,
+                   svn_wc__db_pdh_t *dst_pdh,
+                   const char *dst_relpath,
+                   svn_wc__db_kind_t kind,
+                   apr_int64_t copyfrom_id,
+                   const char *copyfrom_relpath,
+                   svn_revnum_t copyfrom_rev,
+                   apr_pool_t *scratch_pool)
+{
+  insert_working_baton_t iwb;
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+  const svn_checksum_t *checksum;
+  apr_hash_t *props;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(kind == svn_wc__db_kind_file);
+
+  SVN_ERR(svn_wc__db_read_info(NULL, /* status */
+                               NULL, /* kind */
+                               NULL, /* revision */
+                               NULL, /* repos_relpath */
+                               NULL, /* repos_root_url */
+                               NULL, /* repos_uuid */
+                               &changed_rev, &changed_date, &changed_author,
+                               NULL, /* last_mod_time */
+                               NULL, /* depth */
+                               &checksum,
+                               NULL, /* translated_size */
+                               NULL, /* target */
+                               NULL, /* changelist */
+                               NULL, /* original_repos_relpath */
+                               NULL, /* original_root_url */
+                               NULL, /* original_uuid */
+                               NULL, /* original_revision */
+                               NULL, /* text_mod */
+                               NULL, /* props_mod */
+                               NULL, /* base_shadowed */

[... 2462 lines stripped ...]