diff options
Diffstat (limited to 'subversion/include/private/svn_element.h')
-rw-r--r-- | subversion/include/private/svn_element.h | 399 |
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 */ |