You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/03/12 21:06:40 UTC

svn commit: r1299817 - /subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c

Author: stsp
Date: Mon Mar 12 20:06:40 2012
New Revision: 1299817

URL: http://svn.apache.org/viewvc?rev=1299817&view=rev
Log:
On the multi-layer-moves branch, retain move information during replace.

Before this change, replacing a moved-away node with a copy deleted the
moved-to relpath of the node from the DB row. So given a node such as
 2|A/B/C/D|base-deleted|X|
the result of replacing A/B with a copy that includes a C/D was this:
  2|A/B/C/D|normal||

With this change, the moved-to relpath is retained:
  2|A/B/C/D|normal|X|

See http://wiki.apache.org/subversion/MultiLayerMoves for details.

Note that, after the replacement, 'svn status' still doesn't show A/B/C/D
as having moved to X. This is probably because status only shows move
information for op-roots. This might need to be revisited... *grumble*
Though maybe this is fine as is?

* subversion/libsvn_wc/wc_db.c
  (insert_incomplete_children): Preserve the moved-to path while replacing
    working nodes. While here, introduce an iterpool.

Modified:
    subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c

Modified: subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c?rev=1299817&r1=1299816&r2=1299817&view=diff
==============================================================================
--- subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/multi-layer-moves/subversion/libsvn_wc/wc_db.c Mon Mar 12 20:06:40 2012
@@ -967,38 +967,72 @@ insert_incomplete_children(svn_sqlite__d
 {
   svn_sqlite__stmt_t *stmt;
   int i;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_t *moved_to_relpaths = apr_hash_make(scratch_pool);
 
   SVN_ERR_ASSERT(repos_path != NULL || op_depth > 0);
   SVN_ERR_ASSERT((repos_id != INVALID_REPOS_ID)
                  == (repos_path != NULL));
 
+  /* If we're inserting WORKING nodes, we might be replacing existing
+   * nodes which were moved-away. We need to retain the moved-to relpath of
+   * such nodes in order not to lose move information during replace. */
+  if (op_depth > 0)
+    {
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE));
+
+      for (i = children->nelts; i--; )
+        {
+          const char *name = APR_ARRAY_IDX(children, i, const char *);
+          svn_boolean_t have_row;
+
+          svn_pool_clear(iterpool);
+
+          SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id,
+                                    svn_relpath_join(local_relpath, name,
+                                                     iterpool)));
+          SVN_ERR(svn_sqlite__step(&have_row, stmt));
+          if (have_row && !svn_sqlite__column_is_null(stmt, 14))
+            apr_hash_set(moved_to_relpaths, name, APR_HASH_KEY_STRING,
+              svn_sqlite__column_text(stmt, 14, scratch_pool));
+        }
+
+      SVN_ERR(svn_sqlite__reset(stmt));
+    }
+
   SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
 
   for (i = children->nelts; i--; )
     {
       const char *name = APR_ARRAY_IDX(children, i, const char *);
 
-      SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsns",
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_sqlite__bindf(stmt, "isisnnrsnsnnnnnnnnnnsn",
                                 wc_id,
                                 svn_relpath_join(local_relpath, name,
-                                                 scratch_pool),
+                                                 iterpool),
                                 op_depth,
                                 local_relpath,
                                 revision,
                                 "incomplete", /* 8, presence */
-                                "unknown"));  /* 10, kind */
-
+                                "unknown",    /* 10, kind */
+                                /* 21, moved_to */
+                                apr_hash_get(moved_to_relpaths, name,
+                                             APR_HASH_KEY_STRING)));
       if (repos_id != INVALID_REPOS_ID)
         {
           SVN_ERR(svn_sqlite__bind_int64(stmt, 5, repos_id));
           SVN_ERR(svn_sqlite__bind_text(stmt, 6,
                                         svn_relpath_join(repos_path, name,
-                                                         scratch_pool)));
+                                                         iterpool)));
         }
 
       SVN_ERR(svn_sqlite__insert(NULL, stmt));
     }
 
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }