Return-Path: Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: (qmail 67580 invoked from network); 10 Dec 2010 21:24:25 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 10 Dec 2010 21:24:25 -0000 Received: (qmail 22669 invoked by uid 500); 10 Dec 2010 21:24:25 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 22647 invoked by uid 500); 10 Dec 2010 21:24:25 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 22640 invoked by uid 99); 10 Dec 2010 21:24:25 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Dec 2010 21:24:25 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED,T_FRT_PROFILE2 X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Dec 2010 21:24:06 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id CEDD92388C22; Fri, 10 Dec 2010 21:23:20 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1044516 [13/22] - in /subversion/branches/ignore-mergeinfo: ./ build/ac-macros/ build/generator/ contrib/server-side/ notes/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subve... Date: Fri, 10 Dec 2010 21:23:13 -0000 To: commits@subversion.apache.org From: hwright@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20101210212320.CEDD92388C22@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/upgrade.c URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/upgrade.c?rev=1044516&r1=1044515&r2=1044516&view=diff ============================================================================== --- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/upgrade.c (original) +++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/upgrade.c Fri Dec 10 21:23:03 2010 @@ -35,12 +35,18 @@ #include "wc_db.h" #include "tree_conflicts.h" #include "wc-queries.h" /* for STMT_* */ +#include "workqueue.h" #include "svn_private_config.h" #include "private/svn_wc_private.h" #include "private/svn_sqlite.h" #include "private/svn_token.h" +/* WC-1.0 administrative area extensions */ +#define SVN_WC__BASE_EXT ".svn-base" /* for text and prop bases */ +#define SVN_WC__WORK_EXT ".svn-work" /* for working propfiles */ +#define SVN_WC__REVERT_EXT ".svn-revert" /* for reverting a replaced + file */ /* Old locations for storing "wcprops" (aka "dav cache"). */ #define WCPROPS_SUBDIR_FOR_FILES "wcprops" @@ -67,6 +73,7 @@ /* New pristine location */ #define PRISTINE_STORAGE_RELPATH "pristine" +#define SDB_FILE "wc.db" /* Read the properties from the file at PROPFILE_ABSPATH, returning them @@ -280,60 +287,36 @@ maybe_add_subdir(apr_array_header_t *sub } -/* Return in CHILDREN, the list of all versioned subdirectories which also - exist on disk as directories. */ +/* Return in CHILDREN, the list of all 1.6 versioned subdirectories + which also exist on disk as directories. */ static svn_error_t * get_versioned_subdirs(apr_array_header_t **children, - svn_wc__db_t *db, const char *dir_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - int wc_format; apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_hash_t *entries; + apr_hash_index_t *hi; *children = apr_array_make(result_pool, 10, sizeof(const char *)); - SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, dir_abspath, iterpool)); - if (wc_format >= SVN_WC__WC_NG_VERSION) - { - const apr_array_header_t *all_children; - int i; - - SVN_ERR(svn_wc__db_read_children(&all_children, db, dir_abspath, - scratch_pool, scratch_pool)); - for (i = 0; i < all_children->nelts; ++i) - { - const char *name = APR_ARRAY_IDX(all_children, i, const char *); - - svn_pool_clear(iterpool); - - SVN_ERR(maybe_add_subdir(*children, dir_abspath, name, - result_pool, iterpool)); - } - } - else + SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath, + scratch_pool, iterpool)); + for (hi = apr_hash_first(scratch_pool, entries); + hi; + hi = apr_hash_next(hi)) { - apr_hash_t *entries; - apr_hash_index_t *hi; - - SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath, - scratch_pool, iterpool)); - for (hi = apr_hash_first(scratch_pool, entries); - hi; - hi = apr_hash_next(hi)) - { - const char *name = svn__apr_hash_index_key(hi); + const char *name = svn__apr_hash_index_key(hi); - /* skip "this dir" */ - if (*name == '\0') - continue; + /* skip "this dir" */ + if (*name == '\0') + continue; - svn_pool_clear(iterpool); + svn_pool_clear(iterpool); - SVN_ERR(maybe_add_subdir(*children, dir_abspath, name, - result_pool, iterpool)); - } + SVN_ERR(maybe_add_subdir(*children, dir_abspath, name, + result_pool, iterpool)); } svn_pool_destroy(iterpool); @@ -342,34 +325,34 @@ get_versioned_subdirs(apr_array_header_t } -/* Return in CHILDREN, the list of all versioned *files* in SDB. - These files' existence on disk is not tested. +/* Return in CHILDREN the names of all versioned *files* in SDB that + are children of PARENT_RELPATH. These files' existence on disk is + not tested. - This set of children is intended for props/text-base upgrades. - Subdirectory's properties exist in the subdirs. Non-files have no - text bases. + This set of children is intended for property upgrades. + Subdirectory's properties exist in the subdirs. Note that this uses just the SDB to locate children, which means - that the children must have been upgraded to wc-ng format. Also note - that this returns *all* files found in SDB. Typically, this is just - one directory's worth since it won't be run on a single-db. */ + that the children must have been upgraded to wc-ng format. */ static svn_error_t * get_versioned_files(const apr_array_header_t **children, + const char *parent_relpath, svn_sqlite__db_t *sdb, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; - apr_array_header_t *child_relpaths; + apr_array_header_t *child_names; svn_boolean_t have_row; /* ### just select 'file' children. do we need 'symlink' in the future? */ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ALL_FILES)); + SVN_ERR(svn_sqlite__bindf(stmt, "s", parent_relpath)); /* ### 10 is based on Subversion's average of 8.5 files per versioned ### directory in its repository. maybe use a different value? or ### count rows first? */ - child_relpaths = apr_array_make(result_pool, 10, sizeof(const char *)); + child_names = apr_array_make(result_pool, 10, sizeof(const char *)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); while (have_row) @@ -377,12 +360,13 @@ get_versioned_files(const apr_array_head const char *local_relpath = svn_sqlite__column_text(stmt, 0, result_pool); - APR_ARRAY_PUSH(child_relpaths, const char *) = local_relpath; + APR_ARRAY_PUSH(child_names, const char *) + = svn_relpath_basename(local_relpath, result_pool); SVN_ERR(svn_sqlite__step(&have_row, stmt)); } - *children = child_relpaths; + *children = child_names; return svn_error_return(svn_sqlite__reset(stmt)); } @@ -478,7 +462,6 @@ wipe_obsolete_files(const char *wcroot_a scratch_pool), FALSE, NULL, NULL, scratch_pool)); -#if (SVN_WC__VERSION >= 18) /* Remove the old properties files... whole directories at a time. */ svn_error_clear(svn_io_remove_dir2( svn_wc__adm_child(wcroot_abspath, @@ -505,7 +488,6 @@ wipe_obsolete_files(const char *wcroot_a PROP_REVERT_FOR_DIR, scratch_pool), TRUE, scratch_pool)); -#endif #if 0 /* ### this checks for a write-lock, and we are not (always) taking out @@ -519,6 +501,54 @@ wipe_obsolete_files(const char *wcroot_a TRUE, scratch_pool)); } +svn_error_t * +svn_wc__wipe_postupgrade(const char *dir_abspath, + svn_boolean_t whole_admin, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_array_header_t *subdirs; + svn_error_t *err; + int i; + + if (cancel_func) + SVN_ERR((*cancel_func)(cancel_baton)); + + err = get_versioned_subdirs(&subdirs, dir_abspath, scratch_pool, iterpool); + if (err) + { + if (APR_STATUS_IS_ENOENT(err->apr_err)) + { + /* An unversioned dir is obstructing a versioned dir */ + svn_error_clear(err); + err = NULL; + } + svn_pool_destroy(iterpool); + return err; + } + for (i = 0; i < subdirs->nelts; ++i) + { + const char *child_abspath = APR_ARRAY_IDX(subdirs, i, const char *); + + svn_pool_clear(iterpool); + SVN_ERR(svn_wc__wipe_postupgrade(child_abspath, TRUE, + cancel_func, cancel_baton, iterpool)); + } + + /* ### Should we really be ignoring errors here? */ + if (whole_admin) + svn_error_clear(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, "", + iterpool), + TRUE, NULL, NULL, iterpool)); + else + wipe_obsolete_files(dir_abspath, scratch_pool); + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} /* Ensure that ENTRY has its REPOS and UUID fields set. These will be used to establish the REPOSITORY row in the new database, and then @@ -877,9 +907,6 @@ migrate_locks(const char *wcroot_abspath struct bump_baton { const char *wcroot_abspath; -#ifdef SINGLE_DB - const char *single_db_wcroot_abspath; -#endif }; /* */ @@ -918,7 +945,8 @@ bump_to_16(void *baton, svn_sqlite__db_t /* Migrate the properties for one node (LOCAL_ABSPATH). */ static svn_error_t * -migrate_node_props(const char *wcroot_abspath, +migrate_node_props(const char *dir_abspath, + const char *new_wcroot_abspath, const char *name, svn_sqlite__db_t *sdb, int original_format, @@ -930,24 +958,29 @@ migrate_node_props(const char *wcroot_ab apr_hash_t *base_props; apr_hash_t *revert_props; apr_hash_t *working_props; + const char *old_wcroot_abspath + = svn_dirent_get_longest_ancestor(dir_abspath, new_wcroot_abspath, + scratch_pool); + const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath, + dir_abspath); if (*name == '\0') { - base_abspath = svn_wc__adm_child(wcroot_abspath, PROP_BASE_FOR_DIR, - scratch_pool); - revert_abspath = svn_wc__adm_child(wcroot_abspath, PROP_REVERT_FOR_DIR, - scratch_pool); - working_abspath = svn_wc__adm_child(wcroot_abspath, PROP_WORKING_FOR_DIR, - scratch_pool); + base_abspath = svn_wc__adm_child(dir_abspath, + PROP_BASE_FOR_DIR, scratch_pool); + revert_abspath = svn_wc__adm_child(dir_abspath, + PROP_REVERT_FOR_DIR, scratch_pool); + working_abspath = svn_wc__adm_child(dir_abspath, + PROP_WORKING_FOR_DIR, scratch_pool); } else { const char *basedir_abspath; const char *propsdir_abspath; - propsdir_abspath = svn_wc__adm_child(wcroot_abspath, PROPS_SUBDIR, + propsdir_abspath = svn_wc__adm_child(dir_abspath, PROPS_SUBDIR, scratch_pool); - basedir_abspath = svn_wc__adm_child(wcroot_abspath, PROP_BASE_SUBDIR, + basedir_abspath = svn_wc__adm_child(dir_abspath, PROP_BASE_SUBDIR, scratch_pool); base_abspath = svn_dirent_join(basedir_abspath, @@ -980,7 +1013,8 @@ migrate_node_props(const char *wcroot_ab scratch_pool, scratch_pool)); return svn_error_return(svn_wc__db_upgrade_apply_props( - sdb, wcroot_abspath, name, + sdb, new_wcroot_abspath, + svn_relpath_join(dir_relpath, name, scratch_pool), base_props, revert_props, working_props, original_format, scratch_pool)); @@ -989,7 +1023,8 @@ migrate_node_props(const char *wcroot_ab /* */ static svn_error_t * -migrate_props(const char *wcroot_abspath, +migrate_props(const char *dir_abspath, + const char *new_wcroot_abspath, svn_sqlite__db_t *sdb, int original_format, apr_pool_t *scratch_pool) @@ -1016,22 +1051,28 @@ migrate_props(const char *wcroot_abspath */ const apr_array_header_t *children; apr_pool_t *iterpool = svn_pool_create(scratch_pool); + const char *old_wcroot_abspath + = svn_dirent_get_longest_ancestor(dir_abspath, new_wcroot_abspath, + scratch_pool); + const char *dir_relpath = svn_dirent_skip_ancestor(old_wcroot_abspath, + dir_abspath); int i; /* Migrate the props for "this dir". */ - SVN_ERR(migrate_node_props(wcroot_abspath, "", sdb, original_format, - iterpool)); + SVN_ERR(migrate_node_props(dir_abspath, new_wcroot_abspath, "", sdb, + original_format, iterpool)); /* Iterate over all the files in this SDB. */ - SVN_ERR(get_versioned_files(&children, sdb, scratch_pool, iterpool)); + SVN_ERR(get_versioned_files(&children, dir_relpath, sdb, scratch_pool, + iterpool)); for (i = 0; i < children->nelts; i++) { const char *name = APR_ARRAY_IDX(children, i, const char *); svn_pool_clear(iterpool); - SVN_ERR(migrate_node_props(wcroot_abspath, name, sdb, original_format, - iterpool)); + SVN_ERR(migrate_node_props(dir_abspath, new_wcroot_abspath, + name, sdb, original_format, iterpool)); } svn_pool_destroy(iterpool); @@ -1056,22 +1097,23 @@ bump_to_18(void *baton, svn_sqlite__db_t /* ### no schema changes (yet)... */ SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_18)); - SVN_ERR(migrate_props(b18->wcroot_abspath, sdb, b18->original_format, - scratch_pool)); + SVN_ERR(migrate_props(b18->wcroot_abspath, b18->wcroot_abspath, sdb, + b18->original_format, scratch_pool)); return SVN_NO_ERROR; } static svn_error_t * -migrate_text_bases(const char *wcroot_abspath, +migrate_text_bases(const char *dir_abspath, + const char *new_wcroot_abspath, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) { apr_hash_t *dirents; apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_hash_index_t *hi; - const char *text_base_dir = svn_wc__adm_child(wcroot_abspath, + const char *text_base_dir = svn_wc__adm_child(dir_abspath, TEXT_BASE_SUBDIR, scratch_pool); @@ -1119,7 +1161,7 @@ migrate_text_bases(const char *wcroot_ab SVN_ERR(svn_sqlite__insert(NULL, stmt)); SVN_ERR(svn_wc__db_pristine_get_future_path(&pristine_path, - wcroot_abspath, + new_wcroot_abspath, sha1_checksum, iterpool, iterpool)); @@ -1147,78 +1189,11 @@ bump_to_17(void *baton, svn_sqlite__db_t const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath; SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_17)); - SVN_ERR(migrate_text_bases(wcroot_abspath, sdb, scratch_pool)); - - return SVN_NO_ERROR; -} - - -#ifdef SINGLE_DB -/* Migrate one directory to a Single DB (per WC): if this is a subdirectory, - * move all of its DB rows and pristine texts to the real WC-root. - * - * ### JAF: This is experimental code for others to use or ignore until I - * get back to it. It may need to be re-written in a completely - * different way. Especially, it probably wants to be moved from - * the auto-upgrade code path to the manual-upgrade code path. - * How to make the caller provide the BATON->wcroot_abspath and - */ -static svn_error_t * -bump_to_19(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - struct bump_baton *bb = baton; - const char *this_wc_dir_abspath = bb->wcroot_abspath; - const char *single_db_wcroot_abspath = bb->single_db_wcroot_abspath; - const char *this_wc_dir_relpath - = svn_relpath_is_child(single_db_wcroot_abspath, this_wc_dir_abspath, - scratch_pool); - const char *parent_wc_dir_relpath - = svn_relpath_dirname(this_wc_dir_relpath, scratch_pool); - const char *single_db_sdb_abspath; - svn_sqlite__stmt_t *stmt; - - /* If this is the single-DB WC root directory, there is nothing to do for - * this particular directory. */ - if (strcmp(this_wc_dir_abspath, single_db_wcroot_abspath) == 0) - return SVN_NO_ERROR; - - /* Get the path to the WC-root SDB as a native style path, UTF-8-encoded. */ - single_db_sdb_abspath = svn_wc__adm_child(single_db_wcroot_abspath, "wc.db", - scratch_pool); - /* ### TODO: convert path to native style */ - - /* Attach the single-db so we can write into it. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_ATTACH_WCROOT_DB)); - SVN_ERR(svn_sqlite__bindf(stmt, "s", single_db_sdb_abspath)); - SVN_ERR(svn_sqlite__step_done(stmt)); - - /* ### TODO: the REPOSITORY table */ - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_COPY_BASE_NODE_TABLE_TO_WCROOT_DB)); - SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath)); - SVN_ERR(svn_sqlite__update(NULL, stmt)); - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_COPY_WORKING_NODE_TABLE_TO_WCROOT_DB)); - SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath)); - SVN_ERR(svn_sqlite__update(NULL, stmt)); - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_COPY_ACTUAL_NODE_TABLE_TO_WCROOT_DB)); - SVN_ERR(svn_sqlite__bindf(stmt, "ss", this_wc_dir_relpath, parent_wc_dir_relpath)); - SVN_ERR(svn_sqlite__update(NULL, stmt)); - - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_COPY_LOCK_TABLE_TO_WCROOT_DB)); - - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_COPY_PRISTINE_TABLE_TO_WCROOT_DB)); - - /* ### TODO: move the pristine text files from this_wc_dir_abspath to - * single_db_wcroot_abspath. */ + SVN_ERR(migrate_text_bases(wcroot_abspath, wcroot_abspath, sdb, + scratch_pool)); return SVN_NO_ERROR; } -#endif /* SINGLE_DB */ #if 0 /* ### no tree conflict migration yet */ @@ -1238,6 +1213,13 @@ bump_to_XXX(void *baton, svn_sqlite__db_ #endif /* ### no tree conflict migration yet */ +struct upgrade_data_t { + svn_sqlite__db_t *sdb; + const char *root_abspath; + apr_int64_t repos_id; + apr_int64_t wc_id; +}; + /* Upgrade the working copy directory represented by DB/DIR_ABSPATH from OLD_FORMAT to the wc-ng format (SVN_WC__WC_NG_VERSION)'. @@ -1246,6 +1228,10 @@ bump_to_XXX(void *baton, svn_sqlite__db_ REPOS_CACHE if it doesn't have a cached entry for this repository. + DATA->SDB will be null if this is the root directory, in which case + the db must be created and *DATA filled in, otherwise *DATA refer + to the single root db. + Uses SCRATCH_POOL for all temporary allocation. */ static svn_error_t * upgrade_to_wcng(svn_wc__db_t *db, @@ -1254,6 +1240,8 @@ upgrade_to_wcng(svn_wc__db_t *db, svn_wc_upgrade_get_repos_info_t repos_info_func, void *repos_info_baton, apr_hash_t *repos_cache, + struct upgrade_data_t *data, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *logfile_path = svn_wc__adm_child(dir_abspath, ADM_LOG, @@ -1261,15 +1249,11 @@ upgrade_to_wcng(svn_wc__db_t *db, svn_node_kind_t logfile_on_disk; apr_hash_t *entries; svn_wc_entry_t *this_dir; - svn_sqlite__db_t *sdb; - apr_int64_t repos_id; - apr_int64_t wc_id; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); /* Don't try to mess with the WC if there are old log files left. */ /* Is the (first) log file present? */ - SVN_ERR(svn_io_check_path(logfile_path, &logfile_on_disk, iterpool)); + SVN_ERR(svn_io_check_path(logfile_path, &logfile_on_disk, scratch_pool)); if (logfile_on_disk == svn_node_file) return svn_error_create(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, _("Cannot upgrade with existing logs; please " @@ -1278,7 +1262,7 @@ upgrade_to_wcng(svn_wc__db_t *db, /* Lock this working copy directory, or steal an existing lock. Do this BEFORE we read the entries. We don't want another process to modify the entries after we've read them into memory. */ - SVN_ERR(create_physical_lock(dir_abspath, iterpool)); + SVN_ERR(create_physical_lock(dir_abspath, scratch_pool)); /* What's going on here? * @@ -1299,13 +1283,13 @@ upgrade_to_wcng(svn_wc__db_t *db, /***** ENTRIES *****/ SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath, - scratch_pool, iterpool)); + scratch_pool, scratch_pool)); this_dir = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING); SVN_ERR(ensure_repos_info(this_dir, dir_abspath, repos_info_func, repos_info_baton, repos_cache, - scratch_pool, iterpool)); + scratch_pool, scratch_pool)); /* Cache repos UUID pairs for when a subdir doesn't have this information */ if (!apr_hash_get(repos_cache, this_dir->repos, APR_HASH_KEY_STRING)) @@ -1318,22 +1302,45 @@ upgrade_to_wcng(svn_wc__db_t *db, apr_pstrdup(hash_pool, this_dir->uuid)); } - /* Create an empty sqlite database for this directory. */ - SVN_ERR(svn_wc__db_upgrade_begin(&sdb, &repos_id, &wc_id, dir_abspath, - this_dir->repos, this_dir->uuid, - scratch_pool, iterpool)); + if (!data->sdb) + { + const char *root_adm_abspath; - /* Migrate the entries over to the new database. - ### We need to think about atomicity here. + /* In root wc construst path to temporary root wc/.svn/tmp/wcng/.svn */ - entries_write_new() writes in current format rather than f12. Thus, this - function bumps a working copy all the way to current. */ - SVN_ERR(svn_wc__db_temp_reset_format(SVN_WC__VERSION, db, dir_abspath, - iterpool)); - SVN_ERR(svn_wc__db_wclock_obtain(db, dir_abspath, 0, FALSE, iterpool)); - SVN_ERR(svn_wc__write_upgraded_entries(db, sdb, repos_id, wc_id, - dir_abspath, entries, - iterpool)); + data->root_abspath = svn_dirent_join(svn_wc__adm_child(dir_abspath, "tmp", + scratch_pool), + "wcng", result_pool); + root_adm_abspath = svn_wc__adm_child(data->root_abspath, "", + scratch_pool); + SVN_ERR(svn_io_remove_dir2(root_adm_abspath, TRUE, NULL, NULL, + scratch_pool)); + SVN_ERR(svn_wc__ensure_directory(root_adm_abspath, scratch_pool)); + + /* Create an empty sqlite database for this directory. */ + SVN_ERR(svn_wc__db_upgrade_begin(&data->sdb, + &data->repos_id, &data->wc_id, + data->root_abspath, + this_dir->repos, this_dir->uuid, + result_pool, scratch_pool)); + + /* Migrate the entries over to the new database. + ### We need to think about atomicity here. + + entries_write_new() writes in current format rather than + f12. Thus, this function bumps a working copy all the way to + current. */ + SVN_ERR(svn_wc__db_temp_reset_format(SVN_WC__VERSION, db, + data->root_abspath, scratch_pool)); + SVN_ERR(svn_wc__db_wclock_obtain(db, data->root_abspath, 0, FALSE, + scratch_pool)); + } + + SVN_ERR(svn_wc__write_upgraded_entries(db, data->sdb, + data->repos_id, data->wc_id, + dir_abspath, data->root_abspath, + entries, + scratch_pool)); /***** WC PROPS *****/ @@ -1341,44 +1348,37 @@ upgrade_to_wcng(svn_wc__db_t *db, 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, - iterpool, iterpool)); + scratch_pool, scratch_pool)); else SVN_ERR(read_wcprops(&all_wcprops, dir_abspath, - iterpool, iterpool)); + scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(sdb, all_wcprops, iterpool)); + SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(data->sdb, dir_relpath, + all_wcprops, scratch_pool)); } - SVN_ERR(migrate_text_bases(dir_abspath, sdb, iterpool)); + SVN_ERR(migrate_text_bases(dir_abspath, data->root_abspath, data->sdb, + scratch_pool)); -#if (SVN_WC__VERSION >= 18) /* Upgrade all the properties (including "this dir"). Note: this must come AFTER the entries have been migrated into the database. The upgrade process needs the children in BASE_NODE and WORKING_NODE, and to examine the resultant WORKING state. */ - SVN_ERR(migrate_props(dir_abspath, sdb, old_format, iterpool)); -#endif + SVN_ERR(migrate_props(dir_abspath, data->root_abspath, data->sdb, old_format, + scratch_pool)); /* All done. DB should finalize the upgrade process now. */ - SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, sdb, iterpool)); - - /* All subdir access batons (and locks!) will be closed. Of course, they - should have been closed/unlocked just after their own upgrade process - has run. */ - /* ### well, actually.... we don't recursively delete subdir locks here, - ### we rely upon their own upgrade processes to do it. */ - SVN_ERR(svn_wc__db_wclock_release(db, dir_abspath, iterpool)); - - /* Zap all the obsolete files. This removes the old-style lock file. */ - wipe_obsolete_files(dir_abspath, iterpool); - - /* ### need to (eventually) delete the .svn subdir. */ + SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, data->sdb, scratch_pool)); - svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1449,7 +1449,6 @@ svn_wc__upgrade_sdb(int *result_format, *result_format = 16; /* FALLTHROUGH */ -#if (SVN_WC__VERSION > 16) case 16: { const char *pristine_dir; @@ -1467,9 +1466,7 @@ svn_wc__upgrade_sdb(int *result_format, *result_format = 17; /* FALLTHROUGH */ -#endif -#if (SVN_WC__VERSION > 17) case 17: { struct bump_to_18_baton b18; @@ -1484,16 +1481,13 @@ svn_wc__upgrade_sdb(int *result_format, *result_format = 18; /* FALLTHROUGH */ -#endif #if (SVN_WC__VERSION > 18) case 18: - /* Merge all subdirectory DBs and pristines into the WC-root. */ - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_19, &bb, - scratch_pool)); - - *result_format = 19; - /* FALLTHROUGH */ + 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); #endif /* ### future bumps go here. */ @@ -1532,6 +1526,7 @@ upgrade_working_copy(svn_wc__db_t *db, svn_wc_upgrade_get_repos_info_t repos_info_func, void *repos_info_baton, apr_hash_t *repos_cache, + struct upgrade_data_t *data, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, @@ -1541,23 +1536,48 @@ upgrade_working_copy(svn_wc__db_t *db, int old_format; apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_array_header_t *subdirs; + svn_error_t *err; int i; - /* Check cancellation; note that this catches recursive calls too. */ if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_wc__db_temp_get_format(&old_format, db, dir_abspath, iterpool)); - SVN_ERR(get_versioned_subdirs(&subdirs, db, dir_abspath, - scratch_pool, iterpool)); + if (old_format >= SVN_WC__WC_NG_VERSION) + { + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(dir_abspath, svn_wc_notify_skip, + iterpool), + iterpool); + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; + } + + err = get_versioned_subdirs(&subdirs, dir_abspath, scratch_pool, iterpool); + if (err) + { + if (APR_STATUS_IS_ENOENT(err->apr_err)) + { + /* An unversioned dir is obstructing a versioned dir */ + svn_error_clear(err); + err = NULL; + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(dir_abspath, svn_wc_notify_skip, + iterpool), + iterpool); + } + svn_pool_destroy(iterpool); + return err; + } - /* Upgrade this directory first. */ - if (old_format < SVN_WC__WC_NG_VERSION) - SVN_ERR(upgrade_to_wcng(db, dir_abspath, old_format, - repos_info_func, repos_info_baton, - repos_cache, iterpool)); + + SVN_ERR(upgrade_to_wcng(db, dir_abspath, old_format, + repos_info_func, repos_info_baton, + repos_cache, data, scratch_pool, iterpool)); if (notify_func) notify_func(notify_baton, @@ -1565,7 +1585,6 @@ upgrade_working_copy(svn_wc__db_t *db, iterpool), iterpool); - /* Now recurse. */ for (i = 0; i < subdirs->nelts; ++i) { const char *child_abspath = APR_ARRAY_IDX(subdirs, i, const char *); @@ -1574,7 +1593,7 @@ upgrade_working_copy(svn_wc__db_t *db, SVN_ERR(upgrade_working_copy(db, child_abspath, repos_info_func, repos_info_baton, - repos_cache, + repos_cache, data, cancel_func, cancel_baton, notify_func, notify_baton, iterpool)); @@ -1586,6 +1605,44 @@ upgrade_working_copy(svn_wc__db_t *db, } +/* Return TRUE if LOCAL_ABSPATH is a pre-1.7 working copy root, FALSE + otherwise. */ +static svn_boolean_t +is_old_wcroot(const char *local_abspath, + apr_pool_t *scratch_pool) +{ + apr_hash_t *entries; + const char *parent_abspath, *name; + svn_wc_entry_t *entry; + svn_error_t *err = svn_wc__read_entries_old(&entries, local_abspath, + scratch_pool, scratch_pool); + if (err) + { + svn_error_clear(err); + return FALSE; + } + + svn_dirent_split(&parent_abspath, &name, local_abspath, scratch_pool); + + err = svn_wc__read_entries_old(&entries, parent_abspath, + scratch_pool, scratch_pool); + if (err) + { + svn_error_clear(err); + return TRUE; + } + + entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING); + if (!entry + || entry->absent + || (entry->deleted && entry->schedule != svn_wc_schedule_add)) + { + return TRUE; + } + + return FALSE; +} + svn_error_t * svn_wc_upgrade(svn_wc_context_t *wc_ctx, const char *local_abspath, @@ -1598,36 +1655,73 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx, apr_pool_t *scratch_pool) { svn_wc__db_t *db; -#if 0 - svn_boolean_t is_wcroot; -#endif + struct upgrade_data_t data = { NULL }; + svn_skel_t *work_item, *work_items = NULL; + const char *pristine_from, *pristine_to, *db_from, *db_to; + + if (!is_old_wcroot(local_abspath, scratch_pool)) + return svn_error_createf( + SVN_ERR_WC_INVALID_OP_ON_CWD, NULL, + _("Cannot upgrade '%s' as it is not a pre-1.7 working copy root"), + svn_dirent_local_style(local_abspath, scratch_pool)); + + /* Given a pre-wcng root some/wc we create a temporary wcng in + some/wc/.svn/tmp/wcng/wc.db and copy the metadata from one to the + other, then the temporary wc.db file gets moved into the original + root. Until the wc.db file is moved the original working copy + remains a pre-wcng and 'cleanup' with an old client will remove + the partial upgrade. Moving the wc.db file creates a wcng, and + 'cleanup' with a new client will complete any outstanding + upgrade. */ - /* We need a DB that does not attempt an auto-upgrade, nor require - running a stale work queue. We'll handle everything manually. */ SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readwrite, NULL /* ### config */, FALSE, FALSE, scratch_pool, scratch_pool)); - /* ### this expects a wc-ng working copy. sigh. fix up soonish... */ -#if 0 - SVN_ERR(svn_wc__strictly_is_wc_root(&is_wcroot, wc_ctx, local_abspath, - scratch_pool)); - if (!is_wcroot) - return svn_error_create( - SVN_ERR_WC_INVALID_OP_ON_CWD, NULL, - _("'svn upgrade' can only be run from the root of the working copy.")); -#endif - - /* Upgrade this directory and/or its subdirectories. */ + /* Upgrade the pre-wcng into a wcng in a temporary location. */ SVN_ERR(upgrade_working_copy(db, local_abspath, repos_info_func, repos_info_baton, - apr_hash_make(scratch_pool), + apr_hash_make(scratch_pool), &data, cancel_func, cancel_baton, notify_func, notify_baton, scratch_pool)); + /* A workqueue item to move the pristine dir into place */ + pristine_from = svn_wc__adm_child(data.root_abspath, PRISTINE_STORAGE_RELPATH, + scratch_pool); + pristine_to = svn_wc__adm_child(local_abspath, PRISTINE_STORAGE_RELPATH, + scratch_pool); + SVN_ERR(svn_wc__wq_build_file_move(&work_item, db, + pristine_from, pristine_to, + scratch_pool, scratch_pool)); + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + + /* A workqueue item to remove pre-wcng metadata */ + SVN_ERR(svn_wc__wq_build_postupgrade(&work_item, scratch_pool)); + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + SVN_ERR(svn_wc__db_wq_add(db, data.root_abspath, work_items, scratch_pool)); + + SVN_ERR(svn_wc__db_wclock_release(db, data.root_abspath, scratch_pool)); + SVN_ERR(svn_sqlite__close(data.sdb)); + SVN_ERR(svn_wc__db_close(db)); + + /* Renaming the db file is what makes the pre-wcng into a wcng */ + db_from = svn_wc__adm_child(data.root_abspath, SDB_FILE, scratch_pool); + db_to = svn_wc__adm_child(local_abspath, SDB_FILE, scratch_pool); + SVN_ERR(svn_io_file_rename(db_from, db_to, scratch_pool)); + + /* Now we have a working wcng, tidy up the droppings */ + SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readwrite, + NULL /* ### config */, FALSE, FALSE, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); SVN_ERR(svn_wc__db_close(db)); + /* Should we have the workqueue remove this empty dir? */ + SVN_ERR(svn_io_remove_dir2(data.root_abspath, FALSE, NULL, NULL, + scratch_pool)); + return SVN_NO_ERROR; } Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/util.c URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/util.c?rev=1044516&r1=1044515&r2=1044516&view=diff ============================================================================== --- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/util.c (original) +++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/util.c Fri Dec 10 21:23:03 2010 @@ -532,8 +532,7 @@ svn_wc__status2_from_3(svn_wc_status2_t { svn_error_t *err; err= svn_wc__get_entry(&entry, wc_ctx->db, local_abspath, FALSE, - svn_node_unknown, FALSE, result_pool, - scratch_pool); + svn_node_unknown, result_pool, scratch_pool); if (err && err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND) svn_error_clear(err); Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-metadata.sql URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-metadata.sql?rev=1044516&r1=1044515&r2=1044516&view=diff ============================================================================== --- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-metadata.sql (original) +++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-metadata.sql Fri Dec 10 21:23:03 2010 @@ -76,6 +76,142 @@ CREATE UNIQUE INDEX I_LOCAL_ABSPATH ON W /* ------------------------------------------------------------------------- */ +/* +The BASE_NODE table: + + BASE is what we get from the server. It is the *absolute* pristine copy. + You need to use checkout, update, switch, or commit to alter your view of + the repository. + + In the BASE tree, each node corresponds to a particular node-rev in the + repository. It can be a mixed-revision tree. Each node holds either a + copy of the node-rev as it exists in the repository (if presence == + 'normal'), or a place-holder (if presence == 'absent' or 'excluded' or + 'not-present'). + [Quoted from wc_db.h] + +Overview of BASE_NODE columns: + + Indexing columns: (wc_id, local_relpath, parent_relpath) + + (presence) + + - The Node-Rev, Content and Last-Change column groups take one of the + states shown in the table below, according to the 'presence': + + Has Has Has + 'presence' Meaning Node-Rev? Content? Last-Change? + ---------- ----------- ----------- -------- ------------ + normal => Present Yes Yes Yes + incomplete => Incomplete Yes Partial No ### ? + absent => Unauthz Yes No No + excluded => Unwanted Yes No No + not-present => Nonexistent No No No + + - If presence==incomplete, this node refers to an existing node-rev but + its Content is not fully and correctly stored. In particular, if it + is a directory, some rows that should represent its children may not + exist or may be in the wrong state. This is intended to be a + temporary state, e.g. during an update. + + - If presence==absent or ==excluded, this row refers to a node that + exists in the repo, but the node is not stored in the WC. + + - If presence==not-present, this row indicates that its parent in the WC + is a directory that, in its pristine state, would have a child of this + name. However, this child was updated or switched to a node-revision + that does not exist. Information about which node-revision it was + updated or switched to is lost; only the fact that it is currently not + present is remembered. + + - The order of precedence of the negative presence values is: + 'excluded' if administratively excluded from the WC, else + 'absent' if server doesn't authorize reading the path, else + 'not-present' if it does not exist in repo. + + Node-Rev columns: (repos_id, repos_relpath, revnum) + + - The Node-Rev group points to the corresponding repository node-rev. + + - If not used (as specified by the 'presence' table above), the values + are undefined. + ### Perhaps we should set them to null to make it clearer. + + Content columns: (kind, properties, depth, target, checksum) + ---- ---------- ----- ------ -------- + 'dir' Yes Yes null null + 'symlink' Yes null Yes null + 'file' Yes null null Yes + 'unknown' null null null null + + - The Content columns take one of the states shown in the table above. + If Content is present, a copy of the Node-Rev's content is stored + locally according to one of the first three rows in the table above, + otherwise kind==unknown and the other columns are null. + + - If kind==dir, the children are represented by the existence of other + BASE_NODE rows. For each immediate child of 'repos_relpath'@'revnum' + in the repo, subject to 'depth', a BASE_NODE row exists with its + 'local_relpath' being this node's 'local_relpath' plus the child's + basename. (Rows may also exist for additional children which are + outside the scope of 'depth' or do not exist as children of this + node-rev in the repository, including 'externals' and paths updated to + a revision in which they do exist.) There is no distinction between + depth==immediates and depth==infinity here. + + - If kind==symlink, the target path is contained in 'target'. + + - If kind==file, the content is contained in the Pristine Store, + referenced by its SHA-1 checksum 'checksum'. + + Last-Change columns: (changed_rev, changed_date, changed_author) + + - Specifies the revision in which the content was last changed before + Node-Rev, following copies and not counting the copy operation itself + as a change. + + - Does not specify the revision in which this node first appeared at + the repository path 'repos_relpath', which could be more recent than + the last change of this node's content. + + - Includes a copy of the corresponding date and author rev-props. + + - If not used (as specified by the 'presence' table above), all null. + ### Not checked; in practice these columns may have undefined values. + + Working file status: (translated_size, last_mod_time) + + - Present iff kind==file and node has no WORKING_NODE row, otherwise + null. (If kind==file and node has a WORKING_NODE row, the info is + recorded in that row). ### True? + + - Records the status of the working file on disk, for the purpose of + detecting quickly whether that file has been modified. + + - Logically belongs to the ACTUAL_NODE table but is recorded in the + BASE_NODE and WORKING_NODE tables instead to avoid the overhead of + storing an ACTUAL_NODE row for each unmodified file. + + - Records the actual size and mod-time of the disk file at the time when + its content was last determined to be logically unmodified relative to + its base, taking account of keywords and EOL style. + + (dav_cache) + + - Content is opaque to libsvn_wc. ### ? + + - Lifetime is managed by the WC: values cleared to null at certain times. + ### To be documented. + + (incomplete_children) + + - Obsolete, unused. + + (file_external) + + - ### To be obsoleted? +*/ + CREATE TABLE BASE_NODE ( /* specifies the location of this node in the local filesystem. wc_id implies an absolute path, and local_relpath is relative to that @@ -83,8 +219,8 @@ CREATE TABLE BASE_NODE ( wc_id INTEGER NOT NULL REFERENCES WCROOT (id), local_relpath TEXT NOT NULL, - /* the repository this node is part of, and the relative path [to its - root] within revision "revnum" of that repository. These may be NULL, + /* The repository this node is part of, and the relative path (from its + root) within revision "revnum" of that repository. These may be NULL, implying they should be derived from the parent and local_relpath. Non-NULL typically indicates a switched node. @@ -137,12 +273,19 @@ CREATE TABLE BASE_NODE ( /* for kind==symlink, this specifies the target. */ symlink_target TEXT, + /* The mod-time of the working file when it was last determined to be + logically unmodified relative to its base, taking account of keywords + and EOL style. + + NULL if this node is not a file or if this info has not yet been + determined. + */ /* ### Do we need this? We've currently got various mod time APIs ### internal to libsvn_wc, but those might be used in answering some ### question which is better answered some other way. */ last_mod_time INTEGER, /* an APR date/time (usec since 1970) */ - /* serialized skel of this node's properties. could be NULL if we + /* serialized skel of this node's properties. NULL if we have no information about the properties (a non-present node). */ properties BLOB, @@ -241,8 +384,8 @@ CREATE TABLE WORKING_NODE ( parent_relpath TEXT, /* Is this node "present" or has it been excluded for some reason? - Only allowed values: normal, not-present, incomplete, base-deleted. - (the others do not make sense for the WORKING tree) + Only allowed values: normal, not-present, incomplete, base-deleted, + excluded. (the others do not make sense for the WORKING tree) normal: this node has been added/copied/moved-here. There may be an underlying BASE node at this location, implying this is a replace. @@ -264,7 +407,11 @@ CREATE TABLE WORKING_NODE ( base-deleted: the underlying BASE node has been marked for deletion due to a delete or a move-away (see the moved_to column to determine - which), and has not been replaced. */ + which), and has not been replaced. + + excluded: this node is administratively excluded (sparse WC). This must + be a child (or grandchild etc.) of a copied directory. + */ presence TEXT NOT NULL, /* the kind of the new node. may be "unknown" if the node is not present. */ @@ -339,13 +486,20 @@ CREATE TABLE WORKING_NODE ( /* should the node on disk be kept after a schedule delete? - ### Bert points out that this can disappear once we get centralized - ### with our metadata. The entire reason for this flag to exist is - ### so that the admin area can exist for the commit of a the delete, + ### Bert points out that this can disappear once we get to single-db. + ### The entire reason for this flag to exist is + ### so that the admin area can exist for the commit of a delete, ### and so the post-commit cleanup knows not to actually delete the dir ### from disk (which is why the flag is only ever set on the this_dir - ### entry in WC-OLD.) In the New World, we don't need to keep the old - ### admin area around, so this flag can disappear. */ + ### entry in WC-OLD.) With single-db, we don't need to keep the old + ### admin area around, so this flag can disappear. + ### neels: In contrast, the --keep-local commandline option will not + ### disappear. The user will still be able to do + ### 'svn delete --keep-local' and keep the to-be-unversioned paths + ### in the file system. It just won't be necessary to remember the + ### keep-local-ness here, because we either delete the file system paths + ### right away during 'svn delete' or we don't at all. There won't be a + ### "second pass" for file system deletion at commit time anymore. */ keep_local INTEGER, PRIMARY KEY (wc_id, local_relpath) @@ -479,21 +633,38 @@ PRAGMA user_version = -- define: SVN_WC__VERSION ; + /* ------------------------------------------------------------------------- */ -/* The NODE_DATA table describes the way WORKING nodes are layered on top of +/* The NODES table describes the way WORKING nodes are layered on top of BASE nodes and on top of other WORKING nodes, due to nested tree structure changes. The layers are modelled using the "op_depth" column. + An 'operation depth' refers to the number of directory levels down from + the WC root at which a tree-change operation (delete, add?, copy, move) + was performed. A row's 'op_depth' does NOT refer to the depth of its own + 'local_relpath', but rather to the depth of the nearest tree change that + affects that node. + + The row with op_depth=0 for any given local relpath represents the "base" + node that is created and updated by checkout, update, switch and commit + post-processing. The row with the highest op_depth for a particular + local_relpath represents the working version. Any rows with intermediate + op_depth values are not normally visible to the user but may become + visible after reverting local changes. + + ### The following text needs revision + Each row in BASE_NODE has an associated row NODE_DATA. Additionally, each row in WORKING_NODE has one or more associated rows in NODE_DATA. - This table contains only those data elements which apply to BASE as well as - all WORKING layers; fields applicable only to the currently visible WORKING - node or BASE node are located in the WORKING_NODE and BASE_NODE tables. + This table contains full node descriptions for nodes in either the BASE + or WORKING trees as described in notes/wc-ng/design. Fields relate + both to BASE and WORKING trees, unless documented otherwise. ### This table is to be integrated into the SCHEMA statement as soon - the experimental status of NODE_DATA is lifted. + the experimental status of NODES is lifted. + ### This table superseeds NODE_DATA For illustration, with a scenario like this: @@ -504,44 +675,69 @@ PRAGMA user_version = touch foo/bar svn add foo/bar # (2) - , these are the NODE_DATA for the path foo/bar (before single-db, the + , these are the NODES for the path foo/bar (before single-db, the numbering of op_depth is still a bit different): - - (0) BASE_NODE -----> NODE_DATA (op_depth == 0) - (1) NODE_DATA (op_depth == 1) ( <----_ ) - (2) NODE_DATA (op_depth == 2) <----- WORKING_NODE - + + (0) BASE_NODE -----> NODES (op_depth == 0) + (1) NODES (op_depth == 1) ( <----_ ) + (2) NODES (op_depth == 2) <----- WORKING_NODE + 0 is the original data for foo/bar before 'svn rm foo' (if it existed). - 1 is the data for foo/bar copied in from ^/moo/bar. (There would also be a - WORKING_NODE for the path foo, with original_* pointing at ^/moo.) + 1 is the data for foo/bar copied in from ^/moo/bar. 2 is the to-be-committed data for foo/bar, created by 'svn add foo/bar'. - An 'svn revert foo/bar' would remove the NODE_DATA of (2) (and possibly - rewire the WORKING_NODE to represent a child of the operation (1)). - So foo/bar would be a copy of ^/moo/bar again. + An 'svn revert foo/bar' would remove the NODES of (2). + */ --- STMT_CREATE_NODE_DATA -CREATE TABLE NODE_DATA ( +-- STMT_CREATE_NODES +CREATE TABLE NODES ( + /* Working copy location related fields */ + wc_id INTEGER NOT NULL REFERENCES WCROOT (id), local_relpath TEXT NOT NULL, + + /* Contains the depth (= number of path segments) of the operation + modifying the working copy tree structure. All nodes below the root + of the operation (aka operation root, aka oproot) affected by the + operation will be assigned the same op_depth. + + op_depth == 0 designates the initial checkout; the BASE tree. + + */ op_depth INTEGER NOT NULL, /* parent's local_relpath for aggregating children of a given parent. this will be "" if the parent is the wcroot. Since a wcroot will - never have a WORKING node the parent_relpath will never be null. */ - /* ### would be nice to make this column NOT NULL. */ + never have a WORKING node the parent_relpath will never be null, + except when op_depth == 0 and the node is a wcroot. */ parent_relpath TEXT, - /* In case 'op_depth' is equal to 0, this is part of the BASE tree; in - that case, all presence values except 'base-deleted' are allowed. + /* Repository location fields */ + + /* When op_depth == 0, these fields refer to the repository location of the + BASE node, the location of the initial checkout. + + When op_depth != 0, they indicate where this node was copied/moved from. + In this case, the fields are set only on the root of the operation, + and are NULL for all children. */ + repos_id INTEGER REFERENCES REPOSITORY (id), + repos_path TEXT, + revision INTEGER, + + + /* WC state fields */ + + /* Is this node "present" or has it been excluded for some reason? + + In case 'op_depth' is equal to 0, this is part of the BASE tree; in + that case, all presence values except 'base-deleted' are allowed. In case 'op_depth' is greater than 0, this is part of a layer of working nodes; in that case, the following presence values apply: - Is this node "present" or has it been excluded for some reason? - Only allowed values: normal, not-present, incomplete, base-deleted. - (the others do not make sense for the WORKING tree) + Only allowed values: normal, not-present, incomplete, base-deleted, + excluded. (the others do not make sense for the WORKING tree) normal: this node has been added/copied/moved-here. There may be an underlying BASE node at this location, implying this is a replace. @@ -563,9 +759,41 @@ CREATE TABLE NODE_DATA ( base-deleted: the underlying BASE node has been marked for deletion due to a delete or a move-away (see the moved_to column to determine - which), and has not been replaced. */ + which), and has not been replaced. + + excluded: this node is administratively excluded (sparse WC). This must + be a child (or grandchild etc.) of a copied directory. + */ presence TEXT NOT NULL, + /* NULL depth means "default" (typically svn_depth_infinity) */ + /* ### depth on WORKING? seems this is a BASE-only concept. how do + ### you do "files" on an added-directory? can't really ignore + ### the subdirs! */ + /* ### maybe a WC-to-WC copy can retain a depth? */ + depth TEXT, + + /* ### JF: For an old-style move, "copyfrom" info stores its source, but a + new WC-NG "move" is intended to be a "true rename" so its copyfrom + revision is implicit, being in effect (new head - 1) at commit time. + For a (new) move, we need to store or deduce the copyfrom local-relpath; + perhaps add a column called "moved_from". */ + + /* Boolean value, specifying if this node was moved here (rather than just + copied). The source of the move is specified in copyfrom_*. */ + moved_here INTEGER, + + /* If the underlying node was moved away (rather than just deleted), this + specifies the local_relpath of where the BASE node was moved to. + This is set only on the root of a move, and is NULL for all children. + + Note that moved_to never refers to *this* node. It always refers + to the "underlying" node, whether that is BASE or a child node + implied from a parent's move/copy. */ + moved_to TEXT, + + /* Repository state fields */ + /* the kind of the new node. may be "unknown" if the node is not present. */ kind TEXT NOT NULL, @@ -578,36 +806,63 @@ CREATE TABLE NODE_DATA ( changed_date INTEGER, /* an APR date/time (usec since 1970) */ changed_author TEXT, - /* NULL depth means "default" (typically svn_depth_infinity) */ - /* ### depth on WORKING? seems this is a BASE-only concept. how do - ### you do "files" on an added-directory? can't really ignore - ### the subdirs! */ - /* ### maybe a WC-to-WC copy can retain a depth? */ - depth TEXT, - /* 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, + /* serialized skel of this node's properties. NULL if we + have no information about the properties (a non-present node). */ + properties BLOB, + + + /* Various cache fields */ + + /* The size in bytes of the working file when it had no local text + modifications. This means the size of the text when translated from + repository-normal format to working copy format with EOL style + translated and keywords expanded according to the properties in the + "properties" column of this row. + + NULL if this node is not a file or if the size has not (yet) been + computed. */ + translated_size INTEGER, + + /* The mod-time of the working file when it was last determined to be + logically unmodified relative to its base, taking account of keywords + and EOL style. This value is used in the change detection heuristic + used by the status command. + + NULL if this node is not a file or if this info has not yet been + determined. + */ + last_mod_time INTEGER, /* an APR date/time (usec since 1970) */ + + /* serialized skel of this node's dav-cache. could be NULL if the + node does not have any dav-cache. */ + dav_cache BLOB, + /* for kind==symlink, this specifies the target. */ symlink_target TEXT, - /* Where this node was copied/moved from. All copyfrom_* fields are set - only on the root of the operation, and are NULL for all children. */ - original_repos_id INTEGER REFERENCES REPOSITORY (id), - original_repos_path TEXT, - original_revision INTEGER, + /* The serialized file external information. */ + /* ### hack. hack. hack. + ### This information is already stored in properties, but because the + ### current working copy implementation is such a pain, we can't + ### readily retrieve it, hence this temporary cache column. + ### When it is removed, be sure to remove the extra column from + ### the db-tests. + + ### Note: This is only here as a hack, and should *NOT* be added + ### to any wc_db APIs. */ + file_external TEXT, - /* serialized skel of this node's properties. NULL if we - have no information about the properties (a non-present node). */ - properties BLOB, PRIMARY KEY (wc_id, local_relpath, op_depth) ); -CREATE INDEX I_NODE_PARENT ON NODE_DATA (wc_id, parent_relpath); -CREATE INDEX I_NODE_PATH ON NODE_DATA (wc_id, local_relpath); +CREATE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath); +CREATE INDEX I_NODES_PATH ON NODES (wc_id, local_relpath); Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-queries.sql?rev=1044516&r1=1044515&r2=1044516&view=diff ============================================================================== --- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/wc-queries.sql Fri Dec 10 21:23:03 2010 @@ -33,6 +33,13 @@ select repos_id, repos_relpath, presence from base_node where wc_id = ?1 and local_relpath = ?2; +-- STMT_SELECT_BASE_NODE_1 +select repos_id, repos_path, presence, kind, revision, checksum, + translated_size, changed_revision, changed_date, changed_author, depth, + symlink_target, last_mod_time, properties +from nodes +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_SELECT_BASE_NODE_WITH_LOCK select base_node.repos_id, base_node.repos_relpath, presence, kind, revnum, checksum, translated_size, changed_rev, changed_date, @@ -43,6 +50,16 @@ left outer join lock on base_node.repos_ and base_node.repos_relpath = lock.repos_relpath where wc_id = ?1 and local_relpath = ?2; +-- STMT_SELECT_BASE_NODE_WITH_LOCK_1 +select nodes.repos_id, nodes.repos_path, presence, kind, revision, + checksum, translated_size, changed_revision, changed_date, changed_author, + depth, symlink_target, last_mod_time, properties, lock_token, lock_owner, + lock_comment, lock_date +from nodes +left outer join lock on nodes.repos_id = lock.repos_id + and nodes.repos_path = lock.repos_relpath +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_SELECT_WORKING_NODE select presence, kind, checksum, translated_size, changed_rev, changed_date, changed_author, depth, symlink_target, @@ -51,6 +68,15 @@ select presence, kind, checksum, transla from working_node where wc_id = ?1 and local_relpath = ?2; +-- STMT_SELECT_WORKING_NODE_1 +select presence, kind, checksum, translated_size, + changed_revision, changed_date, changed_author, depth, symlink_target, + repos_id, repos_path, revision, + moved_here, moved_to, last_mod_time, properties +from nodes +where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 order by op_depth desc +limit 1; + -- STMT_SELECT_ACTUAL_NODE select prop_reject, changelist, conflict_old, conflict_new, conflict_working, tree_conflict_data, properties @@ -77,14 +103,14 @@ insert or replace into base_node ( values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17); --- STMT_INSERT_NODE_DATA -insert or replace into node_data ( - wc_id, local_relpath, op_depth, parent_relpath, presence, kind, - changed_revision, changed_date, changed_author, depth, checksum, - symlink_target, original_repos_id, original_repos_path, - original_revision, properties) -values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, - ?13, ?14, ?15, ?16); +-- STMT_INSERT_NODE +insert or replace into nodes ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, depth, kind, changed_revision, changed_date, + changed_author, checksum, properties, translated_size, last_mod_time, + dav_cache, symlink_target ) +values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, + ?15, ?16, ?17, ?18, ?19); -- STMT_INSERT_BASE_NODE_INCOMPLETE insert or ignore into base_node ( @@ -102,27 +128,47 @@ INSERT OR IGNORE INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind) VALUES (?1, ?2, ?3, 'incomplete', 'unknown'); --- STMT_INSERT_NODE_DATA_INCOMPLETE -INSERT OR IGNORE INTO NODE_DATA ( - wc_id, local_relpath, op_depth, parent_relpath, presence, kind) -VALUES (?1, ?2, ?3, ?4, 'incomplete', 'unknown'); - -- STMT_COUNT_BASE_NODE_CHILDREN SELECT COUNT(*) FROM BASE_NODE WHERE wc_id = ?1 AND parent_relpath = ?2; +-- STMT_COUNT_BASE_NODE_CHILDREN_1 +SELECT COUNT(*) FROM NODES +WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0; + -- STMT_COUNT_WORKING_NODE_CHILDREN SELECT COUNT(*) FROM WORKING_NODE WHERE wc_id = ?1 AND parent_relpath = ?2; +-- STMT_COUNT_WORKING_NODE_CHILDREN_1 +SELECT COUNT(*) FROM NODES +WHERE wc_id = ?1 AND parent_relpath = ?2 + AND op_depth IN (SELECT op_depth FROM NODES + WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth > 0 + ORDER BY op_depth DESC + LIMIT 1); + + -- STMT_SELECT_BASE_NODE_CHILDREN select local_relpath from base_node where wc_id = ?1 and parent_relpath = ?2; +-- STMT_SELECT_BASE_NODE_CHILDREN_1 +select local_relpath from nodes +where wc_id = ?1 and parent_relpath = ?2 and op_depth = 0; + -- STMT_SELECT_WORKING_NODE_CHILDREN SELECT local_relpath FROM WORKING_NODE WHERE wc_id = ?1 AND parent_relpath = ?2; +-- STMT_SELECT_WORKING_NODE_CHILDREN_1 +SELECT local_relpath FROM NODES +WHERE wc_id = ?1 AND parent_relpath = ?2 + AND op_depth IN (SELECT op_depth FROM NODES + WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth > 0 + ORDER BY op_depth DESC + LIMIT 1); + -- STMT_SELECT_WORKING_IS_FILE select kind == 'file' from working_node where wc_id = ?1 and local_relpath = ?2; @@ -135,10 +181,19 @@ where wc_id = ?1 and local_relpath = ?2; select properties from base_node where wc_id = ?1 and local_relpath = ?2; +-- STMT_SELECT_BASE_PROPS_1 +select properties from nodes +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_SELECT_WORKING_PROPS SELECT properties, presence FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_SELECT_WORKING_PROPS_1 +SELECT properties, presence FROM NODES +WHERE wc_id = ?1 AND local_relpath = ?2 +AND op_depth > 0 ORDER BY op_depth DESC LIMIT 1; + -- STMT_SELECT_ACTUAL_PROPS select properties from actual_node where wc_id = ?1 and local_relpath = ?2; @@ -147,20 +202,22 @@ where wc_id = ?1 and local_relpath = ?2; update base_node set properties = ?3 where wc_id = ?1 and local_relpath = ?2; --- STMT_UPDATE_NODE_DATA_BASE_PROPS -update node_data set properties = ?3 +-- STMT_UPDATE_NODE_BASE_PROPS +update nodes set properties = ?3 where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_UPDATE_WORKING_PROPS update working_node set properties = ?3 where wc_id = ?1 and local_relpath = ?2; --- STMT_UPDATE_NODE_DATA_WORKING_PROPS -update node_data set properties = ?3 +-- STMT_UPDATE_NODE_WORKING_PROPS +update nodes set properties = ?3 where wc_id = ?1 and local_relpath = ?2 and op_depth in - (select max(op_depth) from node_data - where wc_id = ?1 and local_relpath = ?2); + (select op_depth from nodes + where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 + order by op_depth desc + limit 1); -- STMT_UPDATE_ACTUAL_PROPS update actual_node set properties = ?3 @@ -184,6 +241,10 @@ values (?1); update base_node set dav_cache = ?3 where wc_id = ?1 and local_relpath = ?2; +-- STMT_UPDATE_BASE_NODE_DAV_CACHE +update nodes set dav_cache = ?3 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_SELECT_BASE_DAV_CACHE select dav_cache from base_node where wc_id = ?1 and local_relpath = ?2; @@ -195,10 +256,6 @@ left outer join base_node on base_node.w and base_node.local_relpath = working_node.local_relpath where working_node.wc_id = ?1 and working_node.local_relpath = ?2; --- STMT_SELECT_PARENT_STUB_INFO -select presence = 'not-present', revnum from base_node -where wc_id = ?1 and local_relpath = ?2; - -- STMT_DELETE_LOCK delete from lock where repos_id = ?1 and repos_relpath = ?2; @@ -209,6 +266,12 @@ where dav_cache is not null and wc_id = (local_relpath = ?2 or local_relpath like ?3 escape '#'); +-- STMT_CLEAR_BASE_NODE_RECURSIVE_DAV_CACHE +update nodes set dav_cache = null +where dav_cache is not null and wc_id = ?1 and op_depth = 0 and + (local_relpath = ?2 or + local_relpath like ?3 escape '#'); + -- STMT_UPDATE_BASE_RECURSIVE_REPO update base_node set repos_id = ?4 where repos_id is not null and wc_id = ?1 and @@ -221,11 +284,11 @@ where copyfrom_repos_id is not null and (local_relpath = ?2 or local_relpath like ?3 escape '#'); --- STMT_UPDATE_NODE_DATA_RECURSIVE_ORIGINAL_REPO -update node_data set original_repos_id = ?5 -where wc_id = ?1 and original_repos_id = ?4 and - (local_relpath = ?2 or - local_relpath like ?3 escape '#'); +-- STMT_RECURSIVE_UPDATE_NODE_REPO +update NODES set repos_id = ?5, dav_cache = null +where wc_id = ?1 and repos_id = ?4 and + (local_relpath = ?2 + or local_relpath like ?3 escape '#'); -- STMT_UPDATE_LOCK_REPOS_ID update lock set repos_id = ?4 @@ -237,10 +300,22 @@ where repos_id = ?1 and UPDATE BASE_NODE SET translated_size = ?3, last_mod_time = ?4 WHERE wc_id = ?1 AND local_relpath = ?2; +-- 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_FILEINFO UPDATE WORKING_NODE SET translated_size = ?3, last_mod_time = ?4 WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_UPDATE_WORKING_NODE_FILEINFO +update nodes set translated_size = ?3, last_mod_time = ?4 +where wc_id = ?1 and local_relpath = ?2 + and op_depth = (select op_depth from nodes + where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 + order by op_depth desc + limit 1); + -- STMT_UPDATE_ACTUAL_TREE_CONFLICTS update actual_node set tree_conflict_data = ?3 where wc_id = ?1 and local_relpath = ?2; @@ -290,25 +365,21 @@ VALUES (?1, ?2, ?3, ?4); delete from base_node where wc_id = ?1 and local_relpath = ?2; -/* ### Basically, this query can't exist: - we can't be deleting BASE nodes while they still have - associated WORKING nodes; - at minimum, the op_depth restriction should be removed */ --- STMT_DELETE_NODE_DATA_BASE -delete from node_data +-- STMT_DELETE_BASE_NODE_1 +delete from nodes where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_DELETE_WORKING_NODE delete from working_node where wc_id = ?1 and local_relpath = ?2; --- STMT_DELETE_NODE_DATA_WORKING -delete from node_data +-- STMT_DELETE_WORKING_NODES +delete from nodes where wc_id = ?1 and local_relpath = ?2 and op_depth > 0; --- STMT_DELETE_NODE_DATA_LAYERS -delete from node_data -where wc_id = ?1 and local_relpath = ?2 and op_depth >= ?3; +-- STMT_DELETE_NODES +delete from nodes +where wc_id = ?1 and local_relpath = ?2; -- STMT_DELETE_ACTUAL_NODE delete from actual_node @@ -319,43 +390,47 @@ UPDATE BASE_NODE SET depth = ?3 WHERE wc_id = ?1 AND local_relpath = ?2; -- STMT_UPDATE_NODE_BASE_DEPTH -UPDATE NODE_DATA SET depth = ?3 -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0; +update NODES set depth = ?3 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_UPDATE_WORKING_DEPTH UPDATE WORKING_NODE SET depth = ?3 WHERE wc_id = ?1 AND local_relpath = ?2; -- STMT_UPDATE_NODE_WORKING_DEPTH -UPDATE NODE_DATA SET depth = ?3 -WHERE wc_id = ?1 AND local_relpath = ?2 AND - op_depth IN (SELECT MAX(op_depth) FROM NODE_DATA - WHERE wc_id = ?1 AND local_relpath = ?2); +update NODES set depth = ?3 +where wc_id = ?1 and local_relpath = ?2 and + op_depth in (select op_depth from NODES + where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 + order by op_depth desc + limit 1); -- STMT_UPDATE_BASE_EXCLUDED UPDATE BASE_NODE SET presence = 'excluded', depth = NULL WHERE wc_id = ?1 AND local_relpath = ?2; -- STMT_UPDATE_NODE_BASE_EXCLUDED -UPDATE NODE_DATA SET presence = 'excluded', depth = NULL -WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0; +update NODES set presence = 'excluded', depth = NULL +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_UPDATE_WORKING_EXCLUDED UPDATE WORKING_NODE SET presence = 'excluded', depth = NULL WHERE wc_id = ?1 AND local_relpath = ?2; -- STMT_UPDATE_NODE_WORKING_EXCLUDED -UPDATE NODE_DATA SET presence = 'excluded', depth = NULL -WHERE wc_id = ?1 AND local_relpath = ?2 AND - op_depth IN (SELECT MAX(op_depth) FROM NODE_DATA - WHERE wc_id = ?1 AND local_relpath = ?2); +update nodes SET presence = 'excluded', depth = NULL +where wc_id = ?1 and local_relpath = ?2 and + op_depth IN (select op_depth from NODES + where wc_id = ?1 and local_relpath = ?2 + order by op_depth DECSC + limit 1); -- STMT_UPDATE_BASE_PRESENCE update base_node set presence= ?3 where wc_id = ?1 and local_relpath = ?2; -- STMT_UPDATE_NODE_BASE_PRESENCE -update node_data set presence = ?3 +update nodes set presence = ?3 where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_UPDATE_BASE_PRESENCE_KIND @@ -363,7 +438,7 @@ update base_node set presence = ?3, kind where wc_id = ?1 and local_relpath = ?2; -- STMT_UPDATE_NODE_BASE_PRESENCE_KIND -update node_data set presence = ?3, kind = ?4 +update nodes set presence = ?3, kind = ?4 where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; -- STMT_UPDATE_WORKING_PRESENCE @@ -371,10 +446,10 @@ update working_node set presence = ?3 where wc_id = ?1 and local_relpath =?2; -- STMT_UPDATE_NODE_WORKING_PRESENCE -update node_data set presence = ?3 +update nodes set presence = ?3 where wc_id = ?1 and local_relpath = ?2 - and op_depth in (select op_depth from node_data - where wc_id = ?1 and local_relpath = ?2 + and op_depth in (select op_depth from nodes + where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 order by op_depth desc limit 1); @@ -382,10 +457,18 @@ where wc_id = ?1 and local_relpath = ?2 update base_node set presence = ?3, revnum = ?4 where wc_id = ?1 and local_relpath = ?2; +-- STMT_UPDATE_BASE_NODE_PRESENCE_AND_REVNUM +update nodes set presence = ?3, revision = ?4 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_UPDATE_BASE_PRESENCE_REVNUM_AND_REPOS_RELPATH update base_node set presence = ?3, revnum = ?4, repos_relpath = ?5 where wc_id = ?1 and local_relpath = ?2; +-- STMT_UPDATE_BASE_NODE_PRESENCE_REVNUM_AND_REPOS_PATH +update nodes set presence = ?3, revision = ?4, repos_path = ?5 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_LOOK_FOR_WORK SELECT id FROM WORK_QUEUE LIMIT 1; @@ -488,6 +571,14 @@ INSERT OR REPLACE INTO BASE_NODE ( depth, symlink_target, dav_cache) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16); +-- STMT_APPLY_CHANGES_TO_BASE_NODE +insert or replace into NODES ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, depth, kind, changed_revision, changed_date, + changed_author, checksum, properties, dav_cache, symlink_target ) +values (?1, ?2, 0, + ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16); + -- STMT_INSERT_WORKING_NODE_FROM_BASE_NODE INSERT INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind, checksum, @@ -498,6 +589,17 @@ SELECT wc_id, local_relpath, parent_relp symlink_target, last_mod_time FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_INSERT_WORKING_NODE_FROM_BASE +INSERT INTO NODES ( + wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum, + changed_revision, changed_date, changed_author, depth, symlink_target, + translated_size, last_mod_time, properties) +SELECT wc_id, local_relpath, ?3 as op_depth, parent_relpath, ?4 as presence, + kind, checksum, changed_revision, changed_date, changed_author, depth, + symlink_target, translated_size, last_mod_time, properties +FROM NODES +WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0; + -- STMT_INSERT_WORKING_NODE_NORMAL_FROM_BASE_NODE INSERT INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind, checksum, @@ -510,6 +612,20 @@ SELECT wc_id, local_relpath, parent_relp repos_relpath, revnum FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_INSERT_WORKING_NODE_NORMAL_FROM_BASE +insert into NODES ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, depth, kind, changed_revision, changed_date, + changed_author, checksum, properties, translated_size, last_mod_time, + symlink_target ) +select wc_id, local_relpath, ?3 as op_depth, parent_relpath, repos_id, + repos_path, revision, 'normal', depth, kind, changed_revision, + changed_date, changed_author, checksum, properties, translated_size, + last_mod_time, symlink_target +from NODES +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + + -- STMT_INSERT_WORKING_NODE_NOT_PRESENT_FROM_BASE_NODE INSERT INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind, changed_rev, @@ -520,6 +636,17 @@ SELECT wc_id, local_relpath, parent_relp repos_relpath, revnum FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_INSERT_WORKING_NODE_NOT_PRESENT_FROM_BASE +insert into NODES ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, kind, changed_revision, changed_date, changed_author ) +select wc_id, local_relpath, ?3 as op_depth, parent_relpath, repos_id, + repos_path, revision, 'not-present', kind, changed_revision, + changed_date, changed_author +from NODES +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + + -- ### the statement below should be setting copyfrom_revision! -- STMT_UPDATE_COPYFROM UPDATE WORKING_NODE set copyfrom_repos_id = ?3, copyfrom_repos_path = ?4 @@ -532,11 +659,34 @@ UPDATE WORKING_NODE SET copyfrom_revnum = null WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_UPDATE_COPYFROM_TO_INHERIT_1 +UPDATE NODES SET + repos_id = null, + repos_path = null, + revision = null +WHERE wc_id = ?1 AND local_relpath = ?2 + AND op_depth IN (SELECT op_depth FROM nodes + WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0 + ORDER BY op_depth DESC + LIMIT 1); + -- STMT_DETERMINE_TREE_FOR_RECORDING SELECT 0 FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2 UNION SELECT 1 FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_DETERMINE_TREE_FOR_RECORDING_1 +SELECT 0 FROM NODES WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0 +UNION +SELECT 1 FROM NODES WHERE wc_id = ?1 AND local_relpath = ?2 + AND op_depth IN (SELECT op_depth FROM nodes + WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0 + ORDER BY op_depth DESC + LIMIT 1); + + +/* ### Why can't this query not just use the BASE repository + location values, instead of taking 3 additional parameters?! */ -- STMT_INSERT_WORKING_NODE_COPY_FROM_BASE INSERT OR REPLACE INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind, checksum, @@ -549,6 +699,19 @@ SELECT wc_id, ?3 AS local_relpath, ?4 AS ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM BASE_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_INSERT_WORKING_NODE_COPY_FROM_BASE_1 +insert or replace into NODES ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, + repos_path, revision, presence, depth, kind, changed_revision, + changed_date, changed_author, checksum, properties, translated_size, + last_mod_time, symlink_target ) +select wc_id, ?3 as local_relpath, ?4 as op_depth, ?5 as parent_relpath, + ?6 as repos_id, ?7 as repos_path, ?8 as revision, ?9 as presence, depth, + kind, changed_revision, changed_date, changed_author, checksum, properties, + translated_size, last_mod_time, symlink_target +from NODES +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING INSERT OR REPLACE INTO WORKING_NODE ( wc_id, local_relpath, parent_relpath, presence, kind, checksum, @@ -561,6 +724,21 @@ SELECT wc_id, ?3 AS local_relpath, ?4 AS ?7 AS copyfrom_repos_path, ?8 AS copyfrom_revnum FROM WORKING_NODE WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_INSERT_WORKING_NODE_COPY_FROM_WORKING_1 +insert or replace into NODES ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, depth, kind, changed_revision, changed_date, + changed_author, checksum, properties, translated_size, last_mod_time, + symlink_target ) +select wc_id, ?3 as local_relpath, ?4 as op_depth, ?5 as parent_relpath, + ?6 as repos_id, ?7 as repos_path, ?8 as revision, ?9 as presence, depth, + kind, changed_revision, changed_date, changed_author, checksum, properties, + translated_size, last_mod_time, symlink_target +from NODES +where wc_id = ?1 and local_relpath = ?2 and op_depth > 0 +order by op_depth desc +limit 1; + -- STMT_INSERT_ACTUAL_NODE_FROM_ACTUAL_NODE INSERT OR REPLACE INTO ACTUAL_NODE ( wc_id, local_relpath, parent_relpath, properties, @@ -580,10 +758,18 @@ SELECT 0 FROM WORKING_NODE WHERE wc_id = UPDATE BASE_NODE SET revnum=?3 WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_UPDATE_BASE_REVISION_1 +update nodes set revision = ?3 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + -- STMT_UPDATE_BASE_REPOS UPDATE BASE_NODE SET repos_id = ?3, repos_relpath = ?4 WHERE wc_id = ?1 AND local_relpath = ?2; +-- STMT_UPDATE_BASE_REPOS_1 +update nodes set repos_id = ?3, repos_path = ?4 +where wc_id = ?1 and local_relpath = ?2 and op_depth = 0; + /* ------------------------------------------------------------------------- */ /* these are used in entries.c */ @@ -597,6 +783,16 @@ insert or replace into base_node ( values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16); +-- STMT_INSERT_BASE_NODE_FOR_ENTRY_1 +/* The BASE tree has a fixed op_depth '0' */ +insert or replace into nodes ( + wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path, + revision, presence, kind, checksum, + changed_revision, changed_date, changed_author, depth, properties, + translated_size, last_mod_time ) +values (?1, ?2, 0, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, + ?14, ?15, ?16 ); + -- STMT_INSERT_WORKING_NODE insert or replace into working_node ( wc_id, local_relpath, parent_relpath, presence, kind, @@ -607,6 +803,22 @@ insert or replace into working_node ( values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20); +-- STMT_INSERT_WORKING_NODE_DATA_1 +insert or replace into node_data ( + wc_id, local_relpath, op_depth, parent_relpath, presence, kind, + original_repos_id, original_repos_path, original_revision, checksum, + changed_revision, changed_date, changed_author, depth, properties, + symlink_target ) +values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, + ?10, ?11, ?12, ?13, ?14, ?15, ?16 ); + +-- STMT_INSERT_WORKING_NODE_DATA_2 +insert or replace into working_node ( + wc_id, local_relpath, parent_relpath, moved_here, moved_to, translated_size, + last_mod_time, keep_local ) +values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8 ); + + -- STMT_INSERT_ACTUAL_NODE insert or replace into actual_node ( wc_id, local_relpath, parent_relpath, properties, conflict_old, @@ -657,97 +869,18 @@ values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, update actual_node set tree_conflict_data = null; -- STMT_SELECT_ALL_FILES +/* Should this select on wc_id as well? */ SELECT local_relpath FROM BASE_NODE -WHERE kind = 'file' +WHERE kind = 'file' AND parent_relpath = ?1 UNION SELECT local_relpath FROM WORKING_NODE -WHERE kind = 'file'; +WHERE kind = 'file' AND parent_relpath = ?1; -- STMT_PLAN_PROP_UPGRADE SELECT 0, presence, wc_id FROM BASE_NODE WHERE local_relpath = ?1 UNION ALL SELECT 1, presence, wc_id FROM WORKING_NODE WHERE local_relpath = ?1; --- STMT_ATTACH_WCROOT_DB -/* ?1 is the path to the WC-root DB file to attach. */ -ATTACH ?1 AS root; - --- STMT_COPY_BASE_NODE_TABLE_TO_WCROOT_DB -/* Copy BASE_NODE to WC-root DB: first the '' row, then the rest. */ -/* ?1 is the wc_relpath of the subdirectory that we're processing. */ -/* ?2 is the wc_relpath of the parent of the subdir we're processing. */ -INSERT INTO root.BASE_NODE ( - wc_id, local_relpath, repos_id, repos_relpath, parent_relpath, - presence, - revnum, kind, checksum, translated_size, changed_rev, changed_date, - changed_author, depth, last_mod_time, properties ) -SELECT wc_id, ?1, - repos_id, repos_relpath, ?2 AS parent_relpath, presence, - revnum, kind, checksum, translated_size, changed_rev, changed_date, - changed_author, depth, last_mod_time, properties FROM BASE_NODE -WHERE local_relpath = ''; -INSERT INTO root.BASE_NODE ( - wc_id, local_relpath, repos_id, repos_relpath, parent_relpath, - presence, - revnum, kind, checksum, translated_size, changed_rev, changed_date, - changed_author, depth, last_mod_time, properties ) -SELECT wc_id, ?1 || '/' || local_relpath, - repos_id, repos_relpath, ?1 AS parent_relpath, presence, - revnum, kind, checksum, translated_size, changed_rev, changed_date, - changed_author, depth, last_mod_time, properties FROM BASE_NODE -WHERE local_relpath != ''; - --- STMT_COPY_WORKING_NODE_TABLE_TO_WCROOT_DB -INSERT INTO root.WORKING_NODE ( - wc_id, local_relpath, parent_relpath, presence, kind, checksum, - translated_size, changed_rev, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties, copyfrom_repos_id, - copyfrom_repos_path, copyfrom_revnum ) -SELECT wc_id, ?1, ?2 AS parent_relpath, - presence, kind, checksum, - translated_size, changed_rev, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties, copyfrom_repos_id, - copyfrom_repos_path, copyfrom_revnum FROM WORKING_NODE -WHERE local_relpath = ''; -INSERT INTO root.WORKING_NODE ( - wc_id, local_relpath, parent_relpath, presence, kind, checksum, - translated_size, changed_rev, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties, copyfrom_repos_id, - copyfrom_repos_path, copyfrom_revnum ) -SELECT wc_id, ?1 || '/' || local_relpath, ?1 AS parent_relpath, - presence, kind, checksum, - translated_size, changed_rev, changed_date, changed_author, depth, - symlink_target, last_mod_time, properties, copyfrom_repos_id, - copyfrom_repos_path, copyfrom_revnum FROM WORKING_NODE -WHERE local_relpath != ''; -/* TODO - maybe: WHERE kind != 'subdir'; */ - --- STMT_COPY_ACTUAL_NODE_TABLE_TO_WCROOT_DB -INSERT INTO root.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, ?1, ?2 AS parent_relpath, properties, - conflict_old, conflict_new, conflict_working, - prop_reject, changelist, text_mod, tree_conflict_data FROM ACTUAL_NODE -WHERE local_relpath = ''; -INSERT INTO root.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, ?1 || '/' || local_relpath, ?1 AS parent_relpath, properties, - conflict_old, conflict_new, conflict_working, - prop_reject, changelist, text_mod, tree_conflict_data FROM ACTUAL_NODE -WHERE local_relpath != ''; - --- STMT_COPY_LOCK_TABLE_TO_WCROOT_DB -INSERT INTO root.LOCK -SELECT * FROM LOCK; - --- STMT_COPY_PRISTINE_TABLE_TO_WCROOT_DB -INSERT INTO root.PRISTINE -SELECT * FROM PRISTINE; - /* ------------------------------------------------------------------------- */