You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/11/05 15:19:32 UTC

svn commit: r1539007 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c

Author: rhuijben
Date: Tue Nov  5 14:19:32 2013
New Revision: 1539007

URL: http://svn.apache.org/r1539007
Log:
Apply more strict op_depth fixes to move handling to properly handle
shadowed moves.

* subversion/libsvn_wc/wc-queries.sql
  (STMT_SELECT_OP_DEPTH_MOVED_TO): Match the requested node with its direct
    shadowing move by a join.
  (STMT_SELECT_MOVED_HERE): Remove unused query.

* subversion/libsvn_wc/wc_db.c
  (clear_moved_here): Use the moved_to relative path, as that is unique,
    because the moved_from relpath doesn't have to be. This also allows
    removing a now unused query. Return error when the target is not found.
  (db_base_remove): Update caller. Use different column of existing query.

  (follow_moved_to): Simplify code, based on the new query. Don't hide moves
    that don't specify the same revision or repos_relpath. While they are
    out of sync they are still moves, that need to be tracked... or the
    conflict handling isn't able to resolve the problem.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.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=1539007&r1=1539006&r2=1539007&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Tue Nov  5 14:19:32 2013
@@ -425,24 +425,23 @@ WHERE work.wc_id = ?1 AND work.local_rel
 LIMIT 1
 
 -- STMT_SELECT_OP_DEPTH_MOVED_TO
-SELECT op_depth, moved_to, repos_path, revision
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2
- AND op_depth <= (SELECT MIN(op_depth) FROM nodes
-                  WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3)
-ORDER BY op_depth DESC
+SELECT n.op_depth, n.moved_to, p.repos_path, p.revision
+FROM nodes p
+LEFT JOIN nodes n
+  ON p.wc_id=n.wc_id AND p.local_relpath = n.local_relpath
+ AND  n.op_depth = (SELECT MIN(d.op_depth)
+                    FROM nodes d
+                    WHERE d.wc_id = ?1
+                      AND d.local_relpath = n.local_relpath
+                      AND d.op_depth > ?3)
+WHERE p.wc_id = ?1 AND p.local_relpath = ?2 AND p.op_depth = ?3
+LIMIT 1
 
 -- STMT_SELECT_MOVED_TO
 SELECT moved_to
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
 
--- STMT_SELECT_MOVED_HERE
-SELECT moved_here, presence, repos_path, revision
-FROM nodes
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth >= ?3
-ORDER BY op_depth
-
 -- STMT_SELECT_MOVED_BACK
 SELECT u.local_relpath,
        u.presence, u.repos_id, u.repos_path, u.revision,

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1539007&r1=1539006&r2=1539007&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Tue Nov  5 14:19:32 2013
@@ -2101,28 +2101,29 @@ svn_wc__db_base_add_not_present_node(svn
 }
 
 /* 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. */
+ * which moved a node to MOVED_TO_RELPATH. This transforms this side of the
+ * move into a simple copy.
+ */
 static svn_error_t *
-clear_moved_here(const char *src_relpath,
-                 svn_wc__db_wcroot_t *wcroot,
+clear_moved_here(svn_wc__db_wcroot_t *wcroot,
+                 const char *moved_to_relpath,
                  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));
+  int affected_rows;
 
   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));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, moved_to_relpath,
+                            relpath_depth(moved_to_relpath)));
+
+  SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+  if (affected_rows == 0)
+     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                              _("The node '%s' was not found."),
+                              path_for_error_message(wcroot, moved_to_relpath,
+                                                     scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2313,12 +2314,12 @@ db_base_remove(svn_wc__db_wcroot_t *wcro
       iterpool = svn_pool_create(scratch_pool);
       while (have_row)
         {
-          const char *child_relpath;
+          const char *moved_to_relpath;
           svn_error_t *err;
 
           svn_pool_clear(iterpool);
-          child_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
-          err = clear_moved_here(child_relpath, wcroot, iterpool);
+          moved_to_relpath = svn_sqlite__column_text(stmt, 1, iterpool);
+          err = clear_moved_here(wcroot, moved_to_relpath, iterpool);
           if (err)
             return svn_error_compose_create(err, svn_sqlite__reset(stmt));
           SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -12200,23 +12201,20 @@ svn_wc__db_scan_moved(const char **moved
 /* ###
  */
 static svn_error_t *
-follow_moved_to(apr_array_header_t **moved_tos,
-                int op_depth,
-                const char *repos_path,
-                svn_revnum_t revision,
-                svn_wc__db_wcroot_t *wcroot,
+follow_moved_to(svn_wc__db_wcroot_t *wcroot,
                 const char *local_relpath,
+                int op_depth,
+                apr_array_header_t **moved_tos,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
   int working_op_depth;
-  const char *ancestor_relpath, *node_moved_to = NULL;
+  const char *ancestor_relpath;
+  const char *node_moved_to = NULL;
   int i;
 
-  SVN_ERR_ASSERT((!op_depth && !repos_path) || (op_depth && repos_path));
-
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_OP_DEPTH_MOVED_TO));
   SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath,
@@ -12226,50 +12224,26 @@ follow_moved_to(apr_array_header_t **mov
     {
       working_op_depth = svn_sqlite__column_int(stmt, 0);
       node_moved_to = svn_sqlite__column_text(stmt, 1, result_pool);
-      if (!repos_path)
-        {
-          SVN_ERR(svn_sqlite__step(&have_row, stmt));
-          if (!have_row || svn_sqlite__column_revnum(stmt, 0))
-            return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
-                                     svn_sqlite__reset(stmt),
-                                     _("The base node '%s' was not found."),
-                                     path_for_error_message(wcroot,
-                                                            local_relpath,
-                                                            scratch_pool));
-          repos_path = svn_sqlite__column_text(stmt, 2, scratch_pool);
-          revision = svn_sqlite__column_revnum(stmt, 3);
-        }
-    }
-  SVN_ERR(svn_sqlite__reset(stmt));
 
-  if (node_moved_to)
-    {
-      svn_boolean_t have_row2;
+      if (node_moved_to)
+        {
+          struct svn_wc__db_moved_to_t *moved_to;
 
-      SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_MOVED_HERE));
-      SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, node_moved_to,
-                                relpath_depth(node_moved_to)));
-      SVN_ERR(svn_sqlite__step(&have_row2, stmt));
-      if (!have_row2 || !svn_sqlite__column_int(stmt, 0)
-          || revision != svn_sqlite__column_revnum(stmt, 3)
-          || strcmp(repos_path, svn_sqlite__column_text(stmt, 2, NULL)))
-        node_moved_to = NULL;
-      SVN_ERR(svn_sqlite__reset(stmt));
+          moved_to = apr_palloc(result_pool, sizeof(*moved_to));
+          moved_to->op_depth = working_op_depth;
+          moved_to->local_relpath = node_moved_to;
+          APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
+        }
     }
 
-  if (node_moved_to)
-    {
-      struct svn_wc__db_moved_to_t *moved_to;
-
-      moved_to = apr_palloc(result_pool, sizeof(*moved_to));
-      moved_to->op_depth = working_op_depth;
-      moved_to->local_relpath = node_moved_to;
-      APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
-    }
+  SVN_ERR(svn_sqlite__reset(stmt));
 
-  /* A working row with moved_to, or no working row, and we are done. */
-  if (node_moved_to || !have_row)
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                             _("The node '%s' was not found."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+  else if (node_moved_to)
     return SVN_NO_ERROR;
 
   /* Need to handle being moved via an ancestor. */
@@ -12284,55 +12258,29 @@ follow_moved_to(apr_array_header_t **mov
                                         STMT_SELECT_MOVED_TO));
       SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, ancestor_relpath,
                                 working_op_depth));
-      SVN_ERR(svn_sqlite__step(&have_row, stmt));
-      SVN_ERR_ASSERT(have_row);
+      SVN_ERR(svn_sqlite__step_row(stmt));
+
       ancestor_moved_to = svn_sqlite__column_text(stmt, 0, scratch_pool);
       SVN_ERR(svn_sqlite__reset(stmt));
       if (ancestor_moved_to)
         {
-          node_moved_to
-            = svn_relpath_join(ancestor_moved_to,
-                               svn_relpath_skip_ancestor(ancestor_relpath,
-                                                         local_relpath),
-                               result_pool);
-
-          SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                            STMT_SELECT_MOVED_HERE));
-          SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, node_moved_to,
-                                    relpath_depth(ancestor_moved_to)));
-          SVN_ERR(svn_sqlite__step(&have_row, stmt));
-          if (!have_row)
-            ancestor_moved_to = NULL;
-          else if (!svn_sqlite__column_int(stmt, 0))
-            {
-              svn_wc__db_status_t presence
-                = svn_sqlite__column_token(stmt, 1, presence_map);
-              if (presence != svn_wc__db_status_not_present)
-                ancestor_moved_to = NULL;
-              else
-                {
-                  SVN_ERR(svn_sqlite__step(&have_row, stmt));
-                  if (!have_row && !svn_sqlite__column_int(stmt, 0))
-                    ancestor_moved_to = NULL;
-                }
-            }
-          SVN_ERR(svn_sqlite__reset(stmt));
-          if (!ancestor_moved_to)
-            break;
-          /* verify repos_path points back? */
-        }
-      if (ancestor_moved_to)
-        {
           struct svn_wc__db_moved_to_t *moved_to;
 
+          node_moved_to
+              = svn_relpath_join(ancestor_moved_to,
+                                 svn_relpath_skip_ancestor(ancestor_relpath,
+                                                           local_relpath),
+                                 result_pool);
+
           moved_to = apr_palloc(result_pool, sizeof(*moved_to));
           moved_to->op_depth = working_op_depth;
           moved_to->local_relpath = node_moved_to;
           APR_ARRAY_PUSH(*moved_tos, struct svn_wc__db_moved_to_t *) = moved_to;
 
-          SVN_ERR(follow_moved_to(moved_tos, relpath_depth(ancestor_moved_to),
-                                  repos_path, revision, wcroot, node_moved_to,
-                                  result_pool, scratch_pool));
+          SVN_ERR(follow_moved_to(wcroot, node_moved_to,
+                                  relpath_depth(ancestor_moved_to),
+                                  moved_tos, result_pool, scratch_pool));
+
           break;
         }
     }
@@ -12360,9 +12308,9 @@ svn_wc__db_follow_moved_to(apr_array_hea
                               sizeof(struct svn_wc__db_moved_to_t *));
 
   /* ### Wrap in a transaction */
-  SVN_ERR(follow_moved_to(moved_tos, 0, NULL, SVN_INVALID_REVNUM,
-                          wcroot, local_relpath,
-                          result_pool, scratch_pool));
+  SVN_WC__DB_WITH_TXN(follow_moved_to(wcroot, local_relpath, 0, moved_tos,
+                                      result_pool, scratch_pool),
+                      wcroot);
 
   /* ### Convert moved_to to abspath */