You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2013/01/18 14:56:30 UTC
svn commit: r1435138 - in /subversion/trunk/subversion:
libsvn_wc/update_editor.c libsvn_wc/wc-queries.sql libsvn_wc/wc.h
libsvn_wc/wc_db_update_move.c tests/cmdline/update_tests.py
tests/libsvn_wc/op-depth-test.c
Author: philip
Date: Fri Jan 18 13:56:30 2013
New Revision: 1435138
URL: http://svn.apache.org/viewvc?rev=1435138&view=rev
Log:
Handle delete conflicts during move-update by raising tree-conflicts
and converting modified trees to copies.
* subversion/libsvn_wc/wc_db_update_move.c
(tc_editor_delete): Handle delete conflicts.
(get_info): Return correct enum type.
* subversion/libsvn_wc/wc.h
(svn_wc__node_has_local_mods): New.
* subversion/libsvn_wc/update_editor.c
(node_has_local_mods): Renamed to ...
(svn_wc__node_has_local_mods): ... this, made non-static.
(check_tree_conflict): Adjust call.
* subversion/libsvn_wc/wc-queries.sql
(STMT_DELETE_WORKING_OP_DEPTH_ABOVE, STMT_UPDATE_OP_DEPTH_RECURSIVE): New.
* subversion/tests/libsvn_wc/op-depth-test.c
(move_update_delete_mods): New test.
(test_funcs): Add new test.
* subversion/tests/cmdline/update_tests.py
(update_moved_dir_leaf_del, update_moved_dir_file_add): Do non-recursive
resolves, expect delete-delete conflicts.
Modified:
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc.h
subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
subversion/trunk/subversion/tests/cmdline/update_tests.py
subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Jan 18 13:56:30 2013
@@ -1322,14 +1322,14 @@ modcheck_callback(void *baton,
* is set to true and all the local modifications were deletes then set
* *ALL_EDITS_ARE_DELETES to true, set it to false otherwise. LOCAL_ABSPATH
* may be a file or a directory. */
-static svn_error_t *
-node_has_local_mods(svn_boolean_t *modified,
- svn_boolean_t *all_edits_are_deletes,
- svn_wc__db_t *db,
- const char *local_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+svn_error_t *
+svn_wc__node_has_local_mods(svn_boolean_t *modified,
+ svn_boolean_t *all_edits_are_deletes,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
modcheck_baton_t modcheck_baton = { NULL, FALSE, FALSE };
svn_error_t *err;
@@ -1496,10 +1496,10 @@ check_tree_conflict(svn_skel_t **pconfli
* not visit the subdirectories of a directory that it wants to delete.
* Therefore, we need to start a separate crawl here. */
- SVN_ERR(node_has_local_mods(&modified, &all_mods_are_deletes,
- eb->db, local_abspath,
- eb->cancel_func, eb->cancel_baton,
- scratch_pool));
+ SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_mods_are_deletes,
+ eb->db, local_abspath,
+ eb->cancel_func, eb->cancel_baton,
+ scratch_pool));
if (modified)
{
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Jan 18 13:56:30 2013
@@ -226,6 +226,12 @@ WHERE wc_id = ?1
AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
AND op_depth = ?3
+-- STMT_DELETE_WORKING_OP_DEPTH_ABOVE
+DELETE FROM nodes
+WHERE wc_id = ?1
+ AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+ AND op_depth > ?3
+
-- STMT_SELECT_LOCAL_RELPATH_OP_DEPTH
SELECT local_relpath
FROM nodes
@@ -885,6 +891,12 @@ WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
AND op_depth = ?3
+-- STMT_UPDATE_OP_DEPTH_RECURSIVE
+UPDATE nodes SET op_depth = ?4, moved_here = NULL
+WHERE wc_id = ?1
+ AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+ AND op_depth = ?3
+
-- STMT_DOES_NODE_EXIST
SELECT 1 FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2
LIMIT 1
Modified: subversion/trunk/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Fri Jan 18 13:56:30 2013
@@ -783,6 +783,15 @@ svn_wc__revert_internal(svn_wc__db_t *db
void *notify_baton,
apr_pool_t *scratch_pool);
+svn_error_t *
+svn_wc__node_has_local_mods(svn_boolean_t *modified,
+ svn_boolean_t *all_edits_are_deletes,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Fri Jan 18 13:56:30 2013
@@ -843,6 +843,52 @@ tc_editor_delete(void *baton,
svn_wc_conflict_action_delete,
scratch_pool));
+ if (!is_conflicted)
+ {
+ svn_boolean_t is_modified, is_all_deletes;
+
+ SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, b->db,
+ svn_dirent_join(b->wcroot->abspath,
+ relpath,
+ scratch_pool),
+ NULL, NULL, scratch_pool));
+ if (is_modified)
+ {
+ /* No conflict means no NODES rows at the relpath op-depth
+ so it's easy to convert the modified tree into a copy. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ STMT_UPDATE_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
+ op_depth, relpath_depth(relpath)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ SVN_ERR(mark_tree_conflict(b, relpath,
+ /* ### kinds? */
+ svn_node_dir, svn_node_dir,
+ svn_wc_conflict_reason_edited,
+ svn_wc_conflict_action_delete, NULL,
+ scratch_pool));
+ is_conflicted = TRUE;
+ }
+ else if (is_all_deletes)
+ {
+ SVN_ERR(mark_tree_conflict(b, relpath,
+ /* ### kinds? */
+ svn_node_dir, svn_node_dir,
+ svn_wc_conflict_reason_deleted,
+ svn_wc_conflict_action_delete, NULL,
+ scratch_pool));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+ STMT_DELETE_WORKING_OP_DEPTH_ABOVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
+ op_depth));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ is_conflicted = TRUE;
+ }
+ }
+
/* Deleting the ROWS is valid so long as we update the parent before
committing the transaction. */
SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
@@ -1047,7 +1093,7 @@ get_info(apr_hash_t **props,
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
{
svn_error_clear(err);
- *kind = svn_node_none;
+ *kind = svn_kind_none;
}
else
SVN_ERR(err);
Modified: subversion/trunk/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/update_tests.py?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/update_tests.py Fri Jan 18 13:56:30 2013
@@ -5462,14 +5462,15 @@ def update_moved_dir_leaf_del(sbox):
None, None, None,
None, None, 1)
- # Now resolve the conflict, using --accept=mine-conflict.
- # This should apply the update to A/B/E2, deleting A/B/E2/alpha.
+ # Now resolve the conflict, using --accept=mine-conflict applying
+ # the update to A/B/E2 causing a delete-delete conflict
svntest.actions.run_and_verify_svn("resolve failed", None, [],
'resolve',
- '--recursive',
- '--accept=mine-conflict', wc_dir)
+ '--accept=mine-conflict',
+ sbox.ospath('A/B/E'))
expected_status.tweak('A/B/E', treeconflict=None)
- expected_status.remove('A/B/E2/alpha')
+ expected_status.tweak('A/B/E2/alpha', status='? ', treeconflict='C',
+ copied=None, wc_rev=None)
svntest.actions.run_and_verify_status(wc_dir, expected_status)
@XFail()
@@ -5581,8 +5582,8 @@ def update_moved_dir_file_add(sbox):
# This should apply the update to A/B/E2, adding A/B/E2/foo.
svntest.actions.run_and_verify_svn("resolve failed", None, [],
'resolve',
- '--recursive',
- '--accept=mine-conflict', wc_dir)
+ '--accept=mine-conflict',
+ sbox.ospath('A/B/E'))
# the incoming file should auto-merge
expected_status.tweak('A/B/E', treeconflict=None)
expected_status.add({
@@ -5697,15 +5698,15 @@ def update_moved_dir_file_move(sbox):
# The incoming change is a delete as we don't yet track server-side
# moves. Resolving the tree-conflict as "mine-conflict" applies the
- # delete to the move destination. This is effectively accepting the
- # move from the server.
+ # delete to the move destination creating a delete-delete conflict.
svntest.actions.run_and_verify_svn("resolve failed", None, [],
'resolve',
- '--recursive',
- '--accept=mine-conflict', wc_dir)
+ '--accept=mine-conflict',
+ sbox.ospath('A/B/E'))
expected_status.tweak('A/B/E', treeconflict=None)
- expected_status.remove('A/B/E2/alpha')
+ expected_status.tweak('A/B/E2/alpha', status='? ', treeconflict='C',
+ copied=None, wc_rev=None)
svntest.actions.run_and_verify_status(wc_dir, expected_status)
Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1435138&r1=1435137&r2=1435138&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Fri Jan 18 13:56:30 2013
@@ -5624,6 +5624,72 @@ move_update_conflicts(const svn_test_opt
return SVN_NO_ERROR;
}
+static svn_error_t *
+move_update_delete_mods(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_update_delete_mods", opts, pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B/D"));
+ sbox_file_write(&b, "A/B/C/f", "r1 content\n");
+ SVN_ERR(sbox_wc_add(&b, "A/B/C/f"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_delete(&b, "A/B/D"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B2"));
+ sbox_file_write(&b, "B2/C/f", "modified content\n");
+ SVN_ERR(sbox_wc_delete(&b, "B2/D"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+ {0, "A/B/C", "normal", 1, "A/B/C"},
+ {0, "A/B/C/f", "normal", 1, "A/B/C/f"},
+ {0, "A/B/D", "normal", 1, "A/B/D"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/C/f", "base-deleted", NO_COPY_FROM},
+ {2, "A/B/D", "base-deleted", NO_COPY_FROM},
+ {1, "B2", "normal", 1, "A/B", MOVED_HERE},
+ {1, "B2/C", "normal", 1, "A/B/C", MOVED_HERE},
+ {1, "B2/C/f", "normal", 1, "A/B/C/f", MOVED_HERE},
+ {1, "B2/D", "normal", 1, "A/B/D", MOVED_HERE},
+ {2, "B2/D", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_update(&b, "A", 2));
+ SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_wc_conflict_choose_mine_conflict));
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 2, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {2, "A/B", "base-deleted", NO_COPY_FROM, "B2"},
+ {1, "B2", "normal", 2, "A/B", MOVED_HERE},
+ {2, "B2/C", "normal", 1, "A/B/C"},
+ {2, "B2/C/f", "normal", 1, "A/B/C/f"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(check_tree_conflict_repos_path(&b, "B2/C", "A/B/C", "A/B/C"));
+ SVN_ERR(check_tree_conflict_repos_path(&b, "B2/D", "A/B/D", "A/B/D"));
+
+ return SVN_NO_ERROR;
+}
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -5731,5 +5797,7 @@ struct svn_test_descriptor_t test_funcs[
"nested_move_update2"),
SVN_TEST_OPTS_PASS(move_update_conflicts,
"move_update_conflicts"),
+ SVN_TEST_OPTS_PASS(move_update_delete_mods,
+ "move_update_delete_mods"),
SVN_TEST_NULL
};