/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/repository.py

[merge] bzr.dev 2255, resolve conflicts, update copyrights

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
 
17
from cStringIO import StringIO
 
18
 
 
19
from bzrlib.lazy_import import lazy_import
 
20
lazy_import(globals(), """
17
21
from binascii import hexlify
18
22
from copy import deepcopy
19
 
from cStringIO import StringIO
20
23
import re
21
24
import time
22
 
from unittest import TestSuite
 
25
import unittest
23
26
 
24
27
from bzrlib import (
25
 
    bzrdir, 
26
 
    check, 
27
 
    delta, 
28
 
    gpg, 
29
 
    errors, 
 
28
    bzrdir,
 
29
    check,
 
30
    delta,
 
31
    errors,
 
32
    generate_ids,
 
33
    gpg,
 
34
    graph,
 
35
    knit,
 
36
    lazy_regex,
 
37
    lockable_files,
 
38
    lockdir,
30
39
    osutils,
 
40
    registry,
 
41
    revision as _mod_revision,
 
42
    symbol_versioning,
31
43
    transactions,
32
 
    ui, 
33
 
    xml5, 
 
44
    ui,
 
45
    weave,
 
46
    weavefile,
 
47
    xml5,
34
48
    xml6,
35
49
    )
 
50
from bzrlib.osutils import (
 
51
    rand_bytes,
 
52
    compact_date, 
 
53
    local_time_offset,
 
54
    )
 
55
from bzrlib.revisiontree import RevisionTree
 
56
from bzrlib.store.versioned import VersionedFileStore
 
57
from bzrlib.store.text import TextStore
 
58
from bzrlib.testament import Testament
 
59
""")
 
60
 
36
61
from bzrlib.decorators import needs_read_lock, needs_write_lock
37
 
from bzrlib.errors import InvalidRevisionId
38
 
from bzrlib.graph import Graph
39
62
from bzrlib.inter import InterObject
40
63
from bzrlib.inventory import Inventory, InventoryDirectory, ROOT_ID
41
 
from bzrlib.knit import KnitVersionedFile, KnitPlainFactory
42
 
from bzrlib.lockable_files import LockableFiles, TransportLock
43
 
from bzrlib.lockdir import LockDir
44
 
from bzrlib.osutils import (safe_unicode, rand_bytes, compact_date, 
45
 
                            local_time_offset)
46
 
from bzrlib.revision import NULL_REVISION, Revision
47
 
from bzrlib.revisiontree import RevisionTree
48
 
from bzrlib.store.versioned import VersionedFileStore, WeaveStore
49
 
from bzrlib.store.text import TextStore
50
 
from bzrlib import symbol_versioning
51
 
from bzrlib.symbol_versioning import (deprecated_method,
52
 
        zero_nine, 
 
64
from bzrlib.symbol_versioning import (
 
65
        deprecated_method,
 
66
        zero_nine,
53
67
        )
54
 
from bzrlib.testament import Testament
55
68
from bzrlib.trace import mutter, note, warning
56
 
from bzrlib.tsort import topo_sort
57
 
from bzrlib.weave import WeaveFile
58
69
 
59
70
 
60
71
# Old formats display a warning, but only once
73
84
    remote) disk.
74
85
    """
75
86
 
 
87
    _file_ids_altered_regex = lazy_regex.lazy_compile(
 
88
        r'file_id="(?P<file_id>[^"]+)"'
 
89
        r'.*revision="(?P<revision_id>[^"]+)"'
 
90
        )
 
91
 
76
92
    @needs_write_lock
77
93
    def add_inventory(self, revid, inv, parents):
78
94
        """Add the inventory inv to the repository as revid.
82
98
 
83
99
        returns the sha1 of the serialized inventory.
84
100
        """
 
101
        _mod_revision.check_not_reserved_id(revid)
85
102
        assert inv.revision_id is None or inv.revision_id == revid, \
86
103
            "Mismatch between inventory revision" \
87
104
            " id and insertion revid (%r, %r)" % (inv.revision_id, revid)
113
130
                       If supplied its signature_needed method will be used
114
131
                       to determine if a signature should be made.
115
132
        """
 
133
        _mod_revision.check_not_reserved_id(rev_id)
116
134
        if config is not None and config.signature_needed():
117
135
            if inv is None:
118
136
                inv = self.get_inventory(rev_id)
317
335
        or testing the revision graph.
318
336
        """
319
337
        if not revision_id or not isinstance(revision_id, basestring):
320
 
            raise InvalidRevisionId(revision_id=revision_id, branch=self)
 
338
            raise errors.InvalidRevisionId(revision_id=revision_id,
 
339
                                           branch=self)
321
340
        return self._revision_store.get_revisions([revision_id],
322
341
                                                  self.get_transaction())[0]
323
342
    @needs_read_lock
426
445
        # revisions. We don't need to see all lines in the inventory because
427
446
        # only those added in an inventory in rev X can contain a revision=X
428
447
        # line.
 
448
        unescape_revid_cache = {}
 
449
        unescape_fileid_cache = {}
 
450
 
 
451
        # jam 20061218 In a big fetch, this handles hundreds of thousands
 
452
        # of lines, so it has had a lot of inlining and optimizing done.
 
453
        # Sorry that it is a little bit messy.
 
454
        # Move several functions to be local variables, since this is a long
 
455
        # running loop.
 
456
        search = self._file_ids_altered_regex.search
 
457
        unescape = _unescape_xml
 
458
        setdefault = result.setdefault
429
459
        pb = ui.ui_factory.nested_progress_bar()
430
460
        try:
431
461
            for line in w.iter_lines_added_or_present_in_versions(
432
 
                selected_revision_ids, pb=pb):
433
 
                start = line.find('file_id="')+9
434
 
                if start < 9: continue
435
 
                end = line.find('"', start)
436
 
                assert end>= 0
437
 
                file_id = _unescape_xml(line[start:end])
438
 
 
439
 
                start = line.find('revision="')+10
440
 
                if start < 10: continue
441
 
                end = line.find('"', start)
442
 
                assert end>= 0
443
 
                revision_id = _unescape_xml(line[start:end])
 
462
                                        selected_revision_ids, pb=pb):
 
463
                match = search(line)
 
464
                if match is None:
 
465
                    continue
 
466
                # One call to match.group() returning multiple items is quite a
 
467
                # bit faster than 2 calls to match.group() each returning 1
 
468
                file_id, revision_id = match.group('file_id', 'revision_id')
 
469
 
 
470
                # Inlining the cache lookups helps a lot when you make 170,000
 
471
                # lines and 350k ids, versus 8.4 unique ids.
 
472
                # Using a cache helps in 2 ways:
 
473
                #   1) Avoids unnecessary decoding calls
 
474
                #   2) Re-uses cached strings, which helps in future set and
 
475
                #      equality checks.
 
476
                # (2) is enough that removing encoding entirely along with
 
477
                # the cache (so we are using plain strings) results in no
 
478
                # performance improvement.
 
479
                try:
 
480
                    revision_id = unescape_revid_cache[revision_id]
 
481
                except KeyError:
 
482
                    unescaped = unescape(revision_id)
 
483
                    unescape_revid_cache[revision_id] = unescaped
 
484
                    revision_id = unescaped
 
485
 
444
486
                if revision_id in selected_revision_ids:
445
 
                    result.setdefault(file_id, set()).add(revision_id)
 
487
                    try:
 
488
                        file_id = unescape_fileid_cache[file_id]
 
489
                    except KeyError:
 
490
                        unescaped = unescape(file_id)
 
491
                        unescape_fileid_cache[file_id] = unescaped
 
492
                        file_id = unescaped
 
493
                    setdefault(file_id, set()).add(revision_id)
446
494
        finally:
447
495
            pb.finished()
448
496
        return result
497
545
        :return: a dictionary of revision_id->revision_parents_list.
498
546
        """
499
547
        # special case NULL_REVISION
500
 
        if revision_id == NULL_REVISION:
 
548
        if revision_id == _mod_revision.NULL_REVISION:
501
549
            return {}
502
 
        weave = self.get_inventory_weave()
503
 
        all_revisions = self._eliminate_revisions_not_present(weave.versions())
504
 
        entire_graph = dict([(node, weave.get_parents(node)) for 
 
550
        a_weave = self.get_inventory_weave()
 
551
        all_revisions = self._eliminate_revisions_not_present(
 
552
                                a_weave.versions())
 
553
        entire_graph = dict([(node, a_weave.get_parents(node)) for 
505
554
                             node in all_revisions])
506
555
        if revision_id is None:
507
556
            return entire_graph
526
575
        :param revision_ids: an iterable of revisions to graph or None for all.
527
576
        :return: a Graph object with the graph reachable from revision_ids.
528
577
        """
529
 
        result = Graph()
 
578
        result = graph.Graph()
530
579
        if not revision_ids:
531
580
            pending = set(self.all_revision_ids())
532
581
            required = set([])
533
582
        else:
534
583
            pending = set(revision_ids)
535
584
            # special case NULL_REVISION
536
 
            if NULL_REVISION in pending:
537
 
                pending.remove(NULL_REVISION)
 
585
            if _mod_revision.NULL_REVISION in pending:
 
586
                pending.remove(_mod_revision.NULL_REVISION)
538
587
            required = set(pending)
539
588
        done = set([])
540
589
        while len(pending):
594
643
        """
595
644
        # TODO: refactor this to use an existing revision object
596
645
        # so we don't need to read it in twice.
597
 
        if revision_id is None or revision_id == NULL_REVISION:
598
 
            return RevisionTree(self, Inventory(), NULL_REVISION)
 
646
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
 
647
            return RevisionTree(self, Inventory(root_id=None), 
 
648
                                _mod_revision.NULL_REVISION)
599
649
        else:
600
650
            inv = self.get_revision_inventory(revision_id)
601
651
            return RevisionTree(self, inv, revision_id)
606
656
 
607
657
        `revision_id` may not be None or 'null:'"""
608
658
        assert None not in revision_ids
609
 
        assert NULL_REVISION not in revision_ids
 
659
        assert _mod_revision.NULL_REVISION not in revision_ids
610
660
        texts = self.get_inventory_weave().get_texts(revision_ids)
611
661
        for text, revision_id in zip(texts, revision_ids):
612
662
            inv = self.deserialise_inventory(revision_id, text)
717
767
    def supports_rich_root(self):
718
768
        return self._format.rich_root_data
719
769
 
 
770
    def _check_ascii_revisionid(self, revision_id, method):
 
771
        """Private helper for ascii-only repositories."""
 
772
        # weave repositories refuse to store revisionids that are non-ascii.
 
773
        if revision_id is not None:
 
774
            # weaves require ascii revision ids.
 
775
            if isinstance(revision_id, unicode):
 
776
                try:
 
777
                    revision_id.encode('ascii')
 
778
                except UnicodeEncodeError:
 
779
                    raise errors.NonAsciiRevisionId(method, self)
 
780
 
720
781
 
721
782
class AllInOneRepository(Repository):
722
783
    """Legacy support - the repository behaviour for all-in-one branches."""
751
812
            text_store = get_store('text-store')
752
813
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
753
814
 
 
815
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
816
                           timezone=None, committer=None, revprops=None,
 
817
                           revision_id=None):
 
818
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
 
819
        return Repository.get_commit_builder(self, branch, parents, config,
 
820
            timestamp, timezone, committer, revprops, revision_id)
 
821
 
754
822
    @needs_read_lock
755
823
    def is_shared(self):
756
824
        """AllInOne repositories cannot be shared."""
862
930
        return not self.control_files._transport.has('no-working-trees')
863
931
 
864
932
 
 
933
class WeaveMetaDirRepository(MetaDirRepository):
 
934
    """A subclass of MetaDirRepository to set weave specific policy."""
 
935
 
 
936
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
937
                           timezone=None, committer=None, revprops=None,
 
938
                           revision_id=None):
 
939
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
 
940
        return MetaDirRepository.get_commit_builder(self, branch, parents,
 
941
            config, timestamp, timezone, committer, revprops, revision_id)
 
942
 
 
943
 
865
944
class KnitRepository(MetaDirRepository):
866
945
    """Knit format repository."""
867
946
 
933
1012
        :return: a dictionary of revision_id->revision_parents_list.
934
1013
        """
935
1014
        # special case NULL_REVISION
936
 
        if revision_id == NULL_REVISION:
 
1015
        if revision_id == _mod_revision.NULL_REVISION:
937
1016
            return {}
938
 
        weave = self._get_revision_vf()
939
 
        entire_graph = weave.get_graph()
 
1017
        a_weave = self._get_revision_vf()
 
1018
        entire_graph = a_weave.get_graph()
940
1019
        if revision_id is None:
941
 
            return weave.get_graph()
942
 
        elif revision_id not in weave:
 
1020
            return a_weave.get_graph()
 
1021
        elif revision_id not in a_weave:
943
1022
            raise errors.NoSuchRevision(self, revision_id)
944
1023
        else:
945
1024
            # add what can be reached from revision_id
947
1026
            pending = set([revision_id])
948
1027
            while len(pending) > 0:
949
1028
                node = pending.pop()
950
 
                result[node] = weave.get_parents(node)
 
1029
                result[node] = a_weave.get_parents(node)
951
1030
                for revision_id in result[node]:
952
1031
                    if revision_id not in result:
953
1032
                        pending.add(revision_id)
960
1039
        :param revision_ids: an iterable of revisions to graph or None for all.
961
1040
        :return: a Graph object with the graph reachable from revision_ids.
962
1041
        """
963
 
        result = Graph()
 
1042
        result = graph.Graph()
964
1043
        vf = self._get_revision_vf()
965
1044
        versions = set(vf.versions())
966
1045
        if not revision_ids:
969
1048
        else:
970
1049
            pending = set(revision_ids)
971
1050
            # special case NULL_REVISION
972
 
            if NULL_REVISION in pending:
973
 
                pending.remove(NULL_REVISION)
 
1051
            if _mod_revision.NULL_REVISION in pending:
 
1052
                pending.remove(_mod_revision.NULL_REVISION)
974
1053
            required = set(pending)
975
1054
        done = set([])
976
1055
        while len(pending):
1057
1136
                                 committer, revprops, revision_id)
1058
1137
 
1059
1138
 
 
1139
class RepositoryFormatRegistry(registry.Registry):
 
1140
    """Registry of RepositoryFormats.
 
1141
    """
 
1142
    
 
1143
 
 
1144
format_registry = RepositoryFormatRegistry()
 
1145
"""Registry of formats, indexed by their identifying format string."""
 
1146
 
 
1147
 
1060
1148
class RepositoryFormat(object):
1061
1149
    """A repository format.
1062
1150
 
1081
1169
    parameterisation.
1082
1170
    """
1083
1171
 
1084
 
    _default_format = None
1085
 
    """The default format used for new repositories."""
1086
 
 
1087
 
    _formats = {}
1088
 
    """The known formats."""
1089
 
 
1090
1172
    def __str__(self):
1091
1173
        return "<%s>" % self.__class__.__name__
1092
1174
 
1093
1175
    @classmethod
1094
1176
    def find_format(klass, a_bzrdir):
1095
 
        """Return the format for the repository object in a_bzrdir."""
 
1177
        """Return the format for the repository object in a_bzrdir.
 
1178
        
 
1179
        This is used by bzr native formats that have a "format" file in
 
1180
        the repository.  Other methods may be used by different types of 
 
1181
        control directory.
 
1182
        """
1096
1183
        try:
1097
1184
            transport = a_bzrdir.get_repository_transport(None)
1098
1185
            format_string = transport.get("format").read()
1099
 
            return klass._formats[format_string]
 
1186
            return format_registry.get(format_string)
1100
1187
        except errors.NoSuchFile:
1101
1188
            raise errors.NoRepositoryPresent(a_bzrdir)
1102
1189
        except KeyError:
1103
1190
            raise errors.UnknownFormatError(format=format_string)
1104
1191
 
1105
 
    def _get_control_store(self, repo_transport, control_files):
1106
 
        """Return the control store for this repository."""
1107
 
        raise NotImplementedError(self._get_control_store)
 
1192
    @classmethod
 
1193
    @deprecated_method(symbol_versioning.zero_fourteen)
 
1194
    def set_default_format(klass, format):
 
1195
        klass._set_default_format(format)
 
1196
 
 
1197
    @classmethod
 
1198
    def _set_default_format(klass, format):
 
1199
        """Set the default format for new Repository creation.
 
1200
 
 
1201
        The format must already be registered.
 
1202
        """
 
1203
        format_registry.default_key = format.get_format_string()
 
1204
 
 
1205
    @classmethod
 
1206
    def register_format(klass, format):
 
1207
        format_registry.register(format.get_format_string(), format)
 
1208
 
 
1209
    @classmethod
 
1210
    def unregister_format(klass, format):
 
1211
        format_registry.remove(format.get_format_string())
1108
1212
    
1109
1213
    @classmethod
1110
1214
    def get_default_format(klass):
1111
1215
        """Return the current default format."""
1112
 
        return klass._default_format
 
1216
        return format_registry.get(format_registry.default_key)
 
1217
 
 
1218
    def _get_control_store(self, repo_transport, control_files):
 
1219
        """Return the control store for this repository."""
 
1220
        raise NotImplementedError(self._get_control_store)
1113
1221
 
1114
1222
    def get_format_string(self):
1115
1223
        """Return the ASCII format string that identifies this format.
1155
1263
                                  transport,
1156
1264
                                  control_files,
1157
1265
                                  prefixed=True,
1158
 
                                  versionedfile_class=WeaveFile,
 
1266
                                  versionedfile_class=weave.WeaveFile,
1159
1267
                                  versionedfile_kwargs={},
1160
1268
                                  escaped=False):
1161
1269
        weave_transport = control_files._transport.clone(name)
1197
1305
        """
1198
1306
        raise NotImplementedError(self.open)
1199
1307
 
1200
 
    @classmethod
1201
 
    def register_format(klass, format):
1202
 
        klass._formats[format.get_format_string()] = format
1203
 
 
1204
 
    @classmethod
1205
 
    def set_default_format(klass, format):
1206
 
        klass._default_format = format
1207
 
 
1208
 
    @classmethod
1209
 
    def unregister_format(klass, format):
1210
 
        assert klass._formats[format.get_format_string()] is format
1211
 
        del klass._formats[format.get_format_string()]
1212
 
 
1213
1308
 
1214
1309
class PreSplitOutRepositoryFormat(RepositoryFormat):
1215
1310
    """Base class for the pre split out repository formats."""
1222
1317
        TODO: when creating split out bzr branch formats, move this to a common
1223
1318
        base for Format5, Format6. or something like that.
1224
1319
        """
1225
 
        from bzrlib.weavefile import write_weave_v5
1226
 
        from bzrlib.weave import Weave
1227
 
 
1228
1320
        if shared:
1229
1321
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
1230
1322
 
1234
1326
        
1235
1327
        # Create an empty weave
1236
1328
        sio = StringIO()
1237
 
        write_weave_v5(Weave(), sio)
 
1329
        weavefile.write_weave_v5(weave.Weave(), sio)
1238
1330
        empty_weave = sio.getvalue()
1239
1331
 
1240
1332
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1244
1336
        
1245
1337
        # FIXME: RBC 20060125 don't peek under the covers
1246
1338
        # NB: no need to escape relative paths that are url safe.
1247
 
        control_files = LockableFiles(a_bzrdir.transport, 'branch-lock',
1248
 
                                      TransportLock)
 
1339
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
 
1340
                                'branch-lock', lockable_files.TransportLock)
1249
1341
        control_files.create_lock()
1250
1342
        control_files.lock_write()
1251
1343
        control_files._transport.mkdir_multi(dirs,
1415
1507
        # FIXME: RBC 20060125 don't peek under the covers
1416
1508
        # NB: no need to escape relative paths that are url safe.
1417
1509
        repository_transport = a_bzrdir.get_repository_transport(self)
1418
 
        control_files = LockableFiles(repository_transport, 'lock', LockDir)
 
1510
        control_files = lockable_files.LockableFiles(repository_transport,
 
1511
                                'lock', lockdir.LockDir)
1419
1512
        control_files.create_lock()
1420
1513
        return control_files
1421
1514
 
1487
1580
        :param shared: If true the repository will be initialized as a shared
1488
1581
                       repository.
1489
1582
        """
1490
 
        from bzrlib.weavefile import write_weave_v5
1491
 
        from bzrlib.weave import Weave
1492
 
 
1493
1583
        # Create an empty weave
1494
1584
        sio = StringIO()
1495
 
        write_weave_v5(Weave(), sio)
 
1585
        weavefile.write_weave_v5(weave.Weave(), sio)
1496
1586
        empty_weave = sio.getvalue()
1497
1587
 
1498
1588
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1518
1608
            repo_transport = _override_transport
1519
1609
        else:
1520
1610
            repo_transport = a_bzrdir.get_repository_transport(None)
1521
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1611
        control_files = lockable_files.LockableFiles(repo_transport,
 
1612
                                'lock', lockdir.LockDir)
1522
1613
        text_store = self._get_text_store(repo_transport, control_files)
1523
1614
        control_store = self._get_control_store(repo_transport, control_files)
1524
1615
        _revision_store = self._get_revision_store(repo_transport, control_files)
1525
 
        return MetaDirRepository(_format=self,
1526
 
                                 a_bzrdir=a_bzrdir,
1527
 
                                 control_files=control_files,
1528
 
                                 _revision_store=_revision_store,
1529
 
                                 control_store=control_store,
1530
 
                                 text_store=text_store)
 
1616
        return WeaveMetaDirRepository(_format=self,
 
1617
            a_bzrdir=a_bzrdir,
 
1618
            control_files=control_files,
 
1619
            _revision_store=_revision_store,
 
1620
            control_store=control_store,
 
1621
            text_store=text_store)
1531
1622
 
1532
1623
 
1533
1624
class RepositoryFormatKnit(MetaDirRepositoryFormat):
1550
1641
            repo_transport,
1551
1642
            prefixed=False,
1552
1643
            file_mode=control_files._file_mode,
1553
 
            versionedfile_class=KnitVersionedFile,
1554
 
            versionedfile_kwargs={'factory':KnitPlainFactory()},
 
1644
            versionedfile_class=knit.KnitVersionedFile,
 
1645
            versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1555
1646
            )
1556
1647
 
1557
1648
    def _get_revision_store(self, repo_transport, control_files):
1562
1653
            file_mode=control_files._file_mode,
1563
1654
            prefixed=False,
1564
1655
            precious=True,
1565
 
            versionedfile_class=KnitVersionedFile,
1566
 
            versionedfile_kwargs={'delta':False, 'factory':KnitPlainFactory(),},
 
1656
            versionedfile_class=knit.KnitVersionedFile,
 
1657
            versionedfile_kwargs={'delta':False,
 
1658
                                  'factory':knit.KnitPlainFactory(),
 
1659
                                 },
1567
1660
            escaped=True,
1568
1661
            )
1569
1662
        return KnitRevisionStore(versioned_file_store)
1571
1664
    def _get_text_store(self, transport, control_files):
1572
1665
        """See RepositoryFormat._get_text_store()."""
1573
1666
        return self._get_versioned_file_store('knits',
1574
 
                                              transport,
1575
 
                                              control_files,
1576
 
                                              versionedfile_class=KnitVersionedFile,
1577
 
                                              versionedfile_kwargs={
1578
 
                                                  'create_parent_dir':True,
1579
 
                                                  'delay_create':True,
1580
 
                                                  'dir_mode':control_files._dir_mode,
1581
 
                                              },
1582
 
                                              escaped=True)
 
1667
                                  transport,
 
1668
                                  control_files,
 
1669
                                  versionedfile_class=knit.KnitVersionedFile,
 
1670
                                  versionedfile_kwargs={
 
1671
                                      'create_parent_dir':True,
 
1672
                                      'delay_create':True,
 
1673
                                      'dir_mode':control_files._dir_mode,
 
1674
                                  },
 
1675
                                  escaped=True)
1583
1676
 
1584
1677
    def initialize(self, a_bzrdir, shared=False):
1585
1678
        """Create a knit format 1 repository.
1596
1689
        
1597
1690
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1598
1691
        repo_transport = a_bzrdir.get_repository_transport(None)
1599
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1692
        control_files = lockable_files.LockableFiles(repo_transport,
 
1693
                                'lock', lockdir.LockDir)
1600
1694
        control_store = self._get_control_store(repo_transport, control_files)
1601
1695
        transaction = transactions.WriteTransaction()
1602
1696
        # trigger a write of the inventory store.
1603
1697
        control_store.get_weave_or_empty('inventory', transaction)
1604
1698
        _revision_store = self._get_revision_store(repo_transport, control_files)
 
1699
        # the revision id here is irrelevant: it will not be stored, and cannot
 
1700
        # already exist.
1605
1701
        _revision_store.has_revision_id('A', transaction)
1606
1702
        _revision_store.get_signature_file(transaction)
1607
1703
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1620
1716
            repo_transport = _override_transport
1621
1717
        else:
1622
1718
            repo_transport = a_bzrdir.get_repository_transport(None)
1623
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1719
        control_files = lockable_files.LockableFiles(repo_transport,
 
1720
                                'lock', lockdir.LockDir)
1624
1721
        text_store = self._get_text_store(repo_transport, control_files)
1625
1722
        control_store = self._get_control_store(repo_transport, control_files)
1626
1723
        _revision_store = self._get_revision_store(repo_transport, control_files)
1705
1802
            repo_transport = _override_transport
1706
1803
        else:
1707
1804
            repo_transport = a_bzrdir.get_repository_transport(None)
1708
 
        control_files = LockableFiles(repo_transport, 'lock', LockDir)
 
1805
        control_files = lockable_files.LockableFiles(repo_transport, 'lock',
 
1806
                                                     lockdir.LockDir)
1709
1807
        text_store = self._get_text_store(repo_transport, control_files)
1710
1808
        control_store = self._get_control_store(repo_transport, control_files)
1711
1809
        _revision_store = self._get_revision_store(repo_transport, control_files)
1721
1819
# formats which have no format string are not discoverable
1722
1820
# and not independently creatable, so are not registered.
1723
1821
RepositoryFormat.register_format(RepositoryFormat7())
 
1822
# KEEP in sync with bzrdir.format_registry default, which controls the overall
 
1823
# default control directory format
1724
1824
_default_format = RepositoryFormatKnit1()
1725
1825
RepositoryFormat.register_format(_default_format)
1726
1826
RepositoryFormat.register_format(RepositoryFormatKnit2())
1727
 
RepositoryFormat.set_default_format(_default_format)
 
1827
RepositoryFormat._set_default_format(_default_format)
1728
1828
_legacy_formats = [RepositoryFormat4(),
1729
1829
                   RepositoryFormat5(),
1730
1830
                   RepositoryFormat6()]
1826
1926
        if basis is not None:
1827
1927
            self.target.fetch(basis, revision_id=revision_id)
1828
1928
        # but don't bother fetching if we have the needed data now.
1829
 
        if (revision_id not in (None, NULL_REVISION) and 
 
1929
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
1830
1930
            self.target.has_revision(revision_id)):
1831
1931
            return
1832
1932
        self.target.fetch(self.source, revision_id=revision_id)
2070
2170
        if basis is not None:
2071
2171
            self.target.fetch(basis, revision_id=revision_id)
2072
2172
        # but don't bother fetching if we have the needed data now.
2073
 
        if (revision_id not in (None, NULL_REVISION) and 
 
2173
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
2074
2174
            self.target.has_revision(revision_id)):
2075
2175
            return
2076
2176
        self.target.fetch(self.source, revision_id=revision_id)
2125
2225
        self._formats = formats
2126
2226
    
2127
2227
    def adapt(self, test):
2128
 
        result = TestSuite()
 
2228
        result = unittest.TestSuite()
2129
2229
        for repository_format, bzrdir_format in self._formats:
2130
2230
            new_test = deepcopy(test)
2131
2231
            new_test.transport_server = self._transport_server
2155
2255
        self._formats = formats
2156
2256
    
2157
2257
    def adapt(self, test):
2158
 
        result = TestSuite()
 
2258
        result = unittest.TestSuite()
2159
2259
        for interrepo_class, repository_format, repository_format_to in self._formats:
2160
2260
            new_test = deepcopy(test)
2161
2261
            new_test.transport_server = self._transport_server
2304
2404
 
2305
2405
        :return: The revision id of the recorded revision.
2306
2406
        """
2307
 
        rev = Revision(timestamp=self._timestamp,
 
2407
        rev = _mod_revision.Revision(
 
2408
                       timestamp=self._timestamp,
2308
2409
                       timezone=self._timezone,
2309
2410
                       committer=self._committer,
2310
2411
                       message=message,
2344
2445
 
2345
2446
    def _gen_revision_id(self):
2346
2447
        """Return new revision-id."""
2347
 
        s = '%s-%s-' % (self._config.user_email(), 
2348
 
                        compact_date(self._timestamp))
2349
 
        s += hexlify(rand_bytes(8))
2350
 
        return s
 
2448
        return generate_ids.gen_revision_id(self._config.username(),
 
2449
                                            self._timestamp)
2351
2450
 
2352
2451
    def _generate_revision_if_needed(self):
2353
2452
        """Create a revision id if None was supplied.
2354
2453
        
2355
2454
        If the repository can not support user-specified revision ids
2356
 
        they should override this function and raise UnsupportedOperation
 
2455
        they should override this function and raise CannotSetRevisionId
2357
2456
        if _new_revision_id is not None.
2358
2457
 
2359
 
        :raises: UnsupportedOperation
 
2458
        :raises: CannotSetRevisionId
2360
2459
        """
2361
2460
        if self._new_revision_id is None:
2362
2461
            self._new_revision_id = self._gen_revision_id()
2522
2621
    """Unescape predefined XML entities in a string of data."""
2523
2622
    global _unescape_re
2524
2623
    if _unescape_re is None:
2525
 
        _unescape_re = re.compile('\&([^;]*);')
 
2624
        _unescape_re = re.compile('\&([^;]*);')
2526
2625
    return _unescape_re.sub(_unescaper, data)