Author: rhuijben
Date: Thu Apr 21 10:26:51 2011
New Revision: 1095645

URL: http://svn.apache.org/viewvc?rev=1095645&view=rev
Log:
Resolve two issues I found by writing the op-depth test 'test_shadowed_update'
Most importantly stop adding base-deleted nodes above base nodes that don't
describe a present node and start removing the base-deletes for that case.

And when updating a node to a revision in which it does not exist, mark
it as not existing in that revision instead of not-present in its former
revision (where it was present).

* subversion/libsvn_wc/update_editor.c
  (delete_entry): Update caller to pass explicit not-present revision.

* subversion/libsvn_wc/wc_db.c
  (extend_parent_delete,
   retract_parent_delete): Take a svn_wc__db_wcroot_t* argument instead of a
     sqlite database and a working copy id.
  (insert_base_node): Don't extend deletes over not-present nodes, instead
     retract existing deletes.

* subversion/libsvn_wc/workqueue.c
  (run_base_remove): Read the not-present revision and kind from the skel
     instead of determining them locally.
  (svn_wc__wq_build_base_remove): Accept an explicit revision and kind for the
     not present node.
* subversion/libsvn_wc/workqueue.h
  (svn_wc__wq_build_base_remove): Accept an explicit revision and kind for the
     not present node.

* subversion/tests/libsvn_wc/op-depth-test.c
  (test_mixed_rev_copy,
   test_del_replace_not_present): Expect the update target revision on
     not-present nodes.
  (test_shadowed_update): Also verify the same operations on the A-tree.
  (test_funcs): Remove XFail marking.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/workqueue.c
    subversion/trunk/subversion/libsvn_wc/workqueue.h
    subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1095645&r1=1095644&r2=1095645&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Apr 21 10:26:51 
2011
@@ -1572,7 +1572,7 @@ delete_entry(const char *path,
   const char *base = svn_relpath_basename(path, NULL);
   const char *local_abspath;
   const char *repos_relpath;
-  svn_wc__db_kind_t kind;
+  svn_wc__db_kind_t kind, base_kind;
   svn_boolean_t conflicted;
   svn_boolean_t have_base;
   svn_boolean_t have_work;
@@ -1623,9 +1623,13 @@ delete_entry(const char *path,
                                scratch_pool, scratch_pool));
 
   if (!have_work)
-    base_status = status;
+    {
+      base_status = status;
+      base_kind = kind;
+    }
   else
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, &repos_relpath,
+    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL,
+                                     &repos_relpath,
                                      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                      eb->db, local_abspath,
@@ -1740,14 +1744,18 @@ delete_entry(const char *path,
     {
       /* Delete, and do not leave a not-present node.  */
       SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath, FALSE,
+                                           eb->db, local_abspath,
+                                           SVN_INVALID_REVNUM,
+                                           svn_wc__db_kind_unknown,
                                            scratch_pool, scratch_pool));
     }
   else
     {
       /* Delete, leaving a not-present node.  */
       SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath, TRUE,
+                                           eb->db, local_abspath,
+                                           *eb->target_revision,
+                                           base_kind,
                                            scratch_pool, scratch_pool));
       eb->target_deleted = TRUE;
     }

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1095645&r1=1095644&r2=1095645&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Apr 21 10:26:51 2011
@@ -685,8 +685,7 @@ blank_ibb(insert_base_baton_t *pibb)
    the extended delete, A/B/C is already deleted.
  */
 static svn_error_t *
-extend_parent_delete(svn_sqlite__db_t *sdb,
-                     apr_int64_t wc_id,
+extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
                      const char *local_relpath,
                      apr_pool_t *scratch_pool)
 {
@@ -697,9 +696,9 @@ extend_parent_delete(svn_sqlite__db_t *s
 
   SVN_ERR_ASSERT(local_relpath[0]);
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_LOWEST_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, parent_relpath));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (have_row)
     parent_op_depth = svn_sqlite__column_int64(stmt, 0);
@@ -708,16 +707,16 @@ extend_parent_delete(svn_sqlite__db_t *s
     {
       apr_int64_t op_depth;
 
-      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
       if (have_row)
         op_depth = svn_sqlite__column_int64(stmt, 0);
       SVN_ERR(svn_sqlite__reset(stmt));
       if (!have_row || parent_op_depth < op_depth)
         {
-          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+          SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                           STMT_INSERT_WORKING_NODE_FROM_BASE));
-          SVN_ERR(svn_sqlite__bindf(stmt, "isit", wc_id,
+          SVN_ERR(svn_sqlite__bindf(stmt, "isit", wcroot->wc_id,
                                     local_relpath, parent_op_depth,
                                     presence_map,
                                     svn_wc__db_status_base_deleted));
@@ -736,16 +735,15 @@ extend_parent_delete(svn_sqlite__db_t *s
    this node must be removed.
  */
 static svn_error_t *
-retract_parent_delete(svn_sqlite__db_t *sdb,
-                      apr_int64_t wc_id,
+retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
                       const char *local_relpath,
                       apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_DELETE_LOWEST_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
   return SVN_NO_ERROR;
@@ -849,9 +847,22 @@ insert_base_node(void *baton,
                                        0 /* BASE */,
                                        scratch_pool));
 
-  if (parent_relpath)
-    SVN_ERR(extend_parent_delete(wcroot->sdb, wcroot->wc_id, local_relpath,
-                                 scratch_pool));
+  /* When this is not the root node, check shadowing behavior */
+  if (*local_relpath)
+    {
+      if (parent_relpath
+          && (pibb->status == svn_wc__db_status_normal)
+              || (pibb->status == svn_wc__db_status_incomplete))
+        {
+          SVN_ERR(extend_parent_delete(wcroot, local_relpath, scratch_pool));
+        }
+      else if (pibb->status == svn_wc__db_status_not_present
+               || pibb->status == svn_wc__db_status_absent
+               || pibb->status == svn_wc__db_status_excluded)
+        {
+          SVN_ERR(retract_parent_delete(wcroot, local_relpath, scratch_pool));
+        }
+    }
 
   SVN_ERR(add_work_items(wcroot->sdb, pibb->work_items, scratch_pool));
 
@@ -1833,8 +1844,7 @@ db_base_remove(void *baton,
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
   SVN_ERR(svn_sqlite__step_done(stmt));
 
-  SVN_ERR(retract_parent_delete(wcroot->sdb, wcroot->wc_id, local_relpath,
-                                scratch_pool));
+  SVN_ERR(retract_parent_delete(wcroot, local_relpath, scratch_pool));
 
   /* If there is no working node then any actual node must be deleted,
      unless it marks a conflict */

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=1095645&r1=1095644&r2=1095645&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Thu Apr 21 10:26:51 2011
@@ -246,40 +246,70 @@ run_base_remove(svn_wc__db_t *db,
   const svn_skel_t *arg1 = work_item->children->next;
   const char *local_relpath;
   const char *local_abspath;
-  svn_boolean_t keep_not_present;
-  svn_revnum_t revision;
+  svn_revnum_t not_present_rev = SVN_INVALID_REVNUM;
+  svn_wc__db_kind_t not_present_kind;
   const char *repos_relpath, *repos_root_url, *repos_uuid;
-  svn_wc__db_kind_t kind;
   apr_int64_t val;
 
   local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
   SVN_ERR(svn_wc__db_from_relpath(&local_abspath, db, wri_abspath,
                                   local_relpath, scratch_pool, scratch_pool));
   SVN_ERR(svn_skel__parse_int(&val, arg1->next, scratch_pool));
-  keep_not_present = (val != 0);
 
-  if (keep_not_present)
+  if (arg1->next->next)
     {
-      SVN_ERR(svn_wc__db_base_get_info(NULL, &kind, &revision, &repos_relpath,
-                                       &repos_root_url, &repos_uuid, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, local_abspath,
-                                       scratch_pool, scratch_pool));
+      not_present_rev = (svn_revnum_t)val;
+      SVN_ERR(svn_skel__parse_int(&val, arg1->next->next, scratch_pool));
+      not_present_kind = val;
+
+      if (SVN_IS_VALID_REVNUM(not_present_rev))
+        {
+          const char *dir_abspath, *name;
+
+          /* This wq operation is restartable, so we can't assume the node
+             to be here. But we can assume that the parent is still there */
+          svn_dirent_split(&dir_abspath, &name, local_abspath, scratch_pool);
+
+          SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
+                                             &repos_uuid,
+                                             db, dir_abspath,
+                                             scratch_pool, scratch_pool));
+
+          repos_relpath = svn_relpath_join(repos_relpath, name, scratch_pool);
+        }
+    }
+  else
+    {
+      svn_boolean_t keep_not_present;
+
+      SVN_ERR_ASSERT(SVN_WC__VERSION <= 28); /* Case unused in later versions*/
+
+      keep_not_present = (val != 0);
+
+      if (keep_not_present)
+        {
+          SVN_ERR(svn_wc__db_base_get_info(NULL, &not_present_kind,
+                                           &not_present_rev, &repos_relpath,
+                                           &repos_root_url, &repos_uuid, NULL,
+                                           NULL, NULL, NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL,
+                                           db, local_abspath,
+                                           scratch_pool, scratch_pool));
+        }
     }
 
   SVN_ERR(remove_base_node(db, local_abspath,
                            cancel_func, cancel_baton,
                            scratch_pool));
 
-  if (keep_not_present)
+  if (SVN_IS_VALID_REVNUM(not_present_rev))
     {
       SVN_ERR(svn_wc__db_base_add_not_present_node(db, local_abspath,
                                                    repos_relpath,
                                                    repos_root_url,
                                                    repos_uuid,
-                                                   revision,
-                                                   kind,
+                                                   not_present_rev,
+                                                   not_present_kind,
                                                    NULL,
                                                    NULL,
                                                    scratch_pool));
@@ -292,7 +322,8 @@ svn_error_t *
 svn_wc__wq_build_base_remove(svn_skel_t **work_item,
                              svn_wc__db_t *db,
                              const char *local_abspath,
-                             svn_boolean_t keep_not_present,
+                             svn_revnum_t not_present_revision,
+                             svn_wc__db_kind_t not_present_kind,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
 {
@@ -302,7 +333,8 @@ svn_wc__wq_build_base_remove(svn_skel_t 
   SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
                                 local_abspath, result_pool, scratch_pool));
 
-  svn_skel__prepend_int(keep_not_present, *work_item, result_pool);
+  svn_skel__prepend_int(not_present_kind, *work_item, result_pool);
+  svn_skel__prepend_int(not_present_revision, *work_item, result_pool);
   svn_skel__prepend_str(local_relpath, *work_item, result_pool);
   svn_skel__prepend_str(OP_BASE_REMOVE, *work_item, result_pool);
 

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.h?rev=1095645&r1=1095644&r2=1095645&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.h Thu Apr 21 10:26:51 2011
@@ -211,7 +211,8 @@ svn_error_t *
 svn_wc__wq_build_base_remove(svn_skel_t **work_item,
                              svn_wc__db_t *db,
                              const char *local_abspath,
-                             svn_boolean_t keep_not_present,
+                             svn_revnum_t not_present_revision,
+                             svn_wc__db_kind_t not_present_kind,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
 

Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1095645&r1=1095644&r2=1095645&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Thu Apr 21 
10:26:51 2011
@@ -1747,7 +1747,7 @@ test_mixed_rev_copy(const svn_test_opts_
       { 0, "",      "normal",       0, "" },
       { 0, "A",     "normal",       1, "A" },
       { 0, "A/B",   "normal",       2, "A/B" },
-      { 0, "A/B/C", "not-present",  3, "A/B/C" },
+      { 0, "A/B/C", "not-present",  0, "A/B/C" },
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "", rows));
@@ -1759,7 +1759,7 @@ test_mixed_rev_copy(const svn_test_opts_
       { 1, "X",     "normal",       1, "A" },
       { 1, "X/B",   "not-present",  2, "A/B" },
       { 2, "X/B",   "normal",       2, "A/B" },
-      { 2, "X/B/C", "not-present",  3, "A/B/C" },
+      { 2, "X/B/C", "not-present",  0, "A/B/C" },
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "X", rows));
@@ -1866,8 +1866,8 @@ test_del_replace_not_present(const svn_t
     nodes_row_t rows[] = {
       { 0, "A",         "normal",       2, "A" },
       { 0, "A/B",       "normal",       2, "A/B" },
-      { 0, "A/B/X",     "not-present",  2, "A/B/X" },
-      { 0, "A/B/Y",     "not-present",  2, "A/B/Y" },
+      { 0, "A/B/X",     "not-present",  0, "A/B/X" },
+      { 0, "A/B/Y",     "not-present",  0, "A/B/Y" },
       { 0, "A/B/Z",     "normal",       2, "A/B/Z" },
       { 1, "A",         "base-deleted", NO_COPY_FROM },
       { 1, "A/B",       "base-deleted", NO_COPY_FROM },
@@ -1882,15 +1882,15 @@ test_del_replace_not_present(const svn_t
     nodes_row_t rows[] = {
       { 0, "A",         "normal",       2, "A" },
       { 0, "A/B",       "normal",       2, "A/B" },
-      { 0, "A/B/X",     "not-present",  2, "A/B/X" },
-      { 0, "A/B/Y",     "not-present",  2, "A/B/Y" },
+      { 0, "A/B/X",     "not-present",  0, "A/B/X" },
+      { 0, "A/B/Y",     "not-present",  0, "A/B/Y" },
       { 0, "A/B/Z",     "normal",       2, "A/B/Z" },
       { 1, "A",         "normal",       2, "X" },
       { 1, "A/B",       "normal",       2, "X/B" },
-      { 1, "A/B/W",     "not-present",  2, "X/B/W" },
+      { 1, "A/B/W",     "not-present",  0, "X/B/W" },
       { 1, "A/B/X",     "normal",       2, "X/B/X" },
-      { 1, "A/B/Y",     "not-present",  2, "X/B/Y" },
-      { 1, "A/B/Z",     "not-present",  2, "X/B/Z" },
+      { 1, "A/B/Y",     "not-present",  0, "X/B/Y" },
+      { 1, "A/B/Z",     "not-present",  0, "X/B/Z" },
       { 0 }
     };
     SVN_ERR(check_db_rows(&b, "A", rows));
@@ -1901,8 +1901,8 @@ test_del_replace_not_present(const svn_t
     nodes_row_t rows[] = {
       { 0, "A",         "normal",       2, "A" },
       { 0, "A/B",       "normal",       2, "A/B" },
-      { 0, "A/B/X",     "not-present",  2, "A/B/X" },
-      { 0, "A/B/Y",     "not-present",  2, "A/B/Y" },
+      { 0, "A/B/X",     "not-present",  0, "A/B/X" },
+      { 0, "A/B/Y",     "not-present",  0, "A/B/Y" },
       { 0, "A/B/Z",     "normal",       2, "A/B/Z" },
       { 1, "A",         "base-deleted", NO_COPY_FROM },
       { 1, "A/B",       "base-deleted", NO_COPY_FROM },
@@ -3042,6 +3042,16 @@ test_shadowed_update(const svn_test_opts
   SVN_ERR(wc_delete(&b, "K/L/M"));
   {
     nodes_row_t rows[] = {
+      {0, "",        "normal",           3, ""},
+      {0, "iota",    "normal",           3, "iota"},
+
+      {0, "A",       "normal",           3, "A"},
+      {0, "A/B",     "normal",           3, "A/B"},
+      {0, "A/B/C",   "normal",           3, "A/B/C"},
+
+      {1, "A",       "normal",           2, "A"},
+      {1, "A/B",     "normal",           2, "A/B"},
+      {1, "A/B/C",   "normal",           2, "A/B/C"},
 
       {0, "K",       "normal",           3, "K"},
       {0, "K/L",     "normal",           3, "K/L"},
@@ -3055,7 +3065,7 @@ test_shadowed_update(const svn_test_opts
 
       { 0 }
     };
-    SVN_ERR(check_db_rows(&b, "K", rows));
+    SVN_ERR(check_db_rows(&b, "", rows));
   }
 
   /* Resolve conflict on K and go back to r1 */
@@ -3085,13 +3095,26 @@ test_shadowed_update(const svn_test_opts
     SVN_ERR(check_db_rows(&b, "K", rows));
   }
 
-  /* Update the shadowed K/L/M to r4 where it does not exits */
+  /* Update the shadowed K/L/M to r4 where they do not exit */
   SVN_ERR(wc_resolved(&b, "K"));
   SVN_ERR(wc_update(&b, "K/L/M", 4));
+  SVN_ERR(wc_resolved(&b, "A"));
+  SVN_ERR(wc_update(&b, "A/B/C", 4));
 
   {
     nodes_row_t rows[] = {
 
+      {0, "",        "normal",           3, ""},
+      {0, "iota",    "normal",           3, "iota"},
+
+      {0, "A",       "normal",           3, "A"},
+      {0, "A/B",     "normal",           3, "A/B"},
+      {0, "A/B/C",   "not-present",      4, "A/B/C"},
+
+      {1, "A",       "normal",           2, "A"},
+      {1, "A/B",     "normal",           2, "A/B"},
+      {1, "A/B/C",   "normal",           2, "A/B/C"},
+
       {0, "K",       "normal",           3, "K"},
       {0, "K/L",     "normal",           3, "K/L"},
       {0, "K/L/M",   "not-present",      4, "K/L/M"},
@@ -3101,13 +3124,9 @@ test_shadowed_update(const svn_test_opts
 
       {2, "K/L",     "normal",           NO_COPY_FROM},
 
-      /* ### Currently I see an unexpected
-      { 1, "K/L/M",  "base-deleted",     NO_COPY_FROM},
-         ### Which shadows the not-present node */
-
       { 0 }
     };
-    SVN_ERR(check_db_rows(&b, "K", rows));
+    SVN_ERR(check_db_rows(&b, "", rows));
   }
 
 
@@ -3160,7 +3179,7 @@ struct svn_test_descriptor_t test_funcs[
                        "test_op_delete"),
     SVN_TEST_OPTS_PASS(test_child_replace_with_same_origin,
                        "test_child_replace_with_same"),
-    SVN_TEST_OPTS_XFAIL(test_shadowed_update,
+    SVN_TEST_OPTS_PASS(test_shadowed_update,
                        "test_shadowed_update"),
     SVN_TEST_NULL
   };


Reply via email to