summaryrefslogtreecommitdiff
path: root/subversion/include/private/svn_element.h
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/include/private/svn_element.h')
-rw-r--r--subversion/include/private/svn_element.h399
1 files changed, 399 insertions, 0 deletions
diff --git a/subversion/include/private/svn_element.h b/subversion/include/private/svn_element.h
new file mode 100644
index 0000000000000..c467175c748eb
--- /dev/null
+++ b/subversion/include/private/svn_element.h
@@ -0,0 +1,399 @@
+/**
+ * @copyright
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_element.h
+ * @brief Tree elements
+ *
+ * @since New in ???.
+ */
+
+#ifndef SVN_BRANCH_ELEMENT_H
+#define SVN_BRANCH_ELEMENT_H
+
+#include <apr_pools.h>
+#include <apr_tables.h>
+
+#include "svn_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* ====================================================================== */
+
+/** Like apr_hash_get() but the hash key is an integer. */
+void *
+svn_eid__hash_get(apr_hash_t *ht,
+ int key);
+
+/** Like apr_hash_set() but the hash key is an integer. */
+void
+svn_eid__hash_set(apr_hash_t *ht,
+ int key,
+ const void *val);
+
+/** Like apr_hash_this_key() but the hash key is an integer. */
+int
+svn_eid__hash_this_key(apr_hash_index_t *hi);
+
+struct svn_sort__item_t;
+
+/** A hash iterator for iterating over an array or a hash table in
+ * its natural order or in sorted order.
+ *
+ * For an array, the @a i and @a val members provide the index and value
+ * of the current item.
+ */
+typedef struct svn_eid__hash_iter_t
+{
+ /* private: an array of (svn_sort__item_t) hash items for sorted iteration */
+ const apr_array_header_t *array;
+
+ /* current element: iteration order index */
+ int i;
+ /* current element: key */
+ int eid;
+ /* current element: value */
+ void *val;
+} svn_eid__hash_iter_t;
+
+svn_eid__hash_iter_t *
+svn_eid__hash_sorted_first(apr_pool_t *pool,
+ apr_hash_t *ht,
+ int (*comparison_func)(const struct svn_sort__item_t *,
+ const struct svn_sort__item_t *));
+
+svn_eid__hash_iter_t *
+svn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi);
+
+/** A sort ordering callback function that returns an indication whether
+ * A sorts before or after or equal to B, by comparing their keys as EIDs.
+ */
+int
+svn_eid__hash_sort_compare_items_by_eid(const struct svn_sort__item_t *a,
+ const struct svn_sort__item_t *b);
+
+#define SVN_EID__HASH_ITER_SORTED(i, ht, comparison_func, pool) \
+ i = (void *)svn_eid__hash_sorted_first(pool, ht, comparison_func); \
+ i; \
+ i = (void *)svn_eid__hash_sorted_next((void *)i)
+
+#define SVN_EID__HASH_ITER_SORTED_BY_EID(i, ht, pool) \
+ SVN_EID__HASH_ITER_SORTED(i, ht, svn_eid__hash_sort_compare_items_by_eid, pool)
+
+
+/* ====================================================================== */
+
+/**
+ */
+typedef struct svn_element__branch_ref_t
+{
+ svn_revnum_t rev;
+ const char *branch_id;
+ int eid;
+} svn_element__branch_ref_t;
+
+/** Versioned payload of an element, excluding tree structure information.
+ *
+ * This specifies the properties and the text of a file or target of a
+ * symlink, directly, or by reference to an existing committed element, or
+ * by a delta against such a reference payload.
+ *
+ * ### An idea: If the sender and receiver agree, the payload for an element
+ * may be specified as "null" to designate that the payload is not
+ * available. For example, when a client performing a WC update has
+ * no read authorization for a given path, the server may send null
+ * payload and the client may record an 'absent' WC node. (This
+ * would not make sense in a commit.)
+ */
+typedef struct svn_element__payload_t svn_element__payload_t;
+
+/*
+ * ========================================================================
+ * Element Payload Interface
+ * ========================================================================
+ *
+ * @defgroup svn_element_payload Element payload interface
+ * @{
+ */
+
+/** Versioned payload of a node, excluding tree structure information.
+ *
+ * Payload is described by setting fields in one of the following ways.
+ * Other fields SHOULD be null (or equivalent).
+ *
+ * by reference: (kind=unknown, ref)
+ * dir: (kind=dir, props)
+ * file: (kind=file, props, text)
+ * symlink: (kind=symlink, props, target)
+ *
+ * ### Idea for the future: Specify payload as an (optional) reference
+ * plus (optional) overrides or deltas against the reference?
+ */
+struct svn_element__payload_t
+{
+ /* Is this a subbranch-root element, in other words a link to a nested
+ * branch? If so, all other fields are irrelevant. */
+ svn_boolean_t is_subbranch_root;
+
+ /* The node kind for this payload: dir, file, symlink, or unknown. */
+ svn_node_kind_t kind;
+
+ /* Reference an existing, committed payload. (Use with kind=unknown if
+ * there is no content in props/text/targe fields.)
+ * The 'null' value is (SVN_INVALID_REVNUM, NULL, *). */
+ svn_element__branch_ref_t branch_ref;
+
+ /* The pool in which the payload's content is allocated. Used when
+ * resolving (populating the props/text/target in) a payload that was
+ * originally defined by reference. */
+ apr_pool_t *pool;
+
+ /* Properties (for kind != unknown).
+ * Maps (const char *) name -> (svn_string_t) value.
+ * An empty hash means no properties. (SHOULD NOT be NULL.)
+ * ### Presently NULL means 'no change' in some contexts. */
+ apr_hash_t *props;
+
+ /* File text (for kind=file; otherwise SHOULD be NULL). */
+ svn_stringbuf_t *text;
+
+ /* Symlink target (for kind=symlink; otherwise SHOULD be NULL). */
+ const char *target;
+
+};
+
+/* Return true iff PAYLOAD satisfies all its invariants.
+ */
+svn_boolean_t
+svn_element__payload_invariants(const svn_element__payload_t *payload);
+
+/** Duplicate a node-payload @a old into @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_dup(const svn_element__payload_t *old,
+ apr_pool_t *result_pool);
+
+/* Return true iff the payload of LEFT is identical to that of RIGHT.
+ * References are not supported. Node kind 'unknown' is not supported.
+ */
+svn_boolean_t
+svn_element__payload_equal(const svn_element__payload_t *left,
+ const svn_element__payload_t *right,
+ apr_pool_t *scratch_pool);
+
+/** Create a new node-payload object for a subbranch-root (link to a
+ * nested branch).
+ *
+ * Allocate the result in @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_create_subbranch(apr_pool_t *result_pool);
+
+/** Create a new node-payload object by reference to an existing payload.
+ *
+ * Set the node kind to 'unknown'.
+ *
+ * Allocate the result in @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_create_ref(svn_revnum_t rev,
+ const char *branch_id,
+ int eid,
+ apr_pool_t *result_pool);
+
+/** Create a new node-payload object for a directory node.
+ *
+ * Allocate the result in @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_create_dir(apr_hash_t *props,
+ apr_pool_t *result_pool);
+
+/** Create a new node-payload object for a file node.
+ *
+ * Allocate the result in @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_create_file(apr_hash_t *props,
+ svn_stringbuf_t *text,
+ apr_pool_t *result_pool);
+
+/** Create a new node-payload object for a symlink node.
+ *
+ * Allocate the result in @a result_pool.
+ */
+svn_element__payload_t *
+svn_element__payload_create_symlink(apr_hash_t *props,
+ const char *target,
+ apr_pool_t *result_pool);
+
+/** @} */
+
+
+/*
+ * ========================================================================
+ * Element-Revision Content
+ * ========================================================================
+ *
+ * @defgroup svn_el_rev_content Element-Revision Content
+ * @{
+ */
+
+/* The content (parent, name and payload) of an element-revision.
+ * In other words, an el-rev node in a (mixed-rev) directory-tree.
+ */
+typedef struct svn_element__content_t
+{
+ /* eid of the parent element, or -1 if this is the root element */
+ int parent_eid;
+ /* element name, or "" for root element; never null */
+ const char *name;
+ /* payload (kind, props, text, ...) */
+ svn_element__payload_t *payload;
+
+} svn_element__content_t;
+
+/* Return a new content object constructed with deep copies of PARENT_EID,
+ * NAME and PAYLOAD, allocated in RESULT_POOL.
+ */
+svn_element__content_t *
+svn_element__content_create(int parent_eid,
+ const char *name,
+ const svn_element__payload_t *payload,
+ apr_pool_t *result_pool);
+
+/* Return a deep copy of OLD, allocated in RESULT_POOL.
+ */
+svn_element__content_t *
+svn_element__content_dup(const svn_element__content_t *old,
+ apr_pool_t *result_pool);
+
+/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */
+svn_boolean_t
+svn_element__content_equal(const svn_element__content_t *content_left,
+ const svn_element__content_t *content_right,
+ apr_pool_t *scratch_pool);
+
+/** @} */
+
+
+/*
+ * ========================================================================
+ * Element Tree
+ * ========================================================================
+ *
+ * The elements in an Element Tree do not necessarily form a single,
+ * complete tree at all times.
+ *
+ * @defgroup svn_element_tree Element Tree
+ * @{
+ */
+
+/* A (sub)tree of elements.
+ *
+ * An element tree is described by the content of element ROOT_EID in E_MAP,
+ * and its children (as determined by their parent links) and their names
+ * and their content recursively. For the element ROOT_EID itself, only
+ * its content is relevant; its parent and name are to be ignored.
+ *
+ * E_MAP may also contain entries that are not part of the subtree. Thus,
+ * to select a sub-subtree, it is only necessary to change ROOT_EID.
+ *
+ * The EIDs used in here may be considered either as global EIDs (known to
+ * the repo), or as local stand-alone EIDs (in their own local name-space),
+ * according to the context.
+ */
+typedef struct svn_element__tree_t
+{
+ /* EID -> svn_element__content_t mapping. */
+ apr_hash_t *e_map;
+
+ /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */
+ int root_eid;
+
+} svn_element__tree_t;
+
+/* Create an element tree object.
+ *
+ * The result contains a *shallow* copy of E_MAP, or a new empty mapping
+ * if E_MAP is null.
+ */
+svn_element__tree_t *
+svn_element__tree_create(apr_hash_t *e_map,
+ int root_eid,
+ apr_pool_t *result_pool);
+
+svn_element__content_t *
+svn_element__tree_get(const svn_element__tree_t *tree,
+ int eid);
+
+svn_error_t *
+svn_element__tree_set(svn_element__tree_t *tree,
+ int eid,
+ const svn_element__content_t *element);
+
+/* Purge entries from E_MAP that don't connect, via parent directory hierarchy,
+ * to ROOT_EID. In other words, remove elements that have been implicitly
+ * deleted.
+ *
+ * ROOT_EID must be present in E_MAP.
+ *
+ * ### Does not detect cycles: current implementation will not purge a cycle
+ * that is disconnected from ROOT_EID. This could be a problem.
+ */
+void
+svn_element__tree_purge_orphans(apr_hash_t *e_map,
+ int root_eid,
+ apr_pool_t *scratch_pool);
+
+/* Return the subtree-relative path of element EID in TREE.
+ *
+ * If the element EID does not currently exist in TREE, return NULL.
+ *
+ * ### TODO: Clarify sequencing requirements.
+ */
+const char *
+svn_element__tree_get_path_by_eid(const svn_element__tree_t *tree,
+ int eid,
+ apr_pool_t *result_pool);
+
+/* Return the subtree rooted at EID within ELEMENT_TREE.
+ *
+ * The result is limited by the lifetime of ELEMENT_TREE. It includes a
+ * shallow copy of the mapping in ELEMENT_TREE: the hash table is
+ * duplicated but the keys and values (element content data) are not.
+ */
+svn_element__tree_t *
+svn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree,
+ int eid,
+ apr_pool_t *result_pool);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_BRANCH_ELEMENT_H */