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/12/11 01:16:08 UTC
svn commit: r1044548 [16/39] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/ contrib/hook-scripts/
contrib/server-side/ notes/api-errata/ notes/api-err...
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc_db.c Sat Dec 11 00:15:55 2010
@@ -101,6 +101,7 @@
* wc_id a WCROOT id associated with a node
*/
+#define INVALID_REPOS_ID ((apr_int64_t) -1)
#define UNKNOWN_WC_ID ((apr_int64_t) -1)
#define FORMAT_FROM_SDB (-1)
@@ -111,7 +112,7 @@
#define LIKE_ESCAPE_CHAR "#"
/* Calculates the depth of the relpath below "" */
-APR_INLINE static int relpath_op_depth(const char *relpath)
+APR_INLINE static int relpath_depth(const char *relpath)
{
int n = 1;
if (*relpath == '\0')
@@ -127,6 +128,11 @@ APR_INLINE static int relpath_op_depth(c
return n;
}
+int svn_wc__db_op_depth_for_upgrade(const char *local_relpath)
+{
+ return relpath_depth(local_relpath);
+}
+
typedef struct insert_base_baton_t {
/* common to all insertions into BASE */
svn_wc__db_status_t status;
@@ -225,8 +231,100 @@ add_work_items(svn_sqlite__db_t *sdb,
const svn_skel_t *skel,
apr_pool_t *scratch_pool);
+static svn_error_t *
+insert_incomplete_children(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_int64_t repos_id,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ const apr_array_header_t *children,
+ apr_int64_t op_depth,
+ apr_pool_t *scratch_pool);
-/* */
+static svn_error_t *
+db_read_pristine_props(apr_hash_t **props,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
+read_info(svn_wc__db_status_t *status,
+ svn_wc__db_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,
+ apr_time_t *last_mod_time,
+ svn_depth_t *depth,
+ const svn_checksum_t **checksum,
+ svn_filesize_t *translated_size,
+ const char **target,
+ const char **changelist,
+ const char **original_repos_relpath,
+ apr_int64_t *original_repos_id,
+ svn_revnum_t *original_revision,
+ svn_boolean_t *props_mod,
+ svn_boolean_t *have_base,
+ svn_boolean_t *have_work,
+ svn_boolean_t *conflicted,
+ svn_wc__db_lock_t **lock,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+#ifndef SVN_WC__OP_DEPTH
+static svn_error_t *
+elide_copyfrom(svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool);
+#endif
+
+static svn_error_t *
+scan_addition(svn_wc__db_status_t *status,
+ const char **op_root_relpath,
+ 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_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
+scan_deletion(const char **base_del_relpath,
+ const char **moved_to_relpath,
+ const char **work_del_relpath,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+static svn_error_t *
+convert_to_working_status(svn_wc__db_status_t *working_status,
+ svn_wc__db_status_t status);
+
+/* Return the absolute path, in local path style, of LOCAL_RELPATH in WCROOT. */
+static const char *
+path_for_error_message(const svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *result_pool)
+{
+ const char *local_abspath
+ = svn_dirent_join(wcroot->abspath, local_relpath, result_pool);
+
+ return svn_dirent_local_style(local_abspath, result_pool);
+}
+
+
+/* Return a file size from column SLOT of the SQLITE statement STMT, or
+ * SVN_INVALID_FILESIZE if the column value is NULL. */
static svn_filesize_t
get_translated_size(svn_sqlite__stmt_t *stmt, int slot)
{
@@ -236,6 +334,34 @@ get_translated_size(svn_sqlite__stmt_t *
}
+/* Return a lock info structure constructed from the given columns of the
+ * SQLITE statement STMT, or return NULL if the token column value is null. */
+static svn_wc__db_lock_t *
+lock_from_columns(svn_sqlite__stmt_t *stmt,
+ int col_token,
+ int col_owner,
+ int col_comment,
+ int col_date,
+ apr_pool_t *result_pool)
+{
+ svn_wc__db_lock_t *lock;
+
+ if (svn_sqlite__column_is_null(stmt, col_token))
+ {
+ lock = NULL;
+ }
+ else
+ {
+ lock = apr_pcalloc(result_pool, sizeof(svn_wc__db_lock_t));
+ lock->token = svn_sqlite__column_text(stmt, col_token, result_pool);
+ lock->owner = svn_sqlite__column_text(stmt, col_owner, result_pool);
+ lock->comment = svn_sqlite__column_text(stmt, col_comment, result_pool);
+ lock->date = svn_sqlite__column_int64(stmt, col_date);
+ }
+ return lock;
+}
+
+
/* */
static const char *
escape_sqlite_like(const char * const str, apr_pool_t *result_pool)
@@ -274,6 +400,25 @@ escape_sqlite_like(const char * const st
return result;
}
+/* Return a string that can be used as the argument to a SQLite 'LIKE'
+ * operator, in order to match any path that is a child of LOCAL_RELPATH
+ * (at any depth below LOCAL_RELPATH), *excluding* LOCAL_RELPATH itself.
+ * LOCAL_RELPATH may be the empty string, in which case the result will
+ * match any path except the empty path.
+ *
+ * Allocate the result either statically or in RESULT_POOL. */
+static const char *construct_like_arg(const char *local_relpath,
+ apr_pool_t *result_pool)
+{
+ if (local_relpath[0] == '\0')
+ return "_%";
+
+ return apr_pstrcat(result_pool,
+ escape_sqlite_like(local_relpath, result_pool),
+ "/%", (char *)NULL);
+}
+
+
/* Returns in PRISTINE_ABSPATH a new string allocated from RESULT_POOL,
holding the local absolute path to the file location that is dedicated
@@ -346,7 +491,10 @@ get_pristine_fname(const char **pristine
}
-/* */
+/* Look up REPOS_ID in 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. */
static svn_error_t *
fetch_repos_info(const char **repos_root_url,
const char **repos_uuid,
@@ -357,6 +505,18 @@ fetch_repos_info(const char **repos_root
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
+ if (!repos_root_url && !repos_uuid)
+ return SVN_NO_ERROR;
+
+ if (repos_id == INVALID_REPOS_ID)
+ {
+ if (repos_root_url)
+ *repos_root_url = NULL;
+ if (repos_uuid)
+ *repos_uuid = NULL;
+ return SVN_NO_ERROR;
+ }
+
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_SELECT_REPOSITORY_BY_ID));
SVN_ERR(svn_sqlite__bindf(stmt, "i", repos_id));
@@ -374,318 +534,83 @@ 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;
-}
-
-static svn_error_t *
-assert_blob_columns_equal(svn_sqlite__stmt_t *stmt1,
- svn_sqlite__stmt_t *stmt2,
- int column,
- apr_pool_t *scratch_pool)
-{
- apr_size_t len1, len2;
- const void *val1 = svn_sqlite__column_blob(stmt1, column, &len1, NULL);
- const void *val2 = svn_sqlite__column_blob(stmt2, column, &len2, NULL);
-
- if (!len1 && !len2)
- return SVN_NO_ERROR;
-
- if (len1 != len2 || memcmp(val1, val2, len1))
- return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
- "Blob of length %ld in statement 1 differs "
- "from blob of length %ld in statement 2",
- len1, len2);
- return SVN_NO_ERROR;
-}
-
-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));
-
- /* verify props */
- SVN_ERR(assert_blob_columns_equal(stmt1, stmt2, 13, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-assert_working_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)
+/* Set *REPOS_ID, *REVISION and *REPOS_RELPATH from the
+ * given columns of the SQLITE statement STMT, or to NULL if the respective
+ * column value is null. Any of the output parameters may be NULL if not
+ * required. */
+static svn_error_t *
+repos_location_from_columns(apr_int64_t *repos_id,
+ svn_revnum_t *revision,
+ const char **repos_relpath,
+ svn_wc__db_pdh_t *pdh,
+ svn_sqlite__stmt_t *stmt,
+ int col_repos_id,
+ int col_revision,
+ int col_repos_relpath,
+ apr_pool_t *result_pool)
{
- if (have_row1 != have_row2)
- SVN_ERR(svn_error_createf(
- SVN_ERR_WC_CORRUPT, NULL,
- "Different results from WORKING (%d) and NODES queries (%d), "
- "for local_relpath %s",
- have_row1, have_row2, relpath));
-
- if (!have_row1)
- return SVN_NO_ERROR;
+ svn_error_t *err = SVN_NO_ERROR;
- /* presence */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 0, scratch_pool));
- /* kind */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 1, scratch_pool));
- /* checksum */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 2, scratch_pool));
- /* translated_size */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 3)
- == svn_sqlite__column_int64(stmt2, 3));
- /* changed_rev */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 4)
- == svn_sqlite__column_int64(stmt2, 4));
- /* changed_date */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 5)
- == svn_sqlite__column_int64(stmt2, 5));
- /* changed_author */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 6, scratch_pool));
- /* depth */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 7, scratch_pool));
- /* symlink_target */
- /* copyfrom_repos_id */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 9)
- == svn_sqlite__column_int64(stmt2, 9));
- /* copyfrom_repos_path */
- SVN_ERR(assert_text_columns_equal(stmt1, stmt2, 7, scratch_pool));
- /* copyfrom_revnum */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 11)
- == svn_sqlite__column_int64(stmt2, 11));
- /* moved_here */
- /* moved_to */
- /* last_mod_time */
- SVN_ERR_ASSERT(svn_sqlite__column_int64(stmt1, 14)
- == svn_sqlite__column_int64(stmt2, 14));
- /* properties */
-#if 0
- /* Disabled for now as base-deleted don't match */
- SVN_ERR(assert_blob_columns_equal(stmt1, stmt2, 15, scratch_pool));
-#endif
+ if (repos_id)
+ {
+ /* Fetch repository information via REPOS_ID. */
+ if (svn_sqlite__column_is_null(stmt, col_repos_id))
+ *repos_id = INVALID_REPOS_ID;
+ else
+ *repos_id = svn_sqlite__column_int64(stmt, col_repos_id);
+ }
+ if (revision)
+ {
+ *revision = svn_sqlite__column_revnum(stmt, col_revision);
+ }
+ if (repos_relpath)
+ {
+ *repos_relpath = svn_sqlite__column_text(stmt, col_repos_relpath,
+ result_pool);
+ }
- return SVN_NO_ERROR;
+ return err;
}
-#endif /* SVN_WC__NODES_ONLY */
-#endif /* SVN_WC__NODES */
-
-/* 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
- that information in REPOS_ID and REPOS_RELPATH (either may be NULL).
- Use LOCAL_ABSPATH for diagnostics */
+/* Set *REPOS_ID and *REPOS_RELPATH to the BASE node of LOCAL_RELPATH.
+ * Either of REPOS_ID and REPOS_RELPATH may be NULL if not wanted. */
static svn_error_t *
scan_upwards_for_repos(apr_int64_t *repos_id,
const char **repos_relpath,
const svn_wc__db_wcroot_t *wcroot,
- const char *local_abspath,
const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- const char *relpath_suffix = "";
- const char *current_basename = svn_dirent_basename(local_relpath,
- scratch_pool);
- const char *current_relpath = local_relpath;
svn_sqlite__stmt_t *stmt;
-
-#ifdef SVN_WC__NODES
- svn_sqlite__stmt_t *data_stmt;
-#endif
+ svn_boolean_t have_row;
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
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
- while (TRUE)
+ if (!have_row)
{
- 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));
- SVN_ERR(svn_sqlite__reset(data_stmt));
-#else
- have_row = have_data_row;
- stmt = data_stmt;
-#endif
-#endif
-
- if (!have_row)
- {
- svn_error_t *err;
-
- /* If we moved upwards at least once, or we're looking at the
- root directory of this WCROOT, then something is wrong. */
- if (*relpath_suffix != '\0' || *local_relpath == '\0')
- {
- err = svn_error_createf(
- SVN_ERR_WC_CORRUPT, NULL,
- _("Parent(s) of '%s' should have been present."),
- svn_dirent_local_style(local_abspath, scratch_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));
- }
-
-#ifdef SVN_WC__NODES
-#endif
- return svn_error_compose_create(err, svn_sqlite__reset(stmt));
- }
-
- /* Did we find some non-NULL repository columns? */
- if (!svn_sqlite__column_is_null(stmt, 0))
- {
- /* If one is non-NULL, then so should the other. */
- SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
-
- if (repos_id)
- *repos_id = svn_sqlite__column_int64(stmt, 0);
-
- /* Given the node's relpath, append all the segments that
- we stripped as we scanned upwards. */
- if (repos_relpath)
- *repos_relpath = svn_relpath_join(svn_sqlite__column_text(stmt, 1,
- NULL),
- relpath_suffix,
- result_pool);
- return svn_sqlite__reset(stmt);
- }
-#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.
- Something is corrupt in the database. */
- return svn_error_createf(
- SVN_ERR_WC_CORRUPT, NULL,
- _("Parent(s) of '%s' should have repository information."),
- svn_relpath_local_style(local_abspath, scratch_pool));
- }
+ svn_error_t *err = svn_error_createf(
+ SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("The node '%s' was not found."),
+ path_for_error_message(wcroot, local_relpath, scratch_pool));
- /* 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(¤t_relpath, ¤t_basename, current_relpath,
- scratch_pool);
- relpath_suffix = svn_relpath_join(relpath_suffix, current_basename,
- scratch_pool);
+ return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ }
- /* Loop to try the parent. */
+ SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 0));
+ SVN_ERR_ASSERT(!svn_sqlite__column_is_null(stmt, 1));
- /* ### strictly speaking, moving to the parent could send us to a
- ### different SDB, and (thus) we would need to fetch STMT again.
- ### but we happen to know the parent is *always* in the same db,
- ### and will have the repos info. */
- }
+ if (repos_id)
+ *repos_id = svn_sqlite__column_int64(stmt, 0);
+ if (repos_relpath)
+ *repos_relpath = svn_sqlite__column_text(stmt, 1, result_pool);
+ return svn_sqlite__reset(stmt);
}
@@ -718,6 +643,26 @@ get_statement_for_path(svn_sqlite__stmt_
}
+/* For a given REPOS_ROOT_URL/REPOS_UUID pair, set *REPOS_ID to the existing
+ REPOS_ID value. If one does not exist, throw an error. */
+static svn_error_t *
+fetch_repos_id(apr_int64_t *repos_id,
+ const char *repos_root_url,
+ const char *repos_uuid,
+ svn_sqlite__db_t *sdb,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *get_stmt;
+
+ SVN_ERR(svn_sqlite__get_statement(&get_stmt, sdb, STMT_SELECT_REPOSITORY));
+ SVN_ERR(svn_sqlite__bindf(get_stmt, "s", repos_root_url));
+ SVN_ERR(svn_sqlite__step_row(get_stmt));
+
+ *repos_id = svn_sqlite__column_int64(get_stmt, 0);
+ return svn_error_return(svn_sqlite__reset(get_stmt));
+}
+
+
/* 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 *
@@ -771,151 +716,172 @@ blank_ibb(insert_base_baton_t *pibb)
}
+/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
+
+ Given a wc:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C not-pres normal
+ A/B/C/D normal
+
+ That is checkout, delete A/B, copy a replacement A/B, delete copied
+ child A/B/C, add replacement A/B/C, add A/B/C/D.
+
+ Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
+ must extend the A/B deletion:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C normal not-pres normal
+ A/B/C/D normal base-del normal
+ A/B/C/D/E normal base-del
+
+ When adding a base node if the parent has a working node then the
+ parent base is deleted and this must be extended to cover new base
+ node.
+
+ In the example above A/B/C/D and A/B/C/D/E are the nodes that get
+ the extended delete, A/B/C is already deleted.
+ */
+static svn_error_t *
+extend_parent_delete(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t have_row;
+ svn_sqlite__stmt_t *stmt;
+ apr_int64_t parent_op_depth;
+ const char *parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+ SVN_ERR_ASSERT(local_relpath[0]);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_SELECT_LOWEST_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (have_row)
+ {
+ apr_int64_t op_depth;
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (!have_row || parent_op_depth < op_depth)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isit", wc_id,
+ local_relpath, parent_op_depth,
+ presence_map,
+ svn_wc__db_status_base_deleted));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* This is the reverse of extend_parent_delete.
+
+ When removing a base node if the parent has a working node then the
+ parent base and this node are both deleted and so the delete of
+ this node must be removed.
+ */
+static svn_error_t *
+retract_parent_delete(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_DELETE_LOWEST_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ return SVN_NO_ERROR;
+}
+
+
+
/* */
static svn_error_t *
insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
{
const insert_base_baton_t *pibb = baton;
-#ifndef SVN_WC__NODES_ONLY
svn_sqlite__stmt_t *stmt;
-#endif
-#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);
+ SVN_ERR_ASSERT(pibb->repos_id != INVALID_REPOS_ID);
+ SVN_ERR_ASSERT(pibb->repos_relpath != NULL);
+
/* ### 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, "isissttr",
- pibb->wc_id, pibb->local_relpath,
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "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,
- parent_relpath,
- presence_map, pibb->status,
- kind_map, pibb->kind,
- pibb->revision));
+ 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 */
+ pibb->changed_rev, /* 11 */
+ pibb->changed_date, /* 12 */
+ pibb->changed_author, /* 13 */
+ (pibb->kind == svn_wc__db_kind_symlink) ?
+ pibb->target : NULL)); /* 19 */
- SVN_ERR(svn_sqlite__bind_properties(stmt, 9, pibb->props, scratch_pool));
+ if (pibb->kind == svn_wc__db_kind_file) {
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, pibb->checksum, scratch_pool));
+ if (pibb->translated_size != SVN_INVALID_FILESIZE)
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 16, pibb->translated_size));
+ }
- if (SVN_IS_VALID_REVNUM(pibb->changed_rev))
- SVN_ERR(svn_sqlite__bind_int64(stmt, 10, pibb->changed_rev));
- if (pibb->changed_date)
- SVN_ERR(svn_sqlite__bind_int64(stmt, 11, pibb->changed_date));
- if (pibb->changed_author)
- SVN_ERR(svn_sqlite__bind_text(stmt, 12, pibb->changed_author));
-
- if (pibb->kind == svn_wc__db_kind_dir)
- {
- SVN_ERR(svn_sqlite__bind_text(stmt, 13, svn_depth_to_word(pibb->depth)));
- }
- else if (pibb->kind == svn_wc__db_kind_file)
- {
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, pibb->checksum,
- scratch_pool));
- if (pibb->translated_size != SVN_INVALID_FILESIZE)
- SVN_ERR(svn_sqlite__bind_int64(stmt, 15, pibb->translated_size));
- }
- else if (pibb->kind == svn_wc__db_kind_symlink)
- {
- /* Note: incomplete nodes may have a NULL target. */
- if (pibb->target)
- 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_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 */
- pibb->changed_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,
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, pibb->props,
scratch_pool));
if (pibb->dav_cache)
- SVN_ERR(svn_sqlite__bind_properties(stmt_node, 18, pibb->dav_cache,
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 18, pibb->dav_cache,
scratch_pool));
- SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
-#endif
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
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(insert_incomplete_children(sdb, pibb->wc_id,
+ pibb->local_relpath,
+ pibb->repos_id,
+ pibb->repos_relpath,
+ pibb->revision,
+ pibb->children,
+ 0 /* BASE */,
+ scratch_pool));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(svn_sqlite__bindf(stmt, "issr",
- pibb->wc_id,
- svn_relpath_join(pibb->local_relpath,
- name,
- scratch_pool),
- 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
- }
- }
+ if (parent_relpath)
+ SVN_ERR(extend_parent_delete(sdb, pibb->wc_id, pibb->local_relpath,
+ scratch_pool));
SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
@@ -934,93 +900,57 @@ 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,
- const char *local_relpath,
- const apr_array_header_t *children,
- apr_pool_t *scratch_pool)
+/* Insert a row in NODES for each (const char *) child name in CHILDREN,
+ whose parent directory is LOCAL_RELPATH, at op_depth=OP_DEPTH. Set each
+ child's presence to 'incomplete', kind to 'unknown', repos_id to REPOS_ID,
+ repos_path by appending the child name to REPOS_PATH, and revision to
+ REVISION (which should match the parent's revision).
+
+ If REPOS_ID is INVALID_REPOS_ID, set each child's repos_id to null. */
+static svn_error_t *
+insert_incomplete_children(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_int64_t repos_id,
+ const char *repos_path,
+ svn_revnum_t revision,
+ const apr_array_header_t *children,
+ apr_int64_t op_depth,
+ 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
+ SVN_ERR_ASSERT(repos_path != NULL || op_depth > 0);
+ SVN_ERR_ASSERT((repos_id != INVALID_REPOS_ID)
+ == (repos_path != NULL));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
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",
+ SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsns",
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 */
+ op_depth,
local_relpath,
+ revision,
"incomplete", /* 8, presence */
"unknown")); /* 10, kind */
- SVN_ERR(svn_sqlite__insert(NULL, stmt_node));
-#endif
+ if (repos_id != INVALID_REPOS_ID)
+ {
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 5, repos_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 6,
+ svn_relpath_join(repos_path, name,
+ scratch_pool)));
+ }
+
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
}
return SVN_NO_ERROR;
@@ -1034,89 +964,20 @@ insert_working_node(void *baton,
{
const insert_working_baton_t *piwb = baton;
const char *parent_relpath;
-#ifndef SVN_WC__NODES_ONLY
svn_sqlite__stmt_t *stmt;
-#endif
-#ifdef SVN_WC__NODES
- svn_sqlite__stmt_t *stmt_node;
- apr_int64_t op_depth;
-#endif
+
+ SVN_ERR_ASSERT(piwb->op_depth > 0);
/* We cannot insert a WORKING_NODE row at the wcroot. */
- /* ### actually, with per-dir DB, we can... */
SVN_ERR_ASSERT(*piwb->local_relpath != '\0');
- 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,
- parent_relpath,
- presence_map, piwb->presence,
- kind_map, piwb->kind));
-
- if (piwb->original_repos_relpath != NULL)
- {
- SVN_ERR_ASSERT(piwb->original_repos_id > 0);
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(piwb->original_revnum));
-
- SVN_ERR(svn_sqlite__bind_int64(stmt, 6, piwb->original_repos_id));
- SVN_ERR(svn_sqlite__bind_text(stmt, 7, piwb->original_repos_relpath));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 8, piwb->original_revnum));
- }
-
- /* Do not bind 'moved_here' (9), nor 'moved_to' (10). */
-
- /* 'checksum' (11) is bound below. */
-
- /* Do not bind 'translated_size' (12). */
-
- if (SVN_IS_VALID_REVNUM(piwb->changed_rev))
- SVN_ERR(svn_sqlite__bind_int64(stmt, 13, piwb->changed_rev));
- if (piwb->changed_date)
- SVN_ERR(svn_sqlite__bind_int64(stmt, 14, piwb->changed_date));
- if (piwb->changed_author)
- SVN_ERR(svn_sqlite__bind_text(stmt, 15, piwb->changed_author));
-
- if (piwb->kind == svn_wc__db_kind_dir)
- {
- SVN_ERR(svn_sqlite__bind_text(stmt, 16, svn_depth_to_word(piwb->depth)));
- }
- else if (piwb->kind == svn_wc__db_kind_file)
- {
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 11, piwb->checksum,
- scratch_pool));
- }
- else if (piwb->kind == svn_wc__db_kind_symlink)
- {
- SVN_ERR_ASSERT(piwb->target != NULL);
-
- SVN_ERR(svn_sqlite__bind_text(stmt, 20, piwb->target));
- }
-
- /* Do not bind 'last_mod_time' (17). */
-
- SVN_ERR(svn_sqlite__bind_properties(stmt, 18, piwb->props, scratch_pool));
-
- /* Do not bind 'keep_local' (19). */
- /* 'symlink_target' (20) is bound above. */
+ parent_relpath = svn_relpath_dirname(piwb->local_relpath, scratch_pool);
- 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"
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isisnnntstrisn"
"nnnn" /* properties translated_size last_mod_time dav_cache */
"s",
piwb->wc_id, piwb->local_relpath,
- op_depth,
+ piwb->op_depth,
parent_relpath,
presence_map, piwb->presence,
(piwb->kind == svn_wc__db_kind_dir)
@@ -1131,37 +992,41 @@ insert_working_node(void *baton,
if (piwb->kind == svn_wc__db_kind_file)
{
- SVN_ERR(svn_sqlite__bind_checksum(stmt_node, 14, piwb->checksum,
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 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));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 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_int64(stmt, 5, piwb->original_repos_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 6, piwb->original_repos_relpath));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 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
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, piwb->props, scratch_pool));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+ /* Insert incomplete children, if specified.
+ The children are part of the same op and so have the same op_depth.
+ (The only time we'd want a different depth is during a recursive
+ simple add, but we never insert children here during a simple add.) */
if (piwb->kind == svn_wc__db_kind_dir && piwb->children)
- SVN_ERR(insert_incomplete_working_children(sdb, piwb->wc_id,
- piwb->local_relpath,
- piwb->children,
- scratch_pool));
+ SVN_ERR(insert_incomplete_children(sdb, piwb->wc_id,
+ piwb->local_relpath,
+ INVALID_REPOS_ID /* inherit repos_id */,
+ NULL /* inherit repos_path */,
+ piwb->original_revnum,
+ piwb->children,
+ piwb->op_depth,
+ scratch_pool));
SVN_ERR(add_work_items(sdb, piwb->work_items, scratch_pool));
@@ -1169,25 +1034,6 @@ 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,
- svn_sqlite__db_t *sdb,
- apr_int64_t wc_id,
- const char *parent_relpath)
-{
- svn_sqlite__stmt_t *stmt;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
- SVN_ERR(svn_sqlite__step_row(stmt));
- *count = svn_sqlite__column_int(stmt, 0);
- return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
/* Each name is allocated in RESULT_POOL and stored into CHILDREN as a key
pointed to the same name. */
static svn_error_t *
@@ -1218,226 +1064,65 @@ 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). */
+/* Return in *CHILDREN all of the children of the directory LOCAL_RELPATH,
+ of any status, in all op-depths in the NODES table. */
static svn_error_t *
-union_children(const apr_array_header_t **children,
- svn_sqlite__db_t *sdb,
- apr_int64_t wc_id,
- const char *parent_relpath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+gather_children(const apr_array_header_t **children,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- /* ### it would be nice to pre-size this hash table. */
- apr_hash_t *names = apr_hash_make(scratch_pool);
-#ifdef SVN_WC__NODES
- apr_hash_t *names_nodes = apr_hash_make(scratch_pool);
-#endif
+ apr_hash_t *names_hash = apr_hash_make(scratch_pool);
apr_array_header_t *names_array;
- /* All of the names get allocated in RESULT_POOL. */
- SVN_ERR(add_children_to_hash(names, STMT_SELECT_BASE_NODE_CHILDREN,
- sdb, wc_id, parent_relpath, result_pool));
- SVN_ERR(add_children_to_hash(names, STMT_SELECT_WORKING_NODE_CHILDREN,
- sdb, wc_id, parent_relpath, result_pool));
-#ifdef SVN_WC__NODES
- SVN_ERR(add_children_to_hash(names_nodes, STMT_SELECT_BASE_NODE_CHILDREN_1,
- sdb, wc_id, parent_relpath, result_pool));
- SVN_ERR(add_children_to_hash(names_nodes, STMT_SELECT_WORKING_NODE_CHILDREN_1,
- sdb, wc_id, parent_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT(apr_hash_count(names) == apr_hash_count(names_nodes));
-#else
- names = names_nodes;
-#endif
-#endif
+ /* All of the names get allocated in RESULT_POOL. It
+ appears to be faster to use the hash to remove duplicates than to
+ use DISTINCT in the SQL query. */
+ SVN_ERR(add_children_to_hash(names_hash, STMT_SELECT_NODE_CHILDREN,
+ pdh->wcroot->sdb, pdh->wcroot->wc_id,
+ local_relpath, result_pool));
- SVN_ERR(svn_hash_keys(&names_array, names, result_pool));
+ SVN_ERR(svn_hash_keys(&names_array, names_hash, result_pool));
*children = names_array;
-
return SVN_NO_ERROR;
}
-
-/* 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,
- int start_size,
- svn_sqlite__db_t *sdb,
- apr_int64_t wc_id,
- const char *parent_relpath,
- apr_pool_t *result_pool)
+/* Set *CHILDREN to a new array of (const char *) names of the repository
+ children of the directory PDH:LOCAL_RELPATH - that is, the children at
+ the same op-depth. */
+static svn_error_t *
+gather_repo_children(const apr_array_header_t **children,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_int64_t op_depth,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
+ apr_array_header_t *result
+ = apr_array_make(result_pool, 0, sizeof(const char *));
svn_sqlite__stmt_t *stmt;
- apr_array_header_t *child_names;
svn_boolean_t have_row;
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, stmt_idx));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
-
- /* ### should test the node to ensure it is a directory */
-
- child_names = apr_array_make(result_pool, start_size, sizeof(const char *));
-
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_OP_DEPTH_CHILDREN));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isi", pdh->wcroot->wc_id, local_relpath,
+ op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
while (have_row)
{
const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
- APR_ARRAY_PUSH(child_names, const char *) =
- svn_relpath_basename(child_relpath, result_pool);
+ /* Allocate the name in RESULT_POOL so we won't have to copy it. */
+ APR_ARRAY_PUSH(result, const char *)
+ = svn_relpath_basename(child_relpath, result_pool);
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
+ SVN_ERR(svn_sqlite__reset(stmt));
- *children = child_names;
-
- return svn_sqlite__reset(stmt);
-}
-
-
-/* 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,
- 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;
- int base_count;
- int working_count;
-#ifdef SVN_WC__NODES
- int base_count_nodes, working_count_nodes;
- const apr_array_header_t *children_nodes;
-#endif
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath,
- svn_sqlite__mode_readonly,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- if (base_only)
- {
- /* 10 is based on Subversion's average of 8.7 files per versioned
- directory in its repository.
-
- ### note "files". should redo count with subdirs included */
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
- 10 /* start_size */,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
- SVN_ERR(single_table_children(&children_nodes,
- STMT_SELECT_BASE_NODE_CHILDREN_1,
- 10 /* start_size */,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
- *children = children_nodes;
-#endif
-#endif
- return SVN_NO_ERROR;
- }
-
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(count_children(&base_count, STMT_COUNT_BASE_NODE_CHILDREN,
- pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
- SVN_ERR(count_children(&working_count, STMT_COUNT_WORKING_NODE_CHILDREN,
- pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
-#endif
-#ifdef SVN_WC__NODES
- SVN_ERR(count_children(&base_count_nodes, STMT_COUNT_BASE_NODE_CHILDREN_1,
- pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
- SVN_ERR(count_children(&working_count_nodes,
- STMT_COUNT_WORKING_NODE_CHILDREN_1,
- pdh->wcroot->sdb, pdh->wcroot->wc_id, local_relpath));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT(base_count == base_count_nodes);
- SVN_ERR_ASSERT(working_count == working_count_nodes);
-#else
- base_count = base_count_nodes;
- working_count = working_count_nodes;
-#endif
-#endif
-
- if (base_count == 0)
- {
- if (working_count == 0)
- {
- *children = apr_array_make(result_pool, 0, sizeof(const char *));
- return SVN_NO_ERROR;
- }
-
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(single_table_children(children, STMT_SELECT_WORKING_NODE_CHILDREN,
- working_count,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
- SVN_ERR(single_table_children(&children_nodes,
- STMT_SELECT_WORKING_NODE_CHILDREN,
- working_count,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
- *children = children_nodes;
-#endif
-#endif
- return SVN_NO_ERROR;
- }
- if (working_count == 0)
- {
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(single_table_children(children, STMT_SELECT_BASE_NODE_CHILDREN,
- base_count,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#endif
-#ifdef SVN_WC__NODES
- SVN_ERR(single_table_children(&children_nodes,
- STMT_SELECT_BASE_NODE_CHILDREN_1,
- base_count,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath, result_pool));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT((*children)->nelts == children_nodes->nelts);
-#else
- *children = children_nodes;
-#endif
-#endif
- return SVN_NO_ERROR;
- }
-
- /* ### it would be nice to pass BASE_COUNT and WORKING_COUNT, but there is
- ### nothing union_children() can do with those. */
- return svn_error_return(union_children(children,
- pdh->wcroot->sdb, pdh->wcroot->wc_id,
- local_relpath,
- result_pool, scratch_pool));
+ *children = result;
+ return SVN_NO_ERROR;
}
@@ -1535,33 +1220,14 @@ which_trees_exist(svn_boolean_t *base_ex
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
-#ifdef SVN_WC__NODES
- svn_sqlite__stmt_t *stmt_nodes;
- svn_boolean_t have_nodes_row;
-#endif
*base_exists = FALSE;
*working_exists = FALSE;
-#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_DETERMINE_TREE_FOR_RECORDING));
SVN_ERR(svn_sqlite__bindf(stmt, "is", 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, sdb,
- STMT_DETERMINE_TREE_FOR_RECORDING_1));
- SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(svn_sqlite__reset(stmt_nodes));
-#else
- stmt = stmt_nodes;
- have_row = have_nodes_row;
-#endif
-#endif
if (have_row)
{
@@ -1607,7 +1273,6 @@ prop_upgrade_trees(svn_boolean_t *base_e
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PLAN_PROP_UPGRADE));
SVN_ERR(svn_sqlite__bindf(stmt, "s", local_relpath));
-
SVN_ERR(svn_sqlite__step(&have_row, stmt));
/* During a property upgrade, there better be a row corresponding to
@@ -1674,10 +1339,8 @@ 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,
@@ -2218,109 +1881,101 @@ svn_wc__db_base_add_not_present_node(svn
kind, svn_wc__db_status_not_present, conflict, work_items, scratch_pool);
}
+struct base_remove_baton {
+ const char *local_relpath;
+ apr_int64_t wc_id;
+};
-svn_error_t *
-svn_wc__db_base_remove(svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+db_base_remove(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
+ struct base_remove_baton *brb = baton;
svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_BASE_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", brb->wc_id, brb->local_relpath));
+ SVN_ERR(svn_sqlite__step_done(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);
-
-#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
+ SVN_ERR(retract_parent_delete(sdb, brb->wc_id, brb->local_relpath,
+ scratch_pool));
-#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
-
- SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+ /* If there is no working node then any actual node must be deleted,
+ unless it marks a conflict */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", brb->wc_id, brb->local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (!have_row)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", brb->wc_id, brb->local_relpath));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
return SVN_NO_ERROR;
}
-
svn_error_t *
-svn_wc__db_base_get_info(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_revnum_t *changed_rev,
- apr_time_t *changed_date,
- const char **changed_author,
- apr_time_t *last_mod_time,
- svn_depth_t *depth,
- const svn_checksum_t **checksum,
- svn_filesize_t *translated_size,
- const char **target,
- svn_wc__db_lock_t **lock,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_wc__db_base_remove(svn_wc__db_t *db,
+ const char *local_abspath,
+ 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;
-#ifdef SVN_WC__NODES
- svn_sqlite__stmt_t *stmt_nodes;
- svn_boolean_t have_node_row;
-#endif
- svn_error_t *err = SVN_NO_ERROR;
+ struct base_remove_baton brb;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readonly,
+ local_abspath, svn_sqlite__mode_readwrite,
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
-#ifndef SVN_WC__NODES_ONLY
+ brb.local_relpath = local_relpath;
+ brb.wc_id = pdh->wcroot->wc_id;
+
+ SVN_ERR(svn_sqlite__with_transaction(pdh->wcroot->sdb,
+ db_base_remove, &brb,
+ scratch_pool));
+
+ SVN_ERR(flush_entries(db, pdh, local_abspath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Like svn_wc__db_base_get_info(), but taking PDH+LOCAL_RELPATH instead of
+ * DB+LOCAL_ABSPATH and outputting REPOS_ID instead of URL+UUID. */
+static svn_error_t *
+base_get_info(svn_wc__db_status_t *status,
+ svn_wc__db_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,
+ apr_time_t *last_mod_time,
+ svn_depth_t *depth,
+ const svn_checksum_t **checksum,
+ svn_filesize_t *translated_size,
+ const char **target,
+ svn_wc__db_lock_t **lock,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ svn_error_t *err = SVN_NO_ERROR;
+
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));
-
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(assert_base_rows_match(have_row, have_node_row, stmt, stmt_nodes,
- local_relpath, scratch_pool));
-#else
- /* Lets assume the two queries return compatible data */
- have_row = have_node_row;
- stmt = stmt_nodes;
-#endif
-
-#endif /* SVN_WC__NODES */
if (have_row)
{
@@ -2335,51 +1990,13 @@ svn_wc__db_base_get_info(svn_wc__db_stat
{
*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);
- }
+ err = repos_location_from_columns(repos_id, revision, repos_relpath,
+ pdh, stmt, 0, 4, 1, result_pool);
+ SVN_ERR_ASSERT(!repos_id || *repos_id != INVALID_REPOS_ID);
+ SVN_ERR_ASSERT(!repos_relpath || *repos_relpath);
if (lock)
{
- if (svn_sqlite__column_is_null(stmt, 14))
- {
- *lock = NULL;
- }
- else
- {
- *lock = apr_pcalloc(result_pool, sizeof(svn_wc__db_lock_t));
- (*lock)->token = svn_sqlite__column_text(stmt, 14, result_pool);
- if (!svn_sqlite__column_is_null(stmt, 15))
- (*lock)->owner = svn_sqlite__column_text(stmt, 15,
- result_pool);
- if (!svn_sqlite__column_is_null(stmt, 16))
- (*lock)->comment = svn_sqlite__column_text(stmt, 16,
- result_pool);
- if (!svn_sqlite__column_is_null(stmt, 17))
- (*lock)->date = svn_sqlite__column_int64(stmt, 17);
- }
- }
- 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);
- }
+ *lock = lock_from_columns(stmt, 14, 15, 16, 17, result_pool);
}
if (changed_rev)
{
@@ -2428,7 +2045,8 @@ svn_wc__db_base_get_info(svn_wc__db_stat
err = svn_error_createf(
err->apr_err, err,
_("The node '%s' has a corrupt checksum value."),
- svn_dirent_local_style(local_abspath, scratch_pool));
+ path_for_error_message(pdh->wcroot, local_relpath,
+ scratch_pool));
}
}
if (translated_size)
@@ -2447,110 +2065,59 @@ svn_wc__db_base_get_info(svn_wc__db_stat
{
err = svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
_("The node '%s' was not found."),
- svn_dirent_local_style(local_abspath,
+ path_for_error_message(pdh->wcroot, local_relpath,
scratch_pool));
}
-#ifdef SVN_WC__NODES
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR(svn_sqlite__reset(stmt_nodes));
-#endif
-#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_base_get_info(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_revnum_t *changed_rev,
+ apr_time_t *changed_date,
+ const char **changed_author,
+ apr_time_t *last_mod_time,
+ svn_depth_t *depth,
+ const svn_checksum_t **checksum,
+ svn_filesize_t *translated_size,
+ const char **target,
+ svn_wc__db_lock_t **lock,
+ 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;
+ apr_int64_t repos_id;
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,
+ local_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));
- }
+ SVN_ERR(base_get_info(status, kind, revision, repos_relpath, &repos_id,
+ changed_rev, changed_date, changed_author,
+ last_mod_time, depth, checksum, translated_size,
+ target, lock,
+ pdh, local_relpath, result_pool, scratch_pool));
+ SVN_ERR_ASSERT(repos_id != INVALID_REPOS_ID);
+ SVN_ERR(fetch_repos_info(repos_root_url, repos_uuid,
+ pdh->wcroot->sdb, repos_id, result_pool));
- /* Note: given the composition, no need to wrap for tracing. */
- return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ return SVN_NO_ERROR;
}
-
svn_error_t *
svn_wc__db_base_get_prop(const svn_string_t **propval,
svn_wc__db_t *db,
@@ -2587,29 +2154,10 @@ svn_wc__db_base_get_props(apr_hash_t **p
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
svn_error_t *err;
-#ifdef SVN_WC__NODES
- svn_sqlite__stmt_t *stmt_node;
- svn_boolean_t have_node_row;
-#endif
-#ifndef SVN_WC__NODES_ONLY
SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
STMT_SELECT_BASE_PROPS, scratch_pool));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
-#endif
-#ifdef SVN_WC__NODES
- SVN_ERR(get_statement_for_path(&stmt_node, db, local_abspath,
- STMT_SELECT_BASE_PROPS_1, scratch_pool));
- SVN_ERR(svn_sqlite__step(&have_node_row, stmt_node));
-#ifndef SVN_WC__NODES_ONLY
- SVN_ERR_ASSERT(have_row == have_node_row);
- SVN_ERR(assert_blob_columns_equal(stmt, stmt_node, 0, scratch_pool));
- SVN_ERR(svn_sqlite__reset(stmt_node));
-#else
- stmt = stmt_node;
- have_row = have_node_row;
-#endif
-#endif
if (!have_row)
{
err = svn_sqlite__reset(stmt);
@@ -2639,8 +2187,19 @@ svn_wc__db_base_get_children(const apr_a
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- return gather_children(children, TRUE,
- db, local_abspath, result_pool, scratch_pool);
+ svn_wc__db_pdh_t *pdh;
+ const char *local_relpath;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
+ local_abspath,
+ svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ return gather_repo_children(children, pdh, local_relpath, 0,
+ result_pool, scratch_pool);
}
@@ -2653,20 +2212,6 @@ svn_wc__db_base_set_dav_cache(svn_wc__db
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));
-
- 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
-#ifdef SVN_WC__NODES
SVN_ERR(get_statement_for_path(&stmt, db, local_abspath,
STMT_UPDATE_BASE_NODE_DAV_CACHE,
scratch_pool));
@@ -2679,7 +2224,6 @@ svn_wc__db_base_set_dav_cache(svn_wc__db
_("The node '%s' was not found."),
svn_dirent_local_style(local_abspath,
scratch_pool));
-#endif
return SVN_NO_ERROR;
}
@@ -2727,28 +2271,14 @@ svn_wc__db_base_clear_dav_cache_recursiv
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);
+ like_arg = construct_like_arg(local_relpath, scratch_pool);
-#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;
}
@@ -3136,22 +2666,21 @@ svn_wc__db_pristine_cleanup(svn_wc__db_t
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- /* Find the pristines in the DB */
+ /* Find each unreferenced pristine in the DB and remove it. */
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_SELECT_PRISTINE_ROWS));
+ STMT_SELECT_UNREFERENCED_PRISTINES));
while (1)
{
svn_boolean_t have_row;
- const svn_checksum_t *checksum;
+ const svn_checksum_t *sha1_checksum;
SVN_ERR(svn_sqlite__step(&have_row, stmt));
if (! have_row)
break;
- SVN_ERR(svn_sqlite__column_checksum(&checksum, stmt, 0,
+ SVN_ERR(svn_sqlite__column_checksum(&sha1_checksum, stmt, 0,
scratch_pool));
- SVN_ERR(svn_wc__db_pristine_remove(db, wri_abspath, checksum,
- scratch_pool));
+ SVN_ERR(pristine_remove(pdh, sha1_checksum, scratch_pool));
}
SVN_ERR(svn_sqlite__reset(stmt));
@@ -3215,57 +2744,21 @@ svn_wc__db_pristine_check(svn_boolean_t
}
-svn_error_t *
-svn_wc__db_pristine_repair(svn_wc__db_t *db,
- const char *wri_abspath,
- const svn_checksum_t *sha1_checksum,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
- SVN_ERR_ASSERT(sha1_checksum != NULL);
- SVN_ERR_ASSERT(sha1_checksum->kind == svn_checksum_sha1);
-
- NOT_IMPLEMENTED();
-}
-
-
-svn_error_t *
-svn_wc__db_repos_ensure(apr_int64_t *repos_id,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *repos_root_url,
- const char *repos_uuid,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
-
- 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);
-
- return svn_error_return(create_repos_id(repos_id, repos_root_url,
- repos_uuid, pdh->wcroot->sdb,
- scratch_pool));
-}
-
-/* Temporary helper for svn_wc__db_op_copy to handle copying from one
- db to another, it becomes redundant when we centralise. */
+/* Helper for svn_wc__db_op_copy to handle copying from one db to
+ another */
static svn_error_t *
-temp_cross_db_copy(svn_wc__db_t *db,
- const char *src_abspath,
- svn_wc__db_pdh_t *src_pdh,
- const char *src_relpath,
- svn_wc__db_pdh_t *dst_pdh,
- const char *dst_relpath,
- svn_wc__db_status_t dst_status,
- svn_wc__db_kind_t kind,
- const apr_array_header_t *children,
- apr_int64_t copyfrom_id,
- const char *copyfrom_relpath,
- svn_revnum_t copyfrom_rev,
- apr_pool_t *scratch_pool)
+cross_db_copy(svn_wc__db_pdh_t *src_pdh,
+ const char *src_relpath,
+ svn_wc__db_pdh_t *dst_pdh,
+ const char *dst_relpath,
+ svn_wc__db_status_t dst_status,
+ apr_int64_t dst_op_depth,
+ svn_wc__db_kind_t kind,
+ const apr_array_header_t *children,
+ apr_int64_t copyfrom_id,
+ const char *copyfrom_relpath,
+ svn_revnum_t copyfrom_rev,
+ apr_pool_t *scratch_pool)
{
insert_working_baton_t iwb;
svn_revnum_t changed_rev;
@@ -3281,32 +2774,30 @@ temp_cross_db_copy(svn_wc__db_t *db,
|| kind == svn_wc__db_kind_dir
);
- SVN_ERR(svn_wc__db_read_info(NULL /* status */,
- NULL /* kind */,
- NULL /* revision */,
- NULL /* repos_relpath */,
- NULL /* repos_root_url */,
- NULL /* repos_uuid */,
- &changed_rev, &changed_date, &changed_author,
- NULL /* last_mod_time */,
- &depth,
- &checksum,
- NULL /* translated_size */,
- NULL /* target */,
- NULL /* changelist */,
- NULL /* original_repos_relpath */,
- NULL /* original_root_url */,
- NULL /* original_uuid */,
- NULL /* original_revision */,
- NULL /* props_mod */,
- NULL /* have_base */,
- NULL /* have_work */,
- NULL /* conflicted */,
- NULL /* lock */,
- db, src_abspath, scratch_pool, scratch_pool));
+ SVN_ERR(read_info(NULL /* status */,
+ NULL /* kind */,
+ NULL /* revision */,
+ NULL /* repos_relpath */,
+ NULL /* repos_id */,
+ &changed_rev, &changed_date, &changed_author,
+ NULL /* last_mod_time */,
+ &depth,
+ &checksum,
+ NULL /* translated_size */,
+ NULL /* target */,
+ NULL /* changelist */,
+ NULL /* original_repos_relpath */,
+ NULL /* original_repos_id */,
+ NULL /* original_revision */,
+ NULL /* props_mod */,
+ NULL /* have_base */,
+ NULL /* have_work */,
+ NULL /* conflicted */,
+ NULL /* lock */,
+ src_pdh, src_relpath, scratch_pool, scratch_pool));
- SVN_ERR(svn_wc__get_pristine_props(&props, db, src_abspath,
- scratch_pool, scratch_pool));
+ SVN_ERR(db_read_pristine_props(&props, src_pdh, src_relpath,
+ scratch_pool, scratch_pool));
blank_iwb(&iwb);
iwb.presence = dst_status;
@@ -3323,6 +2814,8 @@ temp_cross_db_copy(svn_wc__db_t *db,
iwb.original_revnum = copyfrom_rev;
iwb.moved_here = FALSE;
+ iwb.op_depth = dst_op_depth;
+
iwb.checksum = checksum;
iwb.children = children;
iwb.depth = depth;
@@ -3380,50 +2873,47 @@ get_info_for_copy(apr_int64_t *copyfrom_
svn_wc__db_kind_t *kind,
svn_boolean_t *have_work,
svn_wc__db_pdh_t *pdh,
- svn_wc__db_t *db,
- const char *local_abspath,
+ const char *local_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- const char *repos_relpath, *repos_root_url, *repos_uuid;
+ const char *repos_relpath;
svn_revnum_t revision;
- SVN_ERR(svn_wc__db_read_info(status, kind, &revision,
- &repos_relpath, &repos_root_url, &repos_uuid,
- NULL /* changed_rev */,
- NULL /* changed_date */,
- NULL /* changed_author */,
- NULL /* last_mod_time */,
- NULL /* depth */,
- NULL /* checksum */,
- NULL /* translated_size */,
- NULL /* target */,
- NULL /* changelist */,
- NULL /* original_repos_relpath */,
- NULL /* original_root_url */,
- NULL /* original_uuid */,
- NULL /* original_revision */,
- NULL /* props_mod */,
- NULL /* have_base */,
- have_work,
- NULL /* conflicted */,
- NULL /* lock */,
- db, local_abspath, result_pool, scratch_pool));
+ SVN_ERR(read_info(status, kind, &revision, &repos_relpath, copyfrom_id,
+ NULL /* changed_rev */,
+ NULL /* changed_date */,
+ NULL /* changed_author */,
+ NULL /* last_mod_time */,
+ NULL /* depth */,
+ NULL /* checksum */,
+ NULL /* translated_size */,
+ NULL /* target */,
+ NULL /* changelist */,
+ NULL /* original_repos_relpath */,
+ NULL /* original_repos_id */,
+ NULL /* original_revision */,
+ NULL /* props_mod */,
+ NULL /* have_base */,
+ have_work,
+ NULL /* conflicted */,
+ NULL /* lock */,
+ pdh, local_relpath, result_pool, scratch_pool));
if (*status == svn_wc__db_status_excluded)
{
/* The parent cannot be excluded, so look at the parent and then
adjust the relpath */
- const char *parent_abspath, *base_name;
+ const char *parent_relpath, *base_name;
svn_wc__db_status_t parent_status;
svn_wc__db_kind_t parent_kind;
svn_boolean_t parent_have_work;
- svn_dirent_split(&parent_abspath, &base_name, local_abspath,
+ svn_dirent_split(&parent_relpath, &base_name, local_relpath,
scratch_pool);
SVN_ERR(get_info_for_copy(copyfrom_id, copyfrom_relpath, copyfrom_rev,
&parent_status, &parent_kind, &parent_have_work,
- pdh, db, parent_abspath,
+ pdh, parent_relpath,
scratch_pool, scratch_pool));
if (*copyfrom_relpath)
*copyfrom_relpath = svn_relpath_join(*copyfrom_relpath, base_name,
@@ -3431,142 +2921,108 @@ get_info_for_copy(apr_int64_t *copyfrom_
}
else if (*status == svn_wc__db_status_added)
{
- const char *op_root_abspath;
- const char *original_repos_relpath, *original_root_url, *original_uuid;
- svn_revnum_t original_revision;
-
- SVN_ERR(svn_wc__db_scan_addition(status, &op_root_abspath,
- NULL /* repos_relpath */,
- NULL /* repos_root_url */,
- NULL /* repos_uuid */,
- &original_repos_relpath,
- &original_root_url, &original_uuid,
- &original_revision,
- db, local_abspath,
[... 5771 lines stripped ...]