📄 tree.c
字号:
apr_psprintf(pool, _("Failure opening '%s'"), path)); rest = next; here = child; } *parent_path_p = parent_path; return SVN_NO_ERROR;}/* Make the node referred to by PARENT_PATH mutable, if it isn't already, allocating from POOL. ROOT must be the root from which PARENT_PATH descends. Clone any parent directories as needed. Adjust the dag nodes in PARENT_PATH to refer to the clones. Use ERROR_PATH in error messages. */static svn_error_t *make_path_mutable(svn_fs_root_t *root, parent_path_t *parent_path, const char *error_path, apr_pool_t *pool){ dag_node_t *clone; const char *txn_id = root->txn; /* Is the node mutable already? */ if (svn_fs_fs__dag_check_mutable(parent_path->node, txn_id)) return SVN_NO_ERROR; /* Are we trying to clone the root, or somebody's child node? */ if (parent_path->parent) { const svn_fs_id_t *parent_id, *child_id, *copyroot_id; const char *copy_id = NULL; copy_id_inherit_t inherit = parent_path->copy_inherit; const char *clone_path, *copyroot_path; svn_revnum_t copyroot_rev; svn_boolean_t is_parent_copyroot = FALSE; svn_fs_root_t *copyroot_root; dag_node_t *copyroot_node; /* We're trying to clone somebody's child. Make sure our parent is mutable. */ SVN_ERR(make_path_mutable(root, parent_path->parent, error_path, pool)); switch (inherit) { case copy_id_inherit_parent: parent_id = svn_fs_fs__dag_get_id(parent_path->parent->node); copy_id = svn_fs_fs__id_copy_id(parent_id); break; case copy_id_inherit_new: SVN_ERR(svn_fs_fs__reserve_copy_id(©_id, root->fs, txn_id, pool)); break; case copy_id_inherit_self: copy_id = NULL; break; case copy_id_inherit_unknown: default: abort(); /* uh-oh -- somebody didn't calculate copy-ID inheritance data. */ } /* Determine what copyroot our new child node should use. */ SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path, parent_path->node, pool)); SVN_ERR(svn_fs_fs__revision_root(©root_root, root->fs, copyroot_rev, pool)); SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); child_id = svn_fs_fs__dag_get_id(parent_path->node); copyroot_id = svn_fs_fs__dag_get_id(copyroot_node); if (strcmp(svn_fs_fs__id_node_id(child_id), svn_fs_fs__id_node_id(copyroot_id)) != 0) is_parent_copyroot = TRUE; /* Now make this node mutable. */ clone_path = parent_path_path(parent_path->parent, pool); SVN_ERR(svn_fs_fs__dag_clone_child(&clone, parent_path->parent->node, clone_path, parent_path->entry, copy_id, txn_id, is_parent_copyroot, pool)); /* Update the path cache. */ dag_node_cache_set(root, parent_path_path(parent_path, pool), clone); } else { /* We're trying to clone the root directory. */ SVN_ERR(mutable_root_node(&clone, root, error_path, pool)); } /* Update the PARENT_PATH link to refer to the clone. */ parent_path->node = clone; return SVN_NO_ERROR;}/* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the *node we find, allocated in POOL. Return the error *SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */static svn_error_t *get_dag(dag_node_t **dag_node_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ parent_path_t *parent_path; dag_node_t *node = NULL; /* Canonicalize the input PATH. */ path = svn_fs_fs__canonicalize_abspath(path, pool); /* If ROOT is a revision root, we'll look for the DAG in our cache. */ node = dag_node_cache_get(root, path, pool); if (! node) { /* Call open_path with no flags, as we want this to return an error if the node for which we are searching doesn't exist. */ SVN_ERR(open_path(&parent_path, root, path, 0, NULL, pool)); node = parent_path->node; /* No need to cache our find -- open_path() will do that for us. */ } *dag_node_p = node; return SVN_NO_ERROR;}/* Populating the `changes' table. *//* Add a change to the changes table in FS, keyed on transaction id TXN_ID, and indicated that a change of kind CHANGE_KIND occurred on PATH (whose node revision id is--or was, in the case of a deletion--NODEREV_ID), and optionally that TEXT_MODs or PROP_MODs occurred. If the change resulted from a copy, COPYFROM_REV and COPYFROM_PATH specify under which revision and path the node was copied from. If this was not part of a copy, COPYFROM_REV should be SVN_INVALID_REVNUM. Do all this as part of POOL. */static svn_error_t *add_change(svn_fs_t *fs, const char *txn_id, const char *path, const svn_fs_id_t *noderev_id, svn_fs_path_change_kind_t change_kind, svn_boolean_t text_mod, svn_boolean_t prop_mod, svn_revnum_t copyfrom_rev, const char *copyfrom_path, apr_pool_t *pool){ SVN_ERR(svn_fs_fs__add_change(fs, txn_id, svn_fs_fs__canonicalize_abspath(path, pool), noderev_id, change_kind, text_mod, prop_mod, copyfrom_rev, copyfrom_path, pool)); return SVN_NO_ERROR;}/* Generic node operations. *//* Get the id of a node referenced by path PATH in ROOT. Return the id in *ID_P allocated in POOL. */static svn_error_t *fs_node_id(const svn_fs_id_t **id_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ fs_root_data_t *frd = root->fsap_data; if ((! root->is_txn_root) && (path[0] == '\0' || ((path[0] == '/') && (path[1] == '\0')))) { /* Optimize the case where we don't need any db access at all. The root directory ("" or "/") node is stored in the svn_fs_root_t object, and never changes when it's a revision root, so we can just reach in and grab it directly. */ *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(frd->root_dir), pool); } else { dag_node_t *node; SVN_ERR(get_dag(&node, root, path, pool)); *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool); } return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__node_created_rev(svn_revnum_t *revision, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ dag_node_t *node; SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_revision(revision, node, pool)); return SVN_NO_ERROR;}/* Set *CREATED_PATH to the path at which PATH under ROOT was created. Return a string allocated in POOL. */static svn_error_t *fs_node_created_path(const char **created_path, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ dag_node_t *node; SVN_ERR(get_dag(&node, root, path, pool)); *created_path = svn_fs_fs__dag_get_created_path(node); return SVN_NO_ERROR;}/* Set *KIND_P to the type of node located at PATH under ROOT. Perform temporary allocations in POOL. */static svn_error_t *node_kind(svn_node_kind_t *kind_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ const svn_fs_id_t *node_id; dag_node_t *node; /* Get the node id. */ SVN_ERR(fs_node_id(&node_id, root, path, pool)); /* Use the node id to get the real kind. */ SVN_ERR(svn_fs_fs__dag_get_node(&node, root->fs, node_id, pool)); *kind_p = svn_fs_fs__dag_node_kind(node); return SVN_NO_ERROR;}/* Set *KIND_P to the type of node present at PATH under ROOT. If PATH does not exist under ROOT, set *KIND_P to svn_node_none. Use POOL for temporary allocation. */svn_error_t *svn_fs_fs__check_path(svn_node_kind_t *kind_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ svn_error_t *err = node_kind(kind_p, root, path, pool); if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND)) { svn_error_clear(err); *kind_p = svn_node_none; } else if (err) { return err; } return SVN_NO_ERROR;}/* Set *VALUE_P to the value of the property named PROPNAME of PATH in ROOT. If the node has no property by that name, set *VALUE_P to zero. Allocate the result in POOL. */static svn_error_t *fs_node_prop(svn_string_t **value_p, svn_fs_root_t *root, const char *path, const char *propname, apr_pool_t *pool){ dag_node_t *node; apr_hash_t *proplist; SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool)); *value_p = NULL; if (proplist) *value_p = apr_hash_get(proplist, propname, APR_HASH_KEY_STRING); return SVN_NO_ERROR;}/* Set *TABLE_P to the entire property list of PATH under ROOT, as an APR hash table allocated in POOL. The resulting property table maps property names to pointers to svn_string_t objects containing the property value. */static svn_error_t *fs_node_proplist(apr_hash_t **table_p, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ apr_hash_t *table; dag_node_t *node; SVN_ERR(get_dag(&node, root, path, pool)); SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool)); *table_p = table ? table : apr_hash_make(pool); return SVN_NO_ERROR;}/* Change, add, or delete a node's property value. The node affect is PATH under ROOT, the property value to modify is NAME, and VALUE points to either a string value to set the new contents to, or NULL if the property should be deleted. Perform temporary allocations in POOL. */static svn_error_t *fs_change_node_prop(svn_fs_root_t *root, const char *path, const char *name, const svn_string_t *value, apr_pool_t *pool){ parent_path_t *parent_path; apr_hash_t *proplist; const char *txn_id; if (! root->is_txn_root) return not_txn(root); txn_id = root->txn; SVN_ERR(open_path(&parent_path, root, path, 0, txn_id, pool)); /* Check (non-recursively) to see if path is locked; if so, check that we can use it. */ if (root->txn_flags & SVN_FS_TXN_CHECK_LOCKS) SVN_ERR(svn_fs_fs__allow_locked_operation(path, root->fs, FALSE, FALSE, pool)); SVN_ERR(make_path_mutable(root, parent_path, path, pool)); SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, parent_path->node, pool)); /* If there's no proplist, but we're just deleting a property, exit now. */ if ((! proplist) && (! value)) return SVN_NO_ERROR; /* Now, if there's no proplist, we know we need to make one. */ if (! proplist) proplist = apr_hash_make(pool); /* Set the property. */ apr_hash_set(proplist, name, APR_HASH_KEY_STRING, value); /* Overwrite the node's proplist. */ SVN_ERR(svn_fs_fs__dag_set_proplist(parent_path->node, proplist, txn_id, pool)); /* Make a record of this modification in the changes table. */ SVN_ERR(add_change(root->fs, txn_id, path, svn_fs_fs__dag_get_id(parent_path->node), svn_fs_path_change_modify, 0, 1, SVN_INVALID_REVNUM, NULL, pool)); return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -