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