📄 dag.c
字号:
}svn_error_t *svn_fs_base__dag_clone_root(dag_node_t **root_p, svn_fs_t *fs, const char *txn_id, trail_t *trail, apr_pool_t *pool){ const svn_fs_id_t *base_root_id, *root_id; node_revision_t *noderev; /* Get the node ID's of the root directories of the transaction and its base revision. */ SVN_ERR(svn_fs_base__get_txn_ids(&root_id, &base_root_id, fs, txn_id, trail, pool)); /* Oh, give me a clone... (If they're the same, we haven't cloned the transaction's root directory yet.) */ if (svn_fs_base__id_eq(root_id, base_root_id)) { const char *base_copy_id = svn_fs_base__id_copy_id(base_root_id); /* Of my own flesh and bone... (Get the NODE-REVISION for the base node, and then write it back out as the clone.) */ SVN_ERR(svn_fs_bdb__get_node_revision(&noderev, fs, base_root_id, trail, pool)); /* Store it. */ /* ### todo: Does it even makes sense to have a different copy id for the root node? That is, does this function need a copy_id passed in? */ noderev->predecessor_id = svn_fs_base__id_copy(base_root_id, pool); if (noderev->predecessor_count != -1) noderev->predecessor_count++; SVN_ERR(svn_fs_base__create_successor(&root_id, fs, base_root_id, noderev, base_copy_id, txn_id, trail, pool)); /* ... And when it is grown * Then my own little clone * Will be of the opposite sex! */ SVN_ERR(svn_fs_base__set_txn_root(fs, txn_id, root_id, trail, pool)); } /* One way or another, root_id now identifies a cloned root node. */ SVN_ERR(svn_fs_base__dag_get_node(root_p, fs, root_id, trail, pool)); /* * (Sung to the tune of "Home, Home on the Range", with thanks to * Randall Garrett and Isaac Asimov.) */ return SVN_NO_ERROR;}/* 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 a directory, it must be empty. If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in PARENT. */svn_error_t *svn_fs_base__dag_delete(dag_node_t *parent, const char *name, const char *txn_id, trail_t *trail, apr_pool_t *pool){ node_revision_t *parent_noderev; const char *rep_key, *mutable_rep_key; apr_hash_t *entries = NULL; skel_t *entries_skel; svn_fs_t *fs = parent->fs; svn_string_t str; svn_fs_id_t *id = NULL; dag_node_t *node; /* Make sure parent is a directory. */ if (parent->kind != svn_node_dir) return svn_error_createf (SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Attempted to delete entry '%s' from *non*-directory node"), name); /* Make sure parent is mutable. */ if (! svn_fs_base__dag_check_mutable(parent, txn_id)) return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, _("Attempted to delete entry '%s' from immutable directory node"), name); /* Make sure that NAME is a single path component. */ if (! svn_path_is_single_path_component(name)) return svn_error_createf (SVN_ERR_FS_NOT_SINGLE_PATH_COMPONENT, NULL, _("Attempted to delete a node with an illegal name '%s'"), name); /* Get a fresh NODE-REVISION for the parent node. */ SVN_ERR(svn_fs_bdb__get_node_revision(&parent_noderev, fs, parent->id, trail, pool)); /* Get the key for the parent's entries list (data) representation. */ rep_key = parent_noderev->data_key; /* No REP_KEY means no representation, and no representation means no data, and no data means no entries...there's nothing here to delete! */ if (! rep_key) return svn_error_createf (SVN_ERR_FS_NO_SUCH_ENTRY, NULL, _("Delete failed: directory has no entry '%s'"), name); /* Ensure we have a key to a mutable representation of the entries list. We'll have to update the NODE-REVISION if it points to an immutable version. */ SVN_ERR(svn_fs_base__get_mutable_rep(&mutable_rep_key, rep_key, fs, txn_id, trail, pool)); if (! svn_fs_base__same_keys(mutable_rep_key, rep_key)) { parent_noderev->data_key = mutable_rep_key; SVN_ERR(svn_fs_bdb__put_node_revision(fs, parent->id, parent_noderev, trail, pool)); } /* Read the representation, then use it to get the string that holds the entries list. Parse that list into a skel, and parse *that* into a hash. */ SVN_ERR(svn_fs_base__rep_contents(&str, fs, rep_key, trail, pool)); entries_skel = svn_fs_base__parse_skel(str.data, str.len, pool); if (entries_skel) SVN_ERR(svn_fs_base__parse_entries_skel(&entries, entries_skel, pool)); /* Find NAME in the ENTRIES skel. */ if (entries) id = apr_hash_get(entries, name, APR_HASH_KEY_STRING); /* If we never found ID in ENTRIES (perhaps because there are no ENTRIES, perhaps because ID just isn't in the existing ENTRIES ... it doesn't matter), return an error. */ if (! id) return svn_error_createf (SVN_ERR_FS_NO_SUCH_ENTRY, NULL, _("Delete failed: directory has no entry '%s'"), name); /* Use the ID of this ENTRY to get the entry's node. */ SVN_ERR(svn_fs_base__dag_get_node(&node, svn_fs_base__dag_get_fs(parent), id, trail, pool)); /* If mutable, remove it and any mutable children from db. */ SVN_ERR(svn_fs_base__dag_delete_if_mutable(parent->fs, id, txn_id, trail, pool)); /* Remove this entry from its parent's entries list. */ apr_hash_set(entries, name, APR_HASH_KEY_STRING, NULL); /* Replace the old entries list with the new one. */ { svn_stream_t *ws; svn_stringbuf_t *unparsed_entries; apr_size_t len; SVN_ERR(svn_fs_base__unparse_entries_skel(&entries_skel, entries, pool)); unparsed_entries = svn_fs_base__unparse_skel(entries_skel, pool); SVN_ERR(svn_fs_base__rep_contents_write_stream(&ws, fs, mutable_rep_key, txn_id, TRUE, trail, pool)); len = unparsed_entries->len; SVN_ERR(svn_stream_write(ws, unparsed_entries->data, &len)); SVN_ERR(svn_stream_close(ws)); } return SVN_NO_ERROR;}svn_error_t *svn_fs_base__dag_remove_node(svn_fs_t *fs, const svn_fs_id_t *id, const char *txn_id, trail_t *trail, apr_pool_t *pool){ dag_node_t *node; node_revision_t *noderev; /* Fetch the node. */ SVN_ERR(svn_fs_base__dag_get_node(&node, fs, id, trail, pool)); /* If immutable, do nothing and return immediately. */ if (! svn_fs_base__dag_check_mutable(node, txn_id)) return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL, _("Attempted removal of immutable node")); /* Get a fresh node-revision. */ SVN_ERR(svn_fs_bdb__get_node_revision(&noderev, fs, id, trail, pool)); /* Delete any mutable property representation. */ if (noderev->prop_key) SVN_ERR(svn_fs_base__delete_rep_if_mutable(fs, noderev->prop_key, txn_id, trail, pool)); /* Delete any mutable data representation. */ if (noderev->data_key) SVN_ERR(svn_fs_base__delete_rep_if_mutable(fs, noderev->data_key, txn_id, trail, pool)); /* Delete any mutable edit representation (files only). */ if (noderev->edit_key) SVN_ERR(svn_fs_base__delete_rep_if_mutable(fs, noderev->edit_key, txn_id, trail, pool)); /* Delete the node revision itself. */ SVN_ERR(svn_fs_base__delete_node_revision(fs, id, trail, pool)); return SVN_NO_ERROR;}svn_error_t *svn_fs_base__dag_delete_if_mutable(svn_fs_t *fs, const svn_fs_id_t *id, const char *txn_id, trail_t *trail, apr_pool_t *pool){ dag_node_t *node; /* Get the node. */ SVN_ERR(svn_fs_base__dag_get_node(&node, fs, id, trail, pool)); /* If immutable, do nothing and return immediately. */ if (! svn_fs_base__dag_check_mutable(node, txn_id)) return SVN_NO_ERROR; /* Else it's mutable. Recurse on directories... */ if (node->kind == svn_node_dir) { apr_hash_t *entries; apr_hash_index_t *hi; /* Loop over hash entries */ SVN_ERR(svn_fs_base__dag_dir_entries(&entries, node, trail, pool)); if (entries) { apr_pool_t *subpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi)) { void *val; svn_fs_dirent_t *dirent; apr_hash_this(hi, NULL, NULL, &val); dirent = val; SVN_ERR(svn_fs_base__dag_delete_if_mutable(fs, dirent->id, txn_id, trail, subpool)); } } } /* ... then delete the node itself, after deleting any mutable representations and strings it points to. */ SVN_ERR(svn_fs_base__dag_remove_node(fs, id, txn_id, trail, pool)); return SVN_NO_ERROR;}svn_error_t *svn_fs_base__dag_make_file(dag_node_t **child_p, dag_node_t *parent, const char *parent_path, const char *name, const char *txn_id, trail_t *trail, apr_pool_t *pool){ /* Call our little helper function */ return make_entry(child_p, parent, parent_path, name, FALSE, txn_id, trail, pool);}svn_error_t *svn_fs_base__dag_make_dir(dag_node_t **child_p, dag_node_t *parent, const char *parent_path, const char *name, const char *txn_id, trail_t *trail, apr_pool_t *pool){ /* Call our little helper function */ return make_entry(child_p, parent, parent_path, name, TRUE, txn_id, trail, pool);}svn_error_t *svn_fs_base__dag_get_contents(svn_stream_t **contents, dag_node_t *file, trail_t *trail, apr_pool_t *pool){ node_revision_t *noderev; /* Make sure our node is a file. */ if (file->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, _("Attempted to get textual contents of a *non*-file node")); /* Go get a fresh node-revision for FILE. */ SVN_ERR(svn_fs_bdb__get_node_revision(&noderev, file->fs, file->id, trail, pool)); /* Our job is to _return_ a stream on the file's contents, so the stream has to be trail-independent. Here, we pass NULL to tell the stream that we're not providing it a trail that lives across reads. This means the stream will do each read in a one-off, temporary trail. */ SVN_ERR(svn_fs_base__rep_contents_read_stream(contents, file->fs, noderev->data_key, FALSE, trail, pool)); /* Note that we're not registering any `close' func, because there's nothing to cleanup outside of our trail. When the trail is freed, the stream/baton will be too. */ return SVN_NO_ERROR;}svn_error_t *svn_fs_base__dag_file_length(svn_filesize_t *length, dag_node_t *file, trail_t *trail, apr_pool_t *pool){ node_revision_t *noderev; /* Make sure our node is a file. */ if (file->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, _("Attempted to get length of a *non*-file node")); /* Go get a fresh node-revision for FILE, and . */ SVN_ERR(svn_fs_bdb__get_node_revision(&noderev, file->fs, file->id, trail, pool)); if (noderev->data_key) SVN_ERR(svn_fs_base__rep_contents_size(length, file->fs, noderev->data_key, trail, pool)); else *length = 0; return SVN_NO_ERROR;}svn_error_t *svn_fs_base__dag_file_checksum(unsigned char digest[], dag_node_t *file, trail_t *trail, apr_pool_t *pool){ node_revision_t *noderev; if (file->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, _("Attempted to get checksum of a *non*-file node"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -