You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/11/28 13:03:49 UTC

svn commit: r1771732 - in /subversion/trunk/subversion: libsvn_client/conflicts.c tests/libsvn_client/conflicts-test.c

Author: stsp
Date: Mon Nov 28 13:03:48 2016
New Revision: 1771732

URL: http://svn.apache.org/viewvc?rev=1771732&view=rev
Log:
Fix handling of keywords while resolving an incoming move of a file.

* subversion/libsvn_client/conflicts.c
  (get_keywords): New helper based on similar code from libsvn_client/patch.c.
  (resolve_incoming_move_file_text_merge): Convert the move target file to
   repository-normal form while setting it aside. Fixes merging of keywords.

* subversion/tests/libsvn_client/conflicts-test.c
  (test_merge_incoming_move_file_text_merge_keywords): Update a comment, and
   fix the HEAD revision number expected by this test.
  (test_func): Switch "move file merge with keywords" test to PASS.

Modified:
    subversion/trunk/subversion/libsvn_client/conflicts.c
    subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c

Modified: subversion/trunk/subversion/libsvn_client/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/conflicts.c?rev=1771732&r1=1771731&r2=1771732&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_client/conflicts.c Mon Nov 28 13:03:48 2016
@@ -37,6 +37,7 @@
 #include "svn_props.h"
 #include "svn_hash.h"
 #include "svn_sorts.h"
+#include "svn_subst.h"
 #include "client.h"
 
 #include "private/svn_diff_tree.h"
@@ -6840,6 +6841,57 @@ unlock_wc:
   return SVN_NO_ERROR;
 }
 
+/* Get KEYWORDS for LOCAL_ABSPATH.
+ * WC_CTX is a context for the working copy the patch is applied to.
+ * Use RESULT_POOL for allocations of fields in TARGET.
+ * Use SCRATCH_POOL for all other allocations. */
+static svn_error_t *
+get_keywords(apr_hash_t **keywords,
+             svn_wc_context_t *wc_ctx,
+             const char *local_abspath,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  apr_hash_t *props;
+  svn_string_t *keywords_val;
+
+  SVN_ERR(svn_wc_prop_list2(&props, wc_ctx, local_abspath,
+                            scratch_pool, scratch_pool));
+  keywords_val = svn_hash_gets(props, SVN_PROP_KEYWORDS);
+  if (keywords_val)
+    {
+      svn_revnum_t changed_rev;
+      apr_time_t changed_date;
+      const char *rev_str;
+      const char *author;
+      const char *url;
+      const char *repos_root_url;
+      const char *repos_relpath;
+
+      SVN_ERR(svn_wc__node_get_changed_info(&changed_rev,
+                                            &changed_date,
+                                            &author, wc_ctx,
+                                            local_abspath,
+                                            scratch_pool,
+                                            scratch_pool));
+      rev_str = apr_psprintf(scratch_pool, "%ld", changed_rev);
+      SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, &repos_root_url,
+                                          NULL,
+                                          wc_ctx, local_abspath,
+                                          scratch_pool, scratch_pool));
+      url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+                                        scratch_pool);
+
+      SVN_ERR(svn_subst_build_keywords3(keywords,
+                                        keywords_val->data,
+                                        rev_str, url, repos_root_url,
+                                        changed_date,
+                                        author, result_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Implements conflict_option_resolve_func_t. */
 static svn_error_t *
 resolve_incoming_move_file_text_merge(svn_client_conflict_option_t *option,
@@ -6872,7 +6924,7 @@ resolve_incoming_move_file_text_merge(sv
   struct conflict_tree_incoming_delete_details *details;
   apr_array_header_t *possible_moved_to_abspaths;
   const char *moved_to_abspath;
-  const char *incoming_abspath;
+  const char *incoming_abspath = NULL;
 
   local_abspath = svn_client_conflict_get_local_abspath(conflict);
   operation = svn_client_conflict_get_operation(conflict);
@@ -6978,28 +7030,47 @@ resolve_incoming_move_file_text_merge(sv
     }
   else if (operation == svn_wc_operation_merge)
     {
+      svn_stream_t *incoming_stream;
+      svn_stream_t *move_target_stream;
+      svn_stream_t *normalized_stream;
+      apr_hash_t *keywords;
+
       /* Set aside the current move target file. This is required to apply
        * the move, and only then perform a three-way text merge between
        * the ancestor's file, our working file (which we would move to
        * the destination), and the file that we have set aside, which
        * contains the incoming fulltext. */
-      err = svn_io_open_uniquely_named(NULL, &incoming_abspath,
-                                       svn_dirent_dirname(moved_to_abspath,
-                                                          scratch_pool),
-                                       svn_dirent_basename(moved_to_abspath,
-                                                           scratch_pool),
-                                       ".tmp",
-                                       svn_io_file_del_on_pool_cleanup,
-                                       scratch_pool, scratch_pool);
+      err = svn_stream_open_unique(&incoming_stream,
+                                   &incoming_abspath, wc_tmpdir,
+                                   svn_io_file_del_none,
+                                   scratch_pool, scratch_pool);
+      if (err)
+        goto unlock_wc;
+
+      err = svn_stream_open_readonly(&move_target_stream, moved_to_abspath,
+                                     scratch_pool, scratch_pool);
       if (err)
         goto unlock_wc;
 
-      err = svn_io_file_rename2(moved_to_abspath, incoming_abspath,
-                                FALSE, scratch_pool);
+      err = get_keywords(&keywords, ctx->wc_ctx, moved_to_abspath,
+                         scratch_pool, scratch_pool);
+      if (err)
+        goto unlock_wc;
+
+      normalized_stream = svn_subst_stream_translated(move_target_stream,
+                                                      "\n", TRUE,
+                                                      keywords, FALSE,
+                                                      scratch_pool);
+      err = svn_stream_copy3(normalized_stream, incoming_stream,
+                             NULL, NULL, /* no cancellation */
+                             scratch_pool);
       if (err)
         goto unlock_wc;
 
       /* Apply the incoming move. */
+      err = svn_io_remove_file2(moved_to_abspath, FALSE, scratch_pool);
+      if (err)
+        goto unlock_wc;
       err = svn_wc__move2(ctx->wc_ctx, local_abspath, moved_to_abspath,
                           FALSE, /* ordinary (not meta-data only) move */
                           FALSE, /* mixed-revisions don't apply to files */
@@ -7012,12 +7083,7 @@ resolve_incoming_move_file_text_merge(sv
   else
     SVN_ERR_MALFUNCTION();
 
-  /* Perform the file merge.
-   *
-   *  ### Need to fix what we pass as "right_abspath" here, as svn_wc_merge5()
-   *  ### expects to see the fulltext in repository-normal form (linefeeds,
-   *  ### with keywords contracted).
-   */
+  /* Perform the file merge. */
   err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome,
                       ctx->wc_ctx, ancestor_abspath,
                       incoming_abspath, moved_to_abspath,
@@ -7033,6 +7099,14 @@ resolve_incoming_move_file_text_merge(sv
   if (err)
     goto unlock_wc;
 
+  if (operation == svn_wc_operation_merge && incoming_abspath)
+    {
+      err = svn_io_remove_file2(incoming_abspath, TRUE, scratch_pool);
+      if (err)
+        goto unlock_wc;
+      incoming_abspath = NULL;
+    }
+  
   if (ctx->notify_func2)
     {
       svn_wc_notify_t *notify;
@@ -7074,6 +7148,11 @@ resolve_incoming_move_file_text_merge(sv
   conflict->resolution_tree = option_id;
 
 unlock_wc:
+  if (err && operation == svn_wc_operation_merge && incoming_abspath)
+      err = svn_error_quick_wrapf(
+              err, _("If needed, a backup copy of '%s' can be found at '%s'"),
+              svn_dirent_local_style(moved_to_abspath, scratch_pool),
+              svn_dirent_local_style(incoming_abspath, scratch_pool));
   err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
                                                                  lock_abspath,
                                                                  scratch_pool));

Modified: subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c?rev=1771732&r1=1771731&r2=1771732&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/conflicts-test.c Mon Nov 28 13:03:48 2016
@@ -3679,10 +3679,7 @@ test_merge_incoming_move_file_text_merge
 
   /* The file should no longer be in conflict, and should not have a
    * text conflict, because the contents are identical in "trunk" and
-   * in the "branch".
-   *
-   * XFAIL: Currently, there is an unexpected text conflict.
-   */
+   * in the "branch". */
   SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A1/mu-moved"),
                                   ctx, pool, pool));
   SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
@@ -3696,7 +3693,7 @@ test_merge_incoming_move_file_text_merge
   /* And it should have expected contents (with expanded keywords). */
   SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A1/mu-moved"),
                                    pool));
-  SVN_TEST_STRING_ASSERT(buf->data, "$Revision: 4 $\n");
+  SVN_TEST_STRING_ASSERT(buf->data, "$Revision: 5 $\n");
 
   return SVN_NO_ERROR;
 }
@@ -3763,8 +3760,8 @@ static struct svn_test_descriptor_t test
                        "update incoming add file text merge"),
     SVN_TEST_OPTS_PASS(test_merge_incoming_move_file_prop_merge_conflict,
                        "merge incoming move file merge with prop conflict"),
-    SVN_TEST_OPTS_XFAIL(test_merge_incoming_move_file_text_merge_keywords,
-                        "merge incoming move file merge with keywords"),
+    SVN_TEST_OPTS_PASS(test_merge_incoming_move_file_text_merge_keywords,
+                       "merge incoming move file merge with keywords"),
     SVN_TEST_NULL
   };