subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject 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...
Date Thu, 16 Aug 2012 10:18:03 GMT
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



Mime
View raw message