~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Danny van Heumen
  • Date: 2010-03-09 21:42:11 UTC
  • mto: (4634.139.5 2.0)
  • mto: This revision was merged to the branch mainline in revision 5160.
  • Revision ID: danny@dannyvanheumen.nl-20100309214211-iqh42x6qcikgd9p3
Reverted now-useless TODO list.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
29
29
 
30
30
import os
31
31
import sys
32
 
import warnings
33
32
 
34
33
from bzrlib.lazy_import import lazy_import
35
34
lazy_import(globals(), """
36
35
from stat import S_ISDIR
 
36
import textwrap
37
37
 
38
38
import bzrlib
39
39
from bzrlib import (
40
40
    branch,
41
41
    config,
42
 
    controldir,
43
42
    errors,
44
43
    graph,
45
44
    lockable_files,
88
87
    )
89
88
 
90
89
 
91
 
class BzrDir(controldir.ControlDir):
 
90
class BzrDir(object):
92
91
    """A .bzr control diretory.
93
92
 
94
93
    BzrDir instances let you create or open any of the things that can be
125
124
                    return
126
125
        thing_to_unlock.break_lock()
127
126
 
 
127
    def can_convert_format(self):
 
128
        """Return true if this bzrdir is one whose format we can convert from."""
 
129
        return True
 
130
 
128
131
    def check_conversion_target(self, target_format):
129
132
        """Check that a bzrdir as a whole can be converted to a new format."""
130
133
        # The only current restriction is that the repository content can be 
204
207
        """
205
208
        # Overview: put together a broad description of what we want to end up
206
209
        # with; then make as few api calls as possible to do it.
207
 
 
 
210
        
208
211
        # We may want to create a repo/branch/tree, if we do so what format
209
212
        # would we want for each:
210
213
        require_stacking = (stacked_on is not None)
211
214
        format = self.cloning_metadir(require_stacking)
212
 
 
 
215
        
213
216
        # Figure out what objects we want:
214
217
        try:
215
218
            local_repo = self.find_repository()
257
260
                # copied, and finally if we are copying up to a specific
258
261
                # revision_id then we can use the pending-ancestry-result which
259
262
                # does not require traversing all of history to describe it.
260
 
                if (result_repo.user_url == result.user_url
261
 
                    and not require_stacking and
 
263
                if (result_repo.bzrdir.root_transport.base ==
 
264
                    result.root_transport.base and not require_stacking and
262
265
                    revision_id is not None):
263
266
                    fetch_spec = graph.PendingAncestryResult(
264
267
                        [revision_id], local_repo)
292
295
        t = get_transport(url)
293
296
        t.ensure_base()
294
297
 
 
298
    @classmethod
 
299
    def create(cls, base, format=None, possible_transports=None):
 
300
        """Create a new BzrDir at the url 'base'.
 
301
 
 
302
        :param format: If supplied, the format of branch to create.  If not
 
303
            supplied, the default is used.
 
304
        :param possible_transports: If supplied, a list of transports that
 
305
            can be reused to share a remote connection.
 
306
        """
 
307
        if cls is not BzrDir:
 
308
            raise AssertionError("BzrDir.create always creates the default"
 
309
                " format, not one of %r" % cls)
 
310
        t = get_transport(base, possible_transports)
 
311
        t.ensure_base()
 
312
        if format is None:
 
313
            format = BzrDirFormat.get_default_format()
 
314
        return format.initialize_on_transport(t)
 
315
 
295
316
    @staticmethod
296
317
    def find_bzrdirs(transport, evaluate=None, list_current=None):
297
318
        """Find bzrdirs recursively from current location.
320
341
            recurse = True
321
342
            try:
322
343
                bzrdir = BzrDir.open_from_transport(current_transport)
323
 
            except (errors.NotBranchError, errors.PermissionDenied):
 
344
            except errors.NotBranchError:
324
345
                pass
325
346
            else:
326
347
                recurse, value = evaluate(bzrdir)
327
348
                yield value
328
349
            try:
329
350
                subdirs = list_current(current_transport)
330
 
            except (errors.NoSuchFile, errors.PermissionDenied):
 
351
            except errors.NoSuchFile:
331
352
                continue
332
353
            if recurse:
333
354
                for subdir in sorted(subdirs, reverse=True):
350
371
            except errors.NoRepositoryPresent:
351
372
                pass
352
373
            else:
353
 
                return False, ([], repository)
354
 
            return True, (bzrdir.list_branches(), None)
355
 
        ret = []
356
 
        for branches, repo in BzrDir.find_bzrdirs(transport,
357
 
                                                  evaluate=evaluate):
 
374
                return False, (None, repository)
 
375
            try:
 
376
                branch = bzrdir.open_branch()
 
377
            except errors.NotBranchError:
 
378
                return True, (None, None)
 
379
            else:
 
380
                return True, (branch, None)
 
381
        branches = []
 
382
        for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
358
383
            if repo is not None:
359
 
                ret.extend(repo.find_branches())
360
 
            if branches is not None:
361
 
                ret.extend(branches)
362
 
        return ret
 
384
                branches.extend(repo.find_branches())
 
385
            if branch is not None:
 
386
                branches.append(branch)
 
387
        return branches
 
388
 
 
389
    def destroy_repository(self):
 
390
        """Destroy the repository in this BzrDir"""
 
391
        raise NotImplementedError(self.destroy_repository)
 
392
 
 
393
    def create_branch(self):
 
394
        """Create a branch in this BzrDir.
 
395
 
 
396
        The bzrdir's format will control what branch format is created.
 
397
        For more control see BranchFormatXX.create(a_bzrdir).
 
398
        """
 
399
        raise NotImplementedError(self.create_branch)
 
400
 
 
401
    def destroy_branch(self):
 
402
        """Destroy the branch in this BzrDir"""
 
403
        raise NotImplementedError(self.destroy_branch)
363
404
 
364
405
    @staticmethod
365
406
    def create_branch_and_repo(base, force_new_repo=False, format=None):
404
445
            stop = False
405
446
            stack_on = config.get_default_stack_on()
406
447
            if stack_on is not None:
407
 
                stack_on_pwd = found_bzrdir.user_url
 
448
                stack_on_pwd = found_bzrdir.root_transport.base
408
449
                stop = True
409
450
            # does it have a repository ?
410
451
            try:
412
453
            except errors.NoRepositoryPresent:
413
454
                repository = None
414
455
            else:
415
 
                if (found_bzrdir.user_url != self.user_url 
416
 
                    and not repository.is_shared()):
 
456
                if ((found_bzrdir.root_transport.base !=
 
457
                     self.root_transport.base) and not repository.is_shared()):
417
458
                    # Don't look higher, can't use a higher shared repo.
418
459
                    repository = None
419
460
                    stop = True
515
556
                                               format=format).bzrdir
516
557
        return bzrdir.create_workingtree()
517
558
 
518
 
    def generate_backup_name(self, base):
519
 
        """Generate a non-existing backup file name based on base."""
520
 
        counter = 1
521
 
        name = "%s.~%d~" % (base, counter)
522
 
        while self.root_transport.has(name):
523
 
            counter += 1
524
 
            name = "%s.~%d~" % (base, counter)
525
 
        return name
 
559
    def create_workingtree(self, revision_id=None, from_branch=None,
 
560
        accelerator_tree=None, hardlink=False):
 
561
        """Create a working tree at this BzrDir.
 
562
 
 
563
        :param revision_id: create it as of this revision id.
 
564
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
565
        :param accelerator_tree: A tree which can be used for retrieving file
 
566
            contents more quickly than the revision tree, i.e. a workingtree.
 
567
            The revision tree will be used for cases where accelerator_tree's
 
568
            content is different.
 
569
        """
 
570
        raise NotImplementedError(self.create_workingtree)
526
571
 
527
572
    def backup_bzrdir(self):
528
573
        """Backup this bzr control directory.
529
574
 
530
575
        :return: Tuple with old path name and new path name
531
576
        """
532
 
 
533
 
        backup_dir=self.generate_backup_name('backup.bzr')
534
577
        pb = ui.ui_factory.nested_progress_bar()
535
578
        try:
536
579
            # FIXME: bug 300001 -- the backup fails if the backup directory
537
580
            # already exists, but it should instead either remove it or make
538
581
            # a new backup directory.
539
582
            #
 
583
            # FIXME: bug 262450 -- the backup directory should have the same
 
584
            # permissions as the .bzr directory (probably a bug in copy_tree)
540
585
            old_path = self.root_transport.abspath('.bzr')
541
 
            new_path = self.root_transport.abspath(backup_dir)
542
 
            ui.ui_factory.note('making backup of %s\n  to %s' % (old_path, new_path,))
543
 
            self.root_transport.copy_tree('.bzr', backup_dir)
 
586
            new_path = self.root_transport.abspath('backup.bzr')
 
587
            pb.note('making backup of %s' % (old_path,))
 
588
            pb.note('  to %s' % (new_path,))
 
589
            self.root_transport.copy_tree('.bzr', 'backup.bzr')
544
590
            return (old_path, new_path)
545
591
        finally:
546
592
            pb.finished()
570
616
                else:
571
617
                    pass
572
618
 
 
619
    def destroy_workingtree(self):
 
620
        """Destroy the working tree at this BzrDir.
 
621
 
 
622
        Formats that do not support this may raise UnsupportedOperation.
 
623
        """
 
624
        raise NotImplementedError(self.destroy_workingtree)
 
625
 
 
626
    def destroy_workingtree_metadata(self):
 
627
        """Destroy the control files for the working tree at this BzrDir.
 
628
 
 
629
        The contents of working tree files are not affected.
 
630
        Formats that do not support this may raise UnsupportedOperation.
 
631
        """
 
632
        raise NotImplementedError(self.destroy_workingtree_metadata)
 
633
 
573
634
    def _find_containing(self, evaluate):
574
635
        """Find something in a containing control directory.
575
636
 
589
650
            if stop:
590
651
                return result
591
652
            next_transport = found_bzrdir.root_transport.clone('..')
592
 
            if (found_bzrdir.user_url == next_transport.base):
 
653
            if (found_bzrdir.root_transport.base == next_transport.base):
593
654
                # top of the file system
594
655
                return None
595
656
            # find the next containing bzrdir
612
673
                repository = found_bzrdir.open_repository()
613
674
            except errors.NoRepositoryPresent:
614
675
                return None, False
615
 
            if found_bzrdir.user_url == self.user_url:
 
676
            if found_bzrdir.root_transport.base == self.root_transport.base:
616
677
                return repository, True
617
678
            elif repository.is_shared():
618
679
                return repository, True
624
685
            raise errors.NoRepositoryPresent(self)
625
686
        return found_repo
626
687
 
 
688
    def get_branch_reference(self):
 
689
        """Return the referenced URL for the branch in this bzrdir.
 
690
 
 
691
        :raises NotBranchError: If there is no Branch.
 
692
        :return: The URL the branch in this bzrdir references if it is a
 
693
            reference branch, or None for regular branches.
 
694
        """
 
695
        return None
 
696
 
 
697
    def get_branch_transport(self, branch_format):
 
698
        """Get the transport for use by branch format in this BzrDir.
 
699
 
 
700
        Note that bzr dirs that do not support format strings will raise
 
701
        IncompatibleFormat if the branch format they are given has
 
702
        a format string, and vice versa.
 
703
 
 
704
        If branch_format is None, the transport is returned with no
 
705
        checking. If it is not None, then the returned transport is
 
706
        guaranteed to point to an existing directory ready for use.
 
707
        """
 
708
        raise NotImplementedError(self.get_branch_transport)
 
709
 
627
710
    def _find_creation_modes(self):
628
711
        """Determine the appropriate modes for files and directories.
629
712
 
668
751
            self._find_creation_modes()
669
752
        return self._dir_mode
670
753
 
 
754
    def get_repository_transport(self, repository_format):
 
755
        """Get the transport for use by repository format in this BzrDir.
 
756
 
 
757
        Note that bzr dirs that do not support format strings will raise
 
758
        IncompatibleFormat if the repository format they are given has
 
759
        a format string, and vice versa.
 
760
 
 
761
        If repository_format is None, the transport is returned with no
 
762
        checking. If it is not None, then the returned transport is
 
763
        guaranteed to point to an existing directory ready for use.
 
764
        """
 
765
        raise NotImplementedError(self.get_repository_transport)
 
766
 
 
767
    def get_workingtree_transport(self, tree_format):
 
768
        """Get the transport for use by workingtree format in this BzrDir.
 
769
 
 
770
        Note that bzr dirs that do not support format strings will raise
 
771
        IncompatibleFormat if the workingtree format they are given has a
 
772
        format string, and vice versa.
 
773
 
 
774
        If workingtree_format is None, the transport is returned with no
 
775
        checking. If it is not None, then the returned transport is
 
776
        guaranteed to point to an existing directory ready for use.
 
777
        """
 
778
        raise NotImplementedError(self.get_workingtree_transport)
 
779
 
671
780
    def get_config(self):
672
781
        """Get configuration for this BzrDir."""
673
782
        return config.BzrDirConfig(self)
686
795
        :param _transport: the transport this dir is based at.
687
796
        """
688
797
        self._format = _format
689
 
        # these are also under the more standard names of 
690
 
        # control_transport and user_transport
691
798
        self.transport = _transport.clone('.bzr')
692
799
        self.root_transport = _transport
693
800
        self._mode_check_done = False
694
801
 
695
 
    @property 
696
 
    def user_transport(self):
697
 
        return self.root_transport
698
 
 
699
 
    @property
700
 
    def control_transport(self):
701
 
        return self.transport
702
 
 
703
802
    def is_control_filename(self, filename):
704
803
        """True if filename is the name of a path which is reserved for bzrdir's.
705
804
 
707
806
 
708
807
        This is true IF and ONLY IF the filename is part of the namespace reserved
709
808
        for bzr control dirs. Currently this is the '.bzr' directory in the root
710
 
        of the root_transport. 
 
809
        of the root_transport. it is expected that plugins will need to extend
 
810
        this in the future - for instance to make bzr talk with svn working
 
811
        trees.
711
812
        """
712
813
        # this might be better on the BzrDirFormat class because it refers to
713
814
        # all the possible bzrdir disk formats.
717
818
        # add new tests for it to the appropriate place.
718
819
        return filename == '.bzr' or filename.startswith('.bzr/')
719
820
 
 
821
    def needs_format_conversion(self, format=None):
 
822
        """Return true if this bzrdir needs convert_format run on it.
 
823
 
 
824
        For instance, if the repository format is out of date but the
 
825
        branch and working tree are not, this should return True.
 
826
 
 
827
        :param format: Optional parameter indicating a specific desired
 
828
                       format we plan to arrive at.
 
829
        """
 
830
        raise NotImplementedError(self.needs_format_conversion)
 
831
 
720
832
    @staticmethod
721
833
    def open_unsupported(base):
722
834
        """Open a branch which is not supported."""
745
857
        # the redirections.
746
858
        base = transport.base
747
859
        def find_format(transport):
748
 
            return transport, controldir.ControlDirFormat.find_format(
 
860
            return transport, BzrDirFormat.find_format(
749
861
                transport, _server_formats=_server_formats)
750
862
 
751
863
        def redirected(transport, e, redirection_notice):
766
878
        BzrDir._check_supported(format, _unsupported)
767
879
        return format.open(transport, _found=True)
768
880
 
 
881
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
 
882
        """Open the branch object at this BzrDir if one is present.
 
883
 
 
884
        If unsupported is True, then no longer supported branch formats can
 
885
        still be opened.
 
886
 
 
887
        TODO: static convenience version of this?
 
888
        """
 
889
        raise NotImplementedError(self.open_branch)
 
890
 
769
891
    @staticmethod
770
892
    def open_containing(url, possible_transports=None):
771
893
        """Open an existing branch which contains url.
809
931
                raise errors.NotBranchError(path=url)
810
932
            a_transport = new_t
811
933
 
 
934
    def _get_tree_branch(self):
 
935
        """Return the branch and tree, if any, for this bzrdir.
 
936
 
 
937
        Return None for tree if not present or inaccessible.
 
938
        Raise NotBranchError if no branch is present.
 
939
        :return: (tree, branch)
 
940
        """
 
941
        try:
 
942
            tree = self.open_workingtree()
 
943
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
944
            tree = None
 
945
            branch = self.open_branch()
 
946
        else:
 
947
            branch = tree.branch
 
948
        return tree, branch
 
949
 
812
950
    @classmethod
813
951
    def open_tree_or_branch(klass, location):
814
952
        """Return the branch and working tree at a location.
860
998
                raise errors.NotBranchError(location)
861
999
        return tree, branch, branch.repository, relpath
862
1000
 
 
1001
    def open_repository(self, _unsupported=False):
 
1002
        """Open the repository object at this BzrDir if one is present.
 
1003
 
 
1004
        This will not follow the Branch object pointer - it's strictly a direct
 
1005
        open facility. Most client code should use open_branch().repository to
 
1006
        get at a repository.
 
1007
 
 
1008
        :param _unsupported: a private parameter, not part of the api.
 
1009
        TODO: static convenience version of this?
 
1010
        """
 
1011
        raise NotImplementedError(self.open_repository)
 
1012
 
 
1013
    def open_workingtree(self, _unsupported=False,
 
1014
                         recommend_upgrade=True, from_branch=None):
 
1015
        """Open the workingtree object at this BzrDir if one is present.
 
1016
 
 
1017
        :param recommend_upgrade: Optional keyword parameter, when True (the
 
1018
            default), emit through the ui module a recommendation that the user
 
1019
            upgrade the working tree when the workingtree being opened is old
 
1020
            (but still fully supported).
 
1021
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
1022
        """
 
1023
        raise NotImplementedError(self.open_workingtree)
 
1024
 
 
1025
    def has_branch(self):
 
1026
        """Tell if this bzrdir contains a branch.
 
1027
 
 
1028
        Note: if you're going to open the branch, you should just go ahead
 
1029
        and try, and not ask permission first.  (This method just opens the
 
1030
        branch and discards it, and that's somewhat expensive.)
 
1031
        """
 
1032
        try:
 
1033
            self.open_branch()
 
1034
            return True
 
1035
        except errors.NotBranchError:
 
1036
            return False
 
1037
 
 
1038
    def has_workingtree(self):
 
1039
        """Tell if this bzrdir contains a working tree.
 
1040
 
 
1041
        This will still raise an exception if the bzrdir has a workingtree that
 
1042
        is remote & inaccessible.
 
1043
 
 
1044
        Note: if you're going to open the working tree, you should just go ahead
 
1045
        and try, and not ask permission first.  (This method just opens the
 
1046
        workingtree and discards it, and that's somewhat expensive.)
 
1047
        """
 
1048
        try:
 
1049
            self.open_workingtree(recommend_upgrade=False)
 
1050
            return True
 
1051
        except errors.NoWorkingTree:
 
1052
            return False
 
1053
 
863
1054
    def _cloning_metadir(self):
864
1055
        """Produce a metadir suitable for cloning with.
865
1056
 
923
1114
            format.require_stacking()
924
1115
        return format
925
1116
 
926
 
    @classmethod
927
 
    def create(cls, base, format=None, possible_transports=None):
928
 
        """Create a new BzrDir at the url 'base'.
929
 
 
930
 
        :param format: If supplied, the format of branch to create.  If not
931
 
            supplied, the default is used.
932
 
        :param possible_transports: If supplied, a list of transports that
933
 
            can be reused to share a remote connection.
 
1117
    def checkout_metadir(self):
 
1118
        return self.cloning_metadir()
 
1119
 
 
1120
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
1121
               recurse='down', possible_transports=None,
 
1122
               accelerator_tree=None, hardlink=False, stacked=False,
 
1123
               source_branch=None, create_tree_if_local=True):
 
1124
        """Create a copy of this bzrdir prepared for use as a new line of
 
1125
        development.
 
1126
 
 
1127
        If url's last component does not exist, it will be created.
 
1128
 
 
1129
        Attributes related to the identity of the source branch like
 
1130
        branch nickname will be cleaned, a working tree is created
 
1131
        whether one existed before or not; and a local branch is always
 
1132
        created.
 
1133
 
 
1134
        if revision_id is not None, then the clone operation may tune
 
1135
            itself to download less data.
 
1136
        :param accelerator_tree: A tree which can be used for retrieving file
 
1137
            contents more quickly than the revision tree, i.e. a workingtree.
 
1138
            The revision tree will be used for cases where accelerator_tree's
 
1139
            content is different.
 
1140
        :param hardlink: If true, hard-link files from accelerator_tree,
 
1141
            where possible.
 
1142
        :param stacked: If true, create a stacked branch referring to the
 
1143
            location of this control directory.
 
1144
        :param create_tree_if_local: If true, a working-tree will be created
 
1145
            when working locally.
934
1146
        """
935
 
        if cls is not BzrDir:
936
 
            raise AssertionError("BzrDir.create always creates the"
937
 
                "default format, not one of %r" % cls)
938
 
        t = get_transport(base, possible_transports)
939
 
        t.ensure_base()
940
 
        if format is None:
941
 
            format = controldir.ControlDirFormat.get_default_format()
942
 
        return format.initialize_on_transport(t)
943
 
 
 
1147
        target_transport = get_transport(url, possible_transports)
 
1148
        target_transport.ensure_base()
 
1149
        cloning_format = self.cloning_metadir(stacked)
 
1150
        # Create/update the result branch
 
1151
        result = cloning_format.initialize_on_transport(target_transport)
 
1152
        # if a stacked branch wasn't requested, we don't create one
 
1153
        # even if the origin was stacked
 
1154
        stacked_branch_url = None
 
1155
        if source_branch is not None:
 
1156
            if stacked:
 
1157
                stacked_branch_url = self.root_transport.base
 
1158
            source_repository = source_branch.repository
 
1159
        else:
 
1160
            try:
 
1161
                source_branch = self.open_branch()
 
1162
                source_repository = source_branch.repository
 
1163
                if stacked:
 
1164
                    stacked_branch_url = self.root_transport.base
 
1165
            except errors.NotBranchError:
 
1166
                source_branch = None
 
1167
                try:
 
1168
                    source_repository = self.open_repository()
 
1169
                except errors.NoRepositoryPresent:
 
1170
                    source_repository = None
 
1171
        repository_policy = result.determine_repository_policy(
 
1172
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
1173
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
1174
        if is_new_repo and revision_id is not None and not stacked:
 
1175
            fetch_spec = graph.PendingAncestryResult(
 
1176
                [revision_id], source_repository)
 
1177
        else:
 
1178
            fetch_spec = None
 
1179
        if source_repository is not None:
 
1180
            # Fetch while stacked to prevent unstacked fetch from
 
1181
            # Branch.sprout.
 
1182
            if fetch_spec is None:
 
1183
                result_repo.fetch(source_repository, revision_id=revision_id)
 
1184
            else:
 
1185
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
1186
 
 
1187
        if source_branch is None:
 
1188
            # this is for sprouting a bzrdir without a branch; is that
 
1189
            # actually useful?
 
1190
            # Not especially, but it's part of the contract.
 
1191
            result_branch = result.create_branch()
 
1192
        else:
 
1193
            result_branch = source_branch.sprout(result,
 
1194
                revision_id=revision_id, repository_policy=repository_policy)
 
1195
        mutter("created new branch %r" % (result_branch,))
 
1196
 
 
1197
        # Create/update the result working tree
 
1198
        if (create_tree_if_local and
 
1199
            isinstance(target_transport, local.LocalTransport) and
 
1200
            (result_repo is None or result_repo.make_working_trees())):
 
1201
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
1202
                hardlink=hardlink)
 
1203
            wt.lock_write()
 
1204
            try:
 
1205
                if wt.path2id('') is None:
 
1206
                    try:
 
1207
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
1208
                    except errors.NoWorkingTree:
 
1209
                        pass
 
1210
            finally:
 
1211
                wt.unlock()
 
1212
        else:
 
1213
            wt = None
 
1214
        if recurse == 'down':
 
1215
            if wt is not None:
 
1216
                basis = wt.basis_tree()
 
1217
                basis.lock_read()
 
1218
                subtrees = basis.iter_references()
 
1219
            elif result_branch is not None:
 
1220
                basis = result_branch.basis_tree()
 
1221
                basis.lock_read()
 
1222
                subtrees = basis.iter_references()
 
1223
            elif source_branch is not None:
 
1224
                basis = source_branch.basis_tree()
 
1225
                basis.lock_read()
 
1226
                subtrees = basis.iter_references()
 
1227
            else:
 
1228
                subtrees = []
 
1229
                basis = None
 
1230
            try:
 
1231
                for path, file_id in subtrees:
 
1232
                    target = urlutils.join(url, urlutils.escape(path))
 
1233
                    sublocation = source_branch.reference_parent(file_id, path)
 
1234
                    sublocation.bzrdir.sprout(target,
 
1235
                        basis.get_reference_revision(file_id, path),
 
1236
                        force_new_repo=force_new_repo, recurse=recurse,
 
1237
                        stacked=stacked)
 
1238
            finally:
 
1239
                if basis is not None:
 
1240
                    basis.unlock()
 
1241
        return result
 
1242
 
 
1243
    def push_branch(self, source, revision_id=None, overwrite=False, 
 
1244
        remember=False, create_prefix=False):
 
1245
        """Push the source branch into this BzrDir."""
 
1246
        br_to = None
 
1247
        # If we can open a branch, use its direct repository, otherwise see
 
1248
        # if there is a repository without a branch.
 
1249
        try:
 
1250
            br_to = self.open_branch()
 
1251
        except errors.NotBranchError:
 
1252
            # Didn't find a branch, can we find a repository?
 
1253
            repository_to = self.find_repository()
 
1254
        else:
 
1255
            # Found a branch, so we must have found a repository
 
1256
            repository_to = br_to.repository
 
1257
 
 
1258
        push_result = PushResult()
 
1259
        push_result.source_branch = source
 
1260
        if br_to is None:
 
1261
            # We have a repository but no branch, copy the revisions, and then
 
1262
            # create a branch.
 
1263
            repository_to.fetch(source.repository, revision_id=revision_id)
 
1264
            br_to = source.clone(self, revision_id=revision_id)
 
1265
            if source.get_push_location() is None or remember:
 
1266
                source.set_push_location(br_to.base)
 
1267
            push_result.stacked_on = None
 
1268
            push_result.branch_push_result = None
 
1269
            push_result.old_revno = None
 
1270
            push_result.old_revid = _mod_revision.NULL_REVISION
 
1271
            push_result.target_branch = br_to
 
1272
            push_result.master_branch = None
 
1273
            push_result.workingtree_updated = False
 
1274
        else:
 
1275
            # We have successfully opened the branch, remember if necessary:
 
1276
            if source.get_push_location() is None or remember:
 
1277
                source.set_push_location(br_to.base)
 
1278
            try:
 
1279
                tree_to = self.open_workingtree()
 
1280
            except errors.NotLocalUrl:
 
1281
                push_result.branch_push_result = source.push(br_to, 
 
1282
                    overwrite, stop_revision=revision_id)
 
1283
                push_result.workingtree_updated = False
 
1284
            except errors.NoWorkingTree:
 
1285
                push_result.branch_push_result = source.push(br_to,
 
1286
                    overwrite, stop_revision=revision_id)
 
1287
                push_result.workingtree_updated = None # Not applicable
 
1288
            else:
 
1289
                tree_to.lock_write()
 
1290
                try:
 
1291
                    push_result.branch_push_result = source.push(
 
1292
                        tree_to.branch, overwrite, stop_revision=revision_id)
 
1293
                    tree_to.update()
 
1294
                finally:
 
1295
                    tree_to.unlock()
 
1296
                push_result.workingtree_updated = True
 
1297
            push_result.old_revno = push_result.branch_push_result.old_revno
 
1298
            push_result.old_revid = push_result.branch_push_result.old_revid
 
1299
            push_result.target_branch = \
 
1300
                push_result.branch_push_result.target_branch
 
1301
        return push_result
944
1302
 
945
1303
 
946
1304
class BzrDirHooks(hooks.Hooks):
952
1310
        self.create_hook(hooks.HookPoint('pre_open',
953
1311
            "Invoked before attempting to open a BzrDir with the transport "
954
1312
            "that the open will use.", (1, 14), None))
955
 
        self.create_hook(hooks.HookPoint('post_repo_init',
956
 
            "Invoked after a repository has been initialized. "
957
 
            "post_repo_init is called with a "
958
 
            "bzrlib.bzrdir.RepoInitHookParams.",
959
 
            (2, 2), None))
960
1313
 
961
1314
# install the default hooks
962
1315
BzrDir.hooks = BzrDirHooks()
963
1316
 
964
1317
 
965
 
class RepoInitHookParams(object):
966
 
    """Object holding parameters passed to *_repo_init hooks.
967
 
 
968
 
    There are 4 fields that hooks may wish to access:
969
 
 
970
 
    :ivar repository: Repository created
971
 
    :ivar format: Repository format
972
 
    :ivar bzrdir: The bzrdir for the repository
973
 
    :ivar shared: The repository is shared
974
 
    """
975
 
 
976
 
    def __init__(self, repository, format, a_bzrdir, shared):
977
 
        """Create a group of RepoInitHook parameters.
978
 
 
979
 
        :param repository: Repository created
980
 
        :param format: Repository format
981
 
        :param bzrdir: The bzrdir for the repository
982
 
        :param shared: The repository is shared
983
 
        """
984
 
        self.repository = repository
985
 
        self.format = format
986
 
        self.bzrdir = a_bzrdir
987
 
        self.shared = shared
988
 
 
989
 
    def __eq__(self, other):
990
 
        return self.__dict__ == other.__dict__
991
 
 
992
 
    def __repr__(self):
993
 
        if self.repository:
994
 
            return "<%s for %s>" % (self.__class__.__name__,
995
 
                self.repository)
996
 
        else:
997
 
            return "<%s for %s>" % (self.__class__.__name__,
998
 
                self.bzrdir)
999
 
 
1000
 
 
1001
1318
class BzrDirPreSplitOut(BzrDir):
1002
1319
    """A common class for the all-in-one formats."""
1003
1320
 
1016
1333
    def cloning_metadir(self, require_stacking=False):
1017
1334
        """Produce a metadir suitable for cloning with."""
1018
1335
        if require_stacking:
1019
 
            return controldir.format_registry.make_bzrdir('1.6')
 
1336
            return format_registry.make_bzrdir('1.6')
1020
1337
        return self._format.__class__()
1021
1338
 
1022
1339
    def clone(self, url, revision_id=None, force_new_repo=False,
1042
1359
            tree.clone(result)
1043
1360
        return result
1044
1361
 
1045
 
    def create_branch(self, name=None):
 
1362
    def create_branch(self):
1046
1363
        """See BzrDir.create_branch."""
1047
 
        return self._format.get_branch_format().initialize(self, name=name)
 
1364
        return self._format.get_branch_format().initialize(self)
1048
1365
 
1049
 
    def destroy_branch(self, name=None):
 
1366
    def destroy_branch(self):
1050
1367
        """See BzrDir.destroy_branch."""
1051
1368
        raise errors.UnsupportedOperation(self.destroy_branch, self)
1052
1369
 
1108
1425
        raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1109
1426
                                          self)
1110
1427
 
1111
 
    def get_branch_transport(self, branch_format, name=None):
 
1428
    def get_branch_transport(self, branch_format):
1112
1429
        """See BzrDir.get_branch_transport()."""
1113
 
        if name is not None:
1114
 
            raise errors.NoColocatedBranchSupport(self)
1115
1430
        if branch_format is None:
1116
1431
            return self.transport
1117
1432
        try:
1150
1465
            format = BzrDirFormat.get_default_format()
1151
1466
        return not isinstance(self._format, format.__class__)
1152
1467
 
1153
 
    def open_branch(self, name=None, unsupported=False,
1154
 
                    ignore_fallbacks=False):
 
1468
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
1155
1469
        """See BzrDir.open_branch."""
1156
1470
        from bzrlib.branch import BzrBranchFormat4
1157
1471
        format = BzrBranchFormat4()
1158
1472
        self._check_supported(format, unsupported)
1159
 
        return format.open(self, name, _found=True)
 
1473
        return format.open(self, _found=True)
1160
1474
 
1161
1475
    def sprout(self, url, revision_id=None, force_new_repo=False,
1162
1476
               possible_transports=None, accelerator_tree=None,
1223
1537
    This is a deprecated format and may be removed after sept 2006.
1224
1538
    """
1225
1539
 
1226
 
    def has_workingtree(self):
1227
 
        """See BzrDir.has_workingtree."""
1228
 
        return True
1229
 
    
1230
1540
    def open_repository(self):
1231
1541
        """See BzrDir.open_repository."""
1232
1542
        from bzrlib.repofmt.weaverepo import RepositoryFormat5
1248
1558
    This is a deprecated format and may be removed after sept 2006.
1249
1559
    """
1250
1560
 
1251
 
    def has_workingtree(self):
1252
 
        """See BzrDir.has_workingtree."""
1253
 
        return True
1254
 
    
1255
1561
    def open_repository(self):
1256
1562
        """See BzrDir.open_repository."""
1257
1563
        from bzrlib.repofmt.weaverepo import RepositoryFormat6
1279
1585
        """See BzrDir.can_convert_format()."""
1280
1586
        return True
1281
1587
 
1282
 
    def create_branch(self, name=None):
 
1588
    def create_branch(self):
1283
1589
        """See BzrDir.create_branch."""
1284
 
        return self._format.get_branch_format().initialize(self, name=name)
 
1590
        return self._format.get_branch_format().initialize(self)
1285
1591
 
1286
 
    def destroy_branch(self, name=None):
 
1592
    def destroy_branch(self):
1287
1593
        """See BzrDir.create_branch."""
1288
 
        if name is not None:
1289
 
            raise errors.NoColocatedBranchSupport(self)
1290
1594
        self.transport.delete_tree('branch')
1291
1595
 
1292
1596
    def create_repository(self, shared=False):
1315
1619
    def destroy_workingtree_metadata(self):
1316
1620
        self.transport.delete_tree('checkout')
1317
1621
 
1318
 
    def find_branch_format(self, name=None):
 
1622
    def find_branch_format(self):
1319
1623
        """Find the branch 'format' for this bzrdir.
1320
1624
 
1321
1625
        This might be a synthetic object for e.g. RemoteBranch and SVN.
1322
1626
        """
1323
1627
        from bzrlib.branch import BranchFormat
1324
 
        return BranchFormat.find_format(self, name=name)
 
1628
        return BranchFormat.find_format(self)
1325
1629
 
1326
1630
    def _get_mkdir_mode(self):
1327
1631
        """Figure out the mode to use when creating a bzrdir subdir."""
1329
1633
                                     lockable_files.TransportLock)
1330
1634
        return temp_control._dir_mode
1331
1635
 
1332
 
    def get_branch_reference(self, name=None):
 
1636
    def get_branch_reference(self):
1333
1637
        """See BzrDir.get_branch_reference()."""
1334
1638
        from bzrlib.branch import BranchFormat
1335
 
        format = BranchFormat.find_format(self, name=name)
1336
 
        return format.get_reference(self, name=name)
 
1639
        format = BranchFormat.find_format(self)
 
1640
        return format.get_reference(self)
1337
1641
 
1338
 
    def get_branch_transport(self, branch_format, name=None):
 
1642
    def get_branch_transport(self, branch_format):
1339
1643
        """See BzrDir.get_branch_transport()."""
1340
 
        if name is not None:
1341
 
            raise errors.NoColocatedBranchSupport(self)
1342
1644
        # XXX: this shouldn't implicitly create the directory if it's just
1343
1645
        # promising to get a transport -- mbp 20090727
1344
1646
        if branch_format is None:
1381
1683
            pass
1382
1684
        return self.transport.clone('checkout')
1383
1685
 
1384
 
    def has_workingtree(self):
1385
 
        """Tell if this bzrdir contains a working tree.
1386
 
 
1387
 
        This will still raise an exception if the bzrdir has a workingtree that
1388
 
        is remote & inaccessible.
1389
 
 
1390
 
        Note: if you're going to open the working tree, you should just go
1391
 
        ahead and try, and not ask permission first.
1392
 
        """
1393
 
        from bzrlib.workingtree import WorkingTreeFormat
1394
 
        try:
1395
 
            WorkingTreeFormat.find_format(self)
1396
 
        except errors.NoWorkingTree:
1397
 
            return False
1398
 
        return True
1399
 
 
1400
1686
    def needs_format_conversion(self, format=None):
1401
1687
        """See BzrDir.needs_format_conversion()."""
1402
1688
        if format is None:
1415
1701
                return True
1416
1702
        except errors.NoRepositoryPresent:
1417
1703
            pass
1418
 
        for branch in self.list_branches():
1419
 
            if not isinstance(branch._format,
 
1704
        try:
 
1705
            if not isinstance(self.open_branch()._format,
1420
1706
                              format.get_branch_format().__class__):
1421
1707
                # the branch needs an upgrade.
1422
1708
                return True
 
1709
        except errors.NotBranchError:
 
1710
            pass
1423
1711
        try:
1424
1712
            my_wt = self.open_workingtree(recommend_upgrade=False)
1425
1713
            if not isinstance(my_wt._format,
1430
1718
            pass
1431
1719
        return False
1432
1720
 
1433
 
    def open_branch(self, name=None, unsupported=False,
1434
 
                    ignore_fallbacks=False):
 
1721
    def open_branch(self, unsupported=False, ignore_fallbacks=False):
1435
1722
        """See BzrDir.open_branch."""
1436
 
        format = self.find_branch_format(name=name)
 
1723
        format = self.find_branch_format()
1437
1724
        self._check_supported(format, unsupported)
1438
 
        return format.open(self, name=name,
1439
 
            _found=True, ignore_fallbacks=ignore_fallbacks)
 
1725
        return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1440
1726
 
1441
1727
    def open_repository(self, unsupported=False):
1442
1728
        """See BzrDir.open_repository."""
1459
1745
        return config.TransportConfig(self.transport, 'control.conf')
1460
1746
 
1461
1747
 
1462
 
class BzrProber(controldir.Prober):
1463
 
    """Prober for formats that use a .bzr/ control directory."""
1464
 
 
1465
 
    _formats = {}
1466
 
    """The known .bzr formats."""
1467
 
 
1468
 
    @classmethod
1469
 
    def register_bzrdir_format(klass, format):
1470
 
        klass._formats[format.get_format_string()] = format
1471
 
 
1472
 
    @classmethod
1473
 
    def unregister_bzrdir_format(klass, format):
1474
 
        del klass._formats[format.get_format_string()]
1475
 
 
1476
 
    @classmethod
1477
 
    def probe_transport(klass, transport):
1478
 
        """Return the .bzrdir style format present in a directory."""
1479
 
        try:
1480
 
            format_string = transport.get_bytes(".bzr/branch-format")
1481
 
        except errors.NoSuchFile:
1482
 
            raise errors.NotBranchError(path=transport.base)
1483
 
        try:
1484
 
            return klass._formats[format_string]
1485
 
        except KeyError:
1486
 
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1487
 
 
1488
 
 
1489
 
controldir.ControlDirFormat.register_prober(BzrProber)
1490
 
 
1491
 
 
1492
 
class RemoteBzrProber(controldir.Prober):
1493
 
    """Prober for remote servers that provide a Bazaar smart server."""
1494
 
 
1495
 
    @classmethod
1496
 
    def probe_transport(klass, transport):
1497
 
        """Return a RemoteBzrDirFormat object if it looks possible."""
1498
 
        try:
1499
 
            medium = transport.get_smart_medium()
1500
 
        except (NotImplementedError, AttributeError,
1501
 
                errors.TransportNotPossible, errors.NoSmartMedium,
1502
 
                errors.SmartProtocolError):
1503
 
            # no smart server, so not a branch for this format type.
1504
 
            raise errors.NotBranchError(path=transport.base)
1505
 
        else:
1506
 
            # Decline to open it if the server doesn't support our required
1507
 
            # version (3) so that the VFS-based transport will do it.
1508
 
            if medium.should_probe():
1509
 
                try:
1510
 
                    server_version = medium.protocol_version()
1511
 
                except errors.SmartProtocolError:
1512
 
                    # Apparently there's no usable smart server there, even though
1513
 
                    # the medium supports the smart protocol.
1514
 
                    raise errors.NotBranchError(path=transport.base)
1515
 
                if server_version != '2':
1516
 
                    raise errors.NotBranchError(path=transport.base)
1517
 
            return RemoteBzrDirFormat()
1518
 
 
1519
 
 
1520
 
class BzrDirFormat(controldir.ControlDirFormat):
1521
 
    """ControlDirFormat base class for .bzr/ directories.
 
1748
class BzrDirFormat(object):
 
1749
    """An encapsulation of the initialization and open routines for a format.
 
1750
 
 
1751
    Formats provide three things:
 
1752
     * An initialization routine,
 
1753
     * a format string,
 
1754
     * an open routine.
1522
1755
 
1523
1756
    Formats are placed in a dict by their format string for reference
1524
1757
    during bzrdir opening. These should be subclasses of BzrDirFormat
1529
1762
    object will be created every system load.
1530
1763
    """
1531
1764
 
 
1765
    _default_format = None
 
1766
    """The default format used for new .bzr dirs."""
 
1767
 
 
1768
    _formats = {}
 
1769
    """The known formats."""
 
1770
 
 
1771
    _control_formats = []
 
1772
    """The registered control formats - .bzr, ....
 
1773
 
 
1774
    This is a list of BzrDirFormat objects.
 
1775
    """
 
1776
 
 
1777
    _control_server_formats = []
 
1778
    """The registered control server formats, e.g. RemoteBzrDirs.
 
1779
 
 
1780
    This is a list of BzrDirFormat objects.
 
1781
    """
 
1782
 
1532
1783
    _lock_file_name = 'branch-lock'
1533
1784
 
1534
1785
    # _lock_class must be set in subclasses to the lock type, typ.
1535
1786
    # TransportLock or LockDir
1536
1787
 
 
1788
    @classmethod
 
1789
    def find_format(klass, transport, _server_formats=True):
 
1790
        """Return the format present at transport."""
 
1791
        if _server_formats:
 
1792
            formats = klass._control_server_formats + klass._control_formats
 
1793
        else:
 
1794
            formats = klass._control_formats
 
1795
        for format in formats:
 
1796
            try:
 
1797
                return format.probe_transport(transport)
 
1798
            except errors.NotBranchError:
 
1799
                # this format does not find a control dir here.
 
1800
                pass
 
1801
        raise errors.NotBranchError(path=transport.base)
 
1802
 
 
1803
    @classmethod
 
1804
    def probe_transport(klass, transport):
 
1805
        """Return the .bzrdir style format present in a directory."""
 
1806
        try:
 
1807
            format_string = transport.get(".bzr/branch-format").read()
 
1808
        except errors.NoSuchFile:
 
1809
            raise errors.NotBranchError(path=transport.base)
 
1810
 
 
1811
        try:
 
1812
            return klass._formats[format_string]
 
1813
        except KeyError:
 
1814
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
 
1815
 
 
1816
    @classmethod
 
1817
    def get_default_format(klass):
 
1818
        """Return the current default format."""
 
1819
        return klass._default_format
 
1820
 
1537
1821
    def get_format_string(self):
1538
1822
        """Return the ASCII format string that identifies this format."""
1539
1823
        raise NotImplementedError(self.get_format_string)
1540
1824
 
 
1825
    def get_format_description(self):
 
1826
        """Return the short description for this format."""
 
1827
        raise NotImplementedError(self.get_format_description)
 
1828
 
 
1829
    def get_converter(self, format=None):
 
1830
        """Return the converter to use to convert bzrdirs needing converts.
 
1831
 
 
1832
        This returns a bzrlib.bzrdir.Converter object.
 
1833
 
 
1834
        This should return the best upgrader to step this format towards the
 
1835
        current default format. In the case of plugins we can/should provide
 
1836
        some means for them to extend the range of returnable converters.
 
1837
 
 
1838
        :param format: Optional format to override the default format of the
 
1839
                       library.
 
1840
        """
 
1841
        raise NotImplementedError(self.get_converter)
 
1842
 
 
1843
    def initialize(self, url, possible_transports=None):
 
1844
        """Create a bzr control dir at this url and return an opened copy.
 
1845
 
 
1846
        While not deprecated, this method is very specific and its use will
 
1847
        lead to many round trips to setup a working environment. See
 
1848
        initialize_on_transport_ex for a [nearly] all-in-one method.
 
1849
 
 
1850
        Subclasses should typically override initialize_on_transport
 
1851
        instead of this method.
 
1852
        """
 
1853
        return self.initialize_on_transport(get_transport(url,
 
1854
                                                          possible_transports))
 
1855
 
1541
1856
    def initialize_on_transport(self, transport):
1542
1857
        """Initialize a new bzrdir in the base directory of a Transport."""
1543
1858
        try:
1691
2006
            control_files.unlock()
1692
2007
        return self.open(transport, _found=True)
1693
2008
 
 
2009
    def is_supported(self):
 
2010
        """Is this format supported?
 
2011
 
 
2012
        Supported formats must be initializable and openable.
 
2013
        Unsupported formats may not support initialization or committing or
 
2014
        some other features depending on the reason for not being supported.
 
2015
        """
 
2016
        return True
 
2017
 
 
2018
    def network_name(self):
 
2019
        """A simple byte string uniquely identifying this format for RPC calls.
 
2020
 
 
2021
        Bzr control formats use thir disk format string to identify the format
 
2022
        over the wire. Its possible that other control formats have more
 
2023
        complex detection requirements, so we permit them to use any unique and
 
2024
        immutable string they desire.
 
2025
        """
 
2026
        raise NotImplementedError(self.network_name)
 
2027
 
 
2028
    def same_model(self, target_format):
 
2029
        return (self.repository_format.rich_root_data ==
 
2030
            target_format.rich_root_data)
 
2031
 
 
2032
    @classmethod
 
2033
    def known_formats(klass):
 
2034
        """Return all the known formats.
 
2035
 
 
2036
        Concrete formats should override _known_formats.
 
2037
        """
 
2038
        # There is double indirection here to make sure that control
 
2039
        # formats used by more than one dir format will only be probed
 
2040
        # once. This can otherwise be quite expensive for remote connections.
 
2041
        result = set()
 
2042
        for format in klass._control_formats:
 
2043
            result.update(format._known_formats())
 
2044
        return result
 
2045
 
 
2046
    @classmethod
 
2047
    def _known_formats(klass):
 
2048
        """Return the known format instances for this control format."""
 
2049
        return set(klass._formats.values())
 
2050
 
1694
2051
    def open(self, transport, _found=False):
1695
2052
        """Return an instance of this format for the dir transport points at.
1696
2053
 
1697
2054
        _found is a private parameter, do not use it.
1698
2055
        """
1699
2056
        if not _found:
1700
 
            found_format = controldir.ControlDirFormat.find_format(transport)
 
2057
            found_format = BzrDirFormat.find_format(transport)
1701
2058
            if not isinstance(found_format, self.__class__):
1702
2059
                raise AssertionError("%s was asked to open %s, but it seems to need "
1703
2060
                        "format %s"
1717
2074
 
1718
2075
    @classmethod
1719
2076
    def register_format(klass, format):
1720
 
        BzrProber.register_bzrdir_format(format)
 
2077
        klass._formats[format.get_format_string()] = format
1721
2078
        # bzr native formats have a network name of their format string.
1722
2079
        network_format_registry.register(format.get_format_string(), format.__class__)
1723
 
        controldir.ControlDirFormat.register_format(format)
 
2080
 
 
2081
    @classmethod
 
2082
    def register_control_format(klass, format):
 
2083
        """Register a format that does not use '.bzr' for its control dir.
 
2084
 
 
2085
        TODO: This should be pulled up into a 'ControlDirFormat' base class
 
2086
        which BzrDirFormat can inherit from, and renamed to register_format
 
2087
        there. It has been done without that for now for simplicity of
 
2088
        implementation.
 
2089
        """
 
2090
        klass._control_formats.append(format)
 
2091
 
 
2092
    @classmethod
 
2093
    def register_control_server_format(klass, format):
 
2094
        """Register a control format for client-server environments.
 
2095
 
 
2096
        These formats will be tried before ones registered with
 
2097
        register_control_format.  This gives implementations that decide to the
 
2098
        chance to grab it before anything looks at the contents of the format
 
2099
        file.
 
2100
        """
 
2101
        klass._control_server_formats.append(format)
 
2102
 
 
2103
    @classmethod
 
2104
    def _set_default_format(klass, format):
 
2105
        """Set default format (for testing behavior of defaults only)"""
 
2106
        klass._default_format = format
 
2107
 
 
2108
    def __str__(self):
 
2109
        # Trim the newline
 
2110
        return self.get_format_description().rstrip()
1724
2111
 
1725
2112
    def _supply_sub_formats_to(self, other_format):
1726
2113
        """Give other_format the same values for sub formats as this has.
1736
2123
 
1737
2124
    @classmethod
1738
2125
    def unregister_format(klass, format):
1739
 
        BzrProber.unregister_bzrdir_format(format)
1740
 
        controldir.ControlDirFormat.unregister_format(format)
1741
 
        network_format_registry.remove(format.get_format_string())
 
2126
        del klass._formats[format.get_format_string()]
 
2127
 
 
2128
    @classmethod
 
2129
    def unregister_control_format(klass, format):
 
2130
        klass._control_formats.remove(format)
1742
2131
 
1743
2132
 
1744
2133
class BzrDirFormat4(BzrDirFormat):
2156
2545
"""
2157
2546
 
2158
2547
 
 
2548
# Register bzr control format
 
2549
BzrDirFormat.register_control_format(BzrDirFormat)
 
2550
 
2159
2551
# Register bzr formats
2160
2552
BzrDirFormat.register_format(BzrDirFormat4())
2161
2553
BzrDirFormat.register_format(BzrDirFormat5())
2162
2554
BzrDirFormat.register_format(BzrDirFormat6())
2163
2555
__default_format = BzrDirMetaFormat1()
2164
2556
BzrDirFormat.register_format(__default_format)
2165
 
controldir.ControlDirFormat._default_format = __default_format
 
2557
BzrDirFormat._default_format = __default_format
2166
2558
 
2167
2559
 
2168
2560
class Converter(object):
2194
2586
    def convert(self, to_convert, pb):
2195
2587
        """See Converter.convert()."""
2196
2588
        self.bzrdir = to_convert
2197
 
        if pb is not None:
2198
 
            warnings.warn("pb parameter to convert() is deprecated")
2199
 
        self.pb = ui.ui_factory.nested_progress_bar()
2200
 
        try:
2201
 
            ui.ui_factory.note('starting upgrade from format 4 to 5')
2202
 
            if isinstance(self.bzrdir.transport, local.LocalTransport):
2203
 
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2204
 
            self._convert_to_weaves()
2205
 
            return BzrDir.open(self.bzrdir.user_url)
2206
 
        finally:
2207
 
            self.pb.finished()
 
2589
        self.pb = pb
 
2590
        self.pb.note('starting upgrade from format 4 to 5')
 
2591
        if isinstance(self.bzrdir.transport, local.LocalTransport):
 
2592
            self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
 
2593
        self._convert_to_weaves()
 
2594
        return BzrDir.open(self.bzrdir.root_transport.base)
2208
2595
 
2209
2596
    def _convert_to_weaves(self):
2210
 
        ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
 
2597
        self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2211
2598
        try:
2212
2599
            # TODO permissions
2213
2600
            stat = self.bzrdir.transport.stat('weaves')
2241
2628
        self.pb.clear()
2242
2629
        self._write_all_weaves()
2243
2630
        self._write_all_revs()
2244
 
        ui.ui_factory.note('upgraded to weaves:')
2245
 
        ui.ui_factory.note('  %6d revisions and inventories' % len(self.revisions))
2246
 
        ui.ui_factory.note('  %6d revisions not present' % len(self.absent_revisions))
2247
 
        ui.ui_factory.note('  %6d texts' % self.text_count)
 
2631
        self.pb.note('upgraded to weaves:')
 
2632
        self.pb.note('  %6d revisions and inventories', len(self.revisions))
 
2633
        self.pb.note('  %6d revisions not present', len(self.absent_revisions))
 
2634
        self.pb.note('  %6d texts', self.text_count)
2248
2635
        self._cleanup_spare_files_after_format4()
2249
2636
        self.branch._transport.put_bytes(
2250
2637
            'branch-format',
2318
2705
                       len(self.known_revisions))
2319
2706
        if not self.branch.repository.has_revision(rev_id):
2320
2707
            self.pb.clear()
2321
 
            ui.ui_factory.note('revision {%s} not present in branch; '
2322
 
                         'will be converted as a ghost' %
 
2708
            self.pb.note('revision {%s} not present in branch; '
 
2709
                         'will be converted as a ghost',
2323
2710
                         rev_id)
2324
2711
            self.absent_revisions.add(rev_id)
2325
2712
        else:
2330
2717
            self.revisions[rev_id] = rev
2331
2718
 
2332
2719
    def _load_old_inventory(self, rev_id):
2333
 
        f = self.branch.repository.inventory_store.get(rev_id)
2334
 
        try:
2335
 
            old_inv_xml = f.read()
2336
 
        finally:
2337
 
            f.close()
 
2720
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2338
2721
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2339
2722
        inv.revision_id = rev_id
2340
2723
        rev = self.revisions[rev_id]
2396
2779
        previous_entries = dict((head, parent_candiate_entries[head]) for head
2397
2780
            in heads)
2398
2781
        self.snapshot_ie(previous_entries, ie, w, rev_id)
 
2782
        del ie.text_id
2399
2783
 
2400
2784
    def get_parent_map(self, revision_ids):
2401
2785
        """See graph.StackedParentsProvider.get_parent_map"""
2417
2801
                ie.revision = previous_ie.revision
2418
2802
                return
2419
2803
        if ie.has_text():
2420
 
            f = self.branch.repository._text_store.get(ie.text_id)
2421
 
            try:
2422
 
                file_lines = f.readlines()
2423
 
            finally:
2424
 
                f.close()
 
2804
            text = self.branch.repository._text_store.get(ie.text_id)
 
2805
            file_lines = text.readlines()
2425
2806
            w.add_lines(rev_id, previous_revisions, file_lines)
2426
2807
            self.text_count += 1
2427
2808
        else:
2457
2838
    def convert(self, to_convert, pb):
2458
2839
        """See Converter.convert()."""
2459
2840
        self.bzrdir = to_convert
2460
 
        pb = ui.ui_factory.nested_progress_bar()
2461
 
        try:
2462
 
            ui.ui_factory.note('starting upgrade from format 5 to 6')
2463
 
            self._convert_to_prefixed()
2464
 
            return BzrDir.open(self.bzrdir.user_url)
2465
 
        finally:
2466
 
            pb.finished()
 
2841
        self.pb = pb
 
2842
        self.pb.note('starting upgrade from format 5 to 6')
 
2843
        self._convert_to_prefixed()
 
2844
        return BzrDir.open(self.bzrdir.root_transport.base)
2467
2845
 
2468
2846
    def _convert_to_prefixed(self):
2469
2847
        from bzrlib.store import TransportStore
2470
2848
        self.bzrdir.transport.delete('branch-format')
2471
2849
        for store_name in ["weaves", "revision-store"]:
2472
 
            ui.ui_factory.note("adding prefixes to %s" % store_name)
 
2850
            self.pb.note("adding prefixes to %s" % store_name)
2473
2851
            store_transport = self.bzrdir.transport.clone(store_name)
2474
2852
            store = TransportStore(store_transport, prefixed=True)
2475
2853
            for urlfilename in store_transport.list_dir('.'):
2502
2880
        from bzrlib.repofmt.weaverepo import RepositoryFormat7
2503
2881
        from bzrlib.branch import BzrBranchFormat5
2504
2882
        self.bzrdir = to_convert
2505
 
        self.pb = ui.ui_factory.nested_progress_bar()
 
2883
        self.pb = pb
2506
2884
        self.count = 0
2507
2885
        self.total = 20 # the steps we know about
2508
2886
        self.garbage_inventories = []
2509
2887
        self.dir_mode = self.bzrdir._get_dir_mode()
2510
2888
        self.file_mode = self.bzrdir._get_file_mode()
2511
2889
 
2512
 
        ui.ui_factory.note('starting upgrade from format 6 to metadir')
 
2890
        self.pb.note('starting upgrade from format 6 to metadir')
2513
2891
        self.bzrdir.transport.put_bytes(
2514
2892
                'branch-format',
2515
2893
                "Converting to format 6",
2565
2943
        else:
2566
2944
            has_checkout = True
2567
2945
        if not has_checkout:
2568
 
            ui.ui_factory.note('No working tree.')
 
2946
            self.pb.note('No working tree.')
2569
2947
            # If some checkout files are there, we may as well get rid of them.
2570
2948
            for name, mandatory in checkout_files:
2571
2949
                if name in bzrcontents:
2588
2966
            'branch-format',
2589
2967
            BzrDirMetaFormat1().get_format_string(),
2590
2968
            mode=self.file_mode)
2591
 
        self.pb.finished()
2592
 
        return BzrDir.open(self.bzrdir.user_url)
 
2969
        return BzrDir.open(self.bzrdir.root_transport.base)
2593
2970
 
2594
2971
    def make_lock(self, name):
2595
2972
        """Make a lock for the new control dir name."""
2630
3007
    def convert(self, to_convert, pb):
2631
3008
        """See Converter.convert()."""
2632
3009
        self.bzrdir = to_convert
2633
 
        self.pb = ui.ui_factory.nested_progress_bar()
 
3010
        self.pb = pb
2634
3011
        self.count = 0
2635
3012
        self.total = 1
2636
3013
        self.step('checking repository format')
2641
3018
        else:
2642
3019
            if not isinstance(repo._format, self.target_format.repository_format.__class__):
2643
3020
                from bzrlib.repository import CopyConverter
2644
 
                ui.ui_factory.note('starting repository conversion')
 
3021
                self.pb.note('starting repository conversion')
2645
3022
                converter = CopyConverter(self.target_format.repository_format)
2646
3023
                converter.convert(repo, pb)
2647
 
        for branch in self.bzrdir.list_branches():
 
3024
        try:
 
3025
            branch = self.bzrdir.open_branch()
 
3026
        except errors.NotBranchError:
 
3027
            pass
 
3028
        else:
2648
3029
            # TODO: conversions of Branch and Tree should be done by
2649
3030
            # InterXFormat lookups/some sort of registry.
2650
3031
            # Avoid circular imports
2692
3073
                isinstance(self.target_format.workingtree_format,
2693
3074
                    workingtree_4.WorkingTreeFormat6)):
2694
3075
                workingtree_4.Converter4or5to6().convert(tree)
2695
 
        self.pb.finished()
2696
3076
        return to_convert
2697
3077
 
2698
3078
 
2705
3085
 
2706
3086
    def __init__(self):
2707
3087
        BzrDirMetaFormat1.__init__(self)
2708
 
        # XXX: It's a bit ugly that the network name is here, because we'd
2709
 
        # like to believe that format objects are stateless or at least
2710
 
        # immutable,  However, we do at least avoid mutating the name after
2711
 
        # it's returned.  See <https://bugs.launchpad.net/bzr/+bug/504102>
2712
3088
        self._network_name = None
2713
3089
 
2714
 
    def __repr__(self):
2715
 
        return "%s(_network_name=%r)" % (self.__class__.__name__,
2716
 
            self._network_name)
2717
 
 
2718
3090
    def get_format_description(self):
2719
 
        if self._network_name:
2720
 
            real_format = network_format_registry.get(self._network_name)
2721
 
            return 'Remote: ' + real_format.get_format_description()
2722
3091
        return 'bzr remote bzrdir'
2723
3092
 
2724
3093
    def get_format_string(self):
2730
3099
        else:
2731
3100
            raise AssertionError("No network name set.")
2732
3101
 
 
3102
    @classmethod
 
3103
    def probe_transport(klass, transport):
 
3104
        """Return a RemoteBzrDirFormat object if it looks possible."""
 
3105
        try:
 
3106
            medium = transport.get_smart_medium()
 
3107
        except (NotImplementedError, AttributeError,
 
3108
                errors.TransportNotPossible, errors.NoSmartMedium,
 
3109
                errors.SmartProtocolError):
 
3110
            # no smart server, so not a branch for this format type.
 
3111
            raise errors.NotBranchError(path=transport.base)
 
3112
        else:
 
3113
            # Decline to open it if the server doesn't support our required
 
3114
            # version (3) so that the VFS-based transport will do it.
 
3115
            if medium.should_probe():
 
3116
                try:
 
3117
                    server_version = medium.protocol_version()
 
3118
                except errors.SmartProtocolError:
 
3119
                    # Apparently there's no usable smart server there, even though
 
3120
                    # the medium supports the smart protocol.
 
3121
                    raise errors.NotBranchError(path=transport.base)
 
3122
                if server_version != '2':
 
3123
                    raise errors.NotBranchError(path=transport.base)
 
3124
            return klass()
 
3125
 
2733
3126
    def initialize_on_transport(self, transport):
2734
3127
        try:
2735
3128
            # hand off the request to the smart server
2833
3226
        args.append(self._serialize_NoneString(repo_format_name))
2834
3227
        args.append(self._serialize_NoneTrueFalse(make_working_trees))
2835
3228
        args.append(self._serialize_NoneTrueFalse(shared_repo))
2836
 
        request_network_name = self._network_name or \
 
3229
        if self._network_name is None:
 
3230
            self._network_name = \
2837
3231
            BzrDirFormat.get_default_format().network_name()
2838
3232
        try:
2839
3233
            response = client.call('BzrDirFormat.initialize_ex_1.16',
2840
 
                request_network_name, path, *args)
 
3234
                self.network_name(), path, *args)
2841
3235
        except errors.UnknownSmartMethod:
2842
3236
            client._medium._remember_remote_is_before((1,16))
2843
3237
            local_dir_format = BzrDirMetaFormat1()
2934
3328
        BzrDirMetaFormat1._set_repository_format) #.im_func)
2935
3329
 
2936
3330
 
2937
 
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
 
3331
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
 
3332
 
 
3333
 
 
3334
class BzrDirFormatInfo(object):
 
3335
 
 
3336
    def __init__(self, native, deprecated, hidden, experimental):
 
3337
        self.deprecated = deprecated
 
3338
        self.native = native
 
3339
        self.hidden = hidden
 
3340
        self.experimental = experimental
 
3341
 
 
3342
 
 
3343
class BzrDirFormatRegistry(registry.Registry):
 
3344
    """Registry of user-selectable BzrDir subformats.
 
3345
 
 
3346
    Differs from BzrDirFormat._control_formats in that it provides sub-formats,
 
3347
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
 
3348
    """
 
3349
 
 
3350
    def __init__(self):
 
3351
        """Create a BzrDirFormatRegistry."""
 
3352
        self._aliases = set()
 
3353
        self._registration_order = list()
 
3354
        super(BzrDirFormatRegistry, self).__init__()
 
3355
 
 
3356
    def aliases(self):
 
3357
        """Return a set of the format names which are aliases."""
 
3358
        return frozenset(self._aliases)
 
3359
 
 
3360
    def register_metadir(self, key,
 
3361
             repository_format, help, native=True, deprecated=False,
 
3362
             branch_format=None,
 
3363
             tree_format=None,
 
3364
             hidden=False,
 
3365
             experimental=False,
 
3366
             alias=False):
 
3367
        """Register a metadir subformat.
 
3368
 
 
3369
        These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
 
3370
        by the Repository/Branch/WorkingTreeformats.
 
3371
 
 
3372
        :param repository_format: The fully-qualified repository format class
 
3373
            name as a string.
 
3374
        :param branch_format: Fully-qualified branch format class name as
 
3375
            a string.
 
3376
        :param tree_format: Fully-qualified tree format class name as
 
3377
            a string.
 
3378
        """
 
3379
        # This should be expanded to support setting WorkingTree and Branch
 
3380
        # formats, once BzrDirMetaFormat1 supports that.
 
3381
        def _load(full_name):
 
3382
            mod_name, factory_name = full_name.rsplit('.', 1)
 
3383
            try:
 
3384
                mod = __import__(mod_name, globals(), locals(),
 
3385
                        [factory_name])
 
3386
            except ImportError, e:
 
3387
                raise ImportError('failed to load %s: %s' % (full_name, e))
 
3388
            try:
 
3389
                factory = getattr(mod, factory_name)
 
3390
            except AttributeError:
 
3391
                raise AttributeError('no factory %s in module %r'
 
3392
                    % (full_name, mod))
 
3393
            return factory()
 
3394
 
 
3395
        def helper():
 
3396
            bd = BzrDirMetaFormat1()
 
3397
            if branch_format is not None:
 
3398
                bd.set_branch_format(_load(branch_format))
 
3399
            if tree_format is not None:
 
3400
                bd.workingtree_format = _load(tree_format)
 
3401
            if repository_format is not None:
 
3402
                bd.repository_format = _load(repository_format)
 
3403
            return bd
 
3404
        self.register(key, helper, help, native, deprecated, hidden,
 
3405
            experimental, alias)
 
3406
 
 
3407
    def register(self, key, factory, help, native=True, deprecated=False,
 
3408
                 hidden=False, experimental=False, alias=False):
 
3409
        """Register a BzrDirFormat factory.
 
3410
 
 
3411
        The factory must be a callable that takes one parameter: the key.
 
3412
        It must produce an instance of the BzrDirFormat when called.
 
3413
 
 
3414
        This function mainly exists to prevent the info object from being
 
3415
        supplied directly.
 
3416
        """
 
3417
        registry.Registry.register(self, key, factory, help,
 
3418
            BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3419
        if alias:
 
3420
            self._aliases.add(key)
 
3421
        self._registration_order.append(key)
 
3422
 
 
3423
    def register_lazy(self, key, module_name, member_name, help, native=True,
 
3424
        deprecated=False, hidden=False, experimental=False, alias=False):
 
3425
        registry.Registry.register_lazy(self, key, module_name, member_name,
 
3426
            help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3427
        if alias:
 
3428
            self._aliases.add(key)
 
3429
        self._registration_order.append(key)
 
3430
 
 
3431
    def set_default(self, key):
 
3432
        """Set the 'default' key to be a clone of the supplied key.
 
3433
 
 
3434
        This method must be called once and only once.
 
3435
        """
 
3436
        registry.Registry.register(self, 'default', self.get(key),
 
3437
            self.get_help(key), info=self.get_info(key))
 
3438
        self._aliases.add('default')
 
3439
 
 
3440
    def set_default_repository(self, key):
 
3441
        """Set the FormatRegistry default and Repository default.
 
3442
 
 
3443
        This is a transitional method while Repository.set_default_format
 
3444
        is deprecated.
 
3445
        """
 
3446
        if 'default' in self:
 
3447
            self.remove('default')
 
3448
        self.set_default(key)
 
3449
        format = self.get('default')()
 
3450
 
 
3451
    def make_bzrdir(self, key):
 
3452
        return self.get(key)()
 
3453
 
 
3454
    def help_topic(self, topic):
 
3455
        output = ""
 
3456
        default_realkey = None
 
3457
        default_help = self.get_help('default')
 
3458
        help_pairs = []
 
3459
        for key in self._registration_order:
 
3460
            if key == 'default':
 
3461
                continue
 
3462
            help = self.get_help(key)
 
3463
            if help == default_help:
 
3464
                default_realkey = key
 
3465
            else:
 
3466
                help_pairs.append((key, help))
 
3467
 
 
3468
        def wrapped(key, help, info):
 
3469
            if info.native:
 
3470
                help = '(native) ' + help
 
3471
            return ':%s:\n%s\n\n' % (key,
 
3472
                textwrap.fill(help, initial_indent='    ',
 
3473
                    subsequent_indent='    ',
 
3474
                    break_long_words=False))
 
3475
        if default_realkey is not None:
 
3476
            output += wrapped(default_realkey, '(default) %s' % default_help,
 
3477
                              self.get_info('default'))
 
3478
        deprecated_pairs = []
 
3479
        experimental_pairs = []
 
3480
        for key, help in help_pairs:
 
3481
            info = self.get_info(key)
 
3482
            if info.hidden:
 
3483
                continue
 
3484
            elif info.deprecated:
 
3485
                deprecated_pairs.append((key, help))
 
3486
            elif info.experimental:
 
3487
                experimental_pairs.append((key, help))
 
3488
            else:
 
3489
                output += wrapped(key, help, info)
 
3490
        output += "\nSee ``bzr help formats`` for more about storage formats."
 
3491
        other_output = ""
 
3492
        if len(experimental_pairs) > 0:
 
3493
            other_output += "Experimental formats are shown below.\n\n"
 
3494
            for key, help in experimental_pairs:
 
3495
                info = self.get_info(key)
 
3496
                other_output += wrapped(key, help, info)
 
3497
        else:
 
3498
            other_output += \
 
3499
                "No experimental formats are available.\n\n"
 
3500
        if len(deprecated_pairs) > 0:
 
3501
            other_output += "\nDeprecated formats are shown below.\n\n"
 
3502
            for key, help in deprecated_pairs:
 
3503
                info = self.get_info(key)
 
3504
                other_output += wrapped(key, help, info)
 
3505
        else:
 
3506
            other_output += \
 
3507
                "\nNo deprecated formats are available.\n\n"
 
3508
        other_output += \
 
3509
            "\nSee ``bzr help formats`` for more about storage formats."
 
3510
 
 
3511
        if topic == 'other-formats':
 
3512
            return other_output
 
3513
        else:
 
3514
            return output
2938
3515
 
2939
3516
 
2940
3517
class RepositoryAcquisitionPolicy(object):
2969
3546
            try:
2970
3547
                stack_on = urlutils.rebase_url(self._stack_on,
2971
3548
                    self._stack_on_pwd,
2972
 
                    branch.user_url)
 
3549
                    branch.bzrdir.root_transport.base)
2973
3550
            except errors.InvalidRebaseURLs:
2974
3551
                stack_on = self._get_full_stack_on()
2975
3552
        try:
3094
3671
        return self._repository, False
3095
3672
 
3096
3673
 
3097
 
def register_metadir(registry, key,
3098
 
         repository_format, help, native=True, deprecated=False,
3099
 
         branch_format=None,
3100
 
         tree_format=None,
3101
 
         hidden=False,
3102
 
         experimental=False,
3103
 
         alias=False):
3104
 
    """Register a metadir subformat.
3105
 
 
3106
 
    These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3107
 
    by the Repository/Branch/WorkingTreeformats.
3108
 
 
3109
 
    :param repository_format: The fully-qualified repository format class
3110
 
        name as a string.
3111
 
    :param branch_format: Fully-qualified branch format class name as
3112
 
        a string.
3113
 
    :param tree_format: Fully-qualified tree format class name as
3114
 
        a string.
3115
 
    """
3116
 
    # This should be expanded to support setting WorkingTree and Branch
3117
 
    # formats, once BzrDirMetaFormat1 supports that.
3118
 
    def _load(full_name):
3119
 
        mod_name, factory_name = full_name.rsplit('.', 1)
3120
 
        try:
3121
 
            mod = __import__(mod_name, globals(), locals(),
3122
 
                    [factory_name])
3123
 
        except ImportError, e:
3124
 
            raise ImportError('failed to load %s: %s' % (full_name, e))
3125
 
        try:
3126
 
            factory = getattr(mod, factory_name)
3127
 
        except AttributeError:
3128
 
            raise AttributeError('no factory %s in module %r'
3129
 
                % (full_name, mod))
3130
 
        return factory()
3131
 
 
3132
 
    def helper():
3133
 
        bd = BzrDirMetaFormat1()
3134
 
        if branch_format is not None:
3135
 
            bd.set_branch_format(_load(branch_format))
3136
 
        if tree_format is not None:
3137
 
            bd.workingtree_format = _load(tree_format)
3138
 
        if repository_format is not None:
3139
 
            bd.repository_format = _load(repository_format)
3140
 
        return bd
3141
 
    registry.register(key, helper, help, native, deprecated, hidden,
3142
 
        experimental, alias)
3143
 
 
 
3674
# Please register new formats after old formats so that formats
 
3675
# appear in chronological order and format descriptions can build
 
3676
# on previous ones.
 
3677
format_registry = BzrDirFormatRegistry()
3144
3678
# The pre-0.8 formats have their repository format network name registered in
3145
3679
# repository.py. MetaDir formats have their repository format network name
3146
3680
# inferred from their disk format string.
3147
 
controldir.format_registry.register('weave', BzrDirFormat6,
 
3681
format_registry.register('weave', BzrDirFormat6,
3148
3682
    'Pre-0.8 format.  Slower than knit and does not'
3149
3683
    ' support checkouts or shared repositories.',
3150
 
    hidden=True,
3151
3684
    deprecated=True)
3152
 
register_metadir(controldir.format_registry, 'metaweave',
 
3685
format_registry.register_metadir('metaweave',
3153
3686
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3154
3687
    'Transitional format in 0.8.  Slower than knit.',
3155
3688
    branch_format='bzrlib.branch.BzrBranchFormat5',
3156
3689
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3157
 
    hidden=True,
3158
3690
    deprecated=True)
3159
 
register_metadir(controldir.format_registry, 'knit',
 
3691
format_registry.register_metadir('knit',
3160
3692
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3161
3693
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
3162
3694
    branch_format='bzrlib.branch.BzrBranchFormat5',
3163
3695
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3164
 
    hidden=True,
3165
3696
    deprecated=True)
3166
 
register_metadir(controldir.format_registry, 'dirstate',
 
3697
format_registry.register_metadir('dirstate',
3167
3698
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3168
3699
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3169
3700
        'above when accessed over the network.',
3171
3702
    # this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3172
3703
    # directly from workingtree_4 triggers a circular import.
3173
3704
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3174
 
    hidden=True,
3175
3705
    deprecated=True)
3176
 
register_metadir(controldir.format_registry, 'dirstate-tags',
 
3706
format_registry.register_metadir('dirstate-tags',
3177
3707
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3178
3708
    help='New in 0.15: Fast local operations and improved scaling for '
3179
3709
        'network operations. Additionally adds support for tags.'
3180
3710
        ' Incompatible with bzr < 0.15.',
3181
3711
    branch_format='bzrlib.branch.BzrBranchFormat6',
3182
3712
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3183
 
    hidden=True,
3184
3713
    deprecated=True)
3185
 
register_metadir(controldir.format_registry, 'rich-root',
 
3714
format_registry.register_metadir('rich-root',
3186
3715
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3187
3716
    help='New in 1.0.  Better handling of tree roots.  Incompatible with'
3188
3717
        ' bzr < 1.0.',
3189
3718
    branch_format='bzrlib.branch.BzrBranchFormat6',
3190
3719
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3191
 
    hidden=True,
3192
3720
    deprecated=True)
3193
 
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
 
3721
format_registry.register_metadir('dirstate-with-subtree',
3194
3722
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3195
3723
    help='New in 0.15: Fast local operations and improved scaling for '
3196
3724
        'network operations. Additionally adds support for versioning nested '
3200
3728
    experimental=True,
3201
3729
    hidden=True,
3202
3730
    )
3203
 
register_metadir(controldir.format_registry, 'pack-0.92',
 
3731
format_registry.register_metadir('pack-0.92',
3204
3732
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3205
3733
    help='New in 0.92: Pack-based format with data compatible with '
3206
3734
        'dirstate-tags format repositories. Interoperates with '
3207
3735
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3208
 
        ,
 
3736
        'Previously called knitpack-experimental.  '
 
3737
        'For more information, see '
 
3738
        'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3209
3739
    branch_format='bzrlib.branch.BzrBranchFormat6',
3210
3740
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3211
3741
    )
3212
 
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
 
3742
format_registry.register_metadir('pack-0.92-subtree',
3213
3743
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3214
3744
    help='New in 0.92: Pack-based format with data compatible with '
3215
3745
        'dirstate-with-subtree format repositories. Interoperates with '
3216
3746
        'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3217
 
        ,
 
3747
        'Previously called knitpack-experimental.  '
 
3748
        'For more information, see '
 
3749
        'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3218
3750
    branch_format='bzrlib.branch.BzrBranchFormat6',
3219
3751
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3220
3752
    hidden=True,
3221
3753
    experimental=True,
3222
3754
    )
3223
 
register_metadir(controldir.format_registry, 'rich-root-pack',
 
3755
format_registry.register_metadir('rich-root-pack',
3224
3756
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3225
3757
    help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3226
3758
         '(needed for bzr-svn and bzr-git).',
3227
3759
    branch_format='bzrlib.branch.BzrBranchFormat6',
3228
3760
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3229
 
    hidden=True,
3230
3761
    )
3231
 
register_metadir(controldir.format_registry, '1.6',
 
3762
format_registry.register_metadir('1.6',
3232
3763
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3233
3764
    help='A format that allows a branch to indicate that there is another '
3234
3765
         '(stacked) repository that should be used to access data that is '
3235
3766
         'not present locally.',
3236
3767
    branch_format='bzrlib.branch.BzrBranchFormat7',
3237
3768
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3238
 
    hidden=True,
3239
3769
    )
3240
 
register_metadir(controldir.format_registry, '1.6.1-rich-root',
 
3770
format_registry.register_metadir('1.6.1-rich-root',
3241
3771
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3242
3772
    help='A variant of 1.6 that supports rich-root data '
3243
3773
         '(needed for bzr-svn and bzr-git).',
3244
3774
    branch_format='bzrlib.branch.BzrBranchFormat7',
3245
3775
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3246
 
    hidden=True,
3247
3776
    )
3248
 
register_metadir(controldir.format_registry, '1.9',
 
3777
format_registry.register_metadir('1.9',
3249
3778
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3250
3779
    help='A repository format using B+tree indexes. These indexes '
3251
3780
         'are smaller in size, have smarter caching and provide faster '
3252
3781
         'performance for most operations.',
3253
3782
    branch_format='bzrlib.branch.BzrBranchFormat7',
3254
3783
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3255
 
    hidden=True,
3256
3784
    )
3257
 
register_metadir(controldir.format_registry, '1.9-rich-root',
 
3785
format_registry.register_metadir('1.9-rich-root',
3258
3786
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3259
3787
    help='A variant of 1.9 that supports rich-root data '
3260
3788
         '(needed for bzr-svn and bzr-git).',
3261
3789
    branch_format='bzrlib.branch.BzrBranchFormat7',
3262
3790
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3263
 
    hidden=True,
3264
3791
    )
3265
 
register_metadir(controldir.format_registry, '1.14',
 
3792
format_registry.register_metadir('1.14',
3266
3793
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3267
3794
    help='A working-tree format that supports content filtering.',
3268
3795
    branch_format='bzrlib.branch.BzrBranchFormat7',
3269
3796
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3270
3797
    )
3271
 
register_metadir(controldir.format_registry, '1.14-rich-root',
 
3798
format_registry.register_metadir('1.14-rich-root',
3272
3799
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3273
3800
    help='A variant of 1.14 that supports rich-root data '
3274
3801
         '(needed for bzr-svn and bzr-git).',
3276
3803
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3277
3804
    )
3278
3805
# The following un-numbered 'development' formats should always just be aliases.
3279
 
register_metadir(controldir.format_registry, 'development-rich-root',
 
3806
format_registry.register_metadir('development-rich-root',
3280
3807
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3281
3808
    help='Current development format. Supports rich roots. Can convert data '
3282
3809
        'to and from rich-root-pack (and anything compatible with '
3283
3810
        'rich-root-pack) format repositories. Repositories and branches in '
3284
3811
        'this format can only be read by bzr.dev. Please read '
3285
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3812
        'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3286
3813
        'before use.',
3287
3814
    branch_format='bzrlib.branch.BzrBranchFormat7',
3288
3815
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3289
3816
    experimental=True,
3290
3817
    alias=True,
3291
 
    hidden=True,
3292
3818
    )
3293
 
register_metadir(controldir.format_registry, 'development-subtree',
 
3819
format_registry.register_metadir('development-subtree',
3294
3820
    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3295
3821
    help='Current development format, subtree variant. Can convert data to and '
3296
3822
        'from pack-0.92-subtree (and anything compatible with '
3297
3823
        'pack-0.92-subtree) format repositories. Repositories and branches in '
3298
3824
        'this format can only be read by bzr.dev. Please read '
3299
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3825
        'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3300
3826
        'before use.',
3301
3827
    branch_format='bzrlib.branch.BzrBranchFormat7',
3302
3828
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3303
3829
    experimental=True,
3304
 
    hidden=True,
3305
3830
    alias=False, # Restore to being an alias when an actual development subtree format is added
3306
3831
                 # This current non-alias status is simply because we did not introduce a
3307
3832
                 # chk based subtree format.
3308
3833
    )
3309
3834
 
3310
3835
# And the development formats above will have aliased one of the following:
3311
 
register_metadir(controldir.format_registry, 'development6-rich-root',
 
3836
format_registry.register_metadir('development6-rich-root',
3312
3837
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3313
3838
    help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3314
3839
        'Please read '
3315
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3840
        'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3316
3841
        'before use.',
3317
3842
    branch_format='bzrlib.branch.BzrBranchFormat7',
3318
3843
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3320
3845
    experimental=True,
3321
3846
    )
3322
3847
 
3323
 
register_metadir(controldir.format_registry, 'development7-rich-root',
 
3848
format_registry.register_metadir('development7-rich-root',
3324
3849
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3325
3850
    help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3326
3851
        'rich roots. Please read '
3327
 
        'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
 
3852
        'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3328
3853
        'before use.',
3329
3854
    branch_format='bzrlib.branch.BzrBranchFormat7',
3330
3855
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3332
3857
    experimental=True,
3333
3858
    )
3334
3859
 
3335
 
register_metadir(controldir.format_registry, '2a',
 
3860
format_registry.register_metadir('2a',
3336
3861
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3337
3862
    help='First format for bzr 2.0 series.\n'
3338
3863
        'Uses group-compress storage.\n'
3346
3871
 
3347
3872
# The following format should be an alias for the rich root equivalent 
3348
3873
# of the default format
3349
 
register_metadir(controldir.format_registry, 'default-rich-root',
 
3874
format_registry.register_metadir('default-rich-root',
3350
3875
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3351
3876
    branch_format='bzrlib.branch.BzrBranchFormat7',
3352
3877
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3353
3878
    alias=True,
3354
 
    hidden=True,
3355
3879
    help='Same as 2a.')
3356
3880
 
3357
3881
# The current format that is made on 'bzr init'.
3358
 
controldir.format_registry.set_default('2a')
3359
 
 
3360
 
# XXX 2010-08-20 JRV: There is still a lot of code relying on
3361
 
# bzrlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc
3362
 
# get changed to ControlDir.create/ControlDir.open/etc this should be removed.
3363
 
format_registry = controldir.format_registry
 
3882
format_registry.set_default('2a')