Author: philip Date: Thu Dec 16 16:01:35 2010 New Revision: 1050019 URL: http://svn.apache.org/viewvc?rev=1050019&view=rev Log: Make upgrades handle revert properties for working-only replaced files.
* subversion/libsvn_wc/wc-queries.sql (STMT_PLAN_PROP_UPGRADE): Remove. (STMT_SELECT_NODE_UPGRADE, STMT_UPDATE_NODE_PROPS): New. * subversion/libsvn_wc/wc_db.c (prop_upgrade_trees): Remove. (svn_wc__db_upgrade_apply_props): Handle revert-props for working-only replaces. * subversion/tests/cmdline/upgrade_tests.py (replaced_files): New. (test_list): Mark replaced_files PASS. * subversion/tests/cmdline/upgrade_tests_data/replaced-files.tar.bz2: New. Added: subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/replaced-files.tar.bz2 (with props) Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql subversion/trunk/subversion/libsvn_wc/wc_db.c subversion/trunk/subversion/tests/cmdline/upgrade_tests.py Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1050019&r1=1050018&r2=1050019&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu Dec 16 16:01:35 2010 @@ -712,14 +712,15 @@ 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; Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1050019&r1=1050018&r2=1050019&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/wc_db.c (original) +++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Dec 16 16:01:35 2010 @@ -1244,73 +1244,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, @@ -7094,12 +7027,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. @@ -7129,19 +7060,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. */ @@ -7154,48 +7097,44 @@ 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, 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. */ Modified: subversion/trunk/subversion/tests/cmdline/upgrade_tests.py URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests.py?rev=1050019&r1=1050018&r2=1050019&view=diff ============================================================================== --- subversion/trunk/subversion/tests/cmdline/upgrade_tests.py (original) +++ subversion/trunk/subversion/tests/cmdline/upgrade_tests.py Thu Dec 16 16:01:35 2010 @@ -754,6 +754,47 @@ def delete_in_copy_upgrade(sbox): }) run_and_verify_status_no_server(sbox.wc_dir, expected_status) +def replaced_files(sbox): + "upgrade with base and working replaced files" + + sbox.build(create_wc = False) + wc_dir = sbox.wc_dir + replace_sbox_with_tarfile(sbox, 'replaced-files.tar.bz2') + + svntest.actions.run_and_verify_svn(None, None, [], + 'upgrade', sbox.wc_dir) + + # A/f is a base file that is replaced with a copy of A/g, B is a + # working-only copy of A, and B/f is a working-only file replaced + # with a copy of A/g + expected_status = svntest.wc.State(sbox.wc_dir, + { + '' : Item(status=' ', wc_rev='5'), + 'A' : Item(status=' ', wc_rev='5'), + 'A/f' : Item(status='R ', wc_rev='-', copied='+'), + 'A/g' : Item(status=' ', wc_rev='5'), + 'B' : Item(status='A ', wc_rev='-', copied='+'), + 'B/f' : Item(status='R ', wc_rev='-', copied='+'), + 'B/g' : Item(status=' ', wc_rev='-', copied='+'), + }) + run_and_verify_status_no_server(sbox.wc_dir, expected_status) + + simple_property_verify(sbox.wc_dir, { + 'A/f' : {'pAg' : 'vAg' }, + 'A/g' : {'pAg' : 'vAg' }, + 'B/f' : {'pAg' : 'vAg' }, + 'B/g' : {'pAg' : 'vAg' }, + }) + + svntest.actions.run_and_verify_svn(None, 'Reverted.*', [], 'revert', + sbox.ospath('A/f'), sbox.ospath('B/f')) + + simple_property_verify(sbox.wc_dir, { + 'A/f' : {'pAf' : 'vAf' }, + 'A/g' : {'pAg' : 'vAg' }, + 'B/f' : {'pAf' : 'vAf' }, + 'B/g' : {'pAg' : 'vAg' }, + }) ######################################################################## # Run the tests @@ -778,6 +819,7 @@ test_list = [ None, dirs_only_upgrade, upgrade_tree_conflict_data, delete_in_copy_upgrade, + replaced_files, ] Added: subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/replaced-files.tar.bz2 URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/replaced-files.tar.bz2?rev=1050019&view=auto ============================================================================== Binary file - no diff available. Propchange: subversion/trunk/subversion/tests/cmdline/upgrade_tests_data/replaced-files.tar.bz2 ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream