You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2019/01/07 20:45:55 UTC

svn commit: r1850689 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/client.h libsvn_client/commit.c libsvn_client/commit_util.c libsvn_client/wc_editor.c

Author: julianfoad
Date: Mon Jan  7 20:45:55 2019
New Revision: 1850689

URL: http://svn.apache.org/viewvc?rev=1850689&view=rev
Log:
Improvements to the 'WC editor' for issue #4786.

* subversion/include/private/svn_client_private.h
  (svn_client__wc_editor): Specify the form of path arguments to the editor.
  (svn_client__wc_replay): Same, and add a WC abspath argument.

* subversion/libsvn_client/commit.c
  (svn_client__wc_replay): Add a WC abspath argument, and make all editor
    paths relative to (the URL of) that path.

* subversion/libsvn_client/client.h,
  subversion/libsvn_client/commit_util.c
  (svn_client__condense_commit_items2): New.

* subversion/libsvn_client/wc_editor.c
  (file_baton_t,
   file_textdelta,
   file_close): Add support for making a text-delta against a non-empty
    base.

Modified:
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/commit.c
    subversion/trunk/subversion/libsvn_client/commit_util.c
    subversion/trunk/subversion/libsvn_client/wc_editor.c

Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1850689&r1=1850688&r2=1850689&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Mon Jan  7 20:45:55 2019
@@ -445,6 +445,10 @@ svn_client__repos_to_wc_copy_by_editor(s
  * Return an editor in @a *editor_p, @a *edit_baton_p that will apply
  * local modifications to the WC subdirectory at @a dst_abspath.
  *
+ * The @a path arguments to the editor methods shall be local WC paths,
+ * relative to @a dst_abspath. The @a copyfrom_path arguments to the
+ * editor methods shall be URLs.
+ *
  * Send notifications via @a notify_func / @a notify_baton.
  *
  * RA_SESSION is used to fetch the original content for copies.
@@ -488,7 +492,17 @@ svn_client__wc_editor_internal(const svn
  *
  * Committable changes are found in TARGETS:DEPTH:CHANGELISTS.
  *
- * Send the changes to EDITOR:EDIT_BATON.
+ * Send the changes to @a editor:@a edit_baton. The @a path arguments
+ * to the editor methods are URL-paths relative to the URL of
+ * @a src_wc_abspath.
+ *
+ *    ### We will presumably need to change this so that the @a path
+ *        arguments to the editor will be local WC relpaths, in order
+ *        to handle switched paths.
+ *
+ * The @a copyfrom_path arguments to the editor methods are URLs. As the
+ * WC does not store copied-from-foreign-repository metadata, the URL will
+ * be in the same repository as the URL of its parent path.
  *
  * Compared with svn_client__do_commit(), this (like svn_client_commit6)
  * handles:
@@ -506,7 +520,8 @@ svn_client__wc_editor_internal(const svn
  *  - removing locks and changelists in WC
  */
 svn_error_t *
-svn_client__wc_replay(const apr_array_header_t *targets,
+svn_client__wc_replay(const char *src_wc_abspath,
+                      const apr_array_header_t *targets,
                       svn_depth_t depth,
                       const apr_array_header_t *changelists,
                       const svn_delta_editor_t *editor,

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1850689&r1=1850688&r2=1850689&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Mon Jan  7 20:45:55 2019
@@ -870,6 +870,18 @@ svn_client__condense_commit_items(const
                                   apr_array_header_t *commit_items,
                                   apr_pool_t *pool);
 
+/* Rewrite the COMMIT_ITEMS array to be sorted by URL.
+   Rewrite the items' URLs to be relative to BASE_URL.
+
+   COMMIT_ITEMS is an array of (svn_client_commit_item3_t *) items.
+
+   Afterwards, some of the items in COMMIT_ITEMS may contain data
+   allocated in POOL. */
+svn_error_t *
+svn_client__condense_commit_items2(const char *base_url,
+                                   apr_array_header_t *commit_items,
+                                   apr_pool_t *pool);
+
 /* Commit the items in the COMMIT_ITEMS array using EDITOR/EDIT_BATON
    to describe the committed local mods.  Prior to this call,
    COMMIT_ITEMS should have been run through (and BASE_URL generated

Modified: subversion/trunk/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit.c?rev=1850689&r1=1850688&r2=1850689&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit.c Mon Jan  7 20:45:55 2019
@@ -553,7 +553,8 @@ harvest_committables(apr_array_header_t
 }
 
 svn_error_t *
-svn_client__wc_replay(const apr_array_header_t *targets,
+svn_client__wc_replay(const char *src_wc_abspath,
+                      const apr_array_header_t *targets,
                       svn_depth_t depth,
                       const apr_array_header_t *changelists,
                       const svn_delta_editor_t *editor,
@@ -565,7 +566,9 @@ svn_client__wc_replay(const apr_array_he
   apr_array_header_t *rel_targets;
   apr_hash_t *lock_tokens;
   apr_array_header_t *commit_items;
+  svn_client__pathrev_t *base;
   const char *base_url;
+  svn_wc_notify_func2_t saved_notify_func;
 
   /* Condense the target list. This makes all targets absolute. */
   SVN_ERR(svn_dirent_condense_targets(&base_abspath, &rel_targets, targets,
@@ -592,15 +595,25 @@ svn_client__wc_replay(const apr_array_he
                                FALSE /*just_locked*/,
                                changelists,
                                ctx, pool, pool));
+  if (!commit_items)
+    {
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_client__wc_node_get_base(&base,
+                                       src_wc_abspath, ctx->wc_ctx, pool, pool));
+  base_url = base->url;
+  /* Sort our COMMIT_ITEMS by URL and find their relative URL-paths. */
+  SVN_ERR(svn_client__condense_commit_items2(base_url, commit_items, pool));
 
-  /* Sort and condense our COMMIT_ITEMS. */
-  SVN_ERR(svn_client__condense_commit_items(&base_url, commit_items, pool));
-
+  saved_notify_func = ctx->notify_func2;
   ctx->notify_func2 = NULL;
+  /* BASE_URL is only used here in notifications & errors */
   SVN_ERR(svn_client__do_commit(base_url, commit_items,
                                 editor, edit_baton,
                                 NULL /*notify_prefix*/, NULL /*sha1_checksums*/,
                                 ctx, pool, pool));
+  ctx->notify_func2 = saved_notify_func;
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit_util.c?rev=1850689&r1=1850688&r2=1850689&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit_util.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit_util.c Mon Jan  7 20:45:55 2019
@@ -1392,6 +1392,29 @@ sort_commit_item_urls(const void *a, con
 }
 
 
+svn_error_t *
+svn_client__condense_commit_items2(const char *base_url,
+                                   apr_array_header_t *commit_items,
+                                   apr_pool_t *pool)
+{
+  apr_array_header_t *ci = commit_items; /* convenience */
+  int i;
+
+  /* Sort our commit items by their URLs. */
+  svn_sort__array(ci, sort_commit_item_urls);
+
+  /* Hack BASE_URL off each URL; store the result as session_relpath. */
+  for (i = 0; i < ci->nelts; i++)
+    {
+      svn_client_commit_item3_t *this_item
+        = APR_ARRAY_IDX(ci, i, svn_client_commit_item3_t *);
+
+      this_item->session_relpath = svn_uri_skip_ancestor(base_url,
+                                                         this_item->url, pool);
+    }
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_client__condense_commit_items(const char **base_url,

Modified: subversion/trunk/subversion/libsvn_client/wc_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/wc_editor.c?rev=1850689&r1=1850688&r2=1850689&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/wc_editor.c (original)
+++ subversion/trunk/subversion/libsvn_client/wc_editor.c Mon Jan  7 20:45:55 2019
@@ -1,5 +1,5 @@
 /*
- * copy_foreign.c:  copy from other repository support.
+ * wc_editor.c: editing the local modifications in the WC.
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -51,8 +51,6 @@
  * TODO:
  *   - tests
  *   - use for all existing scenarios ('svn add', 'svn propset', etc.)
- *   - copy-from (half done: in dir_add only, untested)
- *   - text-delta
  *   - Instead of 'root_dir_add' option, probably the driver should anchor
  *     at the parent dir.
  *   - Instead of 'ignore_mergeinfo' option, implement that as a wrapper.
@@ -350,7 +348,7 @@ struct file_baton_t
   svn_boolean_t created;  /* already under version control in the WC */
   apr_hash_t *properties;
 
-  svn_boolean_t writing;
+  const char *writing_file;
   unsigned char digest[APR_MD5_DIGESTSIZE];
 
   const char *tmp_path;
@@ -473,15 +471,28 @@ file_textdelta(void *file_baton,
                void **handler_baton)
 {
   struct file_baton_t *fb = file_baton;
+  const char *target_dir = svn_dirent_dirname(fb->local_abspath, fb->pool);
+  svn_error_t *err;
+  svn_stream_t *source;
   svn_stream_t *target;
 
-  SVN_ERR_ASSERT(! fb->writing);
+  SVN_ERR_ASSERT(! fb->writing_file);
 
-  SVN_ERR(svn_stream_open_writable(&target, fb->local_abspath, fb->pool,
-                                   fb->pool));
+  err = svn_stream_open_readonly(&source, fb->local_abspath,
+                                 fb->pool, fb->pool);
+  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+    {
+      svn_error_clear(err);
+      source = svn_stream_empty(fb->pool);
+    }
+  else
+    SVN_ERR(err);
 
-  fb->writing = TRUE;
-  svn_txdelta_apply(svn_stream_empty(fb->pool) /* source */,
+  SVN_ERR(svn_stream_open_unique(&target, &fb->writing_file,
+                                 target_dir, svn_io_file_del_none,
+                                 fb->pool, fb->pool));
+
+  svn_txdelta_apply(source,
                     target,
                     fb->digest,
                     fb->local_abspath,
@@ -523,6 +534,10 @@ file_close(void *file_baton,
   struct file_baton_t *fb = file_baton;
   struct dir_baton_t *pb = fb->pb;
 
+  if (fb->writing_file)
+    SVN_ERR(svn_io_file_rename2(fb->writing_file, fb->local_abspath,
+                                FALSE /*flush*/, scratch_pool));
+
   if (text_checksum)
     {
       svn_checksum_t *expected_checksum;