/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: John Arbash Meinel
  • Date: 2008-06-05 16:27:16 UTC
  • mfrom: (3475 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3476.
  • Revision ID: john@arbash-meinel.com-20080605162716-a3hn238tnctbfd8j
merge bzr.dev, resolve NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008 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
80
80
from bzrlib.symbol_versioning import (
81
81
    deprecated_function,
82
82
    deprecated_method,
83
 
    zero_ninetyone,
84
83
    )
85
84
 
86
85
 
90
89
    BzrDir instances let you create or open any of the things that can be
91
90
    found within .bzr - checkouts, branches and repositories.
92
91
    
93
 
    transport
 
92
    :ivar transport:
94
93
        the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
95
 
    root_transport
 
94
    :ivar root_transport:
96
95
        a transport connected to the directory this bzr was opened from
97
96
        (i.e. the parent directory holding the .bzr directory).
 
97
 
 
98
    Everything in the bzrdir should have the same file permissions.
98
99
    """
99
100
 
100
101
    def break_lock(self):
180
181
                               even if one is available.
181
182
        """
182
183
        transport.ensure_base()
183
 
        result = self._format.initialize_on_transport(transport)
 
184
        result = self.cloning_metadir().initialize_on_transport(transport)
 
185
        repository_policy = None
184
186
        try:
185
187
            local_repo = self.find_repository()
186
188
        except errors.NoRepositoryPresent:
187
189
            local_repo = None
188
190
        if local_repo:
189
191
            # may need to copy content in
190
 
            if force_new_repo:
191
 
                result_repo = local_repo.clone(
192
 
                    result,
193
 
                    revision_id=revision_id)
194
 
                result_repo.set_make_working_trees(local_repo.make_working_trees())
195
 
            else:
196
 
                try:
197
 
                    result_repo = result.find_repository()
198
 
                    # fetch content this dir needs.
199
 
                    result_repo.fetch(local_repo, revision_id=revision_id)
200
 
                except errors.NoRepositoryPresent:
201
 
                    # needed to make one anyway.
202
 
                    result_repo = local_repo.clone(
203
 
                        result,
204
 
                        revision_id=revision_id)
205
 
                    result_repo.set_make_working_trees(local_repo.make_working_trees())
 
192
            repository_policy = result.determine_repository_policy(
 
193
                force_new_repo)
 
194
            make_working_trees = local_repo.make_working_trees()
 
195
            result_repo = repository_policy.acquire_repository(
 
196
                make_working_trees, local_repo.is_shared())
 
197
            result_repo.fetch(local_repo, revision_id=revision_id)
206
198
        # 1 if there is a branch present
207
199
        #   make sure its content is available in the target repository
208
200
        #   clone it.
209
201
        try:
210
 
            self.open_branch().clone(result, revision_id=revision_id)
 
202
            local_branch = self.open_branch()
211
203
        except errors.NotBranchError:
212
204
            pass
 
205
        else:
 
206
            result_branch = local_branch.clone(result, revision_id=revision_id)
 
207
            if repository_policy is not None:
 
208
                repository_policy.configure_branch(result_branch)
213
209
        try:
214
210
            result_repo = result.find_repository()
215
211
        except errors.NoRepositoryPresent:
318
314
                branches.append(branch)
319
315
        return branches
320
316
 
321
 
 
322
317
    def destroy_repository(self):
323
318
        """Destroy the repository in this BzrDir"""
324
319
        raise NotImplementedError(self.destroy_repository)
356
351
        bzrdir._find_or_create_repository(force_new_repo)
357
352
        return bzrdir.create_branch()
358
353
 
 
354
    def determine_repository_policy(self, force_new_repo=False):
 
355
        """Return an object representing a policy to use.
 
356
 
 
357
        This controls whether a new repository is created, or a shared
 
358
        repository used instead.
 
359
        """
 
360
        def repository_policy(found_bzrdir):
 
361
            stop = False
 
362
            # does it have a repository ?
 
363
            try:
 
364
                repository = found_bzrdir.open_repository()
 
365
            except errors.NoRepositoryPresent:
 
366
                repository = None
 
367
            else:
 
368
                if ((found_bzrdir.root_transport.base !=
 
369
                     self.root_transport.base) and not repository.is_shared()):
 
370
                    repository = None
 
371
                else:
 
372
                    stop = True
 
373
            if not stop:
 
374
                return None, False
 
375
            if repository:
 
376
                return UseExistingRepository(repository), True
 
377
            else:
 
378
                return CreateRepository(self), True
 
379
 
 
380
        if not force_new_repo:
 
381
            policy = self._find_containing(repository_policy)
 
382
            if policy is not None:
 
383
                return policy
 
384
        return CreateRepository(self)
 
385
 
359
386
    def _find_or_create_repository(self, force_new_repo):
360
387
        """Create a new repository if needed, returning the repository."""
361
 
        if force_new_repo:
362
 
            return self.create_repository()
363
 
        try:
364
 
            return self.find_repository()
365
 
        except errors.NoRepositoryPresent:
366
 
            return self.create_repository()
367
 
        
 
388
        policy = self.determine_repository_policy(force_new_repo)
 
389
        return policy.acquire_repository()
 
390
 
368
391
    @staticmethod
369
392
    def create_branch_convenience(base, force_new_repo=False,
370
393
                                  force_new_tree=None, format=None,
411
434
        return result
412
435
 
413
436
    @staticmethod
414
 
    @deprecated_function(zero_ninetyone)
415
 
    def create_repository(base, shared=False, format=None):
416
 
        """Create a new BzrDir and Repository at the url 'base'.
417
 
 
418
 
        If no format is supplied, this will default to the current default
419
 
        BzrDirFormat by default, and use whatever repository format that that
420
 
        uses for bzrdirformat.create_repository.
421
 
 
422
 
        :param shared: Create a shared repository rather than a standalone
423
 
                       repository.
424
 
        The Repository object is returned.
425
 
 
426
 
        This must be overridden as an instance method in child classes, where
427
 
        it should take no parameters and construct whatever repository format
428
 
        that child class desires.
429
 
 
430
 
        This method is deprecated, please call create_repository on a bzrdir
431
 
        instance instead.
432
 
        """
433
 
        bzrdir = BzrDir.create(base, format)
434
 
        return bzrdir.create_repository(shared)
435
 
 
436
 
    @staticmethod
437
437
    def create_standalone_workingtree(base, format=None):
438
438
        """Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
439
439
 
508
508
        """
509
509
        raise NotImplementedError(self.destroy_workingtree_metadata)
510
510
 
 
511
    def _find_containing(self, evaluate):
 
512
        """Find something in a containing control directory.
 
513
 
 
514
        This method will scan containing control dirs, until it finds what
 
515
        it is looking for, decides that it will never find it, or runs out
 
516
        of containing control directories to check.
 
517
 
 
518
        It is used to implement find_repository and
 
519
        determine_repository_policy.
 
520
 
 
521
        :param evaluate: A function returning (value, stop).  If stop is True,
 
522
            the value will be returned.
 
523
        """
 
524
        found_bzrdir = self
 
525
        while True:
 
526
            result, stop = evaluate(found_bzrdir)
 
527
            if stop:
 
528
                return result
 
529
            next_transport = found_bzrdir.root_transport.clone('..')
 
530
            if (found_bzrdir.root_transport.base == next_transport.base):
 
531
                # top of the file system
 
532
                return None
 
533
            # find the next containing bzrdir
 
534
            try:
 
535
                found_bzrdir = BzrDir.open_containing_from_transport(
 
536
                    next_transport)[0]
 
537
            except errors.NotBranchError:
 
538
                return None
 
539
 
511
540
    def find_repository(self):
512
541
        """Find the repository that should be used.
513
542
 
515
544
        new branches as well as to hook existing branches up to their
516
545
        repository.
517
546
        """
518
 
        try:
519
 
            return self.open_repository()
520
 
        except errors.NoRepositoryPresent:
521
 
            pass
522
 
        next_transport = self.root_transport.clone('..')
523
 
        while True:
524
 
            # find the next containing bzrdir
525
 
            try:
526
 
                found_bzrdir = BzrDir.open_containing_from_transport(
527
 
                    next_transport)[0]
528
 
            except errors.NotBranchError:
529
 
                # none found
530
 
                raise errors.NoRepositoryPresent(self)
 
547
        def usable_repository(found_bzrdir):
531
548
            # does it have a repository ?
532
549
            try:
533
550
                repository = found_bzrdir.open_repository()
534
551
            except errors.NoRepositoryPresent:
535
 
                next_transport = found_bzrdir.root_transport.clone('..')
536
 
                if (found_bzrdir.root_transport.base == next_transport.base):
537
 
                    # top of the file system
538
 
                    break
539
 
                else:
540
 
                    continue
541
 
            if ((found_bzrdir.root_transport.base ==
542
 
                 self.root_transport.base) or repository.is_shared()):
543
 
                return repository
 
552
                return None, False
 
553
            if found_bzrdir.root_transport.base == self.root_transport.base:
 
554
                return repository, True
 
555
            elif repository.is_shared():
 
556
                return repository, True
544
557
            else:
545
 
                raise errors.NoRepositoryPresent(self)
546
 
        raise errors.NoRepositoryPresent(self)
 
558
                return None, True
 
559
 
 
560
        found_repo = self._find_containing(usable_repository)
 
561
        if found_repo is None:
 
562
            raise errors.NoRepositoryPresent(self)
 
563
        return found_repo
547
564
 
548
565
    def get_branch_reference(self):
549
566
        """Return the referenced URL for the branch in this bzrdir.
566
583
        guaranteed to point to an existing directory ready for use.
567
584
        """
568
585
        raise NotImplementedError(self.get_branch_transport)
 
586
 
 
587
    def _find_creation_modes(self):
 
588
        """Determine the appropriate modes for files and directories.
 
589
        
 
590
        They're always set to be consistent with the base directory,
 
591
        assuming that this transport allows setting modes.
 
592
        """
 
593
        # TODO: Do we need or want an option (maybe a config setting) to turn
 
594
        # this off or override it for particular locations? -- mbp 20080512
 
595
        if self._mode_check_done:
 
596
            return
 
597
        self._mode_check_done = True
 
598
        try:
 
599
            st = self.transport.stat('.')
 
600
        except errors.TransportNotPossible:
 
601
            self._dir_mode = None
 
602
            self._file_mode = None
 
603
        else:
 
604
            # Check the directory mode, but also make sure the created
 
605
            # directories and files are read-write for this user. This is
 
606
            # mostly a workaround for filesystems which lie about being able to
 
607
            # write to a directory (cygwin & win32)
 
608
            self._dir_mode = (st.st_mode & 07777) | 00700
 
609
            # Remove the sticky and execute bits for files
 
610
            self._file_mode = self._dir_mode & ~07111
 
611
 
 
612
    def _get_file_mode(self):
 
613
        """Return Unix mode for newly created files, or None.
 
614
        """
 
615
        if not self._mode_check_done:
 
616
            self._find_creation_modes()
 
617
        return self._file_mode
 
618
 
 
619
    def _get_dir_mode(self):
 
620
        """Return Unix mode for newly created directories, or None.
 
621
        """
 
622
        if not self._mode_check_done:
 
623
            self._find_creation_modes()
 
624
        return self._dir_mode
569
625
        
570
626
    def get_repository_transport(self, repository_format):
571
627
        """Get the transport for use by repository format in this BzrDir.
605
661
        self._format = _format
606
662
        self.transport = _transport.clone('.bzr')
607
663
        self.root_transport = _transport
 
664
        self._mode_check_done = False
608
665
 
609
666
    def is_control_filename(self, filename):
610
667
        """True if filename is the name of a path which is reserved for bzrdir's.
999
1056
    def __init__(self, _transport, _format):
1000
1057
        """See BzrDir.__init__."""
1001
1058
        super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1002
 
        assert self._format._lock_class == lockable_files.TransportLock
1003
 
        assert self._format._lock_file_name == 'branch-lock'
1004
1059
        self._control_files = lockable_files.LockableFiles(
1005
1060
                                            self.get_branch_transport(None),
1006
1061
                                            self._format._lock_file_name,
1010
1065
        """Pre-splitout bzrdirs do not suffer from stale locks."""
1011
1066
        raise NotImplementedError(self.break_lock)
1012
1067
 
 
1068
    def cloning_metadir(self):
 
1069
        """Produce a metadir suitable for cloning with."""
 
1070
        return self._format.__class__()
 
1071
 
1013
1072
    def clone(self, url, revision_id=None, force_new_repo=False):
1014
1073
        """See BzrDir.clone()."""
1015
1074
        from bzrlib.workingtree import WorkingTreeFormat2
1027
1086
            except errors.NotLocalUrl:
1028
1087
                # but we cannot do it for remote trees.
1029
1088
                to_branch = result.open_branch()
1030
 
                WorkingTreeFormat2().stub_initialize_remote(to_branch.control_files)
 
1089
                WorkingTreeFormat2()._stub_initialize_remote(to_branch)
1031
1090
        return result
1032
1091
 
1033
1092
    def create_branch(self):
1436
1495
        try:
1437
1496
            return klass._formats[format_string]
1438
1497
        except KeyError:
1439
 
            raise errors.UnknownFormatError(format=format_string)
 
1498
            raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1440
1499
 
1441
1500
    @classmethod
1442
1501
    def get_default_format(klass):
1488
1547
            win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1489
1548
        file_mode = temp_control._file_mode
1490
1549
        del temp_control
1491
 
        mutter('created control directory in ' + transport.base)
1492
 
        control = transport.clone('.bzr')
1493
 
        utf8_files = [('README', 
1494
 
                       "This is a Bazaar-NG control directory.\n"
1495
 
                       "Do not change any files in this directory.\n"),
 
1550
        bzrdir_transport = transport.clone('.bzr')
 
1551
        utf8_files = [('README',
 
1552
                       "This is a Bazaar control directory.\n"
 
1553
                       "Do not change any files in this directory.\n"
 
1554
                       "See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1496
1555
                      ('branch-format', self.get_format_string()),
1497
1556
                      ]
1498
1557
        # NB: no need to escape relative paths that are url safe.
1499
 
        control_files = lockable_files.LockableFiles(control,
1500
 
                            self._lock_file_name, self._lock_class)
 
1558
        control_files = lockable_files.LockableFiles(bzrdir_transport,
 
1559
            self._lock_file_name, self._lock_class)
1501
1560
        control_files.create_lock()
1502
1561
        control_files.lock_write()
1503
1562
        try:
1504
 
            for file, content in utf8_files:
1505
 
                control_files.put_utf8(file, content)
 
1563
            for (filename, content) in utf8_files:
 
1564
                bzrdir_transport.put_bytes(filename, content,
 
1565
                    mode=file_mode)
1506
1566
        finally:
1507
1567
            control_files.unlock()
1508
1568
        return self.open(transport, _found=True)
1587
1647
        klass._control_server_formats.append(format)
1588
1648
 
1589
1649
    @classmethod
1590
 
    @symbol_versioning.deprecated_method(symbol_versioning.zero_fourteen)
1591
 
    def set_default_format(klass, format):
1592
 
        klass._set_default_format(format)
1593
 
 
1594
 
    @classmethod
1595
1650
    def _set_default_format(klass, format):
1596
1651
        """Set default format (for testing behavior of defaults only)"""
1597
1652
        klass._default_format = format
1602
1657
 
1603
1658
    @classmethod
1604
1659
    def unregister_format(klass, format):
1605
 
        assert klass._formats[format.get_format_string()] is format
1606
1660
        del klass._formats[format.get_format_string()]
1607
1661
 
1608
1662
    @classmethod
1708
1762
            except errors.NotLocalUrl:
1709
1763
                # Even though we can't access the working tree, we need to
1710
1764
                # create its control files.
1711
 
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
 
1765
                WorkingTreeFormat2()._stub_initialize_remote(branch)
1712
1766
        return result
1713
1767
 
1714
1768
    def _open(self, transport):
1767
1821
            except errors.NotLocalUrl:
1768
1822
                # Even though we can't access the working tree, we need to
1769
1823
                # create its control files.
1770
 
                WorkingTreeFormat2().stub_initialize_remote(branch.control_files)
 
1824
                WorkingTreeFormat2()._stub_initialize_remote(branch)
1771
1825
        return result
1772
1826
 
1773
1827
    def _open(self, transport):
1954
2008
        self.pb.note('  %6d revisions not present', len(self.absent_revisions))
1955
2009
        self.pb.note('  %6d texts', self.text_count)
1956
2010
        self._cleanup_spare_files_after_format4()
1957
 
        self.branch.control_files.put_utf8('branch-format', BzrDirFormat5().get_format_string())
 
2011
        self.branch._transport.put_bytes(
 
2012
            'branch-format',
 
2013
            BzrDirFormat5().get_format_string(),
 
2014
            mode=self.bzrdir._get_file_mode())
1958
2015
 
1959
2016
    def _cleanup_spare_files_after_format4(self):
1960
2017
        # FIXME working tree upgrade foo.
1969
2026
 
1970
2027
    def _convert_working_inv(self):
1971
2028
        inv = xml4.serializer_v4.read_inventory(
1972
 
                    self.branch.control_files.get('inventory'))
 
2029
                self.branch._transport.get('inventory'))
1973
2030
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
1974
 
        # FIXME inventory is a working tree change.
1975
 
        self.branch.control_files.put('inventory', StringIO(new_inv_xml))
 
2031
        self.branch._transport.put_bytes('inventory', new_inv_xml,
 
2032
            mode=self.bzrdir._get_file_mode())
1976
2033
 
1977
2034
    def _write_all_weaves(self):
1978
2035
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2032
2089
            self.revisions[rev_id] = rev
2033
2090
 
2034
2091
    def _load_old_inventory(self, rev_id):
2035
 
        assert rev_id not in self.converted_revs
2036
2092
        old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2037
2093
        inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2038
2094
        inv.revision_id = rev_id
2039
2095
        rev = self.revisions[rev_id]
2040
 
        if rev.inventory_sha1:
2041
 
            assert rev.inventory_sha1 == sha_string(old_inv_xml), \
2042
 
                'inventory sha mismatch for {%s}' % rev_id
2043
2096
        return inv
2044
2097
 
2045
2098
    def _load_updated_inventory(self, rev_id):
2046
 
        assert rev_id in self.converted_revs
2047
2099
        inv_xml = self.inv_weave.get_text(rev_id)
2048
2100
        inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2049
2101
        return inv
2059
2111
        self.converted_revs.add(rev_id)
2060
2112
 
2061
2113
    def _store_new_inv(self, rev, inv, present_parents):
2062
 
        # the XML is now updated with text versions
2063
 
        if __debug__:
2064
 
            entries = inv.iter_entries()
2065
 
            entries.next()
2066
 
            for path, ie in entries:
2067
 
                assert getattr(ie, 'revision', None) is not None, \
2068
 
                    'no revision on {%s} in {%s}' % \
2069
 
                    (file_id, rev.revision_id)
2070
2114
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2071
2115
        new_inv_sha1 = sha_string(new_inv_xml)
2072
2116
        self.inv_weave.add_lines(rev.revision_id,
2101
2145
            self.text_weaves[file_id] = w
2102
2146
        text_changed = False
2103
2147
        parent_candiate_entries = ie.parent_candidates(parent_invs)
2104
 
        for old_revision in parent_candiate_entries.keys():
2105
 
            # if this fails, its a ghost ?
2106
 
            assert old_revision in self.converted_revs, \
2107
 
                "Revision {%s} not in converted_revs" % old_revision
2108
2148
        heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2109
2149
        # XXX: Note that this is unordered - and this is tolerable because 
2110
2150
        # the previous code was also unordered.
2112
2152
            in heads)
2113
2153
        self.snapshot_ie(previous_entries, ie, w, rev_id)
2114
2154
        del ie.text_id
2115
 
        assert getattr(ie, 'revision', None) is not None
2116
2155
 
2117
2156
    @symbol_versioning.deprecated_method(symbol_versioning.one_one)
2118
2157
    def get_parents(self, revision_ids):
2141
2180
        if ie.has_text():
2142
2181
            text = self.branch.repository.weave_store.get(ie.text_id)
2143
2182
            file_lines = text.readlines()
2144
 
            assert sha_strings(file_lines) == ie.text_sha1
2145
 
            assert sum(map(len, file_lines)) == ie.text_size
2146
2183
            w.add_lines(rev_id, previous_revisions, file_lines)
2147
2184
            self.text_count += 1
2148
2185
        else:
2205
2242
                except errors.NoSuchFile: # catches missing dirs strangely enough
2206
2243
                    store_transport.mkdir(prefix_dir)
2207
2244
                    store_transport.move(filename, prefix_dir + '/' + filename)
2208
 
        self.bzrdir._control_files.put_utf8('branch-format', BzrDirFormat6().get_format_string())
 
2245
        self.bzrdir.transport.put_bytes(
 
2246
            'branch-format',
 
2247
            BzrDirFormat6().get_format_string(),
 
2248
            mode=self.bzrdir._get_file_mode())
2209
2249
 
2210
2250
 
2211
2251
class ConvertBzrDir6ToMeta(Converter):
2220
2260
        self.count = 0
2221
2261
        self.total = 20 # the steps we know about
2222
2262
        self.garbage_inventories = []
 
2263
        self.dir_mode = self.bzrdir._get_dir_mode()
 
2264
        self.file_mode = self.bzrdir._get_file_mode()
2223
2265
 
2224
2266
        self.pb.note('starting upgrade from format 6 to metadir')
2225
 
        self.bzrdir._control_files.put_utf8('branch-format', "Converting to format 6")
 
2267
        self.bzrdir.transport.put_bytes(
 
2268
                'branch-format',
 
2269
                "Converting to format 6",
 
2270
                mode=self.file_mode)
2226
2271
        # its faster to move specific files around than to open and use the apis...
2227
2272
        # first off, nuke ancestry.weave, it was never used.
2228
2273
        try:
2238
2283
            if name.startswith('basis-inventory.'):
2239
2284
                self.garbage_inventories.append(name)
2240
2285
        # create new directories for repository, working tree and branch
2241
 
        self.dir_mode = self.bzrdir._control_files._dir_mode
2242
 
        self.file_mode = self.bzrdir._control_files._file_mode
2243
2286
        repository_names = [('inventory.weave', True),
2244
2287
                            ('revision-store', True),
2245
2288
                            ('weaves', True)]
2293
2336
            for entry in checkout_files:
2294
2337
                self.move_entry('checkout', entry)
2295
2338
            if last_revision is not None:
2296
 
                self.bzrdir._control_files.put_utf8(
 
2339
                self.bzrdir.transport.put_bytes(
2297
2340
                    'checkout/last-revision', last_revision)
2298
 
        self.bzrdir._control_files.put_utf8(
2299
 
            'branch-format', BzrDirMetaFormat1().get_format_string())
 
2341
        self.bzrdir.transport.put_bytes(
 
2342
            'branch-format',
 
2343
            BzrDirMetaFormat1().get_format_string(),
 
2344
            mode=self.file_mode)
2300
2345
        return BzrDir.open(self.bzrdir.root_transport.base)
2301
2346
 
2302
2347
    def make_lock(self, name):
2320
2365
                raise
2321
2366
 
2322
2367
    def put_format(self, dirname, format):
2323
 
        self.bzrdir._control_files.put_utf8('%s/format' % dirname, format.get_format_string())
 
2368
        self.bzrdir.transport.put_bytes('%s/format' % dirname,
 
2369
            format.get_format_string(),
 
2370
            self.file_mode)
2324
2371
 
2325
2372
 
2326
2373
class ConvertMetaToMeta(Converter):
2393
2440
    def probe_transport(klass, transport):
2394
2441
        """Return a RemoteBzrDirFormat object if it looks possible."""
2395
2442
        try:
2396
 
            client = transport.get_smart_client()
 
2443
            medium = transport.get_smart_medium()
2397
2444
        except (NotImplementedError, AttributeError,
2398
 
                errors.TransportNotPossible):
 
2445
                errors.TransportNotPossible, errors.NoSmartMedium,
 
2446
                errors.SmartProtocolError):
2399
2447
            # no smart server, so not a branch for this format type.
2400
2448
            raise errors.NotBranchError(path=transport.base)
2401
2449
        else:
2402
 
            # Send a 'hello' request in protocol version one, and decline to
2403
 
            # open it if the server doesn't support our required version (2) so
2404
 
            # that the VFS-based transport will do it.
2405
 
            request = client.get_request()
2406
 
            smart_protocol = protocol.SmartClientRequestProtocolOne(request)
2407
 
            server_version = smart_protocol.query_version()
2408
 
            if server_version != 2:
2409
 
                raise errors.NotBranchError(path=transport.base)
 
2450
            # Decline to open it if the server doesn't support our required
 
2451
            # version (3) so that the VFS-based transport will do it.
 
2452
            if medium.should_probe():
 
2453
                try:
 
2454
                    server_version = medium.protocol_version()
 
2455
                except errors.SmartProtocolError:
 
2456
                    # Apparently there's no usable smart server there, even though
 
2457
                    # the medium supports the smart protocol.
 
2458
                    raise errors.NotBranchError(path=transport.base)
 
2459
                if server_version != '2':
 
2460
                    raise errors.NotBranchError(path=transport.base)
2410
2461
            return klass()
2411
2462
 
2412
2463
    def initialize_on_transport(self, transport):
2413
2464
        try:
2414
2465
            # hand off the request to the smart server
2415
 
            shared_medium = transport.get_shared_medium()
 
2466
            client_medium = transport.get_smart_medium()
2416
2467
        except errors.NoSmartMedium:
2417
2468
            # TODO: lookup the local format from a server hint.
2418
2469
            local_dir_format = BzrDirMetaFormat1()
2419
2470
            return local_dir_format.initialize_on_transport(transport)
2420
 
        client = _SmartClient(shared_medium)
 
2471
        client = _SmartClient(client_medium)
2421
2472
        path = client.remote_path_from_transport(transport)
2422
 
        response = _SmartClient(shared_medium).call('BzrDirFormat.initialize',
2423
 
                                                    path)
2424
 
        assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
 
2473
        response = client.call('BzrDirFormat.initialize', path)
 
2474
        if response[0] != 'ok':
 
2475
            raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2425
2476
        return remote.RemoteBzrDir(transport)
2426
2477
 
2427
2478
    def _open(self, transport):
2549
2600
            self.remove('default')
2550
2601
        self.set_default(key)
2551
2602
        format = self.get('default')()
2552
 
        assert isinstance(format, BzrDirMetaFormat1)
2553
2603
 
2554
2604
    def make_bzrdir(self, key):
2555
2605
        return self.get(key)()
2607
2657
        return output
2608
2658
 
2609
2659
 
 
2660
class RepositoryAcquisitionPolicy(object):
 
2661
    """Abstract base class for repository acquisition policies.
 
2662
 
 
2663
    A repository acquisition policy decides how a BzrDir acquires a repository
 
2664
    for a branch that is being created.  The most basic policy decision is
 
2665
    whether to create a new repository or use an existing one.
 
2666
    """
 
2667
 
 
2668
    def configure_branch(self, branch):
 
2669
        """Apply any configuration data from this policy to the branch.
 
2670
 
 
2671
        Default implementation does nothing.
 
2672
        """
 
2673
        pass
 
2674
 
 
2675
    def acquire_repository(self, make_working_trees=None, shared=False):
 
2676
        """Acquire a repository for this bzrdir.
 
2677
 
 
2678
        Implementations may create a new repository or use a pre-exising
 
2679
        repository.
 
2680
        :param make_working_trees: If creating a repository, set
 
2681
            make_working_trees to this value (if non-None)
 
2682
        :param shared: If creating a repository, make it shared if True
 
2683
        :return: A repository
 
2684
        """
 
2685
        raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
 
2686
 
 
2687
 
 
2688
class CreateRepository(RepositoryAcquisitionPolicy):
 
2689
    """A policy of creating a new repository"""
 
2690
 
 
2691
    def __init__(self, bzrdir):
 
2692
        RepositoryAcquisitionPolicy.__init__(self)
 
2693
        self._bzrdir = bzrdir
 
2694
 
 
2695
    def acquire_repository(self, make_working_trees=None, shared=False):
 
2696
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
 
2697
 
 
2698
        Creates the desired repository in the bzrdir we already have.
 
2699
        """
 
2700
        repository = self._bzrdir.create_repository(shared=shared)
 
2701
        if make_working_trees is not None:
 
2702
            repository.set_make_working_trees(make_working_trees)
 
2703
        return repository
 
2704
 
 
2705
 
 
2706
class UseExistingRepository(RepositoryAcquisitionPolicy):
 
2707
    """A policy of reusing an existing repository"""
 
2708
 
 
2709
    def __init__(self, repository):
 
2710
        RepositoryAcquisitionPolicy.__init__(self)
 
2711
        self._repository = repository
 
2712
 
 
2713
    def acquire_repository(self, make_working_trees=None, shared=False):
 
2714
        """Implementation of RepositoryAcquisitionPolicy.acquire_repository
 
2715
 
 
2716
        Returns an existing repository to use
 
2717
        """
 
2718
        return self._repository
 
2719
 
 
2720
 
2610
2721
format_registry = BzrDirFormatRegistry()
2611
2722
format_registry.register('weave', BzrDirFormat6,
2612
2723
    'Pre-0.8 format.  Slower than knit and does not'