Author: rhuijben
Date: Thu Feb 5 15:08:43 2015
New Revision: 1657599
URL: http://svn.apache.org/r1657599
Log:
Make the move-update bumping code properly ignore not-present nodes
on the move target. These nodes can exist when moving a node with
not-present nodes (like after a commit, svn up -r 0), or when a mixed
revision tree would be recorded as move.
* subversion/libsvn_wc/wc-queries.sql
(STMT_SELECT_LAYER_FOR_REPLACE): Extend query to obtain info about current
data at destination.
(STMT_SELECT_CHILDREN_OP_DEPTH): Rename to...
(STMT_SELECT_DESCENDANTS_OP_DEPTH_RV): ... this to document that it selects
more than immediate children. Ignore not-present nodes.
* subversion/libsvn_wc/wc_db.c
(svn_wc__db_extend_parent_delete): Add optional output argument.
(insert_base_node): Update caller.
* subversion/libsvn_wc/wc_db_private.h
(svn_wc__db_extend_parent_delete): Add optional output argument.
* subversion/libsvn_wc/wc_db_update_move.c
(tc_editor_delete): Update query user.
(update_moved_away_node): Update caller.
(replace_moved_layer): Use improved query. Add some still commented logic
detecting cases where a new node is added unshadowed, which in some
cases need special handling.
Modified:
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/libsvn_wc/wc_db_private.h
subversion/trunk/subversion/libsvn_wc/wc_db_update_move.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=1657599&r1=1657598&r2=1657599&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Thu Feb 5 15:08:43
2015
@@ -263,24 +263,35 @@ 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, kind
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
+/* Full layer replacement check code for handling moves
+The op_root must exist (or there is no layer to replace) and an op-root
+ always has presence 'normal' */
+-- STMT_SELECT_LAYER_FOR_REPLACE
+SELECT s.local_relpath, s.kind,
+ RELPATH_SKIP_JOIN(?2, ?4, s.local_relpath) drp, 'normal', 0
+FROM nodes s
+WHERE s.wc_id = ?1 AND s.local_relpath = ?2 AND s.op_depth = ?3
UNION ALL
-SELECT local_relpath, kind
-FROM nodes
-WHERE wc_id = ?1
- AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
- AND op_depth = ?3
-ORDER BY local_relpath
+SELECT s.local_relpath, s.kind,
+ RELPATH_SKIP_JOIN(?2, ?4, s.local_relpath) drp, d.presence,
+ EXISTS(SELECT * FROM nodes sh
+ WHERE sh.wc_id = ?1 AND sh.op_depth > ?5
+ AND sh.local_relpath = d.local_relpath) shadowed
+FROM nodes s
+LEFT OUTER JOIN nodes d ON d.wc_id= ?1 AND d.op_depth = ?5
+ AND d.local_relpath = drp
+WHERE s.wc_id = ?1
+ AND IS_STRICT_DESCENDANT_OF(s.local_relpath, ?2)
+ AND s.op_depth = ?3
+ORDER BY s.local_relpath
--- STMT_SELECT_CHILDREN_OP_DEPTH
+-- STMT_SELECT_DESCENDANTS_OP_DEPTH_RV
SELECT local_relpath, kind
FROM nodes
WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
AND op_depth = ?3
+ AND presence = MAP_NORMAL
ORDER BY local_relpath DESC
-- STMT_COPY_NODE_MOVE
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1657599&r1=1657598&r2=1657599&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Feb 5 15:08:43 2015
@@ -570,7 +570,8 @@ blank_ibb(insert_base_baton_t *pibb)
svn_error_t *
-svn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
+svn_wc__db_extend_parent_delete(svn_boolean_t *added_delete,
+ svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_node_kind_t kind,
int op_depth,
@@ -583,6 +584,9 @@ svn_wc__db_extend_parent_delete(svn_wc__
SVN_ERR_ASSERT(local_relpath[0]);
+ if (added_delete)
+ *added_delete = FALSE;
+
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
STMT_SELECT_LOWEST_WORKING_NODE));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, parent_relpath,
@@ -609,6 +613,9 @@ svn_wc__db_extend_parent_delete(svn_wc__
local_relpath, parent_op_depth,
parent_relpath, kind_map, kind));
SVN_ERR(svn_sqlite__update(NULL, stmt));
+
+ if (added_delete)
+ *added_delete = TRUE;
}
}
@@ -833,7 +840,8 @@ insert_base_node(const insert_base_baton
|| (pibb->status == svn_wc__db_status_incomplete))
&& ! pibb->file_external)
{
- SVN_ERR(svn_wc__db_extend_parent_delete(wcroot, local_relpath,
+ SVN_ERR(svn_wc__db_extend_parent_delete(NULL,
+ wcroot, local_relpath,
pibb->kind, 0,
scratch_pool));
}
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_private.h?rev=1657599&r1=1657598&r2=1657599&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_private.h Thu Feb 5 15:08:43
2015
@@ -432,9 +432,13 @@ svn_wc__db_get_children_op_depth(apr_has
In the example above A/B/C/D and A/B/C/D/E are the nodes that get
the extended delete, A/B/C is already deleted.
+
+ If ADDED_DELETE is not NULL, set *ADDED_DELETE to TRUE if a new delete
+ was recorded, otherwise to FALSE.
*/
svn_error_t *
-svn_wc__db_extend_parent_delete(svn_wc__db_wcroot_t *wcroot,
+svn_wc__db_extend_parent_delete(svn_boolean_t *added_delete,
+ svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
svn_node_kind_t kind,
int op_depth,
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=1657599&r1=1657598&r2=1657599&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Thu Feb 5
15:08:43 2015
@@ -1171,8 +1171,10 @@ tc_editor_delete(update_move_baton_t *b,
svn_node_kind_t del_kind;
const char *del_abspath;
+ /* Get all descendants of the node in reverse order (so children are
+ handled before their parents, but not strictly depth first) */
SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
- STMT_SELECT_CHILDREN_OP_DEPTH));
+ STMT_SELECT_DESCENDANTS_OP_DEPTH_RV));
SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath,
op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -1541,8 +1543,9 @@ update_moved_away_node(update_move_baton
if (shadowed)
{
SVN_ERR(svn_wc__db_extend_parent_delete(
+ NULL,
b->wcroot, dst_relpath, src_kind,
- relpath_depth(b->move_root_dst_relpath),
+ relpath_depth(b->move_root_dst_relpath),
scratch_pool));
}
if (src_kind == svn_node_file || src_kind == svn_node_symlink)
@@ -1656,60 +1659,111 @@ update_moved_away_node(update_move_baton
rooted at DST_RELPATH to make it match the move source subtree
rooted at SRC_RELPATH. */
static svn_error_t *
-replace_moved_layer(const char *src_relpath,
- const char *dst_relpath,
+replace_moved_layer(const char *src_op_relpath,
+ const char *dst_op_relpath,
int src_op_depth,
svn_wc__db_wcroot_t *wcroot,
apr_pool_t *scratch_pool)
{
- svn_sqlite__stmt_t *stmt;
+ svn_sqlite__stmt_t *stmt, *stmt2;
svn_boolean_t have_row;
- int dst_op_depth = relpath_depth(dst_relpath);
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ int dst_op_depth = relpath_depth(dst_op_relpath);
+ svn_error_t *err = NULL;
- SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool));
- SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool));
+ SVN_ERR(verify_write_lock(wcroot, src_op_relpath, scratch_pool));
+ SVN_ERR(verify_write_lock(wcroot, dst_op_relpath, scratch_pool));
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt2, wcroot->sdb,
+ STMT_COPY_NODE_MOVE));
/* Replace entire subtree at one op-depth. */
SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_LOCAL_RELPATH_OP_DEPTH));
- SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
- src_relpath, src_op_depth));
+ STMT_SELECT_LAYER_FOR_REPLACE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdsd", wcroot->wc_id,
+ src_op_relpath, src_op_depth,
+ dst_op_relpath, dst_op_depth));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
while (have_row)
{
- svn_error_t *err;
- svn_sqlite__stmt_t *stmt2;
- const char *src_cp_relpath = svn_sqlite__column_text(stmt, 0, NULL);
- svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
- const char *dst_cp_relpath
- = svn_relpath_join(dst_relpath,
- svn_relpath_skip_ancestor(src_relpath,
- src_cp_relpath),
- scratch_pool);
+ const char *src_relpath;
+ const char *dst_relpath;
+ svn_boolean_t exists;
- err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
- STMT_COPY_NODE_MOVE);
- if (!err)
- err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
- src_cp_relpath, src_op_depth,
- dst_cp_relpath, dst_op_depth,
- svn_relpath_dirname(dst_cp_relpath,
- scratch_pool));
+ svn_pool_clear(iterpool);
+
+ src_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
+ dst_relpath = svn_sqlite__column_text(stmt, 2, iterpool);
+
+ exists = !svn_sqlite__column_is_null(stmt, 3);
+
+ err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
+ src_relpath, src_op_depth,
+ dst_relpath, dst_op_depth,
+ svn_relpath_dirname(dst_relpath, iterpool));
if (!err)
err = svn_sqlite__step_done(stmt2);
- if (!err && strlen(dst_cp_relpath) > strlen(dst_relpath))
- err = svn_wc__db_extend_parent_delete(wcroot, dst_cp_relpath, kind,
- dst_op_depth, scratch_pool);
+ /* stmt2 is reset (never modified or by step_done) */
if (err)
- return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ break;
+
+ if (strlen(dst_relpath) > strlen(dst_op_relpath))
+ {
+ svn_boolean_t added_delete = FALSE;
+ svn_node_kind_t kind = svn_sqlite__column_token(stmt, 1, kind_map);
+
+ /* The op root can't be shadowed, so extension of a parent delete
+ is only needed when the parent can be deleted */
+ if (relpath_depth(dst_relpath) > (dst_op_depth+1))
+ {
+ err = svn_wc__db_extend_parent_delete(&added_delete,
+ wcroot, dst_relpath, kind,
+ dst_op_depth, iterpool);
+
+ if (err)
+ break;
+ }
+
+ if (exists)
+ {
+ svn_wc__db_status_t presence;
+
+ presence = svn_sqlite__column_token(stmt, 3, presence_map);
+
+ if (presence == svn_wc__db_status_not_present)
+ exists = FALSE;
+ }
+
+ /* ### Fails in a few tests... Needs further research */
+ /*SVN_ERR_ASSERT(!(exists && added_delete));*/
+
+ if (!exists)
+ {
+ svn_boolean_t shadowed;
+
+ shadowed = svn_sqlite__column_int(stmt, 4);
+
+ /*if (!shadowed && !added_delete)
+ {
+ err = svn_error_createf(
+ SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+ _("Node '%s' was unexpectedly added unshadowed"),
+ path_for_error_message(wcroot, dst_relpath,
+ iterpool));
+ break;
+ }*/
+ }
+ }
SVN_ERR(svn_sqlite__step(&have_row, stmt));
}
- SVN_ERR(svn_sqlite__reset(stmt));
- return SVN_NO_ERROR;
+ svn_pool_destroy(iterpool);
+
+ return svn_error_trace(svn_error_compose_create(err,
+ svn_sqlite__reset(stmt)));
}
/* Transfer changes from the move source to the move destination.