blob: a9d7b0417566992c75612a89f5aa78f3519755d2 [file] [log] [blame]
/**
* @copyright
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
* @endcopyright
*/
/* This file is not for general consumption; it should only be used by
wc_db.c. */
#ifndef SVN_WC__I_AM_WC_DB
#error "You should not be using these data structures directly"
#endif /* SVN_WC__I_AM_WC_DB */
#ifndef WC_DB_PRIVATE_H
#define WC_DB_PRIVATE_H
#include "wc_db.h"
struct svn_wc__db_t {
/* We need the config whenever we run into a new WC directory, in order
to figure out where we should look for the corresponding datastore. */
svn_config_t *config;
/* Should we fail with SVN_ERR_WC_UPGRADE_REQUIRED when it is
opened, and found to be not-current? */
svn_boolean_t verify_format;
/* Should we ensure the WORK_QUEUE is empty when a DB is locked
* for writing? */
svn_boolean_t enforce_empty_wq;
/* Should we open Sqlite databases EXCLUSIVE */
svn_boolean_t exclusive;
/* Busy timeout in ms., 0 for the libsvn_subr default. */
apr_int32_t timeout;
/* Map a given working copy directory to its relevant data.
const char *local_abspath -> svn_wc__db_wcroot_t *wcroot */
apr_hash_t *dir_data;
/* A few members to assist with caching of kind values for paths. See
get_path_kind() for use. */
struct
{
svn_stringbuf_t *abspath;
svn_node_kind_t kind;
} parse_cache;
/* As we grow the state of this DB, allocate that state here. */
apr_pool_t *state_pool;
};
/* Hold information about an owned lock */
typedef struct svn_wc__db_wclock_t
{
/* Relative path of the lock root */
const char *local_relpath;
/* Number of levels locked (0 for infinity) */
int levels;
} svn_wc__db_wclock_t;
/** Hold information about a WCROOT.
*
* This structure is referenced by all per-directory handles underneath it.
*/
typedef struct svn_wc__db_wcroot_t {
/* Location of this wcroot in the filesystem. */
const char *abspath;
/* The SQLite database containing the metadata for everything in
this wcroot. */
svn_sqlite__db_t *sdb;
/* The WCROOT.id for this directory (and all its children). */
apr_int64_t wc_id;
/* The format of this wcroot's metadata storage (see wc.h). If the
format has not (yet) been determined, this will be UNKNOWN_FORMAT. */
int format;
/* Array of svn_wc__db_wclock_t structures (not pointers!).
Typically just one or two locks maximum. */
apr_array_header_t *owned_locks;
/* Map a working copy directory to a cached adm_access baton.
const char *local_abspath -> svn_wc_adm_access_t *adm_access */
apr_hash_t *access_cache;
} svn_wc__db_wcroot_t;
/* */
svn_error_t *
svn_wc__db_close_many_wcroots(apr_hash_t *roots,
apr_pool_t *state_pool,
apr_pool_t *scratch_pool);
/* Construct a new svn_wc__db_wcroot_t. The WCROOT_ABSPATH and SDB parameters
must have lifetime of at least RESULT_POOL. */
svn_error_t *
svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t **wcroot,
const char *wcroot_abspath,
svn_sqlite__db_t *sdb,
apr_int64_t wc_id,
int format,
svn_boolean_t verify_format,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* For a given LOCAL_ABSPATH, figure out what sqlite database (WCROOT) to
use and the RELPATH within that wcroot.
*LOCAL_RELPATH will be allocated within RESULT_POOL. Temporary allocations
will be made in SCRATCH_POOL.
*WCROOT will be allocated within DB->STATE_POOL.
Certain internal structures will be allocated in DB->STATE_POOL.
*/
svn_error_t *
svn_wc__db_wcroot_parse_local_abspath(svn_wc__db_wcroot_t **wcroot,
const char **local_relpath,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Return an error if the work queue in SDB is non-empty. */
svn_error_t *
svn_wc__db_verify_no_work(svn_sqlite__db_t *sdb);
/* Assert that the given WCROOT is usable.
NOTE: the expression is multiply-evaluated!! */
#define VERIFY_USABLE_WCROOT(wcroot) SVN_ERR_ASSERT( \
(wcroot) != NULL && (wcroot)->format == SVN_WC__VERSION)
/* Check if the WCROOT is usable for light db operations such as path
calculations */
#define CHECK_MINIMAL_WCROOT(wcroot, abspath, scratch_pool) \
do \
{ \
if (wcroot == NULL) \
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, \
_("The node '%s' is not in a working copy."), \
svn_dirent_local_style(wri_abspath, \
scratch_pool)); \
} \
while (0)
/* Calculates the depth of the relpath below "" */
APR_INLINE static int
relpath_depth(const char *relpath)
{
int n = 1;
if (*relpath == '\0')
return 0;
do
{
if (*relpath == '/')
n++;
}
while (*(++relpath));
return n;
}
/* */
svn_error_t *
svn_wc__db_util_fetch_wc_id(apr_int64_t *wc_id,
svn_sqlite__db_t *sdb,
apr_pool_t *scratch_pool);
/* Open a connection in *SDB to the WC database found in the WC metadata
* directory inside DIR_ABSPATH, having the filename SDB_FNAME.
*
* SMODE, EXCLUSIVE and TIMEOUT are passed to svn_sqlite__open().
*
* Register MY_STATEMENTS, or if that is null, the default set of WC DB
* statements, as the set of statements to be prepared now and executed
* later. MY_STATEMENTS (the strings and the array itself) is not duplicated
* internally, and should have a lifetime at least as long as RESULT_POOL.
* See svn_sqlite__open() for details. */
svn_error_t *
svn_wc__db_util_open_db(svn_sqlite__db_t **sdb,
const char *dir_abspath,
const char *sdb_fname,
svn_sqlite__mode_t smode,
svn_boolean_t exclusive,
apr_int32_t timeout,
const char *const *my_statements,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_wq_add() but taking WCROOT */
svn_error_t *
svn_wc__db_wq_add_internal(svn_wc__db_wcroot_t *wcroot,
const svn_skel_t *work_item,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */
svn_error_t *
svn_wc__db_read_info_internal(svn_wc__db_status_t *status,
svn_node_kind_t *kind,
svn_revnum_t *revision,
const char **repos_relpath,
apr_int64_t *repos_id,
svn_revnum_t *changed_rev,
apr_time_t *changed_date,
const char **changed_author,
svn_depth_t *depth,
const svn_checksum_t **checksum,
const char **target,
const char **original_repos_relpath,
apr_int64_t *original_repos_id,
svn_revnum_t *original_revision,
svn_wc__db_lock_t **lock,
svn_filesize_t *recorded_size,
apr_time_t *recorded_mod_time,
const char **changelist,
svn_boolean_t *conflicted,
svn_boolean_t *op_root,
svn_boolean_t *had_props,
svn_boolean_t *props_mod,
svn_boolean_t *have_base,
svn_boolean_t *have_more_work,
svn_boolean_t *have_work,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
svn_error_t *
svn_wc__db_base_get_info_internal(svn_wc__db_status_t *status,
svn_node_kind_t *kind,
svn_revnum_t *revision,
const char **repos_relpath,
apr_int64_t *repos_id,
svn_revnum_t *changed_rev,
apr_time_t *changed_date,
const char **changed_author,
svn_depth_t *depth,
const svn_checksum_t **checksum,
const char **target,
svn_wc__db_lock_t **lock,
svn_boolean_t *had_props,
apr_hash_t **props,
svn_boolean_t *update_root,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Similar to svn_wc__db_base_get_info(), but taking WCROOT+LOCAL_RELPATH
* instead of DB+LOCAL_ABSPATH, an explicit op-depth of the node to get
* information about, and outputting REPOS_ID instead of URL+UUID, and
* without the LOCK or UPDATE_ROOT outputs.
*
* OR
*
* Similar to svn_wc__db_base_get_info_internal(), but taking an explicit
* op-depth OP_DEPTH of the node to get information about, and without the
* LOCK or UPDATE_ROOT outputs.
*
* ### [JAF] TODO: Harmonize svn_wc__db_base_get_info[_internal] with
* svn_wc__db_depth_get_info -- common API, common implementation.
*/
svn_error_t *
svn_wc__db_depth_get_info(svn_wc__db_status_t *status,
svn_node_kind_t *kind,
svn_revnum_t *revision,
const char **repos_relpath,
apr_int64_t *repos_id,
svn_revnum_t *changed_rev,
apr_time_t *changed_date,
const char **changed_author,
svn_depth_t *depth,
const svn_checksum_t **checksum,
const char **target,
svn_boolean_t *had_props,
apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_scan_addition_internal(
svn_wc__db_status_t *status,
const char **op_root_relpath_p,
const char **repos_relpath,
apr_int64_t *repos_id,
const char **original_repos_relpath,
apr_int64_t *original_repos_id,
svn_revnum_t *original_revision,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_scan_deletion_internal(
const char **base_del_relpath,
const char **moved_to_relpath,
const char **work_del_relpath,
const char **moved_to_op_root_relpath,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Look up REPOS_ID in WCROOT->SDB and set *REPOS_ROOT_URL and/or *REPOS_UUID
to its root URL and UUID respectively. If REPOS_ID is INVALID_REPOS_ID,
use NULL for both URL and UUID. Either or both output parameters may be
NULL if not wanted. */
svn_error_t *
svn_wc__db_fetch_repos_info(const char **repos_root_url,
const char **repos_uuid,
svn_wc__db_wcroot_t *wcroot,
apr_int64_t repos_id,
apr_pool_t *result_pool);
/* Like svn_wc__db_read_conflict(), but with WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
svn_error_t *
svn_wc__db_read_conflict_internal(svn_skel_t **conflict,
svn_node_kind_t *kind,
apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_op_mark_conflict(), but with WCROOT+LOCAL_RELPATH instead of
DB+LOCAL_ABSPATH. */
svn_error_t *
svn_wc__db_mark_conflict_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
const svn_skel_t *conflict_skel,
apr_pool_t *scratch_pool);
/* Transaction handling */
/* Evaluate the expression EXPR within a transaction.
*
* Begin a transaction in WCROOT's DB; evaluate the expression EXPR, which would
* typically be a function call that does some work in DB; finally commit
* the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
* the transaction.
*/
#define SVN_WC__DB_WITH_TXN(expr, wcroot) \
SVN_SQLITE__WITH_LOCK(expr, (wcroot)->sdb)
/* Evaluate the expressions EXPR1..EXPR4 within a transaction, returning the
* first error if an error occurs.
*
* Begin a transaction in WCROOT's DB; evaluate the expressions, which would
* typically be function calls that do some work in DB; finally commit
* the transaction if EXPR evaluated to SVN_NO_ERROR, otherwise roll back
* the transaction.
*/
#define SVN_WC__DB_WITH_TXN4(expr1, expr2, expr3, expr4, wcroot) \
SVN_SQLITE__WITH_LOCK4(expr1, expr2, expr3, expr4, (wcroot)->sdb)
/* Update the single op-depth layer in the move destination subtree
rooted at DST_RELPATH to make it match the move source subtree
rooted at SRC_RELPATH. */
svn_error_t *
svn_wc__db_op_copy_layer_internal(svn_wc__db_wcroot_t *wcroot,
const char *src_op_relpath,
int src_op_depth,
const char *dst_op_relpath,
svn_skel_t *conflict,
svn_skel_t *work_items,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_op_make_copy but with wcroot, local_relpath */
svn_error_t *
svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_boolean_t move_move_info,
const svn_skel_t *conflicts,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
/* Extract the moved-to information for LOCAL_RELPATH as it existed
at OP-DEPTH. The output paths are optional and set to NULL
if there is no move, otherwise:
*MOVE_SRC_RELPATH: the path that was moved (LOCAL_RELPATH or one
of its ancestors)
*MOVE_DST_RELPATH: The path *MOVE_SRC_RELPATH was moved to.
*DELETE_RELPATH: The path at which LOCAL_RELPATH was removed (
*MOVE_SRC_RELPATH or one of its ancestors)
Given a path A/B/C with A/B moved to X and A deleted then for A/B/C:
MOVE_SRC_RELPATH is A/B
MOVE_DST_RELPATH is X
DELETE_RELPATH is A
X/C can be calculated if necessesary, like with the other
scan functions.
This function returns SVN_ERR_WC_PATH_NOT_FOUND if LOCAL_RELPATH didn't
exist at OP_DEPTH, or when it is not shadowed.
### Think about combining with scan_deletion? Also with
### scan_addition to get moved-to for replaces? Do we need to
### return the op-root of the move source, i.e. A/B in the example
### above? */
svn_error_t *
svn_wc__db_scan_moved_to_internal(const char **move_src_relpath,
const char **move_dst_relpath,
const char **delete_relpath,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_op_set_props, but updates ACTUAL_NODE directly without
comparing with the pristine properties, etc.
*/
svn_error_t *
svn_wc__db_op_set_props_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_hash_t *props,
svn_boolean_t clear_recorded_info,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_read_props_internal(apr_hash_t **props,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_wc__db_wclock_owns_lock() but taking WCROOT+LOCAL_RELPATH instead
of DB+LOCAL_ABSPATH. */
svn_error_t *
svn_wc__db_wclock_owns_lock_internal(svn_boolean_t *own_lock,
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_boolean_t exact,
apr_pool_t *scratch_pool);
/* Do a post-drive revision bump for the moved-away destination for
any move sources under LOCAL_RELPATH. This is called from within
the revision bump transaction after the tree at LOCAL_RELPATH has
been bumped. */
svn_error_t *
svn_wc__db_bump_moved_away(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_depth_t depth,
svn_wc__db_t *db,
apr_pool_t *scratch_pool);
/* Unbreak the move from LOCAL_RELPATH on op-depth in WCROOT, by making
the destination DST_RELPATH a normal copy. SRC_OP_DEPTH is the op-depth
where the move_to information is stored */
svn_error_t *
svn_wc__db_op_break_move_internal(svn_wc__db_wcroot_t *wcroot,
const char *src_relpath,
int delete_op_depth,
const char *dst_relpath,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_wc__db_t *db,
svn_boolean_t resolved_text,
svn_boolean_t resolved_props,
svn_boolean_t resolved_tree,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool);
/* op_depth is the depth at which the node is added. */
svn_error_t *
svn_wc__db_op_raise_moved_away_internal(
svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
svn_wc__db_t *db,
svn_wc_operation_t operation,
svn_wc_conflict_action_t action,
const svn_wc_conflict_version_t *old_version,
const svn_wc_conflict_version_t *new_version,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_update_move_list_notify(svn_wc__db_wcroot_t *wcroot,
svn_revnum_t old_revision,
svn_revnum_t new_revision,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
svn_error_t *
svn_wc__db_verify_db_full_internal(svn_wc__db_wcroot_t *wcroot,
svn_wc__db_verify_cb_t callback,
void *baton,
apr_pool_t *scratch_pool);
#endif /* WC_DB_PRIVATE_H */