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

svn commit: r997472 [21/41] - in /subversion/branches/py-tests-as-modules: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/ subversion/bindings/javahl/native/ subversi...

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c Wed Sep 15 19:32:26 2010
@@ -158,22 +158,6 @@ svn_wc__entry_is_hidden(svn_boolean_t *h
 }
 
 
-/* */
-static svn_error_t *
-fetch_wc_id(apr_int64_t *wc_id, svn_sqlite__db_t *sdb)
-{
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-
-  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_create(SVN_ERR_WC_DB_ERROR, NULL, _("No WC table entry"));
-  *wc_id = svn_sqlite__column_int(stmt, 0);
-  return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
 /* Hit the database to check the file external information for the given
    entry.  The entry will be modified in place. */
 static svn_error_t *
@@ -287,8 +271,7 @@ get_base_info_for_deleted(svn_wc_entry_t
                                    NULL, NULL, NULL, NULL, NULL, NULL,
                                    db, parent_abspath,
                                    scratch_pool, scratch_pool));
-      if (parent_status == svn_wc__db_status_added
-          || parent_status == svn_wc__db_status_obstructed_add)
+      if (parent_status == svn_wc__db_status_added)
         SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
                                          &parent_repos_relpath,
                                          &entry->repos,
@@ -420,8 +403,7 @@ get_base_info_for_deleted(svn_wc_entry_t
                                        NULL, NULL, NULL, NULL, NULL, NULL,
                                        db, parent_abspath,
                                        scratch_pool, scratch_pool));
-          if (parent_status == svn_wc__db_status_added
-              || parent_status == svn_wc__db_status_obstructed_add)
+          if (parent_status == svn_wc__db_status_added)
             SVN_ERR(svn_wc__db_scan_addition(&parent_status,
                                              NULL,
                                              NULL, NULL, NULL,
@@ -664,33 +646,24 @@ read_one_entry(const svn_wc_entry_t **ne
           entry->incomplete = (status == svn_wc__db_status_incomplete);
         }
     }
-  else if (status == svn_wc__db_status_deleted
-           || status == svn_wc__db_status_obstructed_delete)
+  else if (status == svn_wc__db_status_deleted)
     {
+      svn_node_kind_t path_kind;
       /* ### we don't have to worry about moves, so this is a delete. */
       entry->schedule = svn_wc_schedule_delete;
 
-      /* ### keep_local ... ugh. hacky.  */
-      /* We only read keep_local in the directory itself, because we
-         can't rely on the actual record being available in the parent
-         stub when the directory is recorded as deleted in the directory
-         itself. (This last value is the status that brought us in this
-         if block).
-
-         This is safe because we will only write this flag in the
-         directory itself (see mark_deleted() in adm_ops.c), and also
-         because we will never use keep_local in the final version of
-         WC-NG. With a central db and central pristine store we can
-         remove working copy directories directly. So any left over
-         directories after the delete operation are always kept locally.
-      */
-      if (*entry->name == '\0')
-        SVN_ERR(svn_wc__db_temp_determine_keep_local(&entry->keep_local,
-                                                     db, entry_abspath,
-                                                     scratch_pool));
+      /* If there is still a directory on-disk we keep it, if not it is
+         already deleted. Simple, isn't it? 
+         
+         Before single-db we had to keep the administative area alive until
+         after the commit really deletes it. Setting keep alive stopped the
+         commit processing from deleting the directory. We don't delete it
+         any more, so all we have to do is provide some 'sane' value.
+       */
+      SVN_ERR(svn_io_check_path(entry_abspath, &path_kind, scratch_pool));
+      entry->keep_local = (path_kind == svn_node_dir);
     }
-  else if (status == svn_wc__db_status_added
-           || status == svn_wc__db_status_obstructed_add)
+  else if (status == svn_wc__db_status_added)
     {
       svn_wc__db_status_t work_status;
       const char *op_root_abspath;
@@ -772,16 +745,7 @@ read_one_entry(const svn_wc_entry_t **ne
                   && !SVN_IS_VALID_REVNUM(entry->cmt_rev))
                 entry->revision = 0;
 
-              if (status == svn_wc__db_status_obstructed_add)
-                entry->revision = SVN_INVALID_REVNUM;
-
-              /* ### when we're reading a directory that is not present,
-                 ### then it must be "normal" rather than "add".  */
-              if (*entry->name == '\0'
-                  && status == svn_wc__db_status_obstructed_add)
-                entry->schedule = svn_wc_schedule_normal;
-              else
-                entry->schedule = svn_wc_schedule_add;
+              entry->schedule = svn_wc_schedule_add;
             }
         }
 
@@ -789,13 +753,6 @@ read_one_entry(const svn_wc_entry_t **ne
          then we cannot begin a scan for data. The original node may
          have important data. Set up stuff to kill that idea off,
          and finish up this entry.  */
-      if (status == svn_wc__db_status_obstructed_add)
-        {
-          entry->cmt_rev = SVN_INVALID_REVNUM;
-          work_status = svn_wc__db_status_normal;
-          scanned_original_relpath = NULL;
-        }
-      else
         {
           SVN_ERR(svn_wc__db_scan_addition(&work_status,
                                            &op_root_abspath,
@@ -993,12 +950,6 @@ read_one_entry(const svn_wc_entry_t **ne
       entry->schedule = svn_wc_schedule_normal;
       entry->deleted = TRUE;
     }
-  else if (status == svn_wc__db_status_obstructed)
-    {
-      /* ### set some values that should (hopefully) let this directory
-         ### be usable.  */
-      entry->revision = SVN_INVALID_REVNUM;
-    }
   else if (status == svn_wc__db_status_absent)
     {
       entry->absent = TRUE;
@@ -1051,13 +1002,9 @@ read_one_entry(const svn_wc_entry_t **ne
   */
   SVN_ERR_ASSERT(repos_relpath != NULL
                  || entry->schedule == svn_wc_schedule_delete
-                 || status == svn_wc__db_status_obstructed
-                 || status == svn_wc__db_status_obstructed_add
-                 || status == svn_wc__db_status_obstructed_delete
                  || status == svn_wc__db_status_not_present
                  || status == svn_wc__db_status_absent
-                 || status == svn_wc__db_status_excluded
-                 );
+                 || status == svn_wc__db_status_excluded);
   if (repos_relpath)
     entry->url = svn_path_url_add_component2(entry->repos,
                                              repos_relpath,
@@ -1307,7 +1254,7 @@ read_entries(apr_hash_t **entries,
    which the entry information is located, and *ENTRY_NAME to the entry name
    to access that entry.
 
-   KIND and NEED_PARENT_STUB are as in svn_wc__get_entry().
+   KIND is as in svn_wc__get_entry().
 
    Return the results in RESULT_POOL and use SCRATCH_POOL for temporary
    allocations. */
@@ -1317,16 +1264,12 @@ get_entry_access_info(const char **adm_a
                       svn_wc__db_t *db,
                       const char *local_abspath,
                       svn_node_kind_t kind,
-                      svn_boolean_t need_parent_stub,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 {
   svn_wc_adm_access_t *adm_access;
   svn_boolean_t read_from_subdir = FALSE;
 
-  /* Can't ask for the parent stub if the node is a file.  */
-  SVN_ERR_ASSERT(!need_parent_stub || kind != svn_node_file);
-
   /* If the caller didn't know the node kind, then stat the path. Maybe
      it is really there, and we can speed up the steps below.  */
   if (kind == svn_node_unknown)
@@ -1370,10 +1313,10 @@ get_entry_access_info(const char **adm_a
         {
           /* We found a directory for this UNKNOWN node. Determine whether
              we need to read inside it.  */
-          read_from_subdir = !need_parent_stub;
+          read_from_subdir = TRUE;
         }
     }
-  else if (kind == svn_node_dir && !need_parent_stub)
+  else if (kind == svn_node_dir)
     {
       read_from_subdir = TRUE;
     }
@@ -1390,7 +1333,7 @@ get_entry_access_info(const char **adm_a
       /* FILE node needs to read the parent directory. Or a DIR node
          needs to read from the parent to get at the stub entry. Or this
          is an UNKNOWN node, and we need to examine the parent.  */
-      svn_dirent_split(local_abspath, adm_abspath, entry_name, result_pool);
+      svn_dirent_split(adm_abspath, entry_name, local_abspath, result_pool);
     }
 
   return SVN_NO_ERROR;
@@ -1403,19 +1346,14 @@ svn_wc__get_entry(const svn_wc_entry_t *
                   const char *local_abspath,
                   svn_boolean_t allow_unversioned,
                   svn_node_kind_t kind,
-                  svn_boolean_t need_parent_stub,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
   const char *dir_abspath;
   const char *entry_name;
 
-  /* Can't ask for the parent stub if the node is a file.  */
-  SVN_ERR_ASSERT(!need_parent_stub || kind != svn_node_file);
-
   SVN_ERR(get_entry_access_info(&dir_abspath, &entry_name, db, local_abspath,
-                                kind, need_parent_stub, scratch_pool,
-                                scratch_pool));
+                                kind, scratch_pool, scratch_pool));
 
     {
       const svn_wc_entry_t *parent_entry;
@@ -1464,8 +1402,7 @@ svn_wc__get_entry(const svn_wc_entry_t *
              Redo the fetch, but "insist" we are trying to find a file.
              This will read from the parent directory of the "file".  */
           err = svn_wc__get_entry(entry, db, local_abspath, allow_unversioned,
-                                  svn_node_file, FALSE,
-                                  result_pool, scratch_pool);
+                                  svn_node_file, result_pool, scratch_pool);
           if (err == SVN_NO_ERROR)
             return SVN_NO_ERROR;
           if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
@@ -1503,106 +1440,9 @@ svn_wc__get_entry(const svn_wc_entry_t *
                              svn_dirent_local_style(local_abspath,
                                                     scratch_pool));
 
-  if (kind == svn_node_unknown)
-    {
-      /* They wanted a (directory) stub, but this isn't a directory.  */
-      if (need_parent_stub && (*entry)->kind != svn_node_dir)
-        return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                                 _("'%s' is not of the right kind"),
-                                 svn_dirent_local_style(local_abspath,
-                                                        scratch_pool));
-
-      /* The actual (directory) information was wanted, but we got a stub.  */
-      if (!need_parent_stub
-          && (*entry)->kind == svn_node_dir
-          && *(*entry)->name != '\0')
-        return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                                 _("'%s' is not of the right kind"),
-                                 svn_dirent_local_style(local_abspath,
-                                                        scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__get_entry_versioned(const svn_wc_entry_t **entry,
-                            svn_wc_context_t *wc_ctx,
-                            const char *local_abspath,
-                            svn_node_kind_t kind,
-                            svn_boolean_t show_hidden,
-                            svn_boolean_t need_parent_stub,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool)
-{
-  svn_error_t *err;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  /* We call this with allow_unversioned=TRUE, since the error returned is
-     different than our callers currently expect.  We catch the NULL entry
-     below and return the correct error. */
-  err = svn_wc__get_entry(entry, wc_ctx->db, local_abspath, TRUE, kind,
-                          need_parent_stub, result_pool, scratch_pool);
-  if (err && (err->apr_err == SVN_ERR_WC_MISSING
-                || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
-                || err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND))
-    {
-      svn_error_clear(err);
-      *entry = NULL;
-    }
-  else if (err)
-    return svn_error_return(err);
-
-
-  if (*entry && !show_hidden)
-    {
-      svn_boolean_t hidden;
-
-      SVN_ERR(svn_wc__entry_is_hidden(&hidden, *entry));
-      if (hidden)
-        *entry = NULL;
-    }
-
-  if (! *entry)
-    return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
-                             _("'%s' is not under version control"),
-                             svn_dirent_local_style(local_abspath,
-                                                    scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__node_is_deleted(svn_boolean_t *deleted,
-                        svn_wc__db_t *db,
-                        const char *local_abspath,
-                        apr_pool_t *scratch_pool)
-{
-  const svn_wc_entry_t *entry;
-  svn_error_t *err;
-
-  /* ### rewrite this in terms of wc_db.  */
-
-  err = svn_wc__get_entry(&entry, db, local_abspath, FALSE,
-                          svn_node_unknown, TRUE, scratch_pool, scratch_pool);
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
-        return svn_error_return(err);
-
-      /* We asked for the parent stub, but got a file. No big deal. We have
-         what we wanted for a file.  */
-      svn_error_clear(err);
-    }
-
-  *deleted = entry->deleted;
   return SVN_NO_ERROR;
 }
 
-
 /* TODO ### Rewrite doc string to mention ENTRIES_ALL; not ADM_ACCESS.
 
    Prune the deleted entries from the cached entries in ADM_ACCESS, and
@@ -1692,7 +1532,8 @@ svn_wc_entries_read(apr_hash_t **entries
 }
 
 
-/* */
+/* No transaction required: called from write_entry which is itself
+   transaction-wrapped. */
 static svn_error_t *
 insert_base_node(svn_sqlite__db_t *sdb,
                  const db_base_node_t *base_node,
@@ -1700,6 +1541,10 @@ insert_base_node(svn_sqlite__db_t *sdb,
 {
   svn_sqlite__stmt_t *stmt;
 
+#ifndef SVN_WC__NODES_ONLY
+  /* ### NODE_DATA when switching to NODE_DATA, replace the
+     query below with STMT_INSERT_BASE_NODE_DATA_FOR_ENTRY_1
+     and adjust the parameters bound. Can't do that yet. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
                                     STMT_INSERT_BASE_NODE_FOR_ENTRY));
 
@@ -1728,13 +1573,8 @@ insert_base_node(svn_sqlite__db_t *sdb,
 
   SVN_ERR(svn_sqlite__bind_int64(stmt, 7, base_node->revision));
 
-  /* ### in per-subdir operation, if we're about to write a directory and
-     ### it is *not* "this dir", then we're writing a row in the parent
-     ### directory about the child. note that in the kind.  */
   /* ### kind might be "symlink" or "unknown" */
-  if (base_node->kind == svn_node_dir && *base_node->local_relpath != '\0')
-    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "subdir"));
-  else if (base_node->kind == svn_node_none)
+  if (base_node->kind == svn_node_none)
     SVN_ERR(svn_sqlite__bind_text(stmt, 5, "unknown"));
   else
     SVN_ERR(svn_sqlite__bind_text(stmt, 8,
@@ -1764,7 +1604,69 @@ insert_base_node(svn_sqlite__db_t *sdb,
                                         scratch_pool));
 
   /* Execute and reset the insert clause. */
-  return svn_error_return(svn_sqlite__insert(NULL, stmt));
+  SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#endif
+#ifdef SVN_WC__NODES
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_INSERT_BASE_NODE_FOR_ENTRY_1));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "issisr",
+                            base_node->wc_id,
+                            base_node->local_relpath,
+                            base_node->parent_relpath,
+                            base_node->repos_id,
+                            base_node->repos_relpath,
+                            base_node->revision));
+
+  if (base_node->presence == svn_wc__db_status_not_present)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 7, "not-present"));
+  else if (base_node->presence == svn_wc__db_status_normal)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 7, "normal"));
+  else if (base_node->presence == svn_wc__db_status_absent)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 7, "absent"));
+  else if (base_node->presence == svn_wc__db_status_incomplete)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 7, "incomplete"));
+  else if (base_node->presence == svn_wc__db_status_excluded)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 7, "excluded"));
+
+  /* ### kind might be "symlink" or "unknown" */
+  if (base_node->kind == svn_node_none)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 8, "unknown"));
+  else
+    SVN_ERR(svn_sqlite__bind_text(stmt, 8,
+                                  svn_node_kind_to_word(base_node->kind)));
+
+  if (base_node->checksum)
+    SVN_ERR(svn_sqlite__bind_checksum(stmt, 9, base_node->checksum,
+                                      scratch_pool));
+
+  /* ### strictly speaking, changed_rev should be valid for present nodes. */
+  if (SVN_IS_VALID_REVNUM(base_node->changed_rev))
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 10, base_node->changed_rev));
+  if (base_node->changed_date)
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 11, base_node->changed_date));
+  if (base_node->changed_author)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 12, base_node->changed_author));
+
+  SVN_ERR(svn_sqlite__bind_text(stmt, 13, svn_depth_to_word(base_node->depth)));
+
+  if (base_node->properties)
+    SVN_ERR(svn_sqlite__bind_properties(stmt, 14, base_node->properties,
+                                        scratch_pool));
+
+  if (base_node->translated_size != SVN_INVALID_FILESIZE)
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 15, base_node->translated_size));
+
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 16, base_node->last_mod_time));
+
+  /* Execute and reset the insert clause. */
+  SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+
+#endif
+  return SVN_NO_ERROR;
 }
 
 /* */
@@ -1775,6 +1677,9 @@ insert_working_node(svn_sqlite__db_t *sd
 {
   svn_sqlite__stmt_t *stmt;
 
+  /* ### NODE_DATA when switching to NODE_DATA, replace the
+     query below with STMT_INSERT_WORKING_NODE_DATA_2
+     and adjust the parameters bound. Can't do that yet. */
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_WORKING_NODE));
 
   SVN_ERR(svn_sqlite__bind_int64(stmt, 1, working_node->wc_id));
@@ -1793,13 +1698,7 @@ insert_working_node(svn_sqlite__db_t *sd
   else if (working_node->presence == svn_wc__db_status_excluded)
     SVN_ERR(svn_sqlite__bind_text(stmt, 4, "excluded"));
 
-  /* ### in per-subdir operation, if we're about to write a directory and
-     ### it is *not* "this dir", then we're writing a row in the parent
-     ### directory about the child. note that in the kind.  */
-  if (working_node->kind == svn_node_dir
-      && *working_node->local_relpath != '\0')
-    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "subdir"));
-  else if (working_node->kind == svn_node_none)
+  if (working_node->kind == svn_node_none)
     SVN_ERR(svn_sqlite__bind_text(stmt, 5, "unknown"));
   else
     SVN_ERR(svn_sqlite__bind_text(stmt, 5,
@@ -1848,7 +1747,72 @@ insert_working_node(svn_sqlite__db_t *sd
   /* ### we should bind 'symlink_target' (20) as appropriate.  */
 
   /* Execute and reset the insert clause. */
-  return svn_error_return(svn_sqlite__insert(NULL, stmt));
+  SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#ifdef SVN_WC__NODE_DATA
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_INSERT_WORKING_NODE_DATA_1));
+
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 1, working_node->wc_id));
+  SVN_ERR(svn_sqlite__bind_text(stmt, 2, working_node->local_relpath));
+  SVN_ERR(svn_sqlite__bind_int64(stmt, 3,
+               (*working_node->local_relpath == '\0') ? 1 : 2));
+  SVN_ERR(svn_sqlite__bind_text(stmt, 4, working_node->parent_relpath));
+
+  /* ### need rest of values */
+  if (working_node->presence == svn_wc__db_status_normal)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "normal"));
+  else if (working_node->presence == svn_wc__db_status_not_present)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "not-present"));
+  else if (working_node->presence == svn_wc__db_status_base_deleted)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "base-deleted"));
+  else if (working_node->presence == svn_wc__db_status_incomplete)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "incomplete"));
+  else if (working_node->presence == svn_wc__db_status_excluded)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 5, "excluded"));
+
+  if (working_node->kind == svn_node_none)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 6, "unknown"));
+  else
+    SVN_ERR(svn_sqlite__bind_text(stmt, 6,
+                                  svn_node_kind_to_word(working_node->kind)));
+
+  if (working_node->copyfrom_repos_path)
+    {
+      SVN_ERR(svn_sqlite__bind_int64(stmt, 7,
+                                     working_node->copyfrom_repos_id));
+      SVN_ERR(svn_sqlite__bind_text(stmt, 8,
+                                    working_node->copyfrom_repos_path));
+      SVN_ERR(svn_sqlite__bind_int64(stmt, 9, working_node->copyfrom_revnum));
+    }
+
+  if (working_node->checksum)
+    SVN_ERR(svn_sqlite__bind_checksum(stmt, 10, working_node->checksum,
+                                      scratch_pool));
+
+  if (SVN_IS_VALID_REVNUM(working_node->changed_rev))
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 11, working_node->changed_rev));
+  if (working_node->changed_date)
+    SVN_ERR(svn_sqlite__bind_int64(stmt, 12, working_node->changed_date));
+  if (working_node->changed_author)
+    SVN_ERR(svn_sqlite__bind_text(stmt, 13, working_node->changed_author));
+
+  SVN_ERR(svn_sqlite__bind_text(stmt, 14,
+                                svn_depth_to_word(working_node->depth)));
+
+  if (working_node->properties)
+    SVN_ERR(svn_sqlite__bind_properties(stmt, 15, working_node->properties,
+                                        scratch_pool));
+
+  /* ### we should bind 'symlink_target' (16) as appropriate.  */
+
+  /* Execute and reset the insert clause. */
+  SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#endif
+
+  return SVN_NO_ERROR;
 }
 
 /* */
@@ -2110,12 +2074,25 @@ write_entry(svn_wc__db_t *db,
         {
           base_node->kind = entry->kind;
 
-          if (entry->incomplete)
+          /* All subdirs are initially incomplete, they stop being
+             incomplete when the entries file in the subdir is
+             upgraded and remain incomplete if that doesn't happen. */
+          if (entry->kind == svn_node_dir
+              && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))
             {
-              /* ### nobody should have set the presence.  */
-              SVN_ERR_ASSERT(base_node->presence == svn_wc__db_status_normal);
               base_node->presence = svn_wc__db_status_incomplete;
             }
+          else
+            {
+
+              if (entry->incomplete)
+                {
+                  /* ### nobody should have set the presence.  */
+                  SVN_ERR_ASSERT(base_node->presence
+                                 == svn_wc__db_status_normal);
+                  base_node->presence = svn_wc__db_status_incomplete;
+                }
+            }
         }
 
       if (entry->kind == svn_node_dir)
@@ -2231,7 +2208,15 @@ write_entry(svn_wc__db_t *db,
                                        svn_checksum_md5,
                                        entry->checksum, scratch_pool));
 
-      if (entry->schedule == svn_wc_schedule_delete)
+      /* All subdirs start of incomplete, and stop being incomplete
+         when the entries file in the subdir is upgraded. */
+      if (entry->kind == svn_node_dir
+          && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))
+        {
+          working_node->presence = svn_wc__db_status_incomplete;
+          working_node->kind = svn_node_dir;
+        }
+      else if (entry->schedule == svn_wc_schedule_delete)
         {
           if (entry->incomplete)
             {
@@ -2305,7 +2290,8 @@ struct entries_write_baton
   svn_wc__db_t *db;
   apr_int64_t repos_id;
   apr_int64_t wc_id;
-  const char *local_abspath;
+  const char *dir_abspath;
+  const char *new_root_abspath;
   apr_hash_t *entries;
 };
 
@@ -2318,11 +2304,12 @@ entries_write_new_cb(void *baton,
 {
   struct entries_write_baton *ewb = baton;
   svn_wc__db_t *db = ewb->db;
-  const char *local_abspath = ewb->local_abspath;
+  const char *dir_abspath = ewb->dir_abspath;
+  const char *new_root_abspath = ewb->new_root_abspath;
   const svn_wc_entry_t *this_dir;
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  const char *repos_root;
+  const char *repos_root, *old_root_abspath, *dir_relpath;
 
   /* Get a copy of the "this dir" entry for comparison purposes. */
   this_dir = apr_hash_get(ewb->entries, SVN_WC_ENTRY_THIS_DIR,
@@ -2332,13 +2319,24 @@ entries_write_new_cb(void *baton,
   if (! this_dir)
     return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
                              _("No default entry in directory '%s'"),
-                             svn_dirent_local_style(local_abspath,
+                             svn_dirent_local_style(dir_abspath,
                                                     iterpool));
   repos_root = this_dir->repos;
 
+  old_root_abspath = svn_dirent_get_longest_ancestor(dir_abspath,
+                                                     new_root_abspath,
+                                                     scratch_pool);
+
+  SVN_ERR_ASSERT(old_root_abspath[0]);
+
+  dir_relpath = svn_dirent_skip_ancestor(old_root_abspath, dir_abspath);
+
   /* Write out "this dir" */
   SVN_ERR(write_entry(db, sdb, ewb->wc_id, ewb->repos_id, repos_root,
-                      this_dir, SVN_WC_ENTRY_THIS_DIR, local_abspath,
+                      this_dir,
+                      dir_relpath,
+                      svn_dirent_join(new_root_abspath, dir_relpath,
+                                      scratch_pool),
                       this_dir, FALSE, FALSE, iterpool));
 
   for (hi = apr_hash_first(scratch_pool, ewb->entries); hi;
@@ -2346,7 +2344,7 @@ entries_write_new_cb(void *baton,
     {
       const char *name = svn__apr_hash_index_key(hi);
       const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi);
-      const char *child_abspath;
+      const char *child_abspath, *child_relpath;
 
       svn_pool_clear(iterpool);
 
@@ -2356,9 +2354,14 @@ entries_write_new_cb(void *baton,
 
       /* Write the entry. Pass TRUE for create locks, because we still
          use this function for upgrading old working copies. */
-      child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+      child_abspath = svn_dirent_join(dir_abspath, name, iterpool);
+      child_relpath = svn_dirent_skip_ancestor(old_root_abspath, child_abspath);
       SVN_ERR(write_entry(db, sdb, ewb->wc_id, ewb->repos_id, repos_root,
-                          this_entry, name, child_abspath, this_dir,
+                          this_entry,
+                          child_relpath,
+                          svn_dirent_join(new_root_abspath, child_relpath,
+                                          scratch_pool),
+                          this_dir,
                           FALSE, TRUE,
                           iterpool));
     }
@@ -2373,7 +2376,8 @@ svn_wc__write_upgraded_entries(svn_wc__d
                                svn_sqlite__db_t *sdb,
                                apr_int64_t repos_id,
                                apr_int64_t wc_id,
-                               const char *local_abspath,
+                               const char *dir_abspath,
+                               const char *new_root_abspath,
                                apr_hash_t *entries,
                                apr_pool_t *scratch_pool)
 {
@@ -2382,7 +2386,8 @@ svn_wc__write_upgraded_entries(svn_wc__d
   ewb.db = db;
   ewb.repos_id = repos_id;
   ewb.wc_id = wc_id;
-  ewb.local_abspath = local_abspath;
+  ewb.dir_abspath = dir_abspath;
+  ewb.new_root_abspath = new_root_abspath;
   ewb.entries = entries;
 
   /* Run this operation in a transaction to speed up SQLite.
@@ -2392,630 +2397,6 @@ svn_wc__write_upgraded_entries(svn_wc__d
                                    scratch_pool));
 }
 
-struct write_one_entry_baton
-{
-  svn_wc__db_t *db;
-  const char *local_abspath;
-  const svn_wc_entry_t *this_dir;
-  const svn_wc_entry_t *this_entry;
-};
-
-/* Rewrites a single entry inside a sqlite transaction
-   Implements svn_sqlite__transaction_callback_t. */
-static svn_error_t *
-write_one_entry_cb(void *baton,
-                   svn_sqlite__db_t *sdb,
-                   apr_pool_t *scratch_pool)
-{
-  struct write_one_entry_baton *woeb = baton;
-  svn_wc__db_t *db = woeb->db;
-  const char *local_abspath = woeb->local_abspath;
-  const svn_wc_entry_t *this_dir = woeb->this_dir;
-  const svn_wc_entry_t *this_entry = woeb->this_entry;
-  const char *this_abspath = svn_dirent_join(local_abspath, this_entry->name,
-                                             scratch_pool);
-  const void *base_props = NULL;
-  const void *working_props = NULL;
-  const void *actual_props = NULL;
-  apr_size_t base_prop_len;
-  apr_size_t working_prop_len;
-  apr_size_t actual_prop_len;
-  apr_hash_t *dav_cache;
-  const svn_checksum_t *base_checksum;
-  svn_sqlite__stmt_t *stmt;
-  const char *repos_root;
-  apr_int64_t repos_id;
-  apr_int64_t wc_id;
-  svn_error_t *err;
-  svn_boolean_t got_row;
-
-  SVN_ERR_ASSERT(this_dir && this_entry);
-
-  /* Get the repos ID. */
-  if (this_dir->uuid != NULL)
-    {
-      /* ### does this need to be done on a per-entry basis instead of
-         ### the per-directory way we do it now?  me thinks yes...
-         ###
-         ### when do we harvest repository entries which no longer have
-         ### any members?  */
-      SVN_ERR(svn_wc__db_repos_ensure(&repos_id, db, local_abspath,
-                                      this_dir->repos, this_dir->uuid,
-                                      scratch_pool));
-      repos_root = this_dir->repos;
-    }
-  else
-    {
-      repos_id = 0;
-      repos_root = NULL;
-    }
-
-  SVN_ERR(fetch_wc_id(&wc_id, sdb));
-
-  /* Before we nuke all the nodes, we need to get a few values */
-
-  /* The dav cache is not in STMT_SELECT_BASE_NODE */
-  err = svn_wc__db_base_get_dav_cache(&dav_cache, db, this_abspath,
-                                      scratch_pool, scratch_pool);
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
-        return svn_error_return(err);
-      svn_error_clear(err); /* No BASE record */
-      dav_cache = NULL;
-    }
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step(&got_row, stmt));
-  if (got_row)
-    {
-      base_props = svn_sqlite__column_blob(stmt, 13, &base_prop_len,
-                                           scratch_pool);
-
-      err = svn_sqlite__column_checksum(&base_checksum, stmt, 5, scratch_pool);
-      /* ### SVN_EXPERIMENTAL_PRISTINE:
-         base_checksum is originally MD-5 but will later be SHA-1.  The
-         base_checksum is not yet handled by this function. */
-
-      SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
-    }
-  else
-    SVN_ERR(svn_sqlite__reset(stmt));
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step(&got_row, stmt));
-  if (got_row)
-    {
-      /* No need to store the working checksum, that is stored in the entry */
-      working_props = svn_sqlite__column_blob(stmt, 15, &working_prop_len,
-                                              scratch_pool);
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ACTUAL_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step(&got_row, stmt));
-  if (got_row)
-    {
-      actual_props = svn_sqlite__column_blob(stmt, 6, &actual_prop_len,
-                                             scratch_pool);
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
-
-  /* Remove the WORKING, BASE and ACTUAL nodes for this entry */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_ACTUAL_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
-  SVN_ERR(write_entry(db, sdb, wc_id, repos_id, repos_root, this_entry,
-                      this_entry->name, this_abspath, this_dir,
-                      actual_props != NULL, FALSE, scratch_pool));
-
-  if (dav_cache)
-    SVN_ERR(svn_wc__db_base_set_dav_cache(db, this_abspath, dav_cache,
-                                          scratch_pool));
-
-  if (base_props)
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_PROPS));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
-                                base_props, base_prop_len));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
-  if (working_props)
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                        STMT_UPDATE_WORKING_PROPS));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
-                                working_props, working_prop_len));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
-  if (actual_props)
-    {
-      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
-                                        STMT_UPDATE_ACTUAL_PROPS));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
-                                actual_props, actual_prop_len));
-      SVN_ERR(svn_sqlite__step_done(stmt));
-    }
-
-  /* TODO: Update base checksum if needed */
-  return SVN_NO_ERROR;
-}
-
-/* */
-static svn_error_t *
-write_one_entry(svn_wc__db_t *db,
-                const char *local_abspath,
-                const svn_wc_entry_t *this_dir,
-                const svn_wc_entry_t *this_entry,
-                apr_pool_t *scratch_pool)
-{
-  struct write_one_entry_baton woeb;
-  svn_sqlite__db_t *sdb;
-
-  /* ### need the SDB so we can jam rows directly into it.  */
-  SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, db, local_abspath,
-                                     svn_wc__db_openmode_readwrite,
-                                     scratch_pool));
-  woeb.db = db;
-  woeb.local_abspath = local_abspath;
-  woeb.this_dir = this_dir;
-  woeb.this_entry = this_entry;
-
-  /* Run this operation in a transaction to speed up SQLite.
-     See http://www.sqlite.org/faq.html#q19 for more details */
-  return svn_error_return(
-      svn_sqlite__with_transaction(sdb, write_one_entry_cb, &woeb,
-                                   scratch_pool));
-}
-
-
-
-/* Update the entry CUR_ENTRY, according to the combination of
-   entry data found in ENTRY and masked by MODIFY_FLAGS.
-   The requested changes will be folded (merged) into
-   the entry's existing state.
-   Also cleanups meaningless fields combinations.
-
-   PARENT_ENTRY must be passed, in order to grab certain "default" values.
-
-   POOL will be used to allocate memory referenced by ENTRIES.
- */
-static svn_error_t *
-fold_entry(svn_wc_entry_t *cur_entry,
-           const char *name,
-           int modify_flags,
-           const svn_wc_entry_t *entry,
-           const svn_wc_entry_t *parent_entry,
-           apr_pool_t *pool)
-{
-  SVN_ERR_ASSERT(cur_entry != NULL);
-  SVN_ERR_ASSERT(name != NULL);
-  SVN_ERR_ASSERT(entry != NULL);
-
-  /* Name (just a safeguard here, really) */
-  if (! cur_entry->name)
-    cur_entry->name = apr_pstrdup(pool, name);
-
-  /* Revision */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_REVISION)
-    cur_entry->revision = entry->revision;
-
-  /* Ancestral URL in repository */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_URL)
-    cur_entry->url = entry->url ? apr_pstrdup(pool, entry->url) : NULL;
-
-  /* Kind */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_KIND)
-    cur_entry->kind = entry->kind;
-
-  /* Schedule: handled by caller.  */
-
-  /* Checksum */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_CHECKSUM)
-    cur_entry->checksum = entry->checksum
-      ? apr_pstrdup(pool, entry->checksum)
-                          : NULL;
-
-  /* Copy-related stuff */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_COPIED)
-    cur_entry->copied = entry->copied;
-
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_COPYFROM_URL)
-    cur_entry->copyfrom_url = entry->copyfrom_url
-      ? apr_pstrdup(pool, entry->copyfrom_url)
-                              : NULL;
-
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_COPYFROM_REV)
-    cur_entry->copyfrom_rev = entry->copyfrom_rev;
-
-  /* Deleted state */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_DELETED)
-    cur_entry->deleted = entry->deleted;
-
-  /* Absent state is no longer passed to entry_modify() */
-
-  /* text_time, prop_time no longer passed to entry_modify()  */
-
-  /* Conflict stuff no longer passed to entry_modify() */
-
-  /* Last-commit flags are no longer passed to entry_modify() */
-
-  /* LOCK flags are no longer passed to entry_modify().  */
-
-  /* changelist is no longer modified with this function.  */
-
-  /* has-props, prop-mods, cachable-props, and present-props are deprecated,
-     so we do not copy them. */
-
-  /* keep_local is no longer modified with this function */
-
-  /* Note that we don't bother to fold entry->depth, because it is
-     only meaningful on the this-dir entry anyway. */
-
-  /* tree_conflict_data is never modified via entry_t.  */
-
-  /* Absorb defaults from the parent dir, if any, unless this is a
-     subdir entry. */
-  if (cur_entry->kind != svn_node_dir && parent_entry != NULL)
-    {
-      if ((cur_entry->revision == SVN_INVALID_REVNUM) 
-          && (cur_entry->kind != svn_node_dir))
-        cur_entry->revision = parent_entry->revision;
-    }
-
-  /* Cleanup meaningless fields */
-
-  /* ### svn_wc_schedule_delete is the minimal value. We need it because it's
-     impossible to NULLify copyfrom_url with log-instructions.
-
-     Note that I tried to find the smallest collection not to clear these
-     fields for, but this condition still fails the test suite:
-
-     !(entry->schedule == svn_wc_schedule_add
-       || entry->schedule == svn_wc_schedule_replace
-       || (entry->schedule == svn_wc_schedule_normal && entry->copied)))
-
-  */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE
-      && cur_entry->schedule == svn_wc_schedule_delete)
-    {
-      cur_entry->copied = FALSE;
-      cur_entry->copyfrom_rev = SVN_INVALID_REVNUM;
-      cur_entry->copyfrom_url = NULL;
-    }
-
-  /* working_size is no longer passed to entry_modify()  */
-
-  /* keep_local makes sense only when we are going to delete directory. */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE
-      && cur_entry->schedule != svn_wc_schedule_delete)
-    {
-      cur_entry->keep_local = FALSE;
-    }
-
-  /* File externals are no longer passed to entry_modify(). */
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Our general purpose intelligence module for handling a scheduling change
-   to a single entry.
-
-   Given an ENTRY with name NAME, examine the caller's requested scheduling
-    change and the current state of the entry and its directory entry
-   THIS_DIR_ENTRY, which can be equal to ENTRY.
-
-   Determine the final schedule for the entry based on NEW_SCHEDULE and the
-   entries.
-
-   The output can be:
-    * *SKIP_SCHEDULE_CHANGE set to true, when no schedule change is necessary.
-    * Or a schedule change.
-
-   In all these cases *RESULT_SCHEDULE contains the new schedule value.
- */
-static svn_error_t *
-fold_scheduling(svn_boolean_t *skip_schedule_change,
-                svn_wc_schedule_t *result_schedule,
-                const svn_wc_entry_t *this_dir_entry,
-                const svn_wc_entry_t *entry,
-                svn_wc_schedule_t new_schedule,
-                const char *name)
-{
-  SVN_ERR_ASSERT(this_dir_entry);
-  SVN_ERR_ASSERT(new_schedule != svn_wc_schedule_replace);
-
-  *skip_schedule_change = FALSE;
-  *result_schedule = new_schedule;
-
-  /* The only operation valid on an item not already in revision
-     control is addition. */
-  if (entry == NULL)
-    {
-      if (new_schedule == svn_wc_schedule_add)
-        return SVN_NO_ERROR;
-
-      return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
-                               _("'%s' is not under version control"),
-                               name);
-    }
-
-  /* At this point, we know the following things:
-
-     1. There is already an entry for this item in the entries file
-        whose existence is either _normal or _added (or about to
-        become such), which for our purposes mean the same thing.
-
-     2. We have been asked to merge in a state change, not to
-        explicitly set the state.  */
-
-  /* Here are some cases that are parent-directory sensitive.
-     Basically, we make sure that we are not allowing versioned
-     resources to just sorta dangle below directories marked for
-     deletion. */
-  if ((entry != this_dir_entry)
-      && (this_dir_entry->schedule == svn_wc_schedule_delete))
-    {
-      if (new_schedule == svn_wc_schedule_add)
-        return
-          svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
-                            _("Can't add '%s' to deleted directory; "
-                              "try undeleting its parent directory first"),
-                            name);
-    }
-
-  if (entry->absent && (new_schedule == svn_wc_schedule_add))
-    {
-      return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
-                               _("'%s' is marked as absent, so it cannot "
-                                 "be scheduled for addition"),
-                               name);
-    }
-
-  if (entry->schedule == svn_wc_schedule_normal
-      && new_schedule == svn_wc_schedule_add
-      && !entry->deleted)
-    {
-      /* You can't add something that's already been added to
-         revision control... unless it's got a 'deleted' state */
-      return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
-                               _("Entry '%s' is already under version "
-                                 "control"),
-                               name);
-    }
-
-  if (entry->schedule == svn_wc_schedule_normal)
-    {
-      if (new_schedule == svn_wc_schedule_normal)
-        {
-          /* No-op case.  */
-          *skip_schedule_change = TRUE;
-        }
-    }
-  else if (entry->schedule == svn_wc_schedule_add)
-    {
-      if (new_schedule == svn_wc_schedule_normal
-          || new_schedule == svn_wc_schedule_add)
-        {
-          /* These are both no-op cases.  Normal is obvious, as is add.
-
-             ### Neither case is obvious: above, we throw an error if
-             ### already versioned, so why not here too?
-          */
-          *skip_schedule_change = TRUE;
-        }
-      else if (new_schedule == svn_wc_schedule_delete)
-        {
-          /* This is deleting a node added over the top of a not-present
-             (DELETED=true) node. Return it to the not-present state.  */
-          /* ### not trying to delete the directory, and this is a
-             ### not-present node. (otherwise, caller handles this case)  */
-          SVN_ERR_ASSERT(entry != this_dir_entry);
-          SVN_ERR_ASSERT(entry->deleted);
-
-          *result_schedule = svn_wc_schedule_normal;
-        }
-    }
-  else if (entry->schedule == svn_wc_schedule_delete)
-    {
-      if (new_schedule == svn_wc_schedule_normal)
-        {
-          /* Reverting a delete results in normal */
-        }
-      else if (new_schedule == svn_wc_schedule_delete)
-        {
-          /* This is a no-op case  */
-          *skip_schedule_change = TRUE;
-        }
-      else if (new_schedule == svn_wc_schedule_add)
-        {
-          /* Re-adding an entry marked for deletion?  This is really a
-             replace operation. */
-          *result_schedule = svn_wc_schedule_replace;
-        }
-    }
-  else
-    {
-      /* Only possible state left.  */
-      SVN_ERR_ASSERT(entry->schedule == svn_wc_schedule_replace);
-
-      if (new_schedule == svn_wc_schedule_normal)
-        {
-          /* Reverting replacements results in normal  */
-        }
-      else if (new_schedule == svn_wc_schedule_add)
-        {
-          /* Adding a to-be-replaced entry breaks down to ((delete +
-             add) + add) which might deserve a warning, but we'll just
-             no-op it. */
-          *skip_schedule_change = TRUE;
-        }
-      else if (new_schedule == svn_wc_schedule_delete)
-        {
-          /* Deleting a to-be-replaced entry breaks down to ((delete +
-             add) + delete) which resolves to a flat deletion. */
-          *result_schedule = svn_wc_schedule_delete;
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-
-
-static svn_error_t *
-entry_modify(svn_wc__db_t *db,
-             const char *local_abspath,
-             svn_node_kind_t kind,
-             svn_boolean_t parent_stub,
-             const svn_wc_entry_t *entry_mods,
-             int modify_flags,
-             apr_pool_t *scratch_pool)
-{
-  apr_pool_t *subpool = svn_pool_create(scratch_pool);
-  svn_error_t *err;
-  svn_wc_adm_access_t *adm_access;
-  const char *adm_abspath;
-  const char *name;
-  const svn_wc_entry_t *parent_entry;
-  svn_wc_entry_t *cur_entry;
-  svn_wc_schedule_t new_schedule;
-
-  SVN_ERR_ASSERT(entry_mods);
-
-  SVN_ERR(get_entry_access_info(&adm_abspath, &name, db, local_abspath,
-                                kind, parent_stub, subpool, subpool));
-
-  /* Load ADM_ABSPATH's whole entries file:
-     Is there an existing access baton for this path?  */
-  adm_access = svn_wc__adm_retrieve_internal2(db, adm_abspath, subpool);
-  if (adm_access != NULL)
-    {
-      /* Are we allowed to write to this admin area?  */
-      SVN_ERR(svn_wc__write_check(db, svn_wc__adm_access_abspath(adm_access),
-                                  subpool));
-
-      /* Zap any cached entries. We're about to change them.  */
-      svn_wc__adm_access_set_entries(adm_access, NULL);
-    }
-  /* ### else: should we have some kind of write check here?  */
-
-  /* Cast our non-const CUR_ENTRY appropriately. It will be allocated for
-     us in SUB_POOL, so we actually know it is modifiable.  */
-  SVN_ERR(read_entry_pair(&parent_entry, (const svn_wc_entry_t **)&cur_entry,
-                          db, adm_abspath, name, subpool, subpool));
-
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE)
-    {
-      new_schedule = entry_mods->schedule;
-
-      /* We may just want to force the scheduling change in. Otherwise,
-         call our special function to fold the change in.  */
-      if (!(modify_flags & SVN_WC__ENTRY_MODIFY_FORCE))
-        {
-          svn_boolean_t skip_schedule_change;
-
-          /* ### adm_ops.c is the only code that attempts to transition to
-             ### schedule_replace, but it uses FORCE.  */
-          SVN_ERR_ASSERT(entry_mods->schedule != svn_wc_schedule_replace);
-
-          /* If we are deleting a node that has been added, then simply
-             remove the entry. Do NOT do this for an add over a not-present
-             BASE node (the DELETED flag).  */
-          if (entry_mods->schedule == svn_wc_schedule_delete
-              && cur_entry != NULL
-              && cur_entry->schedule == svn_wc_schedule_add
-              && !cur_entry->deleted)
-            {
-              SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath,
-                                                      subpool));
-              svn_pool_destroy(subpool);
-              return SVN_NO_ERROR;
-            }
-
-          /* If scheduling changes were made, we have a special routine to
-             manage those modifications. */
-          SVN_ERR(fold_scheduling(&skip_schedule_change,
-                                  &new_schedule,
-                                  parent_entry,
-                                  cur_entry,
-                                  entry_mods->schedule,
-                                  name));
-
-          if (skip_schedule_change)
-            modify_flags &= ~SVN_WC__ENTRY_MODIFY_SCHEDULE;
-        }
-    }
-
-  /* Yay! Our "modify" function can actually "create". Bleah.  */
-  if (cur_entry == NULL)
-    cur_entry = alloc_entry(subpool);
-
-  /* Fold in the changes, and write them out.  */
-  if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE)
-    cur_entry->schedule = new_schedule;
-  SVN_ERR(fold_entry(cur_entry, name, modify_flags, entry_mods, parent_entry,
-                     subpool));
-
-  err = write_one_entry(db, adm_abspath,
-                        parent_entry,
-                        cur_entry,
-                        subpool);
-
-  svn_pool_destroy(subpool); /* Close wc.db handles */
-
-  return svn_error_return(err);
-}
-
-
-svn_error_t *
-svn_wc__entry_modify(svn_wc__db_t *db,
-                     const char *local_abspath,
-                     svn_node_kind_t kind,
-                     const svn_wc_entry_t *entry,
-                     int modify_flags,
-                     apr_pool_t *scratch_pool)
-{
-  return svn_error_return(entry_modify(db, local_abspath, kind, FALSE,
-                                       entry, modify_flags, scratch_pool));
-}
-
-
-svn_error_t *
-svn_wc__entry_modify_stub(svn_wc__db_t *db,
-                          const char *local_abspath,
-                          const svn_wc_entry_t *entry,
-                          int modify_flags,
-                          apr_pool_t *scratch_pool)
-{
-  SVN_ERR_ASSERT((modify_flags & ~(
-                    /* from adm_ops.c  */
-                    SVN_WC__ENTRY_MODIFY_SCHEDULE
-                    | SVN_WC__ENTRY_MODIFY_KIND
-                    | SVN_WC__ENTRY_MODIFY_REVISION
-                    | SVN_WC__ENTRY_MODIFY_COPYFROM_URL
-                    | SVN_WC__ENTRY_MODIFY_COPYFROM_REV
-                    | SVN_WC__ENTRY_MODIFY_COPIED
-                    | SVN_WC__ENTRY_MODIFY_CHECKSUM
-                                   )) == 0);
-  return svn_error_return(entry_modify(db, local_abspath,
-                                       svn_node_dir, TRUE,
-                                       entry, modify_flags, scratch_pool));
-}
-
 
 svn_wc_entry_t *
 svn_wc_entry_dup(const svn_wc_entry_t *entry, apr_pool_t *pool)
@@ -3282,7 +2663,7 @@ svn_wc_walk_entries3(const char *path,
         }
 
       SVN_ERR(svn_wc__get_entry(&entry, db, local_abspath, FALSE,
-                                svn_node_file, FALSE, pool, pool));
+                                svn_node_file, pool, pool));
 
       err = walk_callbacks->found_entry(path, entry, walk_baton, pool);
       if (err)
@@ -3302,52 +2683,3 @@ svn_wc_walk_entries3(const char *path,
                                svn_dirent_local_style(local_abspath, pool)),
        walk_baton, pool);
 }
-
-svn_error_t *
-svn_wc__temp_mark_missing_not_present(const char *local_abspath,
-                                      svn_wc_context_t *wc_ctx,
-                                      apr_pool_t *scratch_pool)
-{
-  svn_wc__db_status_t status;
-  svn_wc__db_kind_t kind;
-  const char *repos_relpath, *repos_root_url, *repos_uuid;
-  svn_revnum_t revision;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision, &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,
-                               wc_ctx->db, local_abspath,
-                               scratch_pool, scratch_pool));
-  if (kind == svn_wc__db_kind_dir
-      && status == svn_wc__db_status_obstructed_delete)
-    {
-      if (!repos_relpath)
-        SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
-                                           &repos_uuid,
-                                           wc_ctx->db, local_abspath,
-                                           scratch_pool, scratch_pool));
-
-      SVN_ERR(svn_wc__db_temp_op_remove_entry(wc_ctx->db, local_abspath,
-                                              scratch_pool));
-
-      if (!SVN_IS_VALID_REVNUM(revision))
-        revision = 0; /* Just make one up */
-
-      SVN_ERR(svn_wc__db_base_add_absent_node(wc_ctx->db, local_abspath,
-                                              repos_relpath, repos_root_url,
-                                              repos_uuid, revision,
-                                              svn_wc__db_kind_dir,
-                                              svn_wc__db_status_not_present,
-                                              NULL, NULL, scratch_pool));
-
-      return SVN_NO_ERROR;
-    }
-
-  return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
-                           _("Unexpectedly found '%s': "
-                             "path is marked 'missing'"),
-                           svn_dirent_local_style(local_abspath, scratch_pool));
-}

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h Wed Sep 15 19:32:26 2010
@@ -37,66 +37,6 @@
 extern "C" {
 #endif /* __cplusplus */
 
-/* The MODIFY_FLAGS that tell svn_wc__entry_modify which parameters to
-   pay attention to.  ### These should track the changes made to the
-   SVN_WC__ENTRY_ATTR_* #defines! */
-#define SVN_WC__ENTRY_MODIFY_REVISION           0x00000001
-#define SVN_WC__ENTRY_MODIFY_URL                0x00000002
-#define SVN_WC__ENTRY_MODIFY_KIND               0x00000004
-/* ### gap  */
-#define SVN_WC__ENTRY_MODIFY_CHECKSUM           0x00000010
-#define SVN_WC__ENTRY_MODIFY_SCHEDULE           0x00000020
-#define SVN_WC__ENTRY_MODIFY_COPIED             0x00000040
-#define SVN_WC__ENTRY_MODIFY_DELETED            0x00000080
-#define SVN_WC__ENTRY_MODIFY_COPYFROM_URL       0x00000100
-#define SVN_WC__ENTRY_MODIFY_COPYFROM_REV       0x00000200
-/* ### gap  */
-
-/* ...ORed together with this to mean: just set the schedule to the new
-   value, instead of treating the new value as a change of state to be
-   merged with the current schedule. */
-#define SVN_WC__ENTRY_MODIFY_FORCE              0x00020000
-
-
-/* Modify the entry for LOCAL_ABSPATH in DB by folding in
-   ("merging") changes, and sync those changes to disk.  New values
-   for the entry are pulled from their respective fields in ENTRY, and
-   MODIFY_FLAGS is a bitmask to specify which of those fields to pay
-   attention to, formed from the values SVN_WC__ENTRY_MODIFY_....
-
-   ### Old doc: "ADM_ACCESS must hold a write lock."
-
-   If LOCAL_ABSPATH specifies a directory, its full entry will be modified.
-   To modify its "parent stub" entry, use svn_wc__entry_modify_stub().
-
-   "Folding in" a change means, in most cases, simply replacing the field
-   with the new value. However, for the "schedule" field, unless
-   MODIFY_FLAGS includes SVN_WC__ENTRY_MODIFY_FORCE (in which case just take
-   the new schedule from ENTRY), it means to determine the schedule that the
-   entry should end up with if the "schedule" value from ENTRY represents a
-   change/add/delete/replace being made to the
-     ### base / working / base and working version(s) ?
-   of the node.
-
-   Perform all allocations in SCRATCH_POOL.
-*/
-svn_error_t *
-svn_wc__entry_modify(svn_wc__db_t *db,
-                     const char *local_abspath,
-                     svn_node_kind_t kind,
-                     const svn_wc_entry_t *entry,
-                     int modify_flags,
-                     apr_pool_t *scratch_pool);
-
-
-/* Like svn_wc__entry_modify(), but modifies the "parent stub".  */
-svn_error_t *
-svn_wc__entry_modify_stub(svn_wc__db_t *db,
-                          const char *local_abspath,
-                          const svn_wc_entry_t *entry,
-                          int modify_flags,
-                          apr_pool_t *scratch_pool);
-
 /** Get an ENTRY for the given LOCAL_ABSPATH.
  *
  * This API does not require an access baton, just a wc_db handle (DB).
@@ -112,19 +52,9 @@ svn_wc__entry_modify_stub(svn_wc__db_t *
  * If you specify FILE/DIR, and the entry is *something else*, then
  * SVN_ERR_NODE_UNEXPECTED_KIND will be returned.
  *
- * For directory nodes, sometimes the caller may want the "stub" from the
- * parent directory. This is usually to examine the DELETED flag. When
- * this is desired, pass TRUE for NEED_PARENT_STUB. It is illegal to pass
- * TRUE if KIND == FILE.
- *
  * If KIND == UNKNOWN, and you request the parent stub, and the node turns
  * out to NOT be a directory, then SVN_ERR_NODE_UNEXPECTED_KIND is returned.
  *
- * If KIND == UNKNOWN, and you request the actual file/dir data (by setting
- * NEED_PARENT_STUB to FALSE), and the node turns out to be a DIR (as
- * specified by the parent), but the subdirectory is NOT present (obstructed
- * or missing), then SVN_ERR_NODE_UNEXPECTED_KIND is returned.
- *
  * NOTE: if SVN_ERR_NODE_UNEXPECTED_KIND is returned, then the ENTRY *IS*
  * valid and may be examined. For any other error, ENTRY *IS NOT* valid.
  *
@@ -141,11 +71,9 @@ svn_wc__get_entry(const svn_wc_entry_t *
                   const char *local_abspath,
                   svn_boolean_t allow_unversioned,
                   svn_node_kind_t kind,
-                  svn_boolean_t need_parent_stub,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool);
 
-
 /* Is ENTRY in a 'hidden' state in the sense of the 'show_hidden'
  * switches on svn_wc_entries_read(), svn_wc_walk_entries*(), etc.? */
 svn_error_t *
@@ -166,18 +94,10 @@ svn_wc__write_upgraded_entries(svn_wc__d
                                apr_int64_t repos_id,
                                apr_int64_t wc_id,
                                const char *dir_abspath,
+                               const char *new_root_abspath,
                                apr_hash_t *entries,
                                apr_pool_t *scratch_pool);
 
-
-/* ### return a flag corresponding to the classic "DELETED" concept.  */
-svn_error_t *
-svn_wc__node_is_deleted(svn_boolean_t *deleted,
-                        svn_wc__db_t *db,
-                        const char *local_abspath,
-                        apr_pool_t *scratch_pool);
-
-
 /* Parse a file external specification in the NULL terminated STR and
    place the path in PATH_RESULT, the peg revision in PEG_REV_RESULT
    and revision number in REV_RESULT.  STR may be NULL, in which case

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c Wed Sep 15 19:32:26 2010
@@ -35,8 +35,6 @@
 #include "adm_files.h"
 #include "lock.h"
 #include "props.h"
-#include "log.h"
-#include "entries.h"
 #include "wc_db.h"
 
 #include "svn_private_config.h"
@@ -110,6 +108,7 @@ svn_error_t *
 svn_wc__internal_check_wc(int *wc_format,
                           svn_wc__db_t *db,
                           const char *local_abspath,
+                          svn_boolean_t check_path,
                           apr_pool_t *scratch_pool)
 {
   svn_error_t *err;
@@ -144,6 +143,64 @@ svn_wc__internal_check_wc(int *wc_format
         }
     }
 
+    if (*wc_format >= SVN_WC__WC_NG_VERSION)
+      {
+        svn_wc__db_status_t db_status;
+        svn_wc__db_kind_t db_kind;
+
+        if (check_path)
+          {
+            /* If a node is not a directory, it is not a working copy
+               directory.  This allows creating new working copies as
+               a path below an existing working copy. */
+            svn_node_kind_t wc_kind;
+
+            SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool));
+            if (wc_kind != svn_node_dir)
+              {
+                *wc_format = 0; /* Not a directory, so not a wc-directory */
+                return SVN_NO_ERROR;
+              }
+          }
+      
+        err = svn_wc__db_read_info(&db_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,
+                                   scratch_pool, scratch_pool);
+      
+        if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+          {
+            svn_error_clear(err);
+            *wc_format = 0;
+            return SVN_NO_ERROR; 
+          }
+        else
+          SVN_ERR(err);
+
+        if (db_kind != svn_wc__db_kind_dir)
+          {
+            /* The WC thinks there must be a file, so this is not
+               a wc-directory */
+            *wc_format = 0;
+            return SVN_NO_ERROR;
+          }
+
+        switch (db_status)
+          {
+            case svn_wc__db_status_not_present:
+            case svn_wc__db_status_absent:
+            case svn_wc__db_status_excluded:
+              /* If there is a directory here, it is not related to the parent
+                 working copy: Obstruction */
+              *wc_format = 0;
+              return SVN_NO_ERROR;
+            default:
+              break;
+          }
+      }
+
   return SVN_NO_ERROR;
 }
 
@@ -152,10 +209,13 @@ svn_error_t *
 svn_wc_check_wc2(int *wc_format,
                  svn_wc_context_t *wc_ctx,
                  const char *local_abspath,
-                 apr_pool_t *pool)
+                 apr_pool_t *scratch_pool)
 {
+  /* ### Should we pass TRUE for check_path to find obstructions and
+         missing directories? */
   return svn_error_return(
-    svn_wc__internal_check_wc(wc_format, wc_ctx->db, local_abspath, pool));
+    svn_wc__internal_check_wc(wc_format, wc_ctx->db, local_abspath, FALSE,
+                              scratch_pool));
 }
 
 
@@ -205,7 +265,7 @@ pool_cleanup_locked(void *p)
             {
               /* There is no remaining work, so we're good to remove any
                  potential "physical" lock.  */
-              err = svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool);
+              err = svn_wc__db_wclock_release(db, lock->abspath, scratch_pool);
             }
         }
       svn_error_clear(err);
@@ -310,8 +370,22 @@ adm_access_alloc(svn_wc_adm_access_t **a
 
   if (write_lock)
     {
-      SVN_ERR(svn_wc__db_wclock_set(db, lock->abspath, 0, scratch_pool));
-      SVN_ERR(svn_wc__db_temp_mark_locked(db, lock->abspath, scratch_pool));
+      svn_boolean_t owns_lock;
+
+      /* If the db already owns a lock, we can't add an extra lock record */
+      SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, path, FALSE,
+                                          scratch_pool));
+
+      /* If DB owns the lock, but when there is no access baton open for this
+         directory, old access baton based code is trying to access data that
+         was previously locked by new code. Just hand them the lock, or
+         important code paths like svn_wc_add3() will start failing */
+      if (!owns_lock
+          || svn_wc__adm_retrieve_internal2(db, lock->abspath, scratch_pool))
+        {
+          SVN_ERR(svn_wc__db_wclock_obtain(db, lock->abspath, 0, FALSE,
+                                           scratch_pool));
+        }
     }
 
   err = add_to_shared(lock, scratch_pool);
@@ -319,7 +393,7 @@ adm_access_alloc(svn_wc_adm_access_t **a
   if (err)
     return svn_error_compose_create(
                 err,
-                svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool));
+                svn_wc__db_wclock_release(db, lock->abspath, scratch_pool));
 
   /* ### does this utf8 thing really/still apply??  */
   /* It's important that the cleanup handler is registered *after* at least
@@ -409,7 +483,8 @@ probe(svn_wc__db_t *db,
       const char *local_abspath;
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-      SVN_ERR(svn_wc__internal_check_wc(&wc_format, db, local_abspath, pool));
+      SVN_ERR(svn_wc__internal_check_wc(&wc_format, db, local_abspath,
+                                        FALSE, pool));
     }
 
   /* a "version" of 0 means a non-wc directory */
@@ -456,7 +531,8 @@ open_single(svn_wc_adm_access_t **adm_ac
   svn_wc_adm_access_t *lock;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
-  err = svn_wc__internal_check_wc(&wc_format, db, local_abspath, scratch_pool);
+  err = svn_wc__internal_check_wc(&wc_format, db, local_abspath, FALSE,
+                                  scratch_pool);
   if (wc_format == 0 || (err && APR_STATUS_IS_ENOENT(err->apr_err)))
     {
       return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, err,
@@ -503,8 +579,9 @@ close_single(svn_wc_adm_access_t *adm_ac
     return SVN_NO_ERROR;
 
   /* Physically unlock if required */
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked, adm_access->db,
-                                   adm_access->abspath, scratch_pool));
+  SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+                                      adm_access->abspath, TRUE,
+                                      scratch_pool));
   if (locked)
     {
       if (!preserve_lock)
@@ -515,9 +592,9 @@ close_single(svn_wc_adm_access_t *adm_ac
              from the working copy.  It is an error for the lock to
              have disappeared if the administrative area still exists. */
 
-          svn_error_t *err = svn_wc__db_wclock_remove(adm_access->db,
-                                                      adm_access->abspath,
-                                                      scratch_pool);
+          svn_error_t *err = svn_wc__db_wclock_release(adm_access->db,
+                                                       adm_access->abspath,
+                                                       scratch_pool);
           if (err)
             {
               if (svn_wc__adm_area_exists(adm_access->abspath, scratch_pool))
@@ -549,38 +626,38 @@ close_single(svn_wc_adm_access_t *adm_ac
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_wc__adm_available(svn_boolean_t *available,
-                      svn_wc__db_kind_t *kind,
-                      svn_boolean_t *obstructed,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      apr_pool_t *scratch_pool)
+/* Retrieves the KIND of LOCAL_ABSPATH and whether its administrative data is
+   available in the working copy.
+
+   *AVAILABLE is set to TRUE when the node and its metadata are available,
+   otherwise to FALSE (due to obstruction, missing, absence, exclusion,
+   or a "not-present" child).
+
+   KIND can be NULL.
+
+   ### note: this function should go away when we move to a single
+   ### adminstrative area.  */
+static svn_error_t *
+adm_available(svn_boolean_t *available,
+              svn_wc__db_kind_t *kind,
+              svn_wc__db_t *db,
+              const char *local_abspath,
+              apr_pool_t *scratch_pool)
 {
   svn_wc__db_status_t status;
-  svn_depth_t depth;
 
   if (kind)
     *kind = svn_wc__db_kind_unknown;
 
   SVN_ERR(svn_wc__db_read_info(&status, kind, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, &depth, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL,
                                db, local_abspath, scratch_pool, scratch_pool));
 
-  if (obstructed)
-    *obstructed = (status == svn_wc__db_status_obstructed ||
-                   status == svn_wc__db_status_obstructed_add ||
-                   status == svn_wc__db_status_obstructed_delete);
-
-  *available = !(status == svn_wc__db_status_obstructed ||
-                 status == svn_wc__db_status_obstructed_add ||
-                 status == svn_wc__db_status_obstructed_delete ||
-                 status == svn_wc__db_status_absent ||
-                 status == svn_wc__db_status_excluded ||
-                 status == svn_wc__db_status_not_present ||
-                 depth == svn_depth_exclude);
+  *available = !(status == svn_wc__db_status_absent
+                 || status == svn_wc__db_status_excluded
+                 || status == svn_wc__db_status_not_present);
 
   return SVN_NO_ERROR;
 }
@@ -629,7 +706,7 @@ do_open(svn_wc_adm_access_t **adm_access
         {
           const char *node_abspath;
           svn_wc__db_kind_t kind;
-          svn_boolean_t available, obstructed;
+          svn_boolean_t available;
           const char *name = APR_ARRAY_IDX(children, i, const char *);
 
           svn_pool_clear(iterpool);
@@ -640,12 +717,11 @@ do_open(svn_wc_adm_access_t **adm_access
 
           node_abspath = svn_dirent_join(local_abspath, name, iterpool);
 
-          SVN_ERR(svn_wc__adm_available(&available,
-                                        &kind,
-                                        &obstructed,
-                                        db,
-                                        node_abspath,
-                                        scratch_pool));
+          SVN_ERR(adm_available(&available,
+                                &kind,
+                                db,
+                                node_abspath,
+                                scratch_pool));
 
           if (kind != svn_wc__db_kind_dir)
             continue;
@@ -662,12 +738,6 @@ do_open(svn_wc_adm_access_t **adm_access
               /* node_access has been registered in DB, so we don't need
                  to do anything with it.  */
             }
-          else if (obstructed)
-            {
-              svn_wc__db_temp_set_access(lock->db, node_abspath,
-                                         (svn_wc_adm_access_t *)&missing,
-                                         iterpool);
-            }
         }
     }
   svn_pool_destroy(iterpool);
@@ -1038,43 +1108,15 @@ child_is_disjoint(svn_boolean_t *disjoin
   const char *node_repos_root, *node_repos_relpath, *node_repos_uuid;
   const char *parent_repos_root, *parent_repos_relpath, *parent_repos_uuid;
   svn_wc__db_status_t parent_status;
-  const apr_array_header_t *children;
   const char *parent_abspath, *base;
-  svn_error_t *err;
-  svn_boolean_t found_in_parent = FALSE;
-  int i;
-
-  svn_dirent_split(local_abspath, &parent_abspath, &base, scratch_pool);
 
   /* Check if the parent directory knows about this node */
-  err = svn_wc__db_read_children(&children, db, parent_abspath, scratch_pool,
-                                 scratch_pool);
-
-  if (err && err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
-    {
-      svn_error_clear(err);
-      *disjoint = TRUE;
-      return SVN_NO_ERROR;
-    }
-  else
-    SVN_ERR(err);
+  SVN_ERR(svn_wc__db_is_wcroot(disjoint, db, local_abspath, scratch_pool));
 
-  for (i = 0; i < children->nelts; i++)
-    {
-      const char *name = APR_ARRAY_IDX(children, i, const char *);
+  if (*disjoint)
+    return SVN_NO_ERROR;
 
-      if (strcmp(name, base) == 0)
-        {
-          found_in_parent = TRUE;
-          break;
-        }
-    }
-
-  if (!found_in_parent)
-    {
-      *disjoint = TRUE;
-      return SVN_NO_ERROR;
-    }
+  svn_dirent_split(&parent_abspath, &base, local_abspath, scratch_pool);
 
   SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, &node_repos_relpath,
                                &node_repos_root, &node_repos_uuid, NULL, NULL,
@@ -1083,8 +1125,8 @@ child_is_disjoint(svn_boolean_t *disjoin
                                db, local_abspath,
                                scratch_pool, scratch_pool));
 
-  /* If the node does not have its own relpath, its value is inherited
-     which tells us that it is not disjoint. */
+  /* If the node does not have its own repos_relpath, its value is inherited
+     from a parent node, which implies that the node is not disjoint. */
   if (node_repos_relpath == NULL)
     {
       *disjoint = FALSE;
@@ -1283,11 +1325,10 @@ open_anchor(svn_wc_adm_access_t **anchor
 
       if (! t_access)
         {
-          svn_boolean_t available, obstructed;
+          svn_boolean_t available;
           svn_wc__db_kind_t kind;
 
-          err = svn_wc__adm_available(&available, &kind, &obstructed,
-                                      db, local_abspath, pool);
+          err = adm_available(&available, &kind, db, local_abspath, pool);
 
           if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
             svn_error_clear(err);
@@ -1296,13 +1337,6 @@ open_anchor(svn_wc_adm_access_t **anchor
               svn_error_clear(svn_wc_adm_close2(p_access, pool));
               return svn_error_return(err);
             }
-          if (obstructed && kind == svn_wc__db_kind_dir)
-            {
-              /* Child PATH is missing.  */
-              svn_wc__db_temp_set_access(db, local_abspath,
-                                         (svn_wc_adm_access_t *)&missing,
-                                         pool);
-            }
         }
 
       *anchor_access = p_access ? p_access : t_access;
@@ -1406,9 +1440,9 @@ svn_wc_adm_locked(const svn_wc_adm_acces
 {
   svn_boolean_t locked;
   apr_pool_t *subpool = svn_pool_create(adm_access->pool);
-  svn_error_t *err = svn_wc__db_temp_own_lock(&locked, adm_access->db,
-                                              adm_access->abspath,
-                                              subpool);
+  svn_error_t *err = svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+                                                 adm_access->abspath, TRUE,
+                                                 subpool);
   svn_pool_destroy(subpool);
 
   if (err)
@@ -1428,7 +1462,8 @@ svn_wc__write_check(svn_wc__db_t *db,
 {
   svn_boolean_t locked;
 
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked, db, local_abspath, scratch_pool));
+  SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, db, local_abspath, FALSE,
+                                      scratch_pool));
   if (!locked)
     return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
                              _("No write-lock in '%s'"),
@@ -1448,8 +1483,8 @@ svn_wc_locked2(svn_boolean_t *locked_her
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   if (locked_here != NULL)
-    SVN_ERR(svn_wc__db_temp_own_lock(locked_here, wc_ctx->db, local_abspath,
-                                     scratch_pool));
+    SVN_ERR(svn_wc__db_wclock_owns_lock(locked_here, wc_ctx->db, local_abspath,
+                                        FALSE, scratch_pool));
   if (locked != NULL)
     SVN_ERR(svn_wc__db_wclocked(locked, wc_ctx->db, local_abspath,
                                 scratch_pool));
@@ -1509,60 +1544,36 @@ svn_wc__adm_get_db(const svn_wc_adm_acce
   return adm_access->db;
 }
 
-
-svn_boolean_t
-svn_wc__adm_missing(svn_wc__db_t *db,
-                    const char *local_abspath,
-                    apr_pool_t *scratch_pool)
-{
-  const svn_wc_adm_access_t *look;
-  svn_boolean_t available, obstructed;
-  svn_wc__db_kind_t kind;
-
-  look = get_from_shared(local_abspath, db, scratch_pool);
-
-  if (look != NULL)
-    return IS_MISSING(look);
-
-  /* When we switch to a single database an access baton can't be
-     missing, but until then it can. But if there are no access batons we
-     would always return FALSE.
-     For this case we check if an access baton could be opened
-
-*/
-
-  /* This check must match the check in do_open() */
-  svn_error_clear(svn_wc__adm_available(&available, &kind, &obstructed,
-                                        db, local_abspath,
-                                        scratch_pool));
-
-  return (kind == svn_wc__db_kind_dir) && !available && obstructed;
-}
-
-
 svn_error_t *
-svn_wc__acquire_write_lock(const char **anchor_abspath,
+svn_wc__acquire_write_lock(const char **lock_root_abspath,
                            svn_wc_context_t *wc_ctx,
                            const char *local_abspath,
+                           svn_boolean_t lock_anchor,
                            apr_pool_t *result_pool,
                            apr_pool_t *scratch_pool)
 {
+  svn_wc__db_t *db = wc_ctx->db;
   svn_wc__db_kind_t kind;
-  apr_pool_t *iterpool;
-  const apr_array_header_t *children;
-  int format, i;
   svn_error_t *err;
-
-  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
+  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath,
+                               (lock_root_abspath != NULL),
                                scratch_pool));
 
-  if (anchor_abspath)
+  if (!lock_root_abspath && kind != svn_wc__db_kind_dir)
+    return svn_error_createf(SVN_ERR_WC_NOT_DIRECTORY, NULL,
+                             _("Can't obtain lock on non-directory '%s'."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+
+  if (lock_anchor)
     {
       const char *parent_abspath;
       svn_wc__db_kind_t parent_kind;
 
+      SVN_ERR_ASSERT(lock_root_abspath != NULL);
+
       parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-      err = svn_wc__db_read_kind(&parent_kind, wc_ctx->db, parent_abspath, TRUE,
+      err = svn_wc__db_read_kind(&parent_kind, db, parent_abspath, TRUE,
                                  scratch_pool);
       if (err && SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
         {
@@ -1587,67 +1598,31 @@ svn_wc__acquire_write_lock(const char **
                                  _("'%s' is not a working copy"),
                                  svn_dirent_local_style(local_abspath,
                                                         scratch_pool));
-
-      *anchor_abspath = apr_pstrdup(result_pool, local_abspath);
     }
   else if (kind != svn_wc__db_kind_dir)
-    local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
-  SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
-                                   scratch_pool, scratch_pool));
-
-  /* The current lock paradigm is that each directory holds a lock for itself,
-     and there are no inherited locks.  In the eventual wc-ng paradigm, a
-     lock on a directory, would imply a infinite-depth lock on the children.
-     But since we aren't quite there yet, we do the infinite locking
-     manually (and be sure to release them in svn_wc__release_write_lock(). */
-
-  iterpool = svn_pool_create(scratch_pool);
-  for (i = 0; i < children->nelts; i ++)
     {
-      const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-
-      svn_pool_clear(iterpool);
-      child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
+      local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
-      SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
-                                   iterpool));
-      if (kind == svn_wc__db_kind_dir)
+      /* Can't lock parents that don't exist */
+      if (kind == svn_wc__db_kind_unknown)
         {
-          err = svn_wc__acquire_write_lock(NULL, wc_ctx, child_abspath, NULL,
-                                           iterpool);
-          if (err && err->apr_err == SVN_ERR_WC_LOCKED)
-            {
-              while(i >= 0)
-                {
-                  svn_error_t *err2;
-                  svn_pool_clear(iterpool);
-                  child_relpath = APR_ARRAY_IDX(children, i, const char *);
-                  child_abspath = svn_dirent_join(local_abspath, child_relpath,
-                                                  iterpool);
-                   err2 = svn_wc__release_write_lock(wc_ctx, child_abspath,
-                                                     iterpool);
-                   if (err2)
-                     svn_error_compose(err, err2);
-                   --i;
-                }
-              return svn_error_return(err);
-            }
+          SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE,
+                                       scratch_pool));
+
+          if (kind != svn_wc__db_kind_dir)
+            return svn_error_createf(
+                             SVN_ERR_WC_NOT_DIRECTORY, NULL,
+                             _("Can't obtain lock on non-directory '%s'."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
         }
     }
 
-  /* We don't want to try and lock an unversioned directory that
-     obstructs a versioned directory. */
-  err = svn_wc__internal_check_wc(&format, wc_ctx->db, local_abspath, iterpool);
-  if (!err && format)
-    {
-      SVN_ERR(svn_wc__db_wclock_set(wc_ctx->db, local_abspath, 0, iterpool));
-      SVN_ERR(svn_wc__db_temp_mark_locked(wc_ctx->db, local_abspath, iterpool));
-    }
-  svn_error_clear(err);
+  if (lock_root_abspath)
+    *lock_root_abspath = apr_pstrdup(result_pool, local_abspath);
 
-  svn_pool_destroy(iterpool);
+  SVN_ERR(svn_wc__db_wclock_obtain(wc_ctx->db, local_abspath, -1, FALSE,
+                                   scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1658,18 +1633,8 @@ svn_wc__release_write_lock(svn_wc_contex
                            const char *local_abspath,
                            apr_pool_t *scratch_pool)
 {
-  svn_wc__db_kind_t kind;
-  apr_pool_t *iterpool;
-  const apr_array_header_t *children;
   apr_uint64_t id;
   svn_skel_t *work_item;
-  svn_boolean_t locked_here;
-  int i;
-
-  SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
-                               scratch_pool));
-  if (kind != svn_wc__db_kind_dir)
-    local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
   SVN_ERR(svn_wc__db_wq_fetch(&id, &work_item, wc_ctx->db, local_abspath,
                               scratch_pool, scratch_pool));
@@ -1679,33 +1644,7 @@ svn_wc__release_write_lock(svn_wc_contex
       return SVN_NO_ERROR;
     }
 
-  /* We need to recursively remove locks (see comment in
-     svn_wc__acquire_write_lock(). */
-
-  iterpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
-                                   scratch_pool, iterpool));
-  for (i = 0; i < children->nelts; i ++)
-    {
-      const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
-      const char *child_abspath;
-
-      svn_pool_clear(iterpool);
-      child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
-
-      SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
-                                   iterpool));
-      if (kind == svn_wc__db_kind_dir)
-        SVN_ERR(svn_wc__release_write_lock(wc_ctx, child_abspath, iterpool));
-    }
-
-  SVN_ERR(svn_wc__db_temp_own_lock(&locked_here, wc_ctx->db, local_abspath,
-                                   iterpool));
-  if (locked_here)
-    SVN_ERR(svn_wc__db_wclock_remove(wc_ctx->db, local_abspath, iterpool));
-
-  svn_pool_destroy(iterpool);
+  SVN_ERR(svn_wc__db_wclock_release(wc_ctx->db, local_abspath, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1715,14 +1654,16 @@ svn_wc__call_with_write_lock(svn_wc__wit
                              void *baton,
                              svn_wc_context_t *wc_ctx,
                              const char *local_abspath,
+                             svn_boolean_t lock_anchor,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
   svn_error_t *err1, *err2;
-  SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath,
-                                     scratch_pool, scratch_pool));
-  err1 = func(baton, result_pool, scratch_pool);
-  err2 = svn_wc__release_write_lock(wc_ctx, local_abspath, scratch_pool);
+  const char *lock_root_abspath;
+  SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, wc_ctx, local_abspath,
+                                     lock_anchor, scratch_pool, scratch_pool));
+  err1 = svn_error_return(func(baton, result_pool, scratch_pool));
+  err2 = svn_wc__release_write_lock(wc_ctx, lock_root_abspath, scratch_pool);
   return svn_error_compose_create(err1, err2);
 }
 

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h Wed Sep 15 19:32:26 2010
@@ -49,39 +49,6 @@ void svn_wc__adm_access_set_entries(svn_
    be NULL.  */
 apr_hash_t *svn_wc__adm_access_entries(svn_wc_adm_access_t *adm_access);
 
-
-/* Returns TRUE if LOCAL_ABSPATH is a working copy directory that is obstructed
-   or missing such that an access baton is not available for LOCAL_ABSPATH.
-   This means DB must also include the parent of LOCAL_ABSPATH.
-
-   This function falls back to using svn_wc__adm_available() if no access batons
-   for LOCAL_ABSPATH are stored in DB. */
-svn_boolean_t svn_wc__adm_missing(svn_wc__db_t *db,
-                                  const char *local_abspath,
-                                  apr_pool_t *scratch_pool);
-
-/* Retrieves the KIND of LOCAL_ABSPATH and whether its administrative data is
-   available in the working copy.
-
-   *AVAILABLE is set to TRUE when the node and its metadata are available,
-   otherwise to FALSE (due to obstruction, missing, absence, exclusion,
-   or a "not-present" child).
-
-   *OBSTRUCTED is set to TRUE when the node is not available because
-   it is obstructed/missing, otherwise to FALSE.
-
-   KIND and OBSTRUCTED can be NULL.
-
-   ### note: this function should go away when we move to a single
-   ### adminstrative area.  */
-svn_error_t *
-svn_wc__adm_available(svn_boolean_t *available,
-                      svn_wc__db_kind_t *kind,
-                      svn_boolean_t *obstructed,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      apr_pool_t *scratch_pool);
-
 /* Same as svn_wc__adm_retrieve_internal, but takes a DB and an absolute
    directory path.  */
 svn_wc_adm_access_t *
@@ -91,21 +58,16 @@ svn_wc__adm_retrieve_internal2(svn_wc__d
 
 /* ### this is probably bunk. but I dunna want to trace backwards-compat
    ### users of svn_wc_check_wc(). probably gonna be rewritten for wc-ng
-   ### in any case.  */
+   ### in any case.
+   
+   If CHECK_PATH is TRUE, a not-existing directory is not a working copy */
 svn_error_t *
 svn_wc__internal_check_wc(int *wc_format,
                           svn_wc__db_t *db,
                           const char *local_abspath,
+                          svn_boolean_t check_path,
                           apr_pool_t *scratch_pool);
 
-
-/* Ensure LOCAL_ABSPATH is still locked in DB.  Returns the error
- * SVN_ERR_WC_NOT_LOCKED if this is not the case.
- */
-svn_error_t *svn_wc__write_check(svn_wc__db_t *db,
-                                 const char *local_abspath,
-                                 apr_pool_t *scratch_pool);
-
 /* Return the working copy database associated with this access baton. */
 svn_wc__db_t *
 svn_wc__adm_get_db(const svn_wc_adm_access_t *adm_access);