wc_db_private.h revision 289166
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
36struct 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 WCROOT is opened?  */
46  svn_boolean_t enforce_empty_wq;
47
48  /* Should we open Sqlite databases EXCLUSIVE */
49  svn_boolean_t exclusive;
50
51  /* Map a given working copy directory to its relevant data.
52     const char *local_abspath -> svn_wc__db_wcroot_t *wcroot  */
53  apr_hash_t *dir_data;
54
55  /* A few members to assist with caching of kind values for paths.  See
56     get_path_kind() for use. */
57  struct
58  {
59    svn_stringbuf_t *abspath;
60    svn_node_kind_t kind;
61  } parse_cache;
62
63  /* As we grow the state of this DB, allocate that state here. */
64  apr_pool_t *state_pool;
65};
66
67
68/* Hold information about an owned lock */
69typedef struct svn_wc__db_wclock_t
70{
71  /* Relative path of the lock root */
72  const char *local_relpath;
73
74  /* Number of levels locked (0 for infinity) */
75  int levels;
76} svn_wc__db_wclock_t;
77
78
79/** Hold information about a WCROOT.
80 *
81 * This structure is referenced by all per-directory handles underneath it.
82 */
83typedef struct svn_wc__db_wcroot_t {
84  /* Location of this wcroot in the filesystem.  */
85  const char *abspath;
86
87  /* The SQLite database containing the metadata for everything in
88     this wcroot.  */
89  svn_sqlite__db_t *sdb;
90
91  /* The WCROOT.id for this directory (and all its children).  */
92  apr_int64_t wc_id;
93
94  /* The format of this wcroot's metadata storage (see wc.h). If the
95     format has not (yet) been determined, this will be UNKNOWN_FORMAT.  */
96  int format;
97
98  /* Array of svn_wc__db_wclock_t structures (not pointers!).
99     Typically just one or two locks maximum. */
100  apr_array_header_t *owned_locks;
101
102  /* Map a working copy directory to a cached adm_access baton.
103     const char *local_abspath -> svn_wc_adm_access_t *adm_access */
104  apr_hash_t *access_cache;
105
106} svn_wc__db_wcroot_t;
107
108
109/* */
110svn_error_t *
111svn_wc__db_close_many_wcroots(apr_hash_t *roots,
112                              apr_pool_t *state_pool,
113                              apr_pool_t *scratch_pool);
114
115
116/* Construct a new svn_wc__db_wcroot_t. The WCROOT_ABSPATH and SDB parameters
117   must have lifetime of at least RESULT_POOL.  */
118svn_error_t *
119svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t **wcroot,
120                             const char *wcroot_abspath,
121                             svn_sqlite__db_t *sdb,
122                             apr_int64_t wc_id,
123                             int format,
124                             svn_boolean_t verify_format,
125                             svn_boolean_t enforce_empty_wq,
126                             apr_pool_t *result_pool,
127                             apr_pool_t *scratch_pool);
128
129
130/* For a given LOCAL_ABSPATH, figure out what sqlite database (WCROOT) to
131   use and the RELPATH within that wcroot.
132
133   *LOCAL_RELPATH will be allocated within RESULT_POOL. Temporary allocations
134   will be made in SCRATCH_POOL.
135
136   *WCROOT will be allocated within DB->STATE_POOL.
137
138   Certain internal structures will be allocated in DB->STATE_POOL.
139*/
140svn_error_t *
141svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
142                                      const char **local_relpath,
143                                      svn_wc__db_t *db,
144                                      const char *local_abspath,
145                                      apr_pool_t *result_pool,
146                                      apr_pool_t *scratch_pool);
147
148
149/* Assert that the given WCROOT is usable.
150   NOTE: the expression is multiply-evaluated!!  */
151#define VERIFY_USABLE_WCROOT(wcroot)  SVN_ERR_ASSERT(               \
152    (wcroot) != NULL && (wcroot)->format == SVN_WC__VERSION)
153
154/* Check if the WCROOT is usable for light db operations such as path
155   calculations */
156#define CHECK_MINIMAL_WCROOT(wcroot, abspath, scratch_pool)             \
157    do                                                                  \
158    {                                                                   \
159      if (wcroot == NULL)                                               \
160        return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,     \
161                    _("The node '%s' is not in a working copy."),       \
162                             svn_dirent_local_style(wri_abspath,        \
163                                                    scratch_pool));     \
164    }                                                                   \
165    while (0)
166
167/* Calculates the depth of the relpath below "" */
168APR_INLINE static int
169relpath_depth(const char *relpath)
170{
171  int n = 1;
172  if (*relpath == '\0')
173    return 0;
174
175  do
176  {
177    if (*relpath == '/')
178      n++;
179  }
180  while (*(++relpath));
181
182  return n;
183}
184
185
186/* */
187svn_error_t *
188svn_wc__db_util_fetch_wc_id(apr_int64_t *wc_id,
189                            svn_sqlite__db_t *sdb,
190                            apr_pool_t *scratch_pool);
191
192/* Open a connection in *SDB to the WC database found in the WC metadata
193 * directory inside DIR_ABSPATH, having the filename SDB_FNAME.
194 *
195 * SMODE is passed to svn_sqlite__open().
196 *
197 * Register MY_STATEMENTS, or if that is null, the default set of WC DB
198 * statements, as the set of statements to be prepared now and executed
199 * later.  MY_STATEMENTS (the strings and the array itself) is not duplicated
200 * internally, and should have a lifetime at least as long as RESULT_POOL.
201 * See svn_sqlite__open() for details. */
202svn_error_t *
203svn_wc__db_util_open_db(svn_sqlite__db_t **sdb,
204                        const char *dir_abspath,
205                        const char *sdb_fname,
206                        svn_sqlite__mode_t smode,
207                        svn_boolean_t exclusive,
208                        const char *const *my_statements,
209                        apr_pool_t *result_pool,
210                        apr_pool_t *scratch_pool);
211
212/* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
213   DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
214svn_error_t *
215svn_wc__db_read_info_internal(svn_wc__db_status_t *status,
216                              svn_node_kind_t *kind,
217                              svn_revnum_t *revision,
218                              const char **repos_relpath,
219                              apr_int64_t *repos_id,
220                              svn_revnum_t *changed_rev,
221                              apr_time_t *changed_date,
222                              const char **changed_author,
223                              svn_depth_t *depth,
224                              const svn_checksum_t **checksum,
225                              const char **target,
226                              const char **original_repos_relpath,
227                              apr_int64_t *original_repos_id,
228                              svn_revnum_t *original_revision,
229                              svn_wc__db_lock_t **lock,
230                              svn_filesize_t *recorded_size,
231                              apr_time_t *recorded_mod_time,
232                              const char **changelist,
233                              svn_boolean_t *conflicted,
234                              svn_boolean_t *op_root,
235                              svn_boolean_t *had_props,
236                              svn_boolean_t *props_mod,
237                              svn_boolean_t *have_base,
238                              svn_boolean_t *have_more_work,
239                              svn_boolean_t *have_work,
240                              svn_wc__db_wcroot_t *wcroot,
241                              const char *local_relpath,
242                              apr_pool_t *result_pool,
243                              apr_pool_t *scratch_pool);
244
245/* Like svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH instead of
246   DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
247svn_error_t *
248svn_wc__db_base_get_info_internal(svn_wc__db_status_t *status,
249                                  svn_node_kind_t *kind,
250                                  svn_revnum_t *revision,
251                                  const char **repos_relpath,
252                                  apr_int64_t *repos_id,
253                                  svn_revnum_t *changed_rev,
254                                  apr_time_t *changed_date,
255                                  const char **changed_author,
256                                  svn_depth_t *depth,
257                                  const svn_checksum_t **checksum,
258                                  const char **target,
259                                  svn_wc__db_lock_t **lock,
260                                  svn_boolean_t *had_props,
261                                  apr_hash_t **props,
262                                  svn_boolean_t *update_root,
263                                  svn_wc__db_wcroot_t *wcroot,
264                                  const char *local_relpath,
265                                  apr_pool_t *result_pool,
266                                  apr_pool_t *scratch_pool);
267
268/* Similar to svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH
269 * instead of DB+LOCAL_ABSPATH, an explicit op-depth of the node to get
270 * information about, and outputting REPOS_ID instead of URL+UUID, and
271 * without the LOCK or UPDATE_ROOT outputs.
272 *
273 * OR
274 *
275 * Similar to svn_wc__db_base_get_info_internal(), but taking an explicit
276 * op-depth OP_DEPTH of the node to get information about, and without the
277 * LOCK or UPDATE_ROOT outputs.
278 *
279 * ### [JAF] TODO: Harmonize svn_wc__db_base_get_info[_internal] with
280 * svn_wc__db_depth_get_info -- common API, common implementation.
281 */
282svn_error_t *
283svn_wc__db_depth_get_info(svn_wc__db_status_t *status,
284                          svn_node_kind_t *kind,
285                          svn_revnum_t *revision,
286                          const char **repos_relpath,
287                          apr_int64_t *repos_id,
288                          svn_revnum_t *changed_rev,
289                          apr_time_t *changed_date,
290                          const char **changed_author,
291                          svn_depth_t *depth,
292                          const svn_checksum_t **checksum,
293                          const char **target,
294                          svn_boolean_t *had_props,
295                          apr_hash_t **props,
296                          svn_wc__db_wcroot_t *wcroot,
297                          const char *local_relpath,
298                          int op_depth,
299                          apr_pool_t *result_pool,
300                          apr_pool_t *scratch_pool);
301
302/* Look up REPOS_ID in SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID to
303   its root URL and UUID respectively.  If REPOS_ID is INVALID_REPOS_ID,
304   use NULL for both URL and UUID.  Either or both output parameters may be
305   NULL if not wanted.  */
306svn_error_t *
307svn_wc__db_fetch_repos_info(const char **repos_root_url,
308                            const char **repos_uuid,
309                            svn_sqlite__db_t *sdb,
310                            apr_int64_t repos_id,
311                            apr_pool_t *result_pool);
312
313/* Like svn_wc__db_read_conflict(), but with WCROOT+LOCAL_RELPATH instead of
314   DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
315svn_error_t *
316svn_wc__db_read_conflict_internal(svn_skel_t **conflict,
317                                  svn_wc__db_wcroot_t *wcroot,
318                                  const char *local_relpath,
319                                  apr_pool_t *result_pool,
320                                  apr_pool_t *scratch_pool);
321
322/* Like svn_wc__db_op_mark_conflict(), but with WCROOT+LOCAL_RELPATH instead of
323   DB+LOCAL_ABSPATH. */
324svn_error_t *
325svn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
326                                  const char *local_relpath,
327                                  const svn_skel_t *conflict_skel,
328                                  apr_pool_t *scratch_pool);
329
330
331/* Transaction handling */
332
333/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
334typedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
335                                          svn_wc__db_wcroot_t *wcroot,
336                                          const char *local_relpath,
337                                          apr_pool_t *scratch_pool);
338
339
340/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
341   LOCAL_RELPATH.  If callbacks require additional information, they may
342   provide it using CB_BATON. */
343svn_error_t *
344svn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
345                    const char *local_relpath,
346                    svn_wc__db_txn_callback_t cb_func,
347                    void *cb_baton,
348                    apr_pool_t *scratch_pool);
349
350/* Evaluate the expression EXPR within a transaction.
351 *
352 * Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would
353 * typically be a function call that does some work in DB; finally commit
354 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
355 * the transaction.
356 */
357#define SVN_WC__DB_WITH_TXN(expr, wcroot) \
358  SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
359
360
361/* Evaluate the expressions EXPR1..EXPR4 within a transaction, returning the
362 * first error if an error occurs.
363 *
364 * Begin a transaction in WCROOT's DB; evaluate the expressions, which would
365 * typically be  function calls that do some work in DB; finally commit
366 * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
367 * the transaction.
368 */
369#define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
370  SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
371
372
373/* Return CHILDREN mapping const char * names to svn_node_kind_t * for the
374   children of LOCAL_RELPATH at OP_DEPTH. */
375svn_error_t *
376svn_wc__db_get_children_op_depth(apr_hash_t **children,
377                                 svn_wc__db_wcroot_t *wcroot,
378                                 const char *local_relpath,
379                                 int op_depth,
380                                 apr_pool_t *result_pool,
381                                 apr_pool_t *scratch_pool);
382
383
384/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
385
386   ### What about KIND and OP_DEPTH?  KIND ought to be redundant; I'm
387       discussing on dev@ whether we can let that be null for presence
388       == base-deleted.  OP_DEPTH is the op-depth of what, and why?
389       It is used to select the lowest working node higher than OP_DEPTH,
390       so, in terms of the API, OP_DEPTH means ...?
391
392   Given a wc:
393
394              0         1         2         3         4
395              normal
396   A          normal
397   A/B        normal              normal
398   A/B/C                          not-pres  normal
399   A/B/C/D                                            normal
400
401   That is checkout, delete A/B, copy a replacement A/B, delete copied
402   child A/B/C, add replacement A/B/C, add A/B/C/D.
403
404   Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
405   must extend the A/B deletion:
406
407              0         1         2         3         4
408              normal
409   A          normal
410   A/B        normal              normal
411   A/B/C      normal              not-pres  normal
412   A/B/C/D    normal              base-del            normal
413   A/B/C/D/E  normal              base-del
414
415   When adding a node if the parent has a higher working node then the
416   parent node is deleted (or replaced) and the delete must be extended
417   to cover new node.
418
419   In the example above A/B/C/D and A/B/C/D/E are the nodes that get
420   the extended delete, A/B/C is already deleted.
421 */
422svn_error_t *
423svn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
424                                const char *local_relpath,
425                                svn_node_kind_t kind,
426                                int op_depth,
427                                apr_pool_t *scratch_pool);
428
429svn_error_t *
430svn_wc__db_retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
431                                 const char *local_relpath,
432                                 int op_depth,
433                                 apr_pool_t *scratch_pool);
434
435svn_error_t *
436svn_wc__db_op_depth_moved_to(const char **move_dst_relpath,
437                             const char **move_dst_op_root_relpath,
438                             const char **move_src_root_relpath,
439                             const char **move_src_op_root_relpath,
440                             int op_depth,
441                             svn_wc__db_wcroot_t *wcroot,
442                             const char *local_relpath,
443                             apr_pool_t *result_pool,
444                             apr_pool_t *scratch_pool);
445
446/* Do a post-drive revision bump for the moved-away destination for
447   any move sources under LOCAL_RELPATH.  This is called from within
448   the revision bump transaction after the tree at LOCAL_RELPATH has
449   been bumped. */
450svn_error_t *
451svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot,
452                           const char *local_relpath,
453                           svn_depth_t depth,
454                           svn_wc__db_t *db,
455                           apr_pool_t *scratch_pool);
456
457/* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
458   the destination a normal copy */
459svn_error_t *
460svn_wc__db_resolve_break_moved_away_internal(svn_wc__db_wcroot_t *wcroot,
461                                             const char *local_relpath,
462                                             int op_depth,
463                                             apr_pool_t *scratch_pool);
464
465svn_error_t *
466svn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
467                                   svn_revnum_t old_revision,
468                                   svn_revnum_t new_revision,
469                                   svn_wc_notify_func2_t notify_func,
470                                   void *notify_baton,
471                                   apr_pool_t *scratch_pool);
472
473#endif /* WC_DB_PRIVATE_H */
474