subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1357558 - in /subversion/trunk/subversion: libsvn_wc/externals.c libsvn_wc/update_editor.c libsvn_wc/wc-queries.sql libsvn_wc/wc_db.c libsvn_wc/wc_db.h libsvn_wc/workqueue.c libsvn_wc/workqueue.h tests/libsvn_wc/op-depth-test.c
Date Thu, 05 Jul 2012 11:30:38 GMT
Author: rhuijben
Date: Thu Jul  5 11:30:37 2012
New Revision: 1357558

URL: http://svn.apache.org/viewvc?rev=1357558&view=rev
Log:
Transform the base-remove workqueue operation into an atomic wc_db operation
that dynamically creates multiple workqueue operations that transform the
local working copy later.

This removes the last place in the workqueue that may change the NODE
presence/status during its operations. (Except for legacy and upgrade).

This patch removes several ugly corner cases around actual only nodes in
the original implementation of the db function.

* subversion/libsvn_wc/externals.c
  (svn_wc__external_remove): Update caller. Run workqueue instead of manually
    removing a file.

* subversion/libsvn_wc/update_editor.c
  (delete_entry): Handle all changes via a single call to
    svn_wc__db_base_remove, instead of applying multiple small operations.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_BASE_PRESENT,
   STMT_DELETE_ACTUAL_FOR_BASE_RECURSIVE,
   STMT_DELETE_WORKING_BASE_DELETE,
   STMT_DELETE_WORKING_RECURSIVE,
   STMT_DELETE_BASE_RECURSIVE): New queries.

* subversion/libsvn_wc/wc_db.c
  (base_get_info): Add prototype.
  (base_remove_baton): Add new arguments.
  (db_base_remove): Implement as recursive operation via several new Sqlite
    statements.
  (svn_wc__db_base_remove): Pass arguments via baton.
  (svn_wc__db_base_remove): Update caller.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_base_remove): Update prototype and documentation.

* subversion/libsvn_wc/workqueue.c
  (names): Add OP_DIRECTORY_REMOVE. Sort legacy items at the bottom.

  (remove_base_node): Remove function.
  (run_base_remove): Just call svn_wc__db_base_remove.
  (svn_wc__wq_build_base_remove): Remove function.

  (run_dir_remove,
   svn_wc__wq_build_dir_remove): New function.

   (dispatch_table): Add OP_DIRECTORY_REMOVE. Sort legacy items at the bottom.

* subversion/libsvn_wc/workqueue.h
  (svn_wc__wq_build_dir_remove): New function.
  (svn_wc__wq_build_base_remove): Remove function.

* subversion/tests/libsvn_wc/op-depth-test.c
  (includes): Add workqueue.h.
  (base_dir_insert_remove): Run workqueue to avoid an error on closing
    the db.

Modified:
    subversion/trunk/subversion/libsvn_wc/externals.c
    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/libsvn_wc/wc_db.h
    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/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/externals.c?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/externals.c (original)
+++ subversion/trunk/subversion/libsvn_wc/externals.c Thu Jul  5 11:30:37 2012
@@ -1310,8 +1310,12 @@ svn_wc__external_remove(svn_wc_context_t
                                                  scratch_pool));
   else
     {
-      SVN_ERR(svn_wc__db_base_remove(wc_ctx->db, local_abspath, scratch_pool));
-      SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
+      SVN_ERR(svn_wc__db_base_remove(wc_ctx->db, local_abspath,
+                                     FALSE, SVN_INVALID_REVNUM,
+                                     NULL, NULL, scratch_pool));
+      SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath,
+                             cancel_func, cancel_baton,
+                             scratch_pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Thu Jul  5 11:30:37 2012
@@ -1701,11 +1701,11 @@ delete_entry(const char *path,
   svn_boolean_t have_base;
   svn_boolean_t have_work;
   svn_skel_t *tree_conflict = NULL;
-  svn_skel_t *work_item = NULL;
   svn_wc__db_status_t status;
   svn_wc__db_status_t base_status;
   apr_pool_t *scratch_pool;
   svn_boolean_t deleting_target;
+  svn_boolean_t keep_as_working = FALSE;
 
   if (pb->skip_this)
     return SVN_NO_ERROR;
@@ -1785,7 +1785,10 @@ delete_entry(const char *path,
       || base_status == svn_wc__db_status_excluded
       || base_status == svn_wc__db_status_server_excluded)
     {
-      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath, scratch_pool));
+      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
+                                     FALSE, SVN_INVALID_REVNUM,
+                                     NULL, NULL,
+                                     scratch_pool));
 
       if (deleting_target)
         eb->target_deleted = TRUE;
@@ -1843,8 +1846,7 @@ delete_entry(const char *path,
            * To prepare the "accept mine" resolution for the tree conflict,
            * we must schedule the existing content for re-addition as a copy
            * of what it was, but with its local modifications preserved. */
-          SVN_ERR(svn_wc__db_temp_op_make_copy(eb->db, local_abspath,
-                                               scratch_pool));
+          keep_as_working = TRUE;
 
           /* Fall through to remove the BASE_NODEs properly, with potentially
              keeping a not-present marker */
@@ -1892,33 +1894,21 @@ delete_entry(const char *path,
   if (! deleting_target)
     {
       /* Delete, and do not leave a not-present node.  */
-      SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath,
-                                           SVN_INVALID_REVNUM,
-                                           svn_kind_unknown,
-                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
+                                     keep_as_working, SVN_INVALID_REVNUM,
+                                     tree_conflict, NULL,
+                                     scratch_pool));
     }
   else
     {
       /* Delete, leaving a not-present node.  */
-      SVN_ERR(svn_wc__wq_build_base_remove(&work_item,
-                                           eb->db, local_abspath,
-                                           *eb->target_revision,
-                                           base_kind,
-                                           scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_base_remove(eb->db, local_abspath,
+                                     keep_as_working, *eb->target_revision,
+                                     tree_conflict, NULL,
+                                     scratch_pool));
       eb->target_deleted = TRUE;
     }
 
-  if (tree_conflict)
-  {
-    SVN_ERR(svn_wc__db_op_mark_conflict(eb->db, local_abspath,
-                                        tree_conflict, work_item,
-                                        scratch_pool));
-  }
-  else
-    SVN_ERR(svn_wc__db_wq_add(eb->db, pb->local_abspath, work_item,
-                              scratch_pool));
-
   SVN_ERR(svn_wc__wq_run(eb->db, pb->local_abspath,
                          eb->cancel_func, eb->cancel_baton,
                          scratch_pool));
@@ -4756,7 +4746,8 @@ close_edit(void *edit_baton,
                  If so, we should get rid of this excluded node now. */
 
               SVN_ERR(svn_wc__db_base_remove(eb->db, eb->target_abspath,
-                                             scratch_pool));
+                                             FALSE, SVN_INVALID_REVNUM,
+                                             NULL, NULL, scratch_pool));
             }
         }
     }

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu Jul  5 11:30:37 2012
@@ -153,6 +153,51 @@ INSERT OR REPLACE INTO nodes (
 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
         ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22)
 
+-- STMT_SELECT_BASE_PRESENT
+SELECT local_relpath, kind FROM nodes n
+WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = 0
+  AND presence in ('normal', 'incomplete')
+  AND NOT EXISTS(SELECT 1 FROM NODES w
+                 WHERE w.wc_id = ?1 AND w.local_relpath = n.local_relpath
+                   AND op_depth > 0)
+ORDER BY local_relpath DESC
+
+-- STMT_DELETE_ACTUAL_FOR_BASE_RECURSIVE
+/* The ACTUAL_NODE applies to BASE, unless there is in at least one op_depth
+   a WORKING node that could have a conflict */
+DELETE FROM actual_node
+WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND EXISTS(SELECT 1 FROM NODES b
+             WHERE b.wc_id = ?1
+               AND b.local_relpath = actual_node.local_relpath
+               AND op_depth = 0)
+  AND NOT EXISTS(SELECT 1 FROM NODES w
+                 WHERE w.wc_id = ?1
+                   AND w.local_relpath = actual_node.local_relpath
+                   AND op_depth > 0
+                   AND presence in ('normal', 'incomplete', 'not-present'))
+
+-- STMT_DELETE_WORKING_BASE_DELETE
+DELETE FROM nodes
+WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND presence = 'base-deleted'
+  AND op_depth > 0
+  AND op_depth = (SELECT MIN(op_depth) FROM nodes n
+                    WHERE n.wc_id = ?1
+                      AND n.local_relpath = nodes.local_relpath
+                      AND op_depth > 0)
+
+-- STMT_DELETE_WORKING_RECURSIVE
+DELETE FROM nodes
+WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth > 0
+
+-- STMT_DELETE_BASE_RECURSIVE
+DELETE FROM nodes
+WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+  AND op_depth = 0
+
 -- STMT_SELECT_OP_DEPTH_CHILDREN
 SELECT local_relpath FROM nodes
 WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = ?3

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Jul  5 11:30:37 2012
@@ -336,6 +336,26 @@ db_read_pristine_props(apr_hash_t **prop
                        apr_pool_t *scratch_pool);
 
 static svn_error_t *
+base_get_info(svn_wc__db_status_t *status,
+              svn_kind_t *kind,
+              svn_revnum_t *revision,
+              const char **repos_relpath,
+              apr_int64_t *repos_id,
+              svn_revnum_t *changed_rev,
+              apr_time_t *changed_date,
+              const char **changed_author,
+              svn_depth_t *depth,
+              const svn_checksum_t **checksum,
+              const char **target,
+              svn_wc__db_lock_t **lock,
+              svn_boolean_t *had_props,
+              svn_boolean_t *update_root,
+              svn_wc__db_wcroot_t *wcroot,
+              const char *local_relpath,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool);
+
+static svn_error_t *
 read_info(svn_wc__db_status_t *status,
           svn_kind_t *kind,
           svn_revnum_t *revision,
@@ -1958,7 +1978,11 @@ svn_wc__db_base_add_not_present_node(svn
 /* Baton for db_base_remove */
 struct base_remove_baton
 {
-  svn_wc__db_t *db;
+  svn_wc__db_t *db; /* For checking conflicts */
+  svn_boolean_t keep_as_working;
+  svn_revnum_t not_present_revision;
+  svn_skel_t *conflict;
+  svn_skel_t *work_items;
 };
 
 /* This implements svn_wc__db_txn_callback_t */
@@ -1970,76 +1994,193 @@ db_base_remove(void *baton,
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
-#if SVN_WC__VERSION >= SVN_WC__USES_CONFLICT_SKELS
   struct base_remove_baton *rb = baton;
-#endif
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_DELETE_BASE_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step_done(stmt));
+  svn_wc__db_status_t status;
+  apr_int64_t repos_id;
+  const char *repos_relpath;
+  svn_kind_t kind;
+  svn_boolean_t keep_working;
 
-  SVN_ERR(retract_parent_delete(wcroot, local_relpath, scratch_pool));
+  SVN_ERR(base_get_info(&status, &kind, NULL, &repos_relpath, &repos_id,
+                        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                        NULL,
+                        wcroot, local_relpath,
+                        scratch_pool, scratch_pool));
 
-  /* If there is no working node then any actual node must be deleted,
-     unless it marks a conflict */
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                    STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-  SVN_ERR(svn_sqlite__reset(stmt));
-  if (!have_row)
+  /* ### This function should be turned into a helper of this function,
+         as this is the only valid caller */
+  if (status == svn_wc__db_status_normal
+      && rb->keep_as_working)
+    {
+      SVN_ERR(svn_wc__db_temp_op_make_copy(rb->db,
+                                           svn_dirent_join(wcroot->abspath,
+                                                           local_relpath,
+                                                           scratch_pool),
+                                           scratch_pool));
+      keep_working = TRUE;
+    }
+  else
     {
+      /* Check if there is already a working node */
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_ACTUAL_NODE));
+                                        STMT_SELECT_WORKING_NODE));
       SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+      SVN_ERR(svn_sqlite__step(&keep_working, stmt));
+      SVN_ERR(svn_sqlite__reset(stmt));
+    }
 
-      if (! have_row)
-        SVN_ERR(svn_sqlite__reset(stmt));
-      else
+  /* Step 1: Create workqueue operations to remove files and dirs in the
+     local-wc */
+  if (!keep_working
+      && (status == svn_wc__db_status_normal
+          || status == svn_wc__db_status_incomplete))
+    {
+      svn_skel_t *work_item;
+      const char *local_abspath;
+
+      local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+                                      scratch_pool);
+      if (kind == svn_kind_dir)
         {
-          svn_boolean_t tree_conflicted;
-#if SVN_WC__VERSION >= SVN_WC__USES_CONFLICT_SKELS
-          apr_size_t conflict_len;
-          const void *conflict_data;
-#endif
+          apr_pool_t *iterpool;
+          SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                            STMT_SELECT_BASE_PRESENT));
+          SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
 
-#if SVN_WC__VERSION < SVN_WC__USES_CONFLICT_SKELS
-          tree_conflicted = !svn_sqlite__column_is_null(stmt, 7);
-#else
-          conflict_data = svn_sqlite__column_blob(stmt, 2, &conflict_len,
-                                                  NULL);
+          iterpool = svn_pool_create(scratch_pool);
 
-          if (! conflict_data)
-            tree_conflicted = FALSE;
-          else
-           {
-             const svn_skel_t *conflicts;
+          SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
-             conflicts = svn_skel__parse(conflict_data, conflict_len,
-                                         scratch_pool);
+          while (have_row)
+            {
+              const char *node_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+              svn_kind_t node_kind = svn_sqlite__column_token(stmt, 1,
+                                                              kind_map);
+              const char *node_abspath;
 
-             SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, NULL, NULL,
-                                                &tree_conflicted,
-                                                rb->db, wcroot->abspath,
-                                                conflicts,
-                                             scratch_pool, scratch_pool));
+              svn_pool_clear(iterpool);
+
+              node_abspath = svn_dirent_join(wcroot->abspath, node_relpath,
+                                             iterpool);
+
+              if (node_kind == svn_kind_dir)
+                SVN_ERR(svn_wc__wq_build_dir_remove(&work_item,
+                                                    rb->db, wcroot->abspath,
+                                                    node_abspath, FALSE,
+                                                    iterpool, iterpool));
+              else
+                SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
+                                                     rb->db,
+                                                     /* wcroot->abspath, */
+                                                     node_abspath,
+                                                     iterpool, iterpool));
+
+              SVN_ERR(add_work_items(wcroot->sdb, work_item, iterpool));
+
+              SVN_ERR(svn_sqlite__step(&have_row, stmt));
            }
-#endif
+
           SVN_ERR(svn_sqlite__reset(stmt));
 
-          if (! tree_conflicted)
-            {
-              SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                                STMT_DELETE_ACTUAL_NODE));
-              SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
-                                        local_relpath));
-              SVN_ERR(svn_sqlite__step_done(stmt));
-            }
+          SVN_ERR(svn_wc__wq_build_dir_remove(&work_item,
+                                              rb->db, wcroot->abspath,
+                                              local_abspath, FALSE,
+                                              scratch_pool, iterpool));
+          svn_pool_destroy(iterpool);
         }
+      else
+        SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
+                                             rb->db, /* wcroot->abspath, */
+                                             local_abspath,
+                                             scratch_pool, scratch_pool));
+
+      SVN_ERR(add_work_items(wcroot->sdb, work_item, scratch_pool));
+    }
+
+  /* Step 2: Delete ACTUAL nodes */
+  if (! keep_working)
+    {
+      /* There won't be a record in NODE left for this node, so we want
+         to remove *all* ACTUAL nodes, including ACTUAL ONLY. */
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_DELETE_ACTUAL_NODE_RECURSIVE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+  else if (! rb->keep_as_working)
+    {
+      /* Delete only the ACTUAL nodes that apply to a delete of a BASE node */
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                       STMT_DELETE_ACTUAL_FOR_BASE_RECURSIVE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+  /* Else: Everything has been turned into a copy, so we want to keep all
+           ACTUAL_NODE records */
+
+  /* Step 3: Delete WORKING nodes */
+  if (keep_working)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_DELETE_WORKING_BASE_DELETE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+  else
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_DELETE_WORKING_RECURSIVE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
     }
 
+  /* Step 4: Delete the BASE node descendants */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_DELETE_BASE_RECURSIVE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  /* Step 5: handle the BASE node itself */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_DELETE_BASE_NODE));
+  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, local_relpath, scratch_pool));
+
+  /* Step 6: Delete actual node if we don't keep working */
+  if (! keep_working)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                        STMT_DELETE_ACTUAL_NODE));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__step_done(stmt));
+    }
+
+  if (SVN_IS_VALID_REVNUM(rb->not_present_revision))
+    {
+      struct insert_base_baton_t ibb;
+      blank_ibb(&ibb);
+
+      ibb.repos_id = repos_id;
+      ibb.status = svn_wc__db_status_not_present;
+      ibb.kind = kind;
+      ibb.repos_relpath = repos_relpath;
+      ibb.revision = rb->not_present_revision;
+
+      /* Depending upon KIND, any of these might get used. */
+      ibb.children = NULL;
+      ibb.depth = svn_depth_unknown;
+      ibb.checksum = NULL;
+      ibb.target = NULL;
+
+      SVN_ERR(insert_base_node(&ibb, wcroot, local_relpath, scratch_pool));
+    }
+
+  SVN_ERR(add_work_items(wcroot->sdb, rb->work_items, scratch_pool));
+  if (rb->conflict)
+    SVN_ERR(mark_conflict(wcroot, local_relpath, rb->conflict, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -2047,12 +2188,15 @@ db_base_remove(void *baton,
 svn_error_t *
 svn_wc__db_base_remove(svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_boolean_t keep_as_working,
+                       svn_revnum_t not_present_revision,
+                       svn_skel_t *conflict,
+                       svn_skel_t *work_items,
                        apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
   struct base_remove_baton rb;
-  rb.db = db;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -2060,6 +2204,12 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
+  rb.db = db;
+  rb.keep_as_working = keep_as_working;
+  rb.not_present_revision = not_present_revision;
+  rb.conflict = conflict;
+  rb.work_items = work_items;
+
   SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_base_remove, &rb,
                               scratch_pool));
 
@@ -9714,6 +9864,11 @@ bump_node_revision(svn_wc__db_wcroot_t *
     {
       struct base_remove_baton rb;
       rb.db = db;
+      rb.keep_as_working = FALSE;
+      rb.not_present_revision = SVN_INVALID_REVNUM;
+      rb.conflict = NULL;
+      rb.work_items = NULL;
+
       return svn_error_trace(db_base_remove(&rb, wcroot, local_relpath,
                                             scratch_pool));
     }

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Jul  5 11:30:37 2012
@@ -636,13 +636,15 @@ svn_wc__db_base_add_not_present_node(svn
                                      apr_pool_t *scratch_pool);
 
 
-/* Remove a node from the BASE tree.
+/* Remove a node and all its descendants from the BASE tree. This handles
+   the deletion of a tree from the update editor and some file external
+   scenarios.
 
    The node to remove is indicated by LOCAL_ABSPATH from the local
    filesystem.
 
-   Note that no changes are made to the local filesystem; LOCAL_ABSPATH
-   is merely the key to figure out which BASE node to remove.
+   This operation *installs* workqueue operations to update the local
+   filesystem after the database operation.
 
    To maintain a consistent database this function will also remove
    any working node that marks LOCAL_ABSPATH as base-deleted.  If this
@@ -650,12 +652,24 @@ svn_wc__db_base_add_not_present_node(svn
    actual node will be removed if the actual node does not mark a
    conflict.
 
-   Note the caller is responsible for removing base node
-   children before calling this function (this may change).
+   If KEEP_AS_WORKING is TRUE, then the base tree is copied to higher
+   layers as a copy of itself before deleting the BASE nodes.
+
+   If NOT_PRESENT_REVISION specifies a valid revision a not-present
+   node is installed in BASE node with kind NOT_PRESENT_KIND after
+   deleting.
+
+   If CONFLICT and/or WORK_ITEMS are passed they are installed as part
+   of the operation, after the work items inserted by the operation
+   itself.
 */
 svn_error_t *
 svn_wc__db_base_remove(svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_boolean_t keep_as_working,
+                       svn_revnum_t not_present_revision,
+                       svn_skel_t *conflict,
+                       svn_skel_t *work_items,
                        apr_pool_t *scratch_pool);
 
 

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Thu Jul  5 11:30:37 2012
@@ -42,7 +42,6 @@
 
 
 /* Workqueue operation names.  */
-#define OP_BASE_REMOVE "base-remove"
 #define OP_FILE_COMMIT "file-commit"
 #define OP_FILE_INSTALL "file-install"
 #define OP_FILE_REMOVE "file-remove"
@@ -50,10 +49,15 @@
 #define OP_FILE_COPY_TRANSLATED "file-translate"
 #define OP_SYNC_FILE_FLAGS "sync-file-flags"
 #define OP_PREJ_INSTALL "prej-install"
+#define OP_DIRECTORY_REMOVE "dir-remove"
+
+#define OP_POSTUPGRADE "postupgrade"
+
+/* Legacy items */
+#define OP_BASE_REMOVE "base-remove"
 #define OP_RECORD_FILEINFO "record-fileinfo"
 #define OP_TMP_SET_TEXT_CONFLICT_MARKERS "tmp-set-text-conflict-markers"
 #define OP_TMP_SET_PROPERTY_CONFLICT_MARKER "tmp-set-property-conflict-marker"
-#define OP_POSTUPGRADE "postupgrade"
 
 /* For work queue debugging. Generates output about its operation.  */
 /* #define SVN_DEBUG_WORK_QUEUE */
@@ -100,110 +104,7 @@ get_and_record_fileinfo(svn_wc__db_t *db
 /* Removes a BASE_NODE and all it's data, leaving any adds and copies as is.
    Do this as a depth first traversal to make sure than any parent still exists
    on error conditions.
-
-   ### This function needs review for 4th tree behavior.*/
-static svn_error_t *
-remove_base_node(svn_wc__db_t *db,
-                 const char *local_abspath,
-                 svn_cancel_func_t cancel_func,
-                 void *cancel_baton,
-                 apr_pool_t *scratch_pool)
-{
-  svn_wc__db_status_t base_status, wrk_status;
-  svn_kind_t base_kind, wrk_kind;
-  svn_boolean_t have_base, have_work;
-  svn_error_t *err;
-
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  err = svn_wc__db_read_info(&wrk_status, &wrk_kind, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL,
-                             &have_base, NULL, &have_work,
-                             db, local_abspath, scratch_pool, scratch_pool);
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-    {
-      /* No node to delete, this can happen when the wq item is rerun. */
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
-    }
-
-  if(! have_base)
-    /* No base node to delete, this can happen when the wq item is rerun. */
-    return SVN_NO_ERROR;
-
-  if (wrk_status == svn_wc__db_status_normal
-      || wrk_status == svn_wc__db_status_not_present
-      || wrk_status == svn_wc__db_status_server_excluded)
-    {
-      base_status = wrk_status;
-      base_kind = wrk_kind;
-    }
-  else
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL, NULL,
-                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, NULL, NULL,
-                                     db, local_abspath,
-                                     scratch_pool, scratch_pool));
-
-  /* Children first */
-  if (base_kind == svn_kind_dir
-      && (base_status == svn_wc__db_status_normal
-          || base_status == svn_wc__db_status_incomplete))
-    {
-      const apr_array_header_t *children;
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      int i;
-
-      SVN_ERR(svn_wc__db_base_get_children(&children, db, local_abspath,
-                                           scratch_pool, iterpool));
-
-      for (i = 0; i < children->nelts; i++)
-        {
-          const char *child_name = APR_ARRAY_IDX(children, i, const char *);
-          const char *child_abspath;
-
-          svn_pool_clear(iterpool);
-
-          child_abspath = svn_dirent_join(local_abspath, child_name, iterpool);
-
-          SVN_ERR(remove_base_node(db, child_abspath, cancel_func, cancel_baton,
-                                   iterpool));
-        }
-
-      svn_pool_destroy(iterpool);
-    }
-
-  if (base_status == svn_wc__db_status_normal
-      && wrk_status != svn_wc__db_status_added
-      && wrk_status != svn_wc__db_status_excluded)
-    {
-      if (wrk_status != svn_wc__db_status_deleted
-          && (base_kind == svn_kind_file
-              || base_kind == svn_kind_symlink))
-        {
-          SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
-        }
-      else if (base_kind == svn_kind_dir
-               && wrk_status != svn_wc__db_status_deleted)
-        {
-          err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
-          if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
-                      || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)
-                      || APR_STATUS_IS_ENOTEMPTY(err->apr_err)))
-            svn_error_clear(err);
-          else
-            SVN_ERR(err);
-        }
-    }
-
-  SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
+ */
 
 /* Process the OP_REMOVE_BASE work item WORK_ITEM.
  * See svn_wc__wq_build_remove_base() which generates this work item.
@@ -220,8 +121,6 @@ run_base_remove(svn_wc__db_t *db,
   const char *local_relpath;
   const char *local_abspath;
   svn_revnum_t not_present_rev = SVN_INVALID_REVNUM;
-  svn_kind_t not_present_kind;
-  const char *repos_relpath, *repos_root_url, *repos_uuid;
   apr_int64_t val;
 
   local_relpath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
@@ -234,23 +133,6 @@ run_base_remove(svn_wc__db_t *db,
       not_present_rev = (svn_revnum_t)val;
 
       SVN_ERR(svn_skel__parse_int(&val, arg1->next->next, scratch_pool));
-      not_present_kind = (svn_kind_t)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
     {
@@ -262,9 +144,9 @@ run_base_remove(svn_wc__db_t *db,
 
       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,
+          SVN_ERR(svn_wc__db_base_get_info(NULL, NULL,
+                                           &not_present_rev, NULL,
+                                           NULL, NULL, NULL,
                                            NULL, NULL, NULL, NULL, NULL, NULL,
                                            NULL, NULL,
                                            db, local_abspath,
@@ -272,45 +154,8 @@ run_base_remove(svn_wc__db_t *db,
         }
     }
 
-  SVN_ERR(remove_base_node(db, local_abspath,
-                           cancel_func, cancel_baton,
-                           scratch_pool));
-
-  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,
-                                                   not_present_rev,
-                                                   not_present_kind,
-                                                   NULL,
-                                                   NULL,
-                                                   scratch_pool));
-    }
-
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc__wq_build_base_remove(svn_skel_t **work_item,
-                             svn_wc__db_t *db,
-                             const char *local_abspath,
-                             svn_revnum_t not_present_revision,
-                             svn_kind_t not_present_kind,
-                             apr_pool_t *result_pool,
-                             apr_pool_t *scratch_pool)
-{
-  const char *local_relpath;
-  *work_item = svn_skel__make_empty_list(result_pool);
-
-  SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, local_abspath,
-                                local_abspath, result_pool, scratch_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);
+  SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE, not_present_rev,
+                                 NULL, NULL, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -912,6 +757,87 @@ svn_wc__wq_build_file_remove(svn_skel_t 
 
 /* ------------------------------------------------------------------------ */
 
+/* OP_DIRECTORY_REMOVE  */
+
+/* Process the OP_FILE_REMOVE work item WORK_ITEM.
+ * See svn_wc__wq_build_file_remove() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
+static svn_error_t *
+run_dir_remove(svn_wc__db_t *db,
+               const svn_skel_t *work_item,
+               const char *wri_abspath,
+               svn_cancel_func_t cancel_func,
+               void *cancel_baton,
+               apr_pool_t *scratch_pool)
+{
+  const svn_skel_t *arg1 = work_item->children->next;
+  const char *local_relpath;
+  const char *local_abspath;
+  svn_boolean_t recursive;
+
+  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));
+
+  recursive = FALSE;
+  if (arg1->next)
+    {
+      apr_int64_t val;
+      SVN_ERR(svn_skel__parse_int(&val, arg1->next, scratch_pool));
+
+      recursive = (val != 0);
+    }
+
+  /* Remove the path, no worrying if it isn't there.  */
+  if (recursive)
+    return svn_error_trace(
+                svn_io_remove_dir2(local_abspath, TRUE,
+                                   cancel_func, cancel_baton,
+                                   scratch_pool));
+  else
+    {
+      svn_error_t *err;
+
+      err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+
+      if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
+                  || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)
+                  || APR_STATUS_IS_ENOTEMPTY(err->apr_err)))
+        {
+          svn_error_clear(err);
+          err = NULL;
+        }
+
+      return svn_error_trace(err);
+    }
+}
+
+svn_error_t *
+svn_wc__wq_build_dir_remove(svn_skel_t **work_item,
+                            svn_wc__db_t *db,
+                            const char *wri_abspath,
+                            const char *local_abspath,
+                            svn_boolean_t recursive,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  const char *local_relpath;
+  *work_item = svn_skel__make_empty_list(result_pool);
+
+  SVN_ERR(svn_wc__db_to_relpath(&local_relpath, db, wri_abspath,
+                                local_abspath, result_pool, scratch_pool));
+
+  if (recursive)
+    svn_skel__prepend_int(TRUE, *work_item, result_pool);
+
+  svn_skel__prepend_str(local_relpath, *work_item, result_pool);
+  svn_skel__prepend_str(OP_DIRECTORY_REMOVE, *work_item, result_pool);
+
+  return SVN_NO_ERROR;
+}
+
+/* ------------------------------------------------------------------------ */
+
 /* OP_FILE_MOVE  */
 
 /* Process the OP_FILE_MOVE work item WORK_ITEM.
@@ -1442,14 +1368,17 @@ static const struct work_item_dispatch d
   { OP_FILE_COPY_TRANSLATED, run_file_copy_translated },
   { OP_SYNC_FILE_FLAGS, run_sync_file_flags },
   { OP_PREJ_INSTALL, run_prej_install },
-  { OP_RECORD_FILEINFO, run_record_fileinfo },
-  { OP_BASE_REMOVE, run_base_remove },
-  { OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
-  { OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
+  { OP_DIRECTORY_REMOVE, run_dir_remove },
 
   /* Upgrade steps */
   { OP_POSTUPGRADE, run_postupgrade },
 
+  /* Legacy workqueue items. No longer created */
+  { OP_BASE_REMOVE, run_base_remove },
+  { OP_RECORD_FILEINFO, run_record_fileinfo },
+  { OP_TMP_SET_TEXT_CONFLICT_MARKERS, run_set_text_conflict_markers },
+  { OP_TMP_SET_PROPERTY_CONFLICT_MARKER, run_set_property_conflict_marker },
+
   /* Sentinel.  */
   { NULL }
 };

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.h?rev=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.h Thu Jul  5 11:30:37 2012
@@ -122,6 +122,18 @@ svn_wc__wq_build_file_remove(svn_skel_t 
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
 
+/* Set *WORK_ITEM to a new work item that will remove a single
+   directory or if RECURSIVE is TRUE a directory with all its
+   descendants.  */
+svn_error_t *
+svn_wc__wq_build_dir_remove(svn_skel_t **work_item,
+                            svn_wc__db_t *db,
+                            const char *wri_abspath,
+                            const char *local_abspath,
+                            svn_boolean_t recursive,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
+
 /* Set *WORK_ITEM to a new work item that describes a move of
    a file or directory from SRC_ABSPATH to DST_ABSPATH, ready for
    storing in the working copy managing DST_ABSPATH.
@@ -182,24 +194,6 @@ svn_wc__wq_build_prej_install(svn_skel_t
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
 
-/* Set *WORK_ITEM to a new work item that will remove all the data of
-   the BASE_NODE of LOCAL_ABSPATH and all it's descendants, but keeping
-   any WORKING_NODE data.
-
-   This function doesn't check for local modifications of the text files
-   as these would have triggered a tree conflict before.
-
-   ### This is only used from update_editor.c's do_entry_deletion().
- */
-svn_error_t *
-svn_wc__wq_build_base_remove(svn_skel_t **work_item,
-                             svn_wc__db_t *db,
-                             const char *local_abspath,
-                             svn_revnum_t not_present_revision,
-                             svn_kind_t not_present_kind,
-                             apr_pool_t *result_pool,
-                             apr_pool_t *scratch_pool);
-
 /* Handle the final post-commit step of retranslating and recording the
    working copy state of a committed file.
 

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=1357558&r1=1357557&r2=1357558&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Thu Jul  5 11:30:37 2012
@@ -43,6 +43,7 @@
 #include "private/svn_dep_compat.h"
 #include "../../libsvn_wc/wc.h"
 #include "../../libsvn_wc/wc_db.h"
+#include "../../libsvn_wc/workqueue.h"
 #define SVN_WC__I_AM_WC_DB
 #include "../../libsvn_wc/wc_db_private.h"
 
@@ -1295,7 +1296,11 @@ base_dir_insert_remove(svn_test__sandbox
 
   SVN_ERR(check_db_rows(b, "", after));
 
-  SVN_ERR(svn_wc__db_base_remove(b->wc_ctx->db, dir_abspath, b->pool));
+  SVN_ERR(svn_wc__db_base_remove(b->wc_ctx->db, dir_abspath,
+                                 FALSE, SVN_INVALID_REVNUM,
+                                 NULL, NULL, b->pool));
+  SVN_ERR(svn_wc__wq_run(b->wc_ctx->db, dir_abspath,
+                         NULL, NULL, b->pool));
 
   SVN_ERR(check_db_rows(b, "", before));
 



Mime
View raw message