You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/15 21:32:38 UTC
svn commit: r997472 [28/41] - in /subversion/branches/py-tests-as-modules:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/
subversion/bindings/javahl/native/ subversi...
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/wc_db.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/wc_db.c Wed Sep 15 19:32:26 2010
@@ -52,8 +52,7 @@
#include "private/svn_token.h"
-#define NOT_IMPLEMENTED() \
- return svn_error__malfunction(TRUE, __FILE__, __LINE__, "Not implemented.")
+#define NOT_IMPLEMENTED() SVN__NOT_IMPLEMENTED()
/*
@@ -105,31 +104,30 @@
#define UNKNOWN_WC_ID ((apr_int64_t) -1)
#define FORMAT_FROM_SDB (-1)
-
-/* Assert that the given PDH is usable.
- NOTE: the expression is multiply-evaluated!! */
-#define VERIFY_USABLE_PDH(pdh) SVN_ERR_ASSERT( \
- (pdh)->wcroot != NULL \
- && (pdh)->wcroot->format == SVN_WC__VERSION)
-
-
-/* ### since we're putting the pristine files per-dir, then we don't need
- ### to create subdirectories in order to keep the directory size down.
- ### when we can aggregate pristine files across dirs/wcs, then we will
- ### need to undo the SKIP. */
-#define SVN__SKIP_SUBDIR
-
-WC_QUERIES_SQL_DECLARE_STATEMENTS(statements);
-
-
/* This is a character used to escape itself and the globbing character in
globbing sql expressions below. See escape_sqlite_like().
NOTE: this should match the character used within wc-metadata.sql */
#define LIKE_ESCAPE_CHAR "#"
+/* Calculates the depth of the relpath below "" */
+APR_INLINE static int relpath_op_depth(const char *relpath)
+{
+ int n = 1;
+ if (*relpath == '\0')
+ return 0;
-typedef struct {
+ do
+ {
+ if (*relpath == '/')
+ n++;
+ }
+ while (*(++relpath));
+
+ return n;
+}
+
+typedef struct insert_base_baton_t {
/* common to all insertions into BASE */
svn_wc__db_status_t status;
svn_wc__db_kind_t kind;
@@ -144,6 +142,7 @@ typedef struct {
svn_revnum_t changed_rev;
apr_time_t changed_date;
const char *changed_author;
+ apr_hash_t *dav_cache;
/* for inserting directories */
const apr_array_header_t *children;
@@ -166,11 +165,12 @@ typedef struct {
typedef struct {
- /* common to all insertions into WORKING */
+ /* common to all insertions into WORKING (including NODE_DATA) */
svn_wc__db_status_t presence;
svn_wc__db_kind_t kind;
apr_int64_t wc_id;
const char *local_relpath;
+ apr_int64_t op_depth;
/* common to all "normal" presence insertions */
const apr_hash_t *props;
@@ -202,7 +202,6 @@ static const svn_token_map_t kind_map[]
{ "file", svn_wc__db_kind_file },
{ "dir", svn_wc__db_kind_dir },
{ "symlink", svn_wc__db_kind_symlink },
- { "subdir", svn_wc__db_kind_subdir },
{ "unknown", svn_wc__db_kind_unknown },
{ NULL }
};
@@ -281,15 +280,15 @@ escape_sqlite_like(const char * const st
to hold CHECKSUM's pristine file, relating to the pristine store
configured for the working copy indicated by PDH. The returned path
does not necessarily currently exist.
-#ifndef SVN__SKIP_SUBDIR
+
Iff CREATE_SUBDIR is TRUE, then this function will make sure that the
parent directory of PRISTINE_ABSPATH exists. This is only useful when
about to create a new pristine.
-#endif
+
Any other allocations are made in SCRATCH_POOL. */
static svn_error_t *
get_pristine_fname(const char **pristine_abspath,
- svn_wc__db_pdh_t *pdh,
+ const char *wcroot_abspath,
const svn_checksum_t *sha1_checksum,
svn_boolean_t create_subdir,
apr_pool_t *result_pool,
@@ -297,13 +296,11 @@ get_pristine_fname(const char **pristine
{
const char *base_dir_abspath;
const char *hexdigest = svn_checksum_to_cstring(sha1_checksum, scratch_pool);
-#ifndef SVN__SKIP_SUBDIR
char subdir[3];
-#endif
/* ### code is in transition. make sure we have the proper data. */
SVN_ERR_ASSERT(pristine_abspath != NULL);
- SVN_ERR_ASSERT(pdh->wcroot != NULL);
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(wcroot_abspath));
SVN_ERR_ASSERT(sha1_checksum != NULL);
SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
@@ -311,7 +308,7 @@ get_pristine_fname(const char **pristine
### to use join_many since we know "/" is the separator for
### internal canonical paths */
base_dir_abspath = svn_dirent_join_many(scratch_pool,
- pdh->wcroot->abspath,
+ wcroot_abspath,
svn_wc_get_adm_dir(scratch_pool),
PRISTINE_STORAGE_RELPATH,
NULL);
@@ -319,7 +316,6 @@ get_pristine_fname(const char **pristine
/* We should have a valid checksum and (thus) a valid digest. */
SVN_ERR_ASSERT(hexdigest != NULL);
-#ifndef SVN__SKIP_SUBDIR
/* Get the first two characters of the digest, for the subdir. */
subdir[0] = hexdigest[0];
subdir[1] = hexdigest[1];
@@ -339,14 +335,11 @@ get_pristine_fname(const char **pristine
try to access the file within this (missing?) pristine subdir. */
svn_error_clear(err);
}
-#endif
/* The file is located at DIR/.svn/pristine/XX/XXYYZZ... */
*pristine_abspath = svn_dirent_join_many(result_pool,
base_dir_abspath,
-#ifndef SVN__SKIP_SUBDIR
subdir,
-#endif
hexdigest,
NULL);
return SVN_NO_ERROR;
@@ -381,6 +374,94 @@ fetch_repos_info(const char **repos_root
return svn_error_return(svn_sqlite__reset(stmt));
}
+#ifdef SVN_WC__NODES
+
+/* Can't verify if we only have the NODES table */
+#ifndef SVN_WC__NODES_ONLY
+
+/* */
+static svn_error_t *
+assert_text_columns_equal(svn_sqlite__stmt_t *stmt1,
+ svn_sqlite__stmt_t *stmt2,
+ int column,
+ apr_pool_t *scratch_pool)
+{
+ const char *val1 = svn_sqlite__column_text(stmt1, column, scratch_pool);
+ const char *val2 = svn_sqlite__column_text(stmt2, column, scratch_pool);
+
+ if (val1 != NULL && val2 != NULL) {
+ if (strcmp(val1, val2) != 0)
+ return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ "Value in statement 1 (%s) differs from value in statement 2 (%s)",
+ val1, val2);
+ } else if (val1 == NULL && val2 == NULL) {
+ /* Do nothing: equal */
+ } else
+ return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ "Value in statement 1 (%s) differs from value in statement 2 (%s)",
+ val1, val2);
+
+ return SVN_NO_ERROR;
+}
+
+#endif
+
+static svn_error_t *
+assert_base_rows_match(svn_boolean_t have_row1,
+ svn_boolean_t have_row2,
+ svn_sqlite__stmt_t *stmt1,
+ svn_sqlite__stmt_t *stmt2,
+ const char *relpath,
+ apr_pool_t *scratch_pool)
+{
+
+ if (have_row1 != have_row2)
+ SVN_ERR(svn_error_createf(
+ SVN_ERR_WC_CORRUPT, NULL,
+ "Different results from BASE (%d) and NODES queries (%d), "
+ "for local_relpath %s",
+ have_row1, have_row2, relpath));
+
+ if (have_row1) {
+ SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 0)
+ == svn_sqlite__column_int64(stmt2, 0));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 1, scratch_pool));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 2, scratch_pool));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 3, scratch_pool));
+
+ SVN_ERR_ASSERT(svn_sqlite__column_revnum(stmt1, 4)
+ == svn_sqlite__column_revnum(stmt2, 4));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 5, scratch_pool));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 6, scratch_pool));
+
+ SVN_ERR_ASSERT(svn_sqlite__column_revnum(stmt1, 7)
+ == svn_sqlite__column_revnum(stmt2, 7));
+
+
+ SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 8)
+ == svn_sqlite__column_int64(stmt2, 8));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 9, scratch_pool));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 10, scratch_pool));
+
+ SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 11, scratch_pool));
+
+ SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 12)
+ == svn_sqlite__column_int64(stmt2, 12));
+
+ /* 14: verify props? */
+ }
+
+ return SVN_NO_ERROR;
+}
+
+#endif
/* Scan from LOCAL_RELPATH upwards through parent nodes until we find a parent
that has values in the 'repos_id' and 'repos_relpath' columns. Return
@@ -401,20 +482,52 @@ scan_upwards_for_repos(apr_int64_t *repo
const char *current_relpath = local_relpath;
svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *data_stmt;
+#endif
+
SVN_ERR_ASSERT(wcroot->sdb != NULL && wcroot->wc_id != UNKNOWN_WC_ID);
SVN_ERR_ASSERT(repos_id != NULL || repos_relpath != NULL);
+#ifndef SVN_WC__NODES_ONLY
/* ### is it faster to fetch fewer columns? */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_BASE_NODE));
+#endif
+
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&data_stmt, wcroot->sdb,
+ STMT_SELECT_BASE_NODE_1));
+#endif
while (TRUE)
{
svn_boolean_t have_row;
+#ifdef SVN_WC__NODES
+ svn_boolean_t have_data_row;
+#endif
+#ifndef SVN_WC__NODES_ONLY
/* Get the current node's repository information. */
SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+
+ /* Get the current node's repository information. */
+ SVN_ERR(svn_sqlite__bindf(data_stmt, "is",
+ wcroot->wc_id, current_relpath));
+ SVN_ERR(svn_sqlite__step(&have_data_row, data_stmt));
+
+#ifndef SVN_WC__NODES_ONLY
+ /* When switching to NODES_ONLY, stop verifying our results. */
+ SVN_ERR(assert_base_rows_match(have_row, have_data_row,
+ stmt, data_stmt,
+ current_relpath,
+ scratch_pool));
+#endif
+#endif
if (!have_row)
{
@@ -437,6 +550,9 @@ scan_upwards_for_repos(apr_int64_t *repo
svn_dirent_local_style(local_abspath, scratch_pool));
}
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__reset(data_stmt));
+#endif
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
}
@@ -456,10 +572,17 @@ scan_upwards_for_repos(apr_int64_t *repo
NULL),
relpath_suffix,
result_pool);
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__reset(data_stmt));
+#endif
return svn_sqlite__reset(stmt);
}
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__reset(data_stmt));
+#endif
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__reset(stmt));
-
+#endif
if (*current_relpath == '\0')
{
/* We scanned all the way up, and did not find the information.
@@ -472,7 +595,7 @@ scan_upwards_for_repos(apr_int64_t *repo
/* Strip a path segment off the end, and append it to the suffix
that we'll use when we finally find a base relpath. */
- svn_relpath_split(current_relpath, ¤t_relpath, ¤t_basename,
+ svn_relpath_split(¤t_relpath, ¤t_basename, current_relpath,
scratch_pool);
relpath_suffix = svn_relpath_join(relpath_suffix, current_basename,
scratch_pool);
@@ -516,54 +639,6 @@ get_statement_for_path(svn_sqlite__stmt_
}
-/* */
-static svn_error_t *
-navigate_to_parent(svn_wc__db_pdh_t **parent_pdh,
- svn_wc__db_t *db,
- svn_wc__db_pdh_t *child_pdh,
- svn_sqlite__mode_t smode,
- apr_pool_t *scratch_pool)
-{
- const char *parent_abspath;
- const char *local_relpath;
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t got_row;
-
- if ((*parent_pdh = child_pdh->parent) != NULL
- && (*parent_pdh)->wcroot != NULL)
- return SVN_NO_ERROR;
-
- /* Make sure we don't see the root as its own parent */
- SVN_ERR_ASSERT(!svn_dirent_is_root(child_pdh->local_abspath,
- strlen(child_pdh->local_abspath)));
-
- parent_abspath = svn_dirent_dirname(child_pdh->local_abspath, scratch_pool);
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(parent_pdh, &local_relpath, db,
- parent_abspath, smode,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(*parent_pdh);
-
- /* Check that the parent has an entry for the child */
- SVN_ERR(svn_sqlite__get_statement(&stmt, (*parent_pdh)->wcroot->sdb,
- STMT_SELECT_SUBDIR));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", (*parent_pdh)->wcroot->wc_id,
- svn_dirent_basename(child_pdh->local_abspath,
- NULL)));
- SVN_ERR(svn_sqlite__step(&got_row, stmt));
- SVN_ERR(svn_sqlite__reset(stmt));
-
- if (!got_row)
- return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
- _("'%s' does not have a parent."),
- svn_dirent_local_style(child_pdh->local_abspath,
- scratch_pool));
-
- child_pdh->parent = *parent_pdh;
-
- return SVN_NO_ERROR;
-}
-
-
/* For a given REPOS_ROOT_URL/REPOS_UUID pair, return the existing REPOS_ID
value. If one does not exist, then create a new one. */
static svn_error_t *
@@ -623,29 +698,28 @@ insert_base_node(void *baton, svn_sqlite
{
const insert_base_baton_t *pibb = baton;
svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *stmt_node;
+#endif
+ /* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
+ bind the appropriate parent_relpath. */
+ const char *parent_relpath =
+ (*pibb->local_relpath == '\0') ? NULL
+ : svn_relpath_dirname(pibb->local_relpath, scratch_pool);
/* ### we can't handle this right now */
SVN_ERR_ASSERT(pibb->conflict == NULL);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", pibb->wc_id, pibb->local_relpath));
-
- if (TRUE /* maybe_bind_repos() */)
- {
- SVN_ERR(svn_sqlite__bind_int64(stmt, 3, pibb->repos_id));
- SVN_ERR(svn_sqlite__bind_text(stmt, 4, pibb->repos_relpath));
- }
-
- /* The directory at the WCROOT has a NULL parent_relpath. Otherwise,
- bind the appropriate parent_relpath. */
- if (*pibb->local_relpath != '\0')
- SVN_ERR(svn_sqlite__bind_text(stmt, 5,
- svn_relpath_dirname(pibb->local_relpath,
- scratch_pool)));
-
- SVN_ERR(svn_sqlite__bind_token(stmt, 6, presence_map, pibb->status));
- SVN_ERR(svn_sqlite__bind_token(stmt, 7, kind_map, pibb->kind));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 8, pibb->revision));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isissttr",
+ pibb->wc_id, pibb->local_relpath,
+ pibb->repos_id,
+ pibb->repos_relpath,
+ parent_relpath,
+ presence_map, pibb->status,
+ kind_map, pibb->kind,
+ pibb->revision));
SVN_ERR(svn_sqlite__bind_properties(stmt, 9, pibb->props, scratch_pool));
@@ -674,20 +748,72 @@ insert_base_node(void *baton, svn_sqlite
SVN_ERR(svn_sqlite__bind_text(stmt, 16, pibb->target));
}
+ if (pibb->dav_cache)
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 17, pibb->dav_cache,
+ scratch_pool));
+
SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb, STMT_INSERT_NODE));
+ { svn_revnum_t rev = pibb->changed_rev;
+ SVN_ERR(svn_sqlite__bindf(stmt_node, "isisisr"
+ "tstr" /* 8 - 11 */
+ "isnnnnns", /* 12 - 19 */
+ pibb->wc_id, /* 1 */
+ pibb->local_relpath, /* 2 */
+ (apr_int64_t)0, /* op_depth is 0 for base */
+ parent_relpath, /* 4 */
+ pibb->repos_id,
+ pibb->repos_relpath,
+ pibb->revision,
+ presence_map, pibb->status, /* 8 */
+ (pibb->kind == svn_wc__db_kind_dir) ? /* 9 */
+ svn_depth_to_word(pibb->depth) : NULL,
+ kind_map, pibb->kind, /* 10 */
+ rev, /* 11 */
+ pibb->changed_date, /* 12 */
+ pibb->changed_author, /* 13 */
+ (pibb->kind == svn_wc__db_kind_symlink) ?
+ pibb->target : NULL)); /* 19 */
+ }
+
+ if (pibb->kind == svn_wc__db_kind_file) {
+ SVN_ERR(svn_sqlite__bind_checksum(stmt_node, 14, pibb->checksum,
+ scratch_pool));
+ if (pibb->translated_size != SVN_INVALID_FILESIZE)
+ SVN_ERR(svn_sqlite__bind_int64(stmt_node, 16, pibb->translated_size));
+ }
+
+ SVN_ERR(svn_sqlite__bind_properties(stmt_node, 15, pibb->props,
+ scratch_pool));
+ if (pibb->dav_cache)
+ SVN_ERR(svn_sqlite__bind_properties(stmt_node, 18, pibb->dav_cache,
+ scratch_pool));
+
+ SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
+#endif
if (pibb->kind == svn_wc__db_kind_dir && pibb->children)
{
int i;
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_BASE_NODE_INCOMPLETE));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb,
+ STMT_INSERT_NODE));
+#endif
for (i = pibb->children->nelts; i--; )
{
const char *name = APR_ARRAY_IDX(pibb->children, i, const char *);
- SVN_ERR(svn_sqlite__bindf(stmt, "issi",
+#ifndef SVN_WC__NODES_ONLY
+ SVN_ERR(svn_sqlite__bindf(stmt, "issr",
pibb->wc_id,
svn_relpath_join(pibb->local_relpath,
name,
@@ -695,6 +821,20 @@ insert_base_node(void *baton, svn_sqlite
pibb->local_relpath,
(apr_int64_t)pibb->revision));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__bindf(stmt_node, "isisnnrsns",
+ pibb->wc_id,
+ svn_relpath_join(pibb->local_relpath,
+ name,
+ scratch_pool),
+ (apr_int64_t)0 /* BASE */,
+ pibb->local_relpath, /* parent_relpath */
+ pibb->revision,
+ "incomplete",
+ "unknown"));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
+#endif
}
}
@@ -715,6 +855,43 @@ blank_iwb(insert_working_baton_t *piwb)
value, but... meh. We'll avoid them if ORIGINAL_REPOS_RELPATH==NULL. */
}
+/* */
+static svn_error_t *
+copy_working_from_base(void *baton,
+ svn_sqlite__db_t *sdb,
+ apr_pool_t *scratch_pool)
+{
+ const insert_working_baton_t *piwb = baton;
+ svn_sqlite__stmt_t *stmt;
+
+#ifdef SVN_WC__NODES
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isit", piwb->wc_id,
+ piwb->local_relpath,
+ piwb->op_depth,
+ presence_map, piwb->presence));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#endif
+
+#ifndef SVN_WC__NODES_ONLY
+ /* Run the sequence below instead, which copies all the columns, including
+ those with the restrictions */
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "ist", piwb->wc_id, piwb->local_relpath,
+ presence_map, piwb->presence));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+
+
static svn_error_t *
insert_incomplete_working_children(svn_sqlite__db_t *sdb,
apr_int64_t wc_id,
@@ -722,22 +899,49 @@ insert_incomplete_working_children(svn_s
const apr_array_header_t *children,
apr_pool_t *scratch_pool)
{
+#ifndef SVN_WC__NODES_ONLY
svn_sqlite__stmt_t *stmt;
+#endif
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *stmt_node;
+#endif
int i;
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_WORKING_NODE_INCOMPLETE));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb,
+ STMT_INSERT_NODE));
+#endif
+
for (i = children->nelts; i--; )
{
const char *name = APR_ARRAY_IDX(children, i, const char *);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__bindf(stmt, "iss",
wc_id,
svn_relpath_join(local_relpath, name,
scratch_pool),
local_relpath));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__bindf(stmt_node, "isisnnnsns",
+ wc_id,
+ svn_relpath_join(local_relpath, name,
+ scratch_pool),
+ (apr_int64_t) 2, /* ### op_depth
+ non-THIS_DIR working */
+ local_relpath,
+ "incomplete", /* 8, presence */
+ "unknown")); /* 10, kind */
+
+ SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
+#endif
}
return SVN_NO_ERROR;
@@ -752,17 +956,20 @@ insert_working_node(void *baton,
const insert_working_baton_t *piwb = baton;
const char *parent_relpath;
svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *stmt_node;
+ apr_int64_t op_depth;
+#endif
/* We cannot insert a WORKING_NODE row at the wcroot. */
/* ### actually, with per-dir DB, we can... */
-#if 0
SVN_ERR_ASSERT(*piwb->local_relpath != '\0');
-#endif
if (*piwb->local_relpath == '\0')
parent_relpath = NULL;
else
parent_relpath = svn_relpath_dirname(piwb->local_relpath, scratch_pool);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isstt",
piwb->wc_id, piwb->local_relpath,
@@ -818,6 +1025,57 @@ insert_working_node(void *baton,
SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+ op_depth = (parent_relpath == NULL) ? 1 /* THIS_DIR */
+ : 2; /* immediate children */
+ SVN_ERR(svn_sqlite__get_statement(&stmt_node, sdb, STMT_INSERT_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt_node, "isisnnntstrisn"
+ "nnnn" /* properties translated_size last_mod_time dav_cache */
+ "s",
+ piwb->wc_id, piwb->local_relpath,
+ op_depth,
+ parent_relpath,
+ presence_map, piwb->presence,
+ (piwb->kind == svn_wc__db_kind_dir)
+ ? svn_depth_to_word(piwb->depth) : NULL,
+ kind_map, piwb->kind,
+ piwb->changed_rev,
+ piwb->changed_date,
+ piwb->changed_author,
+ (piwb->kind == svn_wc__db_kind_symlink)
+ ? piwb->target : NULL));
+
+
+ if (piwb->kind == svn_wc__db_kind_file)
+ {
+ SVN_ERR(svn_sqlite__bind_checksum(stmt_node, 14, piwb->checksum,
+ scratch_pool));
+ }
+ else if (piwb->kind == svn_wc__db_kind_symlink)
+ {
+ /* Note: incomplete nodes may have a NULL target. */
+ if (piwb->target)
+ SVN_ERR(svn_sqlite__bind_text(stmt_node, 19, piwb->target));
+ }
+
+ if (piwb->original_repos_relpath != NULL)
+ {
+ SVN_ERR(svn_sqlite__bind_int64(stmt_node, 5, piwb->original_repos_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt_node, 6,
+ piwb->original_repos_relpath));
+ SVN_ERR(svn_sqlite__bind_int64(stmt_node, 7, piwb->original_revnum));
+ }
+
+
+ SVN_ERR(svn_sqlite__bind_properties(stmt_node, 15, piwb->props,
+ scratch_pool));
+
+ SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
+#endif
+
+
if (piwb->kind == svn_wc__db_kind_dir && piwb->children)
SVN_ERR(insert_incomplete_working_children(sdb, piwb->wc_id,
piwb->local_relpath,
@@ -830,6 +1088,8 @@ insert_working_node(void *baton,
}
+/* Return the number of children under PARENT_RELPATH in the given WC_ID.
+ The table is implicitly defined by the STMT_IDX query. */
static svn_error_t *
count_children(int *count,
int stmt_idx,
@@ -877,6 +1137,9 @@ add_children_to_hash(apr_hash_t *childre
}
+/* When children of PARENT_RELPATH are in both BASE_NODE and WORKING_NODE,
+ this function can be used to union those two sets, returning the set
+ in *CHILDREN (allocated in RESULT_POOL). */
static svn_error_t *
union_children(const apr_array_header_t **children,
svn_sqlite__db_t *sdb,
@@ -902,6 +1165,13 @@ union_children(const apr_array_header_t
}
+/* Return all the children of PARENT_RELPATH from a single table, implicitly
+ defined by STMT_IDX. If the caller happens to know the count of children,
+ it should be passed as START_SIZE to pre-allocate space in the *CHILDREN
+ return value.
+
+ If the caller doesn't know the count, then it should pass a reasonable
+ idea of how many children may be present. */
static svn_error_t *
single_table_children(const apr_array_header_t **children,
int stmt_idx,
@@ -939,7 +1209,10 @@ single_table_children(const apr_array_he
}
-/* */
+/* Return in *CHILDREN all of the children of the directory LOCAL_ABSPATH.
+ If BASE_ONLY is true, then *only* the children from BASE_NODE are
+ returned (those in WORKING_NODE are ignored). The result children are
+ allocated in RESULT_POOl. */
static svn_error_t *
gather_children(const apr_array_header_t **children,
svn_boolean_t base_only,
@@ -1010,11 +1283,30 @@ gather_children(const apr_array_header_t
/* */
-static void
-flush_entries(const svn_wc__db_pdh_t *pdh)
+static svn_error_t *
+flush_entries(svn_wc__db_t *db,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
{
if (pdh->adm_access)
svn_wc__adm_access_set_entries(pdh->adm_access, NULL);
+
+ if (local_abspath
+ && strcmp(local_abspath, pdh->local_abspath) == 0
+ && strcmp(local_abspath, pdh->wcroot->abspath) != 0)
+ {
+ svn_wc__db_pdh_t *parent_pdh;
+
+ SVN_ERR(svn_wc__db_pdh_navigate_to_parent(&parent_pdh, db, pdh,
+ svn_sqlite__mode_readonly,
+ scratch_pool));
+
+ if (parent_pdh->adm_access)
+ svn_wc__adm_access_set_entries(parent_pdh->adm_access, NULL);
+ }
+
+ return SVN_NO_ERROR;
}
@@ -1122,6 +1414,7 @@ which_trees_exist(svn_boolean_t *base_ex
we return a WC_ID and verify some additional constraints. */
static svn_error_t *
prop_upgrade_trees(svn_boolean_t *base_exists,
+ svn_wc__db_status_t *base_presence,
svn_boolean_t *working_exists,
svn_wc__db_status_t *work_presence,
apr_int64_t *wc_id,
@@ -1153,6 +1446,7 @@ prop_upgrade_trees(svn_boolean_t *base_e
else
{
*base_exists = TRUE; /* value == 0 */
+ *base_presence = svn_sqlite__column_token(stmt, 1, presence_map);
}
/* Return the WC_ID that was assigned. */
@@ -1169,6 +1463,8 @@ prop_upgrade_trees(svn_boolean_t *base_e
fetch the 'presence' column value. */
if (svn_sqlite__column_int(stmt, 0))
*work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+ else
+ *base_presence = svn_sqlite__column_token(stmt, 1, presence_map);
/* During an upgrade, there should be just one working copy, so both
rows should refer to the same value. */
@@ -1200,6 +1496,11 @@ create_db(svn_sqlite__db_t **sdb,
/* Create the database's schema. */
SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_CREATE_SCHEMA));
+#ifdef SVN_WC__NODES
+ /* Create the NODES table for the experimental schema */
+ SVN_ERR(svn_sqlite__exec_statements(*sdb, STMT_CREATE_NODES));
+#endif
+
/* Insert the repository. */
SVN_ERR(create_repos_id(repos_id, repos_root_url, repos_uuid, *sdb,
scratch_pool));
@@ -1325,55 +1626,135 @@ svn_wc__db_from_relpath(const char **loc
return SVN_NO_ERROR;
}
-
svn_error_t *
-svn_wc__db_base_add_directory(svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_relpath,
- const char *repos_root_url,
- const char *repos_uuid,
- svn_revnum_t revision,
- const apr_hash_t *props,
- svn_revnum_t changed_rev,
- apr_time_t changed_date,
- const char *changed_author,
- const apr_array_header_t *children,
- svn_depth_t depth,
- const svn_skel_t *conflict,
- const svn_skel_t *work_items,
- apr_pool_t *scratch_pool)
+svn_wc__db_get_wcroot(const char **wcroot_abspath,
+ svn_wc__db_t *db,
+ const char *wri_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
- apr_int64_t repos_id;
- insert_base_baton_t ibb;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR_ASSERT(repos_relpath != NULL);
- SVN_ERR_ASSERT(svn_uri_is_absolute(repos_root_url));
- SVN_ERR_ASSERT(repos_uuid != NULL);
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
- SVN_ERR_ASSERT(props != NULL);
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
-#if 0
- SVN_ERR_ASSERT(children != NULL);
-#endif
+ const char *unused_relpath;
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &unused_relpath, db,
+ wri_abspath, svn_sqlite__mode_readonly,
scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
- SVN_ERR(create_repos_id(&repos_id, repos_root_url, repos_uuid,
- pdh->wcroot->sdb, scratch_pool));
+ /* Can't use VERIFY_USABLE_PDH, as this should be usable to detect
+ where call upgrade */
- blank_ibb(&ibb);
+ if (pdh->wcroot == NULL)
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("The node '%s' is not in a workingcopy."),
+ svn_dirent_local_style(wri_abspath,
+ scratch_pool));
- ibb.status = svn_wc__db_status_normal;
- ibb.kind = svn_wc__db_kind_dir;
- ibb.wc_id = pdh->wcroot->wc_id;
- ibb.local_relpath = local_relpath;
- ibb.repos_id = repos_id;
+ *wcroot_abspath = apr_pstrdup(result_pool, pdh->wcroot->abspath);
+
+ return SVN_NO_ERROR;
+}
+
+struct with_sqlite_lock_baton
+{
+ svn_wc__db_t *db;
+ svn_wc__db_sqlite_lock_cb lock_cb;
+ void *lock_baton;
+};
+
+static svn_error_t *
+call_sqlite_lock_cb(void *baton,
+ svn_sqlite__db_t *sdb,
+ apr_pool_t *scratch_pool)
+{
+ struct with_sqlite_lock_baton *lb = baton;
+
+ return svn_error_return(lb->lock_cb(lb->db, lb->lock_baton, scratch_pool));
+}
+
+svn_error_t *
+svn_wc__db_with_sqlite_lock(svn_wc__db_t *db,
+ const char *wri_abspath,
+ svn_wc__db_sqlite_lock_cb lock_cb,
+ void *cb_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *unused_relpath;
+ struct with_sqlite_lock_baton baton;
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &unused_relpath, db,
+ wri_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+
+ /* Can't use VERIFY_USABLE_PDH, as this should be usable to detect
+ where call upgrade */
+
+ if (pdh->wcroot == NULL || !pdh->wcroot->sdb)
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("The node '%s' is not in a workingcopy."),
+ svn_dirent_local_style(wri_abspath,
+ scratch_pool));
+
+ baton.db = db;
+ baton.lock_cb = lock_cb;
+ baton.lock_baton = cb_baton;
+
+ return svn_error_return(
+ svn_sqlite__with_lock(pdh->wcroot->sdb,
+ call_sqlite_lock_cb,
+ &baton,
+ scratch_pool));
+}
+
+svn_error_t *
+svn_wc__db_base_add_directory(svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *repos_relpath,
+ const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t revision,
+ const apr_hash_t *props,
+ svn_revnum_t changed_rev,
+ apr_time_t changed_date,
+ const char *changed_author,
+ const apr_array_header_t *children,
+ svn_depth_t depth,
+ apr_hash_t *dav_cache,
+ const svn_skel_t *conflict,
+ const svn_skel_t *work_items,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ apr_int64_t repos_id;
+ insert_base_baton_t ibb;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR_ASSERT(repos_relpath != NULL);
+ SVN_ERR_ASSERT(svn_uri_is_absolute(repos_root_url));
+ SVN_ERR_ASSERT(repos_uuid != NULL);
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+ SVN_ERR_ASSERT(props != NULL);
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
+#if 0
+ SVN_ERR_ASSERT(children != NULL);
+#endif
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath, svn_sqlite__mode_readwrite,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(create_repos_id(&repos_id, repos_root_url, repos_uuid,
+ pdh->wcroot->sdb, scratch_pool));
+
+ blank_ibb(&ibb);
+
+ ibb.status = svn_wc__db_status_normal;
+ ibb.kind = svn_wc__db_kind_dir;
+ ibb.wc_id = pdh->wcroot->wc_id;
+ ibb.local_relpath = local_relpath;
+ ibb.repos_id = repos_id;
ibb.repos_relpath = repos_relpath;
ibb.revision = revision;
@@ -1385,6 +1766,7 @@ svn_wc__db_base_add_directory(svn_wc__db
ibb.children = children;
ibb.depth = depth;
+ ibb.dav_cache = dav_cache;
ibb.conflict = conflict;
ibb.work_items = work_items;
@@ -1397,7 +1779,7 @@ svn_wc__db_base_add_directory(svn_wc__db
scratch_pool));
/* ### worry about flushing child subdirs? */
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1415,6 +1797,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
const char *changed_author,
const svn_checksum_t *checksum,
svn_filesize_t translated_size,
+ apr_hash_t *dav_cache,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -1459,6 +1842,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
ibb.checksum = checksum;
ibb.translated_size = translated_size;
+ ibb.dav_cache = dav_cache;
ibb.conflict = conflict;
ibb.work_items = work_items;
@@ -1470,7 +1854,7 @@ svn_wc__db_base_add_file(svn_wc__db_t *d
insert_base_node, &ibb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1487,6 +1871,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
apr_time_t changed_date,
const char *changed_author,
const char *target,
+ apr_hash_t *dav_cache,
const svn_skel_t *conflict,
const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
@@ -1530,6 +1915,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
ibb.target = target;
+ ibb.dav_cache = dav_cache;
ibb.conflict = conflict;
ibb.work_items = work_items;
@@ -1541,7 +1927,7 @@ svn_wc__db_base_add_symlink(svn_wc__db_t
insert_base_node, &ibb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1609,67 +1995,9 @@ svn_wc__db_base_add_absent_node(svn_wc__
insert_base_node, &ibb,
scratch_pool));
- flush_entries(pdh);
- return SVN_NO_ERROR;
-}
-
-
-/* ### temp API. Remove before release. */
-svn_error_t *
-svn_wc__db_temp_base_add_subdir(svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_relpath,
- const char *repos_root_url,
- const char *repos_uuid,
- svn_revnum_t revision,
- const apr_hash_t *props,
- svn_revnum_t changed_rev,
- apr_time_t changed_date,
- const char *changed_author,
- svn_depth_t depth,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
- apr_int64_t repos_id;
- insert_base_baton_t ibb;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR_ASSERT(repos_relpath != NULL);
- SVN_ERR_ASSERT(svn_uri_is_absolute(repos_root_url));
- SVN_ERR_ASSERT(repos_uuid != NULL);
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
- SVN_ERR_ASSERT(props != NULL);
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(changed_rev));
-
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- SVN_ERR(create_repos_id(&repos_id, repos_root_url, repos_uuid,
- pdh->wcroot->sdb, scratch_pool));
-
- ibb.status = svn_wc__db_status_normal;
- ibb.kind = svn_wc__db_kind_subdir;
- ibb.wc_id = pdh->wcroot->wc_id;
- ibb.local_relpath = local_relpath;
- ibb.repos_id = repos_id;
- ibb.repos_relpath = repos_relpath;
- ibb.revision = revision;
-
- ibb.props = NULL;
- ibb.changed_rev = changed_rev;
- ibb.changed_date = changed_date;
- ibb.changed_author = changed_author;
-
- ibb.children = NULL;
- ibb.depth = depth;
-
- /* ### no children, conflicts, or work items to install in a txn... */
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
- return svn_error_return(insert_base_node(&ibb, pdh->wcroot->sdb,
- scratch_pool));
+ return SVN_NO_ERROR;
}
@@ -1689,13 +2017,23 @@ svn_wc__db_base_remove(svn_wc__db_t *db,
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_DELETE_BASE_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_DELETE_BASE_NODE_1));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1724,8 +2062,14 @@ svn_wc__db_base_get_info(svn_wc__db_stat
{
svn_wc__db_pdh_t *pdh;
const char *local_relpath;
+#ifndef SVN_WC__NODES_ONLY
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+#endif
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *stmt_nodes;
+ svn_boolean_t have_node_row;
+#endif
svn_error_t *err = SVN_NO_ERROR;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -1735,11 +2079,25 @@ svn_wc__db_base_get_info(svn_wc__db_stat
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
lock ? STMT_SELECT_BASE_NODE_WITH_LOCK
: STMT_SELECT_BASE_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, pdh->wcroot->sdb,
+ lock ? STMT_SELECT_BASE_NODE_WITH_LOCK_1
+ : STMT_SELECT_BASE_NODE_1));
+ SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is",
+ pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_node_row, stmt_nodes));
+
+ SVN_ERR(assert_base_rows_match(have_row, have_node_row, stmt, stmt_nodes,
+ local_relpath, scratch_pool));
+#endif
if (have_row)
{
@@ -1748,24 +2106,11 @@ svn_wc__db_base_get_info(svn_wc__db_stat
if (kind)
{
- if (node_kind == svn_wc__db_kind_subdir)
- *kind = svn_wc__db_kind_dir;
- else
- *kind = node_kind;
+ *kind = node_kind;
}
if (status)
{
*status = svn_sqlite__column_token(stmt, 2, presence_map);
-
- if (node_kind == svn_wc__db_kind_subdir
- && *status == svn_wc__db_status_normal)
- {
- /* We're looking at the subdir record in the *parent* directory,
- which implies per-dir .svn subdirs. We should be looking
- at the subdir itself; therefore, it is missing or obstructed
- in some way. Inform the caller. */
- *status = svn_wc__db_status_obstructed;
- }
}
if (revision)
{
@@ -1883,6 +2228,99 @@ svn_wc__db_base_get_info(svn_wc__db_stat
scratch_pool));
}
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#endif
+
+ /* Note: given the composition, no need to wrap for tracing. */
+ return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+}
+
+svn_error_t *
+svn_wc__db_base_get_info_from_parent(svn_wc__db_status_t *status,
+ svn_wc__db_kind_t *kind,
+ svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
+ const char **repos_uuid,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ svn_error_t *err = SVN_NO_ERROR;
+ const char *parent_abspath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ parent_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ local_relpath = svn_relpath_join(local_relpath,
+ svn_dirent_basename(local_abspath, NULL),
+ scratch_pool);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ if (have_row)
+ {
+ svn_wc__db_kind_t node_kind = svn_sqlite__column_token(stmt, 3,
+ kind_map);
+
+ if (kind)
+ {
+ *kind = node_kind;
+ }
+ if (status)
+ {
+ *status = svn_sqlite__column_token(stmt, 2, presence_map);
+ }
+ if (revision)
+ {
+ *revision = svn_sqlite__column_revnum(stmt, 4);
+ }
+ if (repos_relpath)
+ {
+ *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+ }
+ if (repos_root_url || repos_uuid)
+ {
+ /* Fetch repository information via REPOS_ID. */
+ if (svn_sqlite__column_is_null(stmt, 0))
+ {
+ if (repos_root_url)
+ *repos_root_url = NULL;
+ if (repos_uuid)
+ *repos_uuid = NULL;
+ }
+ else
+ {
+ err = fetch_repos_info(repos_root_url, repos_uuid,
+ pdh->wcroot->sdb,
+ svn_sqlite__column_int64(stmt, 0),
+ result_pool);
+ }
+ }
+ }
+ else
+ {
+ err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+ }
+
/* Note: given the composition, no need to wrap for tracing. */
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
}
@@ -1969,14 +2407,37 @@ svn_wc__db_base_set_dav_cache(svn_wc__db
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
+ int affected_rows;
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
STMT_UPDATE_BASE_DAV_CACHE, scratch_pool));
SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
- /* ### we should assert that 1 row was affected. */
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
- return svn_error_return(svn_sqlite__step_done(stmt));
+ if (affected_rows != 1)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
+ STMT_UPDATE_BASE_NODE_DAV_CACHE,
+ scratch_pool));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
+
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+ if (affected_rows != 1)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+#endif
+
+ return SVN_NO_ERROR;
}
@@ -2007,8 +2468,50 @@ svn_wc__db_base_get_dav_cache(apr_hash_t
svn_error_t *
-svn_wc__db_pristine_get_path(const char **pristine_abspath,
- svn_wc__db_t *db,
+svn_wc__db_base_clear_dav_cache_recursive(svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ const char *like_arg;
+ svn_sqlite__stmt_t *stmt;
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath,
+ db, local_abspath,
+ svn_sqlite__mode_readwrite,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ if (local_relpath[0] == 0)
+ like_arg = "%";
+ else
+ like_arg = apr_pstrcat(scratch_pool,
+ escape_sqlite_like(local_relpath, scratch_pool),
+ "/%", NULL);
+
+#ifndef SVN_WC__NODES_ONLY
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_CLEAR_BASE_RECURSIVE_DAV_CACHE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "iss", pdh->wcroot->wc_id, local_relpath,
+ like_arg));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_CLEAR_BASE_NODE_RECURSIVE_DAV_CACHE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "iss", pdh->wcroot->wc_id, local_relpath,
+ like_arg));
+
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_pristine_get_path(const char **pristine_abspath,
+ svn_wc__db_t *db,
const char *wri_abspath,
const svn_checksum_t *sha1_checksum,
apr_pool_t *result_pool,
@@ -2016,6 +2519,7 @@ svn_wc__db_pristine_get_path(const char
{
svn_wc__db_pdh_t *pdh;
const char *local_relpath;
+ svn_boolean_t present;
SVN_ERR_ASSERT(pristine_abspath != NULL);
SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
@@ -2034,15 +2538,33 @@ svn_wc__db_pristine_get_path(const char
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- /* ### should we look in the PRISTINE table for anything? */
+ SVN_ERR(svn_wc__db_pristine_check(&present, db, wri_abspath, sha1_checksum,
+ scratch_pool));
+ if (! present)
+ return svn_error_createf(SVN_ERR_WC_DB_ERROR, NULL,
+ _("Pristine text not found"));
- SVN_ERR(get_pristine_fname(pristine_abspath, pdh, sha1_checksum,
+ SVN_ERR(get_pristine_fname(pristine_abspath, pdh->wcroot->abspath,
+ sha1_checksum,
FALSE /* create_subdir */,
- scratch_pool, scratch_pool));
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_pristine_get_future_path(const char **pristine_abspath,
+ const char *wcroot_abspath,
+ svn_checksum_t *sha1_checksum,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(get_pristine_fname(pristine_abspath, wcroot_abspath,
+ sha1_checksum,
+ FALSE /* create_subdir */,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__db_pristine_read(svn_stream_t **contents,
@@ -2074,7 +2596,8 @@ svn_wc__db_pristine_read(svn_stream_t **
/* ### should we look in the PRISTINE table for anything? */
- SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, pdh->wcroot->abspath,
+ sha1_checksum,
FALSE /* create_subdir */,
scratch_pool, scratch_pool));
return svn_error_return(svn_stream_open_readonly(
@@ -2123,6 +2646,7 @@ svn_wc__db_pristine_install(svn_wc__db_t
const char *pristine_abspath;
apr_finfo_t finfo;
svn_sqlite__stmt_t *stmt;
+ svn_node_kind_t kind;
SVN_ERR_ASSERT(svn_dirent_is_absolute(tempfile_abspath));
SVN_ERR_ASSERT(sha1_checksum != NULL);
@@ -2143,13 +2667,25 @@ svn_wc__db_pristine_install(svn_wc__db_t
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, pdh->wcroot->abspath,
+ sha1_checksum,
TRUE /* create_subdir */,
scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_io_check_path(pristine_abspath, &kind, scratch_pool));
+
+ if (kind == svn_node_file)
+ {
+ /* Remove the tempfile, it's already there */
+ return svn_error_return(
+ svn_io_remove_file2(tempfile_abspath,
+ FALSE, scratch_pool));
+ }
+
/* Put the file into its target location. */
- SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
- scratch_pool));
+ SVN_ERR(svn_io_file_rename(tempfile_abspath, pristine_abspath,
+ scratch_pool));
SVN_ERR(svn_io_stat(&finfo, pristine_abspath, APR_FINFO_SIZE,
scratch_pool));
@@ -2245,6 +2781,32 @@ svn_wc__db_pristine_get_sha1(const svn_c
}
+/* Delete the pristine text referenced by SHA1_CHECKSUM in the database
+ * referenced by PDH. */
+static svn_error_t *
+pristine_remove(svn_wc__db_pdh_t *pdh,
+ const svn_checksum_t *sha1_checksum,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ const char *pristine_abspath;
+
+ /* Remove the DB row. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_DELETE_PRISTINE));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+
+ /* Remove the file */
+ SVN_ERR(get_pristine_fname(&pristine_abspath, pdh->wcroot->abspath,
+ sha1_checksum, TRUE /* create_subdir */,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE /* ignore_enoent */,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_wc__db_pristine_remove(svn_wc__db_t *db,
const char *wri_abspath,
@@ -2270,6 +2832,21 @@ svn_wc__db_pristine_remove(svn_wc__db_t
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
+ /* If the work queue is not empty, don't delete any pristine text because
+ * the work queue may contain a reference to it. */
+ {
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_LOOK_FOR_WORK));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ if (have_row)
+ return SVN_NO_ERROR;
+ }
+
/* Find whether the SHA-1 (or the MD-5) is referenced; set IS_REFERENCED. */
{
const svn_checksum_t *md5_checksum;
@@ -2289,24 +2866,50 @@ svn_wc__db_pristine_remove(svn_wc__db_t
SVN_ERR(svn_sqlite__reset(stmt));
}
- /* If not referenced, remove first the PRISTINE table row, then the file. */
+ /* If not referenced, remove the PRISTINE table row and the file. */
if (! is_referenced)
{
- svn_sqlite__stmt_t *stmt;
- const char *pristine_abspath;
+ SVN_ERR(pristine_remove(pdh, sha1_checksum, scratch_pool));
+ }
- /* Remove the DB row. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool));
- SVN_ERR(svn_sqlite__update(NULL, stmt));
-
- /* Remove the file */
- SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
- TRUE /* create_subdir */,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_io_remove_file2(pristine_abspath, TRUE, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_pristine_cleanup(svn_wc__db_t *db,
+ const char *wri_abspath,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ wri_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ /* Find the pristines in the DB */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_PRISTINE_ROWS));
+ while (1)
+ {
+ svn_boolean_t have_row;
+ const svn_checksum_t *checksum;
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (! have_row)
+ break;
+
+ SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0,
+ scratch_pool));
+ SVN_ERR(svn_wc__db_pristine_remove(db, wri_abspath, checksum,
+ scratch_pool));
}
+ SVN_ERR(svn_sqlite__reset(stmt));
return SVN_NO_ERROR;
}
@@ -2317,7 +2920,6 @@ svn_wc__db_pristine_check(svn_boolean_t
svn_wc__db_t *db,
const char *wri_abspath,
const svn_checksum_t *sha1_checksum,
- svn_wc__db_checkmode_t mode,
apr_pool_t *scratch_pool)
{
svn_wc__db_pdh_t *pdh;
@@ -2351,7 +2953,8 @@ svn_wc__db_pristine_check(svn_boolean_t
SVN_ERR(svn_sqlite__reset(stmt));
/* Check that the pristine text file exists. */
- SVN_ERR(get_pristine_fname(&pristine_abspath, pdh, sha1_checksum,
+ SVN_ERR(get_pristine_fname(&pristine_abspath, pdh->wcroot->abspath,
+ sha1_checksum,
FALSE /* create_subdir */,
scratch_pool, scratch_pool));
SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool));
@@ -2432,7 +3035,7 @@ temp_cross_db_copy(svn_wc__db_t *db,
SVN_ERR_ASSERT(kind == svn_wc__db_kind_file
|| kind == svn_wc__db_kind_dir
- || kind == svn_wc__db_kind_subdir);
+ );
SVN_ERR(svn_wc__db_read_info(NULL /* status */,
NULL /* kind */,
@@ -2572,7 +3175,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
svn_wc__db_kind_t parent_kind;
svn_boolean_t parent_have_work;
- svn_dirent_split(local_abspath, &parent_abspath, &base_name,
+ svn_dirent_split(&parent_abspath, &base_name, local_abspath,
scratch_pool);
SVN_ERR(get_info_for_copy(copyfrom_id, copyfrom_relpath, copyfrom_rev,
&parent_status, &parent_kind, &parent_have_work,
@@ -2582,15 +3185,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
*copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, base_name,
result_pool);
}
- else if (*status != svn_wc__db_status_added)
- {
- *copyfrom_relpath = repos_relpath;
- *copyfrom_rev = revision;
- SVN_ERR(create_repos_id(copyfrom_id,
- repos_root_url, repos_uuid,
- pdh->wcroot->sdb, scratch_pool));
- }
- else
+ else if (*status == svn_wc__db_status_added)
{
const char *op_root_abspath;
const char *original_repos_relpath, *original_root_url, *original_uuid;
@@ -2626,6 +3221,66 @@ get_info_for_copy(apr_int64_t *copyfrom_
*copyfrom_id = 0;
}
}
+ else if (*status == svn_wc__db_status_deleted)
+ {
+ const char *work_del_abspath;
+
+ SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, NULL,
+ &work_del_abspath,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ if (work_del_abspath)
+ {
+ const char *op_root_abspath;
+ const char *original_repos_relpath, *original_root_url;
+ const char *original_uuid;
+ svn_revnum_t original_revision;
+ const char *parent_del_abspath = svn_dirent_dirname(work_del_abspath,
+ scratch_pool);
+
+ /* Similar to, but not the same as, the _scan_addition and
+ _join above. Can we use get_copyfrom here? */
+ SVN_ERR(svn_wc__db_scan_addition(NULL, &op_root_abspath,
+ NULL /* repos_relpath */,
+ NULL /* repos_root_url */,
+ NULL /* repos_uuid */,
+ &original_repos_relpath,
+ &original_root_url, &original_uuid,
+ &original_revision,
+ db, parent_del_abspath,
+ scratch_pool, scratch_pool));
+ *copyfrom_relpath
+ = svn_relpath_join(original_repos_relpath,
+ svn_dirent_skip_ancestor(op_root_abspath,
+ local_abspath),
+ scratch_pool);
+ *copyfrom_rev = original_revision;
+ SVN_ERR(create_repos_id(copyfrom_id,
+ original_root_url, original_uuid,
+ pdh->wcroot->sdb, scratch_pool));
+ }
+ else
+ {
+ *copyfrom_relpath = repos_relpath;
+ *copyfrom_rev = revision;
+ if (!repos_root_url || !repos_uuid)
+ SVN_ERR(svn_wc__db_scan_base_repos(NULL,
+ &repos_root_url, &repos_uuid,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(create_repos_id(copyfrom_id,
+ repos_root_url, repos_uuid,
+ pdh->wcroot->sdb, scratch_pool));
+ }
+ }
+ else
+ {
+ *copyfrom_relpath = repos_relpath;
+ *copyfrom_rev = revision;
+ SVN_ERR(create_repos_id(copyfrom_id,
+ repos_root_url, repos_uuid,
+ pdh->wcroot->sdb, scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -2700,24 +3355,6 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
scratch_pool));
}
-
- /* When copying a directory the destination may not exist, if so we
- only copy the parent stub */
- if (kind == svn_wc__db_kind_dir && !*src_relpath && *dst_relpath)
- {
- /* ### copy_tests.py 69 copies from the root of one wc to
- ### another wc, that means the source doesn't have a
- ### versioned parent and so there is no parent stub to
- ### copy. We could generate a parent stub but it becomes
- ### unnecessary when we centralise so for the moment we just
- ### fail. */
- SVN_ERR(navigate_to_parent(&src_pdh, db, src_pdh,
- svn_sqlite__mode_readwrite, scratch_pool));
- src_relpath = svn_dirent_basename(src_abspath, NULL);
- kind = svn_wc__db_kind_subdir;
- }
-
- /* Get the children for a directory if this is not the parent stub */
if (kind == svn_wc__db_kind_dir)
SVN_ERR(gather_children(&children, FALSE, db, src_abspath,
scratch_pool, scratch_pool));
@@ -2730,6 +3367,7 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
const char *dst_parent_relpath = svn_relpath_dirname(dst_relpath,
scratch_pool);
+#ifndef SVN_WC__NODES_ONLY
if (have_work)
SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING));
@@ -2749,6 +3387,34 @@ svn_wc__db_op_copy(svn_wc__db_t *db,
SVN_ERR(svn_sqlite__bind_int64(stmt, 8, copyfrom_rev));
}
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+
+ if (have_work)
+ SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
+ STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING_1));
+ else
+ SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
+ STMT_INSERT_WORKING_NODE_COPY_FROM_BASE_1));
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "issisnnnt",
+ src_pdh->wcroot->wc_id, src_relpath,
+ dst_relpath,
+ (children == NULL) ? (apr_int64_t)2 :
+ (apr_int64_t)1, /* no directory or stub */
+ dst_parent_relpath,
+ presence_map, dst_status));
+
+ if (copyfrom_relpath)
+ {
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 6, copyfrom_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, copyfrom_relpath));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 8, copyfrom_rev));
+ }
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+#endif
/* ### Copying changelist is OK for a move but what about a copy? */
SVN_ERR(svn_sqlite__get_statement(&stmt, src_pdh->wcroot->sdb,
@@ -2848,33 +3514,7 @@ svn_wc__db_op_copy_dir(svn_wc__db_t *db,
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
-
- /* Add a parent stub. */
- if (*local_relpath == '\0')
- {
- svn_error_t *err;
-
- err = navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool);
- if (err)
- {
- /* Prolly fell off the top of the wcroot. Just call it a day. */
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
-
- blank_iwb(&iwb);
-
- iwb.presence = svn_wc__db_status_normal;
- iwb.kind = svn_wc__db_kind_subdir;
- iwb.wc_id = pdh->wcroot->wc_id;
- iwb.local_relpath = svn_dirent_basename(local_abspath, scratch_pool);
-
- /* No children or work items, so a txn is not needed. */
- SVN_ERR(insert_working_node(&iwb, pdh->wcroot->sdb, scratch_pool));
- flush_entries(pdh);
- }
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -2945,7 +3585,7 @@ svn_wc__db_op_copy_file(svn_wc__db_t *db
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3012,7 +3652,7 @@ svn_wc__db_op_copy_symlink(svn_wc__db_t
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3047,33 +3687,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
-
- /* Add a parent stub. */
- if (*local_relpath == '\0')
- {
- svn_error_t *err;
-
- err = navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool);
- if (err)
- {
- /* Prolly fell off the top of the wcroot. Just call it a day. */
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
-
- blank_iwb(&iwb);
-
- iwb.presence = svn_wc__db_status_normal;
- iwb.kind = svn_wc__db_kind_subdir;
- iwb.wc_id = pdh->wcroot->wc_id;
- iwb.local_relpath = svn_dirent_basename(local_abspath, scratch_pool);
-
- /* No children or work items, so a txn is not needed. */
- SVN_ERR(insert_working_node(&iwb, pdh->wcroot->sdb, scratch_pool));
- flush_entries(pdh);
- }
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3108,7 +3722,7 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3147,7 +3761,7 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
insert_working_node, &iwb,
scratch_pool));
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3188,7 +3802,7 @@ set_props_txn(void *baton, svn_sqlite__d
SVN_ERR(svn_sqlite__bind_properties(stmt, 3, spb->props, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
- if (affected_rows == 1)
+ if (affected_rows == 1 || !spb->props)
return SVN_NO_ERROR; /* We are done */
/* We have to insert a row in ACTUAL */
@@ -3233,6 +3847,7 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
scratch_pool));
}
+#ifdef SVN__SUPPORT_BASE_MERGE
/* Set properties in a given table. The row must exist. */
static svn_error_t *
@@ -3271,10 +3886,20 @@ svn_wc__db_temp_base_set_props(svn_wc__d
const apr_hash_t *props,
apr_pool_t *scratch_pool)
{
+#ifdef SVN_WC__NODES
+ SVN_ERR(set_properties(db, local_abspath, props,
+ STMT_UPDATE_NODE_BASE_PROPS,
+ "base node", scratch_pool));
+#endif
+
+#ifndef SVN_WC__NODES_ONLY
return svn_error_return(set_properties(db, local_abspath, props,
STMT_UPDATE_BASE_PROPS,
"base_node",
scratch_pool));
+#else
+ return SVN_NO_ERROR;
+#endif
}
@@ -3284,12 +3909,23 @@ svn_wc__db_temp_working_set_props(svn_wc
const apr_hash_t *props,
apr_pool_t *scratch_pool)
{
+#ifdef SVN_WC__NODES
+ SVN_ERR(set_properties(db, local_abspath, props,
+ STMT_UPDATE_NODE_WORKING_PROPS,
+ "working node", scratch_pool));
+#endif
+
+#ifndef SVN_WC__NODES_ONLY
return svn_error_return(set_properties(db, local_abspath, props,
STMT_UPDATE_WORKING_PROPS,
"working_node",
scratch_pool));
+#else
+ return SVN_NO_ERROR;
+#endif
}
+#endif /* SVN__SUPPORT_BASE_MERGE */
svn_error_t *
svn_wc__db_op_delete(svn_wc__db_t *db,
@@ -3409,7 +4045,9 @@ svn_wc__db_op_set_changelist(svn_wc__db_
SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb, set_changelist_txn,
&scb, scratch_pool));
- flush_entries(pdh);
+ /* No need to flush the parent entries; changelists were not stored in the
+ stub */
+ SVN_ERR(flush_entries(db, pdh, NULL, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3471,7 +4109,7 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
}
/* Some entries have cached the above values. Kapow!! */
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3574,7 +4212,7 @@ svn_wc__db_op_set_tree_conflict(svn_wc__
scratch_pool));
/* There may be some entries, and the lock info is now out of date. */
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3699,11 +4337,12 @@ svn_wc__db_temp_op_remove_entry(svn_wc__
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
sdb = pdh->wcroot->sdb;
wc_id = pdh->wcroot->wc_id;
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_BASE_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
@@ -3711,39 +4350,18 @@ svn_wc__db_temp_op_remove_entry(svn_wc__
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_ACTUAL_NODE));
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_NODES));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
-
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- /* Check if we should also remove it from the parent db */
- if (*local_relpath == '\0')
- {
- SVN_ERR(navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- local_relpath = svn_dirent_basename(local_abspath, NULL);
-
- flush_entries(pdh);
-
- sdb = pdh->wcroot->sdb;
- wc_id = pdh->wcroot->wc_id;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_ACTUAL_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_ACTUAL_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
+ SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
}
@@ -3765,49 +4383,41 @@ svn_wc__db_temp_op_remove_working(svn_wc
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- flush_entries(pdh);
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- /* Check if we should remove it from the parent db as well. */
- if (*local_relpath == '\0')
- {
- SVN_ERR(navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- local_relpath = svn_dirent_basename(local_abspath, NULL);
-
- flush_entries(pdh);
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_DELETE_WORKING_NODES));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
return SVN_NO_ERROR;
}
static svn_error_t *
-update_depth_values(svn_wc__db_pdh_t *pdh,
+update_depth_values(svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_wc__db_pdh_t *pdh,
const char *local_relpath,
- svn_depth_t depth)
+ svn_depth_t depth,
+ apr_pool_t *scratch_pool)
{
svn_boolean_t excluded = (depth == svn_depth_exclude);
svn_sqlite__stmt_t *stmt;
/* Flush any entries before we start monkeying the database. */
- flush_entries(pdh);
-
- /* Parent stubs have only two depth options: excluded, or infinity. */
- if (*local_relpath != '\0' && !excluded)
- depth = svn_depth_infinity;
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
excluded
? STMT_UPDATE_BASE_EXCLUDED
@@ -3816,7 +4426,20 @@ update_depth_values(svn_wc__db_pdh_t *pd
if (!excluded)
SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ excluded
+ ? STMT_UPDATE_NODE_BASE_EXCLUDED
+ : STMT_UPDATE_NODE_BASE_DEPTH));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ if (!excluded)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
excluded
? STMT_UPDATE_WORKING_EXCLUDED
@@ -3825,14 +4448,26 @@ update_depth_values(svn_wc__db_pdh_t *pd
if (!excluded)
SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_temp_op_set_dir_depth(svn_wc__db_t *db,
- const char *local_abspath,
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ excluded
+ ? STMT_UPDATE_NODE_WORKING_EXCLUDED
+ : STMT_UPDATE_NODE_WORKING_DEPTH));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ if (!excluded)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 3, svn_depth_to_word(depth)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_temp_op_set_dir_depth(svn_wc__db_t *db,
+ const char *local_abspath,
svn_depth_t depth,
apr_pool_t *scratch_pool)
{
@@ -3850,30 +4485,8 @@ svn_wc__db_temp_op_set_dir_depth(svn_wc_
/* ### We set depth on working and base to match entry behavior.
Maybe these should be separated later? */
- SVN_ERR(update_depth_values(pdh, local_relpath, depth));
-
- /* If we're in the subdir, then navigate to the parent to set its
- depth value. */
- if (*local_relpath == '\0')
- {
- svn_error_t *err;
-
- err = navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool);
- if (err)
- {
- if (! SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
- return svn_error_return(err);
-
- /* No parent to update */
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
-
- /* Get the stub name, and update the depth. */
- local_relpath = svn_dirent_basename(local_abspath, scratch_pool);
- SVN_ERR(update_depth_values(pdh, local_relpath, depth));
- }
+ SVN_ERR(update_depth_values(db, local_abspath, pdh, local_relpath, depth,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -3896,17 +4509,21 @@ db_working_update_presence(svn_wc__db_st
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_UPDATE_WORKING_PRESENCE));
SVN_ERR(svn_sqlite__bindf(stmt, "ist", pdh->wcroot->wc_id, local_relpath,
presence_map, status));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- flush_entries(pdh);
-
- /* ### Parent stub? I don't know; I'll punt for now as it passes
- the regression tests as is and the problem will evaporate
- when the db is centralised. */
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_UPDATE_NODE_WORKING_PRESENCE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "ist", pdh->wcroot->wc_id, local_relpath,
+ presence_map, status));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
return SVN_NO_ERROR;
}
@@ -3929,38 +4546,33 @@ db_working_actual_remove(svn_wc__db_t *d
VERIFY_USABLE_PDH(pdh);
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_DELETE_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+
+#ifdef SVN_WC__NODES
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_ACTUAL_NODE));
+ STMT_DELETE_WORKING_NODES));
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
- flush_entries(pdh);
-
- if (*local_relpath == '\0')
- {
- /* ### Delete parent stub. Remove when db is centralised. */
- SVN_ERR(navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool));
- local_relpath = svn_dirent_basename(local_abspath, NULL);
- VERIFY_USABLE_PDH(pdh);
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_DELETE_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is",
- pdh->wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_DELETE_ACTUAL_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
- flush_entries(pdh);
- }
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
+
+
/* Insert a working node for LOCAL_ABSPATH with presence=STATUS. */
static svn_error_t *
db_working_insert(svn_wc__db_status_t status,
@@ -3970,7 +4582,7 @@ db_working_insert(svn_wc__db_status_t st
{
svn_wc__db_pdh_t *pdh;
const char *local_relpath;
- svn_sqlite__stmt_t *stmt;
+ insert_working_baton_t iwb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
@@ -3978,33 +4590,21 @@ db_working_insert(svn_wc__db_status_t st
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_INSERT_WORKING_NODE_FROM_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "ist", pdh->wcroot->wc_id, local_relpath,
- presence_map, status));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ /* Update WORKING_NODE and NODE_DATA transactionally */
+ blank_iwb(&iwb);
- flush_entries(pdh);
+ iwb.wc_id = pdh->wcroot->wc_id;
+ iwb.local_relpath = local_relpath;
+ iwb.presence = status;
+ /* ### NODE_DATA we temporary store 1 or 2 */
+ iwb.op_depth = (*local_relpath == '\0') ? 1 : 2;
- if (*local_relpath == '\0')
- {
- /* ### Insert parent stub. Remove when db is centralised. */
- SVN_ERR(navigate_to_parent(&pdh, db, pdh, svn_sqlite__mode_readwrite,
- scratch_pool));
- local_relpath = svn_dirent_basename(local_abspath, NULL);
- VERIFY_USABLE_PDH(pdh);
+ SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+ copy_working_from_base, &iwb,
+ scratch_pool));
- /* ### Should the parent stub have a full row like this? */
- SVN_ERR(svn_sqlite__get_statement(
- &stmt, pdh->wcroot->sdb,
- STMT_INSERT_WORKING_NODE_FROM_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "ist",
- pdh->wcroot->wc_id, local_relpath,
- presence_map, status));
- SVN_ERR(svn_sqlite__step_done(stmt));
- flush_entries(pdh);
- }
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -4055,7 +4655,7 @@ is_add_or_root_of_copy(svn_boolean_t *ad
svn_revnum_t parent_original_revision;
svn_error_t *err;
- svn_dirent_split(local_abspath, &parent_abspath, &name, scratch_pool);
+ svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool);
err = svn_wc__db_scan_addition(&parent_status,
NULL, NULL, NULL, NULL,
@@ -4128,8 +4728,7 @@ svn_wc__db_temp_op_delete(svn_wc__db_t *
NULL, NULL, NULL, &have_work, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
- if (working_status == svn_wc__db_status_deleted
- || working_status == svn_wc__db_status_obstructed_delete)
+ if (working_status == svn_wc__db_status_deleted)
{
/* The node is already deleted. */
[... 2515 lines stripped ...]