You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gs...@apache.org on 2010/04/23 18:30:42 UTC

svn commit: r937358 - in /subversion/trunk/subversion: libsvn_wc/wc_db.c tests/cmdline/schedule_tests.py

Author: gstein
Date: Fri Apr 23 16:30:42 2010
New Revision: 937358

URL: http://svn.apache.org/viewvc?rev=937358&view=rev
Log:
Be wary of obstructions in svn_wc__db_temp_op_delete. There is not enough
information to determine whether the node is an add or a copy/move and
whether this is the root of a copy/move. This information is needed to
properly mark the node for deletion. When the situation is detected, we
now raise SVN_ERR_WC_MISSING. This error will become moot when we reach
single-db mode.

* subversion/libsvn_wc/wc_db.c:
  (db_working_get_status): removed, in favor of read_info
  (svn_wc__db_temp_op_delete): use read_info, and let it throw
    PATH_NOT_FOUND as appropriate, so we don't have to check for a BASE or
    WORKING node. synthesize the old WORKING_NONE variable from the new
    read_info data. adjust the conditionals a bit for the new status
    values, and handle the special obstructed_add case. for
    obstructed_delete (and regular delete), we just exit early.

* subversion/tests/cmdline/schedule_tests.py:
  (unschedule_missing_added): add a comment explaining the failure
  (test_list): mark the above as XFail

Modified:
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/tests/cmdline/schedule_tests.py

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=937358&r1=937357&r2=937358&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Apr 23 16:30:42 2010
@@ -2472,70 +2472,6 @@ svn_wc__db_base_get_info(svn_wc__db_stat
 }
 
 
-/* A WORKING version of svn_wc__db_base_get_info, stripped down to
-   just the status column.
-
-   ### This function should not exist!  What I really want is presence
-   ### not status, and so it's a mistake to return an
-   ### svn_wc__db_status_t here as it doesn't have quite the same
-   ### meaning as status returned by other functions.  I think I need
-   ### to abandon this function and work out how to decode status back
-   ### into presence :(
-*/
-static svn_error_t *
-db_working_get_status(svn_wc__db_status_t *status,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      apr_pool_t *scratch_pool)
-{
-  svn_wc__db_pdh_t *pdh;
-  const char *local_relpath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
-  svn_error_t *err = SVN_NO_ERROR;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  SVN_ERR(parse_local_abspath(&pdh, &local_relpath, db, local_abspath,
-                              svn_sqlite__mode_readonly,
-                              scratch_pool, scratch_pool));
-  VERIFY_USABLE_PDH(pdh);
-
-  SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
-                                    STMT_SELECT_WORKING_NODE));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
-  if (have_row)
-    {
-      svn_wc__db_kind_t node_kind = svn_sqlite__column_token(stmt, 1,
-                                                             kind_map);
-
-      *status = svn_sqlite__column_token(stmt, 0, presence_map);
-
-      if (node_kind == svn_wc__db_kind_subdir
-          && *status == svn_wc__db_status_normal)
-        {
-          /* We're looking at the subdir record in the *parent* directory,
-             which implies per-dir .svn subdirs. We should be looking
-             at the subdir itself; therefore, it is missing or obstructed
-             in some way. Inform the caller.  */
-          *status = svn_wc__db_status_obstructed;
-        }
-    }
-  else
-    {
-      err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
-                              _("The node '%s' was not found."),
-                              svn_dirent_local_style(local_abspath,
-                                                     scratch_pool));
-    }
-
-
-  return svn_error_compose_create(err, svn_sqlite__reset(stmt));
-}
-
-
 svn_error_t *
 svn_wc__db_base_get_prop(const svn_string_t **propval,
                          svn_wc__db_t *db,
@@ -3854,6 +3790,7 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *
   svn_error_t *err;
   svn_boolean_t base_none, working_none, new_working_none;
   svn_wc__db_status_t base_status, working_status, new_working_status;
+  svn_boolean_t base_shadowed;
 
   err = svn_wc__db_base_get_info(&base_status,
                                  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -3875,24 +3812,71 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *
   if (!base_none && base_status == svn_wc__db_status_absent)
     return SVN_NO_ERROR; /* ### should return an error.... WHICH ONE? */
 
-  err = db_working_get_status(&working_status,
-                              db, local_abspath, scratch_pool);
-  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+  /* No need to check for SVN_ERR_WC_PATH_NOT_FOUND. Something has to
+     be there for us to delete.  */
+  SVN_ERR(svn_wc__db_read_info(&working_status, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, &base_shadowed, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
+  if (working_status == svn_wc__db_status_deleted
+      || working_status == svn_wc__db_status_obstructed_delete)
     {
-      working_none = TRUE;
-      svn_error_clear(err);
+      /* The node is already deleted.  */
+      /* ### return an error? callers should know better.  */
+      return SVN_NO_ERROR;
     }
-  else if (! err)
-    working_none = FALSE;
-  else
-    return svn_error_return(err);
 
-  if (base_none && working_none)
-    return SVN_NO_ERROR; /* ### should return PATH_NOT_FOUND */
+  /* We must have a WORKING node if there is no BASE node (gotta have
+     something!). If there IS a BASE node, then we have a WORKING node
+     if BASE_SHADOWED is TRUE.  */
+  working_none = !(base_none || base_shadowed);
 
   new_working_none = working_none;
   new_working_status = working_status;
-  if (working_none)
+
+  if (working_status == svn_wc__db_status_normal
+      || working_status == svn_wc__db_status_not_present
+      || working_status == svn_wc__db_status_obstructed)
+    {
+      /* No structural changes (ie. no WORKING node). Mark the BASE node
+         as deleted.  */
+
+      SVN_ERR_ASSERT(working_none);
+
+      new_working_none = FALSE;
+      new_working_status = svn_wc__db_status_base_deleted;
+    }
+  else if (working_status == svn_wc__db_status_obstructed_add)
+    {
+      /* There is a parent stub for some kind of addition.
+
+         ### we cannot tell if this is a local-add or a copied/moved-here.
+         ### when the latter case, if this node is the root of that
+         ### copy/move, then we just "revert" it. otherwise, we're deleting
+         ### a child of that copy/move and marked it as delete. and the
+         ### second proble: we also cannot tell whether this is the root
+         ### or not.
+         ###
+         ### return WC_MISSING here. we need that working copy metadata
+         ###
+         ### when we get to single-db, there are no "obstructed" status
+         ### codes, so this will magically work...  */
+      SVN_ERR_ASSERT(!working_none);
+
+      return svn_error_createf(SVN_ERR_WC_MISSING, NULL,
+                               _("The directory '%s' is missing and cannot "
+                                 "be marked for deletion."),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+  /* ### remaining states: added, absent, excluded, incomplete
+     ### the last three have debatable schedule-delete semantics,
+     ### and this code may need to change further, but I'm not
+     ### going to worry about it now
+  */
+  else if (working_none)
     {
       /* No structural changes  */
       if (base_status == svn_wc__db_status_normal
@@ -3904,15 +3888,13 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *
           new_working_status = svn_wc__db_status_base_deleted;
         }
     }
-  else if ((working_status == svn_wc__db_status_normal
-            || working_status == svn_wc__db_status_obstructed)
+  else if (working_status == svn_wc__db_status_added
            && (base_none || base_status == svn_wc__db_status_not_present))
     {
-      /* ADD  */
+      /* ADD/COPY-HERE/MOVE-HERE. There is "no BASE node".  */
 
       svn_boolean_t add_or_root_of_copy;
 
-      /* ### this fails for the status_obstructed case.  */
       SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
                                      db, local_abspath, scratch_pool));
       if (add_or_root_of_copy)
@@ -3920,7 +3902,7 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *
       else
         new_working_status = svn_wc__db_status_not_present;
     }
-  else if (working_status == svn_wc__db_status_normal)
+  else if (working_status == svn_wc__db_status_added)
     {
       /* DELETE + ADD  */
       svn_boolean_t add_or_root_of_copy;
@@ -5370,7 +5352,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
       svn_sqlite__stmt_t *stmt;
       svn_boolean_t have_row;
       svn_wc__db_status_t presence;
-      svn_boolean_t presence_is_normal;
 
       /* ### is it faster to fetch fewer columns? */
       SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,

Modified: subversion/trunk/subversion/tests/cmdline/schedule_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/schedule_tests.py?rev=937358&r1=937357&r2=937358&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/schedule_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/schedule_tests.py Fri Apr 23 16:30:42 2010
@@ -453,6 +453,8 @@ def unschedule_missing_added(sbox):
   # FILE1_PATH will throw an error. DIR1_PATH will not since the stub is
   # still available in the parent directory.
   svntest.main.run_svn(svntest.verify.AnyOutput, 'rm', file1_path)
+  ### actually, the stub does not provide enough information to revert
+  ### the addition, so this command will fail. marking as XFail
   sbox.simple_rm(dir1_path)
   sbox.simple_revert(file2_path, dir2_path)
 
@@ -656,7 +658,7 @@ test_list = [ None,
               SkipUnless(revert_add_executable, svntest.main.is_posix_os),
               revert_delete_files,
               revert_delete_dirs,
-              unschedule_missing_added,
+              XFail(unschedule_missing_added),
               delete_missing,
               revert_inside_newly_added_dir,
               status_add_deleted_directory,