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 2010/08/10 22:56:05 UTC

svn commit: r984206 [15/35] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hudson/jobs/subvers...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/copy.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/copy.c Tue Aug 10 20:55:56 2010
@@ -34,6 +34,8 @@
 #include "svn_path.h"
 
 #include "wc.h"
+#include "log.h"
+#include "workqueue.h"
 #include "adm_files.h"
 #include "entries.h"
 #include "props.h"
@@ -56,8 +58,8 @@ copy_props(svn_wc__db_t *db,
   apr_hash_t *props;
   apr_hash_index_t *hi;
 
-  SVN_ERR(svn_wc__load_props(NULL, &props, db, src_abspath,
-                             scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__get_actual_props(&props, db, src_abspath,
+                                   scratch_pool, scratch_pool));
   for (hi = apr_hash_first(scratch_pool, props); hi; hi = apr_hash_next(hi))
     {
       const char *propname = svn__apr_hash_index_key(hi);
@@ -258,89 +260,7 @@ copy_added_dir_administratively(svn_wc_c
   return SVN_NO_ERROR;
 }
 
-/* A helper for copy_file_administratively() which sets *COPYFROM_URL
-   and *COPYFROM_REV appropriately (possibly to NULL/SVN_INVALID_REVNUM).
-   DST_URL may be NULL, in which case DST_REVISION is ignored. */
-static svn_error_t *
-determine_copyfrom_info(const char **copyfrom_url,
-                        svn_revnum_t *copyfrom_rev,
-                        svn_wc__db_t *db,
-                        const char *src_abspath,
-                        const char *dst_url,
-                        svn_revnum_t dst_revision,
-                        apr_pool_t *result_pool,
-                        apr_pool_t *scratch_pool)
-{
-  const char *url;
-  const char *original_root_url;
-  const char *original_repos_relpath;
-  svn_revnum_t original_revision;
-  svn_wc__db_status_t status;
-
-  url = NULL;
-  original_revision = SVN_INVALID_REVNUM;
-
-  SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, &original_repos_relpath,
-                               &original_root_url, NULL, &original_revision,
-                               NULL, NULL, NULL, NULL, NULL, db, src_abspath,
-                               scratch_pool, scratch_pool));
-  if (original_root_url && original_repos_relpath)
-    {
-      /* When copying/moving a file that was already explicitly
-         copied/moved then we know the URL it was copied from... */
-      url = svn_path_url_add_component2(original_root_url,
-                                        original_repos_relpath, scratch_pool);
-    }
-  else if (status == svn_wc__db_status_added
-           || status == svn_wc__db_status_obstructed_add)
-    {
-      /* ...But if this file is merely the descendant of an explicitly
-         copied/moved directory, we need to do a bit more work to
-         determine copyfrom_url and copyfrom_rev. */
-      const char *op_root_abspath;
-
-      SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath, NULL, NULL,
-                                       NULL, &original_repos_relpath,
-                                       &original_root_url, NULL,
-                                       &original_revision, db, src_abspath,
-                                       scratch_pool, scratch_pool));
-      if (status == svn_wc__db_status_copied ||
-          status == svn_wc__db_status_moved_here)
-        {
-          const char *src_parent_url;
-          const char *src_relpath;
-
-          src_parent_url = svn_path_url_add_component2(original_root_url,
-                                                       original_repos_relpath,
-                                                       scratch_pool);
-          src_relpath = svn_dirent_is_child(op_root_abspath, src_abspath,
-                                            scratch_pool);
-          if (src_relpath)
-            url = svn_path_url_add_component2(src_parent_url, src_relpath,
-                                              scratch_pool);
-        }
-    }
-
-  if (url && dst_url && strcmp(url, dst_url) == 0 &&
-      original_revision == dst_revision)
-    {
-      /* Suppress copyfrom info when the copy source is the same as
-         for the destination. */
-      url = NULL;
-      original_revision = SVN_INVALID_REVNUM;
-    }
-
-  if (url)
-    *copyfrom_url = apr_pstrdup(result_pool, url);
-  else
-    *copyfrom_url = NULL;
-  *copyfrom_rev = original_revision;
-
-  return SVN_NO_ERROR;
-}
-
+#ifndef SVN_EXPERIMENTAL_COPY
 /* This function effectively creates and schedules a file for
    addition, but does extra administrative things to allow it to
    function as a 'copy'.
@@ -426,20 +346,26 @@ copy_file_administratively(svn_wc_contex
     apr_hash_t *props, *base_props;
     svn_stream_t *base_contents;
     svn_stream_t *contents;
-    svn_boolean_t src_exists;
-
-    src_exists = TRUE;
 
     /* Are we moving or copying a file that is already moved or copied
        but not committed? */
     if (src_entry->copied)
       {
-        SVN_ERR(determine_copyfrom_info(&copyfrom_url, &copyfrom_rev, db,
-                                        src_abspath,
-                                        dst_entry ? dst_entry->url : NULL,
-                                        dst_entry ? dst_entry->revision
-                                                  : SVN_INVALID_REVNUM,
-                                        scratch_pool, scratch_pool));
+        SVN_ERR(svn_wc__node_get_copyfrom_info(&copyfrom_url, &copyfrom_rev,
+                                               NULL, wc_ctx, src_abspath,
+                                               scratch_pool, scratch_pool));
+
+        /* If the COPYFROM information is the SAME as the destination
+           URL/REVISION, then omit the copyfrom info.  */
+        if (dst_entry != NULL
+            && dst_entry->revision == copyfrom_rev
+            && copyfrom_url != NULL
+            && dst_entry->url != NULL
+            && strcmp(copyfrom_url, dst_entry->url) == 0)
+          {
+            copyfrom_url = NULL;
+            copyfrom_rev = SVN_INVALID_REVNUM;
+          }
       }
     else
       {
@@ -449,8 +375,10 @@ copy_file_administratively(svn_wc_contex
       }
 
     /* Load source base and working props. */
-    SVN_ERR(svn_wc__load_props(&base_props, &props, db,
-                               src_abspath, scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__get_pristine_props(&base_props, db, src_abspath,
+                                       scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__get_actual_props(&props, db, src_abspath,
+                                     scratch_pool, scratch_pool));
 
     /* Copy working copy file to temporary location */
     {
@@ -481,8 +409,6 @@ copy_file_administratively(svn_wc_contex
             {
               svn_error_clear(err);
 
-              src_exists = FALSE;
-
               err = svn_wc__get_pristine_contents(&contents, db, src_abspath,
                                                   scratch_pool, scratch_pool);
 
@@ -522,7 +448,8 @@ copy_file_administratively(svn_wc_contex
         }
     }
 
-    SVN_ERR(svn_wc_get_pristine_contents2(&base_contents, wc_ctx, src_abspath,
+    SVN_ERR(svn_wc__get_pristine_contents(&base_contents,
+                                          wc_ctx->db, src_abspath,
                                           scratch_pool, scratch_pool));
     /* Above add/replace condition should have caught this already
      * (-> error "Cannot copy..."). */
@@ -551,6 +478,7 @@ copy_file_administratively(svn_wc_contex
 
   return SVN_NO_ERROR;
 }
+#endif
 
 
 /* Recursively crawl over a directory PATH and do a number of things:
@@ -631,9 +559,9 @@ post_copy_cleanup(svn_wc__db_t *db,
          with creating a directory.  See Issue #2101 for details. */
       if (entry->deleted)
         {
-          apr_uint64_t flags = (SVN_WC__ENTRY_MODIFY_FORCE
-                                | SVN_WC__ENTRY_MODIFY_SCHEDULE
-                                | SVN_WC__ENTRY_MODIFY_DELETED);
+          int modify_flags = (SVN_WC__ENTRY_MODIFY_FORCE
+                              | SVN_WC__ENTRY_MODIFY_SCHEDULE
+                              | SVN_WC__ENTRY_MODIFY_DELETED);
           svn_wc_entry_t tmp_entry;
 
           tmp_entry.schedule = svn_wc_schedule_delete;
@@ -659,11 +587,11 @@ post_copy_cleanup(svn_wc__db_t *db,
               schedule delete until the copy is committed, when they become
               state deleted and everything works! */
               tmp_entry.kind = svn_node_file;
-              flags |= SVN_WC__ENTRY_MODIFY_KIND;
+              modify_flags |= SVN_WC__ENTRY_MODIFY_KIND;
             }
 
-          SVN_ERR(svn_wc__entry_modify2(db, child_abspath, svn_node_unknown,
-                                        FALSE, &tmp_entry, flags, iterpool));
+          SVN_ERR(svn_wc__entry_modify(db, child_abspath, svn_node_unknown,
+                                       &tmp_entry, modify_flags, iterpool));
         }
 
       /* Remove lock stuffs. */
@@ -704,6 +632,8 @@ copy_dir_administratively(svn_wc_context
 {
   const svn_wc_entry_t *src_entry;
   svn_wc__db_t *db = wc_ctx->db;
+  const char *dir_abspath;
+  const char *name;
 
   /* Sanity check 1: You cannot make a copy of something that's not
      under version control. */
@@ -725,18 +655,23 @@ copy_dir_administratively(svn_wc_context
      schedulings, existences, etc.
 
       ### Should we be copying unversioned items within the directory? */
+  svn_dirent_split(dst_abspath, &dir_abspath, &name, scratch_pool);
   SVN_ERR(svn_io_copy_dir_recursively(src_abspath,
-                                      svn_dirent_dirname(dst_abspath,
-                                                         scratch_pool),
-                                      svn_dirent_basename(dst_abspath, NULL),
-                                      TRUE,
+                                      dir_abspath,
+                                      name,
+                                      TRUE /* copy_perms */,
                                       cancel_func, cancel_baton,
                                       scratch_pool));
 
-  /* If this is part of a move, the copied directory will be locked,
-     because the source directory was locked.  Running cleanup will remove
-     the locks, even though this directory has not yet been added to the
-     parent. */
+  /* ### the wc.db databases have locks in them, based on the source paths.
+     ### go through and clean out those locks. this should go away in the
+     ### single-db case, but would probably also be fixed if we revamped
+     ### the copy algorithm to: copy all metadata, copy all pristines,
+     ### then install all working copy files from those pristines.
+     ###
+     ### hmm. that would not carry over local edits, however.
+     ### more thinking required...
+  */
   SVN_ERR(svn_wc_cleanup3(wc_ctx, dst_abspath, cancel_func, cancel_baton,
                           scratch_pool));
 
@@ -759,35 +694,138 @@ copy_dir_administratively(svn_wc_context
         SVN_ERR(svn_wc__get_entry(&dst_entry, db, dst_abspath, TRUE,
                                   svn_node_dir, TRUE,
                                   scratch_pool, scratch_pool));
-        SVN_ERR(determine_copyfrom_info(&copyfrom_url, &copyfrom_rev, db,
-                                        src_abspath,
-                                        dst_entry ? dst_entry->url : NULL,
-                                        dst_entry ? dst_entry->revision
-                                                  : SVN_INVALID_REVNUM,
-                                        scratch_pool, scratch_pool));
+        SVN_ERR(svn_wc__node_get_copyfrom_info(&copyfrom_url, &copyfrom_rev,
+                                               NULL, wc_ctx, src_abspath,
+                                               scratch_pool, scratch_pool));
+
+        /* If the COPYFROM information is the SAME as the destination
+           URL/REVISION, then omit the copyfrom info.  */
+        if (dst_entry != NULL
+            && dst_entry->revision == copyfrom_rev
+            && copyfrom_url != NULL
+            && dst_entry->url != NULL
+            && strcmp(copyfrom_url, dst_entry->url) == 0)
+          {
+            copyfrom_url = NULL;
+            copyfrom_rev = SVN_INVALID_REVNUM;
+          }
 
         /* The URL for a copied dir won't exist in the repository, which
            will cause  svn_wc_add4() below to fail.  Set the URL to the
            URL of the first copy for now to prevent this. */
         tmp_entry.url = apr_pstrdup(scratch_pool, copyfrom_url);
-        SVN_ERR(svn_wc__entry_modify2(db, dst_abspath, svn_node_dir, FALSE,
-                                      &tmp_entry, SVN_WC__ENTRY_MODIFY_URL,
-                                      scratch_pool));
+        SVN_ERR(svn_wc__entry_modify(db, dst_abspath, svn_node_dir,
+                                     &tmp_entry, SVN_WC__ENTRY_MODIFY_URL,
+                                     scratch_pool));
       }
     else
       {
         SVN_ERR(svn_wc__internal_get_ancestry(&copyfrom_url, &copyfrom_rev,
-                                              db, src_abspath, scratch_pool,
-                                              scratch_pool));
+                                              db, src_abspath,
+                                              scratch_pool, scratch_pool));
       }
 
-    return svn_wc_add4(wc_ctx, dst_abspath, svn_depth_infinity,
-                       copyfrom_url, copyfrom_rev,
-                       cancel_func, cancel_baton,
-                       notify_copied, notify_baton, scratch_pool);
+    return svn_error_return(svn_wc_add4(wc_ctx, dst_abspath,
+                                        svn_depth_infinity,
+                                        copyfrom_url, copyfrom_rev,
+                                        cancel_func, cancel_baton,
+                                        notify_copied, notify_baton,
+                                        scratch_pool));
   }
 }
 
+#ifdef SVN_EXPERIMENTAL_COPY
+/* A replacement for both copy_file_administratively and
+   copy_added_file_administratively.  Not yet fully working.  Relies
+   on in-db-props.  */
+static svn_error_t *
+copy_versioned_file(svn_wc_context_t *wc_ctx,
+                    const char *src_abspath,
+                    const char *dst_abspath,
+                    svn_cancel_func_t cancel_func,
+                    void *cancel_baton,
+                    svn_wc_notify_func2_t notify_func,
+                    void *notify_baton,
+                    apr_pool_t *scratch_pool)
+{
+  svn_skel_t *work_items = NULL;
+  const char *dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
+  const char *tmpdir_abspath;
+  svn_stream_t *src, *src_pristine;
+  const char *tmp_dst_abspath;
+  svn_error_t *err;
+
+  SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, wc_ctx->db,
+                                         dst_abspath,
+                                         scratch_pool, scratch_pool));
+
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+  SVN_ERR(svn_wc__get_pristine_contents(&src_pristine, wc_ctx->db,
+                                        src_abspath,
+                                        scratch_pool, scratch_pool));
+  if (src_pristine)
+    {
+      svn_skel_t *work_item;
+      svn_stream_t *tmp_pristine;
+      const char *tmp_pristine_abspath, *dst_pristine_abspath;
+
+      SVN_ERR(svn_stream_open_unique(&tmp_pristine, &tmp_pristine_abspath,
+                                     tmpdir_abspath, svn_io_file_del_none,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_stream_copy3(src_pristine, tmp_pristine,
+                               cancel_func, cancel_baton, scratch_pool));
+      SVN_ERR(svn_wc__text_base_path(&dst_pristine_abspath, wc_ctx->db,
+                                     dst_abspath, scratch_pool));
+      SVN_ERR(svn_wc__loggy_move(&work_item, wc_ctx->db, dir_abspath,
+                                 tmp_pristine_abspath, dst_pristine_abspath,
+                                 scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+#endif
+
+  err = svn_stream_open_readonly(&src, src_abspath, scratch_pool, scratch_pool);
+  if (err)
+    {
+      if (!APR_STATUS_IS_ENOENT(err->apr_err))
+        return svn_error_return(err);
+      /* Source may not exist when recursively copying a directory. */
+      svn_error_clear(err);
+    }
+  else
+    {
+      svn_skel_t *work_item;
+      svn_stream_t *tmp_dst;
+
+      SVN_ERR(svn_stream_open_unique(&tmp_dst, &tmp_dst_abspath,
+                                     tmpdir_abspath, svn_io_file_del_none,
+                                     scratch_pool, scratch_pool));
+      SVN_ERR(svn_io_copy_perms(src_abspath,
+                                tmp_dst_abspath, scratch_pool));
+      SVN_ERR(svn_stream_copy3(src, tmp_dst,
+                               cancel_func, cancel_baton, scratch_pool));
+      SVN_ERR(svn_wc__loggy_move(&work_item, wc_ctx->db, dir_abspath,
+                                 tmp_dst_abspath, dst_abspath,
+                                 scratch_pool));
+      work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
+    }
+
+  SVN_ERR(svn_wc__db_op_copy(wc_ctx->db, src_abspath, dst_abspath,
+                             work_items, scratch_pool));
+  SVN_ERR(svn_wc__wq_run(wc_ctx->db, dir_abspath,
+                         cancel_func, cancel_baton, scratch_pool));
+
+  if (notify_func)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(dst_abspath, svn_wc_notify_add,
+                               scratch_pool);
+      notify->kind = svn_node_file;
+      (*notify_func)(notify_baton, notify, scratch_pool);
+    }
+  return SVN_NO_ERROR;
+}
+#endif
+
 
 
 /* Public Interface */
@@ -872,6 +910,7 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
   if (src_kind == svn_node_file ||
       (src_entry->kind == svn_node_file && src_kind == svn_node_none))
     {
+#ifndef SVN_EXPERIMENTAL_COPY
       /* Check if we are copying a file scheduled for addition,
          these require special handling. */
       if (src_entry->schedule == svn_wc_schedule_add
@@ -893,6 +932,42 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
                                              notify_func, notify_baton,
                                              scratch_pool));
         }
+#else
+      svn_node_kind_t dst_kind, dst_db_kind;
+
+      /* This is the error checking from copy_file_administratively
+         but converted to wc-ng.  It's not in copy_file since this
+         checking only needs to happen at the root of the copy and not
+         when called recursively. */
+      SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind, scratch_pool));
+      if (dst_kind != svn_node_none)
+        return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
+                                 _("'%s' already exists and is in the way"),
+                                 svn_dirent_local_style(dst_abspath,
+                                                        scratch_pool));
+      SVN_ERR(svn_wc_read_kind(&dst_db_kind, wc_ctx, dst_abspath, TRUE,
+                               scratch_pool));
+      if (dst_db_kind != svn_node_none)
+        {
+          svn_boolean_t is_deleted, is_present;
+
+          SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, wc_ctx,
+                                                 dst_abspath, scratch_pool));
+          SVN_ERR(svn_wc__node_is_status_present(&is_present, wc_ctx,
+                                                 dst_abspath, scratch_pool));
+          if (is_present && !is_deleted)
+            return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
+                               _("There is already a versioned item '%s'"),
+                               svn_dirent_local_style(dst_abspath,
+                                                      scratch_pool));
+
+        }
+
+      SVN_ERR(copy_versioned_file(wc_ctx, src_abspath, dst_abspath,
+                                  cancel_func, cancel_baton,
+                                  notify_func, notify_baton,
+                                  scratch_pool));
+#endif
     }
   else if (src_kind == svn_node_dir)
     {

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/crop.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/crop.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/crop.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/crop.c Tue Aug 10 20:55:56 2010
@@ -91,7 +91,8 @@ crop_children(svn_wc__db_t *db,
   /* Update the depth of target first, if needed. */
   if (dir_depth > depth)
     {
-      SVN_ERR(svn_wc__set_depth(db, local_abspath, depth, iterpool));
+      SVN_ERR(svn_wc__db_temp_op_set_dir_depth(db, local_abspath, depth,
+                                               iterpool));
     }
 
   /* Looping over current directory's SVN entries: */
@@ -126,7 +127,8 @@ crop_children(svn_wc__db_t *db,
                                             ? svn_depth_immediates
                                             : svn_depth_files;
           if (depth < remove_below)
-            SVN_ERR(svn_wc__entry_remove(db, local_abspath, iterpool));
+            SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath,
+                                                    iterpool));
 
           continue;
         }
@@ -301,6 +303,7 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx,
                                           revision,
                                           kind,
                                           svn_wc__db_status_excluded,
+                                          NULL, NULL,
                                           scratch_pool));
 
   if (notify_func)

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/deprecated.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/deprecated.c Tue Aug 10 20:55:56 2010
@@ -26,6 +26,8 @@
    deprecated functions in this file. */
 #define SVN_DEPRECATED
 
+#include <apr_md5.h>
+
 #include "svn_wc.h"
 #include "svn_subst.h"
 #include "svn_pools.h"
@@ -409,16 +411,23 @@ svn_wc_transmit_text_deltas2(const char 
 {
   const char *local_abspath;
   svn_wc_context_t *wc_ctx;
+  const svn_checksum_t *new_text_base_md5_checksum;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
                                          svn_wc__adm_get_db(adm_access),
                                          pool));
 
-  SVN_ERR(svn_wc_transmit_text_deltas3(tempfile, digest, wc_ctx,
+  SVN_ERR(svn_wc_transmit_text_deltas3(tempfile,
+                                       digest ? &new_text_base_md5_checksum
+                                              : NULL,
+                                       NULL, wc_ctx,
                                        local_abspath, fulltext, editor,
                                        file_baton, pool, pool));
 
+  if (digest)
+    memcpy(digest, new_text_base_md5_checksum->digest, APR_MD5_DIGESTSIZE);
+
   return svn_error_return(svn_wc_context_destroy(wc_ctx));
 }
 
@@ -584,7 +593,7 @@ svn_wc_process_committed4(const char *pa
                                              new_revnum, new_date, rev_author,
                                              wcprop_changes_hash,
                                              !remove_lock, !remove_changelist,
-                                             checksum, NULL, pool));
+                                             checksum, NULL, NULL, pool));
 
   /* Run the log file(s) we just created. */
   return svn_error_return(svn_wc__wq_run(db, local_abspath, NULL, NULL, pool));
@@ -741,13 +750,13 @@ svn_wc_add3(const char *path,
   /* Make sure the caller gets the new access baton in the set. */
   if (svn_wc__adm_retrieve_internal2(wc_db, local_abspath, pool) == NULL)
     {
-      svn_node_kind_t kind;
-      svn_wc_adm_access_t *adm_access;
-
-      SVN_ERR(svn_wc__node_get_kind(&kind, wc_ctx, local_abspath, FALSE, pool));
+      svn_wc__db_kind_t kind;
 
-      if (kind == svn_node_dir)
+      SVN_ERR(svn_wc__db_read_kind(&kind, wc_db, local_abspath, FALSE, pool));
+      if (kind == svn_wc__db_kind_dir)
         {
+          svn_wc_adm_access_t *adm_access;
+
           /* Open the access baton in adm_access' pool to give it the same
              lifetime */
           SVN_ERR(svn_wc_adm_open3(&adm_access, parent_access, path, TRUE,
@@ -1044,17 +1053,14 @@ svn_wc_get_ancestry(char **url,
                     apr_pool_t *pool)
 {
   const char *local_abspath;
-  svn_wc_context_t *wc_ctx;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
-                                         svn_wc__adm_get_db(adm_access),
-                                         pool));
-
-  SVN_ERR(svn_wc_get_ancestry2((const char **)url, rev, wc_ctx, local_abspath,
-                               pool, pool));
 
-  return svn_error_return(svn_wc_context_destroy(wc_ctx));
+  return svn_error_return(svn_wc__internal_get_ancestry(
+                            (const char **)url, rev,
+                            svn_wc__adm_get_db(adm_access),
+                            local_abspath,
+                            pool, pool));
 }
 
 svn_error_t *
@@ -1616,6 +1622,7 @@ wrap_4to3_dir_props_changed(const char *
 static svn_error_t *
 wrap_4to3_dir_opened(const char *local_dir_abspath,
                      svn_boolean_t *tree_conflicted,
+                     svn_boolean_t *skip_children,
                      const char *path,
                      svn_revnum_t rev,
                      void *diff_baton,
@@ -1627,6 +1634,8 @@ wrap_4to3_dir_opened(const char *local_d
   if (local_dir_abspath)
     adm_access = svn_wc__adm_retrieve_internal2(b->db, local_dir_abspath,
                                                 scratch_pool);
+  if (skip_children)
+    *skip_children = FALSE;
 
   return b->callbacks3->dir_opened(adm_access, tree_conflicted, path, rev,
                                    b->baton);
@@ -2124,29 +2133,25 @@ svn_wc_merge_props2(svn_wc_notify_state_
                     svn_boolean_t dry_run,
                     svn_wc_conflict_resolver_func_t conflict_func,
                     void *conflict_baton,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
-  svn_wc_context_t *wc_ctx;
   const char *local_abspath;
 
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
-                                         svn_wc__adm_get_db(adm_access), pool));
-
-  SVN_ERR(svn_wc_merge_props3(state,
-                              wc_ctx,
-                              local_abspath,
-                              NULL, /* left_version */
-                              NULL, /* right_version */
-                              baseprops,
-                              propchanges,
-                              base_merge,
-                              dry_run,
-                              conflict_func, conflict_baton,
-                              NULL, NULL,
-                              pool));
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
 
-  return svn_error_return(svn_wc_context_destroy(wc_ctx));
+  return svn_error_return(svn_wc__perform_props_merge(
+                            state,
+                            svn_wc__adm_get_db(adm_access),
+                            local_abspath,
+                            NULL /* left_version */,
+                            NULL /* right_version */,
+                            baseprops,
+                            propchanges,
+                            base_merge,
+                            dry_run,
+                            conflict_func, conflict_baton,
+                            NULL, NULL,
+                            scratch_pool));
 }
 
 svn_error_t *
@@ -2224,19 +2229,23 @@ struct status4_wrapper_baton
   void *old_baton;
   const char *anchor_abspath;
   const char *anchor_relpath;
+  svn_wc_context_t *wc_ctx;
 };
 
 /* */
 static svn_error_t *
 status4_wrapper_func(void *baton,
                      const char *local_abspath,
-                     const svn_wc_status2_t *status,
+                     const svn_wc_status3_t *status,
                      apr_pool_t *scratch_pool)
 {
   struct status4_wrapper_baton *swb = baton;
-  svn_wc_status2_t *dup = svn_wc_dup_status2(status, scratch_pool);
+  svn_wc_status2_t *dup;
   const char *path = local_abspath;
 
+  SVN_ERR(svn_wc__status2_from_3(&dup, status, swb->wc_ctx, local_abspath,
+                                 scratch_pool, scratch_pool));
+
   if (swb->anchor_abspath != NULL)
     {
       path = svn_dirent_join(
@@ -2281,6 +2290,8 @@ svn_wc_get_status_editor4(const svn_delt
   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
                                          wc_db, pool));
 
+  swb->wc_ctx = wc_ctx;
+
   anchor_abspath = svn_wc__adm_access_abspath(anchor);
 
   if (!svn_dirent_is_absolute(svn_wc_adm_access_path(anchor)))
@@ -2468,6 +2479,37 @@ svn_wc_status(svn_wc_status_t **status,
   return SVN_NO_ERROR;
 }
 
+svn_wc_status2_t *
+svn_wc_dup_status2(const svn_wc_status2_t *orig_stat,
+                   apr_pool_t *pool)
+{
+  svn_wc_status2_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
+
+  /* Shallow copy all members. */
+  *new_stat = *orig_stat;
+
+  /* Now go back and dup the deep items into this pool. */
+  if (orig_stat->entry)
+    new_stat->entry = svn_wc_entry_dup(orig_stat->entry, pool);
+
+  if (orig_stat->repos_lock)
+    new_stat->repos_lock = svn_lock_dup(orig_stat->repos_lock, pool);
+
+  if (orig_stat->url)
+    new_stat->url = apr_pstrdup(pool, orig_stat->url);
+
+  if (orig_stat->ood_last_cmt_author)
+    new_stat->ood_last_cmt_author
+      = apr_pstrdup(pool, orig_stat->ood_last_cmt_author);
+
+  if (orig_stat->tree_conflict)
+    new_stat->tree_conflict
+      = svn_wc__conflict_description_dup(orig_stat->tree_conflict, pool);
+
+  /* Return the new hotness. */
+  return new_stat;
+}
+
 svn_wc_status_t *
 svn_wc_dup_status(const svn_wc_status_t *orig_stat,
                   apr_pool_t *pool)
@@ -2515,13 +2557,16 @@ svn_wc_status2(svn_wc_status2_t **status
 {
   const char *local_abspath;
   svn_wc_context_t *wc_ctx;
+  svn_wc_status3_t *stat3;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
                                          svn_wc__adm_get_db(adm_access),
                                          pool));
 
-  SVN_ERR(svn_wc_status3(status, wc_ctx, local_abspath, pool, pool));
+  SVN_ERR(svn_wc_status3(&stat3, wc_ctx, local_abspath, pool, pool));
+  SVN_ERR(svn_wc__status2_from_3(status, stat3, wc_ctx, local_abspath,
+                                 pool, pool));
 
   return svn_error_return(svn_wc_context_destroy(wc_ctx));
 }
@@ -3160,7 +3205,7 @@ svn_wc_translated_file2(const char **xla
                                          pool));
 
   SVN_ERR(svn_wc_translated_file3(xlated_path, src, wc_ctx, versioned_abspath,
-                                  flags, pool, pool));
+                                  flags, NULL, NULL, pool, pool));
   if (! svn_dirent_is_absolute(versioned_file))
     {
       SVN_ERR(svn_io_temp_dir(&tmp_root, pool));
@@ -3710,15 +3755,15 @@ svn_wc_queue_committed2(svn_wc_committed
                         const apr_array_header_t *wcprop_changes,
                         svn_boolean_t remove_lock,
                         svn_boolean_t remove_changelist,
-                        const svn_checksum_t *checksum,
+                        const svn_checksum_t *md5_checksum,
                         apr_pool_t *scratch_pool)
 {
   const char *local_abspath;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
   return svn_wc_queue_committed3(queue, local_abspath, recurse, wcprop_changes,
-                                 remove_lock, remove_changelist, checksum,
-                                 scratch_pool);
+                                 remove_lock, remove_changelist, md5_checksum,
+                                 NULL /* sha1_checksum */, scratch_pool);
 }
 
 svn_error_t *
@@ -3732,18 +3777,18 @@ svn_wc_queue_committed(svn_wc_committed_
                        const unsigned char *digest,
                        apr_pool_t *pool)
 {
-  const svn_checksum_t *checksum;
+  const svn_checksum_t *md5_checksum;
 
   if (digest)
-    checksum = svn_checksum__from_digest(
+    md5_checksum = svn_checksum__from_digest(
                    digest, svn_checksum_md5,
                    svn_wc__get_committed_queue_pool(*queue));
   else
-    checksum = NULL;
+    md5_checksum = NULL;
 
   return svn_wc_queue_committed2(*queue, path, adm_access, recurse,
                                  wcprop_changes, remove_lock,
-                                 remove_changelist, checksum, pool);
+                                 remove_changelist, md5_checksum, pool);
 }
 
 svn_error_t *
@@ -3766,3 +3811,45 @@ svn_wc_process_committed_queue(svn_wc_co
   return SVN_NO_ERROR;
 }
 
+#ifdef SVN_DISABLE_FULL_VERSION_MATCH
+/* This double underscore name is used by the 1.6 libsvn_client.
+   Keeping this name is sufficient for the 1.6 libsvn_client to link
+   against the 1.7 libraries.  This is only needed for pre-release
+   testing, it's not needed when all the Subversion libraries are
+   upgraded together. */
+svn_error_t *
+svn_wc__entry_versioned_internal(const svn_wc_entry_t **entry,
+                                 const char *path,
+                                 svn_wc_adm_access_t *adm_access,
+                                 svn_boolean_t show_hidden,
+                                 const char *caller_filename,
+                                 int caller_lineno,
+                                 apr_pool_t *pool);
+svn_error_t *
+svn_wc__entry_versioned_internal(const svn_wc_entry_t **entry,
+                                 const char *path,
+                                 svn_wc_adm_access_t *adm_access,
+                                 svn_boolean_t show_hidden,
+                                 const char *caller_filename,
+                                 int caller_lineno,
+                                 apr_pool_t *pool)
+{
+  svn_wc_context_t *wc_ctx;
+  const char *local_abspath;
+
+  SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
+                                         svn_wc__adm_get_db(adm_access),
+                                         pool));
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+  SVN_ERR(svn_wc__get_entry_versioned(entry, wc_ctx, local_abspath,
+                                      svn_node_unknown, show_hidden,
+                                      FALSE, /* NEED_PARENT_STUB */
+                                      pool, pool));
+
+  SVN_ERR(svn_wc_context_destroy(wc_ctx));
+
+  return SVN_NO_ERROR;
+}
+#endif

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/diff.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/diff.c Tue Aug 10 20:55:56 2010
@@ -125,6 +125,103 @@ reverse_propchanges(apr_hash_t *baseprop
 }
 
 
+/* Set *RESULT_ABSPATH to the absolute path to a readable file containing
+   the pristine text of LOCAL_ABSPATH in DB, or to NULL if it does not have
+   any pristine text.  If the node has more than one pristine text, get the
+   one that is "nearest" to the working version.  That means the pristine
+   text of the copied file if this node is copied or moved here, else of the
+   replaced file if it is an add that replaces a file, else of its base
+   node, or NULL if it is a simple add or an add that replaces a non-file.
+
+   Rationale:
+
+   Which text-base do we want to use for the diff?  If the node is replaced
+   by a new file, then the base of the replaced file is called (in WC-1) the
+   "revert base".  If the replacement is a copy or move, then there is also
+   the base of the copied file to consider.
+
+   One could argue that we should never diff against the revert
+   base, and instead diff against the empty-file for both types of
+   replacement.  After all, there is no ancestry relationship
+   between the working file and the base file.  But my guess is that
+   in practice, users want to see the diff between their working
+   file and "the nearest versioned thing", whatever that is.  I'm
+   not 100% sure this is the right decision, but it at least seems
+   to match our test suite's expectations. */
+static svn_error_t *
+get_nearest_pristine_text_as_file(const char **result_abspath,
+                                  svn_wc__db_t *db,
+                                  const char *local_abspath,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
+{
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+  const svn_checksum_t *checksum;
+
+  SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, &checksum,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               db, local_abspath, scratch_pool, scratch_pool));
+  if (checksum == NULL)
+    {
+      svn_error_t *err;
+
+      err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL, &checksum,
+                                     NULL, NULL, NULL,
+                                     db, local_abspath,
+                                     scratch_pool, scratch_pool);
+      if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+        {
+          svn_error_clear(err);
+          checksum = NULL;
+        }
+      else if (err)
+        return svn_error_return(err);
+    }
+
+  if (checksum != NULL)
+    {
+      SVN_ERR(svn_wc__db_pristine_get_path(result_abspath, db, local_abspath,
+                                           checksum,
+                                           result_pool, scratch_pool));
+      return SVN_NO_ERROR;
+    }
+#else
+  svn_error_t *err;
+
+  err = svn_wc__text_base_path_to_read(result_abspath, db, local_abspath,
+                                       result_pool, scratch_pool);
+
+  if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+    svn_error_clear(err);
+  else
+    return svn_error_return(err);
+
+  err = svn_wc__text_revert_path_to_read(result_abspath, db, local_abspath,
+                                         result_pool);
+
+  /* If there is no revert base to diff either, don't attempt to diff it.
+     ### This is a band-aid.
+     ### In WC-NG, files added within a copied subtree are marked "copied",
+     ### which will cause the code below to end up calling
+     ### eb->callbacks->file_changed() with a non-existent text-base.
+     ### Not sure how to properly tell apart a file added within a copied
+     ### subtree from a copied file. But eventually we'll have to get the
+     ### base text from the pristine store anyway and use tempfiles (or
+     ### streams, hopefully) for diffing, so this hack will just go away. */
+  if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+    svn_error_clear(err);
+  else
+    return svn_error_return(err);
+#endif
+
+  *result_abspath = NULL;
+  return SVN_NO_ERROR;
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 
@@ -444,66 +541,6 @@ get_prop_mimetype(apr_hash_t *props)
 }
 
 
-/* Set *MIMETYPE to the BASE version of the svn:mime-type property of
-   file LOCAL_ABSPATH, using DB, or to NULL if no such property exists.
-   BASEPROPS is optional: if present, use it to cache the BASE properties
-   of the file.
-
-   Return the property value and property hash allocated in RESULT_POOL,
-   use SCRATCH_POOL for temporary accesses.
-*/
-static svn_error_t *
-get_base_mimetype(const char **mimetype,
-                  apr_hash_t **baseprops,
-                  svn_wc__db_t *db,
-                  const char *local_abspath,
-                  apr_pool_t *result_pool,
-                  apr_pool_t *scratch_pool)
-{
-  apr_hash_t *props = NULL;
-
-  if (baseprops == NULL)
-    baseprops = &props;
-
-  if (*baseprops == NULL)
-    SVN_ERR(svn_wc__internal_propdiff(NULL, baseprops, db, local_abspath,
-                                      result_pool, scratch_pool));
-
-  *mimetype = get_prop_mimetype(*baseprops);
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Set *MIMETYPE to the WORKING version of the svn:mime-type property
-   of file LOCAL_ABSPATH, using DB, or to NULL if no such property exists.
-   WORKINGPROPS is optional: if present, use it to cache the WORKING
-   properties of the file.
-
-   Return the property value and property hash allocated in POOL.
-*/
-static svn_error_t *
-get_working_mimetype(const char **mimetype,
-                     apr_hash_t **workingprops,
-                     const char *local_abspath,
-                     svn_wc__db_t *db,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
-{
-  apr_hash_t *props = NULL;
-
-  if (workingprops == NULL)
-    workingprops = &props;
-
-  if (*workingprops == NULL)
-    SVN_ERR(svn_wc__load_props(NULL, workingprops, db, local_abspath,
-                               result_pool, scratch_pool));
-
-  *mimetype = get_prop_mimetype(*workingprops);
-
-  return SVN_NO_ERROR;
-}
-
 /* Return the property hash resulting from combining PROPS and PROPCHANGES.
  *
  * A note on pool usage: The returned hash and hash keys are allocated in
@@ -529,7 +566,7 @@ apply_propchanges(apr_hash_t *props,
 }
 
 
-/* Called by directory_elements_diff when a file is to be compared. At this
+/* Diff the file PATH against its text base.  At this
  * stage we are dealing with a file that does exist in the working copy.
  *
  * DIR_BATON is the parent directory baton, PATH is the path to the file to
@@ -551,8 +588,9 @@ file_diff(struct dir_baton *db,
   svn_boolean_t replaced;
   svn_wc__db_status_t status;
   svn_revnum_t revision;
-  apr_array_header_t *propchanges = NULL;
-  apr_hash_t *baseprops = NULL;
+  svn_revnum_t revert_base_revnum;
+  svn_boolean_t base_shadowed;
+  svn_wc__db_status_t base_status;
   const char *local_abspath;
 
   SVN_ERR_ASSERT(! eb->use_text_base);
@@ -570,83 +608,47 @@ file_diff(struct dir_baton *db,
   SVN_ERR(svn_wc__db_read_info(&status, NULL, &revision, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, eb->db, local_abspath,
-                               pool, pool));
+                               &base_shadowed, NULL, NULL,
+                               eb->db, local_abspath, pool, pool));
+  if (base_shadowed)
+    SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &revert_base_revnum,
+                                     NULL, NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL, NULL,
+                                     eb->db, local_abspath, pool, pool));
+
+  replaced = ((status == svn_wc__db_status_added
+               || status == svn_wc__db_status_obstructed_add)
+              && base_shadowed
+              && base_status != svn_wc__db_status_not_present);
 
+  /* Now refine ADDED to one of: ADDED, COPIED, MOVED_HERE. Note that only
+     the latter two have corresponding pristine info to diff against.  */
   if (status == svn_wc__db_status_added)
     SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
                                      NULL, NULL, NULL, eb->db, local_abspath,
                                      pool, pool));
 
-  /* Prep these two paths early. */
-  SVN_ERR(svn_wc__text_base_path(&textbase, eb->db, local_abspath, FALSE,
-                                 pool));
-
-  /* If the regular text base is not there, we fall back to the revert
-     text base (if that's not present either, we'll error later).  But
-     the logic here is subtler than one might at first expect.
-
-     When the file has some non-replacement scheduling, then it can be
-     expected to still have its regular text base.  But what about
-     when it's replaced or replaced-with-history?  In both cases, a
-     revert text-base will be present; in the latter case only, a
-     regular text-base be present as well.  So which text-base do we
-     want to use for the diff?
-
-     One could argue that we should never diff against the revert
-     base, and instead diff against the empty-file for both types of
-     replacement.  After all, there is no ancestry relationship
-     between the working file and the base file.  But my guess is that
-     in practice, users want to see the diff between their working
-     file and "the nearest versioned thing", whatever that is.  I'm
-     not 100% sure this is the right decision, but it at least seems
-     to match our test suite's expectations. */
-  {
-    svn_node_kind_t kind;
-    SVN_ERR(svn_io_check_path(textbase, &kind, pool));
-    if (kind == svn_node_none)
-      SVN_ERR(svn_wc__text_revert_path(&textbase, eb->db, local_abspath,
-                                       pool));
-
-    /* If there is no revert base to diff either, don't attempt to diff it.
-     * ### This is a band-aid.
-     * ### In WC-NG, files added within a copied subtree are marked "copied",
-     * ### which will cause the code below to end up calling
-     * ### eb->callbacks->file_changed() with a non-existent text-base.
-     * ### Not sure how to properly tell apart a file added within a copied
-     * ### subtree from a copied file. But eventually we'll have to get the
-     * ### base text from the pristine store anyway and use tempfiles (or
-     * ### streams, hopefully) for diffing, so all this horrible statting
-     * ### the disk for text bases, and this hack, will just go away. */
-    SVN_ERR(svn_io_check_path(textbase, &kind, pool));
-    if (kind == svn_node_none)
-      textbase = NULL;
-  }
+  /* A wc-wc diff of replaced files actually shows a diff against the
+   * revert-base, showing all previous lines as removed and adding all new
+   * lines. This does not happen for copied/moved-here files, not even with
+   * show_copies_as_adds == TRUE (in which case copy/move is really shown as
+   * an add, diffing against the empty file).
+   * So show the revert-base revision for plain replaces. */
+  if (replaced
+      && ! (status == svn_wc__db_status_copied
+            || status == svn_wc__db_status_moved_here))
+    revision = revert_base_revnum;
+
+  /* Set TEXTBASE to the path to the text-base file that we want to diff
+     against.
+
+     ### There shouldn't be cases where the result is NULL, but at present
+     there might be - see get_nearest_pristine_text_as_file(). */
+  SVN_ERR(get_nearest_pristine_text_as_file(&textbase, eb->db, local_abspath,
+                                            pool, pool));
 
   SVN_ERR(get_empty_file(eb, &empty_file));
 
-  /* Get property diffs if this is not schedule delete. */
-  if (status != svn_wc__db_status_deleted)
-    {
-      svn_boolean_t modified;
-
-      SVN_ERR(svn_wc__props_modified(&modified, eb->db, local_abspath,
-                                     pool));
-      if (modified)
-        SVN_ERR(svn_wc__internal_propdiff(&propchanges, &baseprops, eb->db,
-                                          local_abspath, pool, pool));
-      else
-        propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
-    }
-  else
-    {
-      SVN_ERR(svn_wc__internal_propdiff(NULL, &baseprops, eb->db,
-                                        local_abspath, pool, pool));
-    }
-
-  SVN_ERR(svn_wc__internal_is_replaced(&replaced, eb->db, local_abspath,
-                                       pool));
-
   /* Delete compares text-base against empty file, modifications to the
    * working-copy version of the deleted file are not wanted.
    * Replace is treated like a delete plus an add: two comparisons are
@@ -657,10 +659,12 @@ file_diff(struct dir_baton *db,
       (replaced && ! eb->ignore_ancestry))
     {
       const char *base_mimetype;
+      apr_hash_t *baseprops;
 
-      /* Get svn:mime-type from BASE props of PATH. */
-      SVN_ERR(get_base_mimetype(&base_mimetype, &baseprops, eb->db,
-                                local_abspath, pool, pool));
+      /* Get svn:mime-type from pristine props (in BASE or WORKING) of PATH. */
+      SVN_ERR(svn_wc__get_pristine_props(&baseprops, eb->db, local_abspath,
+                                         pool, pool));
+      base_mimetype = get_prop_mimetype(baseprops);
 
       SVN_ERR(eb->callbacks->file_deleted(NULL, NULL, NULL, path,
                                           textbase,
@@ -690,14 +694,24 @@ file_diff(struct dir_baton *db,
     {
       const char *translated = NULL;
       const char *working_mimetype;
-
-      /* Get svn:mime-type from working props of PATH. */
-      SVN_ERR(get_working_mimetype(&working_mimetype, NULL, local_abspath,
-                                   eb->db, pool, pool));
+      apr_hash_t *baseprops;
+      apr_hash_t *workingprops;
+      apr_array_header_t *propchanges;
+
+      /* Get svn:mime-type from ACTUAL props of PATH. */
+      SVN_ERR(svn_wc__get_actual_props(&workingprops, eb->db, local_abspath,
+                                       pool, pool));
+      working_mimetype = get_prop_mimetype(workingprops);
+
+      /* Set the original properties to empty, then compute "changes" from
+         that. Essentially, all ACTUAL props will be "added".  */
+      baseprops = apr_hash_make(pool);
+      SVN_ERR(svn_prop_diffs(&propchanges, workingprops, baseprops, pool));
 
       SVN_ERR(svn_wc__internal_translated_file(
               &translated, local_abspath, eb->db, local_abspath,
               SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
+              eb->cancel_func, eb->cancel_baton,
               pool, pool));
 
       SVN_ERR(eb->callbacks->file_added(NULL, NULL, NULL, NULL, path,
@@ -715,6 +729,11 @@ file_diff(struct dir_baton *db,
     {
       svn_boolean_t modified;
       const char *translated = NULL;
+      apr_hash_t *baseprops;
+      const char *base_mimetype;
+      const char *working_mimetype;
+      apr_hash_t *workingprops;
+      apr_array_header_t *propchanges;
 
       /* Here we deal with showing pure modifications. */
 
@@ -729,22 +748,45 @@ file_diff(struct dir_baton *db,
              already expensive, translating twice for the sake of code
              modularity is liveable. */
           SVN_ERR(svn_wc__internal_translated_file(
-                   &translated, local_abspath, eb->db, local_abspath,
-                   SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
-                   pool, pool));
+                    &translated, local_abspath, eb->db, local_abspath,
+                    SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
+                    eb->cancel_func, eb->cancel_baton,
+                    pool, pool));
         }
 
-      if (modified || propchanges->nelts > 0)
+      /* Get the properties, the svn:mime-type values, and compute the
+         differences between the two.  */
+      if (replaced
+          && eb->ignore_ancestry)
         {
-          const char *base_mimetype;
-          const char *working_mimetype;
+          /* We don't want the normal pristine properties (which are
+             from the WORKING tree). We want the pristines associated
+             with the BASE tree, which are saved as "revert" props.  */
+          SVN_ERR(svn_wc__get_revert_props(&baseprops,
+                                           eb->db, local_abspath,
+                                           pool, pool));
+        }
+      else
+        {
+          /* We can only fetch the pristine props (from BASE or WORKING) if
+             the node has not been replaced, or it was copied/moved here.  */
+          SVN_ERR_ASSERT(!replaced
+                         || status == svn_wc__db_status_copied
+                         || status == svn_wc__db_status_moved_here);
+
+          SVN_ERR(svn_wc__get_pristine_props(&baseprops, eb->db, local_abspath,
+                                             pool, pool));
+        }
+      base_mimetype = get_prop_mimetype(baseprops);
+
+      SVN_ERR(svn_wc__get_actual_props(&workingprops, eb->db, local_abspath,
+                                       pool, pool));
+      working_mimetype = get_prop_mimetype(workingprops);
 
-          /* Get svn:mime-type for both base and working file. */
-          SVN_ERR(get_base_mimetype(&base_mimetype, &baseprops, eb->db,
-                                    local_abspath, pool, pool));
-          SVN_ERR(get_working_mimetype(&working_mimetype, NULL, local_abspath,
-                                       eb->db, pool, pool));
+      SVN_ERR(svn_prop_diffs(&propchanges, workingprops, baseprops, pool));
 
+      if (modified || propchanges->nelts > 0)
+        {
           SVN_ERR(eb->callbacks->file_changed(NULL, NULL, NULL, NULL,
                                               path,
                                               modified ? textbase : NULL,
@@ -982,25 +1024,28 @@ report_wc_file_as_added(struct dir_baton
   emptyprops = apr_hash_make(pool);
 
   if (eb->use_text_base)
-    SVN_ERR(get_base_mimetype(&mimetype, &wcprops, eb->db, local_abspath,
-                              pool, pool));
+    SVN_ERR(svn_wc__get_pristine_props(&wcprops, eb->db, local_abspath,
+                                       pool, pool));
   else
-    SVN_ERR(get_working_mimetype(&mimetype, &wcprops, local_abspath,
-                                 eb->db, pool, pool));
+    SVN_ERR(svn_wc__get_actual_props(&wcprops, eb->db, local_abspath,
+                                     pool, pool));
+  mimetype = get_prop_mimetype(wcprops);
 
   SVN_ERR(svn_prop_diffs(&propchanges,
                          wcprops, emptyprops, pool));
 
 
   if (eb->use_text_base)
-    SVN_ERR(svn_wc__text_base_path(&source_file, eb->db, local_abspath, FALSE,
-                                   pool));
+    SVN_ERR(svn_wc__text_base_path_to_read(&source_file,
+                                           eb->db, local_abspath,
+                                           pool, pool));
   else
     source_file = path;
 
   SVN_ERR(svn_wc__internal_translated_file(
            &translated_file, source_file, eb->db, local_abspath,
            SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
+           eb->cancel_func, eb->cancel_baton,
            pool, pool));
 
   SVN_ERR(eb->callbacks->file_added(db->local_abspath,
@@ -1049,11 +1094,11 @@ report_wc_directory_as_added(struct dir_
                                         eb->changelist_hash, pool))
     {
       if (eb->use_text_base)
-        SVN_ERR(svn_wc__internal_propdiff(NULL, &wcprops, eb->db, dir_abspath,
-                                          pool, pool));
+        SVN_ERR(svn_wc__get_pristine_props(&wcprops, eb->db, dir_abspath,
+                                           pool, pool));
       else
-        SVN_ERR(svn_wc__load_props(NULL, &wcprops, eb->db, dir_abspath,
-                                   pool, pool));
+        SVN_ERR(svn_wc__get_actual_props(&wcprops, eb->db, dir_abspath,
+                                         pool, pool));
 
       SVN_ERR(svn_prop_diffs(&propchanges, wcprops, emptyprops, pool));
 
@@ -1221,11 +1266,13 @@ delete_entry(const char *path,
           apr_hash_t *baseprops = NULL;
           const char *base_mimetype;
 
-          SVN_ERR(svn_wc__text_base_path(&textbase, eb->db, local_abspath,
-                                         FALSE, pool));
-
-          SVN_ERR(get_base_mimetype(&base_mimetype, &baseprops, eb->db,
-                                    local_abspath, pool, pool));
+          SVN_ERR(svn_wc__text_base_path_to_read(&textbase,
+                                                 eb->db, local_abspath,
+                                                 pool, pool));
+
+          SVN_ERR(svn_wc__get_pristine_props(&baseprops, eb->db, local_abspath,
+                                             pool, pool));
+          base_mimetype = get_prop_mimetype(baseprops);
 
           SVN_ERR(eb->callbacks->file_deleted(NULL, NULL, NULL, full_path,
                                               textbase,
@@ -1332,19 +1379,22 @@ close_directory(void *dir_baton,
         {
           if (db->eb->use_text_base)
             {
-              SVN_ERR(svn_wc__internal_propdiff(NULL, &originalprops, eb->db,
-                                                db->local_abspath, pool, pool));
+              SVN_ERR(svn_wc__get_pristine_props(&originalprops,
+                                                 eb->db, db->local_abspath,
+                                                 pool, pool));
             }
           else
             {
               apr_hash_t *base_props, *repos_props;
 
-              SVN_ERR(svn_wc__load_props(NULL, &originalprops,
-                                         eb->db, db->local_abspath, pool, pool));
+              SVN_ERR(svn_wc__get_actual_props(&originalprops,
+                                               eb->db, db->local_abspath,
+                                               pool, pool));
 
               /* Load the BASE and repository directory properties. */
-              SVN_ERR(svn_wc__internal_propdiff(NULL, &base_props, eb->db,
-                                                db->local_abspath, pool, pool));
+              SVN_ERR(svn_wc__get_pristine_props(&base_props,
+                                                 eb->db, db->local_abspath,
+                                                 pool, pool));
 
               repos_props = apply_propchanges(base_props, db->propchanges);
 
@@ -1575,8 +1625,8 @@ close_file(void *file_baton,
   if (fb->added)
     base_props = apr_hash_make(pool);
   else
-    SVN_ERR(svn_wc__internal_propdiff(NULL, &base_props, eb->db,
-                                      fb->local_abspath, pool, pool));
+    SVN_ERR(svn_wc__get_pristine_props(&base_props, eb->db,
+                                       fb->local_abspath, pool, pool));
 
   repos_props = apply_propchanges(base_props, fb->propchanges);
 
@@ -1587,8 +1637,9 @@ close_file(void *file_baton,
      the same as BASE. */
   temp_file_path = fb->temp_file_path;
   if (!temp_file_path)
-    SVN_ERR(svn_wc__text_base_path(&temp_file_path, eb->db, fb->local_abspath,
-                                   FALSE, fb->pool));
+    SVN_ERR(svn_wc__text_base_path_to_read(&temp_file_path,
+                                           eb->db, fb->local_abspath,
+                                           fb->pool, pool));
 
   /* If the file isn't in the working copy (either because it was added
      in the BASE->repos diff or because we're diffing against WORKING
@@ -1651,13 +1702,15 @@ close_file(void *file_baton,
   if (modified)
     {
       if (eb->use_text_base)
-        SVN_ERR(svn_wc__text_base_path(&localfile, eb->db, fb->local_abspath,
-                                       FALSE, fb->pool));
+        SVN_ERR(svn_wc__text_base_path_to_read(&localfile,
+                                               eb->db, fb->local_abspath,
+                                               fb->pool, pool));
       else
         /* a detranslated version of the working file */
         SVN_ERR(svn_wc__internal_translated_file(
                  &localfile, fb->local_abspath, eb->db, fb->local_abspath,
                  SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
+                 eb->cancel_func, eb->cancel_baton,
                  pool, pool));
     }
   else
@@ -1669,8 +1722,9 @@ close_file(void *file_baton,
     }
   else
     {
-      SVN_ERR(svn_wc__load_props(NULL, &originalprops, eb->db,
-                                 fb->local_abspath, pool, pool));
+      SVN_ERR(svn_wc__get_actual_props(&originalprops,
+                                       eb->db, fb->local_abspath,
+                                       pool, pool));
 
       /* We have the repository properties in repos_props, and the
          WORKING properties in originalprops.  Recalculate
@@ -1797,6 +1851,7 @@ svn_wc_get_diff_editor6(const svn_delta_
   void *inner_baton;
   svn_delta_editor_t *tree_editor;
   const svn_delta_editor_t *inner_editor;
+  const char *anchor_abspath;
 
   SVN_ERR(make_edit_baton(&eb,
                           wc_ctx->db,
@@ -1826,12 +1881,14 @@ svn_wc_get_diff_editor6(const svn_delta_
   inner_editor = tree_editor;
   inner_baton = eb;
 
+  SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor_path, result_pool));
+
   if (depth == svn_depth_unknown)
     SVN_ERR(svn_wc__ambient_depth_filter_editor(&inner_editor,
                                                 &inner_baton,
                                                 inner_editor,
                                                 inner_baton,
-                                                anchor_path,
+                                                anchor_abspath,
                                                 target,
                                                 wc_ctx->db,
                                                 result_pool));