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 2013/01/16 18:35:48 UTC
svn commit: r1434061 - in /subversion/trunk/subversion:
libsvn_client/client.h libsvn_client/delete.c tests/cmdline/basic_tests.py
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.