1251881Speter/**
2251881Speter * @copyright
3251881Speter * ====================================================================
4251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
5251881Speter *    or more contributor license agreements.  See the NOTICE file
6251881Speter *    distributed with this work for additional information
7251881Speter *    regarding copyright ownership.  The ASF licenses this file
8251881Speter *    to you under the Apache License, Version 2.0 (the
9251881Speter *    "License"); you may not use this file except in compliance
10251881Speter *    with the License.  You may obtain a copy of the License at
11251881Speter *
12251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
13251881Speter *
14251881Speter *    Unless required by applicable law or agreed to in writing,
15251881Speter *    software distributed under the License is distributed on an
16251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17251881Speter *    KIND, either express or implied.  See the License for the
18251881Speter *    specific language governing permissions and limitations
19251881Speter *    under the License.
20251881Speter * ====================================================================
21251881Speter * @endcopyright
22251881Speter */
23251881Speter
24251881Speter/* This file is not for general consumption; it should only be used by
25251881Speter   wc_db.c. */
26251881Speter#ifndef SVN_WC__I_AM_WC_DB
27251881Speter#error "You should not be using these data structures directly"
28251881Speter#endif /* SVN_WC__I_AM_WC_DB */
29251881Speter
30251881Speter#ifndef WC_DB_PRIVATE_H
31251881Speter#define WC_DB_PRIVATE_H
32251881Speter
33251881Speter#include "wc_db.h"
34251881Speter
35251881Speter
36251881Speterstruct svn_wc__db_t {
37251881Speter  /* We need the config whenever we run into a new WC directory, in order
38251881Speter     to figure out where we should look for the corresponding datastore. */
39251881Speter  svn_config_t *config;
40251881Speter
41251881Speter  /* Should we fail with SVN_ERR_WC_UPGRADE_REQUIRED when it is
42251881Speter     opened, and found to be not-current?  */
43251881Speter  svn_boolean_t verify_format;
44251881Speter
45251881Speter  /* Should we ensure the WORK_QUEUE is empty when a WCROOT is opened?  */
46251881Speter  svn_boolean_t enforce_empty_wq;
47251881Speter
48251881Speter  /* Should we open Sqlite databases EXCLUSIVE */
49251881Speter  svn_boolean_t exclusive;
50251881Speter
51251881Speter  /* Map a given working copy directory to its relevant data.
52251881Speter     const char *local_abspath -> svn_wc__db_wcroot_t *wcroot  */
53251881Speter  apr_hash_t *dir_data;
54251881Speter
55251881Speter  /* A few members to assist with caching of kind values for paths.  See
56251881Speter     get_path_kind() for use. */
57251881Speter  struct
58251881Speter  {
59251881Speter    svn_stringbuf_t *abspath;
60251881Speter    svn_node_kind_t kind;
61251881Speter  } parse_cache;
62251881Speter
63251881Speter  /* As we grow the state of this DB, allocate that state here. */
64251881Speter  apr_pool_t *state_pool;
65251881Speter};
66251881Speter
67251881Speter
68251881Speter/* Hold information about an owned lock */
69251881Spetertypedef struct svn_wc__db_wclock_t
70251881Speter{
71251881Speter  /* Relative path of the lock root */
72251881Speter  const char *local_relpath;
73251881Speter
74251881Speter  /* Number of levels locked (0 for infinity) */
75251881Speter  int levels;
76251881Speter} svn_wc__db_wclock_t;
77251881Speter
78251881Speter
79251881Speter/** Hold information about a WCROOT.
80251881Speter *
81251881Speter * This structure is referenced by all per-directory handles underneath it.
82251881Speter */
83251881Spetertypedef struct svn_wc__db_wcroot_t {
84251881Speter  /* Location of this wcroot in the filesystem.  */
85251881Speter  const char *abspath;
86251881Speter
87251881Speter  /* The SQLite database containing the metadata for everything in
88251881Speter     this wcroot.  */
89251881Speter  svn_sqlite__db_t *sdb;
90251881Speter
91251881Speter  /* The WCROOT.id for this directory (and all its children).  */
92251881Speter  apr_int64_t wc_id;
93251881Speter
94251881Speter  /* The format of this wcroot's metadata storage (see wc.h). If the
95251881Speter     format has not (yet) been determined, this will be UNKNOWN_FORMAT.  */
96251881Speter  int format;
97251881Speter
98251881Speter  /* Array of svn_wc__db_wclock_t structures (not pointers!).
99251881Speter     Typically just one or two locks maximum. */
100251881Speter  apr_array_header_t *owned_locks;
101251881Speter
102251881Speter  /* Map a working copy directory to a cached adm_access baton.
103251881Speter     const char *local_abspath -> svn_wc_adm_access_t *adm_access */
104251881Speter  apr_hash_t *access_cache;
105251881Speter
106251881Speter} svn_wc__db_wcroot_t;
107251881Speter
108251881Speter
109251881Speter/* */
110251881Spetersvn_error_t *
111251881Spetersvn_wc__db_close_many_wcroots(apr_hash_t *roots,
112251881Speter                              apr_pool_t *state_pool,
113251881Speter                              apr_pool_t *scratch_pool);
114251881Speter
115251881Speter
116251881Speter/* Construct a new svn_wc__db_wcroot_t. The WCROOT_ABSPATH and SDB parameters
117251881Speter   must have lifetime of at least RESULT_POOL.  */
118251881Spetersvn_error_t *
119251881Spetersvn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t **wcroot,
120251881Speter                             const char *wcroot_abspath,
121251881Speter                             svn_sqlite__db_t *sdb,
122251881Speter                             apr_int64_t wc_id,
123251881Speter                             int format,
124251881Speter                             svn_boolean_t verify_format,
125251881Speter                             svn_boolean_t enforce_empty_wq,
126251881Speter                             apr_pool_t *result_pool,
127251881Speter                             apr_pool_t *scratch_pool);
128251881Speter
129251881Speter
130251881Speter/* For a given LOCAL_ABSPATH, figure out what sqlite database (WCROOT) to
131251881Speter   use and the RELPATH within that wcroot.
132251881Speter
133251881Speter   *LOCAL_RELPATH will be allocated within RESULT_POOL. Temporary allocations
134251881Speter   will be made in SCRATCH_POOL.
135251881Speter
136251881Speter   *WCROOT will be allocated within DB->STATE_POOL.
137251881Speter
138251881Speter   Certain internal structures will be allocated in DB->STATE_POOL.
139251881Speter*/
140251881Spetersvn_error_t *
141251881Spetersvn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
142251881Speter                                      const char **local_relpath,
143251881Speter                                      svn_wc__db_t *db,
144251881Speter                                      const char *local_abspath,
145251881Speter                                      apr_pool_t *result_pool,
146251881Speter                                      apr_pool_t *scratch_pool);
147251881Speter
148251881Speter
149251881Speter/* Assert that the given WCROOT is usable.
150251881Speter   NOTE: the expression is multiply-evaluated!!  */
151251881Speter#define VERIFY_USABLE_WCROOT(wcroot)  SVN_ERR_ASSERT(               \
152251881Speter    (wcroot) != NULL && (wcroot)->format == SVN_WC__VERSION)
153251881Speter
154251881Speter/* Check if the WCROOT is usable for light db operations such as path
155251881Speter   calculations */
156251881Speter#define CHECK_MINIMAL_WCROOT(wcroot, abspath, scratch_pool)             \
157251881Speter    do                                                                  \
158251881Speter    {                                                                   \
159251881Speter      if (wcroot == NULL)                                               \
160251881Speter        return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,     \
161251881Speter                    _("The node '%s' is not in a working copy."),       \
162251881Speter                             svn_dirent_local_style(wri_abspath,        \
163251881Speter                                                    scratch_pool));     \
164251881Speter    }                                                                   \
165251881Speter    while (0)
166251881Speter
167251881Speter/* Calculates the depth of the relpath below "" */
168251881SpeterAPR_INLINE static int
169251881Speterrelpath_depth(const char *relpath)
170251881Speter{
171251881Speter  int n = 1;
172251881Speter  if (*relpath == '\0')
173251881Speter    return 0;
174251881Speter
175251881Speter  do
176251881Speter  {
177251881Speter    if (*relpath == '/')
178251881Speter      n++;
179251881Speter  }
180251881Speter  while (*(++relpath));
181251881Speter
182251881Speter  return n;
183251881Speter}
184251881Speter
185251881Speter
186251881Speter/* */
187251881Spetersvn_error_t *
188251881Spetersvn_wc__db_util_fetch_wc_id(apr_int64_t *wc_id,
189251881Speter                            svn_sqlite__db_t *sdb,
190251881Speter                            apr_pool_t *scratch_pool);
191251881Speter
192251881Speter/* Open a connection in *SDB to the WC database found in the WC metadata
193251881Speter * directory inside DIR_ABSPATH, having the filename SDB_FNAME.
194251881Speter *
195251881Speter * SMODE is passed to svn_sqlite__open().
196251881Speter *
197251881Speter * Register MY_STATEMENTS, or if that is null, the default set of WC DB
198251881Speter * statements, as the set of statements to be prepared now and executed
199251881Speter * later.  MY_STATEMENTS (the strings and the array itself) is not duplicated
200251881Speter * internally, and should have a lifetime at least as long as RESULT_POOL.
201251881Speter * See svn_sqlite__open() for details. */
202251881Spetersvn_error_t *
203251881Spetersvn_wc__db_util_open_db(svn_sqlite__db_t **sdb,
204251881Speter                        const char *dir_abspath,
205251881Speter                        const char *sdb_fname,
206251881Speter                        svn_sqlite__mode_t smode,
207251881Speter                        svn_boolean_t exclusive,
208251881Speter                        const char *const *my_statements,
209251881Speter                        apr_pool_t *result_pool,
210251881Speter                        apr_pool_t *scratch_pool);
211251881Speter
212251881Speter/* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
213251881Speter   DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
214251881Spetersvn_error_t *
215251881Spetersvn_wc__db_read_info_internal(svn_wc__db_status_t *status,
216251881Speter                              svn_node_kind_t *kind,
217251881Speter                              svn_revnum_t *revision,
218251881Speter                              const char **repos_relpath,
219251881Speter                              apr_int64_t *repos_id,
220251881Speter                              svn_revnum_t *changed_rev,
221251881Speter                              apr_time_t *changed_date,
222251881Speter                              const char **changed_author,
223251881Speter                              svn_depth_t *depth,
224251881Speter                              const svn_checksum_t **checksum,
225251881Speter                              const char **target,
226251881Speter                              const char **original_repos_relpath,
227251881Speter                              apr_int64_t *original_repos_id,
228251881Speter                              svn_revnum_t *original_revision,
229251881Speter                              svn_wc__db_lock_t **lock,
230251881Speter                              svn_filesize_t *recorded_size,
231251881Speter                              apr_time_t *recorded_mod_time,
232251881Speter                              const char **changelist,
233251881Speter                              svn_boolean_t *conflicted,
234251881Speter                              svn_boolean_t *op_root,
235251881Speter                              svn_boolean_t *had_props,
236251881Speter                              svn_boolean_t *props_mod,
237251881Speter                              svn_boolean_t *have_base,
238251881Speter                              svn_boolean_t *have_more_work,
239251881Speter                              svn_boolean_t *have_work,
240251881Speter                              svn_wc__db_wcroot_t *wcroot,
241251881Speter                              const char *local_relpath,
242251881Speter                              apr_pool_t *result_pool,
243251881Speter                              apr_pool_t *scratch_pool);
244251881Speter
245251881Speter/* Like svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH instead of
246251881Speter   DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
247251881Spetersvn_error_t *
248251881Spetersvn_wc__db_base_get_info_internal(svn_wc__db_status_t *status,
249251881Speter                                  svn_node_kind_t *kind,
250251881Speter                                  svn_revnum_t *revision,
251251881Speter                                  const char **repos_relpath,
252251881Speter                                  apr_int64_t *repos_id,
253251881Speter                                  svn_revnum_t *changed_rev,
254251881Speter                                  apr_time_t *changed_date,
255251881Speter                                  const char **changed_author,
256251881Speter                                  svn_depth_t *depth,
257251881Speter                                  const svn_checksum_t **checksum,
258251881Speter                                  const char **target,
259251881Speter                                  svn_wc__db_lock_t **lock,
260251881Speter                                  svn_boolean_t *had_props,
261251881Speter                                  apr_hash_t **props,
262251881Speter                                  svn_boolean_t *update_root,
263251881Speter                                  svn_wc__db_wcroot_t *wcroot,
264251881Speter                                  const char *local_relpath,
265251881Speter                                  apr_pool_t *result_pool,
266251881Speter                                  apr_pool_t *scratch_pool);
267251881Speter
268251881Speter/* Similar to svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH
269251881Speter * instead of DB+LOCAL_ABSPATH, an explicit op-depth of the node to get
270251881Speter * information about, and outputting REPOS_ID instead of URL+UUID, and
271251881Speter * without the LOCK or UPDATE_ROOT outputs.
272251881Speter *
273251881Speter * OR
274251881Speter *
275251881Speter * Similar to svn_wc__db_base_get_info_internal(), but taking an explicit
276251881Speter * op-depth OP_DEPTH of the node to get information about, and without the
277251881Speter * LOCK or UPDATE_ROOT outputs.
278251881Speter *
279251881Speter * ### [JAF] TODO: Harmonize svn_wc__db_base_get_info[_internal] with
280251881Speter * svn_wc__db_depth_get_info -- common API, common implementation.
281251881Speter */
282251881Spetersvn_error_t *
283251881Spetersvn_wc__db_depth_get_info(svn_wc__db_status_t *status,
284251881Speter                          svn_node_kind_t *kind,
285251881Speter                          svn_revnum_t *revision,
286251881Speter                          const char **repos_relpath,
287251881Speter                          apr_int64_t *repos_id,
288251881Speter                          svn_revnum_t *changed_rev,
289251881Speter                          apr_time_t *changed_date,
290251881Speter                          const char **changed_author,
291251881Speter                          svn_depth_t *depth,
292251881Speter                          const svn_checksum_t **checksum,
293251881Speter                          const char **target,
294251881Speter                          svn_boolean_t *had_props,
295251881Speter                          apr_hash_t **props,
296251881Speter                          svn_wc__db_wcroot_t *wcroot,
297251881Speter                          const char *local_relpath,
298251881Speter                          int op_depth,
299251881Speter                          apr_pool_t *result_pool,
300251881Speter                          apr_pool_t *scratch_pool);
301251881Speter
302251881Speter/* Look up REPOS_ID in SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID to
303251881Speter   its root URL and UUID respectively.  If REPOS_ID is INVALID_REPOS_ID,
304251881Speter   use NULL for both URL and UUID.  Either or both output parameters may be
305251881Speter   NULL if not wanted.  */
306251881Spetersvn_error_t *
307251881Spetersvn_wc__db_fetch_repos_info(const char **repos_root_url,
308251881Speter                            const char **repos_uuid,
309251881Speter                            svn_sqlite__db_t *sdb,
310251881Speter                            apr_int64_t repos_id,
311251881Speter                            apr_pool_t *result_pool);
312251881Speter
313251881Speter/* Like svn_wc__db_read_conflict(), but with WCROOT+LOCAL_RELPATH instead of
314251881Speter   DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
315251881Spetersvn_error_t *
316251881Spetersvn_wc__db_read_conflict_internal(svn_skel_t **conflict,
317251881Speter                                  svn_wc__db_wcroot_t *wcroot,
318251881Speter                                  const char *local_relpath,
319251881Speter                                  apr_pool_t *result_pool,
320251881Speter                                  apr_pool_t *scratch_pool);
321251881Speter
322251881Speter/* Like svn_wc__db_op_mark_conflict(), but with WCROOT+LOCAL_RELPATH instead of
323251881Speter   DB+LOCAL_ABSPATH. */
324251881Spetersvn_error_t *
325251881Spetersvn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
326251881Speter                                  const char *local_relpath,
327251881Speter                                  const svn_skel_t *conflict_skel,
328251881Speter                                  apr_pool_t *scratch_pool);
329251881Speter
330251881Speter
331251881Speter/* Transaction handling */
332251881Speter
333251881Speter/* A callback which supplies WCROOTs and LOCAL_RELPATHs. */
334251881Spetertypedef svn_error_t *(*svn_wc__db_txn_callback_t)(void *baton,
335251881Speter                                          svn_wc__db_wcroot_t *wcroot,
336251881Speter                                          const char *local_relpath,
337251881Speter                                          apr_pool_t *scratch_pool);
338251881Speter
339251881Speter
340251881Speter/* Run CB_FUNC in a SQLite transaction with CB_BATON, using WCROOT and
341251881Speter   LOCAL_RELPATH.  If callbacks require additional information, they may
342251881Speter   provide it using CB_BATON. */
343251881Spetersvn_error_t *
344251881Spetersvn_wc__db_with_txn(svn_wc__db_wcroot_t *wcroot,
345251881Speter                    const char *local_relpath,
346251881Speter                    svn_wc__db_txn_callback_t cb_func,
347251881Speter                    void *cb_baton,
348251881Speter                    apr_pool_t *scratch_pool);
349251881Speter
350251881Speter/* Evaluate the expression EXPR within a transaction.
351251881Speter *
352251881Speter * Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would
353251881Speter * typically be a function call that does some work in DB; finally commit
354251881Speter * the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
355251881Speter * the transaction.
356251881Speter */
357251881Speter#define SVN_WC__DB_WITH_TXN(expr, wcroot) \
358251881Speter  SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
359251881Speter
360251881Speter
361251881Speter/* Return CHILDREN mapping const char * names to svn_node_kind_t * for the
362251881Speter   children of LOCAL_RELPATH at OP_DEPTH. */
363251881Spetersvn_error_t *
364251881Spetersvn_wc__db_get_children_op_depth(apr_hash_t **children,
365251881Speter                                 svn_wc__db_wcroot_t *wcroot,
366251881Speter                                 const char *local_relpath,
367251881Speter                                 int op_depth,
368251881Speter                                 apr_pool_t *result_pool,
369251881Speter                                 apr_pool_t *scratch_pool);
370251881Speter
371251881Speter
372251881Speter/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
373251881Speter
374251881Speter   ### What about KIND and OP_DEPTH?  KIND ought to be redundant; I'm
375251881Speter       discussing on dev@ whether we can let that be null for presence
376251881Speter       == base-deleted.  OP_DEPTH is the op-depth of what, and why?
377251881Speter       It is used to select the lowest working node higher than OP_DEPTH,
378251881Speter       so, in terms of the API, OP_DEPTH means ...?
379251881Speter
380251881Speter   Given a wc:
381251881Speter
382251881Speter              0         1         2         3         4
383251881Speter              normal
384251881Speter   A          normal
385251881Speter   A/B        normal              normal
386251881Speter   A/B/C                          not-pres  normal
387251881Speter   A/B/C/D                                            normal
388251881Speter
389251881Speter   That is checkout, delete A/B, copy a replacement A/B, delete copied
390251881Speter   child A/B/C, add replacement A/B/C, add A/B/C/D.
391251881Speter
392251881Speter   Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
393251881Speter   must extend the A/B deletion:
394251881Speter
395251881Speter              0         1         2         3         4
396251881Speter              normal
397251881Speter   A          normal
398251881Speter   A/B        normal              normal
399251881Speter   A/B/C      normal              not-pres  normal
400251881Speter   A/B/C/D    normal              base-del            normal
401251881Speter   A/B/C/D/E  normal              base-del
402251881Speter
403251881Speter   When adding a node if the parent has a higher working node then the
404251881Speter   parent node is deleted (or replaced) and the delete must be extended
405251881Speter   to cover new node.
406251881Speter
407251881Speter   In the example above A/B/C/D and A/B/C/D/E are the nodes that get
408251881Speter   the extended delete, A/B/C is already deleted.
409251881Speter */
410251881Spetersvn_error_t *
411251881Spetersvn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
412251881Speter                                const char *local_relpath,
413251881Speter                                svn_node_kind_t kind,
414251881Speter                                int op_depth,
415251881Speter                                apr_pool_t *scratch_pool);
416251881Speter
417251881Spetersvn_error_t *
418251881Spetersvn_wc__db_retract_parent_delete(svn_wc__db_wcroot_t *wcroot,
419251881Speter                                 const char *local_relpath,
420251881Speter                                 int op_depth,
421251881Speter                                 apr_pool_t *scratch_pool);
422251881Speter
423251881Spetersvn_error_t *
424251881Spetersvn_wc__db_op_depth_moved_to(const char **move_dst_relpath,
425251881Speter                             const char **move_dst_op_root_relpath,
426251881Speter                             const char **move_src_root_relpath,
427251881Speter                             const char **move_src_op_root_relpath,
428251881Speter                             int op_depth,
429251881Speter                             svn_wc__db_wcroot_t *wcroot,
430251881Speter                             const char *local_relpath,
431251881Speter                             apr_pool_t *result_pool,
432251881Speter                             apr_pool_t *scratch_pool);
433251881Speter
434251881Speter/* Do a post-drive revision bump for the moved-away destination for
435251881Speter   any move sources under LOCAL_RELPATH.  This is called from within
436251881Speter   the revision bump transaction after the tree at LOCAL_RELPATH has
437251881Speter   been bumped. */
438251881Spetersvn_error_t *
439251881Spetersvn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot,
440251881Speter                           const char *local_relpath,
441251881Speter                           svn_depth_t depth,
442251881Speter                           svn_wc__db_t *db,
443251881Speter                           apr_pool_t *scratch_pool);
444251881Speter
445262253Speter/* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
446262253Speter   the destination a normal copy */
447251881Spetersvn_error_t *
448251881Spetersvn_wc__db_resolve_break_moved_away_internal(svn_wc__db_wcroot_t *wcroot,
449251881Speter                                             const char *local_relpath,
450262253Speter                                             int op_depth,
451251881Speter                                             apr_pool_t *scratch_pool);
452251881Speter
453251881Spetersvn_error_t *
454251881Spetersvn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
455251881Speter                                   svn_revnum_t old_revision,
456251881Speter                                   svn_revnum_t new_revision,
457251881Speter                                   svn_wc_notify_func2_t notify_func,
458251881Speter                                   void *notify_baton,
459251881Speter                                   apr_pool_t *scratch_pool);
460251881Speter
461251881Speter#endif /* WC_DB_PRIVATE_H */
462