Version two of the patch. This time for the complete issue.
[[[
Fix for issue 1797. non-recursive delete of directory tree fails
Patch from <makl@tigris.org>
* subversion/libsvn_client/commit.c
(check_for_recursive_locking): New function.
(svn_client_commit): Always lock deleted directories recursive.
* subversion/libsvn_client/commit_util.c
(svn_client__do_commit): Don't commit items where the parent is
deleted too.
* subversion/tests/clients/cmdline/commit_tests.py
(commit_deleted_directory_tree_non_recursive_1): New
regression test for case one.
(commit_deleted_directory_tree_non_recursive_2_1): New
regression test for case two with one deleted directory.
(commit_deleted_directory_tree_non_recursive_2_1): New
regression test for case two with three independent deleted
directories.
]]]
Index: subversion/libsvn_client/commit_util.c
===================================================================
--- subversion/libsvn_client/commit_util.c (revision 9193)
+++ subversion/libsvn_client/commit_util.c (working copy)
@@ -1143,14 +1143,40 @@
/* Build a hash from our COMMIT_ITEMS array, keyed on the
URI-decoded relative paths (which come from the item URLs). And
- keep an array of those decoded paths, too. */
+ keep an array of those decoded paths, too.
+ In addition remove any deleted entries where the parent is also
+ deleted (deletes are always recursive). */
+
+ const char *delete_base = NULL;
for (i = 0; i < commit_items->nelts; i++)
{
+ svn_pool_clear (subpool);
+
svn_client_commit_item_t *item =
APR_ARRAY_IDX (commit_items, i, svn_client_commit_item_t *);
const char *path = svn_path_uri_decode (item->url, pool);
- apr_hash_set (items_hash, path, APR_HASH_KEY_STRING, item);
- APR_ARRAY_PUSH (paths, const char *) = path;
+ svn_boolean_t do_commit = TRUE;
+
+ if (item->state_flags == SVN_CLIENT_COMMIT_ITEM_DELETE)
+ {
+ if (delete_base)
+ {
+ if (svn_path_is_child(delete_base, path, subpool))
+ do_commit = FALSE;
+ else
+ delete_base = path;
+ }
+ else
+ delete_base = path;
+ }
+ else
+ delete_base = NULL;
+
+ if (do_commit)
+ {
+ apr_hash_set (items_hash, path, APR_HASH_KEY_STRING, item);
+ APR_ARRAY_PUSH (paths, const char *) = path;
+ }
}
/* Setup the callback baton. */
Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c (revision 9193)
+++ subversion/libsvn_client/commit.c (working copy)
@@ -1016,6 +1016,29 @@
return SVN_NO_ERROR;
}
+/* Check if a directory must be locked even in non recursive mode.
+ Currently this is the case for deleted directories. */
+static svn_error_t *
+check_for_recursive_locking(svn_boolean_t *is_deleted,
+ const char *path,
+ apr_pool_t *pool)
+{
+ *is_deleted = FALSE;
+
+ const svn_wc_entry_t *tmp_entry;
+ svn_wc_adm_access_t *tmp_adm_access;
+
+ SVN_ERR (svn_wc_adm_open2 (&tmp_adm_access, NULL, path, FALSE, 0, pool));
+ SVN_ERR (svn_wc_entry (&tmp_entry, path, tmp_adm_access, TRUE, pool));
+
+ if (!tmp_entry || (tmp_entry->schedule == svn_wc_schedule_delete))
+ *is_deleted = TRUE;
+
+ SVN_ERR (svn_wc_adm_close (tmp_adm_access));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_commit (svn_client_commit_info_t **commit_info,
const apr_array_header_t *targets,
@@ -1097,8 +1120,18 @@
/* If the final target is a dir, we want to recursively lock it */
if (kind == svn_node_dir)
{
+
if (nonrecursive)
- APR_ARRAY_PUSH (dirs_to_lock, const char *) = target;
+ {
+ svn_boolean_t lock_recursive;
+ SVN_ERR(check_for_recursive_locking(&lock_recursive,
+ target, pool));
+ if (lock_recursive)
+ APR_ARRAY_PUSH (dirs_to_lock_recursive,
+ const char *) = target;
+ else
+ APR_ARRAY_PUSH (dirs_to_lock, const char *) = target;
+ }
else
APR_ARRAY_PUSH (dirs_to_lock_recursive, const char *) = target;
}
@@ -1141,8 +1174,19 @@
if (kind == svn_node_dir)
{
if (nonrecursive)
- APR_ARRAY_PUSH (dirs_to_lock,
- const char *) = apr_pstrdup (pool, target);
+ {
+ svn_boolean_t lock_recursive;
+ SVN_ERR(check_for_recursive_locking(&lock_recursive,
+ target, subpool));
+ if (lock_recursive)
+ APR_ARRAY_PUSH (dirs_to_lock_recursive,
+ const char *) = apr_pstrdup (pool,
+ target);
+ else
+ APR_ARRAY_PUSH (dirs_to_lock,
+ const char *) = apr_pstrdup (pool,
+ target);
+ }
else
APR_ARRAY_PUSH (dirs_to_lock_recursive,
const char *) = apr_pstrdup (pool, target);
Index: subversion/tests/clients/cmdline/commit_tests.py
===================================================================
--- subversion/tests/clients/cmdline/commit_tests.py (revision 9193)
+++ subversion/tests/clients/cmdline/commit_tests.py (working copy)
@@ -1859,6 +1859,113 @@
+#----------------------------------------------------------------------
+# Regression test for issue 1797 case 2 part 1
+# Committing a single deleted directory
+
+def commit_deleted_directory_tree_non_recursive_2_1(sbox):
+ "non-recursively commit a deleted tree case 2-1"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ dir_path = os.path.join(sbox.wc_dir, 'A')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', dir_path)
+ # Created expected output tree for 'svn ci'
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(verb='Deleting'),
+ })
+
+ # Create expected status tree
+ expected_status = svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev=1, repos_rev=2),
+ 'iota' : Item(status=' ', wc_rev=1, repos_rev=2) ,
+ })
+
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None,
+ None, None, None, None, '-N',
+ dir_path)
+
+
+
+#----------------------------------------------------------------------
+# Regression test for issue 1797 case 2 part 2
+# Committing three independent deleted directories
+
+def commit_deleted_directory_tree_non_recursive_2_2(sbox):
+ "non-recursively commit a deleted tree case 2-2"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ dir_path1 = os.path.join(sbox.wc_dir, 'A/B')
+ dir_path2 = os.path.join(sbox.wc_dir, 'A/C')
+ dir_path3 = os.path.join(sbox.wc_dir, 'A/D')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', dir_path1, dir_path2, dir_path3)
+ # Created expected output tree for 'svn ci'
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A/B' : Item(verb='Deleting'),
+ 'A/C' : Item(verb='Deleting'),
+ 'A/D' : Item(verb='Deleting'),
+ })
+
+ # Create expected status tree
+ expected_status = svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev=1, repos_rev=2),
+ 'iota' : Item(status=' ', wc_rev=1, repos_rev=2) ,
+ 'A' : Item(status=' ', wc_rev=1, repos_rev=2) ,
+ 'A/mu' : Item(status=' ', wc_rev=1, repos_rev=2) ,
+ })
+
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None,
+ None, None, None, None, '-N',
+ dir_path1, dir_path2, dir_path3)
+
+
+
+#----------------------------------------------------------------------
+# Regression test for issue 1797 case 1
+# Committing multiple directories in the same directory tree
+
+def commit_deleted_directory_tree_non_recursive_1(sbox):
+ "non-recursively commit a deleted tree case 1"
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ dir_path1 = os.path.join(sbox.wc_dir, 'A')
+ dir_path2 = os.path.join(sbox.wc_dir, 'A/B')
+ dir_path3 = os.path.join(sbox.wc_dir, 'A/C')
+ dir_path4 = os.path.join(sbox.wc_dir, 'A/D')
+ dir_path5 = os.path.join(sbox.wc_dir, 'A/B/E')
+ dir_path6 = os.path.join(sbox.wc_dir, 'A/B/F')
+ dir_path7 = os.path.join(sbox.wc_dir, 'A/D/G')
+ dir_path8 = os.path.join(sbox.wc_dir, 'A/D/H')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', dir_path1)
+ # Created expected output tree for 'svn ci'
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(verb='Deleting'),
+ })
+
+ # Create expected status tree
+ expected_status = svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev=1, repos_rev=2),
+ 'iota' : Item(status=' ', wc_rev=1, repos_rev=2) ,
+ })
+
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None,
+ None, None, None, None, '-N',
+ dir_path1, dir_path2, dir_path3,
+ dir_path4, dir_path5, dir_path6,
+ dir_path7, dir_path8)
+
+
########################################################################
# Run the tests
@@ -1896,6 +2003,9 @@
commit_out_of_date_deletions,
commit_with_bad_log_message,
from_wc_top_with_bad_editor,
+ commit_deleted_directory_tree_non_recursive_1,
+ commit_deleted_directory_tree_non_recursive_2_1,
+ commit_deleted_directory_tree_non_recursive_2_2,
]
if __name__ == '__main__':
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Mar 25 21:06:26 2004