1333347Speter/** 2333347Speter * @copyright 3333347Speter * ==================================================================== 4333347Speter * Licensed to the Apache Software Foundation (ASF) under one 5333347Speter * or more contributor license agreements. See the NOTICE file 6333347Speter * distributed with this work for additional information 7333347Speter * regarding copyright ownership. The ASF licenses this file 8333347Speter * to you under the Apache License, Version 2.0 (the 9333347Speter * "License"); you may not use this file except in compliance 10333347Speter * with the License. You may obtain a copy of the License at 11333347Speter * 12333347Speter * http://www.apache.org/licenses/LICENSE-2.0 13333347Speter * 14333347Speter * Unless required by applicable law or agreed to in writing, 15333347Speter * software distributed under the License is distributed on an 16333347Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17333347Speter * KIND, either express or implied. See the License for the 18333347Speter * specific language governing permissions and limitations 19333347Speter * under the License. 20333347Speter * ==================================================================== 21333347Speter * @endcopyright 22333347Speter * 23333347Speter * @file svn_element.h 24333347Speter * @brief Tree elements 25333347Speter * 26333347Speter * @since New in ???. 27333347Speter */ 28333347Speter 29333347Speter#ifndef SVN_BRANCH_ELEMENT_H 30333347Speter#define SVN_BRANCH_ELEMENT_H 31333347Speter 32333347Speter#include <apr_pools.h> 33333347Speter#include <apr_tables.h> 34333347Speter 35333347Speter#include "svn_types.h" 36333347Speter 37333347Speter#ifdef __cplusplus 38333347Speterextern "C" { 39333347Speter#endif /* __cplusplus */ 40333347Speter 41333347Speter 42333347Speter/* ====================================================================== */ 43333347Speter 44333347Speter/** Like apr_hash_get() but the hash key is an integer. */ 45333347Spetervoid * 46333347Spetersvn_eid__hash_get(apr_hash_t *ht, 47333347Speter int key); 48333347Speter 49333347Speter/** Like apr_hash_set() but the hash key is an integer. */ 50333347Spetervoid 51333347Spetersvn_eid__hash_set(apr_hash_t *ht, 52333347Speter int key, 53333347Speter const void *val); 54333347Speter 55333347Speter/** Like apr_hash_this_key() but the hash key is an integer. */ 56333347Speterint 57333347Spetersvn_eid__hash_this_key(apr_hash_index_t *hi); 58333347Speter 59333347Speterstruct svn_sort__item_t; 60333347Speter 61333347Speter/** A hash iterator for iterating over an array or a hash table in 62333347Speter * its natural order or in sorted order. 63333347Speter * 64333347Speter * For an array, the @a i and @a val members provide the index and value 65333347Speter * of the current item. 66333347Speter */ 67333347Spetertypedef struct svn_eid__hash_iter_t 68333347Speter{ 69333347Speter /* private: an array of (svn_sort__item_t) hash items for sorted iteration */ 70333347Speter const apr_array_header_t *array; 71333347Speter 72333347Speter /* current element: iteration order index */ 73333347Speter int i; 74333347Speter /* current element: key */ 75333347Speter int eid; 76333347Speter /* current element: value */ 77333347Speter void *val; 78333347Speter} svn_eid__hash_iter_t; 79333347Speter 80333347Spetersvn_eid__hash_iter_t * 81333347Spetersvn_eid__hash_sorted_first(apr_pool_t *pool, 82333347Speter apr_hash_t *ht, 83333347Speter int (*comparison_func)(const struct svn_sort__item_t *, 84333347Speter const struct svn_sort__item_t *)); 85333347Speter 86333347Spetersvn_eid__hash_iter_t * 87333347Spetersvn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi); 88333347Speter 89333347Speter/** A sort ordering callback function that returns an indication whether 90333347Speter * A sorts before or after or equal to B, by comparing their keys as EIDs. 91333347Speter */ 92333347Speterint 93333347Spetersvn_eid__hash_sort_compare_items_by_eid(const struct svn_sort__item_t *a, 94333347Speter const struct svn_sort__item_t *b); 95333347Speter 96333347Speter#define SVN_EID__HASH_ITER_SORTED(i, ht, comparison_func, pool) \ 97333347Speter i = (void *)svn_eid__hash_sorted_first(pool, ht, comparison_func); \ 98333347Speter i; \ 99333347Speter i = (void *)svn_eid__hash_sorted_next((void *)i) 100333347Speter 101333347Speter#define SVN_EID__HASH_ITER_SORTED_BY_EID(i, ht, pool) \ 102333347Speter SVN_EID__HASH_ITER_SORTED(i, ht, svn_eid__hash_sort_compare_items_by_eid, pool) 103333347Speter 104333347Speter 105333347Speter/* ====================================================================== */ 106333347Speter 107333347Speter/** 108333347Speter */ 109333347Spetertypedef struct svn_element__branch_ref_t 110333347Speter{ 111333347Speter svn_revnum_t rev; 112333347Speter const char *branch_id; 113333347Speter int eid; 114333347Speter} svn_element__branch_ref_t; 115333347Speter 116333347Speter/** Versioned payload of an element, excluding tree structure information. 117333347Speter * 118333347Speter * This specifies the properties and the text of a file or target of a 119333347Speter * symlink, directly, or by reference to an existing committed element, or 120333347Speter * by a delta against such a reference payload. 121333347Speter * 122333347Speter * ### An idea: If the sender and receiver agree, the payload for an element 123333347Speter * may be specified as "null" to designate that the payload is not 124333347Speter * available. For example, when a client performing a WC update has 125333347Speter * no read authorization for a given path, the server may send null 126333347Speter * payload and the client may record an 'absent' WC node. (This 127333347Speter * would not make sense in a commit.) 128333347Speter */ 129333347Spetertypedef struct svn_element__payload_t svn_element__payload_t; 130333347Speter 131333347Speter/* 132333347Speter * ======================================================================== 133333347Speter * Element Payload Interface 134333347Speter * ======================================================================== 135333347Speter * 136333347Speter * @defgroup svn_element_payload Element payload interface 137333347Speter * @{ 138333347Speter */ 139333347Speter 140333347Speter/** Versioned payload of a node, excluding tree structure information. 141333347Speter * 142333347Speter * Payload is described by setting fields in one of the following ways. 143333347Speter * Other fields SHOULD be null (or equivalent). 144333347Speter * 145333347Speter * by reference: (kind=unknown, ref) 146333347Speter * dir: (kind=dir, props) 147333347Speter * file: (kind=file, props, text) 148333347Speter * symlink: (kind=symlink, props, target) 149333347Speter * 150333347Speter * ### Idea for the future: Specify payload as an (optional) reference 151333347Speter * plus (optional) overrides or deltas against the reference? 152333347Speter */ 153333347Speterstruct svn_element__payload_t 154333347Speter{ 155333347Speter /* Is this a subbranch-root element, in other words a link to a nested 156333347Speter * branch? If so, all other fields are irrelevant. */ 157333347Speter svn_boolean_t is_subbranch_root; 158333347Speter 159333347Speter /* The node kind for this payload: dir, file, symlink, or unknown. */ 160333347Speter svn_node_kind_t kind; 161333347Speter 162333347Speter /* Reference an existing, committed payload. (Use with kind=unknown if 163333347Speter * there is no content in props/text/targe fields.) 164333347Speter * The 'null' value is (SVN_INVALID_REVNUM, NULL, *). */ 165333347Speter svn_element__branch_ref_t branch_ref; 166333347Speter 167333347Speter /* The pool in which the payload's content is allocated. Used when 168333347Speter * resolving (populating the props/text/target in) a payload that was 169333347Speter * originally defined by reference. */ 170333347Speter apr_pool_t *pool; 171333347Speter 172333347Speter /* Properties (for kind != unknown). 173333347Speter * Maps (const char *) name -> (svn_string_t) value. 174333347Speter * An empty hash means no properties. (SHOULD NOT be NULL.) 175333347Speter * ### Presently NULL means 'no change' in some contexts. */ 176333347Speter apr_hash_t *props; 177333347Speter 178333347Speter /* File text (for kind=file; otherwise SHOULD be NULL). */ 179333347Speter svn_stringbuf_t *text; 180333347Speter 181333347Speter /* Symlink target (for kind=symlink; otherwise SHOULD be NULL). */ 182333347Speter const char *target; 183333347Speter 184333347Speter}; 185333347Speter 186333347Speter/* Return true iff PAYLOAD satisfies all its invariants. 187333347Speter */ 188333347Spetersvn_boolean_t 189333347Spetersvn_element__payload_invariants(const svn_element__payload_t *payload); 190333347Speter 191333347Speter/** Duplicate a node-payload @a old into @a result_pool. 192333347Speter */ 193333347Spetersvn_element__payload_t * 194333347Spetersvn_element__payload_dup(const svn_element__payload_t *old, 195333347Speter apr_pool_t *result_pool); 196333347Speter 197333347Speter/* Return true iff the payload of LEFT is identical to that of RIGHT. 198333347Speter * References are not supported. Node kind 'unknown' is not supported. 199333347Speter */ 200333347Spetersvn_boolean_t 201333347Spetersvn_element__payload_equal(const svn_element__payload_t *left, 202333347Speter const svn_element__payload_t *right, 203333347Speter apr_pool_t *scratch_pool); 204333347Speter 205333347Speter/** Create a new node-payload object for a subbranch-root (link to a 206333347Speter * nested branch). 207333347Speter * 208333347Speter * Allocate the result in @a result_pool. 209333347Speter */ 210333347Spetersvn_element__payload_t * 211333347Spetersvn_element__payload_create_subbranch(apr_pool_t *result_pool); 212333347Speter 213333347Speter/** Create a new node-payload object by reference to an existing payload. 214333347Speter * 215333347Speter * Set the node kind to 'unknown'. 216333347Speter * 217333347Speter * Allocate the result in @a result_pool. 218333347Speter */ 219333347Spetersvn_element__payload_t * 220333347Spetersvn_element__payload_create_ref(svn_revnum_t rev, 221333347Speter const char *branch_id, 222333347Speter int eid, 223333347Speter apr_pool_t *result_pool); 224333347Speter 225333347Speter/** Create a new node-payload object for a directory node. 226333347Speter * 227333347Speter * Allocate the result in @a result_pool. 228333347Speter */ 229333347Spetersvn_element__payload_t * 230333347Spetersvn_element__payload_create_dir(apr_hash_t *props, 231333347Speter apr_pool_t *result_pool); 232333347Speter 233333347Speter/** Create a new node-payload object for a file node. 234333347Speter * 235333347Speter * Allocate the result in @a result_pool. 236333347Speter */ 237333347Spetersvn_element__payload_t * 238333347Spetersvn_element__payload_create_file(apr_hash_t *props, 239333347Speter svn_stringbuf_t *text, 240333347Speter apr_pool_t *result_pool); 241333347Speter 242333347Speter/** Create a new node-payload object for a symlink node. 243333347Speter * 244333347Speter * Allocate the result in @a result_pool. 245333347Speter */ 246333347Spetersvn_element__payload_t * 247333347Spetersvn_element__payload_create_symlink(apr_hash_t *props, 248333347Speter const char *target, 249333347Speter apr_pool_t *result_pool); 250333347Speter 251333347Speter/** @} */ 252333347Speter 253333347Speter 254333347Speter/* 255333347Speter * ======================================================================== 256333347Speter * Element-Revision Content 257333347Speter * ======================================================================== 258333347Speter * 259333347Speter * @defgroup svn_el_rev_content Element-Revision Content 260333347Speter * @{ 261333347Speter */ 262333347Speter 263333347Speter/* The content (parent, name and payload) of an element-revision. 264333347Speter * In other words, an el-rev node in a (mixed-rev) directory-tree. 265333347Speter */ 266333347Spetertypedef struct svn_element__content_t 267333347Speter{ 268333347Speter /* eid of the parent element, or -1 if this is the root element */ 269333347Speter int parent_eid; 270333347Speter /* element name, or "" for root element; never null */ 271333347Speter const char *name; 272333347Speter /* payload (kind, props, text, ...) */ 273333347Speter svn_element__payload_t *payload; 274333347Speter 275333347Speter} svn_element__content_t; 276333347Speter 277333347Speter/* Return a new content object constructed with deep copies of PARENT_EID, 278333347Speter * NAME and PAYLOAD, allocated in RESULT_POOL. 279333347Speter */ 280333347Spetersvn_element__content_t * 281333347Spetersvn_element__content_create(int parent_eid, 282333347Speter const char *name, 283333347Speter const svn_element__payload_t *payload, 284333347Speter apr_pool_t *result_pool); 285333347Speter 286333347Speter/* Return a deep copy of OLD, allocated in RESULT_POOL. 287333347Speter */ 288333347Spetersvn_element__content_t * 289333347Spetersvn_element__content_dup(const svn_element__content_t *old, 290333347Speter apr_pool_t *result_pool); 291333347Speter 292333347Speter/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */ 293333347Spetersvn_boolean_t 294333347Spetersvn_element__content_equal(const svn_element__content_t *content_left, 295333347Speter const svn_element__content_t *content_right, 296333347Speter apr_pool_t *scratch_pool); 297333347Speter 298333347Speter/** @} */ 299333347Speter 300333347Speter 301333347Speter/* 302333347Speter * ======================================================================== 303333347Speter * Element Tree 304333347Speter * ======================================================================== 305333347Speter * 306333347Speter * The elements in an Element Tree do not necessarily form a single, 307333347Speter * complete tree at all times. 308333347Speter * 309333347Speter * @defgroup svn_element_tree Element Tree 310333347Speter * @{ 311333347Speter */ 312333347Speter 313333347Speter/* A (sub)tree of elements. 314333347Speter * 315333347Speter * An element tree is described by the content of element ROOT_EID in E_MAP, 316333347Speter * and its children (as determined by their parent links) and their names 317333347Speter * and their content recursively. For the element ROOT_EID itself, only 318333347Speter * its content is relevant; its parent and name are to be ignored. 319333347Speter * 320333347Speter * E_MAP may also contain entries that are not part of the subtree. Thus, 321333347Speter * to select a sub-subtree, it is only necessary to change ROOT_EID. 322333347Speter * 323333347Speter * The EIDs used in here may be considered either as global EIDs (known to 324333347Speter * the repo), or as local stand-alone EIDs (in their own local name-space), 325333347Speter * according to the context. 326333347Speter */ 327333347Spetertypedef struct svn_element__tree_t 328333347Speter{ 329333347Speter /* EID -> svn_element__content_t mapping. */ 330333347Speter apr_hash_t *e_map; 331333347Speter 332333347Speter /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */ 333333347Speter int root_eid; 334333347Speter 335333347Speter} svn_element__tree_t; 336333347Speter 337333347Speter/* Create an element tree object. 338333347Speter * 339333347Speter * The result contains a *shallow* copy of E_MAP, or a new empty mapping 340333347Speter * if E_MAP is null. 341333347Speter */ 342333347Spetersvn_element__tree_t * 343333347Spetersvn_element__tree_create(apr_hash_t *e_map, 344333347Speter int root_eid, 345333347Speter apr_pool_t *result_pool); 346333347Speter 347333347Spetersvn_element__content_t * 348333347Spetersvn_element__tree_get(const svn_element__tree_t *tree, 349333347Speter int eid); 350333347Speter 351362181Sdimvoid 352333347Spetersvn_element__tree_set(svn_element__tree_t *tree, 353333347Speter int eid, 354333347Speter const svn_element__content_t *element); 355333347Speter 356333347Speter/* Purge entries from E_MAP that don't connect, via parent directory hierarchy, 357333347Speter * to ROOT_EID. In other words, remove elements that have been implicitly 358333347Speter * deleted. 359333347Speter * 360333347Speter * ROOT_EID must be present in E_MAP. 361333347Speter * 362333347Speter * ### Does not detect cycles: current implementation will not purge a cycle 363333347Speter * that is disconnected from ROOT_EID. This could be a problem. 364333347Speter */ 365333347Spetervoid 366333347Spetersvn_element__tree_purge_orphans(apr_hash_t *e_map, 367333347Speter int root_eid, 368333347Speter apr_pool_t *scratch_pool); 369333347Speter 370333347Speter/* Return the subtree-relative path of element EID in TREE. 371333347Speter * 372333347Speter * If the element EID does not currently exist in TREE, return NULL. 373333347Speter * 374333347Speter * ### TODO: Clarify sequencing requirements. 375333347Speter */ 376333347Speterconst char * 377333347Spetersvn_element__tree_get_path_by_eid(const svn_element__tree_t *tree, 378333347Speter int eid, 379333347Speter apr_pool_t *result_pool); 380333347Speter 381333347Speter/* Return the subtree rooted at EID within ELEMENT_TREE. 382333347Speter * 383333347Speter * The result is limited by the lifetime of ELEMENT_TREE. It includes a 384333347Speter * shallow copy of the mapping in ELEMENT_TREE: the hash table is 385333347Speter * duplicated but the keys and values (element content data) are not. 386333347Speter */ 387333347Spetersvn_element__tree_t * 388333347Spetersvn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree, 389333347Speter int eid, 390333347Speter apr_pool_t *result_pool); 391333347Speter 392333347Speter/** @} */ 393333347Speter 394333347Speter 395333347Speter#ifdef __cplusplus 396333347Speter} 397333347Speter#endif /* __cplusplus */ 398333347Speter 399333347Speter#endif /* SVN_BRANCH_ELEMENT_H */ 400