~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
245
245
            format = BzrDirFormat.get_default_format()
246
246
        return format.initialize_on_transport(t)
247
247
 
 
248
    @staticmethod
 
249
    def find_bzrdirs(transport, evaluate=None, list_current=None):
 
250
        """Find bzrdirs recursively from current location.
 
251
 
 
252
        This is intended primarily as a building block for more sophisticated
 
253
        functionality, like finding trees under a directory, or finding
 
254
        branches that use a given repository.
 
255
        :param evaluate: An optional callable that yields recurse, value,
 
256
            where recurse controls whether this bzrdir is recursed into
 
257
            and value is the value to yield.  By default, all bzrdirs
 
258
            are recursed into, and the return value is the bzrdir.
 
259
        :param list_current: if supplied, use this function to list the current
 
260
            directory, instead of Transport.list_dir
 
261
        :return: a generator of found bzrdirs, or whatever evaluate returns.
 
262
        """
 
263
        if list_current is None:
 
264
            def list_current(transport):
 
265
                return transport.list_dir('')
 
266
        if evaluate is None:
 
267
            def evaluate(bzrdir):
 
268
                return True, bzrdir
 
269
 
 
270
        pending = [transport]
 
271
        while len(pending) > 0:
 
272
            current_transport = pending.pop()
 
273
            recurse = True
 
274
            try:
 
275
                bzrdir = BzrDir.open_from_transport(current_transport)
 
276
            except errors.NotBranchError:
 
277
                pass
 
278
            else:
 
279
                recurse, value = evaluate(bzrdir)
 
280
                yield value
 
281
            try:
 
282
                subdirs = list_current(current_transport)
 
283
            except errors.NoSuchFile:
 
284
                continue
 
285
            if recurse:
 
286
                for subdir in sorted(subdirs, reverse=True):
 
287
                    pending.append(current_transport.clone(subdir))
 
288
 
 
289
    @staticmethod
 
290
    def find_branches(transport):
 
291
        """Find all branches under a transport.
 
292
 
 
293
        This will find all branches below the transport, including branches
 
294
        inside other branches.  Where possible, it will use
 
295
        Repository.find_branches.
 
296
 
 
297
        To list all the branches that use a particular Repository, see
 
298
        Repository.find_branches
 
299
        """
 
300
        def evaluate(bzrdir):
 
301
            try:
 
302
                repository = bzrdir.open_repository()
 
303
            except errors.NoRepositoryPresent:
 
304
                pass
 
305
            else:
 
306
                return False, (None, repository)
 
307
            try:
 
308
                branch = bzrdir.open_branch()
 
309
            except errors.NotBranchError:
 
310
                return True, (None, None)
 
311
            else:
 
312
                return True, (branch, None)
 
313
        branches = []
 
314
        for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
 
315
            if repo is not None:
 
316
                branches.extend(repo.find_branches())
 
317
            if branch is not None:
 
318
                branches.append(branch)
 
319
        return branches
 
320
 
 
321
 
248
322
    def destroy_repository(self):
249
323
        """Destroy the repository in this BzrDir"""
250
324
        raise NotImplementedError(self.destroy_repository)
381
455
                                               format=format).bzrdir
382
456
        return bzrdir.create_workingtree()
383
457
 
384
 
    def create_workingtree(self, revision_id=None, from_branch=None):
 
458
    def create_workingtree(self, revision_id=None, from_branch=None,
 
459
        accelerator_tree=None):
385
460
        """Create a working tree at this BzrDir.
386
461
        
387
462
        :param revision_id: create it as of this revision id.
388
463
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
464
        :param accelerator_tree: A tree which can be used for retrieving file
 
465
            contents more quickly than the revision tree, i.e. a workingtree.
 
466
            The revision tree will be used for cases where accelerator_tree's
 
467
            content is different.
389
468
        """
390
469
        raise NotImplementedError(self.create_workingtree)
391
470
 
666
745
                raise errors.NotBranchError(path=url)
667
746
            a_transport = new_t
668
747
 
 
748
    def _get_tree_branch(self):
 
749
        """Return the branch and tree, if any, for this bzrdir.
 
750
 
 
751
        Return None for tree if not present.
 
752
        Raise NotBranchError if no branch is present.
 
753
        :return: (tree, branch)
 
754
        """
 
755
        try:
 
756
            tree = self.open_workingtree()
 
757
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
758
            tree = None
 
759
            branch = self.open_branch()
 
760
        else:
 
761
            branch = tree.branch
 
762
        return tree, branch
 
763
 
 
764
    @classmethod
 
765
    def open_tree_or_branch(klass, location):
 
766
        """Return the branch and working tree at a location.
 
767
 
 
768
        If there is no tree at the location, tree will be None.
 
769
        If there is no branch at the location, an exception will be
 
770
        raised
 
771
        :return: (tree, branch)
 
772
        """
 
773
        bzrdir = klass.open(location)
 
774
        return bzrdir._get_tree_branch()
 
775
 
669
776
    @classmethod
670
777
    def open_containing_tree_or_branch(klass, location):
671
778
        """Return the branch and working tree contained by a location.
677
784
        relpath is the portion of the path that is contained by the branch.
678
785
        """
679
786
        bzrdir, relpath = klass.open_containing(location)
680
 
        try:
681
 
            tree = bzrdir.open_workingtree()
682
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
683
 
            tree = None
684
 
            branch = bzrdir.open_branch()
685
 
        else:
686
 
            branch = tree.branch
 
787
        tree, branch = bzrdir._get_tree_branch()
687
788
        return tree, branch, relpath
688
789
 
689
790
    def open_repository(self, _unsupported=False):
788
889
        return self.cloning_metadir()
789
890
 
790
891
    def sprout(self, url, revision_id=None, force_new_repo=False,
791
 
               recurse='down', possible_transports=None):
 
892
               recurse='down', possible_transports=None,
 
893
               accelerator_tree=None):
792
894
        """Create a copy of this bzrdir prepared for use as a new line of
793
895
        development.
794
896
 
801
903
 
802
904
        if revision_id is not None, then the clone operation may tune
803
905
            itself to download less data.
 
906
        :param accelerator_tree: A tree which can be used for retrieving file
 
907
            contents more quickly than the revision tree, i.e. a workingtree.
 
908
            The revision tree will be used for cases where accelerator_tree's
 
909
            content is different.
804
910
        """
805
911
        target_transport = get_transport(url, possible_transports)
806
912
        target_transport.ensure_base()
845
951
            result.create_branch()
846
952
        if isinstance(target_transport, LocalTransport) and (
847
953
            result_repo is None or result_repo.make_working_trees()):
848
 
            wt = result.create_workingtree()
 
954
            wt = result.create_workingtree(accelerator_tree=accelerator_tree)
849
955
            wt.lock_write()
850
956
            try:
851
957
                if wt.path2id('') is None:
939
1045
        """See BzrDir.destroy_repository."""
940
1046
        raise errors.UnsupportedOperation(self.destroy_repository, self)
941
1047
 
942
 
    def create_workingtree(self, revision_id=None, from_branch=None):
 
1048
    def create_workingtree(self, revision_id=None, from_branch=None,
 
1049
                           accelerator_tree=None):
943
1050
        """See BzrDir.create_workingtree."""
944
1051
        # this looks buggy but is not -really-
945
1052
        # because this format creates the workingtree when the bzrdir is
1013
1120
        return format.open(self, _found=True)
1014
1121
 
1015
1122
    def sprout(self, url, revision_id=None, force_new_repo=False,
1016
 
               possible_transports=None):
 
1123
               possible_transports=None, accelerator_tree=None):
1017
1124
        """See BzrDir.sprout()."""
1018
1125
        from bzrlib.workingtree import WorkingTreeFormat2
1019
1126
        self._make_tail(url)
1027
1134
        except errors.NotBranchError:
1028
1135
            pass
1029
1136
        # we always want a working tree
1030
 
        WorkingTreeFormat2().initialize(result)
 
1137
        WorkingTreeFormat2().initialize(result,
 
1138
                                        accelerator_tree=accelerator_tree)
1031
1139
        return result
1032
1140
 
1033
1141
 
1121
1229
        """See BzrDir.destroy_repository."""
1122
1230
        self.transport.delete_tree('repository')
1123
1231
 
1124
 
    def create_workingtree(self, revision_id=None, from_branch=None):
 
1232
    def create_workingtree(self, revision_id=None, from_branch=None,
 
1233
                           accelerator_tree=None):
1125
1234
        """See BzrDir.create_workingtree."""
1126
1235
        return self._format.workingtree_format.initialize(
1127
 
            self, revision_id, from_branch=from_branch)
 
1236
            self, revision_id, from_branch=from_branch,
 
1237
            accelerator_tree=accelerator_tree)
1128
1238
 
1129
1239
    def destroy_workingtree(self):
1130
1240
        """See BzrDir.destroy_workingtree."""
2555
2665
format_registry.register_metadir('rich-root-pack',
2556
2666
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
2557
2667
    help='New in 1.0: Pack-based format with data compatible with '
2558
 
        'rich-root format repositories. Interoperates with '
2559
 
        'bzr repositories before 0.92 but cannot be read by bzr < 1.0. '
2560
 
        'NOTE: This format is experimental. Before using it, please read '
2561
 
        'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
 
2668
        'rich-root format repositories. Incompatible with'
 
2669
        ' bzr < 1.0',
2562
2670
    branch_format='bzrlib.branch.BzrBranchFormat6',
2563
2671
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2564
2672
    hidden=False,