[MERGE REVIEW] Clean-tree

John Arbash Meinel john at arbash-meinel.com
Sat Jun 3 09:23:18 BST 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Aaron Bentley wrote:
> Martin recently suggested we might merge clean-tree from bzrtools into
> the mainline, so here it is.  I've, updated it slightly to use note()
> instead of print.
> 
> I've been talking with John Meinel, and he suggested making --detritus
> the default.  Is that something we should do?
> 
> Aaron


Of course we should make it the default :)




...
+import errno
+import os
+import shutil
+import sys
+
+from bzrlib.osutils import has_symlinks, isdir
+from bzrlib.trace import note
+from bzrlib.workingtree import WorkingTree
+

^ you need an extra space here

+def is_detritus(subp):
+    return subp.endswith('.THIS') or subp.endswith('.BASE') or\
+        subp.endswith('.OTHER') or subp.endswith('~') or
subp.endswith('.tmp')


For performance this probably should be turned into the regex:
_is_detritus_re = re.compile(
    r'.*(?:(?:\.THIS$)|(?:\.BASE$)|(?:\.OTHER$)|(?:~$))'
    )

The (?:) is so that you can create a group that python doesn't have to
remember later.

v- you also need a space between the functions here

+
+def iter_deletables(tree, unknown=True, ignored=False, detritus=False):
+    """Iterate through files that may be deleted"""
+    for subp in tree.extras():
+        if detritus and is_detritus(subp):
+            yield tree.abspath(subp), subp
+            continue
+        if tree.is_ignored(subp):
+            if ignored:
+                yield tree.abspath(subp), subp
+        else:
+            if unknown:
+                yield tree.abspath(subp), subp
+

v- Another blank space between functions.

+def clean_tree(directory, ignored=False, detritus=False, dry_run=False):
+    tree = WorkingTree.open_containing(directory)[0]
+    deletables = iter_deletables(tree, ignored=ignored, detritus=detritus)
+    delete_items(deletables, dry_run=dry_run)
+
+def delete_items(deletables, dry_run=False):
+    """Delete files in the deletables iterable"""
+    has_deleted = False
+    for path, subp in deletables:
+        if not has_deleted:
+            note("deleting paths:")
+            has_deleted = True
+        note('  ' + subp)
+        if not dry_run:
+            if isdir(path):
+                shutil.rmtree(path)
+            else:
+                os.unlink(path)
+    if not has_deleted:
+        note("No files deleted.")


^- We have a 'delete_any' function in bzrlib.osutils. Though it doesn't
use rmtree, preferring to just delete a single directory. But I guess
since unknowns() doesn't go into unknown directories, this is really how
you have to do it. I just flinch when I see "rmtree". But it seems
correct here.


=== added file bzrlib/tests/blackbox/test_clean_tree.py //
file-id:test_clean_t
... ree.py-20060601212211-50rds19mwol16lx4-1 //
last-changed:aaron.bentley at utor
... onto.ca-20060601212453-f46ae4b44434594f

^- It would seem that for my mail reader we could wrap a little bit
earlier. I guess you wrap at 79, and the default for Thunderbird is to
wrap at 72 in text mode. I might just bump up thunderbird to 79/80. But
since it is common to wrap at 72 chars for mail readers, it might be
nice to make bundles that don't wrap as much.


...

+
+import os
+
+from bzrlib.tests.blackbox import ExternalBase
+
+

v- I realize this test probably predates it, but is there a reason you
are using 'touch' instead of 'build_tree'? Also we have
'self.failUnlessExists'. It would be nice if this was cleaned up.


+class TestCleanTree(ExternalBase):
+    @staticmethod
+    def touch(filename):
+        file(filename, 'wb').write('')
+
+    def test_clean_tree(self):
+        self.runbzr('init')
+        self.touch('name')
+        self.touch('name~')
+        assert os.path.lexists('name~')
+        self.touch('name.pyc')
+        self.runbzr('clean-tree')
+        assert os.path.lexists('name~')
+        assert not os.path.lexists('name')
+        self.runbzr('clean-tree --detritus')
+        assert not os.path.lexists('name~')
+        assert os.path.lexists('name.pyc')
+        self.runbzr('clean-tree --ignored')
+        assert not os.path.lexists('name.pyc')


v- More 'assert os.path.exists()' stuff, rather than
'self.failUnlessExists()'.

+class TestCleanTree(TestCaseInTempDir):
+    def test_symlinks(self):
+        if has_symlinks() is False:
+            return
+        os.mkdir('branch')
+        BzrDir.create_standalone_workingtree('branch')
+        os.symlink(os.path.realpath('no-die-please'), 'branch/die-please')
+        os.mkdir('no-die-please')
+        assert os.path.exists('branch/die-please')
+        os.mkdir('no-die-please/child')
+
+        clean_tree('branch')
+        assert os.path.exists('no-die-please')
+        assert os.path.exists('no-die-please/child')
+
+    def test_iter_deletable(self):
+        """Files are selected for deletion appropriately"""
+        os.mkdir('branch')
+        tree = BzrDir.create_standalone_workingtree('branch')
+        file('branch/file.BASE', 'wb').write('contents')
+        self.assertEqual(len(list(iter_deletables(tree))), 1)
+        file('branch/file~', 'wb').write('contents')
+        file('branch/file.pyc', 'wb').write('contents')
+        dels = [r for a,r in iter_deletables(tree)]
+        assert 'file~' not in dels
+        assert 'file.pyc' not in dels
+        dels = [r for a,r in iter_deletables(tree, detritus=True)]
+        assert 'file~' in dels
+        assert 'file.pyc' not in dels
+        dels = [r for a,r in iter_deletables(tree, ignored=True)]
+        assert 'file~' in dels
+        assert 'file.BASE' in dels
+        assert 'file.pyc' in dels
+        dels = [r for a,r in iter_deletables(tree, unknown=False)]
+        assert 'file.BASE' not in dels


I didn't review your history.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEgUZOJdeBCYSNAAMRAqf6AKCBmSwZDPLRNevwNVkorklo0D8WagCgng4O
Z2lppqGsyBZAg6aBd+k1Ujk=
=lsWx
-----END PGP SIGNATURE-----




More information about the bazaar mailing list