Change the format of the revprops block sent in svnserve for
[svn.git] / subversion / libsvn_fs_fs / dag.h
blob7a2c4a4f8d7cdab4137bc1daebafdcc719841af5
1 /* dag.h : DAG-like interface filesystem, private to libsvn_fs
3 * ====================================================================
4 * Copyright (c) 2000-2006 CollabNet. All rights reserved.
6 * This software is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at http://subversion.tigris.org/license-1.html.
9 * If newer versions of this license are posted there, you may use a
10 * newer version instead, at your option.
12 * This software consists of voluntary contributions made by many
13 * individuals. For exact contribution history, see the revision
14 * history and logs, available at http://subversion.tigris.org/.
15 * ====================================================================
18 #ifndef SVN_LIBSVN_FS_DAG_H
19 #define SVN_LIBSVN_FS_DAG_H
21 #include "svn_fs.h"
22 #include "svn_delta.h"
24 #include "fs.h"
26 #ifdef __cplusplus
27 extern "C" {
28 #endif /* __cplusplus */
31 /* The interface in this file provides all the essential filesystem
32 operations, but exposes the filesystem's DAG structure. This makes
33 it simpler to implement than the public interface, since a client
34 of this interface has to understand and cope with shared structure
35 directly as it appears in the database. However, it's still a
36 self-consistent set of invariants to maintain, making it
37 (hopefully) a useful interface boundary.
39 In other words:
41 - The dag_node_t interface exposes the internal DAG structure of
42 the filesystem, while the svn_fs.h interface does any cloning
43 necessary to make the filesystem look like a tree.
45 - The dag_node_t interface exposes the existence of copy nodes,
46 whereas the svn_fs.h handles them transparently.
48 - dag_node_t's must be explicitly cloned, whereas the svn_fs.h
49 operations make clones implicitly.
51 - Callers of the dag_node_t interface use Berkeley DB transactions
52 to ensure consistency between operations, while callers of the
53 svn_fs.h interface use Subversion transactions. */
56 /* Generic DAG node stuff. */
59 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
60 allocating in POOL. */
61 svn_error_t *
62 svn_fs_fs__dag_get_node(dag_node_t **node,
63 svn_fs_t *fs,
64 const svn_fs_id_t *id,
65 apr_pool_t *pool);
68 /* Return a new dag_node_t object referring to the same node as NODE,
69 allocated in POOL. If you're trying to build a structure in a
70 pool that wants to refer to dag nodes that may have been allocated
71 elsewhere, you can call this function and avoid inter-pool pointers. */
72 dag_node_t *svn_fs_fs__dag_dup(dag_node_t *node,
73 apr_pool_t *pool);
76 /* Return the filesystem containing NODE. */
77 svn_fs_t *svn_fs_fs__dag_get_fs(dag_node_t *node);
80 /* Set *REV to NODE's revision number, allocating in POOL. If NODE
81 has never been committed as part of a revision, set *REV to
82 SVN_INVALID_REVNUM. */
83 svn_error_t *svn_fs_fs__dag_get_revision(svn_revnum_t *rev,
84 dag_node_t *node,
85 apr_pool_t *pool);
88 /* Return the node revision ID of NODE. The value returned is shared
89 with NODE, and will be deallocated when NODE is. */
90 const svn_fs_id_t *svn_fs_fs__dag_get_id(dag_node_t *node);
93 /* Return the created path of NODE. The value returned is shared
94 with NODE, and will be deallocated when NODE is. */
95 const char *svn_fs_fs__dag_get_created_path(dag_node_t *node);
98 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
99 or NULL if NODE has no predecessor, allocating from POOL. */
100 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
101 dag_node_t *node,
102 apr_pool_t *pool);
105 /* Set *COUNT to the number of predecessors NODE has (recursively), or
106 -1 if not known, allocating from POOL. */
107 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
108 dag_node_t *node,
109 apr_pool_t *pool);
111 /* Set *COUNT to the number of node under NODE (inclusive) with
112 svn:mergeinfo properties, allocating from POOL. */
113 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
114 dag_node_t *node,
115 apr_pool_t *pool);
117 /* Set *DO_THEY to a flag indicating whether or not NODE is a
118 directory with at least one descendant (not including itself) with
119 svn:mergeinfo. */
120 svn_error_t *
121 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
122 dag_node_t *node,
123 apr_pool_t *pool);
125 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
126 has svn:mergeinfo set on it. */
127 svn_error_t *
128 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
129 dag_node_t *node,
130 apr_pool_t *pool);
132 /* Return non-zero IFF NODE is currently mutable. */
133 svn_boolean_t svn_fs_fs__dag_check_mutable(dag_node_t *node);
135 /* Return the node kind of NODE. */
136 svn_node_kind_t svn_fs_fs__dag_node_kind(dag_node_t *node);
138 /* Set *PROPLIST_P to a PROPLIST hash representing the entire property
139 list of NODE, allocating from POOL. The hash has const char *
140 names (the property names) and svn_string_t * values (the property
141 values).
143 If properties do not exist on NODE, *PROPLIST_P will be set to
144 NULL. */
145 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
146 dag_node_t *node,
147 apr_pool_t *pool);
149 /* Set the property list of NODE to PROPLIST, allocating from POOL.
150 The node being changed must be mutable. */
151 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
152 apr_hash_t *proplist,
153 apr_pool_t *pool);
155 /* Increment the mergeinfo_count field on NODE by INCREMENT. The node
156 being changed must be mutable. */
157 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
158 apr_int64_t increment,
159 apr_pool_t *pool);
161 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO. The node
162 being changed must be mutable. */
163 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
164 svn_boolean_t has_mergeinfo,
165 apr_pool_t *pool);
169 /* Revision and transaction roots. */
172 /* Open the root of revision REV of filesystem FS, allocating from
173 POOL. Set *NODE_P to the new node. */
174 svn_error_t *svn_fs_fs__dag_revision_root(dag_node_t **node_p,
175 svn_fs_t *fs,
176 svn_revnum_t rev,
177 apr_pool_t *pool);
180 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
181 from POOL.
183 Note that the root node of TXN_ID is not necessarily mutable. If
184 no changes have been made in the transaction, then it may share its
185 root directory with its base revision. To get a mutable root node
186 for a transaction, call svn_fs_fs__dag_clone_root. */
187 svn_error_t *svn_fs_fs__dag_txn_root(dag_node_t **node_p,
188 svn_fs_t *fs,
189 const char *txn_id,
190 apr_pool_t *pool);
193 /* Set *NODE_P to the base root of transaction TXN_ID in FS,
194 allocating from POOL. Allocate the node in TRAIL->pool. */
195 svn_error_t *svn_fs_fs__dag_txn_base_root(dag_node_t **node_p,
196 svn_fs_t *fs,
197 const char *txn_id,
198 apr_pool_t *pool);
201 /* Clone the root directory of TXN_ID in FS, and update the
202 `transactions' table entry to point to it, unless this has been
203 done already. In either case, set *ROOT_P to a reference to the
204 root directory clone. Allocate *ROOT_P in POOL. */
205 svn_error_t *svn_fs_fs__dag_clone_root(dag_node_t **root_p,
206 svn_fs_t *fs,
207 const char *txn_id,
208 apr_pool_t *pool);
212 /* Directories. */
215 /* Open the node named NAME in the directory PARENT. Set *CHILD_P to
216 the new node, allocated in POOL. NAME must be a single path
217 component; it cannot be a slash-separated directory path. */
218 svn_error_t *svn_fs_fs__dag_open(dag_node_t **child_p,
219 dag_node_t *parent,
220 const char *name,
221 apr_pool_t *pool);
224 /* Set *ENTRIES_P to a hash table of NODE's entries. The keys of the
225 table are entry names, and the values are svn_fs_dirent_t's. The
226 returned table (and its keys and values) is allocated in POOL,
227 which is also used for temporary allocations. NODE_POOL is used
228 for any allocation of memory that needs to live as long as NODE
229 lives. */
230 svn_error_t *svn_fs_fs__dag_dir_entries(apr_hash_t **entries_p,
231 dag_node_t *node,
232 apr_pool_t *pool,
233 apr_pool_t *node_pool);
236 /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
237 from POOL. NODE must be a mutable directory. ID can refer to a
238 mutable or immutable node. If ENTRY_NAME does not exist, it will
239 be created. TXN_ID is the Subversion transaction under which this
240 occurs.*/
241 svn_error_t *svn_fs_fs__dag_set_entry(dag_node_t *node,
242 const char *entry_name,
243 const svn_fs_id_t *id,
244 svn_node_kind_t kind,
245 const char *txn_id,
246 apr_pool_t *pool);
249 /* Make a new mutable clone of the node named NAME in PARENT, and
250 adjust PARENT's directory entry to point to it, unless NAME in
251 PARENT already refers to a mutable node. In either case, set
252 *CHILD_P to a reference to the new node, allocated in POOL. PARENT
253 must be mutable. NAME must be a single path component; it cannot
254 be a slash-separated directory path. PARENT_PATH must be the
255 canonicalized absolute path of the parent directory.
257 COPY_ID, if non-NULL, is a key into the `copies' table, and
258 indicates that this new node is being created as the result of a
259 copy operation, and specifically which operation that was.
261 PATH is the canonicalized absolute path at which this node is being
262 created.
264 TXN_ID is the Subversion transaction under which this occurs. */
265 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
266 dag_node_t *parent,
267 const char *parent_path,
268 const char *name,
269 const char *copy_id,
270 const char *txn_id,
271 svn_boolean_t is_parent_copyroot,
272 apr_pool_t *pool);
275 /* Delete the directory entry named NAME from PARENT, allocating from
276 POOL. PARENT must be mutable. NAME must be a single path
277 component; it cannot be a slash-separated directory path. If the
278 node being deleted is a mutable directory, remove all mutable nodes
279 reachable from it. TXN_ID is the Subversion transaction under
280 which this occurs.
282 If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
283 PARENT. */
284 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
285 const char *name,
286 const char *txn_id,
287 apr_pool_t *pool);
290 /* Delete the node revision assigned to node ID from FS's `nodes'
291 table, allocating from POOL. Also delete any mutable
292 representations and strings associated with that node revision. ID
293 may refer to a file or directory, which must be mutable.
295 NOTE: If ID represents a directory, and that directory has mutable
296 children, you risk orphaning those children by leaving them
297 dangling, disconnected from all DAG trees. It is assumed that
298 callers of this interface know what in the world they are doing. */
299 svn_error_t *svn_fs_fs__dag_remove_node(svn_fs_t *fs,
300 const svn_fs_id_t *id,
301 apr_pool_t *pool);
304 /* Delete all mutable node revisions reachable from node ID, including
305 ID itself, from FS's `nodes' table, allocating from POOL. Also
306 delete any mutable representations and strings associated with that
307 node revision. ID may refer to a file or directory, which may be
308 mutable or immutable. */
309 svn_error_t *svn_fs_fs__dag_delete_if_mutable(svn_fs_t *fs,
310 const svn_fs_id_t *id,
311 apr_pool_t *pool);
314 /* Create a new mutable directory named NAME in PARENT. Set *CHILD_P
315 to a reference to the new node, allocated in POOL. The new
316 directory has no contents, and no properties. PARENT must be
317 mutable. NAME must be a single path component; it cannot be a
318 slash-separated directory path. PARENT_PATH must be the
319 canonicalized absolute path of the parent directory. PARENT must
320 not currently have an entry named NAME. Do any temporary
321 allocation in POOL. TXN_ID is the Subversion transaction under
322 which this occurs. */
323 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
324 dag_node_t *parent,
325 const char *parent_path,
326 const char *name,
327 const char *txn_id,
328 apr_pool_t *pool);
332 /* Files. */
335 /* Set *CONTENTS to a readable generic stream which yields the
336 contents of FILE. Allocate the stream in POOL.
338 If FILE is not a file, return SVN_ERR_FS_NOT_FILE. */
339 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
340 dag_node_t *file,
341 apr_pool_t *pool);
344 /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
345 the contents of TARGET, allocated in POOL. If SOURCE is null, the empty
346 string will be used. */
347 svn_error_t *
348 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
349 dag_node_t *source,
350 dag_node_t *target,
351 apr_pool_t *pool);
353 /* Return a generic writable stream in *CONTENTS with which to set the
354 contents of FILE. Allocate the stream in POOL.
356 Any previous edits on the file will be deleted, and a new edit
357 stream will be constructed. */
358 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
359 dag_node_t *file,
360 apr_pool_t *pool);
363 /* Signify the completion of edits to FILE made using the stream
364 returned by svn_fs_fs__dag_get_edit_stream, allocating from POOL.
366 If CHECKSUM is non-null, it must match the checksum for FILE's
367 contents (note: this is not recalculated, the recorded checksum is
368 used), else the error SVN_ERR_CHECKSUM_MISMATCH is returned.
370 This operation is a no-op if no edits are present. */
371 svn_error_t *svn_fs_fs__dag_finalize_edits(dag_node_t *file,
372 const char *checksum,
373 apr_pool_t *pool);
376 /* Set *LENGTH to the length of the contents of FILE, allocating from
377 POOL. */
378 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
379 dag_node_t *file,
380 apr_pool_t *pool);
382 /* Put the recorded MD5 checksum of FILE into DIGEST, allocating from
383 * POOL. DIGEST must point to APR_MD5_DIGESTSIZE bytes of storage.
385 * If no stored checksum is available, do not calculate the checksum,
386 * just put all 0's into DIGEST.
388 svn_error_t *
389 svn_fs_fs__dag_file_checksum(unsigned char digest[],
390 dag_node_t *file,
391 apr_pool_t *pool);
393 /* Create a new mutable file named NAME in PARENT. Set *CHILD_P to a
394 reference to the new node, allocated in POOL. The new file's
395 contents are the empty string, and it has no properties. PARENT
396 must be mutable. NAME must be a single path component; it cannot
397 be a slash-separated directory path. PARENT_PATH must be the
398 canonicalized absolute path of the parent directory. TXN_ID is the
399 Subversion transaction under which this occurs. */
400 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
401 dag_node_t *parent,
402 const char *parent_path,
403 const char *name,
404 const char *txn_id,
405 apr_pool_t *pool);
409 /* Copies */
411 /* Make ENTRY in TO_NODE be a copy of FROM_NODE, allocating from POOL.
412 TO_NODE must be mutable. TXN_ID is the Subversion transaction
413 under which this occurs.
415 If PRESERVE_HISTORY is true, the new node will record that it was
416 copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be
417 the node found at FROM_PATH in FROM_REV, although this is not
418 checked. FROM_PATH should be canonicalized before being passed
419 here.
421 If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored. */
422 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
423 const char *entry,
424 dag_node_t *from_node,
425 svn_boolean_t preserve_history,
426 svn_revnum_t from_rev,
427 const char *from_path,
428 const char *txn_id,
429 apr_pool_t *pool);
432 /* Comparison */
434 /* Find out what is the same between two nodes.
436 If PROPS_CHANGED is non-null, set *PROPS_CHANGED to 1 if the two
437 nodes have different property lists, or to 0 if same.
439 If CONTENTS_CHANGED is non-null, set *CONTENTS_CHANGED to 1 if the
440 two nodes have different contents, or to 0 if same. For files,
441 file contents are compared; for directories, the entries lists are
442 compared. If one is a file and the other is a directory, the one's
443 contents will be compared to the other's entries list. (Not
444 terribly useful, I suppose, but that's the caller's business.)
446 ### todo: This function only compares rep keys at the moment. This
447 may leave us with a slight chance of a false positive, though I
448 don't really see how that would happen in practice. Nevertheless,
449 it should probably be fixed. */
450 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
451 svn_boolean_t *contents_changed,
452 dag_node_t *node1,
453 dag_node_t *node2,
454 apr_pool_t *pool);
457 /* Set *NODE_ID to the node-id of the coyproot of node NODE, or NULL
458 if no copyroot exists. Get any temporary allocations from POOL. */
459 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
460 const char **path,
461 dag_node_t *node,
462 apr_pool_t *pool);
464 /* Set *REV to the copyfrom revision associated with NODE. Get any
465 temporary allocations from POOL. */
466 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
467 dag_node_t *node,
468 apr_pool_t *pool);
470 /* Set *PATH to the copyfrom path associated with NODE. Get any
471 temporary allocations from POOL. */
472 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
473 dag_node_t *node,
474 apr_pool_t *pool);
476 #ifdef __cplusplus
478 #endif /* __cplusplus */
480 #endif /* SVN_LIBSVN_FS_DAG_H */