Author: julianfoad
Date: Thu Jun 25 16:35:14 2020
New Revision: 1879192

URL: http://svn.apache.org/viewvc?rev=1879192&view=rev
Log:
Fix issue #4859 "Merge removing a folder with non-inheritable mergeinfo ->
E155023: can't set properties: invalid status for updating properties".

The code was attempting to set mergeinfo on a path that is being deleted by
the merge.  This happened only in certain unusual cases such as when
deleting a folder that had non-inheritable mergeinfo and had children.

This patch fixes the problem by removing the 'children_with_mergeinfo'
entries for sub-paths of a deleted folder.

* subversion/libsvn_client/merge.c
  (merge_cmd_baton_t): Allow modifying 'children_with_mergeinfo'.
  (record_update_delete): Remove from 'children_with_mergeinfo' all paths
    in the subtree.

* subversion/tests/cmdline/merge_tests.py
  (merge_deleted_folder_with_mergeinfo): Remove 'XFail'.
  (merge_deleted_folder_with_mergeinfo_2): New test.
  (test_list): Add the new test.

Modified:
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/tests/cmdline/merge_tests.py

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1879192&r1=1879191&r2=1879192&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Jun 25 16:35:14 2020
@@ -264,7 +264,7 @@ typedef struct merge_cmd_baton_t {
 
   /* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
      comment) or a similar list for single-file-merges */
-  const apr_array_header_t *children_with_mergeinfo;
+  apr_array_header_t *children_with_mergeinfo;
 
   svn_client_ctx_t *ctx;              /* Client context for callbacks, etc. */
 
@@ -1545,6 +1545,25 @@ record_update_delete(merge_cmd_baton_t *
                     svn_node_kind_to_word(kind));
     }
 
+  /* Note in children_with_mergeinfo that all paths in this subtree are
+   * being deleted, to avoid trying to set mergeinfo on them later. */
+  if (merge_b->children_with_mergeinfo)
+    {
+      int i;
+
+      for (i = 0; i < merge_b->children_with_mergeinfo->nelts; i++)
+        {
+          svn_client__merge_path_t *child
+            = APR_ARRAY_IDX(merge_b->children_with_mergeinfo, i,
+                            svn_client__merge_path_t *);
+
+          if (svn_dirent_is_ancestor(local_abspath, child->abspath))
+            {
+              
SVN_ERR(svn_sort__array_delete2(merge_b->children_with_mergeinfo, i--, 1));
+            }
+        }
+    }
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=1879192&r1=1879191&r2=1879192&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Thu Jun 25 
16:35:14 2020
@@ -18502,7 +18502,6 @@ def merge_dir_delete_force(sbox):
 
 # Issue #4859: Merge removing a folder with non-inheritable mergeinfo ->
 # E155023: can't set properties: invalid status for updating properties
-@XFail()
 @Issue(4859)
 def merge_deleted_folder_with_mergeinfo(sbox):
   "merge deleted folder with mergeinfo"
@@ -18527,6 +18526,55 @@ def merge_deleted_folder_with_mergeinfo(
   svntest.actions.run_and_verify_svn(None, [],
                                      'merge', '-c4', '^/branch_A', 
sbox.ospath('A'))
 
+# Issue #4859: Merge removing a folder with non-inheritable mergeinfo ->
+# E155023: can't set properties: invalid status for updating properties
+#
+# In this test we split the merge into two separate operable parts, a
+# delete followed later by an add, to check it will set the mergeinfo on the
+# subtree paths if the deleted folder is later replaced within the same
+# overall merge.
+@Issue(4859)
+def merge_deleted_folder_with_mergeinfo_2(sbox):
+  "merge deleted folder with mergeinfo 2"
+
+  sbox.build()
+
+  # Some non-inheritable mergeinfo
+  sbox.simple_propset('svn:mergeinfo', '/A/C:1*', 'A/D')
+  sbox.simple_commit() # r2
+
+  # Branching
+  sbox.simple_repo_copy('A', 'branch_A')  # r3
+  sbox.simple_update()
+
+  # On branch, remove a folder that has non-inheritable mergeinfo
+  sbox.simple_rm('branch_A/D')
+  sbox.simple_commit() # r4
+
+  # A commit that we don't want to merge from the branch, to split the merge
+  # into two separate operable parts.
+  sbox.simple_mkdir('branch_A/IgnoreThis')
+  sbox.simple_commit() # r5
+
+  # On branch, replace the deleted folder with a new one, with mergeinfo,
+  # to check we don't omit setting mergeinfo on this.
+  sbox.simple_mkdir('branch_A/D')
+  sbox.simple_propset('svn:mergeinfo', '/branch_B/C:1*', 'branch_A/D')
+  sbox.simple_mkdir('branch_A/D/G', 'branch_A/D/G2')
+  sbox.simple_propset('svn:mergeinfo', '/branch_B/C/G:1*', 'branch_A/D/G')
+  sbox.simple_propset('svn:mergeinfo', '/branch_B/C/G2:1*', 'branch_A/D/G2')
+  sbox.simple_commit() # r6
+
+  sbox.simple_propset('svn:mergeinfo', '/branch_A:5', 'A')
+  sbox.simple_commit() # r7
+
+  sbox.simple_update()
+
+  # A merge that removes that folder
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'merge', '^/branch_A', sbox.ospath('A'))
+  ### TODO: verify that mergeinfo is set/changed on A/D, A/D/G, A/D/G2.
+
 ########################################################################
 # Run the tests
 
@@ -18675,6 +18723,7 @@ test_list = [ None,
               conflict_naming,
               merge_dir_delete_force,
               merge_deleted_folder_with_mergeinfo,
+              merge_deleted_folder_with_mergeinfo_2,
              ]
 
 if __name__ == '__main__':


Reply via email to