1/*
2 * svn_fs_util.h: Declarations for the APIs of libsvn_fs_util to be
3 * consumed by only fs_* libs.
4 *
5 * ====================================================================
6 *    Licensed to the Apache Software Foundation (ASF) under one
7 *    or more contributor license agreements.  See the NOTICE file
8 *    distributed with this work for additional information
9 *    regarding copyright ownership.  The ASF licenses this file
10 *    to you under the Apache License, Version 2.0 (the
11 *    "License"); you may not use this file except in compliance
12 *    with the License.  You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 *    Unless required by applicable law or agreed to in writing,
17 *    software distributed under the License is distributed on an
18 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 *    KIND, either express or implied.  See the License for the
20 *    specific language governing permissions and limitations
21 *    under the License.
22 * ====================================================================
23 */
24
25#ifndef SVN_FS_UTIL_H
26#define SVN_FS_UTIL_H
27
28#include <apr_pools.h>
29
30#include "svn_types.h"
31#include "svn_error.h"
32#include "svn_version.h"
33#include "svn_fs.h"
34
35#ifdef __cplusplus
36extern "C" {
37#endif /* __cplusplus */
38
39/* Get libsvn_fs_util version information. */
40const svn_version_t *
41svn_fs_util__version(void);
42
43/* Returns whether PATH is in canonical form as defined by
44   svn_fs__canonicalize_abspath().
45 */
46svn_boolean_t
47svn_fs__is_canonical_abspath(const char *path);
48
49/* Return a canonicalized version of a filesystem PATH, allocated in POOL.
50
51   While the filesystem API is pretty flexible about the incoming paths
52   (they must be UTF-8 with '/' as separators, but they don't have to
53   begin with '/', and multiple contiguous '/'s are ignored) we want any
54   paths that are physically stored in the underlying database to look
55   consistent.  Specifically, absolute filesystem paths should begin with
56   '/', and all redundant and trailing '/' characters be removed.
57
58   This is similar to svn_fspath__canonicalize() but doesn't treat "."
59   segments as special.
60*/
61const char *
62svn_fs__canonicalize_abspath(const char *path, apr_pool_t *pool);
63
64/* If EXPECT_OPEN, verify that FS refers to an open database;
65   otherwise, verify that FS refers to an unopened database.  Return
66   an appropriate error if the expectation fails to match the
67   reality.  */
68svn_error_t *
69svn_fs__check_fs(svn_fs_t *fs, svn_boolean_t expect_open);
70
71/* An identifier for FS to be used in the text of error messages.
72   (Not used anywhere but in this header.)
73
74   Note: we log the UUID, rather than (fs)->path, since some of these
75   errors are marshalled to the client. */
76#define svn_fs__identifier(fs) ((fs)->uuid)
77
78/* Constructing nice error messages for roots.  */
79
80/* Build an SVN_ERR_FS_NOT_FOUND error, with a detailed error text,
81   for PATH in ROOT. ROOT is of type svn_fs_root_t *. */
82#define SVN_FS__NOT_FOUND(root, path) (                        \
83  root->is_txn_root ?                                          \
84    svn_error_createf                                          \
85      (SVN_ERR_FS_NOT_FOUND, 0,                                \
86       _("File not found: transaction '%s', path '%s'"),       \
87       root->txn, path)                                        \
88  :                                                            \
89    svn_error_createf                                          \
90      (SVN_ERR_FS_NOT_FOUND, 0,                                \
91       _("File not found: revision %ld, path '%s'"),           \
92       root->rev, path)                                        \
93  )
94
95
96/* Build a detailed `file already exists' message for PATH in ROOT.
97   ROOT is of type svn_fs_root_t *. */
98#define SVN_FS__ALREADY_EXISTS(root, path_str) (                               \
99  root->is_txn_root ?                                                          \
100    svn_error_createf                                                          \
101      (SVN_ERR_FS_ALREADY_EXISTS, 0,                                           \
102       _("File already exists: filesystem '%s', transaction '%s', path '%s'"), \
103       svn_fs__identifier(root->fs), root->txn, path_str)      \
104  :                                                                            \
105    svn_error_createf                                                          \
106      (SVN_ERR_FS_ALREADY_EXISTS, 0,                                           \
107       _("File already exists: filesystem '%s', revision %ld, path '%s'"),     \
108       svn_fs__identifier(root->fs), root->rev, path_str)      \
109  )
110
111/* ROOT is of type svn_fs_root_t *. */
112#define SVN_FS__NOT_TXN(root)                         \
113  svn_error_create                                    \
114    (SVN_ERR_FS_NOT_TXN_ROOT, NULL,                   \
115     _("Root object must be a transaction root"))
116
117/* SVN_FS__ERR_NOT_MUTABLE: the caller attempted to change a node
118   outside of a transaction. FS is of type "svn_fs_t *". */
119#define SVN_FS__ERR_NOT_MUTABLE(fs, rev, path_in_repo)                   \
120  svn_error_createf(                                                     \
121     SVN_ERR_FS_NOT_MUTABLE, 0,                                          \
122     _("File is not mutable: filesystem '%s', revision %ld, path '%s'"), \
123     svn_fs__identifier(fs), rev, path_in_repo)
124
125/* FS is of type "svn_fs_t *".*/
126#define SVN_FS__ERR_NOT_DIRECTORY(fs, path_in_repo)               \
127  svn_error_createf(                                              \
128     SVN_ERR_FS_NOT_DIRECTORY, 0,                                 \
129     _("'%s' is not a directory in filesystem '%s'"),             \
130     path_in_repo, svn_fs__identifier(fs))
131
132/* FS is of type "svn_fs_t *".   */
133#define SVN_FS__ERR_NOT_FILE(fs, path_in_repo)                    \
134  svn_error_createf(                                              \
135     SVN_ERR_FS_NOT_FILE, 0,                                      \
136     _("'%s' is not a file in filesystem '%s'"),                  \
137     path_in_repo, svn_fs__identifier(fs))
138
139
140/* FS is of type "svn_fs_t *", LOCK is of type "svn_lock_t *".   */
141#define SVN_FS__ERR_PATH_ALREADY_LOCKED(fs, lock)                           \
142  svn_error_createf(                                                        \
143     SVN_ERR_FS_PATH_ALREADY_LOCKED, 0,                                     \
144     _("Path '%s' is already locked by user '%s' in filesystem '%s'"),      \
145     (lock)->path, (lock)->owner, svn_fs__identifier(fs))
146
147/* FS is of type "svn_fs_t *". */
148#define SVN_FS__ERR_NO_SUCH_LOCK(fs, path_in_repo)                \
149  svn_error_createf(                                              \
150     SVN_ERR_FS_NO_SUCH_LOCK, 0,                                  \
151     _("No lock on path '%s' in filesystem '%s'"),                \
152     path_in_repo, svn_fs__identifier(fs))
153
154/* FS is of type "svn_fs_t *". */
155#define SVN_FS__ERR_LOCK_EXPIRED(fs, token)                      \
156  svn_error_createf(                                             \
157     SVN_ERR_FS_LOCK_EXPIRED, 0,                                 \
158     _("Lock has expired: lock-token '%s' in filesystem '%s'"),  \
159     token, svn_fs__identifier(fs))
160
161/* FS is of type "svn_fs_t *". */
162#define SVN_FS__ERR_NO_USER(fs)                                     \
163  svn_error_createf(                                                \
164     SVN_ERR_FS_NO_USER, 0,                                         \
165     _("No username is currently associated with filesystem '%s'"), \
166     svn_fs__identifier(fs))
167
168/* SVN_FS__ERR_LOCK_OWNER_MISMATCH: trying to use a lock whose
169   LOCK_OWNER doesn't match the USERNAME associated with FS.
170   FS is of type "svn_fs_t *". */
171#define SVN_FS__ERR_LOCK_OWNER_MISMATCH(fs, username, lock_owner)       \
172  svn_error_createf(                                                    \
173     SVN_ERR_FS_LOCK_OWNER_MISMATCH, 0,                                 \
174     _("User '%s' is trying to use a lock owned by '%s' in "            \
175       "filesystem '%s'"),                                              \
176     username, lock_owner, svn_fs__identifier(fs))
177
178/* Return a NULL-terminated copy of the first component of PATH,
179   allocated in POOL.  If path is empty, or consists entirely of
180   slashes, return the empty string.
181
182   If the component is followed by one or more slashes, we set *NEXT_P
183   to point after the slashes.  If the component ends PATH, we set
184   *NEXT_P to zero.  This means:
185   - If *NEXT_P is zero, then the component ends the PATH, and there
186     are no trailing slashes in the path.
187   - If *NEXT_P points at PATH's terminating NULL character, then
188     the component returned was the last, and PATH ends with one or more
189     slash characters.
190   - Otherwise, *NEXT_P points to the beginning of the next component
191     of PATH.  You can pass this value to next_entry_name to extract
192     the next component. */
193char *
194svn_fs__next_entry_name(const char **next_p,
195                        const char *path,
196                        apr_pool_t *pool);
197
198/* Allocate an svn_fs_path_change2_t structure in POOL, initialize and
199   return it.
200
201   Set the node_rev_id field of the created struct to NODE_REV_ID, and
202   change_kind to CHANGE_KIND.  Set all other fields to their _unknown,
203   NULL or invalid value, respectively. */
204svn_fs_path_change2_t *
205svn_fs__path_change_create_internal(const svn_fs_id_t *node_rev_id,
206                                    svn_fs_path_change_kind_t change_kind,
207                                    apr_pool_t *pool);
208
209/* Allocate an svn_fs_path_change3_t structure in RESULT_POOL, initialize
210   and return it.
211
212   Set the change_kind to CHANGE_KIND.  Set all other fields to their
213   _unknown, NULL or invalid value, respectively. */
214svn_fs_path_change3_t *
215svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind,
216                                     apr_pool_t *result_pool);
217
218/* Append REL_PATH (which may contain slashes) to each path that exists in
219   the mergeinfo INPUT, and return a new mergeinfo in *OUTPUT.  Deep
220   copies the values.  Perform all allocations in POOL. */
221svn_error_t *
222svn_fs__append_to_merged_froms(svn_mergeinfo_t *output,
223                               svn_mergeinfo_t input,
224                               const char *rel_path,
225                               apr_pool_t *pool);
226
227/* Given the FS creation options in CONFIG, return the oldest version that
228   we shall be compatible with in *COMPATIBLE_VERSION.  The patch level
229   is always set to 0 and the tag to "".   Allocate the result in POOL.
230
231   Note that the result will always be compatible to the current tool
232   version, i.e. will be a version number not more recent than this tool. */
233svn_error_t *
234svn_fs__compatible_version(svn_version_t **compatible_version,
235                           apr_hash_t *config,
236                           apr_pool_t *pool);
237
238/* Compare the property lists A and B using POOL for temporary allocations.
239   Return true iff both lists contain the same properties with the same
240   values.  A and B may be NULL in which case they will be equal to and
241   empty list. */
242svn_boolean_t
243svn_fs__prop_lists_equal(apr_hash_t *a,
244                         apr_hash_t *b,
245                         apr_pool_t *pool);
246
247#ifdef __cplusplus
248}
249#endif /* __cplusplus */
250
251#endif /* SVN_FS_UTIL_H */
252