Rev 3621: * ``bzr rm`` will now scan for files that are missing and remove just in http://people.ubuntu.com/~robertc/baz2.0/rm

Robert Collins robertc at robertcollins.net
Wed Aug 13 05:01:51 BST 2008


At http://people.ubuntu.com/~robertc/baz2.0/rm

------------------------------------------------------------
revno: 3621
revision-id: robertc at robertcollins.net-20080813035223-i9sxgq2rp5477oc5
parent: robertc at robertcollins.net-20080813032119-09pl9q0t9gxng5t6
committer: Robert Collins <robertc at robertcollins.net>
branch nick: rm
timestamp: Wed 2008-08-13 13:52:23 +1000
message:
   * ``bzr rm`` will now scan for files that are missing and remove just
     them automatically, much as ``bzr add`` scans for new files that
     are not ignored and adds them automatically. (Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/tests/blackbox/test_remove.py test_remove.py-20060530011439-fika5rm84lon0goe-1
=== modified file 'NEWS'
--- a/NEWS	2008-08-13 03:21:19 +0000
+++ b/NEWS	2008-08-13 03:52:23 +0000
@@ -14,6 +14,10 @@
     * ``bzr export`` can now export a subdirectory of a project.
       (Robert Collins)
 
+    * ``bzr rm`` will now scan for files that are missing and remove just
+      them automatically, much as ``bzr add`` scans for new files that
+      are not ignored and adds them automatically. (Robert Collins)
+
   BUG FIXES:
 
     * ``bzr upgrade`` on remote branches accessed via bzr:// and

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2008-08-11 03:39:25 +0000
+++ b/bzrlib/builtins.py	2008-08-13 03:52:23 +0000
@@ -1066,17 +1066,14 @@
 class cmd_remove(Command):
     """Remove files or directories.
 
-    This makes bzr stop tracking changes to the specified files and
-    delete them if they can easily be recovered using revert.
-
-    You can specify one or more files, and/or --new.  If you specify --new,
-    only 'added' files will be removed.  If you specify both, then new files
-    in the specified directories will be removed.  If the directories are
-    also new, they will also be removed.
+    This makes bzr stop tracking changes to the specified files and delete them
+    if they can easily be recovered using revert. If no options or parameters
+    are given bzr will scan for files that are versioned by bzr but missing in
+    your tree and unversion them for you.
     """
     takes_args = ['file*']
     takes_options = ['verbose',
-        Option('new', help='Remove newly-added files.'),
+        Option('new', help='Only remove files that have never been committed.'),
         RegistryOption.from_kwargs('file-deletion-strategy',
             'The file deletion mode to be used.',
             title='Deletion Strategy', value_switches=True, enum_switch=False,
@@ -1094,19 +1091,31 @@
 
         if file_list is not None:
             file_list = [f for f in file_list]
-        elif not new:
-            raise errors.BzrCommandError('Specify one or more files to'
-            ' remove, or use --new.')
 
-        if new:
-            added = tree.changes_from(tree.basis_tree(),
-                specific_files=file_list).added
-            file_list = sorted([f[0] for f in added], reverse=True)
-            if len(file_list) == 0:
-                raise errors.BzrCommandError('No matching files.')
-        tree.remove(file_list, verbose=verbose, to_file=self.outf,
-            keep_files=file_deletion_strategy=='keep',
-            force=file_deletion_strategy=='force')
+        tree.lock_write()
+        try:
+            # Heuristics should probably all move into tree.remove_smart or
+            # some such?
+            if new:
+                added = tree.changes_from(tree.basis_tree(),
+                    specific_files=file_list).added
+                file_list = sorted([f[0] for f in added], reverse=True)
+                if len(file_list) == 0:
+                    raise errors.BzrCommandError('No matching files.')
+            elif file_list is None:
+                # missing files show up in iter_changes(basis) as
+                # versioned-with-no-kind.
+                missing = []
+                for change in tree.iter_changes(tree.basis_tree()):
+                    if change[6][1] is None:
+                        missing.append(change[1][1])
+                file_list = sorted(missing, reverse=True)
+                file_deletion_strategy = 'keep'
+            tree.remove(file_list, verbose=verbose, to_file=self.outf,
+                keep_files=file_deletion_strategy=='keep',
+                force=file_deletion_strategy=='force')
+        finally:
+            tree.unlock()
 
 
 class cmd_file_id(Command):

=== modified file 'bzrlib/tests/blackbox/test_remove.py'
--- a/bzrlib/tests/blackbox/test_remove.py	2007-11-28 17:02:05 +0000
+++ b/bzrlib/tests/blackbox/test_remove.py	2008-08-13 03:52:23 +0000
@@ -18,7 +18,7 @@
 import os
 import sys
 
-from bzrlib.tests import TestSkipped
+from bzrlib.tests import SymlinkFeature, TestSkipped
 from bzrlib.tests.blackbox import ExternalBase
 from bzrlib.workingtree import WorkingTree
 from bzrlib import osutils
@@ -33,15 +33,16 @@
 
 class TestRemove(ExternalBase):
 
-    def _make_add_and_assert_tree(self, files):
+    def _make_add_and_assert_tree(self, paths):
         tree = self.make_branch_and_tree('.')
-        self.build_tree(files)
-        for f in files:
-            id=str(f).replace('/', '_') + _id
-            tree.add(f, id)
-            self.assertEqual(tree.path2id(f), id)
-            self.failUnlessExists(f)
-            self.assertInWorkingTree(f)
+        tree.lock_write()
+        try:
+            self.build_tree(paths)
+            for path in paths:
+                file_id=str(path).replace('/', '_') + _id
+                tree.add(path, file_id)
+        finally:
+            tree.unlock()
         return tree
 
     def assertFilesDeleted(self, files):
@@ -71,14 +72,58 @@
         self.run_bzr(['remove', '--force'] + list(files_to_remove))
 
     def test_remove_no_files_specified(self):
-        tree = self._make_add_and_assert_tree([])
-        self.run_bzr_error(["bzr: ERROR: Specify one or more files to remove, "
-            "or use --new."], 'remove')
-
-        self.run_bzr_error(["bzr: ERROR: No matching files."], 'remove --new')
-
-        self.run_bzr_error(["bzr: ERROR: No matching files."],
-            'remove --new .')
+        tree = self._make_add_and_assert_tree(['foo'])
+        out, err = self.run_bzr(['rm'])
+        self.assertEqual('', err)
+        self.assertEqual('', out)
+        self.assertInWorkingTree('foo', tree=tree)
+        self.failUnlessExists('foo')
+
+    def test_remove_no_files_specified_missing_dir_and_contents(self):
+        tree = self._make_add_and_assert_tree(
+            ['foo', 'dir/', 'dir/missing/', 'dir/missing/child'])
+        self.get_transport('.').delete_tree('dir/missing')
+        out, err = self.run_bzr(['rm'])
+        self.assertEqual('', out)
+        self.assertEqual(
+            'removed dir/missing/child\n'
+            'removed dir/missing\n',
+            err)
+        # non-missing paths not touched:
+        self.assertInWorkingTree('foo', tree=tree)
+        self.failUnlessExists('foo')
+        self.assertInWorkingTree('dir', tree=tree)
+        self.failUnlessExists('dir')
+        # missing files unversioned
+        self.assertNotInWorkingTree('dir/missing', tree=tree)
+        self.assertNotInWorkingTree('dir/missing/child', tree=tree)
+
+    def test_remove_no_files_specified_missing_file(self):
+        tree = self._make_add_and_assert_tree(['foo', 'bar'])
+        os.unlink('bar')
+        out, err = self.run_bzr(['rm'])
+        self.assertEqual('', out)
+        self.assertEqual('removed bar\n', err)
+        # non-missing files not touched:
+        self.assertInWorkingTree('foo', tree=tree)
+        self.failUnlessExists('foo')
+        # missing files unversioned
+        self.assertNotInWorkingTree('bar', tree=tree)
+
+    def test_remove_no_files_specified_missing_link(self):
+        self.requireFeature(SymlinkFeature)
+        tree = self._make_add_and_assert_tree(['foo'])
+        os.symlink('foo', 'linkname')
+        tree.add(['linkname'])
+        os.unlink('linkname')
+        out, err = self.run_bzr(['rm'])
+        self.assertEqual('', out)
+        self.assertEqual('removed linkname\n', err)
+        # non-missing files not touched:
+        self.assertInWorkingTree('foo', tree=tree)
+        self.failUnlessExists('foo')
+        # missing files unversioned
+        self.assertNotInWorkingTree('linkname', tree=tree)
 
     def test_rm_one_file(self):
         tree = self._make_add_and_assert_tree([a])




More information about the bazaar-commits mailing list