[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Trying and failing to fix issue #2153.

From: <kfogel_at_collab.net>
Date: 2004-12-17 22:52:33 CET

Issue #2153 is a simple bug:

   If you have a mixed-rev working copy, in which .svn/entries has an
   entry E marked as 'deleted', but E's parent is still at a revision
   from before E's deletion, then if you do 'svn cp my_wc new_url',
   the new_url will still contain E. This is because the deleted
   entry is never even seen by harvest_committables(), and therefore
   no editor->delete() command is ever given to remove it from the
   txn.

I thought it would have a simple fix, too, but my simple fix is
causing other regression tests to fail. I need to continue with an
issues sweep right now, so I'm posting my patch here in case anyone's
able to spot the problem quickly.

[[[
Fix issue #2153: wc-to-url copies would wrongly include deleted items.
Thanks to Ben Collins-Sussman for various helpful hints.

    ##############################################################
    ### ###
    ### Not ready for commit yet. The new regression test ###
    ### passes, but these changes cause at least basic_tests ###
    ### 25 and commit_tests 12 to fail. ###
    ### ###
    ##############################################################

* subversion/libsvn_client/commit_util.c
  (harvest_committables): If in copy_mode, request deleted entries
     too, and set the SVN_CLIENT_COMMIT_ITEM_DELETE flag on them.

* subversion/tests/clients/cmdline/copy_tests.py
  (mixed_wc_to_url): New test.
  (test_list): Run it.
]]]

Index: subversion/libsvn_client/commit_util.c
===================================================================
--- subversion/libsvn_client/commit_util.c (revision 12355)
+++ subversion/libsvn_client/commit_util.c (working copy)
@@ -162,8 +162,9 @@
    will not recurse into subdirectories of PATH when PATH is itself a
    directory.
 
- If in COPY_MODE, the entry is treated as if it is destined to be
- added with history as URL.
+ If in COPY_MODE, treat the entry as if it is destined to be added
+ with history as URL, and add 'deleted' entries to COMMITTABLES as
+ items to delete in the copy destination.
 
    If CTX->CANCEL_FUNC is non-null, call it with CTX->CANCEL_BATON to see
    if the user has cancelled the operation. */
@@ -249,7 +250,7 @@
          recurse anyway, so... ) */
       svn_error_t *err;
       const svn_wc_entry_t *e = NULL;
- err = svn_wc_entries_read (&entries, adm_access, FALSE, pool);
+ err = svn_wc_entries_read (&entries, adm_access, copy_mode, pool);
 
       /* If we failed to get an entries hash for the directory, no
          sweat. Cleanup and move along. */
@@ -296,11 +297,20 @@
   if ((entry->url) && (! copy_mode))
     url = entry->url;
 
- /* Check for the deletion case. Deletes can occur only when we are
- not in "adds-only mode". They can be either explicit
- (schedule == delete) or implicit (schedule == replace ::= delete+add). */
+ /* Check for the deletion case. Deletes occur only when not in
+ "adds-only mode". We use the SVN_CLIENT_COMMIT_ITEM_DELETE flag
+ to represent two slightly different conditions:
+
+ - The entry is marked as 'deleted'. When copying a mixed-rev wc,
+ we still need to send a delete for that entry, otherwise the
+ object will wrongly exist in the repository copy.
+
+ - The entry is scheduled for deletion or replacement, which case
+ we need to send a delete either way.
+ */
   if ((! adds_only)
- && ((entry->schedule == svn_wc_schedule_delete)
+ && (entry->deleted
+ || (entry->schedule == svn_wc_schedule_delete)
           || (entry->schedule == svn_wc_schedule_replace)))
     {
       state_flags |= SVN_CLIENT_COMMIT_ITEM_DELETE;
@@ -327,6 +337,7 @@
 
   /* Check for the copied-subtree addition case. */
   if ((entry->copied || copy_mode)
+ && (! entry->deleted)
       && (entry->schedule == svn_wc_schedule_normal))
     {
       svn_revnum_t p_rev = entry->revision - 1; /* arbitrary non-equal value */
Index: subversion/tests/clients/cmdline/copy_tests.py
===================================================================
--- subversion/tests/clients/cmdline/copy_tests.py (revision 12355)
+++ subversion/tests/clients/cmdline/copy_tests.py (working copy)
@@ -1475,6 +1475,65 @@
                                          None, None, None, None, None,
                                          wc_dir)
 
+
+#----------------------------------------------------------------------
+
+def mixed_wc_to_url(sbox):
+ "copy a complex mixed-rev wc"
+
+ # For issue 2153.
+ #
+ # Copy a mixed-revision wc (that also has some uncommitted local
+ # mods, and an entry marked as 'deleted') to a URL. Make sure the
+ # copy gets the uncommitted mods, and does not contain the deleted
+ # file.
+
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+ url = svntest.main.current_repo_url
+ G_url = svntest.main.current_repo_url + '/A/D/G'
+ Z_url = svntest.main.current_repo_url + '/A/D/Z'
+ G_path = os.path.join(wc_dir, 'A', 'D', 'G')
+ pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
+ rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
+
+ # Remove A/D/G/pi, then commit that removal.
+ svntest.actions.run_and_verify_svn(None, None, [], 'rm', pi_path)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'ci', '-m', "Delete pi.", wc_dir)
+
+ # Make a modification to A/D/G/rho, then commit that modification.
+ svntest.main.file_append(rho_path, "\nFirst modification to rho.\n")
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'ci', '-m', "Modify rho.", wc_dir)
+
+ # Make another modification to A/D/G/rho, but don't commit it.
+ svntest.main.file_append(rho_path, "Second modification to rho.\n")
+
+ # Now copy local A/D/G to create new directory A/D/Z the repository.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', '-m', "Make a copy.",
+ G_path, Z_url)
+
+ # Check out A/D/Z. If it has pi, that's a bug; or if its rho does
+ # not have the second local mod, that's also a bug.
+ svntest.main.safe_rmtree(wc_dir)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'co', Z_url, wc_dir)
+
+ if os.path.exists(os.path.join(wc_dir, 'pi')):
+ raise svntest.Failure
+
+ fp = open(os.path.join(wc_dir, 'rho'), 'r')
+ found_it = 0
+ for line in fp.readlines():
+ if re.match("^Second modification to rho.", line):
+ found_it = 1
+ if not found_it:
+ raise svntest.Failure
+
+
 ########################################################################
 # Run the tests
 
@@ -1505,6 +1564,7 @@
               repos_to_wc_1634,
               double_uri_escaping_1814,
               wc_to_wc_copy_deleted,
+ mixed_wc_to_url,
              ]
 
 if __name__ == '__main__':

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri Dec 17 22:54:10 2004

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.