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 2010/08/09 19:42:35 UTC

svn commit: r983747 - in /subversion/trunk/subversion/libsvn_wc: workqueue.c workqueue.h

Author: rhuijben
Date: Mon Aug  9 17:42:35 2010
New Revision: 983747

URL: http://svn.apache.org/viewvc?rev=983747&view=rev
Log:
Following up on r983665, implement the intended behavior of the
OP_REMOVE_BASE workqueue item.

* subversion/libsvn_wc/workqueue.c
  (basic_delete_entry): Rename to ...
  (remove_base_node): ... this and update implementation to keep
    WORKING_NODE instances even though the BASE_NODE nodes are
    removed.
  (run_base_remove): Update caller.

* subversion/libsvn_wc/workqueue.h
  (svn_wc__wq_build_base_remove): Update documentation.

Modified:
    subversion/trunk/subversion/libsvn_wc/workqueue.c
    subversion/trunk/subversion/libsvn_wc/workqueue.h

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=983747&r1=983746&r2=983747&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Mon Aug  9 17:42:35 2010
@@ -641,84 +641,126 @@ svn_wc__wq_add_killme(svn_wc__db_t *db,
 /* ------------------------------------------------------------------------ */
 /* OP_REMOVE_BASE  */
 
-/* Ben sez:  this log command is (at the moment) only executed by the
-   update editor.  It attempts to forcefully remove working data. */
-/* Delete a node from version control, and from disk if unmodified.
- * LOCAL_ABSPATH is the name of the file or directory to be deleted.
- * If it is unversioned,
- * do nothing and return no error. Otherwise, delete its WC entry and, if
- * the working version is unmodified, delete it from disk. */
+/* 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 *
-basic_delete_entry(svn_wc__db_t *db,
-                   const char *local_abspath,
-                   apr_pool_t *scratch_pool)
+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_kind_t kind;
-  svn_boolean_t hidden;
-  svn_error_t *err;
+  svn_wc__db_status_t base_status, wrk_status;
+  svn_wc__db_kind_t base_kind, wrk_kind;
+  svn_boolean_t have_base, have_work;
+
+  if (cancel_func)
+    SVN_ERR(cancel_func(cancel_baton));
+
+  SVN_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, &have_base,
+                               &have_work, NULL, NULL,
+                               db, local_abspath, scratch_pool, scratch_pool));
 
-  /* Figure out if 'name' is a dir or a file */
-  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool));
-  if (kind == svn_wc__db_kind_unknown)
-    return SVN_NO_ERROR; /* Already gone */
+#ifndef SVN_WC__SINGLE_DB
+  if (!have_base)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                             _("Node '%s' not found."),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+#else
+  SVN_ERR_ASSERT(have_base); /* Verified in caller and _base_get_children() */
+#endif
 
-  SVN_ERR(svn_wc__db_node_hidden(&hidden, db, local_abspath, scratch_pool));
-  if (hidden)
-    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_absent)
+    {
+      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));
 
-  /* Remove the object from revision control -- whether it's a
-     single file or recursive directory removal.  Attempt
-     to destroy all working files & dirs too.
-
-     ### We pass NULL, NULL for cancel_func and cancel_baton below.
-     ### If they were available, it would be nice to use them. */
-  if (kind == svn_wc__db_kind_dir)
-    {
-      svn_wc__db_status_t status;
-
-      SVN_ERR(svn_wc__db_read_info(&status, NULL, 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 (status == svn_wc__db_status_obstructed ||
-          status == svn_wc__db_status_obstructed_add ||
-          status == svn_wc__db_status_obstructed_delete)
+  /* Children first */
+  if (base_kind == svn_wc__db_kind_dir
+      && base_status == svn_wc__db_status_normal)
+    {
+      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++)
         {
-          /* Removing a missing wcroot is easy, just remove its parent entry
-             ### BH: I can't tell why we don't use this for adds.
-                     We might want to remove WC obstructions?
-
-             We don't have a missing status in the final version of WC-NG,
-             so why bother researching its history.
-          */
-          if (status != svn_wc__db_status_obstructed_add)
-            {
-              SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath,
-                                                      scratch_pool));
+          const char *child_name = APR_ARRAY_IDX(children, i, const char *);
+          const char *child_abspath;
 
-              return SVN_NO_ERROR;
-            }
+          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);
     }
 
-  err = svn_wc__internal_remove_from_revision_control(db,
-                                                      local_abspath,
-                                                      TRUE, /* destroy */
-                                                      FALSE, /* instant_error*/
-                                                      NULL, NULL,
-                                                      scratch_pool);
+  if (base_status == svn_wc__db_status_normal
+      && wrk_status != svn_wc__db_status_added
+      && wrk_status != svn_wc__db_status_obstructed_add
+      && wrk_status != svn_wc__db_status_excluded)
+    {
+#ifndef SVN_WC__SINGLE_DB
+      if (base_kind == svn_wc__db_kind_dir)
+        SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
+                                    scratch_pool));
+#endif
+
+      if (base_kind == svn_wc__db_kind_file
+          || base_kind == svn_wc__db_kind_symlink)
+        SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
+      else
+        {
+          svn_error_t *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);
+        }
 
-  if (err && err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)
+      /* This should remove just BASE and ACTUAL, but for now also remove
+         not existing WORKING_NODE data. */
+      SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath, scratch_pool));
+    }
+  else if (wrk_status == svn_wc__db_status_added
+           || wrk_status == svn_wc__db_status_obstructed_add
+           || (have_work && wrk_status == svn_wc__db_status_excluded))
+    /* ### deletes of working additions should fall in this case, but
+       ### we can't express these without the 4th tree */
     {
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
+      /* Just remove the BASE_NODE data */
+      SVN_ERR(svn_wc__db_base_remove(db, local_abspath, scratch_pool));
     }
   else
-    {
-      return svn_error_return(err);
-    }
+    SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath, scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 /* Process the OP_REMOVE_BASE work item WORK_ITEM.
@@ -771,7 +813,9 @@ run_base_remove(svn_wc__db_t *db,
 #endif
     }
 
-  SVN_ERR(basic_delete_entry(db, local_abspath, scratch_pool));
+  SVN_ERR(remove_base_node(db, local_abspath,
+                           cancel_func, cancel_baton,
+                           scratch_pool));
 
   if (keep_not_present)
     {

Modified: subversion/trunk/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.h?rev=983747&r1=983746&r2=983747&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.h Mon Aug  9 17:42:35 2010
@@ -200,10 +200,10 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
    the BASE_NODE of LOCAL_ABSPATH and all it's descendants, but keeping
    any WORKING_NODE data.
 
-   ### This is only used from update_editor.c's do_entry_deletion() and
-   ### the current implementation doesn't check if it removes more than
-   ### just this documented behavior. (It is just a copy of the old loggy
-   ### code)
+   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,