You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/24 13:35:39 UTC

svn commit: r1161055 - in /subversion/branches/1.7.x: ./ subversion/bindings/swig/ruby/test/ subversion/libsvn_wc/ subversion/tests/cmdline/

Author: hwright
Date: Wed Aug 24 11:35:38 2011
New Revision: 1161055

URL: http://svn.apache.org/viewvc?rev=1161055&view=rev
Log:
Merge r1158617, r1158875, r1158886, r1158896, r1158919, r1158924, r1158963
from trunk:

  * r1158617, r1158875, r1158886, r1158896, r1158919, r1158924, r1158963
    Make 'svn revert' remove unversioned nodes resulting from reverting a copy.
    Fixes issue #3101.
    Justification:
      Bert suggested to backport this to 1.7.
      I myself am not really sure if we should consider this a bug fix
      or a behaviour change. I think we should merge this before 1.7.0
      if we decide to merge it.
      It does fix some fairly annoying usability issues.
      For instance: If a merge adds files, the merge result is reverted, and
      the merge is repeated, the second merge does not produce the same result
      as the first merge. It will skip the, now unversioned, files added by
      the first merge. There are various other cases where the unversioned
      files get in the way.
    Notes:
      All revisions depend on one another, but some amend or even undo changes
      made in earlier revisions. Instead of reviewing the individual commits
      I would suggest to run the following merge and review the resulting diff:
        svn merge -c1158617,1158875,1158886,1158896,1158919,1158924,1158963 \
          ^/subversion/trunk
    Votes:
      +1: stsp, rhuijben (but only if this gets into 1.7.0), philip

Modified:
    subversion/branches/1.7.x/   (props changed)
    subversion/branches/1.7.x/STATUS
    subversion/branches/1.7.x/subversion/bindings/swig/ruby/test/test_client.rb
    subversion/branches/1.7.x/subversion/libsvn_wc/adm_ops.c
    subversion/branches/1.7.x/subversion/libsvn_wc/wc-queries.sql
    subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.c
    subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.h
    subversion/branches/1.7.x/subversion/tests/cmdline/copy_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/depth_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py
    subversion/branches/1.7.x/subversion/tests/cmdline/revert_tests.py

Propchange: subversion/branches/1.7.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Aug 24 11:35:38 2011
@@ -59,4 +59,4 @@
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
 /subversion/branches/uris-as-urls:1060426-1064427
-/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148853,1148877,1148882,1148936,1149105,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151906,1151911,1152129,1152140,1152189-1152190,1152282,1152726,1153138,1153141,1153416,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,1156098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,115
 8201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616,1158634,1158854,1158893,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705
+/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148853,1148877,1148882,1148936,1149105,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151906,1151911,1152129,1152140,1152189-1152190,1152282,1152726,1153138,1153141,1153416,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,1156098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,115
 8201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705

Modified: subversion/branches/1.7.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/STATUS?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/STATUS (original)
+++ subversion/branches/1.7.x/STATUS Wed Aug 24 11:35:38 2011
@@ -101,26 +101,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
-  * r1158617, r1158875, r1158886, r1158896, r1158919, r1158924, r1158963
-    Make 'svn revert' remove unversioned nodes resulting from reverting a copy.
-    Fixes issue #3101.
-    Justification:
-      Bert suggested to backport this to 1.7.
-      I myself am not really sure if we should consider this a bug fix
-      or a behaviour change. I think we should merge this before 1.7.0
-      if we decide to merge it.
-      It does fix some fairly annoying usability issues.
-      For instance: If a merge adds files, the merge result is reverted, and
-      the merge is repeated, the second merge does not produce the same result
-      as the first merge. It will skip the, now unversioned, files added by
-      the first merge. There are various other cases where the unversioned
-      files get in the way.
-    Notes:
-      All revisions depend on one another, but some amend or even undo changes
-      made in earlier revisions. Instead of reviewing the individual commits
-      I would suggest to run the following merge and review the resulting diff:
-        svn merge -c1158617,1158875,1158886,1158896,1158919,1158924,1158963 \
-          ^/subversion/trunk
-    Votes:
-      +1: stsp, rhuijben (but only if this gets into 1.7.0), philip

Modified: subversion/branches/1.7.x/subversion/bindings/swig/ruby/test/test_client.rb
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/bindings/swig/ruby/test/test_client.rb?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/bindings/swig/ruby/test/test_client.rb (original)
+++ subversion/branches/1.7.x/subversion/bindings/swig/ruby/test/test_client.rb Wed Aug 24 11:35:38 2011
@@ -1287,7 +1287,6 @@ class SvnClientTest < Test::Unit::TestCa
         ctx.mv(path1, path2)
       end
       ctx.revert([path1, path2])
-      FileUtils.rm(path2)
 
       File.open(path1, "w") {|f| f.print(src2)}
       assert_nothing_raised do

Modified: subversion/branches/1.7.x/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_wc/adm_ops.c?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_wc/adm_ops.c Wed Aug 24 11:35:38 2011
@@ -29,6 +29,7 @@
 
 
 #include <string.h>
+#include <stdlib.h>
 
 #include <apr_pools.h>
 #include <apr_tables.h>
@@ -1270,6 +1271,136 @@ remove_conflict_file(svn_boolean_t *noti
 }
 
 
+/* Sort copied children obtained from the revert list based on
+ * their paths in descending order (longest paths first). */
+static int
+compare_revert_list_copied_children(const void *a, const void *b)
+{
+  const svn_wc__db_revert_list_copied_child_info_t *ca = a;
+  const svn_wc__db_revert_list_copied_child_info_t *cb = b;
+  int i;
+
+  i = svn_path_compare_paths(ca->abspath, cb->abspath);
+
+  /* Reverse the result of svn_path_compare_paths() to achieve
+   * descending order. */
+  return -i;
+}
+
+
+/* Remove all reverted copied children from the directory at LOCAL_ABSPATH.
+ * If REMOVE_SELF is TRUE, try to remove LOCAL_ABSPATH itself (REMOVE_SELF
+ * should be set if LOCAL_ABSPATH is itself a reverted copy).
+ *
+ * If REMOVED_SELF is not NULL, indicate in *REMOVED_SELF whether
+ * LOCAL_ABSPATH itself was removed.
+ *
+ * All reverted copied file children are removed from disk. Reverted copied
+ * directories left empty as a result are also removed from disk.
+ */
+static svn_error_t *
+revert_restore_handle_copied_dirs(svn_boolean_t *removed_self,
+                                  svn_wc__db_t *db,
+                                  const char *local_abspath,
+                                  svn_boolean_t remove_self,
+                                  svn_cancel_func_t cancel_func,
+                                  void *cancel_baton,
+                                  apr_pool_t *scratch_pool)
+{
+  const apr_array_header_t *copied_children;
+  svn_wc__db_revert_list_copied_child_info_t *child_info;
+  int i;
+  svn_node_kind_t on_disk;
+  apr_pool_t *iterpool;
+  svn_error_t *err;
+
+  if (removed_self)
+    *removed_self = FALSE;
+
+  SVN_ERR(svn_wc__db_revert_list_read_copied_children(&copied_children,
+                                                      db, local_abspath,
+                                                      scratch_pool,
+                                                      scratch_pool));
+  iterpool = svn_pool_create(scratch_pool);
+
+  /* Remove all copied file children. */
+  for (i = 0; i < copied_children->nelts; i++)
+    {
+      child_info = APR_ARRAY_IDX(
+                     copied_children, i,
+                     svn_wc__db_revert_list_copied_child_info_t *);
+
+      if (cancel_func)
+        SVN_ERR(cancel_func(cancel_baton));
+
+      if (child_info->kind != svn_wc__db_kind_file)
+        continue;
+
+      svn_pool_clear(iterpool);
+
+      /* Make sure what we delete from disk is really a file. */
+      SVN_ERR(svn_io_check_path(child_info->abspath, &on_disk, iterpool));
+      if (on_disk != svn_node_file)
+        continue;
+
+      SVN_ERR(svn_io_remove_file2(child_info->abspath, TRUE, iterpool));
+    }
+
+  /* Delete every empty child directory.
+   * We cannot delete children recursively since we want to keep any files
+   * that still exist on disk (e.g. unversioned files within the copied tree).
+   * So sort the children list such that longest paths come first and try to
+   * remove each child directory in order. */
+  qsort(copied_children->elts, copied_children->nelts,
+        sizeof(svn_wc__db_revert_list_copied_child_info_t *),
+        compare_revert_list_copied_children);
+  for (i = 0; i < copied_children->nelts; i++)
+    {
+      child_info = APR_ARRAY_IDX(
+                     copied_children, i,
+                     svn_wc__db_revert_list_copied_child_info_t *);
+
+      if (cancel_func)
+        SVN_ERR(cancel_func(cancel_baton));
+
+      if (child_info->kind != svn_wc__db_kind_dir)
+        continue;
+
+      svn_pool_clear(iterpool);
+
+      err = svn_io_dir_remove_nonrecursive(child_info->abspath, iterpool);
+      if (err)
+        {
+          if (APR_STATUS_IS_ENOENT(err->apr_err) ||
+              SVN__APR_STATUS_IS_ENOTDIR(err->apr_err) ||
+              APR_STATUS_IS_ENOTEMPTY(err->apr_err))
+            svn_error_clear(err);
+          else
+            return svn_error_trace(err);
+        }
+    }
+
+  if (remove_self)
+    {
+      /* Delete LOCAL_ABSPATH itself if no children are left. */
+      err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
+      if (err)
+       {
+          if (APR_STATUS_IS_ENOTEMPTY(err->apr_err))
+            svn_error_clear(err);
+          else
+            return svn_error_trace(err);
+        }
+      else if (removed_self)
+        *removed_self = TRUE;
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+
 /* Make the working tree under LOCAL_ABSPATH to depth DEPTH match the
    versioned tree.  This function is called after svn_wc__db_op_revert
    has done the database revert and created the revert list.  Notifies
@@ -1300,6 +1431,8 @@ revert_restore(svn_wc__db_t *db,
 #ifdef HAVE_SYMLINK
   svn_boolean_t special;
 #endif
+  svn_boolean_t copied_here;
+  svn_wc__db_kind_t reverted_kind;
 
   if (cancel_func)
     SVN_ERR(cancel_func(cancel_baton));
@@ -1307,6 +1440,7 @@ revert_restore(svn_wc__db_t *db,
   SVN_ERR(svn_wc__db_revert_list_read(&notify_required,
                                       &conflict_old, &conflict_new,
                                       &conflict_working, &prop_reject,
+                                      &copied_here, &reverted_kind,
                                       db, local_abspath,
                                       scratch_pool, scratch_pool));
 
@@ -1321,17 +1455,31 @@ revert_restore(svn_wc__db_t *db,
     {
       svn_error_clear(err);
 
-      if (notify_func && notify_required)
-        notify_func(notify_baton,
-                    svn_wc_create_notify(local_abspath, svn_wc_notify_revert,
-                                         scratch_pool),
-                    scratch_pool);
-
-      if (notify_func)
-        SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
-                                              db, local_abspath,
-                                              scratch_pool));
-      return SVN_NO_ERROR;
+      if (!copied_here)
+        {
+          if (notify_func && notify_required)
+            notify_func(notify_baton,
+                        svn_wc_create_notify(local_abspath,
+                                             svn_wc_notify_revert,
+                                             scratch_pool),
+                        scratch_pool);
+
+          if (notify_func)
+            SVN_ERR(svn_wc__db_revert_list_notify(notify_func, notify_baton,
+                                                  db, local_abspath,
+                                                  scratch_pool));
+          return SVN_NO_ERROR;
+        }
+      else
+        {
+          /* ### Initialise to values which prevent the code below from
+           * ### trying to restore anything to disk.
+           * ### 'status' should be status_unknown but that doesn't exist. */
+          status = svn_wc__db_status_normal;
+          kind = svn_wc__db_kind_unknown;
+          recorded_size = SVN_INVALID_FILESIZE;
+          recorded_mod_time = 0;
+        }
     }
   else if (err)
     return svn_error_trace(err);
@@ -1366,6 +1514,27 @@ revert_restore(svn_wc__db_t *db,
 #endif
     }
 
+  if (copied_here)
+    {
+      /* The revert target itself is the op-root of a copy. */
+      if (reverted_kind == svn_wc__db_kind_file && on_disk == svn_node_file)
+        {
+          SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
+          on_disk = svn_node_none;
+        }
+      else if (reverted_kind == svn_wc__db_kind_dir && on_disk == svn_node_dir)
+        {
+          svn_boolean_t removed;
+
+          SVN_ERR(revert_restore_handle_copied_dirs(&removed, db,
+                                                    local_abspath, TRUE, 
+                                                    cancel_func, cancel_baton,
+                                                    scratch_pool));
+          if (removed)
+            on_disk = svn_node_none;
+        }
+    }
+
   /* If we expect a versioned item to be present then check that any
      item on disk matches the versioned item, if it doesn't match then
      fix it or delete it.  */
@@ -1546,6 +1715,10 @@ revert_restore(svn_wc__db_t *db,
       const apr_array_header_t *children;
       int i;
 
+      SVN_ERR(revert_restore_handle_copied_dirs(NULL, db, local_abspath, FALSE,
+                                                cancel_func, cancel_baton,
+                                                iterpool));
+
       SVN_ERR(svn_wc__db_read_children_of_working_node(&children, db,
                                                        local_abspath,
                                                        scratch_pool,

Modified: subversion/branches/1.7.x/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_wc/wc-queries.sql?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/1.7.x/subversion/libsvn_wc/wc-queries.sql Wed Aug 24 11:35:38 2011
@@ -1102,14 +1102,18 @@ CREATE TEMPORARY TABLE revert_list (
    conflict_working TEXT,
    prop_reject TEXT,
    notify INTEGER,         /* 1 if an actual row had props or tree conflict */
+   op_depth INTEGER,
+   repos_id INTEGER,
+   kind TEXT,
    PRIMARY KEY (local_relpath, actual)
    );
 DROP TRIGGER IF EXISTS   trigger_revert_list_nodes;
 CREATE TEMPORARY TRIGGER trigger_revert_list_nodes
 BEFORE DELETE ON nodes
 BEGIN
-   INSERT OR REPLACE INTO revert_list(local_relpath, actual)
-   SELECT OLD.local_relpath, 0;
+   INSERT OR REPLACE INTO revert_list(local_relpath, actual, op_depth,
+                                      repos_id, kind)
+   SELECT OLD.local_relpath, 0, OLD.op_depth, OLD.repos_id, OLD.kind;
 END;
 DROP TRIGGER IF EXISTS   trigger_revert_list_actual_delete;
 CREATE TEMPORARY TRIGGER trigger_revert_list_actual_delete
@@ -1146,11 +1150,20 @@ DROP TRIGGER IF EXISTS trigger_revert_li
 DROP TRIGGER IF EXISTS trigger_revert_list_actual_update
 
 -- STMT_SELECT_REVERT_LIST
-SELECT conflict_old, conflict_new, conflict_working, prop_reject, notify, actual
+SELECT conflict_old, conflict_new, conflict_working, prop_reject, notify,
+       actual, op_depth, repos_id, kind
 FROM revert_list
 WHERE local_relpath = ?1
 ORDER BY actual DESC
 
+-- STMT_SELECT_REVERT_LIST_COPIED_CHILDREN
+SELECT local_relpath, kind
+FROM revert_list
+WHERE local_relpath LIKE ?1 ESCAPE '#'
+  AND op_depth >= ?2
+  AND repos_id IS NOT NULL
+ORDER BY local_relpath
+
 -- STMT_DELETE_REVERT_LIST
 DELETE FROM revert_list WHERE local_relpath = ?1
 

Modified: subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.c?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.c Wed Aug 24 11:35:38 2011
@@ -5403,6 +5403,8 @@ struct revert_list_read_baton {
   const char **conflict_new;
   const char **conflict_working;
   const char **prop_reject;
+  svn_boolean_t *copied_here;
+  svn_wc__db_kind_t *kind;
   apr_pool_t *result_pool;
 };
 
@@ -5419,6 +5421,8 @@ revert_list_read(void *baton,
   *(b->reverted) = FALSE;
   *(b->conflict_new) = *(b->conflict_old) = *(b->conflict_working) = NULL;
   *(b->prop_reject) = NULL;
+  *(b->copied_here) = FALSE;
+  *(b->kind) = svn_wc__db_kind_unknown;
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
                                     STMT_SELECT_REVERT_LIST));
@@ -5426,9 +5430,10 @@ revert_list_read(void *baton,
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   if (have_row)
     {
-      svn_boolean_t another_row;
+      svn_boolean_t is_actual = (svn_sqlite__column_int64(stmt, 5) != 0);
+      svn_boolean_t another_row = FALSE;
 
-      if (svn_sqlite__column_int64(stmt, 5))
+      if (is_actual)
         {
           if (!svn_sqlite__column_is_null(stmt, 4))
             *(b->reverted) = TRUE;
@@ -5458,11 +5463,19 @@ revert_list_read(void *baton,
                                 b->result_pool);
 
           SVN_ERR(svn_sqlite__step(&another_row, stmt));
-          if (another_row)
-            *(b->reverted) = TRUE;
         }
-      else
-        *(b->reverted) = TRUE;
+
+      if (!is_actual || another_row)
+        {
+          *(b->reverted) = TRUE;
+          if (!svn_sqlite__column_is_null(stmt, 7))
+            {
+              apr_int64_t op_depth = svn_sqlite__column_int64(stmt, 6);
+              *(b->copied_here) = (op_depth == relpath_depth(local_relpath));
+            }
+          *(b->kind) = svn_sqlite__column_token(stmt, 8, kind_map);
+        }
+
     }
   SVN_ERR(svn_sqlite__reset(stmt));
 
@@ -5483,6 +5496,8 @@ svn_wc__db_revert_list_read(svn_boolean_
                             const char **conflict_new,
                             const char **conflict_working,
                             const char **prop_reject,
+                            svn_boolean_t *copied_here,
+                            svn_wc__db_kind_t *kind,
                             svn_wc__db_t *db,
                             const char *local_abspath,
                             apr_pool_t *result_pool,
@@ -5492,7 +5507,7 @@ svn_wc__db_revert_list_read(svn_boolean_
   const char *local_relpath;
   struct revert_list_read_baton b = {reverted, conflict_old, conflict_new,
                                      conflict_working, prop_reject,
-                                     result_pool};
+                                     copied_here, kind, result_pool};
 
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
                               db, local_abspath, scratch_pool, scratch_pool));
@@ -5503,6 +5518,80 @@ svn_wc__db_revert_list_read(svn_boolean_
   return SVN_NO_ERROR;
 }
 
+
+struct revert_list_read_copied_children_baton {
+  const apr_array_header_t **children;
+  apr_pool_t *result_pool;
+};
+
+static svn_error_t *
+revert_list_read_copied_children(void *baton,
+                                 svn_wc__db_wcroot_t *wcroot,
+                                 const char *local_relpath,
+                                 apr_pool_t *scratch_pool)
+{
+  struct revert_list_read_copied_children_baton *b = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_array_header_t *children;
+
+  children =
+    apr_array_make(b->result_pool, 0,
+                  sizeof(svn_wc__db_revert_list_copied_child_info_t *));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_REVERT_LIST_COPIED_CHILDREN));
+  SVN_ERR(svn_sqlite__bindf(stmt, "si",
+                            construct_like_arg(local_relpath, scratch_pool),
+                            relpath_depth(local_relpath)));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  while (have_row)
+    {
+      svn_wc__db_revert_list_copied_child_info_t *child_info;
+      const char *child_relpath;
+
+      child_info = apr_palloc(b->result_pool, sizeof(*child_info));
+
+      child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      child_info->abspath = svn_dirent_join(wcroot->abspath, child_relpath,
+                                            b->result_pool);
+      child_info->kind = svn_sqlite__column_token(stmt, 1, kind_map);
+      APR_ARRAY_PUSH(
+        children,
+        svn_wc__db_revert_list_copied_child_info_t *) = child_info;
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+   SVN_ERR(svn_sqlite__reset(stmt));
+
+  *b->children = children;
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__db_revert_list_read_copied_children(const apr_array_header_t **children,
+                                            svn_wc__db_t *db,
+                                            const char *local_abspath,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  struct revert_list_read_copied_children_baton b = {children, result_pool};
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+                              db, local_abspath, scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath,
+                              revert_list_read_copied_children, &b,
+                              scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
 svn_wc__db_revert_list_notify(svn_wc_notify_func2_t notify_func,
                               void *notify_baton,

Modified: subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.h?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/1.7.x/subversion/libsvn_wc/wc_db.h Wed Aug 24 11:35:38 2011
@@ -1506,6 +1506,10 @@ svn_wc__db_op_revert(svn_wc__db_t *db,
  * path was reverted.  Set *CONFLICT_OLD, *CONFLICT_NEW,
  * *CONFLICT_WORKING and *PROP_REJECT to the names of the conflict
  * files, or NULL if the names are not stored.
+ * 
+ * Set *COPIED_HERE if the reverted node was copied here and is the
+ * operation root of the copy.
+ * Set *KIND to the node kind of the reverted node.
  *
  * Removes the row for LOCAL_ABSPATH from the revert list.
  */
@@ -1515,11 +1519,32 @@ svn_wc__db_revert_list_read(svn_boolean_
                             const char **conflict_new,
                             const char **conflict_working,
                             const char **prop_reject,
+                            svn_boolean_t *copied_here,
+                            svn_wc__db_kind_t *kind,
                             svn_wc__db_t *db,
                             const char *local_abspath,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);
 
+/* The type of elements in the array returned by
+ * svn_wc__db_revert_list_read_copied_children(). */
+typedef struct svn_wc__db_revert_list_copied_child_info_t {
+  const char *abspath;
+  svn_wc__db_kind_t kind;
+} svn_wc__db_revert_list_copied_child_info_t ;
+
+/* Return in *CHILDREN a list of reverted copied nodes at or within
+ * LOCAL_ABSPATH (which is a reverted file or a reverted directory).
+ * Allocate *COPIED_CHILDREN and its elements in RESULT_POOL.
+ * The elements are of type svn_wc__db_revert_list_copied_child_info_t. */
+svn_error_t *
+svn_wc__db_revert_list_read_copied_children(const apr_array_header_t **children,
+                                            svn_wc__db_t *db,
+                                            const char *local_abspath,
+                                            apr_pool_t *result_pool,
+                                            apr_pool_t *scratch_pool);
+
+
 /* Make revert notifications for all paths in the revert list that are
  * equal to LOCAL_ABSPATH or below LOCAL_ABSPATH.
  *

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/copy_tests.py?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/copy_tests.py Wed Aug 24 11:35:38 2011
@@ -955,7 +955,6 @@ def repos_to_wc(sbox):
   svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
 
   svntest.main.safe_rmtree(os.path.join(wc_dir, 'E'))
-  os.unlink(os.path.join(wc_dir, 'pi'))
 
   expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
   svntest.actions.run_and_verify_status(wc_dir, expected_output)

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/depth_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/depth_tests.py?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/depth_tests.py Wed Aug 24 11:35:38 2011
@@ -2229,10 +2229,6 @@ def excluded_path_misc_operation(sbox):
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'revert', '--depth=infinity', L_path)
 
-  # Get rid of A/L.
-  svntest.actions.run_and_verify_svn(None, None, [],
-                                     'rm', '--force', L_path)
-
   # copy A/B to A/L and then cp A/L to A/M, excluded entry should be
   # copied both times
   expected_output = ['A         '+L_path+'\n']

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/merge_tests.py Wed Aug 24 11:35:38 2011
@@ -7482,7 +7482,6 @@ def merge_away_subtrees_noninheritable_r
   #
   # First revert all local changes and remove A_COPY/C/nu from disk.
   svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
-  os.remove(os.path.join(wc_dir, "A_COPY", "nu"))
 
   # Make a text change to A_COPY_2/mu in r11 and then merge that
   # change to A/mu in r12.  This will create mergeinfo of '/A_COPY_2/mu:11'

Modified: subversion/branches/1.7.x/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x/subversion/tests/cmdline/revert_tests.py?rev=1161055&r1=1161054&r2=1161055&view=diff
==============================================================================
--- subversion/branches/1.7.x/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/1.7.x/subversion/tests/cmdline/revert_tests.py Wed Aug 24 11:35:38 2011
@@ -890,13 +890,7 @@ def status_of_missing_dir_after_revert_r
   svntest.actions.run_and_verify_svn(None, expected_output, [], "revert", "-R",
                                      G_path)
 
-
-  # Revert leaves these added nodes as unversioned
-  expected_output = svntest.verify.UnorderedOutput(
-    ["?       " + os.path.join(G_path, "pi") + "\n",
-     "?       " + os.path.join(G_path, "rho") + "\n",
-     "?       " + os.path.join(G_path, "tau") + "\n"])
-  svntest.actions.run_and_verify_svn(None, expected_output, [],
+  svntest.actions.run_and_verify_svn(None, [], [],
                                      "status", wc_dir)
 
   svntest.main.safe_rmtree(G_path)
@@ -977,8 +971,7 @@ def revert_tree_conflicts_in_updated_fil
   expected_status.remove('A/D/G/tau')
 
   expected_disk = svntest.main.greek_state.copy()
-  expected_disk.tweak('A/D/G/rho',
-                      contents="This is the file 'rho'.\nLocal edit.\n")
+  expected_disk.remove('A/D/G/rho')
   expected_disk.tweak('A/D/G/pi',
                       contents="This is the file 'pi'.\nIncoming edit.\n")
   expected_disk.remove('A/D/G/tau')
@@ -1464,8 +1457,6 @@ def revert_tree_conflicts_with_replaceme
 
   # Remove a few unversioned files that revert left behind.
   os.remove(wc('A/B/E/loc_beta'))
-  os.remove(wc('A/D/G/rho'))
-  os.remove(wc('A/D/G/tau'))
   os.remove(wc('A/D/H/loc_psi'))
 
   # The update operation should have put all incoming items in place.