3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
20 * ====================================================================
24 * @brief Tree elements
29 #ifndef SVN_BRANCH_ELEMENT_H
30 #define SVN_BRANCH_ELEMENT_H
32 #include <apr_pools.h>
33 #include <apr_tables.h>
35 #include "svn_types.h"
39 #endif /* __cplusplus */
42 /* ====================================================================== */
44 /** Like apr_hash_get() but the hash key is an integer. */
46 svn_eid__hash_get(apr_hash_t *ht,
49 /** Like apr_hash_set() but the hash key is an integer. */
51 svn_eid__hash_set(apr_hash_t *ht,
55 /** Like apr_hash_this_key() but the hash key is an integer. */
57 svn_eid__hash_this_key(apr_hash_index_t *hi);
59 struct svn_sort__item_t;
61 /** A hash iterator for iterating over an array or a hash table in
62 * its natural order or in sorted order.
64 * For an array, the @a i and @a val members provide the index and value
65 * of the current item.
67 typedef struct svn_eid__hash_iter_t
69 /* private: an array of (svn_sort__item_t) hash items for sorted iteration */
70 const apr_array_header_t *array;
72 /* current element: iteration order index */
74 /* current element: key */
76 /* current element: value */
78 } svn_eid__hash_iter_t;
80 svn_eid__hash_iter_t *
81 svn_eid__hash_sorted_first(apr_pool_t *pool,
83 int (*comparison_func)(const struct svn_sort__item_t *,
84 const struct svn_sort__item_t *));
86 svn_eid__hash_iter_t *
87 svn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi);
89 /** A sort ordering callback function that returns an indication whether
90 * A sorts before or after or equal to B, by comparing their keys as EIDs.
93 svn_eid__hash_sort_compare_items_by_eid(const struct svn_sort__item_t *a,
94 const struct svn_sort__item_t *b);
96 #define SVN_EID__HASH_ITER_SORTED(i, ht, comparison_func, pool) \
97 i = (void *)svn_eid__hash_sorted_first(pool, ht, comparison_func); \
99 i = (void *)svn_eid__hash_sorted_next((void *)i)
101 #define SVN_EID__HASH_ITER_SORTED_BY_EID(i, ht, pool) \
102 SVN_EID__HASH_ITER_SORTED(i, ht, svn_eid__hash_sort_compare_items_by_eid, pool)
105 /* ====================================================================== */
109 typedef struct svn_element__branch_ref_t
112 const char *branch_id;
114 } svn_element__branch_ref_t;
116 /** Versioned payload of an element, excluding tree structure information.
118 * This specifies the properties and the text of a file or target of a
119 * symlink, directly, or by reference to an existing committed element, or
120 * by a delta against such a reference payload.
122 * ### An idea: If the sender and receiver agree, the payload for an element
123 * may be specified as "null" to designate that the payload is not
124 * available. For example, when a client performing a WC update has
125 * no read authorization for a given path, the server may send null
126 * payload and the client may record an 'absent' WC node. (This
127 * would not make sense in a commit.)
129 typedef struct svn_element__payload_t svn_element__payload_t;
132 * ========================================================================
133 * Element Payload Interface
134 * ========================================================================
136 * @defgroup svn_element_payload Element payload interface
140 /** Versioned payload of a node, excluding tree structure information.
142 * Payload is described by setting fields in one of the following ways.
143 * Other fields SHOULD be null (or equivalent).
145 * by reference: (kind=unknown, ref)
146 * dir: (kind=dir, props)
147 * file: (kind=file, props, text)
148 * symlink: (kind=symlink, props, target)
150 * ### Idea for the future: Specify payload as an (optional) reference
151 * plus (optional) overrides or deltas against the reference?
153 struct svn_element__payload_t
155 /* Is this a subbranch-root element, in other words a link to a nested
156 * branch? If so, all other fields are irrelevant. */
157 svn_boolean_t is_subbranch_root;
159 /* The node kind for this payload: dir, file, symlink, or unknown. */
160 svn_node_kind_t kind;
162 /* Reference an existing, committed payload. (Use with kind=unknown if
163 * there is no content in props/text/targe fields.)
164 * The 'null' value is (SVN_INVALID_REVNUM, NULL, *). */
165 svn_element__branch_ref_t branch_ref;
167 /* The pool in which the payload's content is allocated. Used when
168 * resolving (populating the props/text/target in) a payload that was
169 * originally defined by reference. */
172 /* Properties (for kind != unknown).
173 * Maps (const char *) name -> (svn_string_t) value.
174 * An empty hash means no properties. (SHOULD NOT be NULL.)
175 * ### Presently NULL means 'no change' in some contexts. */
178 /* File text (for kind=file; otherwise SHOULD be NULL). */
179 svn_stringbuf_t *text;
181 /* Symlink target (for kind=symlink; otherwise SHOULD be NULL). */
186 /* Return true iff PAYLOAD satisfies all its invariants.
189 svn_element__payload_invariants(const svn_element__payload_t *payload);
191 /** Duplicate a node-payload @a old into @a result_pool.
193 svn_element__payload_t *
194 svn_element__payload_dup(const svn_element__payload_t *old,
195 apr_pool_t *result_pool);
197 /* Return true iff the payload of LEFT is identical to that of RIGHT.
198 * References are not supported. Node kind 'unknown' is not supported.
201 svn_element__payload_equal(const svn_element__payload_t *left,
202 const svn_element__payload_t *right,
203 apr_pool_t *scratch_pool);
205 /** Create a new node-payload object for a subbranch-root (link to a
208 * Allocate the result in @a result_pool.
210 svn_element__payload_t *
211 svn_element__payload_create_subbranch(apr_pool_t *result_pool);
213 /** Create a new node-payload object by reference to an existing payload.
215 * Set the node kind to 'unknown'.
217 * Allocate the result in @a result_pool.
219 svn_element__payload_t *
220 svn_element__payload_create_ref(svn_revnum_t rev,
221 const char *branch_id,
223 apr_pool_t *result_pool);
225 /** Create a new node-payload object for a directory node.
227 * Allocate the result in @a result_pool.
229 svn_element__payload_t *
230 svn_element__payload_create_dir(apr_hash_t *props,
231 apr_pool_t *result_pool);
233 /** Create a new node-payload object for a file node.
235 * Allocate the result in @a result_pool.
237 svn_element__payload_t *
238 svn_element__payload_create_file(apr_hash_t *props,
239 svn_stringbuf_t *text,
240 apr_pool_t *result_pool);
242 /** Create a new node-payload object for a symlink node.
244 * Allocate the result in @a result_pool.
246 svn_element__payload_t *
247 svn_element__payload_create_symlink(apr_hash_t *props,
249 apr_pool_t *result_pool);
255 * ========================================================================
256 * Element-Revision Content
257 * ========================================================================
259 * @defgroup svn_el_rev_content Element-Revision Content
263 /* The content (parent, name and payload) of an element-revision.
264 * In other words, an el-rev node in a (mixed-rev) directory-tree.
266 typedef struct svn_element__content_t
268 /* eid of the parent element, or -1 if this is the root element */
270 /* element name, or "" for root element; never null */
272 /* payload (kind, props, text, ...) */
273 svn_element__payload_t *payload;
275 } svn_element__content_t;
277 /* Return a new content object constructed with deep copies of PARENT_EID,
278 * NAME and PAYLOAD, allocated in RESULT_POOL.
280 svn_element__content_t *
281 svn_element__content_create(int parent_eid,
283 const svn_element__payload_t *payload,
284 apr_pool_t *result_pool);
286 /* Return a deep copy of OLD, allocated in RESULT_POOL.
288 svn_element__content_t *
289 svn_element__content_dup(const svn_element__content_t *old,
290 apr_pool_t *result_pool);
292 /* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */
294 svn_element__content_equal(const svn_element__content_t *content_left,
295 const svn_element__content_t *content_right,
296 apr_pool_t *scratch_pool);
302 * ========================================================================
304 * ========================================================================
306 * The elements in an Element Tree do not necessarily form a single,
307 * complete tree at all times.
309 * @defgroup svn_element_tree Element Tree
313 /* A (sub)tree of elements.
315 * An element tree is described by the content of element ROOT_EID in E_MAP,
316 * and its children (as determined by their parent links) and their names
317 * and their content recursively. For the element ROOT_EID itself, only
318 * its content is relevant; its parent and name are to be ignored.
320 * E_MAP may also contain entries that are not part of the subtree. Thus,
321 * to select a sub-subtree, it is only necessary to change ROOT_EID.
323 * The EIDs used in here may be considered either as global EIDs (known to
324 * the repo), or as local stand-alone EIDs (in their own local name-space),
325 * according to the context.
327 typedef struct svn_element__tree_t
329 /* EID -> svn_element__content_t mapping. */
332 /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */
335 } svn_element__tree_t;
337 /* Create an element tree object.
339 * The result contains a *shallow* copy of E_MAP, or a new empty mapping
342 svn_element__tree_t *
343 svn_element__tree_create(apr_hash_t *e_map,
345 apr_pool_t *result_pool);
347 svn_element__content_t *
348 svn_element__tree_get(const svn_element__tree_t *tree,
352 svn_element__tree_set(svn_element__tree_t *tree,
354 const svn_element__content_t *element);
356 /* Purge entries from E_MAP that don't connect, via parent directory hierarchy,
357 * to ROOT_EID. In other words, remove elements that have been implicitly
360 * ROOT_EID must be present in E_MAP.
362 * ### Does not detect cycles: current implementation will not purge a cycle
363 * that is disconnected from ROOT_EID. This could be a problem.
366 svn_element__tree_purge_orphans(apr_hash_t *e_map,
368 apr_pool_t *scratch_pool);
370 /* Return the subtree-relative path of element EID in TREE.
372 * If the element EID does not currently exist in TREE, return NULL.
374 * ### TODO: Clarify sequencing requirements.
377 svn_element__tree_get_path_by_eid(const svn_element__tree_t *tree,
379 apr_pool_t *result_pool);
381 /* Return the subtree rooted at EID within ELEMENT_TREE.
383 * The result is limited by the lifetime of ELEMENT_TREE. It includes a
384 * shallow copy of the mapping in ELEMENT_TREE: the hash table is
385 * duplicated but the keys and values (element content data) are not.
387 svn_element__tree_t *
388 svn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree,
390 apr_pool_t *result_pool);
397 #endif /* __cplusplus */
399 #endif /* SVN_BRANCH_ELEMENT_H */