You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2011/05/05 14:05:26 UTC

svn commit: r1099764 - in /subversion/trunk/subversion/libsvn_wc: copy.c wc_db.c

Author: rhuijben
Date: Thu May  5 12:05:26 2011
New Revision: 1099764

URL: http://svn.apache.org/viewvc?rev=1099764&view=rev
Log:
Make sure the wc.db database is still consistent after the copy operation
performed in copy_tests.py 98.

This patch removes the addition of several unnecessary nodes records when
processing the copies of deleted nodes.

Before this patch, you could find incomplete nodes for nodes that were in
different layers themselves and not-present nodes with children in the
database.

* subversion/libsvn_wc/copy.c
  (copy_deleted_node): New function.
  (copy_versioned_dir): Handle nodes that exist in the working copy in a
    different way than nodes that don't.

    Only remove nodes that have a representation in the working copy from the
    disk_children hash. This fixes the copying of --keep-local deletes.

* subversion/libsvn_wc/wc_db.c
  (db_op_copy): Don't add incomplete children for not-present and/or
    excluded nodes.
  (op_depth_for_copy): Just use the presence value to allow checking for
    the different kinds of deletes. Assert that we are adding a copy below
    a node that actually exists.

Modified:
    subversion/trunk/subversion/libsvn_wc/copy.c
    subversion/trunk/subversion/libsvn_wc/wc_db.c

Modified: subversion/trunk/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/copy.c?rev=1099764&r1=1099763&r2=1099764&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Thu May  5 12:05:26 2011
@@ -190,6 +190,30 @@ copy_pristine_text_if_necessary(svn_wc__
   return SVN_NO_ERROR;
 }
 
+/* Copy the versioned node SRC_ABSPATH in DB to the path DST_ABSPATH in DB.
+
+   This is a specific variant of copy_versioned_file and copy_versioned_dir
+   specifically handling deleted nodes.
+ */
+static svn_error_t *
+copy_deleted_node(svn_wc__db_t *db,
+                  const char *src_abspath,
+                  const char *dst_abspath,
+                  const char *dst_op_root_abspath,
+                  svn_cancel_func_t cancel_func,
+                  void *cancel_baton,
+                  svn_wc_notify_func2_t notify_func,
+                  void *notify_baton,
+                  apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_wc__db_op_copy(db, src_abspath, dst_abspath, dst_op_root_abspath,
+                             NULL, scratch_pool));
+
+  /* Don't recurse on children while all we do is creating not-present
+     children */
+
+  return SVN_NO_ERROR;
+}
 
 /* Copy the versioned file SRC_ABSPATH in DB to the path DST_ABSPATH in DB.
    If METADATA_ONLY is true, copy only the versioned metadata,
@@ -378,7 +402,9 @@ copy_versioned_dir(svn_wc__db_t *db,
   for (i = 0; i < versioned_children->nelts; ++i)
     {
       const char *child_name, *child_src_abspath, *child_dst_abspath;
+      svn_wc__db_status_t child_status;
       svn_wc__db_kind_t child_kind;
+      svn_boolean_t op_root;
 
       svn_pool_clear(iterpool);
       if (cancel_func)
@@ -388,32 +414,61 @@ copy_versioned_dir(svn_wc__db_t *db,
       child_src_abspath = svn_dirent_join(src_abspath, child_name, iterpool);
       child_dst_abspath = svn_dirent_join(dst_abspath, child_name, iterpool);
 
-      SVN_ERR(svn_wc__db_read_kind(&child_kind, db, child_src_abspath,
-                                   TRUE, iterpool));
-
-      if (child_kind == svn_wc__db_kind_file)
-        SVN_ERR(copy_versioned_file(db,
+      SVN_ERR(svn_wc__db_read_info(&child_status, &child_kind, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, &op_root, NULL, NULL,
+                                   NULL, NULL, NULL,
+                                   db, child_src_abspath,
+                                   iterpool, iterpool));
+
+      if (child_status == svn_wc__db_status_normal
+          || child_status == svn_wc__db_status_added
+          || child_status == svn_wc__db_status_incomplete)
+        {
+          if (child_kind == svn_wc__db_kind_file)
+            SVN_ERR(copy_versioned_file(db,
+                                        child_src_abspath, child_dst_abspath,
+                                        dst_op_root_abspath,
+                                        metadata_only,
+                                        cancel_func, cancel_baton, NULL, NULL,
+                                        iterpool));
+          else if (child_kind == svn_wc__db_kind_dir)
+            SVN_ERR(copy_versioned_dir(db,
+                                       child_src_abspath, child_dst_abspath,
+                                       dst_op_root_abspath,
+                                       metadata_only,
+                                       cancel_func, cancel_baton, NULL, NULL,
+                                       iterpool));
+          else
+            return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                                     _("cannot handle node kind for '%s'"),
+                                     svn_dirent_local_style(child_src_abspath,
+                                                            scratch_pool));
+        }
+      else if (child_status == svn_wc__db_status_deleted
+               || child_status == svn_wc__db_status_not_present
+               || child_status == svn_wc__db_status_excluded)
+        {
+          SVN_ERR(copy_deleted_node(db,
                                     child_src_abspath, child_dst_abspath,
                                     dst_op_root_abspath,
-                                    metadata_only,
                                     cancel_func, cancel_baton, NULL, NULL,
                                     iterpool));
-      else if (child_kind == svn_wc__db_kind_dir)
-        SVN_ERR(copy_versioned_dir(db,
-                                   child_src_abspath, child_dst_abspath,
-                                   dst_op_root_abspath,
-                                   metadata_only,
-                                   cancel_func, cancel_baton, NULL, NULL,
-                                   iterpool));
+        }
       else
-        return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
-                                 _("cannot handle node kind for '%s'"),
-                                 svn_dirent_local_style(child_src_abspath,
-                                                        scratch_pool));
+        {
+          /* Absent nodes should have been handled before we reach this */
+           SVN_ERR_MALFUNCTION(); 
+        }
 
-      if (disk_children)
-        /* Remove versioned child as it has been handled */
-        apr_hash_set(disk_children, child_name, APR_HASH_KEY_STRING, NULL);
+      if (disk_children
+          && (child_status == svn_wc__db_status_normal
+              || child_status == svn_wc__db_status_added))
+        {
+          /* Remove versioned child as it has been handled */
+          apr_hash_set(disk_children, child_name, APR_HASH_KEY_STRING, NULL);
+        }
     }
 
   /* Copy all the remaining filesystem children, which are unversioned. */

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1099764&r1=1099763&r2=1099764&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu May  5 12:05:26 2011
@@ -2692,7 +2692,8 @@ db_op_copy(svn_wc__db_wcroot_t *src_wcro
          The children are part of the same op and so have the same op_depth.
          (The only time we'd want a different depth is during a recursive
          simple add, but we never insert children here during a simple add.) */
-      if (kind == svn_wc__db_kind_dir)
+      if (kind == svn_wc__db_kind_dir
+          && dst_status == svn_wc__db_status_normal)
         SVN_ERR(insert_incomplete_children(
                   dst_wcroot->sdb,
                   dst_wcroot->wc_id,
@@ -2905,12 +2906,8 @@ op_depth_for_copy(apr_int64_t *op_depth,
   if (have_row)
     {
       apr_int64_t parent_op_depth = svn_sqlite__column_int64(stmt, 0);
-      svn_wc__db_status_t status = svn_sqlite__column_token(stmt, 1,
-                                                            presence_map);
-
-      svn_error_t *err = convert_to_working_status(&status, status);
-      if (err)
-        SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+      svn_wc__db_status_t presence = svn_sqlite__column_token(stmt, 1,
+                                                              presence_map);
 
       if (parent_op_depth < min_op_depth)
         {
@@ -2918,9 +2915,13 @@ op_depth_for_copy(apr_int64_t *op_depth,
           return SVN_NO_ERROR;
         }
 
-      if (status == svn_wc__db_status_added
-          && ((incomplete_op_depth < 0)
-              || (incomplete_op_depth == parent_op_depth)))
+      /* You can only add children below a node that exists.
+         In WORKING that must be status added, which is represented
+         as presence normal */
+      SVN_ERR_ASSERT(presence == svn_wc__db_status_normal);
+
+      if ((incomplete_op_depth < 0)
+          || (incomplete_op_depth == parent_op_depth))
         {
           apr_int64_t parent_copyfrom_repos_id
             = svn_sqlite__column_int64(stmt, 10);