You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2010/04/15 17:34:35 UTC

svn commit: r934454 - in /subversion/trunk/subversion: libsvn_client/merge.c tests/cmdline/merge_tests.py

Author: pburba
Date: Thu Apr 15 15:34:35 2010
New Revision: 934454

URL: http://svn.apache.org/viewvc?rev=934454&view=rev
Log:
Fix issue #3603 'allow reintegrate merges into WCs with missing subtrees'.

* subversion/libsvn_client/merge.c

 (ensure_wc_reflects_repository_subtree): Consider shallow WCs as ready
  to reintegrate to.  That's it!  Nothing special, it works as you'd
  expect.

* subversion/tests/cmdline/merge_tests.py

 (reintegrate_fail_on_shallow_wc): Rename to...

 (reintegrate_on_shallow_wc): ...this.  Reimplement the test to expect
  success when reintegrating into a shallow WC.

 (test_list): Reflect test rename.

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=934454&r1=934453&r2=934454&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu Apr 15 15:34:35 2010
@@ -8615,9 +8615,9 @@ svn_client_merge3(const char *source1,
 }
 
 
-/* If TARGET_WCPATH does not reflect a single-revision,
-   svn_depth_infinity, pristine, unswitched working copy -- in other
-   words, a subtree found in a single revision -- raise
+/* If TARGET_WCPATH does not reflect a single-revision, pristine,
+   unswitched working copy -- in other words, a subtree found in a
+   single revision (although sparse checkouts are permitted) -- raise
    SVN_ERR_CLIENT_NOT_READY_TO_MERGE. */
 static svn_error_t *
 ensure_wc_reflects_repository_subtree(const char *target_abspath,
@@ -8636,11 +8636,6 @@ ensure_wc_reflects_repository_subtree(co
                             _("Cannot reintegrate into a working copy "
                               "with a switched subtree"));
 
-  if (wc_stat->sparse_checkout)
-    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
-                            _("Cannot reintegrate into a working copy "
-                              "not entirely at infinite depth"));
-
   if (wc_stat->modified)
     return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
                             _("Cannot reintegrate into a working copy "

Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=934454&r1=934453&r2=934454&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Thu Apr 15 15:34:35 2010
@@ -11026,27 +11026,119 @@ def reintegrate_fail_on_switched_wc(sbox
     ".*Cannot reintegrate into a working copy with a switched subtree.*",
     None, None, None, None, True, False, '--reintegrate')
 
-def reintegrate_fail_on_shallow_wc(sbox):
-  "merge --reintegrate should fail in shallow wc"
+
+# Test for issue #3603 'allow reintegrate merges into WCs with
+# missing subtrees'.
+def reintegrate_on_shallow_wc(sbox):
+  "merge --reintegrate in shallow wc"
+
+  # Create a standard greek tree, branch A to A_COPY in r2.
   sbox.build()
   wc_dir = sbox.wc_dir
-  expected_disk, expected_status = set_up_branch(sbox)
-  A_path = os.path.join(wc_dir, "A")
-  G_path = os.path.join(A_path, "D", "G")
-  # Our default checkout doesn't have any subdirs at non-infinite
-  # depth, so we'll have to create one the old-fashioned way: remove a
-  # tree, then "update" it back into existence at a shallower depth.
-  svntest.main.safe_rmtree(G_path)
-  svntest.actions.run_and_verify_svn(None, None, [], 'update', G_path,
-                                     '--depth=files')
-  # Even though everything is actually present (as G has no subdirs
-  # anyway), the reintegration should fail, because G's depth is other
-  # than infinity.
-  svntest.actions.run_and_verify_merge(
-    A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
-    None, None, None,
-    ".*Cannot reintegrate into a working copy not.*at infinite depth.*",
-    None, None, None, None, True, False, '--reintegrate')
+  expected_disk, expected_status = set_up_branch(sbox, branch_only = True)
+
+  # Some paths we'll care about
+  A_path         = os.path.join(wc_dir, "A")
+  A_D_path       = os.path.join(wc_dir, "A", "D")
+  mu_COPY_path   = os.path.join(wc_dir, "A_COPY", "mu")
+  psi_COPY_path  = os.path.join(wc_dir, "A_COPY", "D", "H", "psi")
+  A_COPY_path    = os.path.join(wc_dir, "A_COPY")
+
+  # r3 - Make a change on the A_COPY branch that will be
+  # reintegrated back to A.
+  svntest.main.file_write(mu_COPY_path, "branch work")
+  svntest.main.run_svn(None, 'commit', '-m',
+                       'Some work on the A_COPY branch', wc_dir)
+
+  # First try a reintegrate where the target WC has a shallow subtree
+  # that is not affected by the reintegrate.  In this case we set the
+  # depth of A/D to empty.  Since the only change made on the branch
+  # since the branch point is to A_COPY/mu, the reintegrate should
+  # simply work and update A/mu with the branch's contents.
+  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'up',
+                                     '--set-depth', 'empty', A_D_path)
+  expected_output = wc.State(A_path, {
+    'mu' : Item(status='U '),
+    })
+  expected_mergeinfo_output = wc.State(A_path, {
+    '' : Item(status=' U'),
+    })
+  expected_elision_output = wc.State(A_path, {
+    })
+  expected_A_status = wc.State(A_path, {
+    ''          : Item(status=' M'),
+    'B'         : Item(status='  '),
+    'mu'        : Item(status='M '),
+    'B/E'       : Item(status='  '),
+    'B/E/alpha' : Item(status='  '),
+    'B/E/beta'  : Item(status='  '),
+    'B/lambda'  : Item(status='  '),
+    'B/F'       : Item(status='  '),
+    'C'         : Item(status='  '),
+    'D'         : Item(status='  '), # Don't expect anything under D,
+                                     # its depth is empty!
+    })
+  expected_A_status.tweak(wc_rev=3)
+  expected_A_disk = wc.State('', {
+    ''          : Item(props={SVN_PROP_MERGEINFO : '/A_COPY:2-3'}),
+    'B'         : Item(),
+    'mu'        : Item("branch work"),
+    'B/E'       : Item(),
+    'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+    'B/E/beta'  : Item("This is the file 'beta'.\n"),
+    'B/lambda'  : Item("This is the file 'lambda'.\n"),
+    'B/F'       : Item(),
+    'C'         : Item(),
+    'D'         : Item(), # Don't expect anything under D, its depth is empty!
+    })
+  expected_A_skip = wc.State(A_COPY_path, {})
+  svntest.actions.run_and_verify_merge(A_path, None, None,
+                                       sbox.repo_url + '/A_COPY', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_A_disk,
+                                       expected_A_status,
+                                       expected_A_skip,
+                                       None, None, None, None,
+                                       None, 1, 1, "--reintegrate")
+
+  # Now revert the reintegrate and make a second change on the
+  # branch in r4, but this time change a subtree that corresponds
+  # to the missing (shallow) portion of the source.  The reintegrate
+  # should still succeed, albeit with a tree-conflict.
+  svntest.actions.run_and_verify_svn(None, None, [], 'revert', '-R', wc_dir)
+  svntest.main.file_write(psi_COPY_path, "more branch work")
+  svntest.main.run_svn(None, 'commit', '-m',
+                       'Some more work on the A_COPY branch', wc_dir)
+  # Reuse the same expectations as the prior merge, except that...
+  #
+  # ...a tree conflict occurs...
+  expected_output.add({
+      'D/H' : Item(status='  ', treeconflict='C')
+      })
+  expected_A_status.add({
+      'D/H' : Item(status='! ', treeconflict='C')
+      })
+  # ...non-inheritable mergeinfo is set on the root of the missing subtree...
+  expected_mergeinfo_output.add({
+      'D' : Item(status=' U')
+      })
+  expected_A_status.tweak('D', status=' M')
+  expected_A_disk.tweak('D', props={SVN_PROP_MERGEINFO : '/A_COPY/D:2-4*'})
+  # ...the mergeinfo on the target root includes the latest rev on the branch.
+  expected_A_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-4'})
+  svntest.actions.run_and_verify_merge(A_path, None, None,
+                                       sbox.repo_url + '/A_COPY', None,
+                                       expected_output,
+                                       expected_mergeinfo_output,
+                                       expected_elision_output,
+                                       expected_A_disk,
+                                       expected_A_status,
+                                       expected_A_skip,
+                                       None, None, None, None,
+                                       None, 1, 1, "--reintegrate")
 
 def reintegrate_fail_on_stale_source(sbox):
   "merge --reintegrate should fail on stale source"
@@ -19033,7 +19125,7 @@ test_list = [ None,
               reintegrate_fail_on_modified_wc,
               reintegrate_fail_on_mixed_rev_wc,
               reintegrate_fail_on_switched_wc,
-              reintegrate_fail_on_shallow_wc,
+              reintegrate_on_shallow_wc,
               SkipUnless(reintegrate_fail_on_stale_source,
                          server_has_mergeinfo),
               SkipUnless(dont_add_mergeinfo_from_own_history,