summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_x/dag.h
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_x/dag.h')
-rw-r--r--subversion/libsvn_fs_x/dag.h580
1 files changed, 580 insertions, 0 deletions
diff --git a/subversion/libsvn_fs_x/dag.h b/subversion/libsvn_fs_x/dag.h
new file mode 100644
index 0000000..6d5e85b
--- /dev/null
+++ b/subversion/libsvn_fs_x/dag.h
@@ -0,0 +1,580 @@
+/* dag.h : DAG-like interface filesystem, private to libsvn_fs
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_FS_DAG_H
+#define SVN_LIBSVN_FS_DAG_H
+
+#include "svn_fs.h"
+#include "svn_delta.h"
+#include "private/svn_cache.h"
+
+#include "fs.h"
+#include "id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* The interface in this file provides all the essential filesystem
+ operations, but exposes the filesystem's DAG structure. This makes
+ it simpler to implement than the public interface, since a client
+ of this interface has to understand and cope with shared structure
+ directly as it appears in the database. However, it's still a
+ self-consistent set of invariants to maintain, making it
+ (hopefully) a useful interface boundary.
+
+ In other words:
+
+ - The dag_node_t interface exposes the internal DAG structure of
+ the filesystem, while the svn_fs.h interface does any cloning
+ necessary to make the filesystem look like a tree.
+
+ - The dag_node_t interface exposes the existence of copy nodes,
+ whereas the svn_fs.h handles them transparently.
+
+ - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
+ operations make clones implicitly.
+
+ - Callers of the dag_node_t interface use Berkeley DB transactions
+ to ensure consistency between operations, while callers of the
+ svn_fs.h interface use Subversion transactions. */
+
+
+/* Generic DAG node stuff. */
+
+typedef struct dag_node_t dag_node_t;
+
+/* Fill *NODE with a dag_node_t representing node revision ID in FS,
+ allocating in RESULT_POOL. Use SCRATCH_POOL for temporaries. */
+svn_error_t *
+svn_fs_x__dag_get_node(dag_node_t **node,
+ svn_fs_t *fs,
+ const svn_fs_x__id_t *id,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Return a new dag_node_t object referring to the same node as NODE,
+ allocated in RESULT_POOL. If you're trying to build a structure in a
+ pool that wants to refer to dag nodes that may have been allocated
+ elsewhere, you can call this function and avoid inter-pool pointers. */
+dag_node_t *
+svn_fs_x__dag_dup(const dag_node_t *node,
+ apr_pool_t *result_pool);
+
+/* If NODE has been allocated in POOL, return NODE. Otherwise, return
+ a copy created in RESULT_POOL with svn_fs_fs__dag_dup. */
+dag_node_t *
+svn_fs_x__dag_copy_into_pool(dag_node_t *node,
+ apr_pool_t *result_pool);
+
+/* Serialize a DAG node, except don't try to preserve the 'fs' member.
+ Implements svn_cache__serialize_func_t */
+svn_error_t *
+svn_fs_x__dag_serialize(void **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool);
+
+/* Deserialize a DAG node, leaving the 'fs' member as NULL.
+ Implements svn_cache__deserialize_func_t */
+svn_error_t *
+svn_fs_x__dag_deserialize(void **out,
+ void *data,
+ apr_size_t data_len,
+ apr_pool_t *pool);
+
+/* Return the filesystem containing NODE. */
+svn_fs_t *
+svn_fs_x__dag_get_fs(dag_node_t *node);
+
+/* Changes the filesystem containing NODE to FS. (Used when pulling
+ nodes out of a shared cache, say.) */
+void
+svn_fs_x__dag_set_fs(dag_node_t *node,
+ svn_fs_t *fs);
+
+
+/* Return NODE's revision number. If NODE has never been committed as
+ part of a revision, set *REV to SVN_INVALID_REVNUM. */
+svn_revnum_t
+svn_fs_x__dag_get_revision(const dag_node_t *node);
+
+
+/* Return the node revision ID of NODE. The value returned is shared
+ with NODE, and will be deallocated when NODE is. */
+const svn_fs_x__id_t *
+svn_fs_x__dag_get_id(const dag_node_t *node);
+
+/* Return the node ID of NODE. The value returned is shared with NODE,
+ and will be deallocated when NODE is. */
+svn_error_t *
+svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id,
+ dag_node_t *node);
+
+/* Return the copy ID of NODE. The value returned is shared with NODE,
+ and will be deallocated when NODE is. */
+svn_error_t *
+svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id,
+ dag_node_t *node);
+
+/* Set *SAME to TRUE, if nodes LHS and RHS have the same node ID. */
+svn_error_t *
+svn_fs_x__dag_related_node(svn_boolean_t *same,
+ dag_node_t *lhs,
+ dag_node_t *rhs);
+
+/* Set *SAME to TRUE, if nodes LHS and RHS have the same node and copy IDs.
+ */
+svn_error_t *
+svn_fs_x__dag_same_line_of_history(svn_boolean_t *same,
+ dag_node_t *lhs,
+ dag_node_t *rhs);
+
+/* Return the created path of NODE. The value returned is shared
+ with NODE, and will be deallocated when NODE is. */
+const char *
+svn_fs_x__dag_get_created_path(dag_node_t *node);
+
+
+/* Set *ID_P to the node revision ID of NODE's immediate predecessor.
+ */
+svn_error_t *
+svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p,
+ dag_node_t *node);
+
+
+/* Set *COUNT to the number of predecessors NODE has (recursively).
+ */
+/* ### This function is currently only used by 'verify'. */
+svn_error_t *
+svn_fs_x__dag_get_predecessor_count(int *count,
+ dag_node_t *node);
+
+/* Set *COUNT to the number of node under NODE (inclusive) with
+ svn:mergeinfo properties.
+ */
+svn_error_t *
+svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count,
+ dag_node_t *node);
+
+/* Set *DO_THEY to a flag indicating whether or not NODE is a
+ directory with at least one descendant (not including itself) with
+ svn:mergeinfo.
+ */
+svn_error_t *
+svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
+ dag_node_t *node);
+
+/* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
+ has svn:mergeinfo set on it.
+ */
+svn_error_t *
+svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
+ dag_node_t *node);
+
+/* Return non-zero IFF NODE is currently mutable. */
+svn_boolean_t
+svn_fs_x__dag_check_mutable(const dag_node_t *node);
+
+/* Return the node kind of NODE. */
+svn_node_kind_t
+svn_fs_x__dag_node_kind(dag_node_t *node);
+
+/* Set *PROPLIST_P to a PROPLIST hash representing the entire property
+ list of NODE, allocating from POOL. The hash has const char *
+ names (the property names) and svn_string_t * values (the property
+ values).
+
+ If properties do not exist on NODE, *PROPLIST_P will be set to
+ NULL.
+
+ Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries.
+ */
+svn_error_t *
+svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p,
+ dag_node_t *node,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Set the property list of NODE to PROPLIST, allocating from POOL.
+ The node being changed must be mutable.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_set_proplist(dag_node_t *node,
+ apr_hash_t *proplist,
+ apr_pool_t *scratch_pool);
+
+/* Increment the mergeinfo_count field on NODE by INCREMENT. The node
+ being changed must be mutable.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
+ apr_int64_t increment,
+ apr_pool_t *scratch_pool);
+
+/* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO. The node
+ being changed must be mutable.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node,
+ svn_boolean_t has_mergeinfo,
+ apr_pool_t *scratch_pool);
+
+
+
+/* Revision and transaction roots. */
+
+
+/* Open the root of revision REV of filesystem FS, allocating from
+ RESULT_POOL. Set *NODE_P to the new node. Use SCRATCH_POOL for
+ temporary allocations.*/
+svn_error_t *
+svn_fs_x__dag_revision_root(dag_node_t **node_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
+ from RESULT_POOL. Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_fs_x__dag_txn_root(dag_node_t **node_p,
+ svn_fs_t *fs,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Directories. */
+
+
+/* Open the node named NAME in the directory PARENT. Set *CHILD_P to
+ the new node, allocated in RESULT_POOL. NAME must be a single path
+ component; it cannot be a slash-separated directory path. If NAME does
+ not exist within PARENT, set *CHILD_P to NULL.
+ */
+svn_error_t *
+svn_fs_x__dag_open(dag_node_t **child_p,
+ dag_node_t *parent,
+ const char *name,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names,
+ and the values are svn_fs_x__dirent_t. The returned table (and elements)
+ is allocated in RESULT_POOL, temporaries in SCRATCH_POOL. */
+svn_error_t *
+svn_fs_x__dag_dir_entries(apr_array_header_t **entries_p,
+ dag_node_t *node,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
+ from POOL. NODE must be a mutable directory. ID can refer to a
+ mutable or immutable node. If ENTRY_NAME does not exist, it will
+ be created. TXN_ID is the Subversion transaction under which this
+ occurs.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_set_entry(dag_node_t *node,
+ const char *entry_name,
+ const svn_fs_x__id_t *id,
+ svn_node_kind_t kind,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *scratch_pool);
+
+
+/* Make a new mutable clone of the node named NAME in PARENT, and
+ adjust PARENT's directory entry to point to it, unless NAME in
+ PARENT already refers to a mutable node. In either case, set
+ *CHILD_P to a reference to the new node, allocated in POOL. PARENT
+ must be mutable. NAME must be a single path component; it cannot
+ be a slash-separated directory path. PARENT_PATH must be the
+ canonicalized absolute path of the parent directory.
+
+ COPY_ID, if non-NULL, is a key into the `copies' table, and
+ indicates that this new node is being created as the result of a
+ copy operation, and specifically which operation that was.
+
+ PATH is the canonicalized absolute path at which this node is being
+ created.
+
+ TXN_ID is the Subversion transaction under which this occurs.
+
+ Allocate *CHILD_P in RESULT_POOL and use SCRATCH_POOL for temporaries.
+ */
+svn_error_t *
+svn_fs_x__dag_clone_child(dag_node_t **child_p,
+ dag_node_t *parent,
+ const char *parent_path,
+ const char *name,
+ const svn_fs_x__id_t *copy_id,
+ svn_fs_x__txn_id_t txn_id,
+ svn_boolean_t is_parent_copyroot,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/* Delete the directory entry named NAME from PARENT, allocating from
+ POOL. 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 mutable nodes
+ reachable from it. TXN_ID is the Subversion transaction under
+ which this occurs.
+
+ If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
+ PARENT.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_delete(dag_node_t *parent,
+ const char *name,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *scratch_pool);
+
+
+/* Create a new mutable directory named NAME in PARENT. Set *CHILD_P
+ to a reference to the new node, allocated in RESULT_POOL. The new
+ directory has no contents, and no properties. PARENT must be
+ mutable. NAME must be a single path component; it cannot be a
+ slash-separated directory path. PARENT_PATH must be the
+ canonicalized absolute path of the parent directory. PARENT must
+ not currently have an entry named NAME. TXN_ID is the Subversion
+ transaction under which this occurs.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_make_dir(dag_node_t **child_p,
+ dag_node_t *parent,
+ const char *parent_path,
+ const char *name,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+
+/* Files. */
+
+
+/* Set *CONTENTS to a readable generic stream which yields the
+ contents of FILE. Allocate the stream in RESULT_POOL.
+
+ If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
+ */
+svn_error_t *
+svn_fs_x__dag_get_contents(svn_stream_t **contents,
+ dag_node_t *file,
+ apr_pool_t *result_pool);
+
+/* Attempt to fetch the contents of NODE and pass it along with the BATON
+ to the PROCESSOR. Set *SUCCESS only of the data could be provided
+ and the processor had been called.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_try_process_file_contents(svn_boolean_t *success,
+ dag_node_t *node,
+ svn_fs_process_contents_func_t processor,
+ void* baton,
+ apr_pool_t *scratch_pool);
+
+
+/* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
+ the contents of TARGET, allocated in RESULT_POOL. If SOURCE is null, the
+ empty string will be used is its stead.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
+ dag_node_t *source,
+ dag_node_t *target,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Return a generic writable stream in *CONTENTS with which to set the
+ contents of FILE. Allocate the stream in RESULT_POOL.
+
+ Any previous edits on the file will be deleted, and a new edit
+ stream will be constructed.
+ */
+svn_error_t *
+svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
+ dag_node_t *file,
+ apr_pool_t *result_pool);
+
+
+/* Signify the completion of edits to FILE made using the stream
+ returned by svn_fs_x__dag_get_edit_stream.
+
+ If CHECKSUM is non-null, it must match the checksum for FILE's
+ contents (note: this is not recalculated, the recorded checksum is
+ used), else the error SVN_ERR_CHECKSUM_MISMATCH is returned.
+
+ This operation is a no-op if no edits are present.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_finalize_edits(dag_node_t *file,
+ const svn_checksum_t *checksum,
+ apr_pool_t *scratch_pool);
+
+
+/* Set *LENGTH to the length of the contents of FILE.
+ */
+svn_error_t *
+svn_fs_x__dag_file_length(svn_filesize_t *length,
+ dag_node_t *file);
+
+/* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
+ from RESULT_POOL.
+
+ If no stored checksum is available, do not calculate the checksum,
+ just put NULL into CHECKSUM.
+ */
+svn_error_t *
+svn_fs_x__dag_file_checksum(svn_checksum_t **checksum,
+ dag_node_t *file,
+ svn_checksum_kind_t kind,
+ apr_pool_t *result_pool);
+
+/* Create a new mutable file named NAME in PARENT. Set *CHILD_P to a
+ reference to the new node, allocated in RESULT_POOL. The new file's
+ contents are the empty string, and it has no properties. PARENT
+ must be mutable. NAME must be a single path component; it cannot
+ be a slash-separated directory path. PARENT_PATH must be the
+ canonicalized absolute path of the parent directory. TXN_ID is the
+ Subversion transaction under which this occurs.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_make_file(dag_node_t **child_p,
+ dag_node_t *parent,
+ const char *parent_path,
+ const char *name,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+
+/* Copies */
+
+/* Make ENTRY in TO_NODE be a copy of FROM_NODE. TO_NODE must be mutable.
+ TXN_ID is the Subversion transaction under which this occurs.
+
+ If PRESERVE_HISTORY is true, the new node will record that it was
+ copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be
+ the node found at FROM_PATH in FROM_REV, although this is not
+ checked. FROM_PATH should be canonicalized before being passed
+ here.
+
+ If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_copy(dag_node_t *to_node,
+ const char *entry,
+ dag_node_t *from_node,
+ svn_boolean_t preserve_history,
+ svn_revnum_t from_rev,
+ const char *from_path,
+ svn_fs_x__txn_id_t txn_id,
+ apr_pool_t *scratch_pool);
+
+
+/* Comparison */
+
+/* Find out what is the same between two nodes. If STRICT is FALSE,
+ this function may report false positives, i.e. report changes even
+ if the resulting contents / props are equal.
+
+ If PROPS_CHANGED is non-null, set *PROPS_CHANGED to 1 if the two
+ nodes have different property lists, or to 0 if same.
+
+ If CONTENTS_CHANGED is non-null, set *CONTENTS_CHANGED to 1 if the
+ two nodes have different contents, or to 0 if same. NODE1 and NODE2
+ must refer to files from the same filesystem.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
+ svn_boolean_t *contents_changed,
+ dag_node_t *node1,
+ dag_node_t *node2,
+ svn_boolean_t strict,
+ apr_pool_t *scratch_pool);
+
+
+/* Set *REV and *PATH to the copyroot revision and path of node NODE, or
+ to SVN_INVALID_REVNUM and NULL if no copyroot exists.
+ */
+svn_error_t *
+svn_fs_x__dag_get_copyroot(svn_revnum_t *rev,
+ const char **path,
+ dag_node_t *node);
+
+/* Set *REV to the copyfrom revision associated with NODE.
+ */
+svn_error_t *
+svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev,
+ dag_node_t *node);
+
+/* Set *PATH to the copyfrom path associated with NODE.
+ */
+svn_error_t *
+svn_fs_x__dag_get_copyfrom_path(const char **path,
+ dag_node_t *node);
+
+/* Update *TARGET so that SOURCE is it's predecessor.
+
+ Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__dag_update_ancestry(dag_node_t *target,
+ dag_node_t *source,
+ apr_pool_t *scratch_pool);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_LIBSVN_FS_DAG_H */