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.


Reply via email to