You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2010/11/05 13:18:25 UTC

svn commit: r1031532 - in /subversion/trunk/subversion: libsvn_wc/update_editor.c libsvn_wc/wc-queries.sql libsvn_wc/wc_db.c tests/libsvn_wc/op-depth-test.c

Author: philip
Date: Fri Nov  5 12:18:25 2010
New Revision: 1031532

URL: http://svn.apache.org/viewvc?rev=1031532&view=rev
Log:
When adding a base node under a working node ensure that there is a
suitable working node at the correct op_depth to delete the base node.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_LOWEST_WORKING_NODE): New.

* subversion/libsvn_wc/wc_db.c
  (extend_parent_delete): New.
  (insert_base_node, set_new_dir_to_incomplete_txn): Call
   extend_parent_delete to add working node.

* subversion/libsvn_wc/update_editor.c
  (add_directory): Don't explicitly add a working node to mark as deleted,
   explicitly take over a locally added directory.
  (close_file): Don't add working node to mark as deleted.

* subversion/tests/libsvn_wc/op-depth-test.c
  (wc_update): New helper.
  (test_delete_with_update): New test.
  (test_funcs): Mark test_delete_with_update as WIMP.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    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=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Nov  5 12:18:25 2010
@@ -2452,14 +2452,10 @@ add_directory(const char *path,
 
   SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
 
-  /* If PATH is within a locally deleted tree then make it also
-     scheduled for deletion.  We should do this at the same time as
-     setting the dir incomplete otherwise the db is temporarily
-     invalid. */
-  if (pb->in_deleted_and_tree_conflicted_subtree)
-    {
-      SVN_ERR(svn_wc__db_temp_op_delete(eb->db, db->local_abspath, pool));
-    }
+  if (!pb->in_deleted_and_tree_conflicted_subtree
+      && status == svn_wc__db_status_added)
+    /* If there is no conflict we take over any added directory */
+    SVN_ERR(svn_wc__db_temp_op_remove_working(eb->db, db->local_abspath, pool));
 
   /* If this add was obstructed by dir scheduled for addition without
      history let close_file() handle the notification because there
@@ -4527,14 +4523,6 @@ close_file(void *file_baton,
 
   /* Deal with the WORKING tree, based on updates to the BASE tree.  */
 
-  /* An ancestor was locally-deleted. This file is being added within
-     that tree. We need to schedule this file for deletion.  This
-     should happen at the same time as svn_wc__db_base_add_file.  */
-  if (fb->dir_baton->in_deleted_and_tree_conflicted_subtree && fb->adding_file)
-    {
-      SVN_ERR(svn_wc__db_temp_op_delete(eb->db, fb->local_abspath, pool));
-    }
-
   /* If this file was locally-added and is now being added by the update, we
      can toss the local-add, turning this into a local-edit.  */
   if (fb->add_existed && fb->adding_file)

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Nov  5 12:18:25 2010
@@ -72,6 +72,13 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 ORDER BY op_depth DESC
 LIMIT 1;
 
+-- STMT_SELECT_LOWEST_WORKING_NODE
+SELECT op_depth, presence
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0
+ORDER BY op_depth
+LIMIT 1;
+
 -- STMT_SELECT_ACTUAL_NODE
 SELECT prop_reject, changelist, conflict_old, conflict_new,
 conflict_working, tree_conflict_data, properties, conflict_data
@@ -473,7 +480,7 @@ VALUES (?1, ?2, 0,
         ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16);
 
 -- STMT_INSERT_WORKING_NODE_FROM_BASE
-INSERT INTO nodes (
+INSERT OR REPLACE INTO nodes (
     wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
     changed_revision, changed_date, changed_author, depth, symlink_target,
     translated_size, last_mod_time, properties)

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Nov  5 12:18:25 2010
@@ -710,6 +710,84 @@ blank_ibb(insert_base_baton_t *pibb)
 }
 
 
+/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
+
+   Given a wc:
+
+              0         1         2         3         4
+              normal
+   A          normal          
+   A/B        normal              normal
+   A/B/C                          not-pres  normal
+   A/B/C/D                                            normal
+
+   That is checkout, delete A/B, copy a replacement A/B, delete copied
+   child A/B/C, add replacement A/B/C, add A/B/C/D.
+
+   Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
+   must extend the A/B deletion:
+   
+              0         1         2         3         4
+              normal
+   A          normal
+   A/B        normal              normal
+   A/B/C      normal              not-pres  normal
+   A/B/C/D    normal              base-del            normal
+   A/B/C/D/E  normal              base-del
+
+   When adding a base node if the parent has a working node then the
+   parent base is deleted and this must be extended to cover new base
+   node.
+
+   In the example above A/B/C/D and A/B/C/D/E are the nodes that get
+   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,
+                     const char *local_relpath,
+                     apr_pool_t *scratch_pool)
+{
+  svn_boolean_t have_row;
+  svn_sqlite__stmt_t *stmt;
+  apr_int64_t parent_op_depth;
+  const char *parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+  SVN_ERR_ASSERT(local_relpath[0]);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_SELECT_LOWEST_WORKING_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+  if (have_row)
+    {
+      apr_int64_t op_depth;
+
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", 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,
+                                          STMT_INSERT_WORKING_NODE_FROM_BASE));
+          SVN_ERR(svn_sqlite__bindf(stmt, "isit", wc_id,
+                                    local_relpath, parent_op_depth,
+                                    presence_map,
+                                    svn_wc__db_status_base_deleted));
+          SVN_ERR(svn_sqlite__update(NULL, stmt));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+
 /* */
 static svn_error_t *
 insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
@@ -773,6 +851,10 @@ insert_base_node(void *baton, svn_sqlite
                                        0 /* BASE */,
                                        scratch_pool));
 
+  if (parent_relpath)
+    SVN_ERR(extend_parent_delete(sdb, pibb->wc_id, pibb->local_relpath,
+                                 scratch_pool));
+
   SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -9457,14 +9539,6 @@ set_new_dir_to_incomplete_txn(void *bato
   SVN_ERR(create_repos_id(&repos_id, dtb->repos_root_url, dtb->repos_uuid,
                           sdb, scratch_pool));
 
-  /* Delete the base and working node data */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
-                                    STMT_DELETE_NODES));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", dtb->pdh->wcroot->wc_id,
-                            dtb->local_relpath));
-  SVN_ERR(svn_sqlite__step_done(stmt));
-
-  /* Insert the incomplete base node */
   SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
                                     STMT_INSERT_NODE));
 
@@ -9486,6 +9560,10 @@ set_new_dir_to_incomplete_txn(void *bato
 
   SVN_ERR(svn_sqlite__step_done(stmt));
 
+  if (parent_relpath)
+    SVN_ERR(extend_parent_delete(dtb->pdh->wcroot->sdb, dtb->pdh->wcroot->wc_id,
+                                 dtb->local_relpath, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 

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=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Fri Nov  5 12:18:25 2010
@@ -200,6 +200,21 @@ wc_commit(wc_baton_t *b, const char *pat
                             NULL, NULL, NULL, NULL, ctx, b->pool);
 }
 
+static svn_error_t *
+wc_update(wc_baton_t *b, const char *path, svn_revnum_t revnum)
+{
+  svn_client_ctx_t *ctx;
+  apr_array_header_t *result_revs;
+  apr_array_header_t *paths = apr_array_make(b->pool, 1,
+                                             sizeof(const char *));
+  svn_opt_revision_t revision = { svn_opt_revision_number, { revnum } };
+
+  APR_ARRAY_PUSH(paths, const char *) = wc_path(b, path);
+  SVN_ERR(svn_client_create_context(&ctx, b->pool));
+  return svn_client_update3(&result_revs, paths, &revision, svn_depth_infinity,
+                            TRUE, FALSE, FALSE, ctx, b->pool);
+}
+
 /* Create the Greek tree on disk in the WC, and commit it. */
 static svn_error_t *
 add_and_commit_greek_tree(wc_baton_t *b)
@@ -956,6 +971,52 @@ test_repo_wc_copies(const svn_test_opts_
   return repo_wc_copies(&b);
 }
 
+static svn_error_t *
+test_delete_with_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  wc_baton_t b;
+
+  b.pool = pool;
+  SVN_ERR(svn_test__create_repos_and_wc(&b.repos_url, &b.wc_abspath,
+                                        "delete_with_update", opts, pool));
+  SVN_ERR(svn_wc_context_create(&b.wc_ctx, NULL, pool, pool));
+  SVN_ERR(wc_mkdir(&b, "A"));
+  SVN_ERR(wc_commit(&b, ""));
+  SVN_ERR(wc_mkdir(&b, "A/B"));
+  SVN_ERR(wc_mkdir(&b, "A/B/C"));
+  SVN_ERR(wc_commit(&b, ""));
+  SVN_ERR(wc_update(&b, "", 1));
+
+  SVN_ERR(wc_delete(&b, "A"));
+  SVN_ERR(wc_mkdir(&b, "A"));
+  SVN_ERR(wc_mkdir(&b, "A/B"));
+  {
+    nodes_row_t rows[] = {
+      { 0, "A",       "normal",        1, "A"},
+      { 1, "A",       "normal",        NO_COPY_FROM},
+      { 2, "A/B",     "normal",        NO_COPY_FROM},
+      { 0 }
+    };
+    SVN_ERR(check_db_rows(&b, "A", rows));
+  }
+  SVN_ERR(wc_update(&b, "", 2));
+  {
+    nodes_row_t rows[] = {
+      { 0, "A",       "normal",        2, "A"},
+      { 0, "A/B",     "normal",        2, "A/B"},
+      { 0, "A/B/C",   "normal",        2, "A/B/C"},
+      { 1, "A",       "normal",        NO_COPY_FROM},
+      { 1, "A/B",     "base-deleted",  NO_COPY_FROM},
+      { 1, "A/B/C",   "base-deleted",  NO_COPY_FROM},
+      { 2, "A/B",     "normal",        NO_COPY_FROM},
+      { 0 }
+    };
+    SVN_ERR(check_db_rows(&b, "A", rows));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
 
@@ -983,5 +1044,8 @@ struct svn_test_descriptor_t test_funcs[
     SVN_TEST_OPTS_WIMP(test_repo_wc_copies,
                        "test_repo_wc_copies",
                        "needs op_depth"),
+    SVN_TEST_OPTS_WIMP(test_delete_with_update,
+                       "test_test_delete_with_update",
+                       "needs op_depth"),
     SVN_TEST_NULL
   };