~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Martin Pool
  • Date: 2006-03-10 06:29:53 UTC
  • mfrom: (1608 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1611.
  • Revision ID: mbp@sourcefrog.net-20060310062953-bc1c7ade75c89a7a
[merge] bzr.dev; pycurl not updated for readv yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
import bzrlib
29
29
import bzrlib.errors as errors
30
30
from bzrlib.lockable_files import LockableFiles, TransportLock
 
31
from bzrlib.lockdir import LockDir
31
32
from bzrlib.osutils import safe_unicode
32
33
from bzrlib.osutils import (
33
34
                            abspath,
36
37
                            sha_strings,
37
38
                            sha_string,
38
39
                            )
 
40
from bzrlib.store.revision.text import TextRevisionStore
39
41
from bzrlib.store.text import TextStore
40
 
from bzrlib.store.weave import WeaveStore
 
42
from bzrlib.store.versioned import WeaveStore
41
43
from bzrlib.symbol_versioning import *
42
44
from bzrlib.trace import mutter
43
 
from bzrlib.transactions import PassThroughTransaction
 
45
from bzrlib.transactions import WriteTransaction
44
46
from bzrlib.transport import get_transport
45
47
from bzrlib.transport.local import LocalTransport
46
48
from bzrlib.weave import Weave
47
 
from bzrlib.weavefile import read_weave, write_weave
48
49
from bzrlib.xml4 import serializer_v4
49
50
from bzrlib.xml5 import serializer_v5
50
51
 
65
66
        """Return true if this bzrdir is one whose format we can convert from."""
66
67
        return True
67
68
 
68
 
    def _check_supported(self, format, allow_unsupported):
 
69
    @staticmethod
 
70
    def _check_supported(format, allow_unsupported):
69
71
        """Check whether format is a supported format.
70
72
 
71
73
        If allow_unsupported is True, this is a no-op.
72
74
        """
73
75
        if not allow_unsupported and not format.is_supported():
74
 
            raise errors.UnsupportedFormatError(format)
 
76
            # see open_downlevel to open legacy branches.
 
77
            raise errors.UnsupportedFormatError(
 
78
                    'sorry, format %s not supported' % format,
 
79
                    ['use a different bzr version',
 
80
                     'or remove the .bzr directory'
 
81
                     ' and "bzr init" again'])
75
82
 
76
83
    def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
77
84
        """Clone this bzrdir and its contents to url verbatim.
150
157
            except errors.FileExists:
151
158
                pass
152
159
 
153
 
    @staticmethod
154
 
    def create(base):
 
160
    @classmethod
 
161
    def create(cls, base):
155
162
        """Create a new BzrDir at the url 'base'.
156
163
        
157
164
        This will call the current default formats initialize with base
160
167
        If you need a specific format, consider creating an instance
161
168
        of that and calling initialize().
162
169
        """
 
170
        if cls is not BzrDir:
 
171
            raise AssertionError("BzrDir.create always creates the default format, "
 
172
                    "not one of %r" % cls)
163
173
        segments = base.split('/')
164
174
        if segments and segments[-1] not in ('', '.'):
165
175
            parent = '/'.join(segments[:-1])
396
406
        t = get_transport(base)
397
407
        mutter("trying to open %r with transport %r", base, t)
398
408
        format = BzrDirFormat.find_format(t)
399
 
        if not _unsupported and not format.is_supported():
400
 
            # see open_downlevel to open legacy branches.
401
 
            raise errors.UnsupportedFormatError(
402
 
                    'sorry, format %s not supported' % format,
403
 
                    ['use a different bzr version',
404
 
                     'or remove the .bzr directory'
405
 
                     ' and "bzr init" again'])
 
409
        BzrDir._check_supported(format, _unsupported)
406
410
        return format.open(t, _found=True)
407
411
 
408
412
    def open_branch(self, unsupported=False):
441
445
        while True:
442
446
            try:
443
447
                format = BzrDirFormat.find_format(a_transport)
 
448
                BzrDir._check_supported(format, False)
444
449
                return format.open(a_transport), a_transport.relpath(url)
445
450
            except errors.NotBranchError, e:
446
451
                mutter('not a branch in: %r %s', a_transport.base, e)
535
540
    def __init__(self, _transport, _format):
536
541
        """See BzrDir.__init__."""
537
542
        super(BzrDirPreSplitOut, self).__init__(_transport, _format)
 
543
        assert self._format._lock_class == TransportLock
 
544
        assert self._format._lock_file_name == 'branch-lock'
538
545
        self._control_files = LockableFiles(self.get_branch_transport(None),
539
 
                                            'branch-lock',
540
 
                                            TransportLock)
 
546
                                            self._format._lock_file_name,
 
547
                                            self._format._lock_class)
541
548
 
542
549
    def clone(self, url, revision_id=None, basis=None, force_new_repo=False):
543
550
        """See BzrDir.clone()."""
551
558
            self.open_workingtree().clone(result, basis=basis_tree)
552
559
        except errors.NotLocalUrl:
553
560
            # make a new one, this format always has to have one.
554
 
            WorkingTreeFormat2().initialize(result)
 
561
            try:
 
562
                WorkingTreeFormat2().initialize(result)
 
563
            except errors.NotLocalUrl:
 
564
                # but we canot do it for remote trees.
 
565
                pass
555
566
        return result
556
567
 
557
568
    def create_branch(self):
700
711
    """A .bzr meta version 1 control object.
701
712
    
702
713
    This is the first control object where the 
703
 
    individual formats are really split out.
 
714
    individual aspects are really split out: there are separate repository,
 
715
    workingtree and branch subdirectories and any subset of the three can be
 
716
    present within a BzrDir.
704
717
    """
705
718
 
706
719
    def can_convert_format(self):
826
839
    _formats = {}
827
840
    """The known formats."""
828
841
 
 
842
    _lock_file_name = 'branch-lock'
 
843
 
 
844
    # _lock_class must be set in subclasses to the lock type, typ.
 
845
    # TransportLock or LockDir
 
846
 
829
847
    @classmethod
830
848
    def find_format(klass, transport):
831
849
        """Return the format registered for URL."""
874
892
        del temp_control
875
893
        mutter('created control directory in ' + t.base)
876
894
        control = t.clone('.bzr')
877
 
        lock_file = 'branch-lock'
878
895
        utf8_files = [('README', 
879
896
                       "This is a Bazaar-NG control directory.\n"
880
897
                       "Do not change any files in this directory.\n"),
881
898
                      ('branch-format', self.get_format_string()),
882
899
                      ]
883
900
        # NB: no need to escape relative paths that are url safe.
884
 
        control_files = LockableFiles(control, lock_file, TransportLock)
 
901
        control_files = LockableFiles(control, self._lock_file_name, self._lock_class)
885
902
        control_files.create_lock()
886
903
        control_files.lock_write()
887
904
        try:
948
965
    removed in format 5; write support for this format has been removed.
949
966
    """
950
967
 
 
968
    _lock_class = TransportLock
 
969
 
951
970
    def get_format_string(self):
952
971
        """See BzrDirFormat.get_format_string()."""
953
972
        return "Bazaar-NG branch, format 0.0.4\n"
992
1011
       Unhashed stores in the repository.
993
1012
    """
994
1013
 
 
1014
    _lock_class = TransportLock
 
1015
 
995
1016
    def get_format_string(self):
996
1017
        """See BzrDirFormat.get_format_string()."""
997
1018
        return "Bazaar-NG branch, format 5\n"
1037
1058
     - Format 6 repositories [always]
1038
1059
    """
1039
1060
 
 
1061
    _lock_class = TransportLock
 
1062
 
1040
1063
    def get_format_string(self):
1041
1064
        """See BzrDirFormat.get_format_string()."""
1042
1065
        return "Bazaar-NG branch, format 6\n"
1088
1111
     - Format 7 repositories [optional]
1089
1112
    """
1090
1113
 
 
1114
    _lock_class = LockDir
 
1115
 
1091
1116
    def get_converter(self, format=None):
1092
1117
        """See BzrDirFormat.get_converter()."""
1093
1118
        if format is None:
1115
1140
    def __set_repository_format(self, value):
1116
1141
        """Allow changint the repository format for metadir formats."""
1117
1142
        self._repository_format = value
 
1143
 
1118
1144
    repository_format = property(__return_repository_format, __set_repository_format)
1119
1145
 
1120
1146
 
1267
1293
                self.bzrdir.transport.mkdir('weaves')
1268
1294
        except errors.NoSuchFile:
1269
1295
            self.bzrdir.transport.mkdir('weaves')
 
1296
        # deliberately not a WeaveFile as we want to build it up slowly.
1270
1297
        self.inv_weave = Weave('inventory')
1271
1298
        # holds in-memory weaves for all files
1272
1299
        self.text_weaves = {}
1319
1346
        controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
1320
1347
        weave_transport = self.bzrdir.transport.clone('weaves')
1321
1348
        weaves = WeaveStore(weave_transport, prefixed=False)
1322
 
        transaction = PassThroughTransaction()
 
1349
        transaction = WriteTransaction()
1323
1350
 
1324
 
        controlweaves.put_weave('inventory', self.inv_weave, transaction)
1325
 
        i = 0
1326
1351
        try:
 
1352
            i = 0
1327
1353
            for file_id, file_weave in self.text_weaves.items():
1328
1354
                self.pb.update('writing weave', i, len(self.text_weaves))
1329
 
                weaves.put_weave(file_id, file_weave, transaction)
 
1355
                weaves._put_weave(file_id, file_weave, transaction)
1330
1356
                i += 1
 
1357
            self.pb.update('inventory', 0, 1)
 
1358
            controlweaves._put_weave('inventory', self.inv_weave, transaction)
 
1359
            self.pb.update('inventory', 1, 1)
1331
1360
        finally:
1332
1361
            self.pb.clear()
1333
1362
 
1337
1366
        self.bzrdir.transport.mkdir('revision-store')
1338
1367
        revision_transport = self.bzrdir.transport.clone('revision-store')
1339
1368
        # TODO permissions
1340
 
        revision_store = TextStore(revision_transport,
1341
 
                                   prefixed=False,
1342
 
                                   compressed=True)
 
1369
        _revision_store = TextRevisionStore(TextStore(revision_transport,
 
1370
                                                      prefixed=False,
 
1371
                                                      compressed=True))
1343
1372
        try:
 
1373
            transaction = bzrlib.transactions.WriteTransaction()
1344
1374
            for i, rev_id in enumerate(self.converted_revs):
1345
1375
                self.pb.update('write revision', i, len(self.converted_revs))
1346
 
                rev_tmp = StringIO()
1347
 
                serializer_v5.write_revision(self.revisions[rev_id], rev_tmp)
1348
 
                rev_tmp.seek(0)
1349
 
                revision_store.add(rev_tmp, rev_id)
 
1376
                _revision_store.add_revision(self.revisions[rev_id], transaction)
1350
1377
        finally:
1351
1378
            self.pb.clear()
1352
1379
            
1358
1385
        self.pb.update('loading revision',
1359
1386
                       len(self.revisions),
1360
1387
                       len(self.known_revisions))
1361
 
        if not self.branch.repository.revision_store.has_id(rev_id):
 
1388
        if not self.branch.repository.has_revision(rev_id):
1362
1389
            self.pb.clear()
1363
1390
            self.pb.note('revision {%s} not present in branch; '
1364
1391
                         'will be converted as a ghost',
1365
1392
                         rev_id)
1366
1393
            self.absent_revisions.add(rev_id)
1367
1394
        else:
1368
 
            rev_xml = self.branch.repository.revision_store.get(rev_id).read()
1369
 
            rev = serializer_v4.read_revision_from_string(rev_xml)
 
1395
            rev = self.branch.repository._revision_store.get_revision(rev_id,
 
1396
                self.branch.repository.get_transaction())
1370
1397
            for parent_id in rev.parent_ids:
1371
1398
                self.known_revisions.add(parent_id)
1372
1399
                self.to_read.append(parent_id)
1410
1437
                    (file_id, rev.revision_id)
1411
1438
        new_inv_xml = serializer_v5.write_inventory_to_string(inv)
1412
1439
        new_inv_sha1 = sha_string(new_inv_xml)
1413
 
        self.inv_weave.add(rev.revision_id, 
1414
 
                           present_parents,
1415
 
                           new_inv_xml.splitlines(True),
1416
 
                           new_inv_sha1)
 
1440
        self.inv_weave.add_lines(rev.revision_id, 
 
1441
                                 present_parents,
 
1442
                                 new_inv_xml.splitlines(True))
1417
1443
        rev.inventory_sha1 = new_inv_sha1
1418
1444
 
1419
1445
    def _convert_revision_contents(self, rev, inv, present_parents):
1464
1490
            if ie._unchanged(previous_ie):
1465
1491
                ie.revision = previous_ie.revision
1466
1492
                return
1467
 
        parent_indexes = map(w.lookup, previous_revisions)
1468
1493
        if ie.has_text():
1469
1494
            text = self.branch.repository.text_store.get(ie.text_id)
1470
1495
            file_lines = text.readlines()
1471
1496
            assert sha_strings(file_lines) == ie.text_sha1
1472
1497
            assert sum(map(len, file_lines)) == ie.text_size
1473
 
            w.add(rev_id, parent_indexes, file_lines, ie.text_sha1)
 
1498
            w.add_lines(rev_id, previous_revisions, file_lines)
1474
1499
            self.text_count += 1
1475
1500
        else:
1476
 
            w.add(rev_id, parent_indexes, [], None)
 
1501
            w.add_lines(rev_id, previous_revisions, [])
1477
1502
        ie.revision = rev_id
1478
1503
 
1479
1504
    def _make_order(self):
1561
1586
            if name.startswith('basis-inventory.'):
1562
1587
                self.garbage_inventories.append(name)
1563
1588
        # create new directories for repository, working tree and branch
1564
 
        dir_mode = self.bzrdir._control_files._dir_mode
 
1589
        self.dir_mode = self.bzrdir._control_files._dir_mode
1565
1590
        self.file_mode = self.bzrdir._control_files._file_mode
1566
1591
        repository_names = [('inventory.weave', True),
1567
1592
                            ('revision-store', True),
1568
1593
                            ('weaves', True)]
1569
1594
        self.step('Upgrading repository  ')
1570
 
        self.bzrdir.transport.mkdir('repository', mode=dir_mode)
 
1595
        self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
1571
1596
        self.make_lock('repository')
1572
1597
        # we hard code the formats here because we are converting into
1573
1598
        # the meta format. The meta format upgrader can take this to a 
1577
1602
            self.move_entry('repository', entry)
1578
1603
 
1579
1604
        self.step('Upgrading branch      ')
1580
 
        self.bzrdir.transport.mkdir('branch', mode=dir_mode)
 
1605
        self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
1581
1606
        self.make_lock('branch')
1582
1607
        self.put_format('branch', bzrlib.branch.BzrBranchFormat5())
1583
1608
        branch_files = [('revision-history', True),
1587
1612
            self.move_entry('branch', entry)
1588
1613
 
1589
1614
        self.step('Upgrading working tree')
1590
 
        self.bzrdir.transport.mkdir('checkout', mode=dir_mode)
 
1615
        self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
1591
1616
        self.make_lock('checkout')
1592
1617
        self.put_format('checkout', bzrlib.workingtree.WorkingTreeFormat3())
1593
1618
        self.bzrdir.transport.delete_multi(self.garbage_inventories, self.pb)
1605
1630
    def make_lock(self, name):
1606
1631
        """Make a lock for the new control dir name."""
1607
1632
        self.step('Make %s lock' % name)
1608
 
        self.bzrdir.transport.put('%s/lock' % name, StringIO(), mode=self.file_mode)
 
1633
        ld = LockDir(self.bzrdir.transport, 
 
1634
                     '%s/lock' % name,
 
1635
                     file_modebits=self.file_mode,
 
1636
                     dir_modebits=self.dir_mode)
 
1637
        ld.create()
1609
1638
 
1610
1639
    def move_entry(self, new_dir, entry):
1611
1640
        """Move then entry name into new_dir."""