Rev 2609: (marius, r=robert, r=mbp) Fix rm of renamed files in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Jul 12 13:42:48 BST 2007


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 2609
revision-id: pqm at pqm.ubuntu.com-20070712124245-vaw0ajlwrexg8d0m
parent: pqm at pqm.ubuntu.com-20070712114408-7iozx4b8hq8ts24n
parent: mbp at sourcefrog.net-20070712101425-tpdmq32cjezsmrsc
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2007-07-12 13:42:45 +0100
message:
  (marius,r=robert,r=mbp) Fix rm of renamed files
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/tests/blackbox/test_remove.py test_remove.py-20060530011439-fika5rm84lon0goe-1
  bzrlib/tests/workingtree_implementations/test_remove.py test_remove.py-20070413183901-rvnp85rtc0q0sclp-1
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 2605.1.2
    merged: mbp at sourcefrog.net-20070712101425-tpdmq32cjezsmrsc
    parent: mbp at sourcefrog.net-20070712092621-y3rt81f3t6rvcfnx
    committer: Martin Pool <mbp at sourcefrog.net>
    branch nick: rm-renamed
    timestamp: Thu 2007-07-12 20:14:25 +1000
    message:
      Fix up run_bzr calls
    ------------------------------------------------------------
    revno: 2605.1.1
    merged: mbp at sourcefrog.net-20070712092621-y3rt81f3t6rvcfnx
    parent: pqm at pqm.ubuntu.com-20070712085245-afvocysw990c1a3z
    parent: marius.kruger at enerweb.co.za-20070628061106-dw6t7vpj0hlo3461
    committer: Martin Pool <mbp at sourcefrog.net>
    branch nick: rm-renamed
    timestamp: Thu 2007-07-12 19:26:21 +1000
    message:
      Merge fix for rm renamed files
    ------------------------------------------------------------
    revno: 2475.5.6
    merged: marius.kruger at enerweb.co.za-20070628061106-dw6t7vpj0hlo3461
    parent: marius.kruger at enerweb.co.za-20070627184810-4jq1y5f20xafow9w
    committer: Marius Kruger <marius.kruger at enerweb.co.za>
    branch nick: bzr.fix_bug_111664
    timestamp: Thu 2007-06-28 08:11:06 +0200
    message:
      * test_remove
        - Remove redundant method _assertRemoveErrorContainsRe and update the test
          which used to use it.
    ------------------------------------------------------------
    revno: 2475.5.5
    merged: marius.kruger at enerweb.co.za-20070627184810-4jq1y5f20xafow9w
    parent: amanic at gmail.com-20070623194517-9kgydu5fgjtzmu7m
    parent: pqm at pqm.ubuntu.com-20070627080723-ci6ghe3bsm0snyit
    committer: Marius Kruger <marius.kruger at enerweb.co.za>
    branch nick: bzr.fix_bug_111664
    timestamp: Wed 2007-06-27 20:48:10 +0200
    message:
      Merge with bzr.dev
    ------------------------------------------------------------
    revno: 2475.5.4
    merged: amanic at gmail.com-20070623194517-9kgydu5fgjtzmu7m
    parent: amanic at gmail.com-20070623175922-9dlpr6bxipcklr8g
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.fix_bug_111664
    timestamp: Sat 2007-06-23 21:45:17 +0200
    message:
      * Don't introduce more tests calling run_bzr with a non-list.
      * Use more elegant way of ignoring new lines in test helper.
    ------------------------------------------------------------
    revno: 2475.5.3
    merged: amanic at gmail.com-20070623175922-9dlpr6bxipcklr8g
    parent: amanic at gmail.com-20070506014714-9vp1redn0760c8ra
    parent: pqm at pqm.ubuntu.com-20070622160825-17gv0lorkzbr3x76
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.fix_bug_111664
    timestamp: Sat 2007-06-23 19:59:22 +0200
    message:
      merge with bzr.dev
    ------------------------------------------------------------
    revno: 2475.5.2
    merged: amanic at gmail.com-20070506014714-9vp1redn0760c8ra
    parent: amanic at gmail.com-20070503071126-jez3l2o6l7oemsux
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.fix_bug_111664
    timestamp: Sun 2007-05-06 03:47:14 +0200
    message:
      * blackbox/test_remove
        - bzr rm bogus_file does not throw an exception any more.
      * workingtree_implementations/test_remove
        - Surround = with spaces for Alexander.
        - Split out _assertRemoveErrorContainsRe which uses
          assertContainsRe, to check if the error is as expected.
        - Use assertRaises to check if the correct exceptions are thrown.
        - Use build_tree_contents to change file contents.
        - update test_remove_renamed_files doc string
        - add test_remove_renamed_changed_files
        - workingtree.remove( ['bogus_file'] does not throw an exception any more.
      * workingtree.remove
        - Fix minor typo in doctring, accidentally introduced by me recently.
        - Rather use _iter_changes to detect changes as suggested by Aaron. 
          This is more flexible and more correct. 
    ------------------------------------------------------------
    revno: 2475.5.1
    merged: amanic at gmail.com-20070503071126-jez3l2o6l7oemsux
    parent: pqm at pqm.ubuntu.com-20070501182714-71xp33bziogu3qu0
    committer: Marius Kruger <amanic at gmail.com>
    branch nick: bzr.rm_delete_working_file
    timestamp: Thu 2007-05-03 09:11:26 +0200
    message:
      Fix bug and test: bzr rm refuses to delete renamed files
      (Bug #111664)
=== modified file 'NEWS'
--- a/NEWS	2007-07-12 09:49:37 +0000
+++ b/NEWS	2007-07-12 12:42:45 +0000
@@ -2,7 +2,9 @@
 
   BUGFIXES:
 
-    * None yet ...
+    * ``bzr rm`` now does not insist on ``--force`` to delete files that
+      have been renamed but not otherwise modified.  (Marius Kruger,
+      #111664)
 
   IMPROVEMENTS:
 

=== modified file 'bzrlib/tests/blackbox/test_remove.py'
--- a/bzrlib/tests/blackbox/test_remove.py	2007-06-27 19:13:50 +0000
+++ b/bzrlib/tests/blackbox/test_remove.py	2007-07-12 10:14:25 +0000
@@ -64,9 +64,9 @@
             ' or --force to delete them regardless.'
             ])
         self.run_bzr_error(error_regexes,
-            'remove ' + ' '.join(files_to_remove))
+            ['remove'] + list(files_to_remove))
         #see if we can force it now
-        self.run_bzr('remove --force ' + ' '.join(files_to_remove))
+        self.run_bzr(['remove', '--force'] + list(files_to_remove))
 
     def test_remove_no_files_specified(self):
         tree = self._make_add_and_assert_tree([])
@@ -106,8 +106,7 @@
     def test_remove_invalid_files(self):
         self.build_tree(files)
         tree = self.make_branch_and_tree('.')
-        self.run_bzr_remove_changed_files(['unknown:[.\s]*xyz[.\s]*abc/def'],
-            ['.', 'xyz', 'abc/def'])
+        self.run_bzr(['remove', '.', 'xyz', 'abc/def'])
 
     def test_remove_unversioned_files(self):
         self.build_tree(files)
@@ -143,7 +142,7 @@
     def test_remove_force_unversioned_files(self):
         self.build_tree(files)
         tree = self.make_branch_and_tree('.')
-        self.run_bzr('remove --force ' + ' '.join(files),
+        self.run_bzr(['remove', '--force'] + list(files),
                      error_regexes=["deleted a", "deleted b",
                                     "deleted b/c", "deleted d"])
         self.assertFilesDeleted(files)
@@ -163,7 +162,7 @@
 
     def test_remove_non_existing_files(self):
         tree = self._make_add_and_assert_tree([])
-        self.run_bzr_remove_changed_files(['unknown:[.\s]*b'], ['b'])
+        self.run_bzr(['remove', 'b'])
 
     def test_remove_keep_non_existing_files(self):
         tree = self._make_add_and_assert_tree([])

=== modified file 'bzrlib/tests/workingtree_implementations/test_remove.py'
--- a/bzrlib/tests/workingtree_implementations/test_remove.py	2007-06-15 07:01:24 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_remove.py	2007-06-28 06:11:06 +0000
@@ -16,14 +16,14 @@
 
 """Tests for interface conformance of 'WorkingTree.remove'"""
 
-import re
 from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
 from bzrlib import errors, osutils
 
 class TestRemove(TestCaseWithWorkingTree):
     """Tests WorkingTree.remove"""
 
-    files=['a', 'b/', 'b/c', 'd/']
+    files = ['a', 'b/', 'b/c', 'd/']
+    rfiles = ['b/c', 'b', 'a', 'd']
     a = ['a']
     b = ['b']
     b_c = ['b', 'b/c']
@@ -60,13 +60,10 @@
         tree = self.getTree()
         tree.add(TestRemove.files)
         self.assertInWorkingTree(TestRemove.files)
-        try:
-            tree.remove(TestRemove.files, keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*added:.*a.*b.*b/c.*d.*',
-                str(e), re.DOTALL))
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            TestRemove.files, keep_files=False)
+        self.assertContainsRe(err.changes_as_text,
+            '(?s)added:.*a.*b/.*b/c.*d/')
         self.assertInWorkingTree(TestRemove.files)
         self.failUnlessExists(TestRemove.files)
 
@@ -75,17 +72,11 @@
         tree = self.getTree()
         tree.add(TestRemove.a)
         tree.commit("make sure a is versioned")
-        f = file('a', 'wb')
-        f.write("some other new content!")
-        f.close()
+        self.build_tree_contents([('a', "some other new content!")])
         self.assertInWorkingTree(TestRemove.a)
-        try:
-            tree.remove(TestRemove.a, keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*modified:.*a.*',
-                str(e), re.DOTALL))
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            TestRemove.a, keep_files=False)
+        self.assertContainsRe(err.changes_as_text, '(?s)modified:.*a')
         self.assertInWorkingTree(TestRemove.a)
         self.failUnlessExists(TestRemove.a)
 
@@ -94,7 +85,7 @@
         tree = self.getTree()
         tree.add(TestRemove.files)
         tree.commit("make sure files are versioned")
-        for f in ['b/c', 'b', 'a', 'd']:
+        for f in TestRemove.rfiles:
             osutils.delete_any(f)
         self.assertInWorkingTree(TestRemove.files)
         self.failIfExists(TestRemove.files)
@@ -104,6 +95,44 @@
         self.assertNotInWorkingTree(TestRemove.files)
         self.failIfExists(TestRemove.files)
 
+    def test_remove_renamed_files(self):
+        """Check that files are removed even if they are renamed."""
+        tree = self.getTree()
+        tree.add(TestRemove.files)
+        tree.commit("make sure files are versioned")
+
+        for f in TestRemove.rfiles:
+            tree.rename_one(f,f+'x')
+        rfilesx = ['bx/cx', 'bx', 'ax', 'dx']
+        self.assertInWorkingTree(rfilesx)
+        self.failUnlessExists(rfilesx)
+
+        tree.remove(rfilesx, keep_files=False)
+
+        self.assertNotInWorkingTree(rfilesx)
+        self.failIfExists(rfilesx)
+
+    def test_remove_renamed_changed_files(self):
+        """Check that files are not removed if they are renamed and changed."""
+        tree = self.getTree()
+        tree.add(TestRemove.files)
+        tree.commit("make sure files are versioned")
+
+        for f in TestRemove.rfiles:
+            tree.rename_one(f,f+'x')
+        rfilesx = ['bx/cx', 'bx', 'ax', 'dx']
+        self.build_tree_contents([('ax','changed and renamed!'),
+                                  ('bx/cx','changed and renamed!')])
+        self.assertInWorkingTree(rfilesx)
+        self.failUnlessExists(rfilesx)
+
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            rfilesx, keep_files=False)
+        self.assertContainsRe(err.changes_as_text,
+            '(?s)modified:.*ax.*bx/cx')
+        self.assertInWorkingTree(rfilesx)
+        self.failUnlessExists(rfilesx)
+
     def test_force_remove_changed_files(self):
         """Check that changed files are removed and deleted when forced."""
         tree = self.getTree()
@@ -118,25 +147,16 @@
     def test_remove_unknown_files(self):
         """Try to delete unknown files."""
         tree = self.getTree()
-        try:
-            tree.remove(TestRemove.files, keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*unknown:.*b/c.*b.*a.*d.*',
-                str(e), re.DOTALL))
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            TestRemove.files, keep_files=False)
+        self.assertContainsRe(err.changes_as_text,
+            '(?s)unknown:.*d/.*b/c.*b/.*a.*')
 
     def test_remove_nonexisting_files(self):
         """Try to delete non-existing files."""
         tree = self.getTree()
         tree.remove([''], keep_files=False)
-        try:
-            tree.remove(['xyz', 'abc/def'], keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*unknown:.*xyz.*abc/def.*',
-                str(e), re.DOTALL))
+        tree.remove(['xyz', 'abc/def'], keep_files=False)
 
     def test_remove_nonempty_directory(self):
         """Unchanged non-empty directories should be deleted."""
@@ -156,16 +176,11 @@
         tree.commit("make sure b is versioned")
         self.assertInWorkingTree(TestRemove.files)
         self.failUnlessExists(TestRemove.files)
-        f = file('b/my_unknown_file', 'wb')
-        f.write("some content!")
-        f.close()
-        try:
-            tree.remove(TestRemove.b, keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*unknown:.*b/my_unknown_file.*',
-                str(e), re.DOTALL))
+        self.build_tree(['b/my_unknown_file'])
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            TestRemove.b, keep_files=False)
+        self.assertContainsRe(err.changes_as_text,
+            '(?s)unknown:.*b/my_unknown_file')
         self.assertInWorkingTree(TestRemove.b)
         self.failUnlessExists(TestRemove.b)
 
@@ -184,17 +199,11 @@
         tree = self.getTree()
         tree.add(TestRemove.b_c)
         tree.commit("make sure b and c are versioned")
-        f = file('b/c', 'wb')
-        f.write("some other new content!")
-        f.close()
+        self.build_tree_contents([('b/c', "some other new content!")])
         self.assertInWorkingTree(TestRemove.b_c)
-        try:
-            tree.remove(TestRemove.b, keep_files=False)
-            self.fail('Should throw BzrRemoveChangedFilesError')
-        except errors.BzrRemoveChangedFilesError, e:
-            self.assertTrue(re.match('Can\'t remove changed or unknown files:'
-                '.*modified:.*b/c.*',
-                str(e), re.DOTALL))
+        err = self.assertRaises(errors.BzrRemoveChangedFilesError, tree.remove,
+            TestRemove.b, keep_files=False)
+        self.assertContainsRe(err.changes_as_text, '(?s)modified:.*b/c')
         self.assertInWorkingTree(TestRemove.b_c)
         self.failUnlessExists(TestRemove.b_c)
 

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2007-07-12 07:22:52 +0000
+++ b/bzrlib/workingtree.py	2007-07-12 12:42:45 +0000
@@ -1767,7 +1767,7 @@
     @needs_tree_write_lock
     def remove(self, files, verbose=False, to_file=None, keep_files=True,
         force=False):
-        """Remove nominated files from the working inventor.
+        """Remove nominated files from the working inventory.
 
         :files: File paths relative to the basedir.
         :keep_files: If true, the files will also be kept.
@@ -1808,18 +1808,30 @@
                     recurse_directory_to_add_files(filename)
         files = [f for f in new_files]
 
+        if len(files) == 0:
+            return # nothing to do
+
         # Sort needed to first handle directory content before the directory
         files.sort(reverse=True)
         if not keep_files and not force:
-            tree_delta = self.changes_from(self.basis_tree(),
-                specific_files=files)
-            for unknown_file in unknown_files_in_directory:
-                tree_delta.unversioned.extend((unknown_file,))
-            if bool(tree_delta.modified
-                    or tree_delta.added
-                    or tree_delta.renamed
-                    or tree_delta.kind_changed
-                    or tree_delta.unversioned):
+            has_changed_files = len(unknown_files_in_directory) > 0
+            if not has_changed_files:
+                for (file_id, path, content_change, versioned, parent_id, name,
+                     kind, executable) in self._iter_changes(self.basis_tree(),
+                         include_unchanged=True, require_versioned=False,
+                         want_unversioned=True, specific_files=files):
+                    # check if it's unknown OR changed but not deleted:
+                    if (versioned == (False, False)
+                        or (content_change and kind[1] != None)):
+                        has_changed_files = True
+                        break
+
+            if has_changed_files:
+                # make delta to show ALL applicable changes in error message.
+                tree_delta = self.changes_from(self.basis_tree(),
+                    specific_files=files)
+                for unknown_file in unknown_files_in_directory:
+                    tree_delta.unversioned.extend((unknown_file,))
                 raise errors.BzrRemoveChangedFilesError(tree_delta)
 
         # do this before any modifications




More information about the bazaar-commits mailing list