Current implementation of svn_fs_delete_tree can't delete a
non-empty mutable directory. Here's the fix. Essentialy,
this patch adds new function svn_fs__dag_delete_tree which
can delete a non-empty mutable directory. Other parts are
just moving bits around. This patch also adds a new check
to svn_fs_delete_tree and svn_fs_delete to see svn_fs_root_t
is a transaction root. Unless someone else adds the same
check to functions like svn_fs_change_node_prop, I'll do it.
* svn_error.h (SVN_ERR_FS_NOT_TXN_ROOT): New error.
* dag.c (svn_fs__dag_delete_tree): New function.
* dag.c (delete_node): New function.
* dag.c (svn_fs__dag_delete_mutable_node): Renamed from
delete_from_id in txn.c. All callers are changed.
* dag.h (svn_fs__dag_delete_tree): New declaration.
* dag.h (svn_fs__dag_delete_mutable_node): New declaration.
* tree.c (struct delete_args): Remove require_empty_dir arg.
* tree.c (txn_body_delete): Check root object is a transaction
root.
* tree.c (svn_fs_delete): Remove require_empty_dir arg.
* tree.c (txn_body_delete_tree): New function.
* tree.c (svn_fs_delete_tree):
* txn.c (delete_from_id): Moved to dag.c and renamed to
svn_fs__dag_delete_mutable_node.
* subversion/tests/libsvn_fs/fs-test.c (delete_tree): New test.
Index: subversion/include/svn_error.h
===================================================================
RCS file: /cvs/subversion/subversion/include/svn_error.h,v
retrieving revision 1.86
diff -u -r1.86 svn_error.h
--- subversion/include/svn_error.h 2001/03/17 07:16:27 1.86
+++ subversion/include/svn_error.h 2001/03/19 05:40:21
@@ -173,6 +173,9 @@
or create another node named /. */
SVN_ERR_FS_ROOT_DIR,
+ /* The root object given is not transaction root. */
+ SVN_ERR_FS_NOT_TXN_ROOT,
+
/* The transaction could not be committed, because of a conflict with
a prior change. */
SVN_ERR_FS_CONFLICT,
Index: subversion/libsvn_fs/dag.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.c,v
retrieving revision 1.87
diff -u -r1.87 dag.c
--- subversion/libsvn_fs/dag.c 2001/03/16 21:53:12 1.87
+++ subversion/libsvn_fs/dag.c 2001/03/19 05:40:21
@@ -1063,10 +1063,15 @@
}
-svn_error_t *
-svn_fs__dag_delete (dag_node_t *parent,
- const char *name,
- trail_t *trail)
+/* Delete the directory entry named NAME from PARENT, as part of
+ TRAIL. PARENT must be mutable. NAME must be a single path
+ component. If REQUIRE_EMPTY is true and the node being deleted is
+ mutable, it must be empty. */
+static svn_error_t *
+delete_node (dag_node_t *parent,
+ const char *name,
+ svn_boolean_t require_empty,
+ trail_t *trail)
{
skel_t *node_rev, *new_dirent_list, *prev_entry, *entry;
int deleted = FALSE;
@@ -1156,7 +1161,8 @@
SVN_ERR (svn_fs__get_node_revision (&content, parent->fs,
id, trail));
- if (svn_fs__list_length (content->children->next) != 0)
+ if (svn_fs__list_length (content->children->next) != 0
+ && require_empty)
{
return
svn_error_createf
@@ -1167,7 +1173,7 @@
}
/* Delete the mutable node from the database. */
- SVN_ERR (svn_fs__delete_node_revision (parent->fs, id, trail));
+ SVN_ERR (svn_fs__dag_delete_mutable_node (parent->fs, id, trail));
}
/* Just "lose" this entry by setting the *previous* entry's
@@ -1197,6 +1203,62 @@
node_rev,
trail));
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_fs__dag_delete (dag_node_t *parent,
+ const char *name,
+ trail_t *trail)
+{
+ return delete_node (parent, name, TRUE, trail);
+}
+
+
+svn_error_t *
+svn_fs__dag_delete_tree (dag_node_t *parent,
+ const char *name,
+ trail_t *trail)
+{
+ return delete_node (parent, name, FALSE, trail);
+}
+
+
+svn_error_t *
+svn_fs__dag_delete_mutable_node (svn_fs_t *fs,
+ svn_fs_id_t *id,
+ trail_t *trail)
+{
+ svn_boolean_t is_mutable;
+ dag_node_t *node;
+
+ SVN_ERR (svn_fs__dag_get_node (&node, fs, id, trail));
+
+ /* If immutable, do nothing and return immediately. */
+ SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, node, trail));
+ if (! is_mutable)
+ return SVN_NO_ERROR;
+
+ /* Else it's mutable. Recurse on directories... */
+ if (svn_fs__dag_is_directory (node))
+ {
+ skel_t *entries, *entry;
+ SVN_ERR (svn_fs__dag_dir_entries_skel (&entries, node, trail));
+
+ for (entry = entries->children; entry; entry = entry->next)
+ {
+ skel_t *id_skel = entry->children->next;
+ svn_fs_id_t *this_id
+ = svn_fs_parse_id (id_skel->data, id_skel->len, trail->pool);
+
+ SVN_ERR (svn_fs__dag_delete_mutable_node (fs, this_id, trail));
+ }
+ }
+
+ /* ... then delete the node itself. */
+ SVN_ERR (svn_fs__delete_node_revision (fs, id, trail));
+
return SVN_NO_ERROR;
}
Index: subversion/libsvn_fs/dag.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.h,v
retrieving revision 1.40
diff -u -r1.40 dag.h
--- subversion/libsvn_fs/dag.h 2001/03/16 03:38:49 1.40
+++ subversion/libsvn_fs/dag.h 2001/03/19 05:40:22
@@ -310,6 +310,25 @@
trail_t *trail);
+/* Delete the directory entry named NAME from PARENT, as part of
+ TRAIL. PARENT must be mutable. NAME must be a single path
+ component; it cannot be a slash-separated directory path. If the
+ node being deleted is a mutable directory, remove all reachable
+ mutable nodes from there. */
+svn_error_t *svn_fs__dag_delete_tree (dag_node_t *parent,
+ const char *name,
+ trail_t *trail);
+
+
+/* Delete all mutable node revisions reachable from node ID, including
+ ID itself, from FS's `nodes' table, as part of TRAIL. ID may refer
+ to a file or directory, which may be mutable or immutable. */
+svn_error_t *
+svn_fs__dag_delete_mutable_node (svn_fs_t *fs,
+ svn_fs_id_t *id,
+ trail_t *trail);
+
+
/* Create a new mutable directory named NAME in PARENT, as part of
TRAIL. Set *CHILD_P to a reference to the new node, allocated in
TRAIL->pool. The new directory has no contents, and no properties.
Index: subversion/libsvn_fs/tree.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/tree.c,v
retrieving revision 1.51
diff -u -r1.51 tree.c
--- subversion/libsvn_fs/tree.c 2001/03/16 20:07:57 1.51
+++ subversion/libsvn_fs/tree.c 2001/03/19 05:40:22
@@ -1760,7 +1760,6 @@
{
svn_fs_root_t *root;
const char *path;
- svn_boolean_t require_empty_dir;
};
@@ -1771,11 +1770,15 @@
struct delete_args *args = baton;
svn_fs_root_t *root = args->root;
const char *path = args->path;
- svn_boolean_t require_empty_dir = args->require_empty_dir;
parent_path_t *parent_path;
SVN_ERR (open_path (&parent_path, root, path, 0, trail));
+ if (root->kind != transaction_root)
+ return svn_error_create
+ (SVN_ERR_FS_NOT_TXN_ROOT, 0, NULL, trail->pool,
+ "root object must be a transaction root");
+
/* We can't remove the root of the filesystem. */
if (! parent_path->parent)
return svn_error_create (SVN_ERR_FS_ROOT_DIR, 0, NULL, trail->pool,
@@ -1785,9 +1788,8 @@
SVN_ERR (make_path_mutable (root, parent_path->parent, path, trail));
/* If this is a directory, we have to check to see if it is required
- by our caller to be empty before deleting it. */
- if (svn_fs__dag_is_directory (parent_path->node)
- && require_empty_dir)
+ by our caller to be empty before deleting it. */
+ if (svn_fs__dag_is_directory (parent_path->node))
{
skel_t *entries;
@@ -1821,11 +1823,42 @@
args.root = root;
args.path = path;
- args.require_empty_dir = TRUE;
return svn_fs__retry_txn (root->fs, txn_body_delete, &args, pool);
}
+static svn_error_t *
+txn_body_delete_tree (void *baton,
+ trail_t *trail)
+{
+ struct delete_args *args = baton;
+ svn_fs_root_t *root = args->root;
+ const char *path = args->path;
+ parent_path_t *parent_path;
+
+ SVN_ERR (open_path (&parent_path, root, path, 0, trail));
+
+ if (root->kind != transaction_root)
+ return svn_error_create
+ (SVN_ERR_FS_NOT_TXN_ROOT, 0, NULL, trail->pool,
+ "root object must be a transaction root");
+
+ /* We can't remove the root of the filesystem. */
+ if (! parent_path->parent)
+ return svn_error_create (SVN_ERR_FS_ROOT_DIR, 0, NULL, trail->pool,
+ "the root directory cannot be deleted");
+
+ /* Make the parent directory mutable. */
+ SVN_ERR (make_path_mutable (root, parent_path->parent, path, trail));
+
+ SVN_ERR (svn_fs__dag_delete_tree (parent_path->parent->node,
+ parent_path->entry,
+ trail));
+
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
svn_fs_delete_tree (svn_fs_root_t *root,
const char *path,
@@ -1835,8 +1868,7 @@
args.root = root;
args.path = path;
- args.require_empty_dir = FALSE;
- return svn_fs__retry_txn (root->fs, txn_body_delete, &args, pool);
+ return svn_fs__retry_txn (root->fs, txn_body_delete_tree, &args, pool);
}
Index: subversion/libsvn_fs/txn.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/txn.c,v
retrieving revision 1.37
diff -u -r1.37 txn.c
--- subversion/libsvn_fs/txn.c 2001/03/14 00:21:28 1.37
+++ subversion/libsvn_fs/txn.c 2001/03/19 05:40:22
@@ -165,46 +165,7 @@
};
-/* Delete all mutable node revisions reachable from node ID, including
- ID itself, from filesystem FS, as part of TRAIL. ID may refer to
- a file or directory, which may be mutable or immutable. */
static svn_error_t *
-delete_from_id (svn_fs_t *fs, svn_fs_id_t *id, trail_t *trail)
-{
- svn_boolean_t is_mutable;
- dag_node_t *node;
-
- SVN_ERR (svn_fs__dag_get_node (&node, fs, id, trail));
-
- /* If immutable, do nothing and return immediately. */
- SVN_ERR (svn_fs__dag_check_mutable (&is_mutable, node, trail));
- if (! is_mutable)
- return SVN_NO_ERROR;
-
- /* Else it's mutable. Recurse on directories... */
- if (svn_fs__dag_is_directory (node))
- {
- skel_t *entries, *entry;
- SVN_ERR (svn_fs__dag_dir_entries_skel (&entries, node, trail));
-
- for (entry = entries->children; entry; entry = entry->next)
- {
- skel_t *id_skel = entry->children->next;
- svn_fs_id_t *this_id
- = svn_fs_parse_id (id_skel->data, id_skel->len, trail->pool);
-
- SVN_ERR (delete_from_id (fs, this_id, trail));
- }
- }
-
- /* ... then delete the node itself. */
- SVN_ERR (svn_fs__delete_node_revision (fs, id, trail));
-
- return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
txn_body_abort_txn (void *baton, trail_t *trail)
{
struct abort_txn_args *args = baton;
@@ -214,7 +175,7 @@
SVN_ERR (svn_fs_txn_name (&txn_name, txn, txn->pool));
SVN_ERR (svn_fs__get_txn (&root_id, &ignored_id, txn->fs, txn_name, trail));
- SVN_ERR (delete_from_id (txn->fs, root_id, trail));
+ SVN_ERR (svn_fs__dag_delete_mutable_node (txn->fs, root_id, trail));
SVN_ERR (svn_fs__delete_txn (txn->fs, txn->id, trail));
return SVN_NO_ERROR;
Index: subversion/tests/libsvn_fs/fs-test.c
===================================================================
RCS file: /cvs/subversion/subversion/tests/libsvn_fs/fs-test.c,v
retrieving revision 1.57
diff -u -r1.57 fs-test.c
--- subversion/tests/libsvn_fs/fs-test.c 2001/03/16 20:08:02 1.57
+++ subversion/tests/libsvn_fs/fs-test.c 2001/03/19 05:40:22
@@ -3026,6 +3026,408 @@
}
/* Close the filesystem. */
SVN_ERR (svn_fs_close_fs (fs));
+ return SVN_NO_ERROR;
+}
+
+
+/* Test svn_fs_delete_tree.
+
+ NOTE: This function tests internal filesystem interfaces, not just
+ the public filesystem interface. */
+static svn_error_t *
+delete_tree (const char **msg)
+{
+ svn_fs_t *fs;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ svn_revnum_t new_rev;
+
+ *msg = "delete nodes tree";
+
+ /* This function tests 5 cases:
+ *
+ * 1. Delete mutable file.
+ * 2. Delete mutable directory.
+ * 3. Delete mutable directory with immutable nodes.
+ * 4. Delete immutable file.
+ * 5. Delete immutable directory.
+ */
+
+ /* Prepare a txn to receive the greek tree. */
+ SVN_ERR (create_fs_and_repos (&fs, "test-repo-del-tree"));
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* Create the greek tree. */
+ SVN_ERR (greek_tree_under_root (txn_root));
+
+ /* 1 */
+ {
+ svn_fs_id_t *iota_id;
+ tree_test_entry_t expected_entries[] = {
+ /* path, is_dir, contents */
+ { "A", 1, "" },
+ { "A/mu", 0, "This is the file 'mu'.\n" },
+ { "A/B", 1, "" },
+ { "A/B/lambda", 0, "This is the file 'lambda'.\n" },
+ { "A/B/E", 1, "" },
+ { "A/B/E/alpha", 0, "This is the file 'alpha'.\n" },
+ { "A/B/E/beta", 0, "This is the file 'beta'.\n" },
+ { "A/B/F", 1, "" },
+ { "A/C", 1, "" },
+ { "A/D", 1, "" },
+ { "A/D/gamma", 0, "This is the file 'gamma'.\n" },
+ { "A/D/G", 1, "" },
+ { "A/D/G/pi", 0, "This is the file 'pi'.\n" },
+ { "A/D/G/rho", 0, "This is the file 'rho'.\n" },
+ { "A/D/G/tau", 0, "This is the file 'tau'.\n" },
+ { "A/D/H", 1, "" },
+ { "A/D/H/chi", 0, "This is the file 'chi'.\n" },
+ { "A/D/H/psi", 0, "This is the file 'psi'.\n" },
+ { "A/D/H/omega", 0, "This is the file 'omega'.\n" }
+ };
+ /* Check nodes revision ID is gone. */
+ SVN_ERR (svn_fs_node_id (&iota_id, txn_root, "iota", pool));
+ SVN_ERR (check_entry_present (txn_root, "", "iota"));
+ SVN_ERR (check_id_present (fs, iota_id));
+
+ SVN_ERR (svn_fs_delete_tree (txn_root, "iota", pool));
+ SVN_ERR (check_entry_absent (txn_root, "", "iota"));
+ SVN_ERR (check_id_absent (fs, iota_id));
+
+ /* Validate the tree. */
+ SVN_ERR (validate_tree (txn_root, expected_entries, 19));
+ }
+ /* Abort transaction. */
+ SVN_ERR (svn_fs_abort_txn (txn));
+
+ /* Prepare a txn to receive the greek tree. */
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* Create the greek tree. */
+ SVN_ERR (greek_tree_under_root (txn_root));
+
+ /* 2 */
+ {
+ svn_fs_id_t *A_id, *mu_id, *B_id, *lambda_id, *E_id, *alpha_id,
+ *beta_id, *F_id, *C_id, *D_id, *gamma_id, *H_id, *chi_id,
+ *psi_id, *omega_id, *G_id, *pi_id, *rho_id, *tau_id;
+
+ tree_test_entry_t expected_entries[] = {
+ /* path, is_dir, contents */
+ { "iota", 0, "This is the file 'iota'.\n" }
+ };
+
+ /* Check nodes revision ID is gone. */
+ SVN_ERR (svn_fs_node_id (&A_id, txn_root, "/A", pool));
+ SVN_ERR (check_entry_present (txn_root, "", "A"));
+ SVN_ERR (svn_fs_node_id (&mu_id, txn_root, "/A/mu", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "mu"));
+ SVN_ERR (svn_fs_node_id (&B_id, txn_root, "/A/B", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "B"));
+ SVN_ERR (svn_fs_node_id (&lambda_id, txn_root, "/A/B/lambda", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "lambda"));
+ SVN_ERR (svn_fs_node_id (&E_id, txn_root, "/A/B/E", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "E"));
+ SVN_ERR (svn_fs_node_id (&alpha_id, txn_root, "/A/B/E/alpha", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "alpha"));
+ SVN_ERR (svn_fs_node_id (&beta_id, txn_root, "/A/B/E/beta", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "beta"));
+ SVN_ERR (svn_fs_node_id (&F_id, txn_root, "/A/B/F", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "F"));
+ SVN_ERR (svn_fs_node_id (&C_id, txn_root, "/A/C", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "C"));
+ SVN_ERR (svn_fs_node_id (&D_id, txn_root, "/A/D", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "D"));
+ SVN_ERR (svn_fs_node_id (&gamma_id, txn_root, "/A/D/gamma", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "gamma"));
+ SVN_ERR (svn_fs_node_id (&H_id, txn_root, "/A/D/H", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "H"));
+ SVN_ERR (svn_fs_node_id (&chi_id, txn_root, "/A/D/H/chi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "chi"));
+ SVN_ERR (svn_fs_node_id (&psi_id, txn_root, "/A/D/H/psi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "psi"));
+ SVN_ERR (svn_fs_node_id (&omega_id, txn_root, "/A/D/H/omega", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "omega"));
+ SVN_ERR (svn_fs_node_id (&G_id, txn_root, "/A/D/G", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "G"));
+ SVN_ERR (svn_fs_node_id (&pi_id, txn_root, "/A/D/G/pi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "pi"));
+ SVN_ERR (svn_fs_node_id (&rho_id, txn_root, "/A/D/G/rho", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "rho"));
+ SVN_ERR (svn_fs_node_id (&tau_id, txn_root, "/A/D/G/tau", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "tau"));
+
+ SVN_ERR (svn_fs_delete_tree (txn_root, "A", pool));
+
+ SVN_ERR (check_entry_absent (txn_root, "", "A"));
+ SVN_ERR (check_id_absent (fs, A_id));
+ SVN_ERR (check_id_absent (fs, mu_id));
+ SVN_ERR (check_id_absent (fs, B_id));
+ SVN_ERR (check_id_absent (fs, lambda_id));
+ SVN_ERR (check_id_absent (fs, E_id));
+ SVN_ERR (check_id_absent (fs, alpha_id));
+ SVN_ERR (check_id_absent (fs, beta_id));
+ SVN_ERR (check_id_absent (fs, F_id));
+ SVN_ERR (check_id_absent (fs, C_id));
+ SVN_ERR (check_id_absent (fs, D_id));
+ SVN_ERR (check_id_absent (fs, gamma_id));
+ SVN_ERR (check_id_absent (fs, H_id));
+ SVN_ERR (check_id_absent (fs, chi_id));
+ SVN_ERR (check_id_absent (fs, psi_id));
+ SVN_ERR (check_id_absent (fs, omega_id));
+ SVN_ERR (check_id_absent (fs, G_id));
+ SVN_ERR (check_id_absent (fs, pi_id));
+ SVN_ERR (check_id_absent (fs, rho_id));
+ SVN_ERR (check_id_absent (fs, tau_id));
+
+ /* Validate the tree. */
+ SVN_ERR (validate_tree (txn_root, expected_entries, 1));
+ }
+
+ /* Abort transaction. */
+ SVN_ERR (svn_fs_abort_txn (txn));
+
+ /* Prepare a txn to receive the greek tree. */
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, 0, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* Create the greek tree. */
+ SVN_ERR (greek_tree_under_root (txn_root));
+
+ /* Commit the greek tree. */
+ {
+ const char *conflict;
+ SVN_ERR (svn_fs_commit_txn (&conflict, &new_rev, txn));
+ }
+ SVN_ERR (svn_fs_close_txn (txn));
+
+ /* Create new transaction. */
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, new_rev, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* 3 */
+ {
+ svn_fs_id_t *A_id, *mu_id, *B_id, *lambda_id, *E_id, *alpha_id,
+ *beta_id, *F_id, *C_id, *D_id, *gamma_id, *H_id, *chi_id,
+ *psi_id, *omega_id, *G_id, *pi_id, *rho_id, *tau_id, *sigma_id;
+
+ tree_test_entry_t expected_entries[] = {
+ /* path, is_dir, contents */
+ { "iota", 0, "This is the file 'iota'.\n" }
+ };
+
+ /* Create A/D/G/sigma. This makes all component of A/D/G
+ mutable. */
+ SVN_ERR (svn_fs_make_file (txn_root, "A/D/G/sigma", pool));
+ SVN_ERR (set_file_contents (txn_root, "A/D/G/sigma",
+ "This is another file 'sigma'.\n"));
+
+ /* Check mutable nodes revision ID is removed and immutable ones
+ still exist. */
+ SVN_ERR (svn_fs_node_id (&A_id, txn_root, "/A", pool));
+ SVN_ERR (check_entry_present (txn_root, "", "A"));
+ SVN_ERR (svn_fs_node_id (&mu_id, txn_root, "/A/mu", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "mu"));
+ SVN_ERR (svn_fs_node_id (&B_id, txn_root, "/A/B", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "B"));
+ SVN_ERR (svn_fs_node_id (&lambda_id, txn_root, "/A/B/lambda", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "lambda"));
+ SVN_ERR (svn_fs_node_id (&E_id, txn_root, "/A/B/E", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "E"));
+ SVN_ERR (svn_fs_node_id (&alpha_id, txn_root, "/A/B/E/alpha", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "alpha"));
+ SVN_ERR (svn_fs_node_id (&beta_id, txn_root, "/A/B/E/beta", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "beta"));
+ SVN_ERR (svn_fs_node_id (&F_id, txn_root, "/A/B/F", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "F"));
+ SVN_ERR (svn_fs_node_id (&C_id, txn_root, "/A/C", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "C"));
+ SVN_ERR (svn_fs_node_id (&D_id, txn_root, "/A/D", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "D"));
+ SVN_ERR (svn_fs_node_id (&gamma_id, txn_root, "/A/D/gamma", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "gamma"));
+ SVN_ERR (svn_fs_node_id (&H_id, txn_root, "/A/D/H", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "H"));
+ SVN_ERR (svn_fs_node_id (&chi_id, txn_root, "/A/D/H/chi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "chi"));
+ SVN_ERR (svn_fs_node_id (&psi_id, txn_root, "/A/D/H/psi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "psi"));
+ SVN_ERR (svn_fs_node_id (&omega_id, txn_root, "/A/D/H/omega", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "omega"));
+ SVN_ERR (svn_fs_node_id (&G_id, txn_root, "/A/D/G", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "G"));
+ SVN_ERR (svn_fs_node_id (&pi_id, txn_root, "/A/D/G/pi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "pi"));
+ SVN_ERR (svn_fs_node_id (&rho_id, txn_root, "/A/D/G/rho", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "rho"));
+ SVN_ERR (svn_fs_node_id (&tau_id, txn_root, "/A/D/G/tau", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "tau"));
+ SVN_ERR (svn_fs_node_id (&sigma_id, txn_root, "/A/D/G/sigma", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "sigma"));
+
+ SVN_ERR (svn_fs_delete_tree (txn_root, "A", pool));
+
+ SVN_ERR (check_entry_absent (txn_root, "", "A"));
+ SVN_ERR (check_id_absent (fs, A_id));
+ SVN_ERR (check_id_present (fs, mu_id));
+ SVN_ERR (check_id_present (fs, B_id));
+ SVN_ERR (check_id_present (fs, lambda_id));
+ SVN_ERR (check_id_present (fs, E_id));
+ SVN_ERR (check_id_present (fs, alpha_id));
+ SVN_ERR (check_id_present (fs, beta_id));
+ SVN_ERR (check_id_present (fs, F_id));
+ SVN_ERR (check_id_present (fs, C_id));
+ SVN_ERR (check_id_absent (fs, D_id));
+ SVN_ERR (check_id_present (fs, gamma_id));
+ SVN_ERR (check_id_present (fs, H_id));
+ SVN_ERR (check_id_present (fs, chi_id));
+ SVN_ERR (check_id_present (fs, psi_id));
+ SVN_ERR (check_id_present (fs, omega_id));
+ SVN_ERR (check_id_absent (fs, G_id));
+ SVN_ERR (check_id_present (fs, pi_id));
+ SVN_ERR (check_id_present (fs, rho_id));
+ SVN_ERR (check_id_present (fs, tau_id));
+ SVN_ERR (check_id_absent (fs, sigma_id));
+
+ /* Validate the tree. */
+ SVN_ERR (validate_tree (txn_root, expected_entries, 1));
+ }
+
+ /* Abort transaction. */
+ SVN_ERR (svn_fs_abort_txn (txn));
+
+ /* Create new transaction. */
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, new_rev, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* 4 */
+ {
+ svn_fs_id_t *iota_id;
+ tree_test_entry_t expected_entries[] = {
+ /* path, is_dir, contents */
+ { "A", 1, "" },
+ { "A/mu", 0, "This is the file 'mu'.\n" },
+ { "A/B", 1, "" },
+ { "A/B/lambda", 0, "This is the file 'lambda'.\n" },
+ { "A/B/E", 1, "" },
+ { "A/B/E/alpha", 0, "This is the file 'alpha'.\n" },
+ { "A/B/E/beta", 0, "This is the file 'beta'.\n" },
+ { "A/B/F", 1, "" },
+ { "A/C", 1, "" },
+ { "A/D", 1, "" },
+ { "A/D/gamma", 0, "This is the file 'gamma'.\n" },
+ { "A/D/G", 1, "" },
+ { "A/D/G/pi", 0, "This is the file 'pi'.\n" },
+ { "A/D/G/rho", 0, "This is the file 'rho'.\n" },
+ { "A/D/G/tau", 0, "This is the file 'tau'.\n" },
+ { "A/D/H", 1, "" },
+ { "A/D/H/chi", 0, "This is the file 'chi'.\n" },
+ { "A/D/H/psi", 0, "This is the file 'psi'.\n" },
+ { "A/D/H/omega", 0, "This is the file 'omega'.\n" }
+ };
+ /* Check nodes revision ID is present. */
+ SVN_ERR (svn_fs_node_id (&iota_id, txn_root, "iota", pool));
+ SVN_ERR (check_entry_present (txn_root, "", "iota"));
+ SVN_ERR (check_id_present (fs, iota_id));
+
+ SVN_ERR (svn_fs_delete_tree (txn_root, "iota", pool));
+ SVN_ERR (check_entry_absent (txn_root, "", "iota"));
+ SVN_ERR (check_id_present (fs, iota_id));
+
+ /* Validate the tree. */
+ SVN_ERR (validate_tree (txn_root, expected_entries, 19));
+ }
+
+ /* Abort transaction. */
+ SVN_ERR (svn_fs_abort_txn (txn));
+
+ /* Create new transaction. */
+ SVN_ERR (svn_fs_begin_txn (&txn, fs, new_rev, pool));
+ SVN_ERR (svn_fs_txn_root (&txn_root, txn, pool));
+
+ /* 5 */
+ {
+ svn_fs_id_t *A_id, *mu_id, *B_id, *lambda_id, *E_id, *alpha_id,
+ *beta_id, *F_id, *C_id, *D_id, *gamma_id, *H_id, *chi_id,
+ *psi_id, *omega_id, *G_id, *pi_id, *rho_id, *tau_id;
+
+ tree_test_entry_t expected_entries[] = {
+ /* path, is_dir, contents */
+ { "iota", 0, "This is the file 'iota'.\n" }
+ };
+
+ /* Check nodes revision ID is present. */
+ SVN_ERR (svn_fs_node_id (&A_id, txn_root, "/A", pool));
+ SVN_ERR (check_entry_present (txn_root, "", "A"));
+ SVN_ERR (svn_fs_node_id (&mu_id, txn_root, "/A/mu", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "mu"));
+ SVN_ERR (svn_fs_node_id (&B_id, txn_root, "/A/B", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "B"));
+ SVN_ERR (svn_fs_node_id (&lambda_id, txn_root, "/A/B/lambda", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "lambda"));
+ SVN_ERR (svn_fs_node_id (&E_id, txn_root, "/A/B/E", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "E"));
+ SVN_ERR (svn_fs_node_id (&alpha_id, txn_root, "/A/B/E/alpha", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "alpha"));
+ SVN_ERR (svn_fs_node_id (&beta_id, txn_root, "/A/B/E/beta", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B/E", "beta"));
+ SVN_ERR (svn_fs_node_id (&F_id, txn_root, "/A/B/F", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/B", "F"));
+ SVN_ERR (svn_fs_node_id (&C_id, txn_root, "/A/C", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "C"));
+ SVN_ERR (svn_fs_node_id (&D_id, txn_root, "/A/D", pool));
+ SVN_ERR (check_entry_present (txn_root, "A", "D"));
+ SVN_ERR (svn_fs_node_id (&gamma_id, txn_root, "/A/D/gamma", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "gamma"));
+ SVN_ERR (svn_fs_node_id (&H_id, txn_root, "/A/D/H", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "H"));
+ SVN_ERR (svn_fs_node_id (&chi_id, txn_root, "/A/D/H/chi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "chi"));
+ SVN_ERR (svn_fs_node_id (&psi_id, txn_root, "/A/D/H/psi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "psi"));
+ SVN_ERR (svn_fs_node_id (&omega_id, txn_root, "/A/D/H/omega", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/H", "omega"));
+ SVN_ERR (svn_fs_node_id (&G_id, txn_root, "/A/D/G", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D", "G"));
+ SVN_ERR (svn_fs_node_id (&pi_id, txn_root, "/A/D/G/pi", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "pi"));
+ SVN_ERR (svn_fs_node_id (&rho_id, txn_root, "/A/D/G/rho", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "rho"));
+ SVN_ERR (svn_fs_node_id (&tau_id, txn_root, "/A/D/G/tau", pool));
+ SVN_ERR (check_entry_present (txn_root, "A/D/G", "tau"));
+
+ SVN_ERR (svn_fs_delete_tree (txn_root, "A", pool));
+
+ SVN_ERR (check_entry_absent (txn_root, "", "A"));
+ SVN_ERR (check_id_present (fs, A_id));
+ SVN_ERR (check_id_present (fs, mu_id));
+ SVN_ERR (check_id_present (fs, B_id));
+ SVN_ERR (check_id_present (fs, lambda_id));
+ SVN_ERR (check_id_present (fs, E_id));
+ SVN_ERR (check_id_present (fs, alpha_id));
+ SVN_ERR (check_id_present (fs, beta_id));
+ SVN_ERR (check_id_present (fs, F_id));
+ SVN_ERR (check_id_present (fs, C_id));
+ SVN_ERR (check_id_present (fs, D_id));
+ SVN_ERR (check_id_present (fs, gamma_id));
+ SVN_ERR (check_id_present (fs, H_id));
+ SVN_ERR (check_id_present (fs, chi_id));
+ SVN_ERR (check_id_present (fs, psi_id));
+ SVN_ERR (check_id_present (fs, omega_id));
+ SVN_ERR (check_id_present (fs, G_id));
+ SVN_ERR (check_id_present (fs, pi_id));
+ SVN_ERR (check_id_present (fs, rho_id));
+ SVN_ERR (check_id_present (fs, tau_id));
+
+ /* Validate the tree. */
+ SVN_ERR (validate_tree (txn_root, expected_entries, 1));
+ }
+
+ /* Close the transaction and fs. */
+ SVN_ERR (svn_fs_close_txn (txn));
+ SVN_ERR (svn_fs_close_fs (fs));
return SVN_NO_ERROR;
}
@@ -3058,6 +3460,7 @@
basic_commit,
copy_test,
merging_commit,
+ delete_tree,
0
};
--
Yoshiki Hayashi
Received on Sat Oct 21 14:36:26 2006