subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r961475 - /subversion/trunk/subversion/libsvn_wc/update_editor.c
Date Wed, 07 Jul 2010 18:45:37 GMT
Author: rhuijben
Date: Wed Jul  7 18:45:37 2010
New Revision: 961475

URL: http://svn.apache.org/viewvc?rev=961475&view=rev
Log:
Bring the locate_copyfrom() handler in our update_editor into the WC-NG
world.  Document it's current behavior which before this patch relied
on svn_wc_entry_t perticularities. This enables future extenstion later.
Also allow using known to be good pristine data without reusing its
in-wc data, to avoid some cases where we contacted the repository, but
really had all the data we need.

It is probably easier to review locate_copyfrom() as a new function, then
trying to extract the old behavior from the patch.

* subversion/libsvn_wc/update_editor.c
  (locate_copyfrom): Rewritten to return streams and hash tables with
     contents and properties. Document old-assumptions as they apply
     to the wc-ng world.
  (add_file_with_history): Update caller. Take scratch pool.
  (add_file): Update caller. Use subpool as scratch_pool for
     add_file_with_history.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=961475&r1=961474&r2=961475&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Wed Jul  7 18:45:37 2010
@@ -3350,15 +3350,35 @@ absent_directory(const char *path,
 }
 
 
-/* Beginning at DIR_ABSPATH (from repository with uuid DIR_REPOS_UUID and
-   with repos_relpath DIR_REPOS_RELPATH) within a working copy, search the
-   working copy for a pre-existing versioned file which is exactly equal
-   to COPYFROM_PATH@COPYFROM_REV.
+/* Beginning at DIR_ABSPATH within a working copy, search the working copy
+   copy for a pre-existing versioned file which is exactly equal to
+   COPYFROM_PATH@COPYFROM_REV.
 
-   If the file isn't found, set *RETURN_ABSPATH to NULL.
+   The current implementation does this by taking the repos_relpath of
+   dir_abspath and copyfrom_relpath to calculate where in the working copy
+   repos_relpath would be and then tries to confirm its guess.
 
-   If the file is found, return the absolute path to it in
-   *RETURN_ABSPATH.
+   1) When it finds a copied file there, it looks for its origin to see
+   if the origin matches the copied file good enough to use it as new base
+   contents and properties. If that is the case set NEW_BASE_CONTENTS
+   and NEW_BASE_PROPS to the found restult.
+
+   If the new base information is found check if the node is tree-conflicted,
+   and when that is the case use its in-wc contents and actual properties
+   to set NEW_CONTENTS and NEW_PROPS.
+
+   (If new base info is found, return)
+
+   2) If the node's BASE information matches the expected origin matches the the
+   copy origin good enough use it as NEW_BASE_CONTENTS and NEW_BASE_PROPS.
+
+   If the new base information is found and the db_status of the node is normal,
+   then set NEW_CONTENTS and NEW_PROPS with the found values.
+
+   If data is not found, its values will be set to NULL. 
+
+   Allocate the return values in RESULT_POOL, but perform all temporary allocations
+   in SCRATCH_POOL.
 
    ### With a centralized datastore this becomes much easier. For now we
    ### keep the old algorithm because the result is also used for copying
@@ -3366,32 +3386,40 @@ absent_directory(const char *path,
    ### local file moves.
 */
 static svn_error_t *
-locate_copyfrom(svn_wc__db_t *db,
-                const char *copyfrom_path,
-                svn_revnum_t copyfrom_rev,
+locate_copyfrom(svn_stream_t **new_base_contents,
+                svn_stream_t **new_contents,
+                apr_hash_t **new_base_props,
+                apr_hash_t **new_props,
+                svn_wc__db_t *db,
                 const char *dir_abspath,
-                const char *dir_repos_uuid,
-                const char *dir_repos_relpath,
-                const char **return_abspath,
+                const char *copyfrom_relpath,
+                svn_revnum_t copyfrom_rev,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
   const char *ancestor_abspath, *ancestor_relpath;
-  const char *copyfrom_relpath;
+  const char *dir_repos_relpath, *dir_repos_root_url, *dir_repos_uuid;
+  const char *repos_relpath, *repos_root_url, *repos_uuid;
+  const char *local_abspath;
+
   apr_size_t levels_up;
-  const char *file_abspath;
   svn_error_t *err;
 
-  SVN_ERR_ASSERT(dir_repos_relpath && dir_repos_uuid);
-  SVN_ERR_ASSERT(copyfrom_path[0] == '/');
+  SVN_ERR_ASSERT(copyfrom_relpath[0] != '/');
+
+  SVN_ERR(svn_wc__db_scan_base_repos(&dir_repos_relpath, &dir_repos_root_url,
+                                     &dir_repos_uuid,
+                                     db, dir_abspath,
+                                     scratch_pool, scratch_pool));
 
   /* Be pessimistic.  This function is basically a series of tests
      that gives dozens of ways to fail our search, returning
      SVN_NO_ERROR in each case.  If we make it all the way to the
      bottom, we have a real discovery to return. */
-  *return_abspath = NULL;
-
-  copyfrom_relpath = copyfrom_path+1; /* Skip the initial '/' */
+  *new_base_contents = NULL;
+  *new_contents = NULL;
+  *new_base_props = NULL;
+  *new_props = NULL;
 
   /* Subtract the dest_dir's URL from the repository "root" URL to get
      the absolute FS path represented by dest_dir. */
@@ -3411,118 +3439,227 @@ locate_copyfrom(svn_wc__db_t *db,
     ancestor_abspath = svn_dirent_dirname(ancestor_abspath, scratch_pool);
 
   /* Verify hypothetical ancestor */
-  {
-    const char *repos_relpath, *repos_uuid;
-
-    err = svn_wc__db_scan_base_repos(&repos_relpath, NULL, &repos_uuid,
-                                     db, ancestor_abspath,
-                                     scratch_pool, scratch_pool);
-
-    if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY) ||
-                (err->apr_err == SVN_ERR_WC_PATH_FOUND)))
-      {
-        svn_error_clear(err);
-        return SVN_NO_ERROR;
-      }
-    else
-      SVN_ERR(err);
+  err = svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
+                                   &repos_uuid,
+                                   db, ancestor_abspath,
+                                   scratch_pool, scratch_pool);
 
-    /* If we got this far, we know that the ancestor dir exists, and
-       that it's a working copy too.  But is it from the same
-       repository?  And does it represent the URL we expect it to? */
-    if (strcmp(dir_repos_uuid, repos_uuid) != 0)
+  if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY) ||
+              (err->apr_err == SVN_ERR_WC_PATH_FOUND)))
+    {
+      svn_error_clear(err);
       return SVN_NO_ERROR;
+    }
+  else
+    SVN_ERR(err);
 
-    if (strcmp(ancestor_relpath, repos_relpath) != 0)
-      return SVN_NO_ERROR;
-  }
+  /* If we got this far, we know that the ancestor dir exists, and
+     that it's a working copy too.  But is it from the same
+     repository?  And does it represent the URL we expect it to? */
+  if ((strcmp(dir_repos_uuid, repos_uuid) != 0)
+      || (strcmp(dir_repos_root_url, repos_root_url) != 0)
+      || (strcmp(ancestor_relpath, repos_relpath) != 0))
+    return SVN_NO_ERROR;
 
   /* Add the remaining components to cwd, then add the remaining relpath to
      where we hope the copyfrom_relpath file exists. */
-  file_abspath = svn_dirent_join(ancestor_abspath,
+  local_abspath = svn_dirent_join(ancestor_abspath,
                                  svn_dirent_skip_ancestor(ancestor_relpath,
                                                           copyfrom_relpath),
                                  scratch_pool);
 
   /* Verify file in expected location */
   {
-    svn_node_kind_t kind;
-    svn_revnum_t addition_rev = SVN_INVALID_REVNUM;
-    const char *repos_relpath, *repos_uuid;
-
-    /* First: does the proposed file path even exist? */
-    SVN_ERR(svn_io_check_path(file_abspath, &kind, scratch_pool));
-    if (kind != svn_node_file)
-      return SVN_NO_ERROR;
+    svn_revnum_t rev, changed_rev;
+    svn_wc__db_status_t status, base_status;
+    svn_boolean_t conflicted, have_base;
+    const svn_checksum_t *checksum;
 
-    /* Next: is the file under version control?   */
-    err = svn_wc__db_scan_base_repos(&repos_relpath, NULL, &repos_uuid,
-                                     db, file_abspath,
-                                     scratch_pool, scratch_pool);
+    err = svn_wc__db_read_info(&status, NULL, &rev, &repos_relpath,
+                               &repos_root_url, &repos_uuid, &changed_rev,
+                               NULL, NULL, NULL, NULL, &checksum, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, &have_base,
+                               NULL, &conflicted, NULL,
+                               db, local_abspath, scratch_pool, scratch_pool);
 
-    if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY) ||
-                (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)))
+    if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
+                (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))))
       {
         svn_error_clear(err);
+        return SVN_NO_ERROR;
+      }
 
-        /* ### Our entries handling made us handle the following
-               scenario: An older version of a file was copied at
-               exactly the expected location. Reproduced this behavior
-               until we can really querry the entire workingcopy. */
-
-        err = svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL,
-                                       &repos_relpath, NULL, &repos_uuid,
-                                       &addition_rev, db, file_abspath,
-                                       scratch_pool, scratch_pool);
+    /* Check if we have an added node with the right copyfrom information, as
+       this is what you would see on a file move. */
+       
+    if (status == svn_wc__db_status_added)
+      {
+        const char *op_root_abspath;
+        const char *original_repos_relpath, *original_root_url;
+        const char *original_uuid;
+        svn_revnum_t original_rev;
+
+        SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath,
+                                         &repos_relpath, &repos_root_url,
+                                         &repos_uuid, &original_repos_relpath,
+                                         &original_root_url, &original_uuid,
+                                         &original_rev,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
 
-        if (err && ((err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
-              (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))))
+        if (status == svn_wc__db_status_copied
+            || status == svn_wc__db_status_moved_here)
           {
-            svn_error_clear(err);
+            original_repos_relpath = svn_relpath_join(
+                                    original_repos_relpath,
+                                    svn_dirent_skip_ancestor(op_root_abspath,
+                                                             local_abspath),
+                                    scratch_pool);
+
+            /* If the repository location matches our exact guess and
+               the file's recorded revisions tell us that the file had the
+               same contents at the copyfrom_revision, we can use this
+               data as new_base */
+            if (strcmp(original_repos_relpath, copyfrom_relpath) == 0
+                && strcmp(original_root_url, dir_repos_root_url) == 0
+                && strcmp(original_uuid, dir_repos_uuid) == 0
+                && strcmp(repos_relpath, copyfrom_relpath) == 0
+                && strcmp(repos_root_url, dir_repos_root_url) == 0
+                && strcmp(repos_uuid, dir_repos_uuid) == 0
+
+                && SVN_IS_VALID_REVNUM(changed_rev)
+                && changed_rev <= copyfrom_rev
+                && copyfrom_rev <= original_rev)
+              {
+                svn_node_kind_t kind;
+                svn_boolean_t text_changed;
+
+                /* WORKING_NODE has the right new-BASE information,
+                   so we have at least a partial result. */
+                SVN_ERR(svn_wc__db_pristine_read(new_base_contents,
+                                                 db, local_abspath, checksum,
+                                                 result_pool, scratch_pool));
+                SVN_ERR(svn_wc__get_pristine_props(new_base_props,
+                                                   db, local_abspath,
+                                                   result_pool, scratch_pool));
+
+                /* If the node is conflicted, that might have happened because
+                   the node was deleted. Which might indicate that we have
+                   a file move. In this case we like the real file data */
+                if (!conflicted
+                    && status == svn_wc__db_status_copied)
+                  return SVN_NO_ERROR; /* A local copy is no local modification
+                                          that we should keep */
+
+                /* ### TODO: Add verification to check that the conflict
+                       tells us that this is the right thing to do.
+
+                   ### Pre 1.7 we just assumed that it is ok without checking for
+                       conflicts, so this is not a regression */
+
+                SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+
+                if (kind != svn_node_file)
+                  return SVN_NO_ERROR; /* Nothing to copy */
+
+                SVN_ERR(svn_wc__internal_text_modified_p(&text_changed, db,
+                                                         local_abspath, FALSE,
+                                                         TRUE, scratch_pool));
+
+                if (!text_changed)
+                  return SVN_NO_ERROR; /* Take the easy route */
 
-            return SVN_NO_ERROR;
+                SVN_ERR(svn_stream_open_readonly(new_contents, local_abspath,
+                                                 result_pool, scratch_pool));
+
+                SVN_ERR(svn_wc__get_actual_props(new_props, db, local_abspath,
+                                                 result_pool, scratch_pool));
+
+                return SVN_NO_ERROR;
+              }
           }
-        else
-          SVN_ERR(err);
       }
-    else
-      SVN_ERR(err);
 
-    if (strcmp(dir_repos_uuid, repos_uuid))
+    if (!have_base)
       return SVN_NO_ERROR;
 
-    if (strcmp(copyfrom_relpath, repos_relpath))
+    base_status = status;
+
+    if (status != svn_wc__db_status_normal)
+      SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &rev,
+                                       &repos_relpath, &repos_root_url,
+                                       &repos_uuid, &changed_rev, NULL,
+                                       NULL, NULL, NULL, &checksum, NULL,
+                                       NULL, NULL,
+                                       db, local_abspath,
+                                       scratch_pool, scratch_pool));
+
+    if (base_status != svn_wc__db_status_normal)
+      return SVN_NO_ERROR; /* No interesting BASE_NODE */
+
+    if (!repos_relpath || !repos_root_url || !repos_uuid)
+      SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
+                                         &repos_uuid,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+
+    /* Is it from the same repository */
+    if ((strcmp(dir_repos_uuid, repos_uuid) != 0)
+        || (strcmp(dir_repos_root_url, repos_root_url) != 0)
+        || (strcmp(copyfrom_relpath, repos_relpath) != 0))
       return SVN_NO_ERROR;
 
-    if (SVN_IS_VALID_REVNUM(addition_rev) && addition_rev == copyfrom_rev)
+    /* Ok, we know that we look at the right node, but do we have the
+       right revision?
+
+       To be sure that the base node has the right properties and text,
+       the node must be the same in copyfrom_rev and changed_rev, which
+       is only true within this specific range
+       */
+    if (!(SVN_IS_VALID_REVNUM(changed_rev)
+          && changed_rev <= copyfrom_rev
+          && copyfrom_rev <= rev))
       {
-        /* We found the right file as copy source */
-        *return_abspath = apr_pstrdup(result_pool, file_abspath);
         return SVN_NO_ERROR;
       }
-  }
 
-  /* Do we actually have valid revisions for the file?  (See Issue
-     #2977.) */
-  {
-    svn_revnum_t wc_rev, change_rev;
+    /* BASE_NODE has the right new-BASE information,
+       so we have at least a partial result. */
+    SVN_ERR(svn_wc__db_pristine_read(new_base_contents,
+                                     db, local_abspath, checksum,
+                                     result_pool, scratch_pool));
+
+    SVN_ERR(svn_wc__db_base_get_props(new_base_props,
+                                      db, local_abspath, result_pool,
+                                      scratch_pool));
+
+    /* If the node is in status normal, the user probably intended to make
+       a copy of this in-wc node, so copy its local changes over to
+       the new file. */
+    if (status == svn_wc__db_status_normal)
+      {
+        svn_node_kind_t kind;
+        svn_boolean_t text_changed;
 
-    SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &wc_rev, NULL, NULL, NULL,
-                                     &change_rev, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, NULL, db, file_abspath,
-                                     scratch_pool, scratch_pool));
+        SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
 
-    if (!SVN_IS_VALID_REVNUM(wc_rev) || !SVN_IS_VALID_REVNUM(change_rev))
-      return SVN_NO_ERROR;
+        if (kind != svn_node_file)
+          return SVN_NO_ERROR; /* Nothing to copy */
 
-    /* Do we have the the right *version* of the file? */
-    if (! ((change_rev <= copyfrom_rev) && (copyfrom_rev <= wc_rev)))
-      return SVN_NO_ERROR;
-  }
+        SVN_ERR(svn_wc__internal_text_modified_p(&text_changed, db,
+                                                 local_abspath, FALSE,
+                                                 TRUE, scratch_pool));
+
+        if (!text_changed)
+            return SVN_NO_ERROR; /* Take the easy route */
 
-  /* Success!  We found the exact file we wanted! */
-  *return_abspath = apr_pstrdup(result_pool, file_abspath);
+        SVN_ERR(svn_stream_open_readonly(new_contents, local_abspath,
+                                         result_pool, scratch_pool));
 
+        SVN_ERR(svn_wc__get_actual_props(new_props, db, local_abspath,
+                                         result_pool, scratch_pool));
+      }
+  }
   return SVN_NO_ERROR;
 }
 
@@ -3572,36 +3709,26 @@ add_file_with_history(struct dir_baton *
                       const char *copyfrom_path,
                       svn_revnum_t copyfrom_rev,
                       struct file_baton *tfb,
-                      apr_pool_t *pool)
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
   struct edit_baton *eb = pb->edit_baton;
-  apr_hash_t *base_props, *working_props;
-  svn_error_t *err;
   svn_stream_t *copied_stream;
-  const char *src_local_abspath, *copied_text_base_tmp_abspath;
+  const char *copied_text_base_tmp_abspath;
   svn_wc__db_t *db = eb->db;
-  const char *dir_repos_relpath, *dir_repos_root, *dir_repos_uuid;
+  svn_stream_t *new_base_contents, *new_contents;
+  apr_hash_t *new_base_props, *new_props;
 
-  /* The file_pool can stick around for a *long* time, so we want to
-     use a subpool for any temporary allocations. */
-  apr_pool_t *subpool = svn_pool_create(pool);
+  SVN_ERR_ASSERT(copyfrom_path[0] == '/');
 
   tfb->added_with_history = TRUE;
 
   /* Attempt to locate the copyfrom_path in the working copy first. */
-
-  SVN_ERR(svn_wc__db_scan_base_repos(&dir_repos_relpath, &dir_repos_root,
-                                     &dir_repos_uuid, db, pb->local_abspath,
-                                     subpool, subpool));
-
-  err = locate_copyfrom(eb->db, copyfrom_path, copyfrom_rev, pb->local_abspath,
-                        dir_repos_uuid, dir_repos_relpath,
-                        &src_local_abspath, subpool, subpool);
-
-  if (err && err->apr_err == SVN_ERR_WC_COPYFROM_PATH_NOT_FOUND)
-    svn_error_clear(err);
-  else
-    SVN_ERR(err);
+  SVN_ERR(locate_copyfrom(&new_base_contents, &new_contents,
+                          &new_base_props, &new_props,
+                          db, pb->local_abspath,
+                          copyfrom_path+1, /* Create repos_relpath */
+                          copyfrom_rev, result_pool, scratch_pool));
 
   /* Open the text base for writing (this will get us a temporary file).  */
   SVN_ERR(svn_wc__open_writable_base(&copied_stream,
@@ -3612,54 +3739,20 @@ add_file_with_history(struct dir_baton *
                                      &tfb->copied_text_base_md5_checksum,
                                      &tfb->copied_text_base_sha1_checksum,
                                      db, pb->local_abspath,
-                                     pool, pool));
+                                     result_pool, scratch_pool));
 
-  if (src_local_abspath != NULL) /* Found a file to copy */
+  if (new_base_contents && new_base_props)
     {
       /* Copy the existing file's text-base over to the (temporary)
          new text-base, where the file baton expects it to be.  Get
          the text base and props from the usual place or from the
          revert place, depending on scheduling. */
-      svn_stream_t *source_text_base;
-      const svn_wc_entry_t *src_entry;
-
-      SVN_ERR(svn_wc__get_entry(&src_entry, db, src_local_abspath, FALSE,
-                            svn_node_file, FALSE, subpool, subpool));
+      SVN_ERR(svn_stream_copy3(new_base_contents, copied_stream,
+                               eb->cancel_func, eb->cancel_baton,
+                               scratch_pool));
 
-      if (src_entry->schedule == svn_wc_schedule_add)
-        SVN_ERR(svn_wc__get_pristine_contents(&source_text_base,
-                                              db, src_local_abspath,
-                                              subpool, subpool));
-      else
-        SVN_ERR(svn_wc__get_ultimate_base_contents(&source_text_base,
-                                                   db, src_local_abspath,
-                                                   subpool, subpool));
-
-      /* If this has no base, should we use an empty stream?
-       * This assert wants to verify that there are no such callers. */
-      SVN_ERR_ASSERT(source_text_base != NULL);
-
-      if (src_entry->schedule == svn_wc_schedule_replace
-          && src_entry->copyfrom_url)
-        {
-          SVN_ERR(svn_wc__get_revert_props(&base_props, db,
-                                           src_local_abspath, pool, subpool));
-          /* The old working props are lost, just like the old
-             working file text is.  Just use the base props. */
-          working_props = base_props;
-        }
-      else
-        {
-          SVN_ERR(svn_wc__get_pristine_props(&base_props,
-                                             db, src_local_abspath,
-                                             pool, subpool));
-          SVN_ERR(svn_wc__get_actual_props(&working_props,
-                                           db, src_local_abspath,
-                                           pool, subpool));
-        }
-
-      SVN_ERR(svn_stream_copy3(source_text_base, copied_stream,
-                               eb->cancel_func, eb->cancel_baton, pool));
+      if (!new_props)
+        new_props = new_base_props;
     }
   else  /* Couldn't find a file to copy  */
     {
@@ -3676,45 +3769,49 @@ add_file_with_history(struct dir_baton *
          to the root of the repository so skip the first '/'. */
       SVN_ERR(eb->fetch_func(eb->fetch_baton, copyfrom_path + 1, copyfrom_rev,
                              copied_stream,
-                             NULL, &base_props, pool));
+                             NULL, &new_base_props, scratch_pool));
       SVN_ERR(svn_stream_close(copied_stream));
-      working_props = base_props;
+
+      /* Filter out wc-props */
+      /* ### Do we get new values as modification or should these really
+             be installed? */
+      new_base_props = svn_prop_hash_dup(copy_regular_props(new_base_props,
+                                                             scratch_pool),
+                                         result_pool);
+
+      new_props = new_base_props;
     }
 
   SVN_ERR(svn_wc__db_pristine_install(db, copied_text_base_tmp_abspath,
                                       tfb->copied_text_base_sha1_checksum,
                                       tfb->copied_text_base_md5_checksum,
-                                      subpool));
+                                      scratch_pool));
 
-  /* Loop over whatever props we have in memory, and add all
-     regular props to hashes in the baton. Skip entry and wc
-     properties, these are only valid for the original file. */
-  tfb->copied_base_props = copy_regular_props(base_props, pool);
-  tfb->copied_working_props = copy_regular_props(working_props, pool);
+  tfb->copied_base_props = new_base_props;
 
-  if (src_local_abspath != NULL)
+  if (new_contents)
     {
       /* If we copied an existing file over, we need to copy its
          working text too, to preserve any local mods.  (We already
          read its working *props* into tfb->copied_working_props.) */
-      svn_boolean_t text_changed;
+      const char *temp_dir_abspath;
+      svn_stream_t *tmp_contents;
 
-      SVN_ERR(svn_wc__internal_text_modified_p(&text_changed, eb->db,
-                                               src_local_abspath, FALSE,
-                                               TRUE, subpool));
+        /* Make a unique file name for the copied working text. */
+      SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath,
+                                             db, pb->local_abspath,
+                                             scratch_pool, scratch_pool));
 
-      if (text_changed)
-        {
-          /* Make a unique file name for the copied working text. */
-          SVN_ERR(get_empty_tmp_file(&tfb->copied_working_text, eb->db,
-                                     pb->local_abspath, pool, pool));
+      SVN_ERR(svn_stream_open_unique(&tmp_contents, &tfb->copied_working_text,
+                                     temp_dir_abspath, svn_io_file_del_none,
+                                     result_pool, scratch_pool));
 
-          SVN_ERR(svn_io_copy_file(src_local_abspath, tfb->copied_working_text,
-                                   TRUE, subpool));
-        }
-    }
+      SVN_ERR(svn_stream_copy3(new_contents, tmp_contents, eb->cancel_func,
+                               eb->cancel_baton,
+                               scratch_pool));
 
-  svn_pool_destroy(subpool);
+       tfb->copied_working_props = new_props;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -4085,15 +4182,15 @@ add_file(const char *path,
                       svn_wc_notify_tree_conflict, subpool);
     }
 
-  svn_pool_destroy(subpool);
-
   /* Now, if this is an add with history, do the history part. */
   if (copyfrom_path && !fb->skip_this)
     {
       SVN_ERR(add_file_with_history(pb, copyfrom_path, copyfrom_rev,
-                                    fb, pool));
+                                    fb, pool, subpool));
     }
 
+  svn_pool_destroy(subpool);
+
   return SVN_NO_ERROR;
 }
 



Mime
View raw message