Author: julianfoad
Date: Mon Sep 24 16:37:53 2018
New Revision: 1841874

URL: http://svn.apache.org/viewvc?rev=1841874&view=rev
Log:
Merge the r1841719 group from trunk:

 * r1841719, r1841742
   Add support for 'local missing' conflicts with directories.
   Justification:
     This case already works with files. Now also works with directories.
   Notes: merge needs --accept=12
   Votes:
     +1: stsp, jcorvel, julianfoad

Modified:
    subversion/branches/1.11.x/   (props changed)
    subversion/branches/1.11.x/STATUS
    subversion/branches/1.11.x/subversion/libsvn_client/conflicts.c
    subversion/branches/1.11.x/subversion/tests/libsvn_client/conflicts-test.c

Propchange: subversion/branches/1.11.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Sep 24 16:37:53 2018
@@ -100,4 +100,4 @@
 /subversion/branches/verify-at-commit:1462039-1462408
 /subversion/branches/verify-keep-going:1439280-1546110
 /subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1840990-1840991,1840995,1840997,1841059,1841079,1841091,1841098,1841136,1841180,1841272,1841481,1841524-1841525,1841567,1841600-1841602,1841606,1841731,1841736,1841743,1841753-1841754,1841822,1841867
+/subversion/trunk:1840990-1840991,1840995,1840997,1841059,1841079,1841091,1841098,1841136,1841180,1841272,1841481,1841524-1841525,1841567,1841600-1841602,1841606,1841719,1841731,1841736,1841742-1841743,1841753-1841754,1841822,1841867

Modified: subversion/branches/1.11.x/STATUS
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.11.x/STATUS?rev=1841874&r1=1841873&r2=1841874&view=diff
==============================================================================
--- subversion/branches/1.11.x/STATUS (original)
+++ subversion/branches/1.11.x/STATUS Mon Sep 24 16:37:53 2018
@@ -29,11 +29,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
- * r1841719, r1841742
-   Add support for 'local missing' conflicts with directories.
-   Justification:
-     This case already works with files. Now also works with directories.
-   Notes: merge needs --accept=12
-   Votes:
-     +1: stsp, jcorvel, julianfoad

Modified: subversion/branches/1.11.x/subversion/libsvn_client/conflicts.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.11.x/subversion/libsvn_client/conflicts.c?rev=1841874&r1=1841873&r2=1841874&view=diff
==============================================================================
--- subversion/branches/1.11.x/subversion/libsvn_client/conflicts.c (original)
+++ subversion/branches/1.11.x/subversion/libsvn_client/conflicts.c Mon Sep 24 
16:37:53 2018
@@ -3032,7 +3032,7 @@ conflict_tree_get_details_local_missing(
           move = APR_ARRAY_IDX(details->moves, i, struct repos_move_info *);
           SVN_ERR(follow_move_chains(details->wc_move_targets, move, ctx,
                                      conflict->local_abspath,
-                                     svn_node_file,
+                                     new_kind,
                                      new_repos_relpath,
                                      new_rev,
                                      scratch_pool, iterpool));
@@ -3064,7 +3064,25 @@ conflict_tree_get_details_local_missing(
                                          
   details->sibling_moves = sibling_moves;
   details->wc_siblings = wc_siblings;
-  if (details->wc_siblings && details->wc_siblings->nelts == 1)
+  if (details->wc_move_targets && apr_hash_count(details->wc_move_targets) == 
1)
+    {
+      apr_array_header_t *wc_abspaths;
+
+      wc_abspaths = svn_hash_gets(details->wc_move_targets,
+                                  details->move_target_repos_relpath);
+      if (wc_abspaths->nelts == 1)
+        {
+          svn_node_kind_t kind = old_rev < new_rev ? new_kind : old_kind;
+
+          if (kind == svn_node_file)
+              conflict->recommended_option_id =
+                  svn_client_conflict_option_local_move_file_text_merge;
+          else if (kind == svn_node_dir)
+              conflict->recommended_option_id =
+                svn_client_conflict_option_local_move_dir_merge;
+      }
+    }
+  else if (details->wc_siblings && details->wc_siblings->nelts == 1)
     {
       svn_node_kind_t kind = old_rev < new_rev ? new_kind : old_kind;
 
@@ -9230,10 +9248,10 @@ resolve_local_move_file_merge(svn_client
 
 /* Implements conflict_option_resolve_func_t. */
 static svn_error_t *
-resolve_sibling_move_dir_merge(svn_client_conflict_option_t *option,
-                              svn_client_conflict_t *conflict,
-                              svn_client_ctx_t *ctx,
-                              apr_pool_t *scratch_pool)
+resolve_local_move_dir_merge(svn_client_conflict_option_t *option,
+                             svn_client_conflict_t *conflict,
+                             svn_client_ctx_t *ctx,
+                             apr_pool_t *scratch_pool)
 {
   const char *lock_abspath;
   svn_error_t *err;
@@ -9264,9 +9282,19 @@ resolve_sibling_move_dir_merge(svn_clien
             NULL, conflict, scratch_pool,
             scratch_pool));
 
-  merge_target_abspath = APR_ARRAY_IDX(details->wc_siblings,
-                                       details->preferred_sibling_idx,
-                                       const char *);
+  if (details->wc_move_targets)
+    {
+      apr_array_header_t *moves;
+
+      moves = svn_hash_gets(details->wc_move_targets,
+                            details->move_target_repos_relpath);
+      merge_target_abspath =
+        APR_ARRAY_IDX(moves, details->wc_move_target_idx, const char *);
+    }
+  else
+    merge_target_abspath = APR_ARRAY_IDX(details->wc_siblings,
+                                         details->preferred_sibling_idx,
+                                         const char *);
 
   /* ### The following WC modifications should be atomic. */
   SVN_ERR(svn_wc__acquire_write_lock_for_resolve(
@@ -9283,7 +9311,7 @@ resolve_sibling_move_dir_merge(svn_clien
   if (err)
     goto unlock_wc;
 
-  /* Merge outstanding changes to the sibling merge target. */
+  /* Merge outstanding changes to the merge target. */
   incoming_old_url = apr_pstrcat(scratch_pool, repos_root_url, "/",
                                  incoming_old_repos_relpath, SVN_VA_NULL);
   incoming_old_opt_rev.kind = svn_opt_revision_number;
@@ -10341,10 +10369,11 @@ configure_option_incoming_dir_merge(svn_
 /* Configure 'local move file merge' resolution option for
  * a tree conflict. */
 static svn_error_t *
-configure_option_local_move_file_merge(svn_client_conflict_t *conflict,
-                                       svn_client_ctx_t *ctx,
-                                       apr_array_header_t *options,
-                                       apr_pool_t *scratch_pool)
+configure_option_local_move_file_or_dir_merge(
+  svn_client_conflict_t *conflict,
+  svn_client_ctx_t *ctx,
+  apr_array_header_t *options,
+  apr_pool_t *scratch_pool)
 {
   svn_wc_operation_t operation;
   svn_wc_conflict_action_t incoming_change;
@@ -10370,12 +10399,7 @@ configure_option_local_move_file_merge(s
 
   if (operation == svn_wc_operation_merge &&
       incoming_change == svn_wc_conflict_action_edit &&
-      local_change == svn_wc_conflict_reason_missing &&
-      /* We do not support this case for directories yet. */
-      (incoming_old_kind == svn_node_file ||
-       incoming_old_kind == svn_node_none) &&
-      (incoming_new_kind == svn_node_file ||
-       incoming_new_kind == svn_node_none))
+      local_change == svn_wc_conflict_reason_missing)
     {
       struct conflict_tree_local_missing_details *details;
       const char *wcroot_abspath;
@@ -10404,11 +10428,25 @@ configure_option_local_move_file_merge(s
                 svn_dirent_skip_ancestor(wcroot_abspath, moved_to_abspath),
                 scratch_pool));
 
-          add_resolution_option(
-            options, conflict,
-            svn_client_conflict_option_local_move_file_text_merge,
-            _("Apply to move destination"),
-            description, resolve_local_move_file_merge);
+          if ((incoming_old_kind == svn_node_file ||
+               incoming_old_kind == svn_node_none) &&
+              (incoming_new_kind == svn_node_file ||
+               incoming_new_kind == svn_node_none))
+            {
+              add_resolution_option(
+                options, conflict,
+                svn_client_conflict_option_local_move_file_text_merge,
+                _("Apply to move destination"),
+                description, resolve_local_move_file_merge);
+            }
+          else
+            {
+              add_resolution_option(
+                options, conflict,
+                svn_client_conflict_option_local_move_dir_merge,
+                _("Apply to move destination"),
+                description, resolve_local_move_dir_merge);
+            }
         }
     }
 
@@ -10491,7 +10529,7 @@ configure_option_sibling_move_merge(svn_
                 options, conflict,
                 svn_client_conflict_option_sibling_move_dir_merge,
                 _("Apply to corresponding local location"),
-                description, resolve_sibling_move_dir_merge);
+                description, resolve_local_move_dir_merge);
             }
         }
     }
@@ -11119,8 +11157,9 @@ svn_client_conflict_tree_get_resolution_
                                                     scratch_pool));
   SVN_ERR(configure_option_incoming_dir_merge(conflict, ctx, *options,
                                               scratch_pool));
-  SVN_ERR(configure_option_local_move_file_merge(conflict, ctx, *options,
-                                                 scratch_pool));
+  SVN_ERR(configure_option_local_move_file_or_dir_merge(conflict, ctx,
+                                                        *options,
+                                                        scratch_pool));
   SVN_ERR(configure_option_sibling_move_merge(conflict, ctx, *options,
                                               scratch_pool));
 

Modified: 
subversion/branches/1.11.x/subversion/tests/libsvn_client/conflicts-test.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/1.11.x/subversion/tests/libsvn_client/conflicts-test.c?rev=1841874&r1=1841873&r2=1841874&view=diff
==============================================================================
--- subversion/branches/1.11.x/subversion/tests/libsvn_client/conflicts-test.c 
(original)
+++ subversion/branches/1.11.x/subversion/tests/libsvn_client/conflicts-test.c 
Mon Sep 24 16:37:53 2018
@@ -5880,6 +5880,185 @@ test_local_missing_abiguous_moves(const
 }
 
 static svn_error_t *
+test_local_missing_abiguous_moves_dir(const svn_test_opts_t *opts,
+                                      apr_pool_t *pool)
+{
+  svn_test__sandbox_t *b = apr_palloc(pool, sizeof(*b));
+  svn_opt_revision_t opt_rev;
+  svn_client_ctx_t *ctx;
+  svn_client_conflict_t *conflict;
+  apr_array_header_t *options;
+  svn_client_conflict_option_t *option;
+  apr_array_header_t *possible_moved_to_repos_relpaths;
+  apr_array_header_t *possible_moved_to_abspaths;
+  struct status_baton sb;
+  struct svn_client_status_t *status;
+  svn_stringbuf_t *buf;
+
+  SVN_ERR(svn_test__sandbox_create(b, "local_missing_ambiguous_moves_dir",
+                                   opts, pool));
+
+  SVN_ERR(sbox_add_and_commit_greek_tree(b)); /* r1 */
+
+  /* Create a copy of node "A" (the "trunk") to "A1" (the "branch"). */
+  SVN_ERR(sbox_wc_copy(b, "A", "A1"));
+  SVN_ERR(sbox_wc_commit(b, "")); /* r2 */
+
+  SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+  /* Copy a dir across branch boundaries (gives ambiguous WC targets later). */
+  SVN_ERR(sbox_wc_copy(b, "A/B", "A1/B-copied-from-A"));
+  /* Create an ambiguous move with the "trunk". */
+  SVN_ERR(sbox_wc_copy(b, "A/B", "A/B-copied"));
+  SVN_ERR(sbox_wc_move(b, "A/B", "A/B-moved"));
+  SVN_ERR(sbox_wc_commit(b, "")); /* r3 */
+
+  /* Modify a file in the moved directory on the "branch". */
+  SVN_ERR(sbox_file_write(b, "A1/B/lambda", "Modified content." APR_EOL_STR));
+  SVN_ERR(sbox_wc_commit(b, "")); /* r4 */
+  SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM));
+
+  /* Merge "A1" ("branch") into "A" ("trunk"). */
+  opt_rev.kind = svn_opt_revision_head;
+  opt_rev.value.number = SVN_INVALID_REVNUM;
+  SVN_ERR(svn_test__create_client_ctx(&ctx, b, pool));
+  SVN_ERR(svn_client_merge_peg5(svn_path_url_add_component2(b->repos_url, "A1",
+                                                            pool),
+                                NULL, &opt_rev, sbox_wc_path(b, "A"),
+                                svn_depth_infinity,
+                                FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+                                NULL, ctx, pool));
+
+  SVN_ERR(svn_client_conflict_get(&conflict, sbox_wc_path(b, "A/B"),
+                                  ctx, b->pool, b->pool));
+  {
+    svn_client_conflict_option_id_t expected_opts[] = {
+      svn_client_conflict_option_postpone,
+      svn_client_conflict_option_accept_current_wc_state,
+      -1 /* end of list */
+    };
+    SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts,
+                                         b->pool));
+  }
+  SVN_ERR(svn_client_conflict_tree_get_details(conflict, ctx, b->pool));
+  {
+    svn_client_conflict_option_id_t expected_opts[] = {
+      svn_client_conflict_option_postpone,
+      svn_client_conflict_option_accept_current_wc_state,
+      svn_client_conflict_option_local_move_dir_merge,
+      -1 /* end of list */
+    };
+    SVN_ERR(assert_tree_conflict_options(conflict, ctx, expected_opts,
+                                         b->pool));
+  }
+
+  SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, conflict,
+                                                          ctx, b->pool,
+                                                          b->pool));
+  option = svn_client_conflict_option_find_by_id(
+             options, svn_client_conflict_option_local_move_dir_merge);
+  SVN_TEST_ASSERT(option != NULL);
+
+       /*
+        * Possible repository destinations for moved-away 'A/mu' are:
+        *  (1): '^/A/B-copied'
+        *  (2): '^/A/B-moved'
+        *  (3): '^/A1/B-copied-from-A'
+        */
+  SVN_ERR(svn_client_conflict_option_get_moved_to_repos_relpath_candidates(
+            &possible_moved_to_repos_relpaths, option, b->pool, b->pool));
+  SVN_TEST_INT_ASSERT(possible_moved_to_repos_relpaths->nelts, 3);
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_repos_relpaths, 0, const char *),
+    "A/B-copied");
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_repos_relpaths, 1, const char *),
+    "A/B-moved");
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_repos_relpaths, 2, const char *),
+    "A1/B-copied-from-A");
+
+  /* Move target for "A/B-copied" (selected by default) is not ambiguous. */
+  SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+            &possible_moved_to_abspaths, option, b->pool, b->pool));
+  SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 1);
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+    sbox_wc_path(b, "A/B-copied"));
+
+  /* Move target for "A/mu-moved" is not ambiguous. */
+  SVN_ERR(svn_client_conflict_option_set_moved_to_repos_relpath(option, 1,
+                                                                ctx, b->pool));
+  SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+            &possible_moved_to_abspaths, option, b->pool, b->pool));
+  SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 1);
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+    sbox_wc_path(b, "A/B-moved"));
+
+  /* Select move target "A1/mu-copied-from-A". */
+  SVN_ERR(svn_client_conflict_option_set_moved_to_repos_relpath(option, 2,
+                                                                ctx, b->pool));
+
+  /*
+        * Possible working copy destinations for moved-away 'A/mu' are:
+        *  (1): 'A/B-copied-from-A'
+        *  (2): 'A1/B-copied-from-A'
+   */
+  SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates(
+            &possible_moved_to_abspaths, option, b->pool, b->pool));
+  SVN_TEST_INT_ASSERT(possible_moved_to_abspaths->nelts, 2);
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_abspaths, 0, const char *),
+    sbox_wc_path(b, "A/B-copied-from-A"));
+  SVN_TEST_STRING_ASSERT(
+    APR_ARRAY_IDX(possible_moved_to_abspaths, 1, const char *),
+    sbox_wc_path(b, "A1/B-copied-from-A"));
+
+  /* Select move target "A/B-moved". */
+  SVN_ERR(svn_client_conflict_option_set_moved_to_repos_relpath(option, 1,
+                                                                ctx, b->pool));
+
+  /* Resolve the tree conflict. */
+  SVN_ERR(svn_client_conflict_tree_resolve_by_id(
+            conflict,
+            svn_client_conflict_option_local_move_dir_merge, ctx,
+            b->pool));
+
+  /* The node "A/mu" should no longer exist. */
+  SVN_TEST_ASSERT_ERROR(svn_client_conflict_get(&conflict,
+                                                sbox_wc_path(b, "A/B"),
+                                                ctx, pool, pool),
+                        SVN_ERR_WC_PATH_NOT_FOUND);
+
+  /* Ensure that the merged file has the expected status. */
+  opt_rev.kind = svn_opt_revision_working;
+  sb.result_pool = b->pool;
+  SVN_ERR(svn_client_status6(NULL, ctx, sbox_wc_path(b, "A/B-moved/lambda"),
+                             &opt_rev, svn_depth_unknown, TRUE, TRUE,
+                             TRUE, TRUE, FALSE, TRUE, NULL,
+                             status_func, &sb, b->pool));
+  status = sb.status;
+  SVN_TEST_ASSERT(status->kind == svn_node_file);
+  SVN_TEST_ASSERT(status->versioned);
+  SVN_TEST_ASSERT(!status->conflicted);
+  SVN_TEST_ASSERT(status->node_status == svn_wc_status_modified);
+  SVN_TEST_ASSERT(status->text_status == svn_wc_status_modified);
+  SVN_TEST_ASSERT(status->prop_status == svn_wc_status_none);
+  SVN_TEST_ASSERT(!status->copied);
+  SVN_TEST_ASSERT(!status->switched);
+  SVN_TEST_ASSERT(!status->file_external);
+  SVN_TEST_ASSERT(status->moved_from_abspath == NULL);
+  SVN_TEST_ASSERT(status->moved_to_abspath == NULL);
+
+  /* And it should have expected contents. */
+  SVN_ERR(svn_stringbuf_from_file2(&buf, sbox_wc_path(b, "A/B-moved/lambda"),
+                                   pool));
+  SVN_TEST_STRING_ASSERT(buf->data, "Modified content." APR_EOL_STR);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 test_file_vs_dir_move_merge_assertion_failure(const svn_test_opts_t *opts,
                                               apr_pool_t *pool)
 {
@@ -6110,6 +6289,8 @@ static struct svn_test_descriptor_t test
                        "cherry-pick edit from moved directory"),
     SVN_TEST_OPTS_PASS(test_local_missing_abiguous_moves,
                        "local missing conflict with ambiguous moves"),
+    SVN_TEST_OPTS_PASS(test_local_missing_abiguous_moves_dir,
+                       "local missing conflict with ambiguous dir moves"),
     SVN_TEST_OPTS_PASS(test_file_vs_dir_move_merge_assertion_failure,
                        "file v dir move merge assertion failure"),
     SVN_TEST_NULL


Reply via email to