Author: stsp
Date: Mon Feb 18 16:33:20 2013
New Revision: 1447380
URL: http://svn.apache.org/r1447380
Log:
Clear moved-here markers of nodes which were moved outside of a subtree
which is being deleted during an update.
Before this change, the move source node disappeared from the working
copy while the moved-here marker remained set at the destination, leaving
behind a dangling move.
Suggested by: philip
* subversion/libsvn_wc/wc-queries.sql
(STMT_CLEAR_MOVED_HERE_RECURSIVE): New. Clears moved-here on a node and
any moved-along children.
* subversion/libsvn_wc/wc_db.c
(clear_moved_here): New helper function.
(db_base_remove): When removing a conflicted node, clear moved-here markers
at the destinations of moves which moved nodes outside the conflicted node.
Add a FIXME comment explaining an alternative approach which we might want
to implement in 1.9 and beyond.
* subversion/tests/libsvn_wc/op-depth-test.c
(move_away_delete_update): This test now passes, so remove XFAIL marker.
Modified:
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1447380&r1=1447379&r2=1447380&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Mon Feb 18 16:33:20
2013
@@ -1499,6 +1499,12 @@ WHERE wc_id = ?1 AND local_relpath = ?2
UPDATE nodes SET moved_to = NULL
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
+-- STMT_CLEAR_MOVED_HERE_RECURSIVE
+UPDATE nodes SET moved_here = NULL
+WHERE wc_id = ?1
+ AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+ AND op_depth = ?3
+
/* This statement returns pairs of move-roots below the path ?2 in WC_ID ?1.
* Each row returns a moved-here path (always a child of ?2) in the first
* column, and its matching moved-away (deleted) path in the second column. */
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1447380&r1=1447379&r2=1447380&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Mon Feb 18 16:33:20 2013
@@ -2055,6 +2055,33 @@ svn_wc__db_base_add_not_present_node(svn
kind, svn_wc__db_status_not_present, conflict, work_items, scratch_pool);
}
+/* Recursively clear moved-here information at the copy-half of the move
+ * which moved the node at SRC_RELPATH away. This transforms the move into
+ * a simple copy. */
+static svn_error_t *
+clear_moved_here(const char *src_relpath,
+ svn_wc__db_wcroot_t *wcroot,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ const char *dst_relpath;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_MOVED_TO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ src_relpath, relpath_depth(src_relpath)));
+ SVN_ERR(svn_sqlite__step_row(stmt));
+ dst_relpath = svn_sqlite__column_text(stmt, 0, scratch_pool);
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_CLEAR_MOVED_HERE_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ dst_relpath, relpath_depth(dst_relpath)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+
+ return SVN_NO_ERROR;
+}
+
/* The body of svn_wc__db_base_remove().
*/
static svn_error_t *
@@ -2199,6 +2226,41 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
ACTUAL_NODE records */
/* Step 3: Delete WORKING nodes */
+ if (conflict)
+ {
+ apr_pool_t *iterpool;
+
+ /*
+ * When deleting a conflicted node, moves of any moved-outside children
+ * of the node must be broken. Else, the destination will still be marked
+ * moved-here after the move source disappears from the working copy.
+ *
+ * ### FIXME: It would be nicer to have the conflict resolver
+ * break the move instead. It might also be a good idea to
+ * flag a tree conflict on each moved-away child. But doing so
+ * might introduce actual-only nodes without direct parents,
+ * and we're not yet sure if other existing code is prepared
+ * to handle such nodes. To be revisited post-1.8.
+ */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_MOVED_OUTSIDE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+ local_relpath,
+ relpath_depth(local_relpath)));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ iterpool = svn_pool_create(scratch_pool);
+ while (have_row)
+ {
+ const char *child_relpath;
+
+ svn_pool_clear(iterpool);
+ child_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
+ clear_moved_here(child_relpath, wcroot, iterpool);
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+ svn_pool_destroy(iterpool);
+ svn_sqlite__reset(stmt);
+ }
if (keep_working)
{
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
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=1447380&r1=1447379&r2=1447380&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Mon Feb 18
16:33:20 2013
@@ -6842,7 +6842,7 @@ struct svn_test_descriptor_t test_funcs[
"commit_moved_away_descendant"),
SVN_TEST_OPTS_PASS(finite_move_update_bump,
"finite_move_update_bump"),
- SVN_TEST_OPTS_XFAIL(move_away_delete_update,
- "move_away_delete_update"),
+ SVN_TEST_OPTS_PASS(move_away_delete_update,
+ "move_away_delete_update"),
SVN_TEST_NULL
};