~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Martin Pool
  • Date: 2010-04-01 04:41:18 UTC
  • mto: This revision was merged to the branch mainline in revision 5128.
  • Revision ID: mbp@sourcefrog.net-20100401044118-shyctqc02ob08ngz
ignore .testrepository

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
from bzrlib.lazy_import import lazy_import
35
35
lazy_import(globals(), """
36
36
from stat import S_ISDIR
 
37
import textwrap
37
38
 
38
39
import bzrlib
39
40
from bzrlib import (
40
41
    branch,
41
42
    config,
42
 
    controldir,
43
43
    errors,
44
44
    graph,
45
45
    lockable_files,
88
88
    )
89
89
 
90
90
 
91
 
class BzrDir(controldir.ControlDir):
 
91
class BzrDir(object):
92
92
    """A .bzr control diretory.
93
93
 
94
94
    BzrDir instances let you create or open any of the things that can be
125
125
                    return
126
126
        thing_to_unlock.break_lock()
127
127
 
 
128
    def can_convert_format(self):
 
129
        """Return true if this bzrdir is one whose format we can convert from."""
 
130
        return True
 
131
 
128
132
    def check_conversion_target(self, target_format):
129
133
        """Check that a bzrdir as a whole can be converted to a new format."""
130
134
        # The only current restriction is that the repository content can be 
204
208
        """
205
209
        # Overview: put together a broad description of what we want to end up
206
210
        # with; then make as few api calls as possible to do it.
207
 
 
 
211
        
208
212
        # We may want to create a repo/branch/tree, if we do so what format
209
213
        # would we want for each:
210
214
        require_stacking = (stacked_on is not None)
211
215
        format = self.cloning_metadir(require_stacking)
212
 
 
 
216
        
213
217
        # Figure out what objects we want:
214
218
        try:
215
219
            local_repo = self.find_repository()
257
261
                # copied, and finally if we are copying up to a specific
258
262
                # revision_id then we can use the pending-ancestry-result which
259
263
                # 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
 
264
                if (result_repo.bzrdir.root_transport.base ==
 
265
                    result.root_transport.base and not require_stacking and
262
266
                    revision_id is not None):
263
267
                    fetch_spec = graph.PendingAncestryResult(
264
268
                        [revision_id], local_repo)
292
296
        t = get_transport(url)
293
297
        t.ensure_base()
294
298
 
 
299
    @classmethod
 
300
    def create(cls, base, format=None, possible_transports=None):
 
301
        """Create a new BzrDir at the url 'base'.
 
302
 
 
303
        :param format: If supplied, the format of branch to create.  If not
 
304
            supplied, the default is used.
 
305
        :param possible_transports: If supplied, a list of transports that
 
306
            can be reused to share a remote connection.
 
307
        """
 
308
        if cls is not BzrDir:
 
309
            raise AssertionError("BzrDir.create always creates the default"
 
310
                " format, not one of %r" % cls)
 
311
        t = get_transport(base, possible_transports)
 
312
        t.ensure_base()
 
313
        if format is None:
 
314
            format = BzrDirFormat.get_default_format()
 
315
        return format.initialize_on_transport(t)
 
316
 
295
317
    @staticmethod
296
318
    def find_bzrdirs(transport, evaluate=None, list_current=None):
297
319
        """Find bzrdirs recursively from current location.
320
342
            recurse = True
321
343
            try:
322
344
                bzrdir = BzrDir.open_from_transport(current_transport)
323
 
            except (errors.NotBranchError, errors.PermissionDenied):
 
345
            except errors.NotBranchError:
324
346
                pass
325
347
            else:
326
348
                recurse, value = evaluate(bzrdir)
327
349
                yield value
328
350
            try:
329
351
                subdirs = list_current(current_transport)
330
 
            except (errors.NoSuchFile, errors.PermissionDenied):
 
352
            except errors.NoSuchFile:
331
353
                continue
332
354
            if recurse:
333
355
                for subdir in sorted(subdirs, reverse=True):
334
356
                    pending.append(current_transport.clone(subdir))
335
357
 
 
358
    def list_branches(self):
 
359
        """Return a sequence of all branches local to this control directory.
 
360
 
 
361
        """
 
362
        try:
 
363
            return [self.open_branch()]
 
364
        except errors.NotBranchError:
 
365
            return []
 
366
 
336
367
    @staticmethod
337
368
    def find_branches(transport):
338
369
        """Find all branches under a transport.
361
392
                ret.extend(branches)
362
393
        return ret
363
394
 
 
395
    def destroy_repository(self):
 
396
        """Destroy the repository in this BzrDir"""
 
397
        raise NotImplementedError(self.destroy_repository)
 
398
 
 
399
    def create_branch(self, name=None):
 
400
        """Create a branch in this BzrDir.
 
401
 
 
402
        :param name: Name of the colocated branch to create, None for
 
403
            the default branch.
 
404
 
 
405
        The bzrdir's format will control what branch format is created.
 
406
        For more control see BranchFormatXX.create(a_bzrdir).
 
407
        """
 
408
        raise NotImplementedError(self.create_branch)
 
409
 
 
410
    def destroy_branch(self, name=None):
 
411
        """Destroy a branch in this BzrDir.
 
412
        
 
413
        :param name: Name of the branch to destroy, None for the default 
 
414
            branch.
 
415
        """
 
416
        raise NotImplementedError(self.destroy_branch)
 
417
 
364
418
    @staticmethod
365
419
    def create_branch_and_repo(base, force_new_repo=False, format=None):
366
420
        """Create a new BzrDir, Branch and Repository at the url 'base'.
404
458
            stop = False
405
459
            stack_on = config.get_default_stack_on()
406
460
            if stack_on is not None:
407
 
                stack_on_pwd = found_bzrdir.user_url
 
461
                stack_on_pwd = found_bzrdir.root_transport.base
408
462
                stop = True
409
463
            # does it have a repository ?
410
464
            try:
412
466
            except errors.NoRepositoryPresent:
413
467
                repository = None
414
468
            else:
415
 
                if (found_bzrdir.user_url != self.user_url 
416
 
                    and not repository.is_shared()):
 
469
                if ((found_bzrdir.root_transport.base !=
 
470
                     self.root_transport.base) and not repository.is_shared()):
417
471
                    # Don't look higher, can't use a higher shared repo.
418
472
                    repository = None
419
473
                    stop = True
515
569
                                               format=format).bzrdir
516
570
        return bzrdir.create_workingtree()
517
571
 
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
 
572
    def create_workingtree(self, revision_id=None, from_branch=None,
 
573
        accelerator_tree=None, hardlink=False):
 
574
        """Create a working tree at this BzrDir.
 
575
 
 
576
        :param revision_id: create it as of this revision id.
 
577
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
578
        :param accelerator_tree: A tree which can be used for retrieving file
 
579
            contents more quickly than the revision tree, i.e. a workingtree.
 
580
            The revision tree will be used for cases where accelerator_tree's
 
581
            content is different.
 
582
        """
 
583
        raise NotImplementedError(self.create_workingtree)
526
584
 
527
585
    def backup_bzrdir(self):
528
586
        """Backup this bzr control directory.
529
587
 
530
588
        :return: Tuple with old path name and new path name
531
589
        """
 
590
        def name_gen(base='backup.bzr'):
 
591
            counter = 1
 
592
            name = "%s.~%d~" % (base, counter)
 
593
            while self.root_transport.has(name):
 
594
                counter += 1
 
595
                name = "%s.~%d~" % (base, counter)
 
596
            return name
532
597
 
533
 
        backup_dir=self.generate_backup_name('backup.bzr')
 
598
        backup_dir=name_gen()
534
599
        pb = ui.ui_factory.nested_progress_bar()
535
600
        try:
536
601
            # FIXME: bug 300001 -- the backup fails if the backup directory
570
635
                else:
571
636
                    pass
572
637
 
 
638
    def destroy_workingtree(self):
 
639
        """Destroy the working tree at this BzrDir.
 
640
 
 
641
        Formats that do not support this may raise UnsupportedOperation.
 
642
        """
 
643
        raise NotImplementedError(self.destroy_workingtree)
 
644
 
 
645
    def destroy_workingtree_metadata(self):
 
646
        """Destroy the control files for the working tree at this BzrDir.
 
647
 
 
648
        The contents of working tree files are not affected.
 
649
        Formats that do not support this may raise UnsupportedOperation.
 
650
        """
 
651
        raise NotImplementedError(self.destroy_workingtree_metadata)
 
652
 
573
653
    def _find_containing(self, evaluate):
574
654
        """Find something in a containing control directory.
575
655
 
589
669
            if stop:
590
670
                return result
591
671
            next_transport = found_bzrdir.root_transport.clone('..')
592
 
            if (found_bzrdir.user_url == next_transport.base):
 
672
            if (found_bzrdir.root_transport.base == next_transport.base):
593
673
                # top of the file system
594
674
                return None
595
675
            # find the next containing bzrdir
612
692
                repository = found_bzrdir.open_repository()
613
693
            except errors.NoRepositoryPresent:
614
694
                return None, False
615
 
            if found_bzrdir.user_url == self.user_url:
 
695
            if found_bzrdir.root_transport.base == self.root_transport.base:
616
696
                return repository, True
617
697
            elif repository.is_shared():
618
698
                return repository, True
624
704
            raise errors.NoRepositoryPresent(self)
625
705
        return found_repo
626
706
 
 
707
    def get_branch_reference(self):
 
708
        """Return the referenced URL for the branch in this bzrdir.
 
709
 
 
710
        :raises NotBranchError: If there is no Branch.
 
711
        :return: The URL the branch in this bzrdir references if it is a
 
712
            reference branch, or None for regular branches.
 
713
        """
 
714
        return None
 
715
 
 
716
    def get_branch_transport(self, branch_format, name=None):
 
717
        """Get the transport for use by branch format in this BzrDir.
 
718
 
 
719
        Note that bzr dirs that do not support format strings will raise
 
720
        IncompatibleFormat if the branch format they are given has
 
721
        a format string, and vice versa.
 
722
 
 
723
        If branch_format is None, the transport is returned with no
 
724
        checking. If it is not None, then the returned transport is
 
725
        guaranteed to point to an existing directory ready for use.
 
726
        """
 
727
        raise NotImplementedError(self.get_branch_transport)
 
728
 
627
729
    def _find_creation_modes(self):
628
730
        """Determine the appropriate modes for files and directories.
629
731
 
668
770
            self._find_creation_modes()
669
771
        return self._dir_mode
670
772
 
 
773
    def get_repository_transport(self, repository_format):
 
774
        """Get the transport for use by repository format in this BzrDir.
 
775
 
 
776
        Note that bzr dirs that do not support format strings will raise
 
777
        IncompatibleFormat if the repository format they are given has
 
778
        a format string, and vice versa.
 
779
 
 
780
        If repository_format is None, the transport is returned with no
 
781
        checking. If it is not None, then the returned transport is
 
782
        guaranteed to point to an existing directory ready for use.
 
783
        """
 
784
        raise NotImplementedError(self.get_repository_transport)
 
785
 
 
786
    def get_workingtree_transport(self, tree_format):
 
787
        """Get the transport for use by workingtree format in this BzrDir.
 
788
 
 
789
        Note that bzr dirs that do not support format strings will raise
 
790
        IncompatibleFormat if the workingtree format they are given has a
 
791
        format string, and vice versa.
 
792
 
 
793
        If workingtree_format is None, the transport is returned with no
 
794
        checking. If it is not None, then the returned transport is
 
795
        guaranteed to point to an existing directory ready for use.
 
796
        """
 
797
        raise NotImplementedError(self.get_workingtree_transport)
 
798
 
671
799
    def get_config(self):
672
800
        """Get configuration for this BzrDir."""
673
801
        return config.BzrDirConfig(self)
686
814
        :param _transport: the transport this dir is based at.
687
815
        """
688
816
        self._format = _format
689
 
        # these are also under the more standard names of 
690
 
        # control_transport and user_transport
691
817
        self.transport = _transport.clone('.bzr')
692
818
        self.root_transport = _transport
693
819
        self._mode_check_done = False
694
820
 
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
821
    def is_control_filename(self, filename):
704
822
        """True if filename is the name of a path which is reserved for bzrdir's.
705
823
 
707
825
 
708
826
        This is true IF and ONLY IF the filename is part of the namespace reserved
709
827
        for bzr control dirs. Currently this is the '.bzr' directory in the root
710
 
        of the root_transport. 
 
828
        of the root_transport. it is expected that plugins will need to extend
 
829
        this in the future - for instance to make bzr talk with svn working
 
830
        trees.
711
831
        """
712
832
        # this might be better on the BzrDirFormat class because it refers to
713
833
        # all the possible bzrdir disk formats.
717
837
        # add new tests for it to the appropriate place.
718
838
        return filename == '.bzr' or filename.startswith('.bzr/')
719
839
 
 
840
    def needs_format_conversion(self, format=None):
 
841
        """Return true if this bzrdir needs convert_format run on it.
 
842
 
 
843
        For instance, if the repository format is out of date but the
 
844
        branch and working tree are not, this should return True.
 
845
 
 
846
        :param format: Optional parameter indicating a specific desired
 
847
                       format we plan to arrive at.
 
848
        """
 
849
        raise NotImplementedError(self.needs_format_conversion)
 
850
 
720
851
    @staticmethod
721
852
    def open_unsupported(base):
722
853
        """Open a branch which is not supported."""
745
876
        # the redirections.
746
877
        base = transport.base
747
878
        def find_format(transport):
748
 
            return transport, controldir.ControlDirFormat.find_format(
 
879
            return transport, BzrDirFormat.find_format(
749
880
                transport, _server_formats=_server_formats)
750
881
 
751
882
        def redirected(transport, e, redirection_notice):
766
897
        BzrDir._check_supported(format, _unsupported)
767
898
        return format.open(transport, _found=True)
768
899
 
 
900
    def open_branch(self, name=None, unsupported=False,
 
901
                    ignore_fallbacks=False):
 
902
        """Open the branch object at this BzrDir if one is present.
 
903
 
 
904
        If unsupported is True, then no longer supported branch formats can
 
905
        still be opened.
 
906
 
 
907
        TODO: static convenience version of this?
 
908
        """
 
909
        raise NotImplementedError(self.open_branch)
 
910
 
769
911
    @staticmethod
770
912
    def open_containing(url, possible_transports=None):
771
913
        """Open an existing branch which contains url.
809
951
                raise errors.NotBranchError(path=url)
810
952
            a_transport = new_t
811
953
 
 
954
    def _get_tree_branch(self):
 
955
        """Return the branch and tree, if any, for this bzrdir.
 
956
 
 
957
        Return None for tree if not present or inaccessible.
 
958
        Raise NotBranchError if no branch is present.
 
959
        :return: (tree, branch)
 
960
        """
 
961
        try:
 
962
            tree = self.open_workingtree()
 
963
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
964
            tree = None
 
965
            branch = self.open_branch()
 
966
        else:
 
967
            branch = tree.branch
 
968
        return tree, branch
 
969
 
812
970
    @classmethod
813
971
    def open_tree_or_branch(klass, location):
814
972
        """Return the branch and working tree at a location.
860
1018
                raise errors.NotBranchError(location)
861
1019
        return tree, branch, branch.repository, relpath
862
1020
 
 
1021
    def open_repository(self, _unsupported=False):
 
1022
        """Open the repository object at this BzrDir if one is present.
 
1023
 
 
1024
        This will not follow the Branch object pointer - it's strictly a direct
 
1025
        open facility. Most client code should use open_branch().repository to
 
1026
        get at a repository.
 
1027
 
 
1028
        :param _unsupported: a private parameter, not part of the api.
 
1029
        TODO: static convenience version of this?
 
1030
        """
 
1031
        raise NotImplementedError(self.open_repository)
 
1032
 
 
1033
    def open_workingtree(self, _unsupported=False,
 
1034
                         recommend_upgrade=True, from_branch=None):
 
1035
        """Open the workingtree object at this BzrDir if one is present.
 
1036
 
 
1037
        :param recommend_upgrade: Optional keyword parameter, when True (the
 
1038
            default), emit through the ui module a recommendation that the user
 
1039
            upgrade the working tree when the workingtree being opened is old
 
1040
            (but still fully supported).
 
1041
        :param from_branch: override bzrdir branch (for lightweight checkouts)
 
1042
        """
 
1043
        raise NotImplementedError(self.open_workingtree)
 
1044
 
 
1045
    def has_branch(self, name=None):
 
1046
        """Tell if this bzrdir contains a branch.
 
1047
 
 
1048
        Note: if you're going to open the branch, you should just go ahead
 
1049
        and try, and not ask permission first.  (This method just opens the
 
1050
        branch and discards it, and that's somewhat expensive.)
 
1051
        """
 
1052
        try:
 
1053
            self.open_branch(name)
 
1054
            return True
 
1055
        except errors.NotBranchError:
 
1056
            return False
 
1057
 
 
1058
    def has_workingtree(self):
 
1059
        """Tell if this bzrdir contains a working tree.
 
1060
 
 
1061
        This will still raise an exception if the bzrdir has a workingtree that
 
1062
        is remote & inaccessible.
 
1063
 
 
1064
        Note: if you're going to open the working tree, you should just go ahead
 
1065
        and try, and not ask permission first.  (This method just opens the
 
1066
        workingtree and discards it, and that's somewhat expensive.)
 
1067
        """
 
1068
        try:
 
1069
            self.open_workingtree(recommend_upgrade=False)
 
1070
            return True
 
1071
        except errors.NoWorkingTree:
 
1072
            return False
 
1073
 
863
1074
    def _cloning_metadir(self):
864
1075
        """Produce a metadir suitable for cloning with.
865
1076
 
923
1134
            format.require_stacking()
924
1135
        return format
925
1136
 
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.
 
1137
    def checkout_metadir(self):
 
1138
        return self.cloning_metadir()
 
1139
 
 
1140
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
1141
               recurse='down', possible_transports=None,
 
1142
               accelerator_tree=None, hardlink=False, stacked=False,
 
1143
               source_branch=None, create_tree_if_local=True):
 
1144
        """Create a copy of this bzrdir prepared for use as a new line of
 
1145
        development.
 
1146
 
 
1147
        If url's last component does not exist, it will be created.
 
1148
 
 
1149
        Attributes related to the identity of the source branch like
 
1150
        branch nickname will be cleaned, a working tree is created
 
1151
        whether one existed before or not; and a local branch is always
 
1152
        created.
 
1153
 
 
1154
        if revision_id is not None, then the clone operation may tune
 
1155
            itself to download less data.
 
1156
        :param accelerator_tree: A tree which can be used for retrieving file
 
1157
            contents more quickly than the revision tree, i.e. a workingtree.
 
1158
            The revision tree will be used for cases where accelerator_tree's
 
1159
            content is different.
 
1160
        :param hardlink: If true, hard-link files from accelerator_tree,
 
1161
            where possible.
 
1162
        :param stacked: If true, create a stacked branch referring to the
 
1163
            location of this control directory.
 
1164
        :param create_tree_if_local: If true, a working-tree will be created
 
1165
            when working locally.
934
1166
        """
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
 
 
 
1167
        target_transport = get_transport(url, possible_transports)
 
1168
        target_transport.ensure_base()
 
1169
        cloning_format = self.cloning_metadir(stacked)
 
1170
        # Create/update the result branch
 
1171
        result = cloning_format.initialize_on_transport(target_transport)
 
1172
        # if a stacked branch wasn't requested, we don't create one
 
1173
        # even if the origin was stacked
 
1174
        stacked_branch_url = None
 
1175
        if source_branch is not None:
 
1176
            if stacked:
 
1177
                stacked_branch_url = self.root_transport.base
 
1178
            source_repository = source_branch.repository
 
1179
        else:
 
1180
            try:
 
1181
                source_branch = self.open_branch()
 
1182
                source_repository = source_branch.repository
 
1183
                if stacked:
 
1184
                    stacked_branch_url = self.root_transport.base
 
1185
            except errors.NotBranchError:
 
1186
                source_branch = None
 
1187
                try:
 
1188
                    source_repository = self.open_repository()
 
1189
                except errors.NoRepositoryPresent:
 
1190
                    source_repository = None
 
1191
        repository_policy = result.determine_repository_policy(
 
1192
            force_new_repo, stacked_branch_url, require_stacking=stacked)
 
1193
        result_repo, is_new_repo = repository_policy.acquire_repository()
 
1194
        if is_new_repo and revision_id is not None and not stacked:
 
1195
            fetch_spec = graph.PendingAncestryResult(
 
1196
                [revision_id], source_repository)
 
1197
        else:
 
1198
            fetch_spec = None
 
1199
        if source_repository is not None:
 
1200
            # Fetch while stacked to prevent unstacked fetch from
 
1201
            # Branch.sprout.
 
1202
            if fetch_spec is None:
 
1203
                result_repo.fetch(source_repository, revision_id=revision_id)
 
1204
            else:
 
1205
                result_repo.fetch(source_repository, fetch_spec=fetch_spec)
 
1206
 
 
1207
        if source_branch is None:
 
1208
            # this is for sprouting a bzrdir without a branch; is that
 
1209
            # actually useful?
 
1210
            # Not especially, but it's part of the contract.
 
1211
            result_branch = result.create_branch()
 
1212
        else:
 
1213
            result_branch = source_branch.sprout(result,
 
1214
                revision_id=revision_id, repository_policy=repository_policy)
 
1215
        mutter("created new branch %r" % (result_branch,))
 
1216
 
 
1217
        # Create/update the result working tree
 
1218
        if (create_tree_if_local and
 
1219
            isinstance(target_transport, local.LocalTransport) and
 
1220
            (result_repo is None or result_repo.make_working_trees())):
 
1221
            wt = result.create_workingtree(accelerator_tree=accelerator_tree,
 
1222
                hardlink=hardlink)
 
1223
            wt.lock_write()
 
1224
            try:
 
1225
                if wt.path2id('') is None:
 
1226
                    try:
 
1227
                        wt.set_root_id(self.open_workingtree.get_root_id())
 
1228
                    except errors.NoWorkingTree:
 
1229
                        pass
 
1230
            finally:
 
1231
                wt.unlock()
 
1232
        else:
 
1233
            wt = None
 
1234
        if recurse == 'down':
 
1235
            if wt is not None:
 
1236
                basis = wt.basis_tree()
 
1237
                basis.lock_read()
 
1238
                subtrees = basis.iter_references()
 
1239
            elif result_branch is not None:
 
1240
                basis = result_branch.basis_tree()
 
1241
                basis.lock_read()
 
1242
                subtrees = basis.iter_references()
 
1243
            elif source_branch is not None:
 
1244
                basis = source_branch.basis_tree()
 
1245
                basis.lock_read()
 
1246
                subtrees = basis.iter_references()
 
1247
            else:
 
1248
                subtrees = []
 
1249
                basis = None
 
1250
            try:
 
1251
                for path, file_id in subtrees:
 
1252
                    target = urlutils.join(url, urlutils.escape(path))
 
1253
                    sublocation = source_branch.reference_parent(file_id, path)
 
1254
                    sublocation.bzrdir.sprout(target,
 
1255
                        basis.get_reference_revision(file_id, path),
 
1256
                        force_new_repo=force_new_repo, recurse=recurse,
 
1257
                        stacked=stacked)
 
1258
            finally:
 
1259
                if basis is not None:
 
1260
                    basis.unlock()
 
1261
        return result
 
1262
 
 
1263
    def push_branch(self, source, revision_id=None, overwrite=False, 
 
1264
        remember=False, create_prefix=False):
 
1265
        """Push the source branch into this BzrDir."""
 
1266
        br_to = None
 
1267
        # If we can open a branch, use its direct repository, otherwise see
 
1268
        # if there is a repository without a branch.
 
1269
        try:
 
1270
            br_to = self.open_branch()
 
1271
        except errors.NotBranchError:
 
1272
            # Didn't find a branch, can we find a repository?
 
1273
            repository_to = self.find_repository()
 
1274
        else:
 
1275
            # Found a branch, so we must have found a repository
 
1276
            repository_to = br_to.repository
 
1277
 
 
1278
        push_result = PushResult()
 
1279
        push_result.source_branch = source
 
1280
        if br_to is None:
 
1281
            # We have a repository but no branch, copy the revisions, and then
 
1282
            # create a branch.
 
1283
            repository_to.fetch(source.repository, revision_id=revision_id)
 
1284
            br_to = source.clone(self, revision_id=revision_id)
 
1285
            if source.get_push_location() is None or remember:
 
1286
                source.set_push_location(br_to.base)
 
1287
            push_result.stacked_on = None
 
1288
            push_result.branch_push_result = None
 
1289
            push_result.old_revno = None
 
1290
            push_result.old_revid = _mod_revision.NULL_REVISION
 
1291
            push_result.target_branch = br_to
 
1292
            push_result.master_branch = None
 
1293
            push_result.workingtree_updated = False
 
1294
        else:
 
1295
            # We have successfully opened the branch, remember if necessary:
 
1296
            if source.get_push_location() is None or remember:
 
1297
                source.set_push_location(br_to.base)
 
1298
            try:
 
1299
                tree_to = self.open_workingtree()
 
1300
            except errors.NotLocalUrl:
 
1301
                push_result.branch_push_result = source.push(br_to, 
 
1302
                    overwrite, stop_revision=revision_id)
 
1303
                push_result.workingtree_updated = False
 
1304
            except errors.NoWorkingTree:
 
1305
                push_result.branch_push_result = source.push(br_to,
 
1306
                    overwrite, stop_revision=revision_id)
 
1307
                push_result.workingtree_updated = None # Not applicable
 
1308
            else:
 
1309
                tree_to.lock_write()
 
1310
                try:
 
1311
                    push_result.branch_push_result = source.push(
 
1312
                        tree_to.branch, overwrite, stop_revision=revision_id)
 
1313
                    tree_to.update()
 
1314
                finally:
 
1315
                    tree_to.unlock()
 
1316
                push_result.workingtree_updated = True
 
1317
            push_result.old_revno = push_result.branch_push_result.old_revno
 
1318
            push_result.old_revid = push_result.branch_push_result.old_revid
 
1319
            push_result.target_branch = \
 
1320
                push_result.branch_push_result.target_branch
 
1321
        return push_result
944
1322
 
945
1323
 
946
1324
class BzrDirHooks(hooks.Hooks):
952
1330
        self.create_hook(hooks.HookPoint('pre_open',
953
1331
            "Invoked before attempting to open a BzrDir with the transport "
954
1332
            "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
1333
 
961
1334
# install the default hooks
962
1335
BzrDir.hooks = BzrDirHooks()
963
1336
 
964
1337
 
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
1338
class BzrDirPreSplitOut(BzrDir):
1002
1339
    """A common class for the all-in-one formats."""
1003
1340
 
1016
1353
    def cloning_metadir(self, require_stacking=False):
1017
1354
        """Produce a metadir suitable for cloning with."""
1018
1355
        if require_stacking:
1019
 
            return controldir.format_registry.make_bzrdir('1.6')
 
1356
            return format_registry.make_bzrdir('1.6')
1020
1357
        return self._format.__class__()
1021
1358
 
1022
1359
    def clone(self, url, revision_id=None, force_new_repo=False,
1315
1652
    def destroy_workingtree_metadata(self):
1316
1653
        self.transport.delete_tree('checkout')
1317
1654
 
1318
 
    def find_branch_format(self, name=None):
 
1655
    def find_branch_format(self):
1319
1656
        """Find the branch 'format' for this bzrdir.
1320
1657
 
1321
1658
        This might be a synthetic object for e.g. RemoteBranch and SVN.
1322
1659
        """
1323
1660
        from bzrlib.branch import BranchFormat
1324
 
        return BranchFormat.find_format(self, name=name)
 
1661
        return BranchFormat.find_format(self)
1325
1662
 
1326
1663
    def _get_mkdir_mode(self):
1327
1664
        """Figure out the mode to use when creating a bzrdir subdir."""
1329
1666
                                     lockable_files.TransportLock)
1330
1667
        return temp_control._dir_mode
1331
1668
 
1332
 
    def get_branch_reference(self, name=None):
 
1669
    def get_branch_reference(self):
1333
1670
        """See BzrDir.get_branch_reference()."""
1334
1671
        from bzrlib.branch import BranchFormat
1335
 
        format = BranchFormat.find_format(self, name=name)
1336
 
        return format.get_reference(self, name=name)
 
1672
        format = BranchFormat.find_format(self)
 
1673
        return format.get_reference(self)
1337
1674
 
1338
1675
    def get_branch_transport(self, branch_format, name=None):
1339
1676
        """See BzrDir.get_branch_transport()."""
1433
1770
    def open_branch(self, name=None, unsupported=False,
1434
1771
                    ignore_fallbacks=False):
1435
1772
        """See BzrDir.open_branch."""
1436
 
        format = self.find_branch_format(name=name)
 
1773
        format = self.find_branch_format()
1437
1774
        self._check_supported(format, unsupported)
1438
1775
        return format.open(self, name=name,
1439
1776
            _found=True, ignore_fallbacks=ignore_fallbacks)
1459
1796
        return config.TransportConfig(self.transport, 'control.conf')
1460
1797
 
1461
1798
 
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.
 
1799
class BzrDirFormat(object):
 
1800
    """An encapsulation of the initialization and open routines for a format.
 
1801
 
 
1802
    Formats provide three things:
 
1803
     * An initialization routine,
 
1804
     * a format string,
 
1805
     * an open routine.
1522
1806
 
1523
1807
    Formats are placed in a dict by their format string for reference
1524
1808
    during bzrdir opening. These should be subclasses of BzrDirFormat
1527
1811
    Once a format is deprecated, just deprecate the initialize and open
1528
1812
    methods on the format class. Do not deprecate the object, as the
1529
1813
    object will be created every system load.
 
1814
 
 
1815
    :cvar colocated_branches: Whether this formats supports colocated branches.
 
1816
    """
 
1817
 
 
1818
    _default_format = None
 
1819
    """The default format used for new .bzr dirs."""
 
1820
 
 
1821
    _formats = {}
 
1822
    """The known formats."""
 
1823
 
 
1824
    _control_formats = []
 
1825
    """The registered control formats - .bzr, ....
 
1826
 
 
1827
    This is a list of BzrDirFormat objects.
 
1828
    """
 
1829
 
 
1830
    _control_server_formats = []
 
1831
    """The registered control server formats, e.g. RemoteBzrDirs.
 
1832
 
 
1833
    This is a list of BzrDirFormat objects.
1530
1834
    """
1531
1835
 
1532
1836
    _lock_file_name = 'branch-lock'
1533
1837
 
 
1838
    colocated_branches = False
 
1839
    """Whether co-located branches are supported for this control dir format.
 
1840
    """
 
1841
 
1534
1842
    # _lock_class must be set in subclasses to the lock type, typ.
1535
1843
    # TransportLock or LockDir
1536
1844
 
 
1845
    @classmethod
 
1846
    def find_format(klass, transport, _server_formats=True):
 
1847
        """Return the format present at transport."""
 
1848
        if _server_formats:
 
1849
            formats = klass._control_server_formats + klass._control_formats
 
1850
        else:
 
1851
            formats = klass._control_formats
 
1852
        for format in formats:
 
1853
            try:
 
1854
                return format.probe_transport(transport)
 
1855
            except errors.NotBranchError:
 
1856
                # this format does not find a control dir here.
 
1857
                pass
 
1858
        raise errors.NotBranchError(path=transport.base)
 
1859
 
 
1860
    @classmethod
 
1861
    def probe_transport(klass, transport):
 
1862
        """Return the .bzrdir style format present in a directory."""
 
1863
        try:
 
1864
            format_string = transport.get_bytes(".bzr/branch-format")
 
1865
        except errors.NoSuchFile:
 
1866
            raise errors.NotBranchError(path=transport.base)
 
1867
 
 
1868
        try:
 
1869
            return klass._formats[format_string]
 
1870
        except KeyError:
 
1871
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
 
1872
 
 
1873
    @classmethod
 
1874
    def get_default_format(klass):
 
1875
        """Return the current default format."""
 
1876
        return klass._default_format
 
1877
 
1537
1878
    def get_format_string(self):
1538
1879
        """Return the ASCII format string that identifies this format."""
1539
1880
        raise NotImplementedError(self.get_format_string)
1540
1881
 
 
1882
    def get_format_description(self):
 
1883
        """Return the short description for this format."""
 
1884
        raise NotImplementedError(self.get_format_description)
 
1885
 
 
1886
    def get_converter(self, format=None):
 
1887
        """Return the converter to use to convert bzrdirs needing converts.
 
1888
 
 
1889
        This returns a bzrlib.bzrdir.Converter object.
 
1890
 
 
1891
        This should return the best upgrader to step this format towards the
 
1892
        current default format. In the case of plugins we can/should provide
 
1893
        some means for them to extend the range of returnable converters.
 
1894
 
 
1895
        :param format: Optional format to override the default format of the
 
1896
                       library.
 
1897
        """
 
1898
        raise NotImplementedError(self.get_converter)
 
1899
 
 
1900
    def initialize(self, url, possible_transports=None):
 
1901
        """Create a bzr control dir at this url and return an opened copy.
 
1902
 
 
1903
        While not deprecated, this method is very specific and its use will
 
1904
        lead to many round trips to setup a working environment. See
 
1905
        initialize_on_transport_ex for a [nearly] all-in-one method.
 
1906
 
 
1907
        Subclasses should typically override initialize_on_transport
 
1908
        instead of this method.
 
1909
        """
 
1910
        return self.initialize_on_transport(get_transport(url,
 
1911
                                                          possible_transports))
 
1912
 
1541
1913
    def initialize_on_transport(self, transport):
1542
1914
        """Initialize a new bzrdir in the base directory of a Transport."""
1543
1915
        try:
1691
2063
            control_files.unlock()
1692
2064
        return self.open(transport, _found=True)
1693
2065
 
 
2066
    def is_supported(self):
 
2067
        """Is this format supported?
 
2068
 
 
2069
        Supported formats must be initializable and openable.
 
2070
        Unsupported formats may not support initialization or committing or
 
2071
        some other features depending on the reason for not being supported.
 
2072
        """
 
2073
        return True
 
2074
 
 
2075
    def network_name(self):
 
2076
        """A simple byte string uniquely identifying this format for RPC calls.
 
2077
 
 
2078
        Bzr control formats use thir disk format string to identify the format
 
2079
        over the wire. Its possible that other control formats have more
 
2080
        complex detection requirements, so we permit them to use any unique and
 
2081
        immutable string they desire.
 
2082
        """
 
2083
        raise NotImplementedError(self.network_name)
 
2084
 
 
2085
    def same_model(self, target_format):
 
2086
        return (self.repository_format.rich_root_data ==
 
2087
            target_format.rich_root_data)
 
2088
 
 
2089
    @classmethod
 
2090
    def known_formats(klass):
 
2091
        """Return all the known formats.
 
2092
 
 
2093
        Concrete formats should override _known_formats.
 
2094
        """
 
2095
        # There is double indirection here to make sure that control
 
2096
        # formats used by more than one dir format will only be probed
 
2097
        # once. This can otherwise be quite expensive for remote connections.
 
2098
        result = set()
 
2099
        for format in klass._control_formats:
 
2100
            result.update(format._known_formats())
 
2101
        return result
 
2102
 
 
2103
    @classmethod
 
2104
    def _known_formats(klass):
 
2105
        """Return the known format instances for this control format."""
 
2106
        return set(klass._formats.values())
 
2107
 
1694
2108
    def open(self, transport, _found=False):
1695
2109
        """Return an instance of this format for the dir transport points at.
1696
2110
 
1697
2111
        _found is a private parameter, do not use it.
1698
2112
        """
1699
2113
        if not _found:
1700
 
            found_format = controldir.ControlDirFormat.find_format(transport)
 
2114
            found_format = BzrDirFormat.find_format(transport)
1701
2115
            if not isinstance(found_format, self.__class__):
1702
2116
                raise AssertionError("%s was asked to open %s, but it seems to need "
1703
2117
                        "format %s"
1717
2131
 
1718
2132
    @classmethod
1719
2133
    def register_format(klass, format):
1720
 
        BzrProber.register_bzrdir_format(format)
 
2134
        klass._formats[format.get_format_string()] = format
1721
2135
        # bzr native formats have a network name of their format string.
1722
2136
        network_format_registry.register(format.get_format_string(), format.__class__)
1723
 
        controldir.ControlDirFormat.register_format(format)
 
2137
 
 
2138
    @classmethod
 
2139
    def register_control_format(klass, format):
 
2140
        """Register a format that does not use '.bzr' for its control dir.
 
2141
 
 
2142
        TODO: This should be pulled up into a 'ControlDirFormat' base class
 
2143
        which BzrDirFormat can inherit from, and renamed to register_format
 
2144
        there. It has been done without that for now for simplicity of
 
2145
        implementation.
 
2146
        """
 
2147
        klass._control_formats.append(format)
 
2148
 
 
2149
    @classmethod
 
2150
    def register_control_server_format(klass, format):
 
2151
        """Register a control format for client-server environments.
 
2152
 
 
2153
        These formats will be tried before ones registered with
 
2154
        register_control_format.  This gives implementations that decide to the
 
2155
        chance to grab it before anything looks at the contents of the format
 
2156
        file.
 
2157
        """
 
2158
        klass._control_server_formats.append(format)
 
2159
 
 
2160
    @classmethod
 
2161
    def _set_default_format(klass, format):
 
2162
        """Set default format (for testing behavior of defaults only)"""
 
2163
        klass._default_format = format
 
2164
 
 
2165
    def __str__(self):
 
2166
        # Trim the newline
 
2167
        return self.get_format_description().rstrip()
1724
2168
 
1725
2169
    def _supply_sub_formats_to(self, other_format):
1726
2170
        """Give other_format the same values for sub formats as this has.
1736
2180
 
1737
2181
    @classmethod
1738
2182
    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())
 
2183
        del klass._formats[format.get_format_string()]
 
2184
 
 
2185
    @classmethod
 
2186
    def unregister_control_format(klass, format):
 
2187
        klass._control_formats.remove(format)
1742
2188
 
1743
2189
 
1744
2190
class BzrDirFormat4(BzrDirFormat):
2156
2602
"""
2157
2603
 
2158
2604
 
 
2605
# Register bzr control format
 
2606
BzrDirFormat.register_control_format(BzrDirFormat)
 
2607
 
2159
2608
# Register bzr formats
2160
2609
BzrDirFormat.register_format(BzrDirFormat4())
2161
2610
BzrDirFormat.register_format(BzrDirFormat5())
2162
2611
BzrDirFormat.register_format(BzrDirFormat6())
2163
2612
__default_format = BzrDirMetaFormat1()
2164
2613
BzrDirFormat.register_format(__default_format)
2165
 
controldir.ControlDirFormat._default_format = __default_format
 
2614
BzrDirFormat._default_format = __default_format
2166
2615
 
2167
2616
 
2168
2617
class Converter(object):
2202
2651
            if isinstance(self.bzrdir.transport, local.LocalTransport):
2203
2652
                self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2204
2653
            self._convert_to_weaves()
2205
 
            return BzrDir.open(self.bzrdir.user_url)
 
2654
            return BzrDir.open(self.bzrdir.root_transport.base)
2206
2655
        finally:
2207
2656
            self.pb.finished()
2208
2657
 
2330
2779
            self.revisions[rev_id] = rev
2331
2780
 
2332
2781
    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()
 
2782
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2338
2783
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2339
2784
        inv.revision_id = rev_id
2340
2785
        rev = self.revisions[rev_id]
2396
2841
        previous_entries = dict((head, parent_candiate_entries[head]) for head
2397
2842
            in heads)
2398
2843
        self.snapshot_ie(previous_entries, ie, w, rev_id)
 
2844
        del ie.text_id
2399
2845
 
2400
2846
    def get_parent_map(self, revision_ids):
2401
2847
        """See graph.StackedParentsProvider.get_parent_map"""
2417
2863
                ie.revision = previous_ie.revision
2418
2864
                return
2419
2865
        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()
 
2866
            text = self.branch.repository._text_store.get(ie.text_id)
 
2867
            file_lines = text.readlines()
2425
2868
            w.add_lines(rev_id, previous_revisions, file_lines)
2426
2869
            self.text_count += 1
2427
2870
        else:
2461
2904
        try:
2462
2905
            ui.ui_factory.note('starting upgrade from format 5 to 6')
2463
2906
            self._convert_to_prefixed()
2464
 
            return BzrDir.open(self.bzrdir.user_url)
 
2907
            return BzrDir.open(self.bzrdir.root_transport.base)
2465
2908
        finally:
2466
2909
            pb.finished()
2467
2910
 
2589
3032
            BzrDirMetaFormat1().get_format_string(),
2590
3033
            mode=self.file_mode)
2591
3034
        self.pb.finished()
2592
 
        return BzrDir.open(self.bzrdir.user_url)
 
3035
        return BzrDir.open(self.bzrdir.root_transport.base)
2593
3036
 
2594
3037
    def make_lock(self, name):
2595
3038
        """Make a lock for the new control dir name."""
2708
3151
        # XXX: It's a bit ugly that the network name is here, because we'd
2709
3152
        # like to believe that format objects are stateless or at least
2710
3153
        # immutable,  However, we do at least avoid mutating the name after
2711
 
        # it's returned.  See <https://bugs.launchpad.net/bzr/+bug/504102>
 
3154
        # it's returned.  See <https://bugs.edge.launchpad.net/bzr/+bug/504102>
2712
3155
        self._network_name = None
2713
3156
 
2714
3157
    def __repr__(self):
2730
3173
        else:
2731
3174
            raise AssertionError("No network name set.")
2732
3175
 
 
3176
    @classmethod
 
3177
    def probe_transport(klass, transport):
 
3178
        """Return a RemoteBzrDirFormat object if it looks possible."""
 
3179
        try:
 
3180
            medium = transport.get_smart_medium()
 
3181
        except (NotImplementedError, AttributeError,
 
3182
                errors.TransportNotPossible, errors.NoSmartMedium,
 
3183
                errors.SmartProtocolError):
 
3184
            # no smart server, so not a branch for this format type.
 
3185
            raise errors.NotBranchError(path=transport.base)
 
3186
        else:
 
3187
            # Decline to open it if the server doesn't support our required
 
3188
            # version (3) so that the VFS-based transport will do it.
 
3189
            if medium.should_probe():
 
3190
                try:
 
3191
                    server_version = medium.protocol_version()
 
3192
                except errors.SmartProtocolError:
 
3193
                    # Apparently there's no usable smart server there, even though
 
3194
                    # the medium supports the smart protocol.
 
3195
                    raise errors.NotBranchError(path=transport.base)
 
3196
                if server_version != '2':
 
3197
                    raise errors.NotBranchError(path=transport.base)
 
3198
            return klass()
 
3199
 
2733
3200
    def initialize_on_transport(self, transport):
2734
3201
        try:
2735
3202
            # hand off the request to the smart server
2934
3401
        BzrDirMetaFormat1._set_repository_format) #.im_func)
2935
3402
 
2936
3403
 
2937
 
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
 
3404
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
 
3405
 
 
3406
 
 
3407
class BzrDirFormatInfo(object):
 
3408
 
 
3409
    def __init__(self, native, deprecated, hidden, experimental):
 
3410
        self.deprecated = deprecated
 
3411
        self.native = native
 
3412
        self.hidden = hidden
 
3413
        self.experimental = experimental
 
3414
 
 
3415
 
 
3416
class BzrDirFormatRegistry(registry.Registry):
 
3417
    """Registry of user-selectable BzrDir subformats.
 
3418
 
 
3419
    Differs from BzrDirFormat._control_formats in that it provides sub-formats,
 
3420
    e.g. BzrDirMeta1 with weave repository.  Also, it's more user-oriented.
 
3421
    """
 
3422
 
 
3423
    def __init__(self):
 
3424
        """Create a BzrDirFormatRegistry."""
 
3425
        self._aliases = set()
 
3426
        self._registration_order = list()
 
3427
        super(BzrDirFormatRegistry, self).__init__()
 
3428
 
 
3429
    def aliases(self):
 
3430
        """Return a set of the format names which are aliases."""
 
3431
        return frozenset(self._aliases)
 
3432
 
 
3433
    def register_metadir(self, key,
 
3434
             repository_format, help, native=True, deprecated=False,
 
3435
             branch_format=None,
 
3436
             tree_format=None,
 
3437
             hidden=False,
 
3438
             experimental=False,
 
3439
             alias=False):
 
3440
        """Register a metadir subformat.
 
3441
 
 
3442
        These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
 
3443
        by the Repository/Branch/WorkingTreeformats.
 
3444
 
 
3445
        :param repository_format: The fully-qualified repository format class
 
3446
            name as a string.
 
3447
        :param branch_format: Fully-qualified branch format class name as
 
3448
            a string.
 
3449
        :param tree_format: Fully-qualified tree format class name as
 
3450
            a string.
 
3451
        """
 
3452
        # This should be expanded to support setting WorkingTree and Branch
 
3453
        # formats, once BzrDirMetaFormat1 supports that.
 
3454
        def _load(full_name):
 
3455
            mod_name, factory_name = full_name.rsplit('.', 1)
 
3456
            try:
 
3457
                mod = __import__(mod_name, globals(), locals(),
 
3458
                        [factory_name])
 
3459
            except ImportError, e:
 
3460
                raise ImportError('failed to load %s: %s' % (full_name, e))
 
3461
            try:
 
3462
                factory = getattr(mod, factory_name)
 
3463
            except AttributeError:
 
3464
                raise AttributeError('no factory %s in module %r'
 
3465
                    % (full_name, mod))
 
3466
            return factory()
 
3467
 
 
3468
        def helper():
 
3469
            bd = BzrDirMetaFormat1()
 
3470
            if branch_format is not None:
 
3471
                bd.set_branch_format(_load(branch_format))
 
3472
            if tree_format is not None:
 
3473
                bd.workingtree_format = _load(tree_format)
 
3474
            if repository_format is not None:
 
3475
                bd.repository_format = _load(repository_format)
 
3476
            return bd
 
3477
        self.register(key, helper, help, native, deprecated, hidden,
 
3478
            experimental, alias)
 
3479
 
 
3480
    def register(self, key, factory, help, native=True, deprecated=False,
 
3481
                 hidden=False, experimental=False, alias=False):
 
3482
        """Register a BzrDirFormat factory.
 
3483
 
 
3484
        The factory must be a callable that takes one parameter: the key.
 
3485
        It must produce an instance of the BzrDirFormat when called.
 
3486
 
 
3487
        This function mainly exists to prevent the info object from being
 
3488
        supplied directly.
 
3489
        """
 
3490
        registry.Registry.register(self, key, factory, help,
 
3491
            BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3492
        if alias:
 
3493
            self._aliases.add(key)
 
3494
        self._registration_order.append(key)
 
3495
 
 
3496
    def register_lazy(self, key, module_name, member_name, help, native=True,
 
3497
        deprecated=False, hidden=False, experimental=False, alias=False):
 
3498
        registry.Registry.register_lazy(self, key, module_name, member_name,
 
3499
            help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
 
3500
        if alias:
 
3501
            self._aliases.add(key)
 
3502
        self._registration_order.append(key)
 
3503
 
 
3504
    def set_default(self, key):
 
3505
        """Set the 'default' key to be a clone of the supplied key.
 
3506
 
 
3507
        This method must be called once and only once.
 
3508
        """
 
3509
        registry.Registry.register(self, 'default', self.get(key),
 
3510
            self.get_help(key), info=self.get_info(key))
 
3511
        self._aliases.add('default')
 
3512
 
 
3513
    def set_default_repository(self, key):
 
3514
        """Set the FormatRegistry default and Repository default.
 
3515
 
 
3516
        This is a transitional method while Repository.set_default_format
 
3517
        is deprecated.
 
3518
        """
 
3519
        if 'default' in self:
 
3520
            self.remove('default')
 
3521
        self.set_default(key)
 
3522
        format = self.get('default')()
 
3523
 
 
3524
    def make_bzrdir(self, key):
 
3525
        return self.get(key)()
 
3526
 
 
3527
    def help_topic(self, topic):
 
3528
        output = ""
 
3529
        default_realkey = None
 
3530
        default_help = self.get_help('default')
 
3531
        help_pairs = []
 
3532
        for key in self._registration_order:
 
3533
            if key == 'default':
 
3534
                continue
 
3535
            help = self.get_help(key)
 
3536
            if help == default_help:
 
3537
                default_realkey = key
 
3538
            else:
 
3539
                help_pairs.append((key, help))
 
3540
 
 
3541
        def wrapped(key, help, info):
 
3542
            if info.native:
 
3543
                help = '(native) ' + help
 
3544
            return ':%s:\n%s\n\n' % (key,
 
3545
                textwrap.fill(help, initial_indent='    ',
 
3546
                    subsequent_indent='    ',
 
3547
                    break_long_words=False))
 
3548
        if default_realkey is not None:
 
3549
            output += wrapped(default_realkey, '(default) %s' % default_help,
 
3550
                              self.get_info('default'))
 
3551
        deprecated_pairs = []
 
3552
        experimental_pairs = []
 
3553
        for key, help in help_pairs:
 
3554
            info = self.get_info(key)
 
3555
            if info.hidden:
 
3556
                continue
 
3557
            elif info.deprecated:
 
3558
                deprecated_pairs.append((key, help))
 
3559
            elif info.experimental:
 
3560
                experimental_pairs.append((key, help))
 
3561
            else:
 
3562
                output += wrapped(key, help, info)
 
3563
        output += "\nSee :doc:`formats-help` for more about storage formats."
 
3564
        other_output = ""
 
3565
        if len(experimental_pairs) > 0:
 
3566
            other_output += "Experimental formats are shown below.\n\n"
 
3567
            for key, help in experimental_pairs:
 
3568
                info = self.get_info(key)
 
3569
                other_output += wrapped(key, help, info)
 
3570
        else:
 
3571
            other_output += \
 
3572
                "No experimental formats are available.\n\n"
 
3573
        if len(deprecated_pairs) > 0:
 
3574
            other_output += "\nDeprecated formats are shown below.\n\n"
 
3575
            for key, help in deprecated_pairs:
 
3576
                info = self.get_info(key)
 
3577
                other_output += wrapped(key, help, info)
 
3578
        else:
 
3579
            other_output += \
 
3580
                "\nNo deprecated formats are available.\n\n"
 
3581
        other_output += \
 
3582
                "\nSee :doc:`formats-help` for more about storage formats."
 
3583
 
 
3584
        if topic == 'other-formats':
 
3585
            return other_output
 
3586
        else:
 
3587
            return output
2938
3588
 
2939
3589
 
2940
3590
class RepositoryAcquisitionPolicy(object):
2969
3619
            try:
2970
3620
                stack_on = urlutils.rebase_url(self._stack_on,
2971
3621
                    self._stack_on_pwd,
2972
 
                    branch.user_url)
 
3622
                    branch.bzrdir.root_transport.base)
2973
3623
            except errors.InvalidRebaseURLs:
2974
3624
                stack_on = self._get_full_stack_on()
2975
3625
        try:
3094
3744
        return self._repository, False
3095
3745
 
3096
3746
 
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
 
 
 
3747
# Please register new formats after old formats so that formats
 
3748
# appear in chronological order and format descriptions can build
 
3749
# on previous ones.
 
3750
format_registry = BzrDirFormatRegistry()
3144
3751
# The pre-0.8 formats have their repository format network name registered in
3145
3752
# repository.py. MetaDir formats have their repository format network name
3146
3753
# inferred from their disk format string.
3147
 
controldir.format_registry.register('weave', BzrDirFormat6,
 
3754
format_registry.register('weave', BzrDirFormat6,
3148
3755
    'Pre-0.8 format.  Slower than knit and does not'
3149
3756
    ' support checkouts or shared repositories.',
3150
3757
    hidden=True,
3151
3758
    deprecated=True)
3152
 
register_metadir(controldir.format_registry, 'metaweave',
 
3759
format_registry.register_metadir('metaweave',
3153
3760
    'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3154
3761
    'Transitional format in 0.8.  Slower than knit.',
3155
3762
    branch_format='bzrlib.branch.BzrBranchFormat5',
3156
3763
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3157
3764
    hidden=True,
3158
3765
    deprecated=True)
3159
 
register_metadir(controldir.format_registry, 'knit',
 
3766
format_registry.register_metadir('knit',
3160
3767
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3161
3768
    'Format using knits.  Recommended for interoperation with bzr <= 0.14.',
3162
3769
    branch_format='bzrlib.branch.BzrBranchFormat5',
3163
3770
    tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3164
3771
    hidden=True,
3165
3772
    deprecated=True)
3166
 
register_metadir(controldir.format_registry, 'dirstate',
 
3773
format_registry.register_metadir('dirstate',
3167
3774
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3168
3775
    help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3169
3776
        'above when accessed over the network.',
3173
3780
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3174
3781
    hidden=True,
3175
3782
    deprecated=True)
3176
 
register_metadir(controldir.format_registry, 'dirstate-tags',
 
3783
format_registry.register_metadir('dirstate-tags',
3177
3784
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3178
3785
    help='New in 0.15: Fast local operations and improved scaling for '
3179
3786
        'network operations. Additionally adds support for tags.'
3182
3789
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3183
3790
    hidden=True,
3184
3791
    deprecated=True)
3185
 
register_metadir(controldir.format_registry, 'rich-root',
 
3792
format_registry.register_metadir('rich-root',
3186
3793
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3187
3794
    help='New in 1.0.  Better handling of tree roots.  Incompatible with'
3188
3795
        ' bzr < 1.0.',
3190
3797
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3191
3798
    hidden=True,
3192
3799
    deprecated=True)
3193
 
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
 
3800
format_registry.register_metadir('dirstate-with-subtree',
3194
3801
    'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3195
3802
    help='New in 0.15: Fast local operations and improved scaling for '
3196
3803
        'network operations. Additionally adds support for versioning nested '
3200
3807
    experimental=True,
3201
3808
    hidden=True,
3202
3809
    )
3203
 
register_metadir(controldir.format_registry, 'pack-0.92',
 
3810
format_registry.register_metadir('pack-0.92',
3204
3811
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3205
3812
    help='New in 0.92: Pack-based format with data compatible with '
3206
3813
        'dirstate-tags format repositories. Interoperates with '
3209
3816
    branch_format='bzrlib.branch.BzrBranchFormat6',
3210
3817
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3211
3818
    )
3212
 
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
 
3819
format_registry.register_metadir('pack-0.92-subtree',
3213
3820
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3214
3821
    help='New in 0.92: Pack-based format with data compatible with '
3215
3822
        'dirstate-with-subtree format repositories. Interoperates with '
3220
3827
    hidden=True,
3221
3828
    experimental=True,
3222
3829
    )
3223
 
register_metadir(controldir.format_registry, 'rich-root-pack',
 
3830
format_registry.register_metadir('rich-root-pack',
3224
3831
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3225
3832
    help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3226
3833
         '(needed for bzr-svn and bzr-git).',
3228
3835
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3229
3836
    hidden=True,
3230
3837
    )
3231
 
register_metadir(controldir.format_registry, '1.6',
 
3838
format_registry.register_metadir('1.6',
3232
3839
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3233
3840
    help='A format that allows a branch to indicate that there is another '
3234
3841
         '(stacked) repository that should be used to access data that is '
3237
3844
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3238
3845
    hidden=True,
3239
3846
    )
3240
 
register_metadir(controldir.format_registry, '1.6.1-rich-root',
 
3847
format_registry.register_metadir('1.6.1-rich-root',
3241
3848
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3242
3849
    help='A variant of 1.6 that supports rich-root data '
3243
3850
         '(needed for bzr-svn and bzr-git).',
3245
3852
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3246
3853
    hidden=True,
3247
3854
    )
3248
 
register_metadir(controldir.format_registry, '1.9',
 
3855
format_registry.register_metadir('1.9',
3249
3856
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3250
3857
    help='A repository format using B+tree indexes. These indexes '
3251
3858
         'are smaller in size, have smarter caching and provide faster '
3254
3861
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3255
3862
    hidden=True,
3256
3863
    )
3257
 
register_metadir(controldir.format_registry, '1.9-rich-root',
 
3864
format_registry.register_metadir('1.9-rich-root',
3258
3865
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3259
3866
    help='A variant of 1.9 that supports rich-root data '
3260
3867
         '(needed for bzr-svn and bzr-git).',
3262
3869
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3263
3870
    hidden=True,
3264
3871
    )
3265
 
register_metadir(controldir.format_registry, '1.14',
 
3872
format_registry.register_metadir('1.14',
3266
3873
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3267
3874
    help='A working-tree format that supports content filtering.',
3268
3875
    branch_format='bzrlib.branch.BzrBranchFormat7',
3269
3876
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3270
3877
    )
3271
 
register_metadir(controldir.format_registry, '1.14-rich-root',
 
3878
format_registry.register_metadir('1.14-rich-root',
3272
3879
    'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3273
3880
    help='A variant of 1.14 that supports rich-root data '
3274
3881
         '(needed for bzr-svn and bzr-git).',
3276
3883
    tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3277
3884
    )
3278
3885
# The following un-numbered 'development' formats should always just be aliases.
3279
 
register_metadir(controldir.format_registry, 'development-rich-root',
 
3886
format_registry.register_metadir('development-rich-root',
3280
3887
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3281
3888
    help='Current development format. Supports rich roots. Can convert data '
3282
3889
        'to and from rich-root-pack (and anything compatible with '
3290
3897
    alias=True,
3291
3898
    hidden=True,
3292
3899
    )
3293
 
register_metadir(controldir.format_registry, 'development-subtree',
 
3900
format_registry.register_metadir('development-subtree',
3294
3901
    'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3295
3902
    help='Current development format, subtree variant. Can convert data to and '
3296
3903
        'from pack-0.92-subtree (and anything compatible with '
3308
3915
    )
3309
3916
 
3310
3917
# And the development formats above will have aliased one of the following:
3311
 
register_metadir(controldir.format_registry, 'development6-rich-root',
 
3918
format_registry.register_metadir('development6-rich-root',
3312
3919
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3313
3920
    help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3314
3921
        'Please read '
3320
3927
    experimental=True,
3321
3928
    )
3322
3929
 
3323
 
register_metadir(controldir.format_registry, 'development7-rich-root',
 
3930
format_registry.register_metadir('development7-rich-root',
3324
3931
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3325
3932
    help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3326
3933
        'rich roots. Please read '
3332
3939
    experimental=True,
3333
3940
    )
3334
3941
 
3335
 
register_metadir(controldir.format_registry, '2a',
 
3942
format_registry.register_metadir('2a',
3336
3943
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3337
3944
    help='First format for bzr 2.0 series.\n'
3338
3945
        'Uses group-compress storage.\n'
3346
3953
 
3347
3954
# The following format should be an alias for the rich root equivalent 
3348
3955
# of the default format
3349
 
register_metadir(controldir.format_registry, 'default-rich-root',
 
3956
format_registry.register_metadir('default-rich-root',
3350
3957
    'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3351
3958
    branch_format='bzrlib.branch.BzrBranchFormat7',
3352
3959
    tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3355
3962
    help='Same as 2a.')
3356
3963
 
3357
3964
# 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
 
3965
format_registry.set_default('2a')