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
22 #include "svn_delta.h"
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.
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. */
62 svn_fs_fs__dag_get_node(dag_node_t
**node
,
64 const svn_fs_id_t
*id
,
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
,
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
,
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
,
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
,
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
,
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
121 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t
*do_they
,
125 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
126 has svn:mergeinfo set on it. */
128 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t
*has_mergeinfo
,
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
143 If properties do not exist on NODE, *PROPLIST_P will be set to
145 svn_error_t
*svn_fs_fs__dag_get_proplist(apr_hash_t
**proplist_p
,
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
,
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
,
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
,
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
,
180 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
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
,
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
,
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
,
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
,
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
230 svn_error_t
*svn_fs_fs__dag_dir_entries(apr_hash_t
**entries_p
,
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
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
,
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
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
,
267 const char *parent_path
,
271 svn_boolean_t is_parent_copyroot
,
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
282 If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
284 svn_error_t
*svn_fs_fs__dag_delete(dag_node_t
*parent
,
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
,
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
,
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
,
325 const char *parent_path
,
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
,
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. */
348 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t
**stream_p
,
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
,
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
,
376 /* Set *LENGTH to the length of the contents of FILE, allocating from
378 svn_error_t
*svn_fs_fs__dag_file_length(svn_filesize_t
*length
,
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.
389 svn_fs_fs__dag_file_checksum(unsigned char digest
[],
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
,
402 const char *parent_path
,
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
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
,
424 dag_node_t
*from_node
,
425 svn_boolean_t preserve_history
,
426 svn_revnum_t from_rev
,
427 const char *from_path
,
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
,
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
,
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
,
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
,
478 #endif /* __cplusplus */
480 #endif /* SVN_LIBSVN_FS_DAG_H */