subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1434061 - in /subversion/trunk/subversion: libsvn_client/client.h libsvn_client/delete.c tests/cmdline/basic_tests.py
Date Wed, 16 Jan 2013 17:35:48 GMT
Author: rhuijben
Date: Wed Jan 16 17:35:48 2013
New Revision: 1434061

URL: http://svn.apache.org/viewvc?rev=1434061&view=rev
Log:
Mostly resolve issue #4023 by trying to use the keep-local support of the
delete if all the targets of a 'svn rm' are status missing during the
status walk.

Note 1: This also applies to deletes from the merge code.
Note 2: This requires the r1434054 regression fix to the status walker.

* subversion/libsvn_client/client.h
  (svn_client__wc_delete): Rename argument and update layout.
  (svn_client__wc_delete_many): Fix typo.

* subversion/libsvn_client/delete.c
  (can_delete_baton_t): New struct.
  (find_undeletables): On status missing determine if it applies to the
    target of the operation. Assume that modified properties are folded
    in the node status.
  (can_delete_node): Add optional output argument. Use baton to set it.

  (svn_client__wc_delete): When the target is missing, don't delete the
    on-disk file.
  (svn_client__wc_delete_many): When all targets are missing, don't delete
    the on-disk files.

* subversion/tests/cmdline/basic_tests.py
  (rm_missing_with_case_clashing_ondisk_item): Remove XFail marker. Verify
    which file is deleted to verify the truename argument parser separately.

Modified:
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/delete.c
    subversion/trunk/subversion/tests/cmdline/basic_tests.py

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1434061&r1=1434060&r2=1434061&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Wed Jan 16 17:35:48 2013
@@ -420,17 +420,18 @@ svn_error_t *svn_client__get_inherited_i
    If DRY_RUN is TRUE all the checks are made to ensure that the delete can
    occur, but the working copy is not modified.  If NOTIFY_FUNC is not
    null, it is called with NOTIFY_BATON for each file or directory deleted. */
-svn_error_t * svn_client__wc_delete(const char *path,
-                                    svn_boolean_t force,
-                                    svn_boolean_t dry_run,
-                                    svn_boolean_t keep_local,
-                                    svn_wc_notify_func2_t notify_func,
-                                    void *notify_baton,
-                                    svn_client_ctx_t *ctx,
-                                    apr_pool_t *pool);
+svn_error_t *
+svn_client__wc_delete(const char *local_abspath,
+                      svn_boolean_t force,
+                      svn_boolean_t dry_run,
+                      svn_boolean_t keep_local,
+                      svn_wc_notify_func2_t notify_func,
+                      void *notify_baton,
+                      svn_client_ctx_t *ctx,
+                      apr_pool_t *pool);
 
 
-/* Like svn_client__wc_delete(), but deletes mulitple TARGETS efficiently. */
+/* Like svn_client__wc_delete(), but deletes multiple TARGETS efficiently. */
 svn_error_t *
 svn_client__wc_delete_many(const apr_array_header_t *targets,
                            svn_boolean_t force,

Modified: subversion/trunk/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/delete.c?rev=1434061&r1=1434060&r2=1434061&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/delete.c (original)
+++ subversion/trunk/subversion/libsvn_client/delete.c Wed Jan 16 17:35:48 2013
@@ -46,36 +46,47 @@
 
 /*** Code. ***/
 
+/* Baton for find_undeletables */
+struct can_delete_baton_t
+{
+  const char *root_abspath;
+  svn_boolean_t target_missing;
+};
 
 /* An svn_wc_status_func4_t callback function for finding
    status structures which are not safely deletable. */
 static svn_error_t *
 find_undeletables(void *baton,
-                  const char *path,
+                  const char *local_abspath,
                   const svn_wc_status3_t *status,
                   apr_pool_t *pool)
 {
+  if (status->node_status == svn_wc_status_missing)
+    {
+      struct can_delete_baton_t *cdt = baton;
+
+      if (strcmp(cdt->root_abspath, local_abspath) == 0)
+        cdt->target_missing = TRUE;
+    }
+
   /* Check for error-ful states. */
   if (status->node_status == svn_wc_status_obstructed)
     return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                              _("'%s' is in the way of the resource "
                                "actually under version control"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
   else if (! status->versioned)
     return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
                              _("'%s' is not under version control"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
 
-  else if ((status->node_status != svn_wc_status_normal
-            && status->node_status != svn_wc_status_deleted
-            && status->node_status != svn_wc_status_missing)
-           ||
-           (status->prop_status != svn_wc_status_none
-            && status->prop_status != svn_wc_status_normal))
+  else if (status->node_status != svn_wc_status_normal
+           && status->node_status != svn_wc_status_deleted
+           && status->node_status != svn_wc_status_missing)
     return svn_error_createf(SVN_ERR_CLIENT_MODIFIED, NULL,
                              _("'%s' has local modifications -- commit or "
                                "revert them first"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
 
   return SVN_NO_ERROR;
 }
@@ -86,13 +97,15 @@ find_undeletables(void *baton,
    command.  CTX is used for the client's config options.  POOL is
    used for all temporary allocations. */
 static svn_error_t *
-can_delete_node(const char *local_abspath,
+can_delete_node(svn_boolean_t *target_missing,
+                const char *local_abspath,
                 svn_client_ctx_t *ctx,
                 apr_pool_t *scratch_pool)
 {
   svn_node_kind_t external_kind;
   const char *defining_abspath;
   apr_array_header_t *ignores;
+  struct can_delete_baton_t cdt;
 
   /* A file external should not be deleted since the file external is
      implemented as a switched file and it would delete the file the
@@ -123,17 +136,25 @@ can_delete_node(const char *local_abspat
 
   SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool));
 
-  return svn_error_trace(svn_wc_walk_status(ctx->wc_ctx,
-                                            local_abspath,
-                                            svn_depth_infinity,
-                                            FALSE /* get_all */,
-                                            FALSE /* no_ignore */,
-                                            FALSE /* ignore_text_mod */,
-                                            ignores,
-                                            find_undeletables, NULL,
-                                            ctx->cancel_func,
-                                            ctx->cancel_baton,
-                                            scratch_pool));
+  cdt.root_abspath = local_abspath;
+  cdt.target_missing = FALSE;
+
+  SVN_ERR(svn_wc_walk_status(ctx->wc_ctx,
+                             local_abspath,
+                             svn_depth_infinity,
+                             FALSE /* get_all */,
+                             FALSE /* no_ignore */,
+                             FALSE /* ignore_text_mod */,
+                             ignores,
+                             find_undeletables, &cdt,
+                             ctx->cancel_func,
+                             ctx->cancel_baton,
+                             scratch_pool));
+
+  if (target_missing)
+    *target_missing = cdt.target_missing;
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -318,7 +339,7 @@ delete_urls_multi_repos(const apr_array_
 }
 
 svn_error_t *
-svn_client__wc_delete(const char *path,
+svn_client__wc_delete(const char *local_abspath,
                       svn_boolean_t force,
                       svn_boolean_t dry_run,
                       svn_boolean_t keep_local,
@@ -327,18 +348,20 @@ svn_client__wc_delete(const char *path,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *pool)
 {
-  const char *local_abspath;
+  svn_boolean_t target_missing = FALSE;
 
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   if (!force && !keep_local)
     /* Verify that there are no "awkward" files */
-    SVN_ERR(can_delete_node(local_abspath, ctx, pool));
+    SVN_ERR(can_delete_node(&target_missing, local_abspath, ctx, pool));
 
   if (!dry_run)
     /* Mark the entry for commit deletion and perform wc deletion */
     return svn_error_trace(svn_wc_delete4(ctx->wc_ctx, local_abspath,
-                                          keep_local, TRUE,
+                                          keep_local || target_missing
+                                                            /*keep_local */,
+                                          TRUE /* delete_unversioned */,
                                           ctx->cancel_func, ctx->cancel_baton,
                                           notify_func, notify_baton, pool));
 
@@ -356,30 +379,43 @@ svn_client__wc_delete_many(const apr_arr
                            apr_pool_t *pool)
 {
   int i;
-  apr_array_header_t *abs_targets;
+  svn_boolean_t has_non_missing = FALSE;
 
-  abs_targets = apr_array_make(pool, targets->nelts, sizeof(const char *));
   for (i = 0; i < targets->nelts; i++)
     {
-      const char *path = APR_ARRAY_IDX(targets, i, const char *);
-      const char *local_abspath;
+      const char *local_abspath = APR_ARRAY_IDX(targets, i, const char *);
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-      APR_ARRAY_PUSH(abs_targets, const char *) = local_abspath;
+      SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
       if (!force && !keep_local)
-        /* Verify that there are no "awkward" files */
-        SVN_ERR(can_delete_node(local_abspath, ctx, pool));
+        {
+          svn_boolean_t missing;
+          /* Verify that there are no "awkward" files */
+
+          SVN_ERR(can_delete_node(&missing, local_abspath, ctx, pool));
+
+          if (! missing)
+            has_non_missing = TRUE;
+        }
+      else
+        has_non_missing = TRUE;
     }
 
   if (!dry_run)
-    /* Mark the entry for commit deletion and perform wc deletion */
-    return svn_error_trace(svn_wc__delete_many(ctx->wc_ctx, abs_targets,
-                                               keep_local, TRUE,
-                                               ctx->cancel_func,
-                                               ctx->cancel_baton,
-                                               notify_func, notify_baton,
-                                               pool));
+    {
+      /* Mark the entry for commit deletion and perform wc deletion */
+
+      /* If none of the targets exists, pass keep local TRUE, to avoid
+         deleting case-different files. Detecting this in the generic case
+         from the delete code is expensive */
+      return svn_error_trace(svn_wc__delete_many(ctx->wc_ctx, targets,
+                                                 keep_local || !has_non_missing,
+                                                 TRUE /* delete_unversioned_target */,
+                                                 ctx->cancel_func,
+                                                 ctx->cancel_baton,
+                                                 notify_func, notify_baton,
+                                                 pool));
+    }
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/basic_tests.py?rev=1434061&r1=1434060&r2=1434061&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/basic_tests.py Wed Jan 16 17:35:48 2013
@@ -2937,7 +2937,6 @@ def quiet_commits(sbox):
 # Regression test for issue #4023: on Windows, 'svn rm' incorrectly deletes
 # on-disk file if it is case-clashing with intended (non-on-disk) target.
 @Issue(4023)
-@XFail(svntest.main.is_fs_case_insensitive)
 def rm_missing_with_case_clashing_ondisk_item(sbox):
   """rm missing item with case-clashing ondisk item"""
 
@@ -2957,8 +2956,10 @@ def rm_missing_with_case_clashing_ondisk
     })
   svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status)
 
+  # Verify that the casing is not updated, because the path is on-disk.
+  expected_output = [ 'D         %s\n' % iota_path ]
   # 'svn rm' iota, should leave IOTA alone.
-  svntest.actions.run_and_verify_svn(None, None, [],
+  svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'rm', iota_path)
 
   # Test status: the unversioned IOTA should still be there.



Mime
View raw message