aboutsummaryrefslogtreecommitdiff
path: root/subversion/include/private/svn_element.h
blob: c467175c748eb7dd031d10349c67ddbe53f1f80d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
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 */