You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/12/29 22:12:38 UTC
svn commit: r1053735 [4/8] - in /subversion/branches/performance: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
contrib/client-side/svn_load_dirs/ notes/
subversion/bindings/javahl/native/ subversion/bindings/swig/
subversion/includ...
Modified: subversion/branches/performance/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/upgrade.c?rev=1053735&r1=1053734&r2=1053735&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/upgrade.c Wed Dec 29 21:12:33 2010
@@ -622,15 +622,6 @@ ensure_repos_info(svn_wc_entry_t *entry,
}
-/* */
-static svn_error_t *
-bump_to_13(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_13));
-
- return SVN_NO_ERROR;
-}
-
/*
* Read tree conflict descriptions from @a conflict_data. Set @a *conflicts
* to a hash of pointers to svn_wc_conflict_description2_t objects indexed by
@@ -804,68 +795,10 @@ migrate_tree_conflict_data(svn_sqlite__d
}
-/* */
-static svn_error_t *
-migrate_locks(const char *wcroot_abspath,
- svn_sqlite__db_t *sdb,
- apr_pool_t *scratch_pool)
-{
- const char *lockfile_abspath = build_lockfile_path(wcroot_abspath,
- scratch_pool);
- svn_node_kind_t kind;
-
- SVN_ERR(svn_io_check_path(lockfile_abspath, &kind, scratch_pool));
- if (kind != svn_node_none)
- {
- svn_sqlite__stmt_t *stmt;
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_WC_LOCK));
- /* ### These values are magic, and will need to be updated when we
- ### go to a centralized system. */
- SVN_ERR(svn_sqlite__bindf(stmt, "is", (apr_int64_t)1, ""));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- return SVN_NO_ERROR;
-}
-
struct bump_baton {
const char *wcroot_abspath;
};
-/* */
-static svn_error_t *
-bump_to_14(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
- const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
-
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_14));
-
- SVN_ERR(migrate_locks(wcroot_abspath, sdb, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-
-/* */
-static svn_error_t *
-bump_to_15(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_15));
-
- return SVN_NO_ERROR;
-}
-
-
-/* */
-static svn_error_t *
-bump_to_16(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_16));
-
- return SVN_NO_ERROR;
-}
-
-
/* Migrate the properties for one node (LOCAL_ABSPATH). */
static svn_error_t *
migrate_node_props(const char *dir_abspath,
@@ -1004,33 +937,36 @@ migrate_props(const char *dir_abspath,
}
-/* */
-struct bump_to_18_baton
-{
- const char *wcroot_abspath;
- int original_format;
-};
-
-
-static svn_error_t *
-bump_to_18(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+/* If STR ends with SUFFIX and is longer than SUFFIX, return the part of
+ * STR that comes before SUFFIX; else return NULL. */
+static char *
+remove_suffix(const char *str, const char *suffix, apr_pool_t *result_pool)
{
- struct bump_to_18_baton *b18 = baton;
-
- /* ### no schema changes (yet)... */
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_18));
+ int str_len = strlen(str);
+ int suffix_len = strlen(suffix);
- SVN_ERR(migrate_props(b18->wcroot_abspath, b18->wcroot_abspath, sdb,
- b18->original_format, scratch_pool));
+ if (str_len > suffix_len
+ && strcmp(str + str_len - suffix_len, suffix) == 0)
+ {
+ return apr_pstrmemdup(result_pool, str, str_len - suffix_len);
+ }
- return SVN_NO_ERROR;
+ return NULL;
}
+/* Copy all the text-base files from the administrative area of WC directory
+ DIR_ABSPATH into the pristine store of SDB which is located in directory
+ NEW_WCROOT_ABSPATH.
+ Set *TEXT_BASES_INFO to a new hash, allocated in RESULT_POOL, that maps
+ (const char *) name of the versioned file to (svn_wc__text_base_info_t *)
+ information about the pristine text. */
static svn_error_t *
-migrate_text_bases(const char *dir_abspath,
+migrate_text_bases(apr_hash_t **text_bases_info,
+ const char *dir_abspath,
const char *new_wcroot_abspath,
svn_sqlite__db_t *sdb,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_hash_t *dirents;
@@ -1040,80 +976,111 @@ migrate_text_bases(const char *dir_abspa
TEXT_BASE_SUBDIR,
scratch_pool);
+ *text_bases_info = apr_hash_make(result_pool);
+
+ /* Iterate over the text-base files */
SVN_ERR(svn_io_get_dirents3(&dirents, text_base_dir, TRUE,
scratch_pool, scratch_pool));
for (hi = apr_hash_first(scratch_pool, dirents); hi;
- hi = apr_hash_next(hi))
+ hi = apr_hash_next(hi))
{
const char *text_base_basename = svn__apr_hash_index_key(hi);
- const char *pristine_path;
- const char *text_base_path;
svn_checksum_t *md5_checksum;
svn_checksum_t *sha1_checksum;
- svn_sqlite__stmt_t *stmt;
- apr_finfo_t finfo;
svn_pool_clear(iterpool);
- text_base_path = svn_dirent_join(text_base_dir, text_base_basename,
- iterpool);
-
- /* ### This code could be a bit smarter: we could chain checksum
- streams instead of reading the file twice; we could check to
- see if a pristine row exists before attempting to insert one;
- we could check and see if a pristine file exists before
- attempting to copy a new one over it.
-
- However, I think simplicity is the big win here, especially since
- this is code that runs exactly once on a user's machine: when
- doing the upgrade. If you disagree, feel free to add the
- complexity. :) */
-
- /* Gather the two checksums. */
- SVN_ERR(svn_io_file_checksum2(&md5_checksum, text_base_path,
- svn_checksum_md5, iterpool));
- SVN_ERR(svn_io_file_checksum2(&sha1_checksum, text_base_path,
- svn_checksum_sha1, iterpool));
-
- SVN_ERR(svn_io_stat(&finfo, text_base_path, APR_FINFO_SIZE, iterpool));
-
- /* Insert a row into the pristine table. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_PRISTINE));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, iterpool));
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, iterpool));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
- SVN_ERR(svn_sqlite__insert(NULL, stmt));
-
- SVN_ERR(svn_wc__db_pristine_get_future_path(&pristine_path,
- new_wcroot_abspath,
- sha1_checksum,
- iterpool, iterpool));
-
- /* Ensure any sharding directories exist. */
- SVN_ERR(svn_wc__ensure_directory(svn_dirent_dirname(pristine_path,
- iterpool),
- iterpool));
-
- /* Copy, rather than move, so that the upgrade can be restarted.
- It could be moved if upgrades scanned for files in the
- pristine directory as well as the text-base directory. */
- SVN_ERR(svn_io_copy_file(text_base_path, pristine_path, TRUE,
- iterpool));
- }
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
+ /* Calculate its checksums and copy it to the pristine store */
+ {
+ const char *pristine_path;
+ const char *text_base_path;
+ svn_sqlite__stmt_t *stmt;
+ apr_finfo_t finfo;
+ text_base_path = svn_dirent_join(text_base_dir, text_base_basename,
+ iterpool);
-static svn_error_t *
-bump_to_17(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
-{
- const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
+ /* ### This code could be a bit smarter: we could chain checksum
+ streams instead of reading the file twice; we could check to
+ see if a pristine row exists before attempting to insert one;
+ we could check and see if a pristine file exists before
+ attempting to copy a new one over it.
+
+ However, I think simplicity is the big win here, especially since
+ this is code that runs exactly once on a user's machine: when
+ doing the upgrade. If you disagree, feel free to add the
+ complexity. :) */
+
+ /* Gather the two checksums. */
+ SVN_ERR(svn_io_file_checksum2(&md5_checksum, text_base_path,
+ svn_checksum_md5, iterpool));
+ SVN_ERR(svn_io_file_checksum2(&sha1_checksum, text_base_path,
+ svn_checksum_sha1, iterpool));
+
+ SVN_ERR(svn_io_stat(&finfo, text_base_path, APR_FINFO_SIZE, iterpool));
+
+ /* Insert a row into the pristine table. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_PRISTINE));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, iterpool));
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, iterpool));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+ SVN_ERR(svn_wc__db_pristine_get_future_path(&pristine_path,
+ new_wcroot_abspath,
+ sha1_checksum,
+ iterpool, iterpool));
+
+ /* Ensure any sharding directories exist. */
+ SVN_ERR(svn_wc__ensure_directory(svn_dirent_dirname(pristine_path,
+ iterpool),
+ iterpool));
+
+ /* Copy, rather than move, so that the upgrade can be restarted.
+ It could be moved if upgrades scanned for files in the
+ pristine directory as well as the text-base directory. */
+ SVN_ERR(svn_io_copy_file(text_base_path, pristine_path, TRUE,
+ iterpool));
+ }
+
+ /* Add the checksums for this text-base to *TEXT_BASES_INFO. */
+ {
+ const char *versioned_file_name;
+ svn_boolean_t is_revert_base;
+ svn_wc__text_base_info_t *info;
+ svn_wc__text_base_file_info_t *file_info;
+
+ /* Determine the versioned file name and whether this is a normal base
+ * or a revert base. */
+ versioned_file_name = remove_suffix(text_base_basename,
+ SVN_WC__REVERT_EXT, result_pool);
+ if (versioned_file_name)
+ {
+ is_revert_base = TRUE;
+ }
+ else
+ {
+ versioned_file_name = remove_suffix(text_base_basename,
+ SVN_WC__BASE_EXT, result_pool);
+ is_revert_base = FALSE;
+ }
+
+ /* Create a new info struct for this versioned file, or fill in the
+ * existing one if this is the second text-base we've found for it. */
+ info = apr_hash_get(*text_bases_info, versioned_file_name,
+ APR_HASH_KEY_STRING);
+ if (info == NULL)
+ info = apr_pcalloc(result_pool, sizeof (*info));
+ file_info = (is_revert_base ? &info->revert_base : &info->normal_base);
+
+ file_info->sha1_checksum = svn_checksum_dup(sha1_checksum, result_pool);
+ file_info->md5_checksum = svn_checksum_dup(md5_checksum, result_pool);
+ apr_hash_set(*text_bases_info, versioned_file_name, APR_HASH_KEY_STRING,
+ info);
+ }
+ }
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_17));
- SVN_ERR(migrate_text_bases(wcroot_abspath, wcroot_abspath, sdb,
- scratch_pool));
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -1141,6 +1108,27 @@ bump_to_22(void *baton, svn_sqlite__db_t
return SVN_NO_ERROR;
}
+static svn_error_t *
+bump_to_23(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
+{
+ const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_HAS_WORKING_NODES));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (have_row)
+ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("The working copy at '%s' is format 22 with "
+ "WORKING nodes; use a format 22 client to "
+ "diff/revert before using this client"),
+ wcroot_abspath);
+
+ SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_23));
+ return SVN_NO_ERROR;
+}
+
struct upgrade_data_t {
svn_sqlite__db_t *sdb;
@@ -1180,6 +1168,8 @@ upgrade_to_wcng(void **dir_baton,
svn_node_kind_t logfile_on_disk;
apr_hash_t *entries;
svn_wc_entry_t *this_dir;
+ const char *old_wcroot_abspath, *dir_relpath;
+ apr_hash_t *text_bases_info;
/* Don't try to mess with the WC if there are old log files left. */
@@ -1201,18 +1191,21 @@ upgrade_to_wcng(void **dir_baton,
* The semantics and storage mechanisms between the two are vastly different,
* so it's going to be a bit painful. Here's a plan for the operation:
*
- * 1) The 'entries' file needs to be moved to the new format. We read it
- * using the old-format reader, and then use our compatibility code
- * for writing entries to fill out the (new) wc_db state.
+ * 1) Read the old 'entries' using the old-format reader.
+ *
+ * 2) Create the new DB if it hasn't already been created.
*
- * 2) Convert wcprop to the wc-ng format
+ * 3) Use our compatibility code for writing entries to fill out the (new)
+ * DB state. Use the remembered checksums, since an entry has only the
+ * MD5 not the SHA1 checksum, and in the case of a revert-base doesn't
+ * even have that.
*
- * 3) Trash old, unused files and subdirs
+ * 4) Convert wcprop to the wc-ng format
*
- * ### (fill in other bits as they are implemented)
+ * 5) Migrate regular properties to the WC-NG DB.
*/
- /***** ENTRIES *****/
+ /***** ENTRIES - READ *****/
SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath,
scratch_pool, scratch_pool));
@@ -1233,6 +1226,7 @@ upgrade_to_wcng(void **dir_baton,
apr_pstrdup(hash_pool, this_dir->uuid));
}
+ /* Create the new DB if it hasn't already been created. */
if (!data->sdb)
{
const char *root_adm_abspath;
@@ -1266,24 +1260,28 @@ upgrade_to_wcng(void **dir_baton,
SVN_ERR(svn_wc__db_wclock_obtain(db, data->root_abspath, 0, FALSE,
scratch_pool));
}
-
+
+ old_wcroot_abspath = svn_dirent_get_longest_ancestor(dir_abspath,
+ data->root_abspath,
+ scratch_pool);
+ dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath, dir_abspath);
+
+ /***** TEXT BASES *****/
+ SVN_ERR(migrate_text_bases(&text_bases_info, dir_abspath, data->root_abspath,
+ data->sdb, scratch_pool, scratch_pool));
+
+ /***** ENTRIES - WRITE *****/
SVN_ERR(svn_wc__write_upgraded_entries(dir_baton, parent_baton, db, data->sdb,
data->repos_id, data->wc_id,
dir_abspath, data->root_abspath,
- entries,
+ entries, text_bases_info,
result_pool, scratch_pool));
/***** WC PROPS *****/
-
- /* Ugh. We don't know precisely where the wcprops are. Ignore them. */
+ /* If we don't know precisely where the wcprops are, ignore them. */
if (old_format != SVN_WC__WCPROPS_LOST)
{
apr_hash_t *all_wcprops;
- const char *old_wcroot_abspath
- = svn_dirent_get_longest_ancestor(dir_abspath, data->root_abspath,
- scratch_pool);
- const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath,
- dir_abspath);
if (old_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)
SVN_ERR(read_many_wcprops(&all_wcprops, dir_abspath,
@@ -1296,9 +1294,6 @@ upgrade_to_wcng(void **dir_baton,
all_wcprops, scratch_pool));
}
- SVN_ERR(migrate_text_bases(dir_abspath, data->root_abspath, data->sdb,
- scratch_pool));
-
/* Upgrade all the properties (including "this dir").
Note: this must come AFTER the entries have been migrated into the
@@ -1314,6 +1309,25 @@ upgrade_to_wcng(void **dir_baton,
}
+/* Return a string indicating the released version (or versions) of
+ * Subversion that used WC format number WC_FORMAT, or some other
+ * suitable string if no released version used WC_FORMAT.
+ *
+ * ### It's not ideal to encode this sort of knowledge in this low-level
+ * library. On the other hand, it doesn't need to be updated often and
+ * should be easily found when it does need to be updated. */
+static const char *
+version_string_from_format(int wc_format)
+{
+ switch (wc_format)
+ {
+ case 4: return "<=1.3";
+ case 8: return "1.4";
+ case 9: return "1.5";
+ case 10: return "1.6";
+ }
+ return _("(unreleased development version)");
+}
svn_error_t *
svn_wc__upgrade_sdb(int *result_format,
@@ -1326,8 +1340,21 @@ svn_wc__upgrade_sdb(int *result_format,
if (start_format < SVN_WC__WC_NG_VERSION /* 12 */)
return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL,
- _("Working copy format of '%s' is too old (%d); "
- "please run 'svn upgrade'"),
+ _("Working copy '%s' is too old (format %d, "
+ "created by Subversion %s)"),
+ svn_dirent_local_style(wcroot_abspath,
+ scratch_pool),
+ start_format,
+ version_string_from_format(start_format));
+
+ /* Early WCNG formats no longer supported. */
+ if (start_format < 19)
+ return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL,
+ _("Working copy '%s' is an old development "
+ "version (format %d); to upgrade it, "
+ "use a format 18 client, then "
+ "use 'tools/dev/wc-ng/bump-to-19.py', then "
+ "use the current client"),
svn_dirent_local_style(wcroot_abspath,
scratch_pool),
start_format);
@@ -1339,86 +1366,6 @@ svn_wc__upgrade_sdb(int *result_format,
intentional. */
switch (start_format)
{
- case 12:
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_13, &bb,
- scratch_pool));
- /* If the transaction succeeded, then we don't need the wcprops
- files. We stopped writing them partway through format 12, but
- we may be upgrading from an "early 12" and need to toss those
- files. We aren't going to migrate them because it is *also*
- possible that current/real data is sitting within the database.
- This is why STMT_UPGRADE_TO_13 just clears the 'dav_cache'
- column -- we cannot definitely state that the column values
- are Proper.
-
- They're removed by wipe_obsolete_files(), below. */
-
- *result_format = 13;
- /* FALLTHROUGH */
-
- case 13:
- /* Build WCLOCKS and migrate any physical lock. */
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_14, &bb,
- scratch_pool));
- /* If the transaction succeeded, then any lock has been migrated,
- and we can toss the physical file (below). */
-
- *result_format = 14;
- /* FALLTHROUGH */
-
- case 14:
- /* Revamp the recording of 'excluded' nodes. */
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_15, &bb,
- scratch_pool));
- *result_format = 15;
- /* FALLTHROUGH */
-
- case 15:
- /* Perform some minor changes to the schema. */
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_16, &bb,
- scratch_pool));
- *result_format = 16;
- /* FALLTHROUGH */
-
- case 16:
- {
- const char *pristine_dir;
-
- /* Create the '.svn/pristine' directory. */
- pristine_dir = svn_wc__adm_child(wcroot_abspath,
- SVN_WC__ADM_PRISTINE,
- scratch_pool);
- SVN_ERR(svn_wc__ensure_directory(pristine_dir, scratch_pool));
-
- /* Move text bases into the pristine directory, and update the db */
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_17, &bb,
- scratch_pool));
- }
-
- *result_format = 17;
- /* FALLTHROUGH */
-
- case 17:
- {
- struct bump_to_18_baton b18;
-
- b18.wcroot_abspath = wcroot_abspath;
- b18.original_format = start_format;
-
- /* Move the properties into the database. */
- SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_18, &b18,
- scratch_pool));
- }
-
- *result_format = 18;
- /* FALLTHROUGH */
-
- case 18:
- return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("The working copy '%s' is at format 18; "
- "use 'tools/dev/wc-ng/bump-to-19.py' to "
- "upgrade it"), wcroot_abspath);
-
case 19:
SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_20, &bb,
scratch_pool));
@@ -1437,6 +1384,12 @@ svn_wc__upgrade_sdb(int *result_format,
*result_format = 22;
/* FALLTHROUGH */
+ case 22:
+ SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_23, &bb,
+ scratch_pool));
+ *result_format = 23;
+ /* FALLTHROUGH */
+
/* ### future bumps go here. */
#if 0
case XXX-1:
Modified: subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql?rev=1053735&r1=1053734&r2=1053735&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-metadata.sql Wed Dec 29 21:12:33 2010
@@ -167,9 +167,9 @@ CREATE TABLE ACTUAL_NODE (
conflicts? Why do we need these in a column to refer to the
pristine store? Can't we just parse the checksums from
conflict_data as well? */
- older_checksum TEXT,
- left_checksum TEXT,
- right_checksum TEXT,
+ older_checksum TEXT REFERENCES PRISTINE (checksum),
+ left_checksum TEXT REFERENCES PRISTINE (checksum),
+ right_checksum TEXT REFERENCES PRISTINE (checksum),
PRIMARY KEY (wc_id, local_relpath)
);
@@ -327,8 +327,6 @@ CREATE TABLE NODES (
/* The tree state of the node.
- ### This applies to SVN_WC__OP_DEPTH, the intended final code!
-
In case 'op_depth' is equal to 0, this node is part of the 'BASE'
tree. The 'BASE' represents pristine nodes that are in the
repository; it is obtained and modified by commands such as
@@ -417,7 +415,7 @@ CREATE TABLE NODES (
/* The SHA-1 checksum of the pristine text, if this node is a file and was
moved here or copied here, else NULL. */
- checksum TEXT,
+ checksum TEXT REFERENCES PRISTINE (checksum),
/* for kind==symlink, this specifies the target. */
symlink_target TEXT,
@@ -483,126 +481,6 @@ CREATE INDEX I_NODES_PARENT ON NODES (wc
-/* ------------------------------------------------------------------------- */
-
-/* Format 13 introduces the work queue, and erases a few columns from the
- original schema. */
--- STMT_UPGRADE_TO_13
-
-CREATE TABLE WORK_QUEUE (
- /* Work items are identified by this value. */
- id INTEGER PRIMARY KEY AUTOINCREMENT,
-
- /* A serialized skel specifying the work item. */
- work BLOB NOT NULL
- );
-
-/* The contents of dav_cache are suspect in format 12, so it is best to just
- erase anything there. */
-UPDATE BASE_NODE SET incomplete_children=null, dav_cache=null;
-
-PRAGMA user_version = 13;
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 14 introduces a table for storing wc locks, and additional columns
- for storing conflict data in ACTUAL. */
--- STMT_UPGRADE_TO_14
-
-/* The existence of a row in this table implies a write lock. */
-CREATE TABLE WC_LOCK (
- /* specifies the location of this node in the local filesystem */
- wc_id INTEGER NOT NULL REFERENCES WCROOT (id),
- local_dir_relpath TEXT NOT NULL,
-
- PRIMARY KEY (wc_id, local_dir_relpath)
- );
-
-/* A skel containing the conflict details. */
-ALTER TABLE ACTUAL_NODE
-ADD COLUMN conflict_data BLOB;
-
-/* Three columns containing the checksums of older, left and right conflict
- texts. Stored in a column to allow storing them in the pristine store */
-ALTER TABLE ACTUAL_NODE
-ADD COLUMN older_checksum TEXT;
-
-ALTER TABLE ACTUAL_NODE
-ADD COLUMN left_checksum TEXT;
-
-ALTER TABLE ACTUAL_NODE
-ADD COLUMN right_checksum TEXT;
-
-PRAGMA user_version = 14;
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 15 introduces new handling for excluded nodes. */
--- STMT_UPGRADE_TO_15
-
-UPDATE base_node
-SET
- presence = 'excluded',
- checksum = NULL, translated_size = NULL, changed_rev = NULL,
- changed_date = NULL, changed_author = NULL, depth = NULL,
- symlink_target = NULL, last_mod_time = NULL, properties = NULL,
- incomplete_children = NULL, file_external = NULL
-WHERE depth = 'exclude';
-
-/* We don't support cropping working nodes, but we might see them
- via a copy from a sparse tree. Convert them anyway to make sure
- we never see depth exclude in our database */
-UPDATE working_node
-SET
- presence = 'excluded',
- checksum = NULL, translated_size = NULL, changed_rev = NULL,
- changed_date = NULL, changed_author = NULL, depth = NULL,
- symlink_target = NULL, copyfrom_repos_id = NULL, copyfrom_repos_path = NULL,
- copyfrom_revnum = NULL, moved_here = NULL, moved_to = NULL,
- last_mod_time = NULL, properties = NULL, keep_local = NULL
-WHERE depth = 'exclude';
-
-PRAGMA user_version = 15;
-
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 16 introduces some new columns for pristines and locks. */
--- STMT_UPGRADE_TO_16
-
-/* An md5 column for the pristine table. */
-ALTER TABLE PRISTINE
-ADD COLUMN md5_checksum TEXT;
-
-/* Add the locked_levels column to record the depth of a lock. */
-ALTER TABLE WC_LOCK
-ADD COLUMN locked_levels INTEGER NOT NULL DEFAULT -1;
-
-/* Default the depth of existing locks to 0. */
-UPDATE wc_lock
-SET locked_levels = 0;
-
-PRAGMA user_version = 16;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 17 involves no schema changes, it moves the pristine files
- from .svn/text-base to .svn/pristine */
-
--- STMT_UPGRADE_TO_17
-PRAGMA user_version = 17;
-
-/* ------------------------------------------------------------------------- */
-
-/* Format 18 involves no schema changes, it moves the property data from files
- into the database. */
-
--- STMT_UPGRADE_TO_18
-PRAGMA user_version = 18;
-
-
/* Format 20 introduces NODES and removes BASE_NODE and WORKING_NODE */
-- STMT_UPGRADE_TO_20
@@ -665,6 +543,15 @@ PRAGMA user_version = 22;
/* ------------------------------------------------------------------------- */
+/* Format 23 involves no schema changes, it introduces multi-layer
+ op-depth processing for NODES. */
+
+-- STMT_UPGRADE_TO_23
+PRAGMA user_version = 23;
+
+
+/* ------------------------------------------------------------------------- */
+
/* Format YYY introduces new handling for conflict information. */
-- format: YYY
@@ -723,8 +610,15 @@ FROM ACTUAL_NODE_BACKUP;
DROP TABLE ACTUAL_NODE_BACKUP;
-/* Note: One difference remains between the schemas of an upgraded and a
- * fresh WC. While format 22 was current, "NOT NULL" was added to the
+/* Note: Other differences between the schemas of an upgraded and a
+ * fresh WC.
+ *
+ * While format 22 was current, "NOT NULL" was added to the
* columns PRISTINE.size and PRISTINE.md5_checksum. The format was not
- * bumped because it is a forward- and backward-compatible change. */
+ * bumped because it is a forward- and backward-compatible change.
+ *
+ * While format 23 was current, "REFERENCES PRISTINE" was added to the
+ * columns ACTUAL_NODE.older_checksum, ACTUAL_NODE.left_checksum,
+ * ACTUAL_NODE.right_checksum, NODES.checksum.
+ */
Modified: subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql?rev=1053735&r1=1053734&r2=1053735&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc-queries.sql Wed Dec 29 21:12:33 2010
@@ -104,6 +104,15 @@ LEFT OUTER JOIN lock ON nodes.repos_id =
AND nodes.repos_path = lock.repos_relpath
WHERE wc_id = ?1 AND parent_relpath = ?2;
+-- STMT_SELECT_NODE_CHILDREN_WALKER_INFO
+/* ### See comment at STMT_SELECT_NODE_CHILDREN_INFO.
+ ### Should C code handle GROUP BY local_relpath ORDER BY op_depths DESC? */
+SELECT local_relpath, op_depth, presence, kind
+FROM nodes
+WHERE wc_id = ?1 AND parent_relpath = ?2
+GROUP BY local_relpath
+ORDER BY op_depth DESC;
+
-- STMT_SELECT_ACTUAL_CHILDREN_INFO
SELECT prop_reject, changelist, conflict_old, conflict_new,
conflict_working, tree_conflict_data, properties, local_relpath,
@@ -224,15 +233,11 @@ WHERE repos_id = ?1 AND
(repos_relpath = ?2 OR
repos_relpath LIKE ?3 ESCAPE '#');
--- STMT_UPDATE_BASE_NODE_FILEINFO
-UPDATE nodes SET translated_size = ?3, last_mod_time = ?4
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
-
--- STMT_UPDATE_WORKING_NODE_FILEINFO
+-- STMT_UPDATE_NODE_FILEINFO
UPDATE nodes SET translated_size = ?3, last_mod_time = ?4
WHERE wc_id = ?1 AND local_relpath = ?2
AND op_depth = (SELECT MAX(op_depth) FROM nodes
- WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0);
+ WHERE wc_id = ?1 AND local_relpath = ?2);
-- STMT_UPDATE_ACTUAL_TREE_CONFLICTS
UPDATE actual_node SET tree_conflict_data = ?3
@@ -320,11 +325,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2;
DELETE FROM actual_node
WHERE wc_id = ?1 AND local_relpath = ?2;
--- STMT_DELETE_ACTUAL_NODE_WITHOUT_CHANGELIST
-DELETE FROM actual_node
-WHERE wc_id = ?1 AND local_relpath = ?2
- AND changelist IS NULL;
-
-- STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT
DELETE FROM actual_node
WHERE wc_id = ?1 AND local_relpath = ?2
@@ -387,10 +387,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2
UPDATE nodes SET presence = ?3
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
--- STMT_UPDATE_NODE_BASE_PRESENCE_KIND
-UPDATE nodes SET presence = ?3, kind = ?4
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
-
-- STMT_UPDATE_NODE_WORKING_PRESENCE
UPDATE nodes SET presence = ?3
WHERE wc_id = ?1 AND local_relpath = ?2
@@ -598,75 +594,6 @@ SELECT 1 FROM nodes WHERE wc_id = ?1 AND
AND op_depth = (SELECT MAX(op_depth) FROM nodes
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0);
-
--- STMT_COPY_NODES_ROW
-INSERT OR REPLACE INTO nodes (
- wc_id, local_relpath, op_depth, parent_relpath,
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
- ?4 /*dst_relpath*/,
- ?6 /*dst_op_depth*/,
- ?5 /*dst_parent_*/,
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
-
--- STMT_COPY_NODES_AT_SAME_OP_DEPTH
-INSERT OR REPLACE INTO nodes (
- wc_id, local_relpath, op_depth, parent_relpath,
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
- ?4 /*dst_relpath*/ || SUBSTR(local_relpath, ?6 /*LEN(src_relpath)+1*/),
- ?5 /*dst_depth*/,
- ?4 /*dst_relpath*/ || SUBSTR(parent_relpath, ?6 /*LEN(src_relpath)+1*/),
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth = ?3;
-
--- STMT_COPY_NODES_AT_GREATER_OP_DEPTH
-INSERT OR REPLACE INTO nodes (
- wc_id, local_relpath, op_depth, parent_relpath,
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */ )
-SELECT wc_id,
- ?4 /*dst_relpath*/ || SUBSTR(local_relpath, ?6 /*LEN(src_relpath)+1*/),
- op_depth + ?5 /*dst_depth*/ - ?3 /*src_depth*/,
- ?4 /*dst_relpath*/ || SUBSTR(parent_relpath, ?6 /*LEN(src_relpath)+1*/),
- repos_id, repos_path, revision, presence, /* moved_here, moved_to, */
- kind, properties, depth, checksum, symlink_target,
- changed_revision, changed_date, changed_author,
- translated_size, last_mod_time /* dav_cache, file_external */
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath LIKE ?2 ESCAPE '#' AND op_depth > ?3;
-
--- STMT_COPY_ACTUAL_NODE_ROWS
-INSERT OR REPLACE INTO actual_node (
- wc_id, local_relpath, parent_relpath, properties,
- conflict_old, conflict_new, conflict_working,
- prop_reject, changelist, text_mod, tree_conflict_data )
-SELECT wc_id,
- ?4 /*dst_relpath*/ || SUBSTR(local_relpath, ?6 /*LEN(src_relpath)+1*/),
- ?5 /*dst_parent_*/ || SUBSTR(parent_relpath, ?7 /*LEN(src_parent_)+1*/),
- properties,
- conflict_old, conflict_new, conflict_working,
- prop_reject, changelist, text_mod, tree_conflict_data
-FROM actual_node
-WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#');
-
-- STMT_SELECT_ABSENT_NODES
SELECT local_relpath FROM nodes
WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#')
@@ -794,14 +721,22 @@ UPDATE actual_node SET tree_conflict_dat
SELECT DISTINCT local_relpath FROM nodes
WHERE kind = 'file' AND parent_relpath = ?1;
--- STMT_PLAN_PROP_UPGRADE
-SELECT 0, nodes_base.presence, nodes_base.wc_id FROM nodes nodes_base
-WHERE nodes_base.local_relpath = ?1 AND nodes_base.op_depth = 0
-UNION ALL
-SELECT 1, nodes_work.presence, nodes_work.wc_id FROM nodes nodes_work
-WHERE nodes_work.local_relpath = ?1
- AND nodes_work.op_depth = (SELECT MAX(op_depth) FROM nodes
- WHERE local_relpath = ?1 AND op_depth > 0);
+-- STMT_SELECT_NODE_UPGRADE
+SELECT op_depth, presence, wc_id
+FROM nodes
+WHERE local_relpath = ?1
+ORDER BY op_depth DESC;
+
+-- STMT_UPDATE_NODE_PROPS
+UPDATE nodes SET properties = ?4
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
+
+-- STMT_HAS_WORKING_NODES
+SELECT 1 FROM nodes WHERE op_depth > 0;
+
+-- STMT_UPDATE_CHECKSUM
+UPDATE nodes SET checksum = ?4
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
/* ------------------------------------------------------------------------- */
Modified: subversion/branches/performance/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc.h?rev=1053735&r1=1053734&r2=1053735&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc.h Wed Dec 29 21:12:33 2010
@@ -124,12 +124,22 @@ extern "C" {
* The change from 19 to 20 introduces NODES and drops BASE_NODE and
* WORKING_NODE, op_depth is always 0 or 2.
*
+ * The change from 20 to 21 moved tree conflict storage from the
+ * parent to the conflicted node.
+ *
+ * The change from 21 to 22 moved tree conflict storage from
+ * conflict_data column to the tree_conflict_data column.
+ *
+ * The change from 22 to 23 introduced multi-layer op_depth processing for
+ * NODES.
+ *
* == 1.7.x shipped with format ???
*
* Please document any further format changes here.
*/
-#define SVN_WC__VERSION 22
+#define SVN_WC__VERSION 23
+
/* Formats <= this have no concept of "revert text-base/props". */
#define SVN_WC__NO_REVERT_FILES 4
Modified: subversion/branches/performance/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_wc/wc_db.c?rev=1053735&r1=1053734&r2=1053735&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/performance/subversion/libsvn_wc/wc_db.c Wed Dec 29 21:12:33 2010
@@ -277,13 +277,6 @@ read_info(svn_wc__db_status_t *status,
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,
@@ -299,7 +292,6 @@ scan_addition(svn_wc__db_status_t *statu
static svn_error_t *
scan_deletion(const char **base_del_relpath,
- svn_boolean_t *base_replaced,
const char **moved_to_relpath,
const char **work_del_relpath,
svn_wc__db_pdh_t *pdh,
@@ -311,6 +303,14 @@ static svn_error_t *
convert_to_working_status(svn_wc__db_status_t *working_status,
svn_wc__db_status_t status);
+static svn_error_t *
+wclock_owns_lock(svn_boolean_t *own_lock,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ svn_boolean_t exact,
+ apr_pool_t *scratch_pool);
+
+
/* 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,
@@ -1252,73 +1252,6 @@ which_trees_exist(svn_boolean_t *base_ex
}
-/* Determine which trees' nodes exist for a given LOCAL_RELPATH in the
- specified SDB.
-
- Note: this is VERY similar to the above which_trees_exist() except that
- 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,
- svn_sqlite__db_t *sdb,
- const char *local_relpath)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
-
- *base_exists = FALSE;
- *working_exists = FALSE;
-
- 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
- the provided LOCAL_RELPATH. We shouldn't even be here without a
- query for available rows. */
- SVN_ERR_ASSERT(have_row);
-
- /* Use the first column to detect which table this row came from. */
- if (svn_sqlite__column_int(stmt, 0))
- {
- *working_exists = TRUE; /* value == 1 */
- *work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
- }
- else
- {
- *base_exists = TRUE; /* value == 0 */
- *base_presence = svn_sqlite__column_token(stmt, 1, presence_map);
- }
-
- /* Return the WC_ID that was assigned. */
- *wc_id = svn_sqlite__column_int64(stmt, 2);
-
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (have_row)
- {
- /* If both rows, then both tables. */
- *base_exists = TRUE;
- *working_exists = TRUE;
-
- /* If the second row came from WORKING_NODE, then we should also
- 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. */
- SVN_ERR_ASSERT(*wc_id == svn_sqlite__column_int64(stmt, 2));
- }
-
- return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
/* */
static svn_error_t *
create_db(svn_sqlite__db_t **sdb,
@@ -2942,7 +2875,7 @@ get_info_for_copy(apr_int64_t *copyfrom_
{
const char *base_del_relpath, *work_del_relpath;
- SVN_ERR(scan_deletion(&base_del_relpath, NULL, NULL, &work_del_relpath,
+ SVN_ERR(scan_deletion(&base_del_relpath, NULL, &work_del_relpath,
pdh, local_relpath, scratch_pool, scratch_pool));
if (work_del_relpath)
{
@@ -3128,11 +3061,6 @@ db_op_copy(svn_wc__db_pdh_t *src_pdh,
scratch_pool));
}
-#ifndef SVN_WC__OP_DEPTH
- /* ### Should do this earlier and insert the node with the right values. */
- SVN_ERR(elide_copyfrom(dst_pdh, dst_relpath, scratch_pool));
-#endif
-
SVN_ERR(add_work_items(dst_pdh->wcroot->sdb, work_items, scratch_pool));
return SVN_NO_ERROR;
@@ -3239,7 +3167,6 @@ op_depth_for_copy(apr_int64_t *op_depth,
const char *local_relpath,
apr_pool_t *scratch_pool)
{
-#ifdef SVN_WC__OP_DEPTH
const char *parent_relpath, *name;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -3295,9 +3222,6 @@ op_depth_for_copy(apr_int64_t *op_depth,
}
SVN_ERR(svn_sqlite__reset(stmt));
-#else
- *op_depth = 2; /* temporary op_depth */
-#endif
return SVN_NO_ERROR;
}
@@ -3548,11 +3472,7 @@ svn_wc__db_op_add_directory(svn_wc__db_t
iwb.kind = svn_wc__db_kind_dir;
iwb.wc_id = pdh->wcroot->wc_id;
iwb.local_relpath = local_relpath;
-#ifdef SVN_WC__OP_DEPTH
iwb.op_depth = relpath_depth(local_relpath);
-#else
- iwb.op_depth = 2; /* ### temporary op_depth */
-#endif
iwb.work_items = work_items;
@@ -3588,11 +3508,7 @@ svn_wc__db_op_add_file(svn_wc__db_t *db,
iwb.kind = svn_wc__db_kind_file;
iwb.wc_id = pdh->wcroot->wc_id;
iwb.local_relpath = local_relpath;
-#ifdef SVN_WC__OP_DEPTH
iwb.op_depth = relpath_depth(local_relpath);
-#else
- iwb.op_depth = 2; /* ### temporary op_depth */
-#endif
iwb.work_items = work_items;
@@ -3630,11 +3546,7 @@ svn_wc__db_op_add_symlink(svn_wc__db_t *
iwb.kind = svn_wc__db_kind_symlink;
iwb.wc_id = pdh->wcroot->wc_id;
iwb.local_relpath = local_relpath;
-#ifdef SVN_WC__OP_DEPTH
iwb.op_depth = relpath_depth(local_relpath);
-#else
- iwb.op_depth = 2; /* ### temporary op_depth */
-#endif
iwb.target = target;
@@ -4488,7 +4400,6 @@ db_working_update_presence(apr_int64_t o
{
/* Switching to base-deleted is undoing an add/copy. By this
stage an add will have no children. */
-#ifdef SVN_WC__OP_DEPTH
const apr_array_header_t *children;
apr_pool_t *iterpool;
int i;
@@ -4527,14 +4438,6 @@ db_working_update_presence(apr_int64_t o
SVN_ERR(db_working_actual_remove(pdh, child_relpath, iterpool));
}
svn_pool_destroy(iterpool);
-#else
- /* If this was a copy then any children of the copy will now be
- not-present and should be removed. */
- SVN_ERR(remove_children(pdh, local_relpath,
- svn_wc__db_status_not_present,
- 2 /* ### temporary op_depth */,
- scratch_pool));
-#endif
/* Reset the copyfrom in case this was a copy.
### What else should be reset? Properties? Or copy the node again? */
@@ -4590,10 +4493,6 @@ db_working_actual_remove(svn_wc__db_pdh_
SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
SVN_ERR(svn_sqlite__step_done(stmt));
-#ifndef SVN_WC__OP_DEPTH
- SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_not_present,
- 2 /* ### temporary op_depth */, scratch_pool));
-#else
SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_base_deleted,
op_depth + 1, scratch_pool));
SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_normal,
@@ -4602,7 +4501,6 @@ db_working_actual_remove(svn_wc__db_pdh_
op_depth, scratch_pool));
SVN_ERR(remove_children(pdh, local_relpath, svn_wc__db_status_incomplete,
op_depth, scratch_pool));
-#endif
/* Postcondition: There are no NODES rows in this subtree, at same or
* greater op_depth. */
@@ -4646,25 +4544,15 @@ db_working_insert(svn_wc__db_status_t st
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
-#ifdef SVN_WC__OP_DEPTH
const char *like_arg = construct_like_arg(local_relpath, scratch_pool);
apr_int64_t op_depth = relpath_depth(local_relpath);
-#else
- apr_int64_t op_depth = 2; /* ### temporary op_depth */
-#endif
-#ifdef SVN_WC__OP_DEPTH
SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
STMT_INSERT_WORKING_NODE_FROM_NODE));
-#else
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_INSERT_WORKING_NODE_FROM_BASE));
-#endif
SVN_ERR(svn_sqlite__bindf(stmt, "isit", pdh->wcroot->wc_id,
local_relpath, op_depth, presence_map, status));
SVN_ERR(svn_sqlite__insert(NULL, stmt));
-#ifdef SVN_WC__OP_DEPTH
/* Need to update the op_depth of all deleted child trees -- this
relies on the recursion having already deleted the trees so
that they are all at op_depth+1.
@@ -4679,7 +4567,6 @@ db_working_insert(svn_wc__db_status_t st
SVN_ERR(svn_sqlite__bindf(stmt, "isi",
pdh->wcroot->wc_id, like_arg, op_depth));
SVN_ERR(svn_sqlite__update(NULL, stmt));
-#endif
return SVN_NO_ERROR;
}
@@ -4868,9 +4755,6 @@ temp_op_delete_txn(void *baton, svn_sqli
struct temp_op_delete_baton *b = baton;
svn_wc__db_status_t status, new_working_status;
svn_boolean_t have_work, add_work = FALSE, del_work = FALSE, mod_work = FALSE;
-#ifndef SVN_WC__OP_DEPTH
- svn_boolean_t new_have_work;
-#endif
SVN_ERR(read_info(&status,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -4880,23 +4764,13 @@ temp_op_delete_txn(void *baton, svn_sqli
b->pdh, b->local_relpath,
scratch_pool, scratch_pool));
-#ifndef SVN_WC__OP_DEPTH
- new_have_work = have_work;
- new_working_status = status;
-#endif
-
if (!have_work)
{
/* No structural changes */
if (status == svn_wc__db_status_normal
|| status == svn_wc__db_status_incomplete)
{
-#ifdef SVN_WC__OP_DEPTH
add_work = TRUE;
-#else
- new_have_work = TRUE;
- new_working_status = svn_wc__db_status_base_deleted;
-#endif
}
}
else if (status == svn_wc__db_status_added)
@@ -4914,26 +4788,15 @@ temp_op_delete_txn(void *baton, svn_sqli
SVN_ERR(info_below_working(&below_base, &below_work, &below_status,
b->pdh, b->local_relpath, scratch_pool));
-#ifdef SVN_WC__OP_DEPTH
if ((below_base || below_work)
&& below_status != svn_wc__db_status_not_present)
mod_work = TRUE;
else
del_work = TRUE;
-#else
- if (below_base && below_status != svn_wc__db_status_not_present)
- new_working_status = svn_wc__db_status_base_deleted;
- else
- new_have_work = FALSE;
-#endif
}
else
{
-#ifdef SVN_WC__OP_DEPTH
add_work = TRUE;
-#else
- new_working_status = svn_wc__db_status_not_present;
-#endif
}
}
else if (status == svn_wc__db_status_incomplete)
@@ -4941,23 +4804,12 @@ temp_op_delete_txn(void *baton, svn_sqli
svn_boolean_t add_or_root_of_copy;
SVN_ERR(is_add_or_root_of_copy(&add_or_root_of_copy,
b->pdh, b->local_relpath, scratch_pool));
-#ifdef SVN_WC__OP_DEPTH
if (add_or_root_of_copy)
del_work = TRUE;
else
add_work = TRUE;
-#else
- if (add_or_root_of_copy)
- new_have_work = FALSE;
-#endif
}
-#ifndef SVN_WC__OP_DEPTH
- del_work = !new_have_work && have_work;
- add_work = new_have_work && !have_work;
- mod_work = new_have_work && have_work && new_working_status != status;
-#endif
-
if (del_work)
{
SVN_ERR(db_working_actual_remove(b->pdh, b->local_relpath, scratch_pool));
@@ -4968,17 +4820,13 @@ temp_op_delete_txn(void *baton, svn_sqli
}
else if (add_work)
{
-#ifdef SVN_WC__OP_DEPTH
new_working_status = svn_wc__db_status_base_deleted;
-#endif
SVN_ERR(db_working_insert(new_working_status, b->pdh, b->local_relpath,
scratch_pool));
}
else if (mod_work)
{
-#ifdef SVN_WC__OP_DEPTH
new_working_status = svn_wc__db_status_base_deleted;
-#endif
SVN_ERR(db_working_update_presence(relpath_depth(b->local_relpath),
new_working_status, b->pdh,
b->local_relpath, scratch_pool));
@@ -5254,8 +5102,7 @@ read_info(svn_wc__db_status_t *status,
op_depth = svn_sqlite__column_int64(stmt_info, 0);
}
- if (have_base)
- *have_base = (op_depth == 0);
+ *have_base = (op_depth == 0);
}
}
else if (have_act)
@@ -5606,6 +5453,61 @@ svn_wc__db_read_children_info(apr_hash_t
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_read_children_walker_info(apr_hash_t **nodes,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_pdh_t *pdh;
+ const char *dir_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ apr_int64_t op_depth;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
+
+ SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &dir_relpath, db,
+ dir_abspath,
+ svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
+ STMT_SELECT_NODE_CHILDREN_WALKER_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, dir_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ *nodes = apr_hash_make(result_pool);
+ while (have_row)
+ {
+ struct svn_wc__db_walker_info_t *child;
+ const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ const char *name = svn_relpath_basename(child_relpath, NULL);
+ svn_error_t *err;
+
+ child = apr_hash_get(*nodes, name, APR_HASH_KEY_STRING);
+ if (child == NULL)
+ child = apr_palloc(result_pool, sizeof(*child));
+
+ op_depth = svn_sqlite__column_int(stmt, 1);
+ child->status = svn_sqlite__column_token(stmt, 2, presence_map);
+ if (op_depth > 0)
+ SVN_ERR(convert_to_working_status(&child->status, child->status));
+ child->kind = svn_sqlite__column_token(stmt, 3, kind_map);
+ apr_hash_set(*nodes, apr_pstrdup(result_pool, name),
+ APR_HASH_KEY_STRING, child);
+
+ err = svn_sqlite__step(&have_row, stmt);
+ if (err)
+ SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__db_read_prop(const svn_string_t **propval,
@@ -5917,7 +5819,7 @@ svn_wc__db_global_relocate(svn_wc__db_t
if (status == svn_wc__db_status_deleted)
{
const char *work_del_relpath;
- SVN_ERR(scan_deletion(NULL, NULL, NULL, &work_del_relpath,
+ SVN_ERR(scan_deletion(NULL, NULL, &work_del_relpath,
pdh, local_dir_relpath,
scratch_pool, scratch_pool));
if (work_del_relpath)
@@ -6404,35 +6306,15 @@ struct record_baton {
};
-/* Record TRANSLATED_SIZE and LAST_MOD_TIME into the WORKING tree if a
- node is present; otherwise, record it into the BASE tree. One of them
- must exist. */
+/* Record TRANSLATED_SIZE and LAST_MOD_TIME into top layer in NODES */
static svn_error_t *
record_fileinfo(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
{
struct record_baton *rb = baton;
- svn_boolean_t base_exists;
- svn_boolean_t working_exists;
svn_sqlite__stmt_t *stmt;
int affected_rows;
- SVN_ERR(which_trees_exist(&base_exists, &working_exists,
- sdb, rb->wcroot->wc_id, rb->local_relpath));
- if (!base_exists && !working_exists)
- return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
- _("Could not find node '%s' for recording file "
- "information."),
- path_for_error_message(rb->wcroot,
- rb->local_relpath,
- scratch_pool));
-
- /* ### Instead of doing it this way, we just ought to update the highest
- op_depth level. That way, there's no need to find out which
- tree to update first */
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- working_exists
- ? STMT_UPDATE_WORKING_NODE_FILEINFO
- : STMT_UPDATE_BASE_NODE_FILEINFO));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_NODE_FILEINFO));
SVN_ERR(svn_sqlite__bindf(stmt, "isii",
rb->wcroot->wc_id, rb->local_relpath,
rb->translated_size, rb->last_mod_time));
@@ -6611,10 +6493,6 @@ scan_addition(svn_wc__db_status_t *statu
const char *current_relpath = local_relpath;
const char *build_relpath = "";
svn_wc__db_wcroot_t *wcroot = pdh->wcroot;
-#ifndef SVN_WC__OP_DEPTH
- svn_boolean_t found_info = FALSE;
- const char *child_relpath = NULL;
-#endif
/* Initialize most of the OUT parameters. Generally, we'll only be filling
in a subset of these, so it is easier to init all up front. Note that
@@ -6629,125 +6507,6 @@ scan_addition(svn_wc__db_status_t *statu
if (original_revision)
*original_revision = SVN_INVALID_REVNUM;
-
-#ifndef SVN_WC__OP_DEPTH
- while (TRUE)
- {
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- svn_wc__db_status_t presence;
-
- /* ### is it faster to fetch fewer columns? */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, current_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
- if (!have_row)
- {
- /* Reset statement before (optionally) returning */
- SVN_ERR(svn_sqlite__reset(stmt));
-
- if (current_relpath == local_relpath)
- /* ### maybe we should return a usage error instead? */
- return 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));
-
- /* We just fell off the top of the WORKING tree. If we haven't
- found the operation root, then the child node that we just
- left was that root. */
- if (op_root_relpath && *op_root_relpath == NULL)
- {
- SVN_ERR_ASSERT(child_relpath != NULL);
- *op_root_relpath = apr_pstrdup(result_pool, child_relpath);
- }
-
- /* This node was added/copied/moved and has an implicit location
- in the repository. We now need to traverse BASE nodes looking
- for repository info. */
- break;
- }
-
- presence = svn_sqlite__column_token(stmt, 1, presence_map);
-
- /* Record information from the starting node. */
- if (current_relpath == local_relpath)
- {
- /* The starting node should exist normally. */
- if (presence != svn_wc__db_status_normal)
- return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
- svn_sqlite__reset(stmt),
- _("Expected node '%s' to be added."),
- path_for_error_message(wcroot,
- local_relpath,
- scratch_pool));
-
- /* Provide the default status; we'll override as appropriate. */
- if (status)
- *status = svn_wc__db_status_added;
- }
-
- /* We want the operation closest to the start node, and then we
- ignore any operations on its ancestors. */
- if (!found_info
- && presence == svn_wc__db_status_normal
- && !svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
- {
- if (status)
- {
- if (svn_sqlite__column_boolean(stmt, 13 /* moved_here */))
- *status = svn_wc__db_status_moved_here;
- else
- *status = svn_wc__db_status_copied;
- }
- if (op_root_relpath)
- *op_root_relpath = apr_pstrdup(result_pool, current_relpath);
- if (original_repos_relpath)
- *original_repos_relpath = svn_sqlite__column_text(stmt, 11,
- result_pool);
- if (original_repos_id)
- *original_repos_id = svn_sqlite__column_int64(stmt, 10);
- if (original_revision)
- *original_revision = svn_sqlite__column_revnum(stmt, 12);
-
- /* We may have to keep tracking upwards for REPOS_* values.
- If they're not needed, then just return. */
- if (repos_relpath == NULL
- && repos_id == NULL)
- return svn_error_return(svn_sqlite__reset(stmt));
-
- /* We've found the info we needed. Scan for the top of the
- WORKING tree, and then the REPOS_* information. */
- found_info = TRUE;
- }
-
- SVN_ERR(svn_sqlite__reset(stmt));
-
- /* If the caller wants to know the starting node's REPOS_RELPATH,
- then keep track of what we're stripping off the ABSPATH as we
- traverse up the tree. */
- if (repos_relpath)
- {
- build_relpath = svn_relpath_join(svn_dirent_basename(current_relpath,
- NULL),
- build_relpath,
- scratch_pool);
- }
-
- /* Move to the parent node. Remember the abspath to this node, since
- it could be the root of an add/delete. */
- child_relpath = current_relpath;
-
- /* The wcroot can't have a restructuring operation; make sure we don't
- loop on invalid data */
- SVN_ERR_ASSERT(current_relpath[0] != '\0');
-
- current_relpath = svn_relpath_dirname(current_relpath, scratch_pool);
- }
-#else /* ifdef SVN_WC__OP_DEPTH */
{
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
@@ -6911,7 +6670,7 @@ scan_addition(svn_wc__db_status_t *statu
build_relpath = repos_prefix_path;
}
-#endif
+
/* If we're here, then we have an added/copied/moved (start) node, and
CURRENT_ABSPATH now points to a BASE node. Figure out the repository
information for the current node, and use that to compute the start
@@ -7019,7 +6778,6 @@ svn_wc__db_scan_addition(svn_wc__db_stat
* DB+LOCAL_ABSPATH, and outputting relpaths instead of abspaths. */
static svn_error_t *
scan_deletion(const char **base_del_relpath,
- svn_boolean_t *base_replaced,
const char **moved_to_relpath,
const char **work_del_relpath,
svn_wc__db_pdh_t *pdh,
@@ -7033,15 +6791,11 @@ scan_deletion(const char **base_del_relp
svn_boolean_t child_has_base = FALSE;
svn_boolean_t found_moved_to = FALSE;
svn_wc__db_wcroot_t *wcroot = pdh->wcroot;
-#ifdef SVN_WC__OP_DEPTH
apr_int64_t local_op_depth, op_depth;
-#endif
/* Initialize all the OUT parameters. */
if (base_del_relpath != NULL)
*base_del_relpath = NULL;
- if (base_replaced != NULL)
- *base_replaced = FALSE; /* becomes TRUE when we know for sure. */
if (moved_to_relpath != NULL)
*moved_to_relpath = NULL;
if (work_del_relpath != NULL)
@@ -7164,16 +6918,6 @@ scan_deletion(const char **base_del_relp
/* If a BASE node is marked as not-present, then we'll ignore
it within this function. That status is simply a bookkeeping
gimmick, not a real node that may have been deleted. */
-
- /* If we're looking at a present BASE node, *and* there is a
- WORKING node (present or deleted), then a replacement has
- occurred here or in an ancestor. */
- if (base_replaced != NULL
- && base_presence == svn_wc__db_status_normal
- && work_presence != svn_wc__db_status_base_deleted)
- {
- *base_replaced = TRUE;
- }
}
/* Only grab the nearest ancestor. */
@@ -7195,7 +6939,6 @@ scan_deletion(const char **base_del_relp
svn_sqlite__column_text(stmt, 2, NULL));
}
-#ifdef SVN_WC__OP_DEPTH
op_depth = svn_sqlite__column_int64(stmt, 3);
if (current_relpath == local_relpath)
local_op_depth = op_depth;
@@ -7203,13 +6946,6 @@ scan_deletion(const char **base_del_relp
if (work_del_relpath && !work_del_relpath[0]
&& ((op_depth < local_op_depth && op_depth > 0)
|| child_presence == svn_wc__db_status_not_present))
-#else
- if (work_del_relpath != NULL
- && work_presence == svn_wc__db_status_normal
- && child_presence == svn_wc__db_status_not_present)
- /* Parent is normal, but child was deleted. Therefore, the child
- is the root of a WORKING subtree deletion. */
-#endif
{
*work_del_relpath = apr_pstrdup(result_pool, child_relpath);
}
@@ -7236,7 +6972,6 @@ scan_deletion(const char **base_del_relp
svn_error_t *
svn_wc__db_scan_deletion(const char **base_del_abspath,
- svn_boolean_t *base_replaced,
const char **moved_to_abspath,
const char **work_del_abspath,
svn_wc__db_t *db,
@@ -7255,7 +6990,7 @@ svn_wc__db_scan_deletion(const char **ba
scratch_pool, scratch_pool));
VERIFY_USABLE_PDH(pdh);
- SVN_ERR(scan_deletion(&base_del_relpath, base_replaced, &moved_to_relpath,
+ SVN_ERR(scan_deletion(&base_del_relpath, &moved_to_relpath,
&work_del_relpath,
pdh, local_relpath, result_pool, scratch_pool));
@@ -7355,12 +7090,10 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
int original_format,
apr_pool_t *scratch_pool)
{
- svn_boolean_t have_base;
- svn_wc__db_status_t base_presence;
- svn_boolean_t have_work;
- svn_wc__db_status_t work_presence;
- apr_int64_t wc_id;
svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ apr_int64_t wc_id, top_op_depth = -1, below_op_depth = -1;
+ svn_wc__db_status_t top_presence, below_presence;
int affected_rows;
/* ### working_props: use set_props_txn.
@@ -7390,19 +7123,31 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
the handling of our inputs, relative to the state of this node.
*/
- /* Collect information about this node. */
- SVN_ERR(prop_upgrade_trees(&have_base, &base_presence,
- &have_work, &work_presence,
- &wc_id, sdb, local_relpath));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_UPGRADE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "s", local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ {
+ top_op_depth = svn_sqlite__column_int64(stmt, 0);
+ top_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+ wc_id = svn_sqlite__column_int64(stmt, 2);
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ {
+ below_op_depth = svn_sqlite__column_int64(stmt, 0);
+ below_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+ }
+ }
+ SVN_ERR(svn_sqlite__reset(stmt));
/* Detect the buggy scenario described above. We cannot upgrade this
working copy if we have no idea where BASE_PROPS should go. */
if (original_format > SVN_WC__NO_REVERT_FILES
&& revert_props == NULL
- && have_work
- && work_presence == svn_wc__db_status_normal
- && have_base
- && base_presence != svn_wc__db_status_not_present)
+ && top_op_depth != -1
+ && top_presence == svn_wc__db_status_normal
+ && below_op_depth != -1
+ && below_presence != svn_wc__db_status_not_present)
{
/* There should be REVERT_PROPS, so it appears that we just ran into
the described bug. Sigh. */
@@ -7415,48 +7160,45 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
scratch_pool), scratch_pool));
}
- if (have_base
- && (base_presence == svn_wc__db_status_normal
- || base_presence == svn_wc__db_status_incomplete))
- {
- apr_hash_t *props = revert_props ? revert_props : base_props;
+ /* Need at least one row, or two rows if there are revert props */
+ if (top_op_depth == -1
+ || (below_op_depth == -1 && revert_props))
+ return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+ _("Insufficient NODES rows for '%s'"),
+ svn_dirent_local_style(
+ svn_dirent_join(dir_abspath, local_relpath,
+ scratch_pool), scratch_pool));
+
+ /* one row, base props only: upper row gets base props
+ two rows, base props only: lower row gets base props
+ two rows, revert props only: lower row gets revert props
+ two rows, base and revert props: upper row gets base, lower gets revert */
+
+ if (revert_props || below_op_depth == -1)
+ {
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_NODE_BASE_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
+ STMT_UPDATE_NODE_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isi",
+ wc_id, local_relpath, top_op_depth));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool));
SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
- /* ### should we provide a nicer error message? */
SVN_ERR_ASSERT(affected_rows == 1);
}
- if (have_work)
+ if (below_op_depth != -1)
{
- /* WORKING_NODE has very limited 'presence' values. */
- SVN_ERR_ASSERT(work_presence == svn_wc__db_status_normal
- || work_presence == svn_wc__db_status_not_present
- || work_presence == svn_wc__db_status_base_deleted
- || work_presence == svn_wc__db_status_incomplete);
+ apr_hash_t *props = revert_props ? revert_props : base_props;
- /* Do we have a replaced node? It has properties: an empty set for
- adds, and a non-empty set for copies/moves. */
- if (original_format > SVN_WC__NO_REVERT_FILES
- && (work_presence == svn_wc__db_status_normal
- || work_presence == svn_wc__db_status_incomplete))
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_NODE_WORKING_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
- SVN_ERR(svn_sqlite__bind_properties(stmt, 3, base_props,
- scratch_pool));
- SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_UPDATE_NODE_PROPS));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isi",
+ wc_id, local_relpath, below_op_depth));
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool));
+ SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
- /* ### should we provide a nicer error message? */
- SVN_ERR_ASSERT(affected_rows == 1);
- }
- /* else other states should have no properties. */
- /* ### should we insert empty props for <= SVN_WC__NO_REVERT_FILES? */
+ SVN_ERR_ASSERT(affected_rows == 1);
}
/* If there are WORKING_PROPS, then they always go into ACTUAL_NODE. */
@@ -8210,7 +7952,6 @@ svn_wc__db_temp_wcroot_tempdir(const cha
/* Baton for wclock_obtain_cb() */
struct wclock_obtain_baton
{
- svn_wc__db_t *db;
svn_wc__db_pdh_t *pdh;
const char *local_relpath;
int levels_to_lock;
@@ -8284,7 +8025,6 @@ wclock_obtain_cb(void *baton,
while (got_row)
{
- const char *lock_abspath;
svn_boolean_t own_lock;
lock_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
@@ -8298,13 +8038,10 @@ wclock_obtain_cb(void *baton,
continue;
}
- lock_abspath = svn_dirent_join(wcroot->abspath,
- lock_relpath, scratch_pool);
-
/* Check if we are the lock owner, because we should be able to
extend our lock. */
- err = svn_wc__db_wclock_owns_lock(&own_lock, bt->db, lock_abspath,
- TRUE, scratch_pool);
+ err = wclock_owns_lock(&own_lock, bt->pdh, lock_relpath,
+ TRUE, scratch_pool);
if (err)
SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
@@ -8314,7 +8051,7 @@ wclock_obtain_cb(void *baton,
SVN_ERR(svn_sqlite__reset(stmt));
err = svn_error_createf(SVN_ERR_WC_LOCKED, NULL,
_("'%s' is already locked."),
- svn_dirent_local_style(lock_abspath,
+ path_for_error_message(wcroot, lock_relpath,
scratch_pool));
return svn_error_createf(SVN_ERR_WC_LOCKED, err,
_("Working copy '%s' locked."),
@@ -8441,22 +8178,16 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *d
|| (lock->levels + relpath_depth(lock->local_relpath))
>= depth))
{
- const char *lock_abspath
- = svn_dirent_join(baton.pdh->wcroot->abspath,
- lock->local_relpath,
- scratch_pool);
-
- return svn_error_createf(SVN_ERR_WC_LOCKED, NULL,
- _("'%s' is already locked via '%s'."),
- svn_dirent_local_style(local_abspath,
- scratch_pool),
- svn_dirent_local_style(lock_abspath,
- scratch_pool));
+ return svn_error_createf(
+ SVN_ERR_WC_LOCKED, NULL,
+ _("'%s' is already locked via '%s'."),
+ svn_dirent_local_style(local_abspath, scratch_pool),
+ path_for_error_message(baton.pdh->wcroot, lock->local_relpath,
+ scratch_pool));
}
}
}
- baton.db = db;
baton.steal_lock = steal_lock;
baton.levels_to_lock = levels_to_lock;
@@ -8585,29 +8316,18 @@ svn_wc__db_wclock_release(svn_wc__db_t *
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_wc__db_wclock_owns_lock(svn_boolean_t *own_lock,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_boolean_t exact,
- apr_pool_t *scratch_pool)
+/* Like svn_wc__db_wclock_owns_lock() but taking PDH+LOCAL_RELPATH instead
+ * of DB+LOCAL_ABSPATH. */
+static svn_error_t *
+wclock_owns_lock(svn_boolean_t *own_lock,
+ svn_wc__db_pdh_t *pdh,
+ const char *local_relpath,
+ svn_boolean_t exact,
+ apr_pool_t *scratch_pool)
{
- svn_wc__db_pdh_t *pdh;
- const char *local_relpath;
apr_array_header_t *owned_locks;
int lock_level, i;
- SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &local_relpath, db,
- local_abspath, svn_sqlite__mode_readwrite,
- scratch_pool, scratch_pool));
-
- if (!pdh->wcroot)
- return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
- _("The node '%s' was not found."),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
-
- VERIFY_USABLE_PDH(pdh);
*own_lock = FALSE;
owned_locks = pdh->wcroot->owned_locks;
lock_level = relpath_depth(local_relpath);
@@ -8644,6 +8364,33 @@ svn_wc__db_wclock_owns_lock(svn_boolean_
}
svn_error_t *
+svn_wc__db_wclock_owns_lock(svn_boolean_t *own_lock,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_boolean_t exact,
+ 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));
+
+ if (!pdh->wcroot)
+ return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
+ _("The node '%s' was not found."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ VERIFY_USABLE_PDH(pdh);
+
+ SVN_ERR(wclock_owns_lock(own_lock, pdh, local_relpath, exact, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_wc__db_temp_op_set_base_incomplete(svn_wc__db_t *db,
const char *local_dir_abspath,
svn_boolean_t incomplete,
@@ -8807,11 +8554,7 @@ make_copy_txn(void *baton,
struct make_copy_baton *mcb = baton;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
-#ifdef SVN_WC__OP_DEPTH
svn_boolean_t add_working_base_deleted = FALSE;
-#else
- svn_boolean_t add_working = TRUE;
-#endif
svn_boolean_t remove_working = FALSE;
const apr_array_header_t *children;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -8839,11 +8582,7 @@ make_copy_txn(void *baton,
/* Make existing deletions of BASE_NODEs remove WORKING_NODEs */
remove_working = TRUE;
-#ifdef SVN_WC__OP_DEPTH
add_working_base_deleted = TRUE;
-#else
- add_working = FALSE;
-#endif
}
else
SVN_ERR(svn_sqlite__reset(stmt));
@@ -8884,7 +8623,6 @@ make_copy_txn(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
-#ifdef SVN_WC__OP_DEPTH
if (add_working_base_deleted)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
@@ -8897,9 +8635,6 @@ make_copy_txn(void *baton,
SVN_ERR(svn_sqlite__step_done(stmt));
}
else
-#else
- if (add_working)
-#endif
{
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_WORKING_NODE_FROM_BASE_COPY));
@@ -8955,11 +8690,7 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
mcb.db = db;
mcb.local_abspath = local_abspath;
-#ifdef SVN_WC__OP_DEPTH
mcb.op_depth = relpath_depth(mcb.local_relpath);
-#else
- mcb.op_depth = 2; /* ### temporary op_depth */
-#endif
SVN_ERR(svn_sqlite__with_transaction(mcb.pdh->wcroot->sdb,
make_copy_txn, &mcb,
@@ -8968,168 +8699,6 @@ svn_wc__db_temp_op_make_copy(svn_wc__db_
return SVN_NO_ERROR;
}
-#ifndef SVN_WC__OP_DEPTH
-/* Return the copyfrom info for LOCAL_ABSPATH resolving inheritance. */
-static svn_error_t *
-get_copyfrom(apr_int64_t *copyfrom_repos_id,
- const char **copyfrom_relpath,
- svn_revnum_t *copyfrom_revnum,
- 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_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_SELECT_WORKING_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)
- {
- *copyfrom_repos_id = INVALID_REPOS_ID;
- *copyfrom_relpath = NULL;
- *copyfrom_revnum = SVN_INVALID_REVNUM;
- SVN_ERR(svn_sqlite__reset(stmt));
- return SVN_NO_ERROR;
- }
-
- if (svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
- {
- /* Resolve inherited copyfrom */
- const char *parent_relpath, *name, *parent_copyfrom_relpath;
-
- SVN_ERR(svn_sqlite__reset(stmt));
- svn_relpath_split(&parent_relpath, &name, local_relpath, scratch_pool);
- SVN_ERR(get_copyfrom(copyfrom_repos_id, &parent_copyfrom_relpath,
- copyfrom_revnum,
- pdh, parent_relpath, scratch_pool, scratch_pool));
- if (parent_copyfrom_relpath)
- *copyfrom_relpath = svn_relpath_join(parent_copyfrom_relpath, name,
- result_pool);
- else
- *copyfrom_relpath = NULL;
- return SVN_NO_ERROR;
- }
-
- *copyfrom_repos_id = svn_sqlite__column_int64(stmt, 10);
- *copyfrom_relpath = svn_sqlite__column_text(stmt, 11, result_pool);
- *copyfrom_revnum = svn_sqlite__column_revnum(stmt, 12);
-
- SVN_ERR(svn_sqlite__reset(stmt));
-
- return SVN_NO_ERROR;
-}
-#endif
-
-
-#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)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
- apr_int64_t original_repos_id;
- const char *original_repos_relpath;
- svn_revnum_t original_revision;
- const char *parent_local_relpath;
- const char *name;
- apr_int64_t parent_repos_id;
- const char *parent_repos_relpath;
- svn_revnum_t parent_revision;
- const char *implied_relpath;
-
- /* Examine the current WORKING_NODE row's copyfrom information. If there
- is no WORKING node, then simply exit. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_SELECT_WORKING_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)
- return svn_error_return(svn_sqlite__reset(stmt));
-
- /* Already inheriting copyfrom information? */
- if (svn_sqlite__column_is_null(stmt, 10 /* copyfrom_repos_id */))
- return svn_error_return(svn_sqlite__reset(stmt));
-
- original_repos_id = svn_sqlite__column_int64(stmt, 10);
- original_repos_relpath = svn_sqlite__column_text(stmt, 11, scratch_pool);
- original_revision = svn_sqlite__column_revnum(stmt, 12);
-
- SVN_ERR(svn_sqlite__reset(stmt));
-
- svn_dirent_split(&parent_local_relpath, &name, local_relpath, scratch_pool);
-
- SVN_ERR(get_copyfrom(&parent_repos_id, &parent_repos_relpath,
- &parent_revision,
- pdh, parent_local_relpath, scratch_pool, scratch_pool));
- if (parent_revision == SVN_INVALID_REVNUM)
- return SVN_NO_ERROR;
-
- /* Now we need to determine if the child's values are derivable from
- the parent values. */
-
- /* If the revision numbers are not the same, then easy exit.
-
- Note that we *can* have a mixed-rev copied subtree. We don't want
- to elide the copyfrom information for these cases. */
- if (original_revision != parent_revision)
- return SVN_NO_ERROR;
-
- /* The child repos_relpath should be under the parent's. */
- if (svn_relpath_is_child(parent_repos_relpath,
- original_repos_relpath,
- NULL) == NULL)
- return SVN_NO_ERROR;
-
- /* Given the relpath from OP_ROOT_ABSPATH down to LOCAL_ABSPATH, compute
- an implied REPOS_RELPATH. If that does not match the RELPATH we found,
- then we can exit (the child is a new copy root). */
- implied_relpath = svn_relpath_join(parent_repos_relpath, name, scratch_pool);
- if (strcmp(implied_relpath, original_repos_relpath) != 0)
- return SVN_NO_ERROR;
-
- if (original_repos_id != parent_repos_id)
- return SVN_NO_ERROR;
-
- /* The child's copyfrom information is derivable from the parent.
- The data should be reset to null, indicating the derivation. */
- /* Should probably use the op_depth from query above and simplify this
- query. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, pdh->wcroot->sdb,
- STMT_UPDATE_COPYFROM_TO_INHERIT));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", pdh->wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__update(NULL, stmt));
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__db_temp_elide_copyfrom(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_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_readwrite,
- scratch_pool, scratch_pool));
- VERIFY_USABLE_PDH(pdh);
-
- SVN_ERR(elide_copyfrom(pdh, local_relpath, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-#endif
-
svn_error_t *
svn_wc__db_temp_get_file_external(const char **serialized_file_external,
@@ -9553,3 +9122,25 @@ svn_wc__db_temp_op_set_new_dir_to_incomp
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_temp_below_work(svn_boolean_t *have_work,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t have_base;
+ svn_wc__db_status_t status;
+ 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_readwrite,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_PDH(pdh);
+ SVN_ERR(info_below_working(&have_base, have_work, &status,
+ pdh, local_relpath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}