You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2011/02/21 18:53:42 UTC

svn commit: r1073093 - in /subversion/trunk/subversion: libsvn_wc/wc-queries.sql libsvn_wc/wc_db.c libsvn_wc/wc_db.h tests/libsvn_wc/op-depth-test.c

Author: philip
Date: Mon Feb 21 17:53:41 2011
New Revision: 1073093

URL: http://svn.apache.org/viewvc?rev=1073093&view=rev
Log:
Start a new recursive revert implementation, the library and client
still use the old implementation.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_op_revert): Add depth parameter

* subversion/libsvn_wc/wc_db.c
  (op_revert_recursive_txn): New.
  (svn_wc__db_op_revert): Add depth parameter

* subversion/libsvn_wc/wc-queries.sql
  (STMT_DELETE_NODES_RECURSIVE, STMT_DELETE_ACTUAL_NODE_RECURSIVE): New.

* subversion/tests/libsvn_wc/op-depth-test.c
  (revert): Add depth parameter.
  (test_op_revert): Adjust calls to revert, add recursive cases.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h
    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=1073093&r1=1073092&r2=1073093&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Mon Feb 21 17:53:41 2011
@@ -338,10 +338,19 @@ WHERE wc_id = ?1 AND local_relpath = ?2 
 DELETE FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_DELETE_NODES_RECURSIVE
+DELETE FROM nodes
+WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#')
+  AND op_depth >= ?4;
+
 -- STMT_DELETE_ACTUAL_NODE
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_DELETE_ACTUAL_NODE_RECURSIVE
+DELETE FROM actual_node
+WHERE wc_id = ?1 AND (local_relpath = ?2 OR local_relpath LIKE ?3 ESCAPE '#');
+
 -- STMT_DELETE_ACTUAL_NODE_WITHOUT_CONFLICT
 DELETE FROM actual_node
 WHERE wc_id = ?1 AND local_relpath = ?2

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1073093&r1=1073092&r2=1073093&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Mon Feb 21 17:53:41 2011
@@ -3556,6 +3556,9 @@ op_revert_txn(void *baton, svn_sqlite__d
   apr_int64_t op_depth;
   int affected_rows;
 
+  /* ### Similar structure to op_revert_recursive_txn, should they be
+         combined? */
+
   SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
                                     STMT_DELETE_ACTUAL_NODE));
   SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id,
@@ -3646,21 +3649,104 @@ op_revert_txn(void *baton, svn_sqlite__d
 }
 
 
+static svn_error_t *
+op_revert_recursive_txn(void *baton,
+                        svn_sqlite__db_t *sdb,
+                        apr_pool_t *scratch_pool)
+{
+  struct op_revert_baton *b = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_int64_t op_depth;
+  int affected_rows;
+
+  /* ### Similar structure to op_revert_txn, should they be
+         combined? */
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_DELETE_ACTUAL_NODE_RECURSIVE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "iss", b->wcroot->wc_id,
+                            b->local_relpath,
+                            construct_like_arg(b->local_relpath,
+                                               scratch_pool)));
+  SVN_ERR(svn_sqlite__step(&affected_rows, stmt));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_SELECT_NODE_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id,
+                            b->local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (!have_row)
+    {
+      SVN_ERR(svn_sqlite__reset(stmt));
+      if (affected_rows)
+        return SVN_NO_ERROR;  /* actual-only revert */
+
+      return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                               _("The node '%s' was not found."),
+                               path_for_error_message(b->wcroot,
+                                                      b->local_relpath,
+                                                      scratch_pool));
+    }
+
+  op_depth = svn_sqlite__column_int64(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  if (op_depth > 0 && op_depth != relpath_depth(b->local_relpath))
+    return svn_error_createf(SVN_ERR_WC_INVALID_OPERATION_DEPTH, NULL,
+                             _("Can't revert '%s' without"
+                               " reverting parent"),
+                             path_for_error_message(b->wcroot,
+                                                    b->local_relpath,
+                                                    scratch_pool));
+
+  if (!op_depth)
+    op_depth = 1; /* Don't delete BASE nodes */
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
+                                    STMT_DELETE_NODES_RECURSIVE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "issi", b->wcroot->wc_id,
+                            b->local_relpath,
+                            construct_like_arg(b->local_relpath,
+                                               scratch_pool),
+                            op_depth));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__db_op_revert(svn_wc__db_t *db,
                      const char *local_abspath,
+                     svn_depth_t depth,
                      apr_pool_t *scratch_pool)
 {
   struct op_revert_baton b;
+  svn_sqlite__transaction_callback_t txn_func;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
+  switch (depth)
+    {
+    case svn_depth_empty:
+      txn_func = op_revert_txn;
+      break;
+    case svn_depth_infinity:
+      txn_func = op_revert_recursive_txn;
+      break;
+    default:
+      return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                               _("Unsupported depth for revert of '%s'"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&b.wcroot, &b.local_relpath,
                               db, local_abspath, svn_sqlite__mode_readwrite,
                               scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(b.wcroot);
 
-  SVN_ERR(svn_sqlite__with_transaction(b.wcroot->sdb, op_revert_txn,
+  SVN_ERR(svn_sqlite__with_transaction(b.wcroot->sdb, txn_func,
                                        &b, scratch_pool));
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1073093&r1=1073092&r2=1073093&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Mon Feb 21 17:53:41 2011
@@ -1246,15 +1246,19 @@ svn_wc__db_op_revert_actual(svn_wc__db_t
 /* Revert all local changes which are being maintained in the database,
  * including conflict storage, properties and text modification status.
  *
- * This is a non-recursive operation.
- *
  * Returns SVN_ERR_WC_INVALID_OPERATION_DEPTH if the revert is not
  * possible, e.g. copy/delete but not a root, or a copy root with
  * children.
+ *
+ * At present only depth=empty and depth=infinity are supported.
+ *
+ * ### Need to return the modified paths for notification.  An array
+ * ### or hash?  A temporary SQLite table?
  */
 svn_error_t *
 svn_wc__db_op_revert(svn_wc__db_t *db,
                      const char *local_abspath,
+                     svn_depth_t depth,
                      apr_pool_t *scratch_pool);
 
 

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=1073093&r1=1073092&r2=1073093&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 21 17:53:41 2011
@@ -2024,6 +2024,7 @@ check_db_actual(wc_baton_t* b,
 static svn_error_t *
 revert(wc_baton_t *b,
        const char *local_relpath,
+       svn_depth_t depth,
        nodes_row_t *before_nodes,
        nodes_row_t *after_nodes,
        const char **before_actual,
@@ -2042,7 +2043,7 @@ revert(wc_baton_t *b,
   SVN_ERR(insert_actual(b, before_actual));
   SVN_ERR(check_db_rows(b, "", before_nodes));
   SVN_ERR(check_db_actual(b, before_actual));
-  err = svn_wc__db_op_revert(b->wc_ctx->db, local_abspath, b->pool);
+  err = svn_wc__db_op_revert(b->wc_ctx->db, local_abspath, depth, b->pool);
   if (err)
     {
       /* If db_op_revert returns an error the DB should be unchanged so
@@ -2091,15 +2092,22 @@ test_op_revert(const svn_test_opts_t *op
     const char *after_actual4[] = { "A/B", NULL };
     const char *common_actual5[] = { "A/B", "A/B/C", NULL };
     const char *common_actual6[] = { "A/B", "A/B/C", "A/B/C/D", NULL };
-    SVN_ERR(revert(&b, "A/B", before, after, NULL, NULL));
-    SVN_ERR(revert(&b, "A/B", before, after, before_actual1, after_actual1));
-    SVN_ERR(revert(&b, "A/B/C", before, before, before_actual2, after_actual2));
-    SVN_ERR(revert(&b, "A", before, before, before_actual3, after_actual3));
-    SVN_ERR(revert(&b, "", before, before, before_actual4, after_actual4));
-    err = revert(&b, "A/B", before, before, common_actual5, common_actual5);
+    SVN_ERR(revert(&b, "A/B", svn_depth_empty,
+                   before, after, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B", svn_depth_empty,
+                   before, after, before_actual1, after_actual1));
+    SVN_ERR(revert(&b, "A/B/C", svn_depth_empty,
+                   before, before, before_actual2, after_actual2));
+    SVN_ERR(revert(&b, "A", svn_depth_empty,
+                   before, before, before_actual3, after_actual3));
+    SVN_ERR(revert(&b, "", svn_depth_empty,
+                   before, before, before_actual4, after_actual4));
+    err = revert(&b, "A/B", svn_depth_empty,
+                 before, before, common_actual5, common_actual5);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "A/B/C", before, before, common_actual6, common_actual6);
+    err = revert(&b, "A/B/C", svn_depth_empty,
+                 before, before, common_actual6, common_actual6);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
   }
@@ -2121,38 +2129,48 @@ test_op_revert(const svn_test_opts_t *op
     };
     const char *common_actual[] = { "A/B/C/D", "A/B/C", "A/B", "P", "X", NULL};
 
-    err = revert(&b, "A/B/C/D", common, common, NULL, NULL);
+    err = revert(&b, "A/B/C/D", svn_depth_empty,
+                 common, common, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "A/B/C/D", common, common, common_actual, common_actual);
+    err = revert(&b, "A/B/C/D", svn_depth_empty,
+                 common, common, common_actual, common_actual);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
 
-    err = revert(&b, "A/B/C", common, common, NULL, NULL);
+    err = revert(&b, "A/B/C", svn_depth_empty,
+                 common, common, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "A/B/C", common, common, common_actual, common_actual);
+    err = revert(&b, "A/B/C", svn_depth_empty,
+                 common, common, common_actual, common_actual);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
 
-    err = revert(&b, "A/B", common, common, NULL, NULL);
+    err = revert(&b, "A/B", svn_depth_empty,
+                 common, common, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "A/B", common, common, common_actual, common_actual);
+    err = revert(&b, "A/B", svn_depth_empty,
+                 common, common, common_actual, common_actual);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
 
-    err = revert(&b, "P", common, common, NULL, NULL);
+    err = revert(&b, "P", svn_depth_empty,
+                 common, common, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "P", common, common, common_actual, common_actual);
+    err = revert(&b, "P", svn_depth_empty,
+                 common, common, common_actual, common_actual);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
 
-    err = revert(&b, "X", common, common, NULL, NULL);
+    err = revert(&b, "X", svn_depth_empty,
+                 common, common, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
-    err = revert(&b, "X", common, common, common_actual, common_actual);
+    err = revert(&b, "X", svn_depth_empty,
+                 common, common, common_actual, common_actual);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
   }
@@ -2175,8 +2193,10 @@ test_op_revert(const svn_test_opts_t *op
     };
     const char *before_actual[] = { "A/B", "A/B/C", NULL };
     const char *after_actual[] = {"A/B", NULL };
-    SVN_ERR(revert(&b, "A/B/C", before, after, NULL, NULL));
-    SVN_ERR(revert(&b, "A/B/C", before, after, before_actual, after_actual));
+    SVN_ERR(revert(&b, "A/B/C", svn_depth_empty,
+                   before, after, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B/C", svn_depth_empty,
+                   before, after, before_actual, after_actual));
   }
 
   {
@@ -2199,7 +2219,8 @@ test_op_revert(const svn_test_opts_t *op
       { 3, "A/B/C/D", "base-deleted", NO_COPY_FROM },
       { 0 },
     };
-    SVN_ERR(revert(&b, "A/B", before, after, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B", svn_depth_empty,
+                   before, after, NULL, NULL));
   }
 
   {
@@ -2236,8 +2257,10 @@ test_op_revert(const svn_test_opts_t *op
       { 1, "A/B/C",   "base-deleted", NO_COPY_FROM },
       { 0 },
     };
-    SVN_ERR(revert(&b, "A/B/C", before, after1, NULL, NULL));
-    SVN_ERR(revert(&b, "A/B", after1, after2, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B/C", svn_depth_empty,
+                   before, after1, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B", svn_depth_empty,
+                   after1, after2, NULL, NULL));
   }
 
   {
@@ -2262,7 +2285,8 @@ test_op_revert(const svn_test_opts_t *op
       { 3, "A/B/C/D", "base-deleted", NO_COPY_FROM },
       { 0 },
     };
-    SVN_ERR(revert(&b, "A/B", before, after, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B", svn_depth_empty,
+                   before, after, NULL, NULL));
   }
 
   {
@@ -2278,7 +2302,49 @@ test_op_revert(const svn_test_opts_t *op
       { 1, "A/B/C/D", "base-deleted", NO_COPY_FROM },
       { 0 },
     };
-    err = revert(&b, "A", common, common, NULL, NULL);
+    err = revert(&b, "A", svn_depth_empty,
+                 common, common, NULL, NULL);
+    SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
+    svn_error_clear(err);
+  }
+
+  {
+    nodes_row_t before[] = {
+      { 0, "",        "normal", 4, "" },
+      { 0, "A",       "normal", 4, "A" },
+      { 0, "A/B",     "normal", 4, "A/B" },
+      { 0, "A/B/C",   "normal", 4, "A/B/C" },
+      { 1, "A",       "normal", NO_COPY_FROM },
+      { 1, "A/B",     "base-deleted", NO_COPY_FROM },
+      { 1, "A/B/C",   "base-deleted", NO_COPY_FROM },
+      { 2, "A/B",     "normal", NO_COPY_FROM },
+      { 0 },
+    };
+    nodes_row_t after1[] = {
+      { 0, "",        "normal", 4, "" },
+      { 0, "A",       "normal", 4, "A" },
+      { 0, "A/B",     "normal", 4, "A/B" },
+      { 0, "A/B/C",   "normal", 4, "A/B/C" },
+      { 0 },
+    };
+    nodes_row_t after2[] = {
+      { 0, "",        "normal", 4, "" },
+      { 0, "A",       "normal", 4, "A" },
+      { 0, "A/B",     "normal", 4, "A/B" },
+      { 0, "A/B/C",   "normal", 4, "A/B/C" },
+      { 1, "A",       "normal", NO_COPY_FROM },
+      { 1, "A/B",     "base-deleted", NO_COPY_FROM },
+      { 1, "A/B/C",   "base-deleted", NO_COPY_FROM },
+      { 0 },
+    };
+    SVN_ERR(revert(&b, "", svn_depth_infinity,
+                   before, after1, NULL, NULL));
+    SVN_ERR(revert(&b, "A", svn_depth_infinity,
+                   before, after1, NULL, NULL));
+    SVN_ERR(revert(&b, "A/B", svn_depth_infinity,
+                   before, after2, NULL, NULL));
+    err = revert(&b, "A/B/C", svn_depth_empty,
+                 before, before, NULL, NULL);
     SVN_TEST_ASSERT(err && err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH);
     svn_error_clear(err);
   }