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

svn commit: r1373783 [26/50] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ cont...

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/adm_ops.c Thu Aug 16 10:17:48 2012
@@ -52,6 +52,7 @@
 
 #include "wc.h"
 #include "adm_files.h"
+#include "conflicts.h"
 #include "props.h"
 #include "translate.h"
 #include "workqueue.h"
@@ -59,7 +60,7 @@
 #include "svn_private_config.h"
 #include "private/svn_io_private.h"
 #include "private/svn_wc_private.h"
-
+#include "private/svn_subr_private.h"
 
 
 struct svn_wc_committed_queue_t
@@ -108,11 +109,19 @@ svn_wc__get_committed_queue_pool(const s
  *   - queue deletion of the old pristine texts by the remembered checksums.
  *
  * CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
- * be provided if there is one, else NULL. */
+ * be provided if there is one, else NULL.
+ *
+ * STATUS, KIND, PROP_MODS and OLD_CHECKSUM are the current in-db values of
+ * the node LOCAL_ABSPATH.
+ */
 static svn_error_t *
 process_committed_leaf(svn_wc__db_t *db,
                        const char *local_abspath,
                        svn_boolean_t via_recurse,
+                       svn_wc__db_status_t status,
+                       svn_kind_t kind,
+                       svn_boolean_t prop_mods,
+                       const svn_checksum_t *old_checksum,
                        svn_revnum_t new_revnum,
                        apr_time_t new_changed_date,
                        const char *new_changed_author,
@@ -122,26 +131,11 @@ process_committed_leaf(svn_wc__db_t *db,
                        const svn_checksum_t *checksum,
                        apr_pool_t *scratch_pool)
 {
-  svn_wc__db_status_t status;
-  svn_kind_t kind;
-  const svn_checksum_t *copied_checksum;
   svn_revnum_t new_changed_rev = new_revnum;
-  svn_boolean_t have_base;
-  svn_boolean_t have_work;
-  svn_boolean_t had_props;
-  svn_boolean_t prop_mods;
   svn_skel_t *work_item = NULL;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &copied_checksum,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &had_props, &prop_mods,
-                               &have_base, NULL, &have_work,
-                               db, local_abspath,
-                               scratch_pool, scratch_pool));
-
   {
     const char *adm_abspath;
 
@@ -155,11 +149,12 @@ process_committed_leaf(svn_wc__db_t *db,
   if (status == svn_wc__db_status_deleted)
     {
       return svn_error_trace(
-                svn_wc__db_op_remove_node(
+                svn_wc__db_base_remove(
                                 db, local_abspath,
-                                (have_base && !via_recurse)
+                                FALSE /* keep_as_working */,
+                                (! via_recurse)
                                     ? new_revnum : SVN_INVALID_REVNUM,
-                                kind,
+                                NULL, NULL,
                                 scratch_pool));
     }
   else if (status == svn_wc__db_status_not_present)
@@ -186,9 +181,9 @@ process_committed_leaf(svn_wc__db_t *db,
         {
           /* It was copied and not modified. We must have a text
              base for it. And the node should have a checksum. */
-          SVN_ERR_ASSERT(copied_checksum != NULL);
+          SVN_ERR_ASSERT(old_checksum != NULL);
 
-          checksum = copied_checksum;
+          checksum = old_checksum;
 
           /* Is the node completely unmodified and are we recursing? */
           if (via_recurse && !prop_mods)
@@ -250,23 +245,41 @@ svn_wc__process_committed_internal(svn_w
                                    const svn_wc_committed_queue_t *queue,
                                    apr_pool_t *scratch_pool)
 {
+  svn_wc__db_status_t status;
   svn_kind_t kind;
+  const svn_checksum_t *old_checksum;
+  svn_boolean_t prop_mods;
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, &old_checksum, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, &prop_mods, NULL, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
 
   /* NOTE: be wary of making crazy semantic changes in this function, since
      svn_wc_process_committed4() calls this.  */
 
   SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse,
+                                 status, kind, prop_mods, old_checksum,
                                  new_revnum, new_date, rev_author,
                                  new_dav_cache,
                                  no_unlock, keep_changelist,
                                  sha1_checksum,
                                  scratch_pool));
 
-  /* Only check kind after processing the node itself. The node might
-     have been deleted */
-  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE, scratch_pool));
+  /* Only check for recursion on nodes that have children */
+  if (kind != svn_kind_file
+      || status == svn_wc__db_status_not_present
+      || status == svn_wc__db_status_excluded
+      || status == svn_wc__db_status_server_excluded
+      /* Node deleted -> then no longer a directory */
+      || status == svn_wc__db_status_deleted)
+    {
+      return SVN_NO_ERROR;
+    }
 
-  if (recurse && kind == svn_kind_dir)
+  if (recurse)
     {
       const apr_array_header_t *children;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -281,38 +294,17 @@ svn_wc__process_committed_internal(svn_w
         {
           const char *name = APR_ARRAY_IDX(children, i, const char *);
           const char *this_abspath;
-          svn_wc__db_status_t status;
+          const committed_queue_item_t *cqi;
 
           svn_pool_clear(iterpool);
 
           this_abspath = svn_dirent_join(local_abspath, name, iterpool);
 
-          SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       db, this_abspath,
-                                       iterpool, iterpool));
-
-          /* We come to this branch since we have committed a copied tree.
-             svn_depth_exclude is possible in this situation. So check and
-             skip */
-          if (status == svn_wc__db_status_excluded)
-            continue;
-
           sha1_checksum = NULL;
-          if (kind != svn_kind_dir && queue != NULL)
-            {
-              const committed_queue_item_t *cqi;
+          cqi = apr_hash_get(queue->queue, this_abspath, APR_HASH_KEY_STRING);
 
-              cqi = apr_hash_get(queue->queue, this_abspath,
-                                 APR_HASH_KEY_STRING);
-              if (cqi != NULL)
-                {
-                  sha1_checksum = cqi->sha1_checksum;
-                }
-            }
+          if (cqi != NULL)
+            sha1_checksum = cqi->sha1_checksum;
 
           /* Recurse.  Pass NULL for NEW_DAV_CACHE, because the
              ones present in the current call are only applicable to
@@ -595,6 +587,72 @@ erase_unversioned_from_wc(const char *pa
   return SVN_NO_ERROR;
 }
 
+/* Helper for svn_wc__delete and svn_wc__delete_many */
+static svn_error_t *
+create_delete_wq_items(svn_skel_t **work_items,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       svn_kind_t kind,
+                       svn_boolean_t conflicted,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  *work_items = NULL;
+
+  /* Schedule the on-disk delete */
+  if (kind == svn_kind_dir)
+    SVN_ERR(svn_wc__wq_build_dir_remove(work_items, db, local_abspath,
+                                        local_abspath,
+                                        TRUE /* recursive */,
+                                        result_pool, scratch_pool));
+  else
+    SVN_ERR(svn_wc__wq_build_file_remove(work_items, db, local_abspath,
+                                         local_abspath,
+                                         result_pool, scratch_pool));
+
+  /* Read conflicts, to allow deleting the markers after updating the DB */
+  if (conflicted)
+    {
+      svn_skel_t *conflict;
+      const apr_array_header_t *markers;
+      int i;
+
+      SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+                                       scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_read_markers(&markers, db, local_abspath,
+                                            conflict,
+                                            scratch_pool, scratch_pool));
+
+      /* Maximum number of markers is 4, so no iterpool */
+      for (i = 0; markers && i < markers->nelts; i++)
+        {
+          const char *marker_abspath;
+          svn_node_kind_t marker_kind;
+
+          marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
+          SVN_ERR(svn_io_check_path(marker_abspath, &marker_kind,
+                                    scratch_pool));
+
+          if (marker_kind == svn_node_file)
+            {
+              svn_skel_t *work_item;
+
+              SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
+                                                   marker_abspath,
+                                                   result_pool,
+                                                   scratch_pool));
+
+              *work_items = svn_wc__wq_merge(*work_items, work_item,
+                                             result_pool);
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__delete_many(svn_wc_context_t *wc_ctx,
                     const apr_array_header_t *targets,
@@ -610,7 +668,7 @@ svn_wc__delete_many(svn_wc_context_t *wc
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_kind_t kind;
-  const apr_array_header_t *conflicts = NULL;
+  svn_skel_t *work_items = NULL;
   apr_array_header_t *versioned_targets;
   const char *local_abspath;
   int i;
@@ -686,74 +744,39 @@ svn_wc__delete_many(svn_wc_context_t *wc
                                                          iterpool),
                                   iterpool));
 
-      /* Read conflicts, to allow deleting the markers after updating the DB */
-      if (!keep_local && conflicted)
-        SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                          scratch_pool, iterpool));
+      /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          svn_skel_t *work_item;
+
+          SVN_ERR(create_delete_wq_items(&work_item, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, iterpool));
 
+          work_items = svn_wc__wq_merge(work_items, work_item,
+                                        scratch_pool);
+        }
     }
 
   if (versioned_targets->nelts == 0)
     return SVN_NO_ERROR;
 
   SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets,
+                                    !keep_local /* delete_dir_externals */,
+                                    work_items,
                                     cancel_func, cancel_baton,
-                                    notify_func, notify_baton, scratch_pool));
-
-  if (!keep_local && conflicts != NULL)
-    {
-      svn_pool_clear(iterpool);
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
+                                    notify_func, notify_baton,
+                                    iterpool));
 
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              iterpool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          iterpool));
-            }
-        }
-    }
-
-  /* By the time we get here, the db knows that all targets are now
-   * unversioned. */
-  if (!keep_local)
+  if (work_items != NULL)
     {
-      for (i = 0; i < versioned_targets->nelts; i++)
-        {
-          svn_pool_clear(iterpool);
+      /* Our only caller locked the wc, so for now assume it only passed
+         nodes from a single wc (asserted in svn_wc__db_op_delete_many) */
+      local_abspath = APR_ARRAY_IDX(versioned_targets, 0, const char *);
 
-          local_abspath = APR_ARRAY_IDX(versioned_targets, i, const char *);
-          SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                            cancel_func, cancel_baton,
-                                            iterpool));
-        }
+      SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                             iterpool));
     }
-
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -777,7 +800,7 @@ svn_wc__delete_internal(svn_wc_context_t
   svn_wc__db_status_t status;
   svn_kind_t kind;
   svn_boolean_t conflicted;
-  const apr_array_header_t *conflicts;
+  svn_skel_t *work_items = NULL;
 
   err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -831,63 +854,24 @@ svn_wc__delete_internal(svn_wc_context_t
   SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, pool),
                               pool));
 
-  /* Read conflicts, to allow deleting the markers after updating the DB */
-  if (!keep_local && conflicted)
-    SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
-                                      scratch_pool, scratch_pool));
+  /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          SVN_ERR(create_delete_wq_items(&work_items, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, scratch_pool));
+        }
 
   SVN_ERR(svn_wc__db_op_delete(db, local_abspath, moved_to_abspath,
-                               notify_func, notify_baton,
+                               !keep_local /* delete_dir_externals */,
+                               NULL, work_items,
                                cancel_func, cancel_baton,
+                               notify_func, notify_baton,
                                pool));
 
-  if (!keep_local && conflicted && conflicts != NULL)
-    {
-      int i;
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
-
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              scratch_pool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          scratch_pool));
-            }
-        }
-    }
-
-  /* By the time we get here, the db knows that everything that is still at
-     LOCAL_ABSPATH is unversioned. */
-  if (!keep_local)
-    {
-        SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                          cancel_func, cancel_baton,
-                                          pool));
-    }
+  if (work_items)
+    SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1606,10 +1590,7 @@ revert_restore(svn_wc__db_t *db,
   svn_kind_t kind;
   svn_node_kind_t on_disk;
   svn_boolean_t notify_required;
-  const char *conflict_old;
-  const char *conflict_new;
-  const char *conflict_working;
-  const char *prop_reject;
+  const apr_array_header_t *conflict_files;
   svn_filesize_t recorded_size;
   apr_time_t recorded_mod_time;
   apr_finfo_t finfo;
@@ -1623,8 +1604,7 @@ revert_restore(svn_wc__db_t *db,
     SVN_ERR(cancel_func(cancel_baton));
 
   SVN_ERR(svn_wc__db_revert_list_read(&notify_required,
-                                      &conflict_old, &conflict_new,
-                                      &conflict_working, &prop_reject,
+                                      &conflict_files,
                                       &copied_here, &reverted_kind,
                                       db, local_abspath,
                                       scratch_pool, scratch_pool));
@@ -1805,25 +1785,30 @@ revert_restore(svn_wc__db_t *db,
                 }
               else
                 {
-                  svn_boolean_t read_only;
-                  svn_string_t *needs_lock_prop;
+                  if (status == svn_wc__db_status_normal)
+                    {
+                      svn_boolean_t read_only;
+                      svn_string_t *needs_lock_prop;
 
-                  SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo,
-                                                     scratch_pool));
+                      SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo,
+                                                         scratch_pool));
 
-                  needs_lock_prop = apr_hash_get(props, SVN_PROP_NEEDS_LOCK,
-                                                 APR_HASH_KEY_STRING);
-                  if (needs_lock_prop && !read_only)
-                    {
-                      SVN_ERR(svn_io_set_file_read_only(local_abspath,
-                                                        FALSE, scratch_pool));
-                      notify_required = TRUE;
-                    }
-                  else if (!needs_lock_prop && read_only)
-                    {
-                      SVN_ERR(svn_io_set_file_read_write(local_abspath,
-                                                         FALSE, scratch_pool));
-                      notify_required = TRUE;
+                      needs_lock_prop = apr_hash_get(props, SVN_PROP_NEEDS_LOCK,
+                                                     APR_HASH_KEY_STRING);
+                      if (needs_lock_prop && !read_only)
+                        {
+                          SVN_ERR(svn_io_set_file_read_only(local_abspath,
+                                                            FALSE,
+                                                            scratch_pool));
+                          notify_required = TRUE;
+                        }
+                      else if (!needs_lock_prop && read_only)
+                        {
+                          SVN_ERR(svn_io_set_file_read_write(local_abspath,
+                                                             FALSE,
+                                                             scratch_pool));
+                          notify_required = TRUE;
+                        }
                     }
 
 #if !defined(WIN32) && !defined(__OS2__)
@@ -1886,14 +1871,17 @@ revert_restore(svn_wc__db_t *db,
       notify_required = TRUE;
     }
 
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_old,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_new,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, conflict_working,
-                               local_abspath, scratch_pool));
-  SVN_ERR(remove_conflict_file(&notify_required, prop_reject,
-                               local_abspath, scratch_pool));
+  if (conflict_files)
+    {
+      int i;
+      for (i = 0; i < conflict_files->nelts; i++)
+        {
+          SVN_ERR(remove_conflict_file(&notify_required,
+                                       APR_ARRAY_IDX(conflict_files, i,
+                                                     const char *),
+                                       local_abspath, scratch_pool));
+        }
+    }
 
   if (notify_func && notify_required)
     notify_func(notify_baton,
@@ -1964,12 +1952,14 @@ revert_internal(svn_wc__db_t *db,
      when local_abspath is the working copy root. */
   {
     const char *dir_abspath;
+    svn_boolean_t is_wcroot;
 
-    SVN_ERR(svn_wc__db_get_wcroot(&dir_abspath, db, local_abspath,
-                                  scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
 
-    if (svn_dirent_is_child(dir_abspath, local_abspath, NULL))
+    if (! is_wcroot)
       dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+    else
+      dir_abspath = local_abspath;
 
     SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
   }
@@ -2119,7 +2109,9 @@ revert_partial(svn_wc__db_t *db,
         {
           svn_kind_t kind;
 
-          SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, TRUE,
+          SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath,
+                                       FALSE /* allow_missing */,
+                                       FALSE /* show_hidden */,
                                        iterpool));
           if (kind != svn_kind_file)
             continue;
@@ -2251,218 +2243,137 @@ svn_wc_get_pristine_contents2(svn_stream
 }
 
 
+typedef struct get_pristine_lazyopen_baton_t
+{
+  svn_wc_context_t *wc_ctx;
+  const char *wri_abspath;
+  const svn_checksum_t *checksum;
+
+} get_pristine_lazyopen_baton_t;
+
+
+/* Implements svn_stream_lazyopen_func_t */
+static svn_error_t *
+get_pristine_lazyopen_func(svn_stream_t **stream,
+                           void *baton,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  get_pristine_lazyopen_baton_t *b = baton;
+  const svn_checksum_t *sha1_checksum;
+
+  /* svn_wc__db_pristine_read() wants a SHA1, so if we have an MD5,
+     we'll use it to lookup the SHA1. */
+  if (b->checksum->kind == svn_checksum_sha1)
+    sha1_checksum = b->checksum;
+  else
+    SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, b->wc_ctx->db,
+                                         b->wri_abspath, b->checksum,
+                                         scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_wc__db_pristine_read(stream, NULL, b->wc_ctx->db,
+                                   b->wri_abspath, sha1_checksum,
+                                   result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__get_pristine_contents_by_checksum(svn_stream_t **contents,
+                                          svn_wc_context_t *wc_ctx,
+                                          const char *wri_abspath,
+                                          const svn_checksum_t *checksum,
+                                          apr_pool_t *result_pool,
+                                          apr_pool_t *scratch_pool)
+{
+  svn_boolean_t present;
+  
+  *contents = NULL;
+
+  SVN_ERR(svn_wc__db_pristine_check(&present, wc_ctx->db, wri_abspath,
+                                    checksum, scratch_pool));
+
+  if (present)
+    {
+      get_pristine_lazyopen_baton_t *gpl_baton;
+
+      gpl_baton = apr_pcalloc(result_pool, sizeof(*gpl_baton));
+      gpl_baton->wc_ctx = wc_ctx;
+      gpl_baton->wri_abspath = wri_abspath;
+      gpl_baton->checksum = checksum;
+      
+      *contents = svn_stream_lazyopen_create(get_pristine_lazyopen_func,
+                                             gpl_baton, result_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__internal_remove_from_revision_control(svn_wc__db_t *db,
                                               const char *local_abspath,
                                               svn_boolean_t destroy_wf,
-                                              svn_boolean_t instant_error,
                                               svn_cancel_func_t cancel_func,
                                               void *cancel_baton,
                                               apr_pool_t *scratch_pool)
 {
-  svn_error_t *err;
   svn_boolean_t left_something = FALSE;
-  svn_wc__db_status_t status;
-  svn_kind_t kind;
-
-  /* ### This whole function should be rewritten to run inside a transaction,
-     ### to allow a stable cancel behavior.
-     ###
-     ### Subversion < 1.7 marked the directory as incomplete to allow updating
-     ### it from a canceled state. But this would not work because update
-     ### doesn't retrieve deleted items.
-     ###
-     ### WC-NG doesn't support a delete+incomplete state, but we can't build
-     ### transactions over multiple databases yet. */
+  svn_boolean_t is_root;
+  svn_error_t *err = NULL;
 
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  /* Check cancellation here, so recursive calls get checked early. */
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL,
-                               db, local_abspath, scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool));
 
-  if (kind == svn_kind_file || kind == svn_kind_symlink)
-    {
-      svn_boolean_t text_modified_p = FALSE;
-
-      if (instant_error || destroy_wf)
-        {
-          svn_node_kind_t on_disk;
-          SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
-          if (on_disk == svn_node_file)
-            {
-              /* Check for local mods. before removing entry */
-              SVN_ERR(svn_wc__internal_file_modified_p(&text_modified_p, db,
-                                                       local_abspath, FALSE,
-                                                       scratch_pool));
-              if (text_modified_p && instant_error)
-                return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
-                       _("File '%s' has local modifications"),
-                       svn_dirent_local_style(local_abspath, scratch_pool));
-            }
-        }
+  SVN_ERR(svn_wc__db_op_remove_node(&left_something,
+                                    db, local_abspath,
+                                    destroy_wf /* destroy_wc */,
+                                    destroy_wf /* destroy_changes */,
+                                    SVN_INVALID_REVNUM,
+                                    svn_wc__db_status_not_present,
+                                    svn_kind_none,
+                                    NULL, NULL,
+                                    cancel_func, cancel_baton,
+                                    scratch_pool));
 
-      /* Remove NAME from DB */
-      SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                        SVN_INVALID_REVNUM,
-                                        svn_kind_unknown,
-                                        scratch_pool));
-
-      /* If we were asked to destroy the working file, do so unless
-         it has local mods. */
-      if (destroy_wf)
-        {
-          /* Don't kill local mods. */
-          if (text_modified_p)
-            return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
-          else  /* The working file is still present; remove it. */
-            SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
-        }
+  SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                         cancel_func, cancel_baton,
+                         scratch_pool));
 
-    }  /* done with file case */
-  else /* looking at THIS_DIR */
+  if (is_root)
     {
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      const apr_array_header_t *children;
-      int i;
-
-      /* ### sanity check:  check 2 places for DELETED flag? */
-
-      /* Walk over every entry. */
-      SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
-                                       scratch_pool, iterpool));
-
-      for (i = 0; i < children->nelts; i++)
-        {
-          const char *node_name = APR_ARRAY_IDX(children, i, const char*);
-          const char *node_abspath;
-          svn_wc__db_status_t node_status;
-          svn_kind_t node_kind;
-
-          svn_pool_clear(iterpool);
-
-          node_abspath = svn_dirent_join(local_abspath, node_name, iterpool);
-
-          SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, node_abspath,
-                                       iterpool, iterpool));
-
-          if (node_status == svn_wc__db_status_normal
-              && node_kind == svn_kind_dir)
-            {
-              svn_boolean_t is_root;
-
-              SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                            db, node_abspath, iterpool));
-
-              if (is_root)
-                continue; /* Just skip working copies as obstruction */
-            }
-
-          if (node_status != svn_wc__db_status_normal
-              && node_status != svn_wc__db_status_added
-              && node_status != svn_wc__db_status_incomplete)
-            {
-              /* The node is already 'deleted', so nothing to do on
-                 versioned nodes */
-              SVN_ERR(svn_wc__db_op_remove_node(db, node_abspath,
-                                                SVN_INVALID_REVNUM,
-                                                svn_kind_unknown,
-                                                iterpool));
-
-              continue;
-            }
-
-          err = svn_wc__internal_remove_from_revision_control(
-                            db, node_abspath,
-                            destroy_wf, instant_error,
-                            cancel_func, cancel_baton,
-                            iterpool);
-
-          if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
-            {
-              if (instant_error)
-                return svn_error_trace(err);
-              else
-                {
-                  svn_error_clear(err);
-                  left_something = TRUE;
-                }
-            }
-          else if (err)
-            return svn_error_trace(err);
-        }
-
-      /* At this point, every directory below this one has been
-         removed from revision control. */
-
-      /* Remove self from parent's entries file, but only if parent is
-         a working copy.  If it's not, that's fine, we just move on. */
-      {
-        svn_boolean_t is_root;
-
-        SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                      db, local_abspath, iterpool));
-
-        /* If full_path is not the top of a wc, then its parent
-           directory is also a working copy and has an entry for
-           full_path.  We need to remove that entry: */
-        if (! is_root)
-          {
-            SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                              SVN_INVALID_REVNUM,
-                                              svn_kind_unknown,
-                                              iterpool));
-          }
-        else
-          {
-            /* Remove the entire administrative .svn area, thereby removing
-               _this_ dir from revision control too.  */
-            SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
-                                        cancel_func, cancel_baton, iterpool));
-          }
-      }
-
-      /* If caller wants us to recursively nuke everything on disk, go
-         ahead, provided that there are no dangling local-mod files
-         below */
-      if (destroy_wf && (! left_something))
-        {
-          /* If the dir is *truly* empty (i.e. has no unversioned
-             resources, all versioned files are gone, all .svn dirs are
-             gone, and contains nothing but empty dirs), then a
-             *non*-recursive dir_remove should work.  If it doesn't,
-             no big deal.  Just assume there are unversioned items in
-             there and set "left_something" */
-          err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
-          if (err)
-            {
-              if (!APR_STATUS_IS_ENOENT(err->apr_err))
-                left_something = TRUE;
-              svn_error_clear(err);
-            }
-        }
-
-      svn_pool_destroy(iterpool);
+      /* Destroy the administrative area */
+      SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
+                                  scratch_pool));
 
-    }  /* end of directory case */
+      /* And if we didn't leave something interesting, remove the directory */
+      if (!left_something && destroy_wf)
+        err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+    }
 
-  if (left_something)
-    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
+  if (left_something || err)
+    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, err, NULL);
 
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_wc_status_func4_t for svn_wc_remove_from_revision_control2 */
+static svn_error_t *
+remove_from_revision_status_callback(void *baton,
+                                     const char *local_abspath,
+                                     const svn_wc_status3_t *status,
+                                     apr_pool_t *scratch_pool)
+{
+  /* For legacy reasons we only check the file contents for changes */
+  if (status->versioned
+      && status->kind == svn_node_file
+      && (status->text_status == svn_wc_status_modified
+          || status->text_status == svn_wc_status_conflicted))
+    {
+      return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
+                               _("File '%s' has local modifications"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc_remove_from_revision_control2(svn_wc_context_t *wc_ctx,
@@ -2473,11 +2384,18 @@ svn_wc_remove_from_revision_control2(svn
                                     void *cancel_baton,
                                     apr_pool_t *scratch_pool)
 {
+  if (instant_error)
+    {
+      SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, svn_depth_infinity,
+                                 FALSE, FALSE, FALSE, NULL,
+                                 remove_from_revision_status_callback, NULL,
+                                 cancel_func, cancel_baton,
+                                 scratch_pool));
+    }
   return svn_error_trace(
       svn_wc__internal_remove_from_revision_control(wc_ctx->db,
                                                     local_abspath,
                                                     destroy_wf,
-                                                    instant_error,
                                                     cancel_func,
                                                     cancel_baton,
                                                     scratch_pool));
@@ -2631,8 +2549,12 @@ svn_wc_get_changelists(svn_wc_context_t 
                        void *cancel_baton,
                        apr_pool_t *scratch_pool)
 {
-  struct get_cl_fn_baton gnb = { wc_ctx->db, NULL,
-                                 callback_func, callback_baton };
+  struct get_cl_fn_baton gnb;
+
+  gnb.db = wc_ctx->db;
+  gnb.clhash = NULL;
+  gnb.callback_func = callback_func;
+  gnb.callback_baton = callback_baton;
 
   if (changelist_filter)
     SVN_ERR(svn_hash_from_cstring_keys(&gnb.clhash, changelist_filter,

Modified: subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_wc/cleanup.c Thu Aug 16 10:17:48 2012
@@ -142,7 +142,7 @@ cleanup_internal(svn_wc__db_t *db,
                  apr_pool_t *scratch_pool)
 {
   int wc_format;
-  const char *cleanup_abspath;
+  svn_boolean_t is_wcroot;
 
   /* Can we even work with this directory?  */
   SVN_ERR(can_be_cleaned(&wc_format, db, dir_abspath, scratch_pool));
@@ -157,8 +157,7 @@ cleanup_internal(svn_wc__db_t *db,
     SVN_ERR(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton,
                            scratch_pool));
 
-  SVN_ERR(svn_wc__db_get_wcroot(&cleanup_abspath, db, dir_abspath,
-                                scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
 
 #ifdef SVN_DEBUG
   SVN_ERR(svn_wc__db_verify(db, dir_abspath, scratch_pool));
@@ -169,7 +168,7 @@ cleanup_internal(svn_wc__db_t *db,
      svn_wc__check_wcroot() as that function, will just return true
      once we start sharing databases with externals.
    */
-  if (strcmp(cleanup_abspath, dir_abspath) == 0)
+  if (is_wcroot)
     {
     /* Cleanup the tmp area of the admin subdir, if running the log has not
        removed it!  The logs have been run, so anything left here has no hope