1 /**
2 * @copyright
3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 * ====================================================================
21 * @endcopyright
22 */
23
24 /* This file is not for general consumption; it should only be used by
25 wc_db.c. */
26 #ifndef SVN_WC__I_AM_WC_DB
27 #error "You should not be using these data structures directly"
28 #endif /* SVN_WC__I_AM_WC_DB */
29
30 #ifndef WC_DB_PRIVATE_H
31 #define WC_DB_PRIVATE_H
32
33 #include "wc_db.h"
34
35
36 struct svn_wc__db_t {
37 /* We need the config whenever we run into a new WC directory, in order
38 to figure out where we should look for the corresponding datastore. */
39 svn_config_t *config;
40
41 /* Should we fail with SVN_ERR_WC_UPGRADE_REQUIRED when it is
42 opened, and found to be not-current? */
43 svn_boolean_t verify_format;
44
45 /* Should we ensure the WORK_QUEUE is empty when a DB is locked
46 * for writing? */
47 svn_boolean_t enforce_empty_wq;
48
49 /* Should we open Sqlite databases EXCLUSIVE */
50 svn_boolean_t exclusive;
51
52 /* Busy timeout in ms., 0 for the libsvn_subr default. */
53 apr_int32_t timeout;
54
55 /* Map a given working copy directory to its relevant data.
56 const char *local_abspath -> svn_wc__db_wcroot_t *wcroot */
57 apr_hash_t *dir_data;
58
59 /* A few members to assist with caching of kind values for paths. See
60 get_path_kind() for use. */
61 struct
62 {
63 svn_stringbuf_t *abspath;
64 svn_node_kind_t kind;
65 } parse_cache;
66
67 /* As we grow the state of this DB, allocate that state here. */
68 apr_pool_t *state_pool;
69 };
70
71
72 /* Hold information about an owned lock */
73 typedef struct svn_wc__db_wclock_t
74 {
75 /* Relative path of the lock root */
76 const char *local_relpath;
77
78 /* Number of levels locked (0 for infinity) */
79 int levels;
80 } svn_wc__db_wclock_t;
81
82
83 /** Hold information about a WCROOT.
84 *
85 * This structure is referenced by all per-directory handles underneath it.
86 */
87 typedef struct svn_wc__db_wcroot_t {
88 /* Location of this wcroot in the filesystem. */
89 const char *abspath;
90
91 /* The SQLite database containing the metadata for everything in
92 this wcroot. */
93 svn_sqlite__db_t *sdb;
94
95 /* The WCROOT.id for this directory (and all its children). */
96 apr_int64_t wc_id;
97
98 /* The format of this wcroot's metadata storage (see wc.h). If the
99 format has not (yet) been determined, this will be UNKNOWN_FORMAT. */
100 int format;
101
102 /* Array of svn_wc__db_wclock_t structures (not pointers!).
103 Typically just one or two locks maximum. */
104 apr_array_header_t *owned_locks;
105
106 /* Map a working copy directory to a cached adm_access baton.
107 const char *local_abspath -> svn_wc_adm_access_t *adm_access */
108 apr_hash_t *access_cache;
109
110 } svn_wc__db_wcroot_t;
111
112
113 /* */
114 svn_error_t *
115 svn_wc__db_close_many_wcroots(apr_hash_t *roots,
116 apr_pool_t *state_pool,
117 apr_pool_t *scratch_pool);
118
119
120 /* Construct a new svn_wc__db_wcroot_t. The WCROOT_ABSPATH and SDB parameters
121 must have lifetime of at least RESULT_POOL. */
122 svn_error_t *
123 svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t **wcroot,
124 const char *wcroot_abspath,
125 svn_sqlite__db_t *sdb,
126 apr_int64_t wc_id,
127 int format,
128 svn_boolean_t verify_format,
129 apr_pool_t *result_pool,
130 apr_pool_t *scratch_pool);
131
132
133 /* For a given LOCAL_ABSPATH, figure out what sqlite database (WCROOT) to
134 use and the RELPATH within that wcroot.
135
136 *LOCAL_RELPATH will be allocated within RESULT_POOL. Temporary allocations
137 will be made in SCRATCH_POOL.
138
139 *WCROOT will be allocated within DB->STATE_POOL.
140
141 Certain internal structures will be allocated in DB->STATE_POOL.
142 */
143 svn_error_t *
144 svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
145 const char **local_relpath,
146 svn_wc__db_t *db,
147 const char *local_abspath,
148 apr_pool_t *result_pool,
149 apr_pool_t *scratch_pool);
150
151 /* Return an error if the work queue in SDB is non-empty. */
152 svn_error_t *
153 svn_wc__db_verify_no_work(svn_sqlite__db_t *sdb);
154
155 /* Assert that the given WCROOT is usable.
156 NOTE: the expression is multiply-evaluated!! */
157 #define VERIFY_USABLE_WCROOT(wcroot) SVN_ERR_ASSERT( \
158 (wcroot) != NULL && (wcroot)->format == SVN_WC__VERSION)
159
160 /* Check if the WCROOT is usable for light db operations such as path
161 calculations */
162 #define CHECK_MINIMAL_WCROOT(wcroot, abspath, scratch_pool) \
163 do \
164 { \
165 if (wcroot == NULL) \
166 return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, \
167 _("The node '%s' is not in a working copy."), \
168 svn_dirent_local_style(wri_abspath, \
169 scratch_pool)); \
170 } \
171 while (0)
172
173 /* Calculates the depth of the relpath below "" */
174 APR_INLINE static int
relpath_depth(const char * relpath)175 relpath_depth(const char *relpath)
176 {
177 int n = 1;
178 if (*relpath == '\0')
179 return 0;
180
181 do
182 {
183 if (*relpath == '/')
184 n++;
185 }
186 while (*(++relpath));
187
188 return n;
189 }
190
191
192 /* */
193 svn_error_t *
194 svn_wc__db_util_fetch_wc_id(apr_int64_t *wc_id,
195 svn_sqlite__db_t *sdb,
196 apr_pool_t *scratch_pool);
197
198 /* Open a connection in *SDB to the WC database found in the WC metadata
199 * directory inside DIR_ABSPATH, having the filename SDB_FNAME.
200 *
201 * SMODE, EXCLUSIVE and TIMEOUT are passed to svn_sqlite__open().
202 *
203 * Register MY_STATEMENTS, or if that is null, the default set of WC DB
204 * statements, as the set of statements to be prepared now and executed
205 * later. MY_STATEMENTS (the strings and the array itself) is not duplicated
206 * internally, and should have a lifetime at least as long as RESULT_POOL.
207 * See svn_sqlite__open() for details. */
208 svn_error_t *
209 svn_wc__db_util_open_db(svn_sqlite__db_t **sdb,
210 const char *dir_abspath,
211 const char *sdb_fname,
212 svn_sqlite__mode_t smode,
213 svn_boolean_t exclusive,
214 apr_int32_t timeout,
215 const char *const *my_statements,
216 apr_pool_t *result_pool,
217 apr_pool_t *scratch_pool);
218
219 /* Like svn_wc__db_wq_add() but taking WCROOT */
220 svn_error_t *
221 svn_wc__db_wq_add_internal(svn_wc__db_wcroot_t *wcroot,
222 const svn_skel_t *work_item,
223 apr_pool_t *scratch_pool);
224
225
226 /* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
227 DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
228 svn_error_t *
229 svn_wc__db_read_info_internal(svn_wc__db_status_t *status,
230 svn_node_kind_t *kind,
231 svn_revnum_t *revision,
232 const char **repos_relpath,
233 apr_int64_t *repos_id,
234 svn_revnum_t *changed_rev,
235 apr_time_t *changed_date,
236 const char **changed_author,
237 svn_depth_t *depth,
238 const svn_checksum_t **checksum,
239 const char **target,
240 const char **original_repos_relpath,
241 apr_int64_t *original_repos_id,
242 svn_revnum_t *original_revision,
243 svn_wc__db_lock_t **lock,
244 svn_filesize_t *recorded_size,
245 apr_time_t *recorded_mod_time,
246 const char **changelist,
247 svn_boolean_t *conflicted,
248 svn_boolean_t *op_root,
249 svn_boolean_t *had_props,
250 svn_boolean_t *props_mod,
251 svn_boolean_t *have_base,
252 svn_boolean_t *have_more_work,
253 svn_boolean_t *have_work,
254 svn_wc__db_wcroot_t *wcroot,
255 const char *local_relpath,
256 apr_pool_t *result_pool,
257 apr_pool_t *scratch_pool);
258
259 /* Like svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH instead of
260 DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
261 svn_error_t *
262 svn_wc__db_base_get_info_internal(svn_wc__db_status_t *status,
263 svn_node_kind_t *kind,
264 svn_revnum_t *revision,
265 const char **repos_relpath,
266 apr_int64_t *repos_id,
267 svn_revnum_t *changed_rev,
268 apr_time_t *changed_date,
269 const char **changed_author,
270 svn_depth_t *depth,
271 const svn_checksum_t **checksum,
272 const char **target,
273 svn_wc__db_lock_t **lock,
274 svn_boolean_t *had_props,
275 apr_hash_t **props,
276 svn_boolean_t *update_root,
277 svn_wc__db_wcroot_t *wcroot,
278 const char *local_relpath,
279 apr_pool_t *result_pool,
280 apr_pool_t *scratch_pool);
281
282 /* Similar to svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH
283 * instead of DB+LOCAL_ABSPATH, an explicit op-depth of the node to get
284 * information about, and outputting REPOS_ID instead of URL+UUID, and
285 * without the LOCK or UPDATE_ROOT outputs.
286 *
287 * OR
288 *
289 * Similar to svn_wc__db_base_get_info_internal(), but taking an explicit
290 * op-depth OP_DEPTH of the node to get information about, and without the
291 * LOCK or UPDATE_ROOT outputs.
292 *
293 * ### [JAF] TODO: Harmonize svn_wc__db_base_get_info[_internal] with
294 * svn_wc__db_depth_get_info -- common API, common implementation.
295 */
296 svn_error_t *
297 svn_wc__db_depth_get_info(svn_wc__db_status_t *status,
298 svn_node_kind_t *kind,
299 svn_revnum_t *revision,
300 const char **repos_relpath,
301 apr_int64_t *repos_id,
302 svn_revnum_t *changed_rev,
303 apr_time_t *changed_date,
304 const char **changed_author,
305 svn_depth_t *depth,
306 const svn_checksum_t **checksum,
307 const char **target,
308 svn_boolean_t *had_props,
309 apr_hash_t **props,
310 svn_wc__db_wcroot_t *wcroot,
311 const char *local_relpath,
312 int op_depth,
313 apr_pool_t *result_pool,
314 apr_pool_t *scratch_pool);
315
316 svn_error_t *
317 svn_wc__db_scan_addition_internal(
318 svn_wc__db_status_t *status,
319 const char **op_root_relpath_p,
320 const char **repos_relpath,
321 apr_int64_t *repos_id,
322 const char **original_repos_relpath,
323 apr_int64_t *original_repos_id,
324 svn_revnum_t *original_revision,
325 svn_wc__db_wcroot_t *wcroot,
326 const char *local_relpath,
327 apr_pool_t *result_pool,
328 apr_pool_t *scratch_pool);
329
330 svn_error_t *
331 svn_wc__db_scan_deletion_internal(
332 const char **base_del_relpath,
333 const char **moved_to_relpath,
334 const char **work_del_relpath,
335 const char **moved_to_op_root_relpath,
336 svn_wc__db_wcroot_t *wcroot,
337 const char *local_relpath,
338 apr_pool_t *result_pool,
339 apr_pool_t *scratch_pool);
340
341
342 /* Look up REPOS_ID in WCROOT->SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID
343 to its root URL and UUID respectively. If REPOS_ID is INVALID_REPOS_ID,
344 use NULL for both URL and UUID. Either or both output parameters may be
345 NULL if not wanted. */
346 svn_error_t *
347 svn_wc__db_fetch_repos_info(const char **repos_root_url,
348 const char **repos_uuid,
349 svn_wc__db_wcroot_t *wcroot,
350 apr_int64_t repos_id,
351 apr_pool_t *result_pool);
352
353 /* Like svn_wc__db_read_conflict(), but with WCROOT+LOCAL_RELPATH instead of
354 DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
355 svn_error_t *
356 svn_wc__db_read_conflict_internal(svn_skel_t **conflict,
357 svn_node_kind_t *kind,
358 apr_hash_t **props,
359 svn_wc__db_wcroot_t *wcroot,
360 const char *local_relpath,
361 apr_pool_t *result_pool,
362 apr_pool_t *scratch_pool);
363
364 /* Like svn_wc__db_op_mark_conflict(), but with WCROOT+LOCAL_RELPATH instead of
365 DB+LOCAL_ABSPATH. */
366 svn_error_t *
367 svn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
368 const char *local_relpath,
369 const svn_skel_t *conflict_skel,
370 apr_pool_t *scratch_pool);
371
372
373 /* Transaction handling */
374
375 /* Evaluate the expression EXPR within a transaction.
376 *
377 * Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would
378 * typically be a function call that does some work in DB; finally commit
379 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
380 * the transaction.
381 */
382 #define SVN_WC__DB_WITH_TXN(expr, wcroot) \
383 SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
384
385
386 /* Evaluate the expressions EXPR1..EXPR4 within a transaction, returning the
387 * first error if an error occurs.
388 *
389 * Begin a transaction in WCROOT's DB; evaluate the expressions, which would
390 * typically be function calls that do some work in DB; finally commit
391 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
392 * the transaction.
393 */
394 #define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
395 SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
396
397 /* Update the single op-depth layer in the move destination subtree
398 rooted at DST_RELPATH to make it match the move source subtree
399 rooted at SRC_RELPATH. */
400 svn_error_t *
401 svn_wc__db_op_copy_layer_internal(svn_wc__db_wcroot_t *wcroot,
402 const char *src_op_relpath,
403 int src_op_depth,
404 const char *dst_op_relpath,
405 svn_skel_t *conflict,
406 svn_skel_t *work_items,
407 apr_pool_t *scratch_pool);
408
409 /* Like svn_wc__db_op_make_copy but with wcroot, local_relpath */
410 svn_error_t *
411 svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot,
412 const char *local_relpath,
413 svn_boolean_t move_move_info,
414 const svn_skel_t *conflicts,
415 const svn_skel_t *work_items,
416 apr_pool_t *scratch_pool);
417
418
419 /* Extract the moved-to information for LOCAL_RELPATH as it existed
420 at OP-DEPTH. The output paths are optional and set to NULL
421 if there is no move, otherwise:
422
423 *MOVE_SRC_RELPATH: the path that was moved (LOCAL_RELPATH or one
424 of its ancestors)
425
426 *MOVE_DST_RELPATH: The path *MOVE_SRC_RELPATH was moved to.
427
428 *DELETE_RELPATH: The path at which LOCAL_RELPATH was removed (
429 *MOVE_SRC_RELPATH or one of its ancestors)
430
431 Given a path A/B/C with A/B moved to X and A deleted then for A/B/C:
432
433 MOVE_SRC_RELPATH is A/B
434 MOVE_DST_RELPATH is X
435 DELETE_RELPATH is A
436
437 X/C can be calculated if necessesary, like with the other
438 scan functions.
439
440 This function returns SVN_ERR_WC_PATH_NOT_FOUND if LOCAL_RELPATH didn't
441 exist at OP_DEPTH, or when it is not shadowed.
442
443 ### Think about combining with scan_deletion? Also with
444 ### scan_addition to get moved-to for replaces? Do we need to
445 ### return the op-root of the move source, i.e. A/B in the example
446 ### above? */
447 svn_error_t *
448 svn_wc__db_scan_moved_to_internal(const char **move_src_relpath,
449 const char **move_dst_relpath,
450 const char **delete_relpath,
451 svn_wc__db_wcroot_t *wcroot,
452 const char *local_relpath,
453 int op_depth,
454 apr_pool_t *result_pool,
455 apr_pool_t *scratch_pool);
456
457 /* Like svn_wc__db_op_set_props, but updates ACTUAL_NODE directly without
458 comparing with the pristine properties, etc.
459 */
460 svn_error_t *
461 svn_wc__db_op_set_props_internal(svn_wc__db_wcroot_t *wcroot,
462 const char *local_relpath,
463 apr_hash_t *props,
464 svn_boolean_t clear_recorded_info,
465 apr_pool_t *scratch_pool);
466
467 svn_error_t *
468 svn_wc__db_read_props_internal(apr_hash_t **props,
469 svn_wc__db_wcroot_t *wcroot,
470 const char *local_relpath,
471 apr_pool_t *result_pool,
472 apr_pool_t *scratch_pool);
473
474 /* Like svn_wc__db_wclock_owns_lock() but taking WCROOT+LOCAL_RELPATH instead
475 of DB+LOCAL_ABSPATH. */
476 svn_error_t *
477 svn_wc__db_wclock_owns_lock_internal(svn_boolean_t *own_lock,
478 svn_wc__db_wcroot_t *wcroot,
479 const char *local_relpath,
480 svn_boolean_t exact,
481 apr_pool_t *scratch_pool);
482
483 /* Do a post-drive revision bump for the moved-away destination for
484 any move sources under LOCAL_RELPATH. This is called from within
485 the revision bump transaction after the tree at LOCAL_RELPATH has
486 been bumped. */
487 svn_error_t *
488 svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot,
489 const char *local_relpath,
490 svn_depth_t depth,
491 svn_wc__db_t *db,
492 apr_pool_t *scratch_pool);
493
494 /* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
495 the destination DST_RELPATH a normal copy. SRC_OP_DEPTH is the op-depth
496 where the move_to information is stored */
497 svn_error_t *
498 svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot,
499 const char *src_relpath,
500 int delete_op_depth,
501 const char *dst_relpath,
502 const svn_skel_t *work_items,
503 apr_pool_t *scratch_pool);
504
505 svn_error_t *
506 svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot,
507 const char *local_relpath,
508 svn_wc__db_t *db,
509 svn_boolean_t resolved_text,
510 svn_boolean_t resolved_props,
511 svn_boolean_t resolved_tree,
512 const svn_skel_t *work_items,
513 apr_pool_t *scratch_pool);
514
515 /* op_depth is the depth at which the node is added. */
516 svn_error_t *
517 svn_wc__db_op_raise_moved_away_internal(
518 svn_wc__db_wcroot_t *wcroot,
519 const char *local_relpath,
520 int op_depth,
521 svn_wc__db_t *db,
522 svn_wc_operation_t operation,
523 svn_wc_conflict_action_t action,
524 const svn_wc_conflict_version_t *old_version,
525 const svn_wc_conflict_version_t *new_version,
526 apr_pool_t *scratch_pool);
527
528 svn_error_t *
529 svn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
530 svn_revnum_t old_revision,
531 svn_revnum_t new_revision,
532 svn_wc_notify_func2_t notify_func,
533 void *notify_baton,
534 apr_pool_t *scratch_pool);
535
536 svn_error_t *
537 svn_wc__db_verify_db_full_internal(svn_wc__db_wcroot_t *wcroot,
538 svn_wc__db_verify_cb_t callback,
539 void *baton,
540 apr_pool_t *scratch_pool);
541
542 #endif /* WC_DB_PRIVATE_H */
543