Rev 3143: Add find_branch, find_trees, find_bzrdirs methods (abentley) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Sat Dec 22 00:03:26 GMT 2007


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

------------------------------------------------------------
revno: 3143
revision-id:pqm at pqm.ubuntu.com-20071222000314-vq5b7m2jkaxvofm9
parent: pqm at pqm.ubuntu.com-20071221185957-5w2bqxno9wfqadyx
parent: abentley at panoramicfeedback.com-20071221230131-zsheywe5tanfcm60
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Sat 2007-12-22 00:03:14 +0000
message:
  Add find_branch, find_trees, find_bzrdirs methods (abentley)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
  bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
  bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
  bzrlib/tests/test_workingtree.py testworkingtree.py-20051004024258-b88d0fe8f101d468
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 3140.1.7
    revision-id:abentley at panoramicfeedback.com-20071221230131-zsheywe5tanfcm60
    parent: abentley at panoramicfeedback.com-20071221223412-bkq5b1e9urirg4dh
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 18:01:31 -0500
    message:
      Update docs
    modified:
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
    ------------------------------------------------------------
    revno: 3140.1.6
    revision-id:abentley at panoramicfeedback.com-20071221223412-bkq5b1e9urirg4dh
    parent: abentley at panoramicfeedback.com-20071221204857-r9pxxwx34iuyt46d
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 17:34:12 -0500
    message:
      Add test that nested branches are returned
    modified:
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
    ------------------------------------------------------------
    revno: 3140.1.5
    revision-id:abentley at panoramicfeedback.com-20071221204857-r9pxxwx34iuyt46d
    parent: abentley at panoramicfeedback.com-20071221204727-t3mw37sray6nx1b8
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 15:48:57 -0500
    message:
      Update NEWS
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3140.1.4
    revision-id:abentley at panoramicfeedback.com-20071221204727-t3mw37sray6nx1b8
    parent: abentley at panoramicfeedback.com-20071221203222-owkqyiye6o5usdwr
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 15:47:27 -0500
    message:
      Add WorkingTree.find_trees
    modified:
      bzrlib/tests/test_workingtree.py testworkingtree.py-20051004024258-b88d0fe8f101d468
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 3140.1.3
    revision-id:abentley at panoramicfeedback.com-20071221203222-owkqyiye6o5usdwr
    parent: abentley at panoramicfeedback.com-20071221195630-u9lqadyl8letkois
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 15:32:22 -0500
    message:
      Add support for finding branches to BzrDir
    modified:
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
    ------------------------------------------------------------
    revno: 3140.1.2
    revision-id:abentley at panoramicfeedback.com-20071221195630-u9lqadyl8letkois
    parent: abentley at panoramicfeedback.com-20071221182048-epdl0q3at7ktf74v
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 14:56:30 -0500
    message:
      Add ability to find branches inside repositories
    modified:
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
    ------------------------------------------------------------
    revno: 3140.1.1
    revision-id:abentley at panoramicfeedback.com-20071221182048-epdl0q3at7ktf74v
    parent: pqm at pqm.ubuntu.com-20071221161317-zdipotctmw8p1yhx
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: find-branches
    timestamp: Fri 2007-12-21 13:20:48 -0500
    message:
      Implement find_bzrdir functionality
    modified:
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
=== modified file 'NEWS'
--- a/NEWS	2007-12-21 17:09:16 +0000
+++ b/NEWS	2007-12-22 00:03:14 +0000
@@ -102,6 +102,9 @@
 
   INTERNALS:
 
+    * find_* methods available for BzrDirs, Branches and WorkingTrees.
+      (Aaron Bentley)
+
     * Help topics can now be loaded from files. 
       (Ian Clatworthy, Alexander Belchenko)
 

=== modified file 'bzrlib/bzrdir.py'
--- a/bzrlib/bzrdir.py	2007-12-21 15:51:02 +0000
+++ b/bzrlib/bzrdir.py	2007-12-22 00:03:14 +0000
@@ -245,6 +245,80 @@
             format = BzrDirFormat.get_default_format()
         return format.initialize_on_transport(t)
 
+    @staticmethod
+    def find_bzrdirs(transport, evaluate=None, list_current=None):
+        """Find bzrdirs recursively from current location.
+
+        This is intended primarily as a building block for more sophisticated
+        functionality, like finding trees under a directory, or finding
+        branches that use a given repository.
+        :param evaluate: An optional callable that yields recurse, value,
+            where recurse controls whether this bzrdir is recursed into
+            and value is the value to yield.  By default, all bzrdirs
+            are recursed into, and the return value is the bzrdir.
+        :param list_current: if supplied, use this function to list the current
+            directory, instead of Transport.list_dir
+        :return: a generator of found bzrdirs, or whatever evaluate returns.
+        """
+        if list_current is None:
+            def list_current(transport):
+                return transport.list_dir('')
+        if evaluate is None:
+            def evaluate(bzrdir):
+                return True, bzrdir
+
+        pending = [transport]
+        while len(pending) > 0:
+            current_transport = pending.pop()
+            recurse = True
+            try:
+                bzrdir = BzrDir.open_from_transport(current_transport)
+            except errors.NotBranchError:
+                pass
+            else:
+                recurse, value = evaluate(bzrdir)
+                yield value
+            try:
+                subdirs = list_current(current_transport)
+            except errors.NoSuchFile:
+                continue
+            if recurse:
+                for subdir in sorted(subdirs, reverse=True):
+                    pending.append(current_transport.clone(subdir))
+
+    @staticmethod
+    def find_branches(transport):
+        """Find all branches under a transport.
+
+        This will find all branches below the transport, including branches
+        inside other branches.  Where possible, it will use
+        Repository.find_branches.
+
+        To list all the branches that use a particular Repository, see
+        Repository.find_branches
+        """
+        def evaluate(bzrdir):
+            try:
+                repository = bzrdir.open_repository()
+            except errors.NoRepositoryPresent:
+                pass
+            else:
+                return False, (None, repository)
+            try:
+                branch = bzrdir.open_branch()
+            except errors.NotBranchError:
+                return True, (None, None)
+            else:
+                return True, (branch, None)
+        branches = []
+        for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
+            if repo is not None:
+                branches.extend(repo.find_branches())
+            if branch is not None:
+                branches.append(branch)
+        return branches
+
+
     def destroy_repository(self):
         """Destroy the repository in this BzrDir"""
         raise NotImplementedError(self.destroy_repository)

=== modified file 'bzrlib/remote.py'
--- a/bzrlib/remote.py	2007-12-19 08:12:34 +0000
+++ b/bzrlib/remote.py	2007-12-21 19:56:30 +0000
@@ -415,6 +415,12 @@
 
         return result
 
+    def find_branches(self, using=False):
+        """See Repository.find_branches()."""
+        # should be an API call to the server.
+        self._ensure_real()
+        return self._real_repository.find_branches(using=using)
+
     def get_physical_lock_status(self):
         """See Repository.get_physical_lock_status()."""
         # should be an API call to the server.

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2007-12-19 08:12:34 +0000
+++ b/bzrlib/repository.py	2007-12-21 23:01:31 +0000
@@ -766,6 +766,45 @@
             result['size'] = t
         return result
 
+    def find_branches(self, using=False):
+        """Find branches underneath this repository.
+
+        This will include branches inside other branches.
+
+        :param using: If True, list only branches using this repository.
+        """
+
+        class Evaluator(object):
+
+            def __init__(self):
+                self.first_call = True
+
+            def __call__(self, bzrdir):
+                # On the first call, the parameter is always the bzrdir
+                # containing the current repo.
+                if not self.first_call:
+                    try:
+                        repository = bzrdir.open_repository()
+                    except errors.NoRepositoryPresent:
+                        pass
+                    else:
+                        return False, (None, repository)
+                self.first_call = False
+                try:
+                    value = (bzrdir.open_branch(), None)
+                except errors.NotBranchError:
+                    value = (None, None)
+                return True, value
+
+        branches = []
+        for branch, repository in bzrdir.BzrDir.find_bzrdirs(
+                self.bzrdir.root_transport, evaluate=Evaluator()):
+            if branch is not None:
+                branches.append(branch)
+            if not using and repository is not None:
+                branches.extend(repository.find_branches())
+        return branches
+
     def get_data_stream(self, revision_ids):
         raise NotImplementedError(self.get_data_stream)
 

=== modified file 'bzrlib/tests/repository_implementations/test_repository.py'
--- a/bzrlib/tests/repository_implementations/test_repository.py	2007-12-19 08:12:34 +0000
+++ b/bzrlib/tests/repository_implementations/test_repository.py	2007-12-21 22:34:12 +0000
@@ -636,6 +636,46 @@
         repo = self.make_repository('repo')
         repo._make_parents_provider().get_parent_map
 
+    def make_repository_and_foo_bar(self, shared):
+        made_control = self.make_bzrdir('repository')
+        repo = made_control.create_repository(shared=shared)
+        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/foo'),
+                                                force_new_repo=False)
+        bzrdir.BzrDir.create_branch_convenience(self.get_url('repository/bar'),
+                                                force_new_repo=True)
+        baz = self.make_bzrdir('repository/baz')
+        qux = self.make_branch('repository/baz/qux')
+        quxx = self.make_branch('repository/baz/qux/quxx')
+        return repo
+
+    def test_find_branches(self):
+        repo = self.make_repository_and_foo_bar(shared=False)
+        branches = repo.find_branches()
+        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
+        self.assertContainsRe(branches[-3].base, 'repository/baz/qux/$')
+        self.assertContainsRe(branches[-2].base, 'repository/baz/qux/quxx/$')
+        # in some formats, creating a repo creates a branch
+        if len(branches) == 6:
+            self.assertContainsRe(branches[-4].base, 'repository/baz/$')
+            self.assertContainsRe(branches[-5].base, 'repository/bar/$')
+            self.assertContainsRe(branches[-6].base, 'repository/$')
+        else:
+            self.assertEqual(4, len(branches))
+            self.assertContainsRe(branches[-4].base, 'repository/bar/$')
+
+    def test_find_branches_using(self):
+        try:
+            repo = self.make_repository_and_foo_bar(shared=True)
+        except errors.IncompatibleFormat:
+            raise TestNotApplicable
+        branches = repo.find_branches(using=True)
+        self.assertContainsRe(branches[-1].base, 'repository/foo/$')
+        # in some formats, creating a repo creates a branch
+        if len(branches) == 2:
+            self.assertContainsRe(branches[-2].base, 'repository/$')
+        else:
+            self.assertEqual(1, len(branches))
+
 
 class TestRepositoryLocking(TestCaseWithRepository):
 

=== modified file 'bzrlib/tests/test_bzrdir.py'
--- a/bzrlib/tests/test_bzrdir.py	2007-12-20 14:07:01 +0000
+++ b/bzrlib/tests/test_bzrdir.py	2007-12-21 20:32:22 +0000
@@ -591,6 +591,66 @@
         self.failUnlessExists('repo/tree2/subtree')
         self.failIfExists('repo/tree2/subtree/file')
 
+    def make_foo_bar_baz(self):
+        foo = bzrdir.BzrDir.create_branch_convenience('foo').bzrdir
+        bar = self.make_branch('foo/bar').bzrdir
+        baz = self.make_branch('baz').bzrdir
+        return foo, bar, baz
+
+    def test_find_bzrdirs(self):
+        foo, bar, baz = self.make_foo_bar_baz()
+        transport = get_transport(self.get_url())
+        self.assertEqualBzrdirs([baz, foo, bar],
+                                bzrdir.BzrDir.find_bzrdirs(transport))
+
+    def test_find_bzrdirs_list_current(self):
+        def list_current(transport):
+            return [s for s in transport.list_dir('') if s != 'baz']
+
+        foo, bar, baz = self.make_foo_bar_baz()
+        transport = get_transport(self.get_url())
+        self.assertEqualBzrdirs([foo, bar],
+                                bzrdir.BzrDir.find_bzrdirs(transport,
+                                    list_current=list_current))
+
+
+    def test_find_bzrdirs_evaluate(self):
+        def evaluate(bzrdir):
+            try:
+                repo = bzrdir.open_repository()
+            except NoRepositoryPresent:
+                return True, bzrdir.root_transport.base
+            else:
+                return False, bzrdir.root_transport.base
+
+        foo, bar, baz = self.make_foo_bar_baz()
+        transport = get_transport(self.get_url())
+        self.assertEqual([baz.root_transport.base, foo.root_transport.base],
+                         list(bzrdir.BzrDir.find_bzrdirs(transport,
+                                                         evaluate=evaluate)))
+
+    def assertEqualBzrdirs(self, first, second):
+        first = list(first)
+        second = list(second)
+        self.assertEqual(len(first), len(second))
+        for x, y in zip(first, second):
+            self.assertEqual(x.root_transport.base, y.root_transport.base)
+
+    def test_find_branches(self):
+        root = self.make_repository('', shared=True)
+        foo, bar, baz = self.make_foo_bar_baz()
+        qux = self.make_bzrdir('foo/qux')
+        transport = get_transport(self.get_url())
+        branches = bzrdir.BzrDir.find_branches(transport)
+        self.assertEqual(baz.root_transport.base, branches[0].base)
+        self.assertEqual(foo.root_transport.base, branches[1].base)
+        self.assertEqual(bar.root_transport.base, branches[2].base)
+
+        # ensure this works without a top-level repo
+        branches = bzrdir.BzrDir.find_branches(transport.clone('foo'))
+        self.assertEqual(foo.root_transport.base, branches[0].base)
+        self.assertEqual(bar.root_transport.base, branches[1].base)
+
 
 class TestMeta1DirFormat(TestCaseWithTransport):
     """Tests specific to the meta1 dir format."""

=== modified file 'bzrlib/tests/test_workingtree.py'
--- a/bzrlib/tests/test_workingtree.py	2007-12-18 23:12:06 +0000
+++ b/bzrlib/tests/test_workingtree.py	2007-12-21 20:47:27 +0000
@@ -376,3 +376,15 @@
         file_conflict = conflicts.TextConflict('file', None, 'hello-id')
         tree.set_conflicts(conflicts.ConflictList([file_conflict]))
         tree.auto_resolve()
+
+
+class TestFindTrees(TestCaseWithTransport):
+
+    def test_find_trees(self):
+        self.make_branch_and_tree('foo')
+        self.make_branch_and_tree('foo/bar')
+        # Sticking a tree inside a control dir is heinous, so let's skip it
+        self.make_branch_and_tree('foo/.bzr/baz')
+        self.make_branch('qux')
+        trees = workingtree.WorkingTree.find_trees('.')
+        self.assertEqual(2, len(list(trees)))

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2007-12-20 15:21:48 +0000
+++ b/bzrlib/workingtree.py	2007-12-21 20:47:27 +0000
@@ -359,6 +359,22 @@
         """
         return WorkingTree.open(path, _unsupported=True)
 
+    @staticmethod
+    def find_trees(location):
+        def list_current(transport):
+            return [d for d in transport.list_dir('') if d != '.bzr']
+        def evaluate(bzrdir):
+            try:
+                tree = bzrdir.open_workingtree()
+            except errors.NoWorkingTree:
+                return True, None
+            else:
+                return True, tree
+        transport = get_transport(location)
+        iterator = bzrdir.BzrDir.find_bzrdirs(transport, evaluate=evaluate,
+                                              list_current=list_current)
+        return [t for t in iterator if t is not None]
+
     # should be deprecated - this is slow and in any case treating them as a
     # container is (we now know) bad style -- mbp 20070302
     ## @deprecated_method(zero_fifteen)




More information about the bazaar-commits mailing list