📄 dag.c
字号:
svn_error_t *svn_fs_fs__dag_set_entry(dag_node_t *node, const char *entry_name, const svn_fs_id_t *id, svn_node_kind_t kind, const char *txn_id, apr_pool_t *pool){ /* Check it's a directory. */ if (node->kind != svn_node_dir) return svn_error_create (SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Attempted to set entry in non-directory node")); /* Check it's mutable. */ if (! svn_fs_fs__dag_check_mutable(node, txn_id)) return svn_error_create (SVN_ERR_FS_NOT_MUTABLE, NULL, _("Attempted to set entry in immutable node")); return set_entry(node, entry_name, id, kind, txn_id, pool);}/*** Proplists. ***/svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p, dag_node_t *node, apr_pool_t *pool){ node_revision_t *noderev; apr_hash_t *proplist = NULL; SVN_ERR(get_node_revision(&noderev, node, pool)); SVN_ERR(svn_fs_fs__get_proplist(&proplist, node->fs, noderev, pool)); *proplist_p = proplist; return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node, apr_hash_t *proplist, const char *txn_id, apr_pool_t *pool){ node_revision_t *noderev; /* Sanity check: this node better be mutable! */ if (! svn_fs_fs__dag_check_mutable(node, txn_id)) { svn_string_t *idstr = svn_fs_fs__id_unparse(node->id, node->pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't set proplist on *immutable* node-revision %s", idstr->data); } /* Go get a fresh NODE-REVISION for this node. */ SVN_ERR(get_node_revision(&noderev, node, pool)); /* Set the new proplist. */ SVN_ERR(svn_fs_fs__set_proplist(node->fs, noderev, proplist, pool)); return SVN_NO_ERROR;}/*** Roots. ***/svn_error_t *svn_fs_fs__dag_revision_root(dag_node_t **node_p, svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool){ svn_fs_id_t *root_id; SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, rev, pool)); return svn_fs_fs__dag_get_node(node_p, fs, root_id, pool);}svn_error_t *svn_fs_fs__dag_txn_root(dag_node_t **node_p, svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){ const svn_fs_id_t *root_id, *ignored; SVN_ERR(svn_fs_fs__get_txn_ids(&root_id, &ignored, fs, txn_id, pool)); return svn_fs_fs__dag_get_node(node_p, fs, root_id, pool);}svn_error_t *svn_fs_fs__dag_txn_base_root(dag_node_t **node_p, svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){ const svn_fs_id_t *base_root_id, *ignored; SVN_ERR(svn_fs_fs__get_txn_ids(&ignored, &base_root_id, fs, txn_id, pool)); return svn_fs_fs__dag_get_node(node_p, fs, base_root_id, pool);}svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p, dag_node_t *parent, const char *parent_path, const char *name, const char *copy_id, const char *txn_id, svn_boolean_t is_parent_copyroot, apr_pool_t *pool){ dag_node_t *cur_entry; /* parent's current entry named NAME */ const svn_fs_id_t *new_node_id; /* node id we'll put into NEW_NODE */ svn_fs_t *fs = svn_fs_fs__dag_get_fs(parent); /* First check that the parent is mutable. */ if (! svn_fs_fs__dag_check_mutable(parent, txn_id)) return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Attempted to clone child of non-mutable node"); /* 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 make a child clone with an illegal name '%s'", name); /* Find the node named NAME in PARENT's entries list if it exists. */ SVN_ERR(svn_fs_fs__dag_open(&cur_entry, parent, name, pool)); /* Check for mutability in the node we found. If it's mutable, we don't need to clone it. */ if (svn_fs_fs__dag_check_mutable(cur_entry, txn_id)) { /* This has already been cloned */ new_node_id = cur_entry->id; } else { node_revision_t *noderev, *parent_noderev; /* Go get a fresh NODE-REVISION for current child node. */ SVN_ERR(get_node_revision(&noderev, cur_entry, pool)); if (is_parent_copyroot) { SVN_ERR(get_node_revision(&parent_noderev, parent, pool)); noderev->copyroot_rev = parent_noderev->copyroot_rev; noderev->copyroot_path = apr_pstrdup(pool, parent_noderev->copyroot_path); } noderev->copyfrom_path = NULL; noderev->copyfrom_rev = SVN_INVALID_REVNUM; noderev->predecessor_id = svn_fs_fs__id_copy(cur_entry->id, pool); if (noderev->predecessor_count != -1) noderev->predecessor_count++; noderev->created_path = svn_path_join(parent_path, name, pool); SVN_ERR(svn_fs_fs__create_successor(&new_node_id, fs, cur_entry->id, noderev, copy_id, txn_id, pool)); /* Replace the ID in the parent's ENTRY list with the ID which refers to the mutable clone of this child. */ SVN_ERR(set_entry(parent, name, new_node_id, noderev->kind, txn_id, pool)); } /* Initialize the youngster. */ return svn_fs_fs__dag_get_node(child_p, fs, new_node_id, pool);}svn_error_t *svn_fs_fs__dag_clone_root(dag_node_t **root_p, svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){ const svn_fs_id_t *base_root_id, *root_id; /* Get the node ID's of the root directories of the transaction and its base revision. */ SVN_ERR(svn_fs_fs__get_txn_ids(&root_id, &base_root_id, fs, txn_id, pool)); /* Oh, give me a clone... (If they're the same, we haven't cloned the transaction's root directory yet.) */ if (svn_fs_fs__id_eq(root_id, base_root_id)) { abort(); } /* One way or another, root_id now identifies a cloned root node. */ SVN_ERR(svn_fs_fs__dag_get_node(root_p, fs, root_id, 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, allocating from POOL. 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_fs__dag_delete(dag_node_t *parent, const char *name, const char *txn_id, apr_pool_t *pool){ node_revision_t *parent_noderev; apr_hash_t *entries; svn_fs_t *fs = parent->fs; svn_fs_dirent_t *dirent; svn_fs_id_t *id; 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_fs__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(get_node_revision(&parent_noderev, parent, pool)); /* Get a dirent hash for this directory. */ SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, parent_noderev, pool)); /* Find name in the ENTRIES hash. */ dirent = 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 (! dirent) return svn_error_createf (SVN_ERR_FS_NO_SUCH_ENTRY, NULL, "Delete failed--directory has no entry '%s'", name); /* Stash a copy of the ID, since dirent will become invalid during svn_fs_fs__dag_delete_if_mutable. */ id = svn_fs_fs__id_copy(dirent->id, pool); /* Use the ID to get the entry's node. */ SVN_ERR(svn_fs_fs__dag_get_node(&node, svn_fs_fs__dag_get_fs(parent), id, pool)); /* If mutable, remove it and any mutable children from db. */ SVN_ERR(svn_fs_fs__dag_delete_if_mutable(parent->fs, id, txn_id, pool)); /* Remove this entry from its parent's entries list. */ SVN_ERR(svn_fs_fs__set_entry(parent->fs, txn_id, parent_noderev, name, NULL, svn_node_unknown, pool)); return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__dag_remove_node(svn_fs_t *fs, const svn_fs_id_t *id, const char *txn_id, apr_pool_t *pool){ dag_node_t *node; /* Fetch the node. */ SVN_ERR(svn_fs_fs__dag_get_node(&node, fs, id, pool)); /* If immutable, do nothing and return immediately. */ if (! svn_fs_fs__dag_check_mutable(node, txn_id)) return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL, "Attempted removal of immutable node"); /* Delete the node revision. */ SVN_ERR(svn_fs_fs__delete_node_revision(fs, id, pool)); return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__dag_delete_if_mutable(svn_fs_t *fs, const svn_fs_id_t *id, const char *txn_id, apr_pool_t *pool){ dag_node_t *node; /* Get the node. */ SVN_ERR(svn_fs_fs__dag_get_node(&node, fs, id, pool)); /* If immutable, do nothing and return immediately. */ if (! svn_fs_fs__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_fs__dag_dir_entries(&entries, node, pool)); entries = svn_fs_fs__copy_dir_entries(entries, pool); if (entries) { 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_fs__dag_delete_if_mutable(fs, dirent->id, txn_id, pool)); } } } /* ... then delete the node itself, after deleting any mutable representations and strings it points to. */ SVN_ERR(svn_fs_fs__dag_remove_node(fs, id, txn_id, pool)); return SVN_NO_ERROR;}svn_error_t *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -