~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

  • Committer: John Arbash Meinel
  • Date: 2007-02-13 20:33:57 UTC
  • mfrom: (2283 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2294.
  • Revision ID: john@arbash-meinel.com-20070213203357-b7yg41mi9sk6cqd0
[merge] bzr.dev 2283
resolve conflicts in moved repository formats
small issue with osutils.contains_whitespace()

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from bzrlib.lazy_import import lazy_import
20
20
lazy_import(globals(), """
21
 
from binascii import hexlify
22
 
from copy import deepcopy
23
21
import re
24
22
import time
25
23
import unittest
27
25
from bzrlib import (
28
26
    bzrdir,
29
27
    check,
30
 
    delta,
31
28
    errors,
32
29
    generate_ids,
33
30
    gpg,
34
31
    graph,
35
 
    knit,
36
32
    lazy_regex,
37
33
    lockable_files,
38
34
    lockdir,
42
38
    symbol_versioning,
43
39
    transactions,
44
40
    ui,
45
 
    weave,
46
 
    weavefile,
47
 
    xml5,
48
 
    xml6,
49
 
    )
50
 
from bzrlib.osutils import (
51
 
    rand_bytes,
52
 
    compact_date, 
53
 
    local_time_offset,
54
41
    )
55
42
from bzrlib.revisiontree import RevisionTree
56
43
from bzrlib.store.versioned import VersionedFileStore
57
44
from bzrlib.store.text import TextStore
58
45
from bzrlib.testament import Testament
 
46
 
59
47
""")
60
48
 
61
49
from bzrlib.decorators import needs_read_lock, needs_write_lock
232
220
        # TODO: make sure to construct the right store classes, etc, depending
233
221
        # on whether escaping is required.
234
222
        self._warn_if_deprecated()
235
 
        self._serializer = xml5.serializer_v5
236
223
 
237
224
    def __repr__(self):
238
225
        return '%s(%r)' % (self.__class__.__name__, 
251
238
        return self.control_files.get_physical_lock_status()
252
239
 
253
240
    @needs_read_lock
 
241
    def gather_stats(self, revid=None, committers=None):
 
242
        """Gather statistics from a revision id.
 
243
 
 
244
        :param revid: The revision id to gather statistics from, if None, then
 
245
            no revision specific statistics are gathered.
 
246
        :param committers: Optional parameter controlling whether to grab
 
247
            a count of committers from the revision specific statistics.
 
248
        :return: A dictionary of statistics. Currently this contains:
 
249
            committers: The number of committers if requested.
 
250
            firstrev: A tuple with timestamp, timezone for the penultimate left
 
251
                most ancestor of revid, if revid is not the NULL_REVISION.
 
252
            latestrev: A tuple with timestamp, timezone for revid, if revid is
 
253
                not the NULL_REVISION.
 
254
            revisions: The total revision count in the repository.
 
255
            size: An estimate disk size of the repository in bytes.
 
256
        """
 
257
        result = {}
 
258
        if revid and committers:
 
259
            result['committers'] = 0
 
260
        if revid and revid != _mod_revision.NULL_REVISION:
 
261
            if committers:
 
262
                all_committers = set()
 
263
            revisions = self.get_ancestry(revid)
 
264
            # pop the leading None
 
265
            revisions.pop(0)
 
266
            first_revision = None
 
267
            if not committers:
 
268
                # ignore the revisions in the middle - just grab first and last
 
269
                revisions = revisions[0], revisions[-1]
 
270
            for revision in self.get_revisions(revisions):
 
271
                if not first_revision:
 
272
                    first_revision = revision
 
273
                if committers:
 
274
                    all_committers.add(revision.committer)
 
275
            last_revision = revision
 
276
            if committers:
 
277
                result['committers'] = len(all_committers)
 
278
            result['firstrev'] = (first_revision.timestamp,
 
279
                first_revision.timezone)
 
280
            result['latestrev'] = (last_revision.timestamp,
 
281
                last_revision.timezone)
 
282
 
 
283
        # now gather global repository information
 
284
        if self.bzrdir.root_transport.listable():
 
285
            c, t = self._revision_store.total_size(self.get_transaction())
 
286
            result['revisions'] = c
 
287
            result['size'] = t
 
288
        return result
 
289
 
 
290
    @needs_read_lock
254
291
    def missing_revision_ids(self, other, revision_id=None):
255
292
        """Return the revision ids that other has that this does not.
256
293
        
316
353
 
317
354
        Currently no check is made that the format of this repository and
318
355
        the bzrdir format are compatible. FIXME RBC 20060201.
 
356
 
 
357
        :return: The newly created destination repository.
319
358
        """
320
359
        if not isinstance(a_bzrdir._format, self.bzrdir._format.__class__):
321
360
            # use target default format.
322
 
            result = a_bzrdir.create_repository()
323
 
        # FIXME RBC 20060209 split out the repository type to avoid this check ?
324
 
        elif isinstance(a_bzrdir._format,
325
 
                      (bzrdir.BzrDirFormat4,
326
 
                       bzrdir.BzrDirFormat5,
327
 
                       bzrdir.BzrDirFormat6)):
328
 
            result = a_bzrdir.open_repository()
 
361
            dest_repo = a_bzrdir.create_repository()
329
362
        else:
330
 
            result = self._format.initialize(a_bzrdir, shared=self.is_shared())
331
 
        self.copy_content_into(result, revision_id, basis)
332
 
        return result
 
363
            # Most control formats need the repository to be specifically
 
364
            # created, but on some old all-in-one formats it's not needed
 
365
            try:
 
366
                dest_repo = self._format.initialize(a_bzrdir, shared=self.is_shared())
 
367
            except errors.UninitializableFormat:
 
368
                dest_repo = a_bzrdir.open_repository()
 
369
        self.copy_content_into(dest_repo, revision_id, basis)
 
370
        return dest_repo
333
371
 
334
372
    @needs_read_lock
335
373
    def has_revision(self, revision_id):
827
865
                    raise errors.NonAsciiRevisionId(method, self)
828
866
 
829
867
 
830
 
class AllInOneRepository(Repository):
831
 
    """Legacy support - the repository behaviour for all-in-one branches."""
832
 
 
833
 
    def __init__(self, _format, a_bzrdir, _revision_store, control_store, text_store):
834
 
        # we reuse one control files instance.
835
 
        dir_mode = a_bzrdir._control_files._dir_mode
836
 
        file_mode = a_bzrdir._control_files._file_mode
837
 
 
838
 
        def get_store(name, compressed=True, prefixed=False):
839
 
            # FIXME: This approach of assuming stores are all entirely compressed
840
 
            # or entirely uncompressed is tidy, but breaks upgrade from 
841
 
            # some existing branches where there's a mixture; we probably 
842
 
            # still want the option to look for both.
843
 
            relpath = a_bzrdir._control_files._escape(name)
844
 
            store = TextStore(a_bzrdir._control_files._transport.clone(relpath),
845
 
                              prefixed=prefixed, compressed=compressed,
846
 
                              dir_mode=dir_mode,
847
 
                              file_mode=file_mode)
848
 
            #if self._transport.should_cache():
849
 
            #    cache_path = os.path.join(self.cache_root, name)
850
 
            #    os.mkdir(cache_path)
851
 
            #    store = bzrlib.store.CachedStore(store, cache_path)
852
 
            return store
853
 
 
854
 
        # not broken out yet because the controlweaves|inventory_store
855
 
        # and text_store | weave_store bits are still different.
856
 
        if isinstance(_format, RepositoryFormat4):
857
 
            # cannot remove these - there is still no consistent api 
858
 
            # which allows access to this old info.
859
 
            self.inventory_store = get_store('inventory-store')
860
 
            text_store = get_store('text-store')
861
 
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
862
 
 
863
 
    def get_commit_builder(self, branch, parents, config, timestamp=None,
864
 
                           timezone=None, committer=None, revprops=None,
865
 
                           revision_id=None):
866
 
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
867
 
        return Repository.get_commit_builder(self, branch, parents, config,
868
 
            timestamp, timezone, committer, revprops, revision_id)
869
 
 
870
 
    @needs_read_lock
871
 
    def is_shared(self):
872
 
        """AllInOne repositories cannot be shared."""
873
 
        return False
874
 
 
875
 
    @needs_write_lock
876
 
    def set_make_working_trees(self, new_value):
877
 
        """Set the policy flag for making working trees when creating branches.
878
 
 
879
 
        This only applies to branches that use this repository.
880
 
 
881
 
        The default is 'True'.
882
 
        :param new_value: True to restore the default, False to disable making
883
 
                          working trees.
884
 
        """
885
 
        raise NotImplementedError(self.set_make_working_trees)
886
 
    
887
 
    def make_working_trees(self):
888
 
        """Returns the policy for making working trees on new branches."""
889
 
        return True
 
868
 
 
869
# remove these delegates a while after bzr 0.15
 
870
def __make_delegated(name, from_module):
 
871
    def _deprecated_repository_forwarder():
 
872
        symbol_versioning.warn('%s moved to %s in bzr 0.15'
 
873
            % (name, from_module),
 
874
            DeprecationWarning,
 
875
            stacklevel=2)
 
876
        m = __import__(from_module, globals(), locals(), [name])
 
877
        try:
 
878
            return getattr(m, name)
 
879
        except AttributeError:
 
880
            raise AttributeError('module %s has no name %s'
 
881
                    % (m, name))
 
882
    globals()[name] = _deprecated_repository_forwarder
 
883
 
 
884
for _name in [
 
885
        'AllInOneRepository',
 
886
        'WeaveMetaDirRepository',
 
887
        'PreSplitOutRepositoryFormat',
 
888
        'RepositoryFormat4',
 
889
        'RepositoryFormat5',
 
890
        'RepositoryFormat6',
 
891
        'RepositoryFormat7',
 
892
        ]:
 
893
    __make_delegated(_name, 'bzrlib.repofmt.weaverepo')
 
894
 
 
895
for _name in [
 
896
        'KnitRepository',
 
897
        'KnitRepository2',
 
898
        'RepositoryFormatKnit',
 
899
        'RepositoryFormatKnit1',
 
900
        'RepositoryFormatKnit2',
 
901
        ]:
 
902
    __make_delegated(_name, 'bzrlib.repofmt.knitrepo')
890
903
 
891
904
 
892
905
def install_revision(repository, rev, revision_tree):
978
991
        return not self.control_files._transport.has('no-working-trees')
979
992
 
980
993
 
981
 
class WeaveMetaDirRepository(MetaDirRepository):
982
 
    """A subclass of MetaDirRepository to set weave specific policy."""
983
 
 
984
 
    def get_commit_builder(self, branch, parents, config, timestamp=None,
985
 
                           timezone=None, committer=None, revprops=None,
986
 
                           revision_id=None):
987
 
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
988
 
        return MetaDirRepository.get_commit_builder(self, branch, parents,
989
 
            config, timestamp, timezone, committer, revprops, revision_id)
990
 
 
991
 
 
992
 
class KnitRepository(MetaDirRepository):
993
 
    """Knit format repository."""
994
 
 
995
 
    def _warn_if_deprecated(self):
996
 
        # This class isn't deprecated
997
 
        pass
998
 
 
999
 
    def _inventory_add_lines(self, inv_vf, revid, parents, lines):
1000
 
        inv_vf.add_lines_with_ghosts(revid, parents, lines)
1001
 
 
1002
 
    @needs_read_lock
1003
 
    def _all_revision_ids(self):
1004
 
        """See Repository.all_revision_ids()."""
1005
 
        # Knits get the revision graph from the index of the revision knit, so
1006
 
        # it's always possible even if they're on an unlistable transport.
1007
 
        return self._revision_store.all_revision_ids(self.get_transaction())
1008
 
 
1009
 
    def fileid_involved_between_revs(self, from_revid, to_revid):
1010
 
        """Find file_id(s) which are involved in the changes between revisions.
1011
 
 
1012
 
        This determines the set of revisions which are involved, and then
1013
 
        finds all file ids affected by those revisions.
1014
 
        """
1015
 
        # TODO: jam 20070210 Is this function even used?
1016
 
        from_revid = osutils.safe_revision_id(from_revid)
1017
 
        to_revid = osutils.safe_revision_id(to_revid)
1018
 
        vf = self._get_revision_vf()
1019
 
        from_set = set(vf.get_ancestry(from_revid))
1020
 
        to_set = set(vf.get_ancestry(to_revid))
1021
 
        changed = to_set.difference(from_set)
1022
 
        return self._fileid_involved_by_set(changed)
1023
 
 
1024
 
    def fileid_involved(self, last_revid=None):
1025
 
        """Find all file_ids modified in the ancestry of last_revid.
1026
 
 
1027
 
        :param last_revid: If None, last_revision() will be used.
1028
 
        """
1029
 
        # TODO: jam 20070210 Is this used anymore?
1030
 
        if not last_revid:
1031
 
            changed = set(self.all_revision_ids())
1032
 
        else:
1033
 
            changed = set(self.get_ancestry(last_revid))
1034
 
        if None in changed:
1035
 
            changed.remove(None)
1036
 
        return self._fileid_involved_by_set(changed)
1037
 
 
1038
 
    @needs_read_lock
1039
 
    def get_ancestry(self, revision_id):
1040
 
        """Return a list of revision-ids integrated by a revision.
1041
 
        
1042
 
        This is topologically sorted.
1043
 
        """
1044
 
        if revision_id is None:
1045
 
            return [None]
1046
 
        revision_id = osutils.safe_revision_id(revision_id)
1047
 
        vf = self._get_revision_vf()
1048
 
        try:
1049
 
            return [None] + vf.get_ancestry(revision_id)
1050
 
        except errors.RevisionNotPresent:
1051
 
            raise errors.NoSuchRevision(self, revision_id)
1052
 
 
1053
 
    @needs_read_lock
1054
 
    def get_revision(self, revision_id):
1055
 
        """Return the Revision object for a named revision"""
1056
 
        revision_id = osutils.safe_revision_id(revision_id)
1057
 
        return self.get_revision_reconcile(revision_id)
1058
 
 
1059
 
    @needs_read_lock
1060
 
    def get_revision_graph(self, revision_id=None):
1061
 
        """Return a dictionary containing the revision graph.
1062
 
 
1063
 
        :param revision_id: The revision_id to get a graph from. If None, then
1064
 
        the entire revision graph is returned. This is a deprecated mode of
1065
 
        operation and will be removed in the future.
1066
 
        :return: a dictionary of revision_id->revision_parents_list.
1067
 
        """
1068
 
        # special case NULL_REVISION
1069
 
        if revision_id == _mod_revision.NULL_REVISION:
1070
 
            return {}
1071
 
        revision_id = osutils.safe_revision_id(revision_id)
1072
 
        a_weave = self._get_revision_vf()
1073
 
        entire_graph = a_weave.get_graph()
1074
 
        if revision_id is None:
1075
 
            return a_weave.get_graph()
1076
 
        elif revision_id not in a_weave:
1077
 
            raise errors.NoSuchRevision(self, revision_id)
1078
 
        else:
1079
 
            # add what can be reached from revision_id
1080
 
            result = {}
1081
 
            pending = set([revision_id])
1082
 
            while len(pending) > 0:
1083
 
                node = pending.pop()
1084
 
                result[node] = a_weave.get_parents(node)
1085
 
                for revision_id in result[node]:
1086
 
                    if revision_id not in result:
1087
 
                        pending.add(revision_id)
1088
 
            return result
1089
 
 
1090
 
    @needs_read_lock
1091
 
    def get_revision_graph_with_ghosts(self, revision_ids=None):
1092
 
        """Return a graph of the revisions with ghosts marked as applicable.
1093
 
 
1094
 
        :param revision_ids: an iterable of revisions to graph or None for all.
1095
 
        :return: a Graph object with the graph reachable from revision_ids.
1096
 
        """
1097
 
        result = graph.Graph()
1098
 
        vf = self._get_revision_vf()
1099
 
        versions = set(vf.versions())
1100
 
        if not revision_ids:
1101
 
            pending = set(self.all_revision_ids())
1102
 
            required = set([])
1103
 
        else:
1104
 
            pending = set(osutils.safe_revision_id(r) for r in revision_ids)
1105
 
            # special case NULL_REVISION
1106
 
            if _mod_revision.NULL_REVISION in pending:
1107
 
                pending.remove(_mod_revision.NULL_REVISION)
1108
 
            required = set(pending)
1109
 
        done = set([])
1110
 
        while len(pending):
1111
 
            revision_id = pending.pop()
1112
 
            if not revision_id in versions:
1113
 
                if revision_id in required:
1114
 
                    raise errors.NoSuchRevision(self, revision_id)
1115
 
                # a ghost
1116
 
                result.add_ghost(revision_id)
1117
 
                # mark it as done so we don't try for it again.
1118
 
                done.add(revision_id)
1119
 
                continue
1120
 
            parent_ids = vf.get_parents_with_ghosts(revision_id)
1121
 
            for parent_id in parent_ids:
1122
 
                # is this queued or done ?
1123
 
                if (parent_id not in pending and
1124
 
                    parent_id not in done):
1125
 
                    # no, queue it.
1126
 
                    pending.add(parent_id)
1127
 
            result.add_node(revision_id, parent_ids)
1128
 
            done.add(revision_id)
1129
 
        return result
1130
 
 
1131
 
    def _get_revision_vf(self):
1132
 
        """:return: a versioned file containing the revisions."""
1133
 
        vf = self._revision_store.get_revision_file(self.get_transaction())
1134
 
        return vf
1135
 
 
1136
 
    @needs_write_lock
1137
 
    def reconcile(self, other=None, thorough=False):
1138
 
        """Reconcile this repository."""
1139
 
        from bzrlib.reconcile import KnitReconciler
1140
 
        reconciler = KnitReconciler(self, thorough=thorough)
1141
 
        reconciler.reconcile()
1142
 
        return reconciler
1143
 
    
1144
 
    def revision_parents(self, revision_id):
1145
 
        revision_id = osutils.safe_revision_id(revision_id)
1146
 
        return self._get_revision_vf().get_parents(revision_id)
1147
 
 
1148
 
 
1149
 
class KnitRepository2(KnitRepository):
1150
 
    """"""
1151
 
    def __init__(self, _format, a_bzrdir, control_files, _revision_store,
1152
 
                 control_store, text_store):
1153
 
        KnitRepository.__init__(self, _format, a_bzrdir, control_files,
1154
 
                              _revision_store, control_store, text_store)
1155
 
        self._serializer = xml6.serializer_v6
1156
 
 
1157
 
    def deserialise_inventory(self, revision_id, xml):
1158
 
        """Transform the xml into an inventory object. 
1159
 
 
1160
 
        :param revision_id: The expected revision id of the inventory.
1161
 
        :param xml: A serialised inventory.
1162
 
        """
1163
 
        result = self._serializer.read_inventory_from_string(xml)
1164
 
        assert result.root.revision is not None
1165
 
        return result
1166
 
 
1167
 
    def serialise_inventory(self, inv):
1168
 
        """Transform the inventory object into XML text.
1169
 
 
1170
 
        :param revision_id: The expected revision id of the inventory.
1171
 
        :param xml: A serialised inventory.
1172
 
        """
1173
 
        assert inv.revision_id is not None
1174
 
        assert inv.root.revision is not None
1175
 
        return KnitRepository.serialise_inventory(self, inv)
1176
 
 
1177
 
    def get_commit_builder(self, branch, parents, config, timestamp=None, 
1178
 
                           timezone=None, committer=None, revprops=None, 
1179
 
                           revision_id=None):
1180
 
        """Obtain a CommitBuilder for this repository.
1181
 
        
1182
 
        :param branch: Branch to commit to.
1183
 
        :param parents: Revision ids of the parents of the new revision.
1184
 
        :param config: Configuration to use.
1185
 
        :param timestamp: Optional timestamp recorded for commit.
1186
 
        :param timezone: Optional timezone for timestamp.
1187
 
        :param committer: Optional committer to set for commit.
1188
 
        :param revprops: Optional dictionary of revision properties.
1189
 
        :param revision_id: Optional revision id.
1190
 
        """
1191
 
        revision_id = osutils.safe_revision_id(revision_id)
1192
 
        return RootCommitBuilder(self, parents, config, timestamp, timezone,
1193
 
                                 committer, revprops, revision_id)
1194
 
 
1195
 
 
1196
994
class RepositoryFormatRegistry(registry.Registry):
1197
995
    """Registry of RepositoryFormats.
1198
996
    """
 
997
 
 
998
    def get(self, format_string):
 
999
        r = registry.Registry.get(self, format_string)
 
1000
        if callable(r):
 
1001
            r = r()
 
1002
        return r
1199
1003
    
1200
1004
 
1201
1005
format_registry = RepositoryFormatRegistry()
1202
 
"""Registry of formats, indexed by their identifying format string."""
 
1006
"""Registry of formats, indexed by their identifying format string.
 
1007
 
 
1008
This can contain either format instances themselves, or classes/factories that
 
1009
can be called to obtain one.
 
1010
"""
1203
1011
 
1204
1012
 
1205
1013
class RepositoryFormat(object):
1229
1037
    def __str__(self):
1230
1038
        return "<%s>" % self.__class__.__name__
1231
1039
 
 
1040
    def __eq__(self, other):
 
1041
        # format objects are generally stateless
 
1042
        return isinstance(other, self.__class__)
 
1043
 
1232
1044
    @classmethod
1233
1045
    def find_format(klass, a_bzrdir):
1234
1046
        """Return the format for the repository object in a_bzrdir.
1247
1059
            raise errors.UnknownFormatError(format=format_string)
1248
1060
 
1249
1061
    @classmethod
1250
 
    @deprecated_method(symbol_versioning.zero_fourteen)
1251
 
    def set_default_format(klass, format):
1252
 
        klass._set_default_format(format)
1253
 
 
1254
 
    @classmethod
1255
 
    def _set_default_format(klass, format):
1256
 
        """Set the default format for new Repository creation.
1257
 
 
1258
 
        The format must already be registered.
1259
 
        """
1260
 
        format_registry.default_key = format.get_format_string()
1261
 
 
1262
 
    @classmethod
1263
1062
    def register_format(klass, format):
1264
1063
        format_registry.register(format.get_format_string(), format)
1265
1064
 
1270
1069
    @classmethod
1271
1070
    def get_default_format(klass):
1272
1071
        """Return the current default format."""
1273
 
        return format_registry.get(format_registry.default_key)
 
1072
        from bzrlib import bzrdir
 
1073
        return bzrdir.format_registry.make_bzrdir('default').repository_format
1274
1074
 
1275
1075
    def _get_control_store(self, repo_transport, control_files):
1276
1076
        """Return the control store for this repository."""
1315
1115
        _revision_store = TextRevisionStore(text_store, serializer)
1316
1116
        return _revision_store
1317
1117
 
 
1118
    # TODO: this shouldn't be in the base class, it's specific to things that
 
1119
    # use weaves or knits -- mbp 20070207
1318
1120
    def _get_versioned_file_store(self,
1319
1121
                                  name,
1320
1122
                                  transport,
1321
1123
                                  control_files,
1322
1124
                                  prefixed=True,
1323
 
                                  versionedfile_class=weave.WeaveFile,
 
1125
                                  versionedfile_class=None,
1324
1126
                                  versionedfile_kwargs={},
1325
1127
                                  escaped=False):
 
1128
        if versionedfile_class is None:
 
1129
            versionedfile_class = self._versionedfile_class
1326
1130
        weave_transport = control_files._transport.clone(name)
1327
1131
        dir_mode = control_files._dir_mode
1328
1132
        file_mode = control_files._file_mode
1363
1167
        raise NotImplementedError(self.open)
1364
1168
 
1365
1169
 
1366
 
class PreSplitOutRepositoryFormat(RepositoryFormat):
1367
 
    """Base class for the pre split out repository formats."""
1368
 
 
1369
 
    rich_root_data = False
1370
 
 
1371
 
    def initialize(self, a_bzrdir, shared=False, _internal=False):
1372
 
        """Create a weave repository.
1373
 
        
1374
 
        TODO: when creating split out bzr branch formats, move this to a common
1375
 
        base for Format5, Format6. or something like that.
1376
 
        """
1377
 
        if shared:
1378
 
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
1379
 
 
1380
 
        if not _internal:
1381
 
            # always initialized when the bzrdir is.
1382
 
            return self.open(a_bzrdir, _found=True)
1383
 
        
1384
 
        # Create an empty weave
1385
 
        sio = StringIO()
1386
 
        weavefile.write_weave_v5(weave.Weave(), sio)
1387
 
        empty_weave = sio.getvalue()
1388
 
 
1389
 
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1390
 
        dirs = ['revision-store', 'weaves']
1391
 
        files = [('inventory.weave', StringIO(empty_weave)),
1392
 
                 ]
1393
 
        
1394
 
        # FIXME: RBC 20060125 don't peek under the covers
1395
 
        # NB: no need to escape relative paths that are url safe.
1396
 
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
1397
 
                                'branch-lock', lockable_files.TransportLock)
1398
 
        control_files.create_lock()
1399
 
        control_files.lock_write()
1400
 
        control_files._transport.mkdir_multi(dirs,
1401
 
                mode=control_files._dir_mode)
1402
 
        try:
1403
 
            for file, content in files:
1404
 
                control_files.put(file, content)
1405
 
        finally:
1406
 
            control_files.unlock()
1407
 
        return self.open(a_bzrdir, _found=True)
1408
 
 
1409
 
    def _get_control_store(self, repo_transport, control_files):
1410
 
        """Return the control store for this repository."""
1411
 
        return self._get_versioned_file_store('',
1412
 
                                              repo_transport,
1413
 
                                              control_files,
1414
 
                                              prefixed=False)
1415
 
 
1416
 
    def _get_text_store(self, transport, control_files):
1417
 
        """Get a store for file texts for this format."""
1418
 
        raise NotImplementedError(self._get_text_store)
1419
 
 
1420
 
    def open(self, a_bzrdir, _found=False):
1421
 
        """See RepositoryFormat.open()."""
1422
 
        if not _found:
1423
 
            # we are being called directly and must probe.
1424
 
            raise NotImplementedError
1425
 
 
1426
 
        repo_transport = a_bzrdir.get_repository_transport(None)
1427
 
        control_files = a_bzrdir._control_files
1428
 
        text_store = self._get_text_store(repo_transport, control_files)
1429
 
        control_store = self._get_control_store(repo_transport, control_files)
1430
 
        _revision_store = self._get_revision_store(repo_transport, control_files)
1431
 
        return AllInOneRepository(_format=self,
1432
 
                                  a_bzrdir=a_bzrdir,
1433
 
                                  _revision_store=_revision_store,
1434
 
                                  control_store=control_store,
1435
 
                                  text_store=text_store)
1436
 
 
1437
 
    def check_conversion_target(self, target_format):
1438
 
        pass
1439
 
 
1440
 
 
1441
 
class RepositoryFormat4(PreSplitOutRepositoryFormat):
1442
 
    """Bzr repository format 4.
1443
 
 
1444
 
    This repository format has:
1445
 
     - flat stores
1446
 
     - TextStores for texts, inventories,revisions.
1447
 
 
1448
 
    This format is deprecated: it indexes texts using a text id which is
1449
 
    removed in format 5; initialization and write support for this format
1450
 
    has been removed.
1451
 
    """
1452
 
 
1453
 
    def __init__(self):
1454
 
        super(RepositoryFormat4, self).__init__()
1455
 
        self._matchingbzrdir = bzrdir.BzrDirFormat4()
1456
 
 
1457
 
    def get_format_description(self):
1458
 
        """See RepositoryFormat.get_format_description()."""
1459
 
        return "Repository format 4"
1460
 
 
1461
 
    def initialize(self, url, shared=False, _internal=False):
1462
 
        """Format 4 branches cannot be created."""
1463
 
        raise errors.UninitializableFormat(self)
1464
 
 
1465
 
    def is_supported(self):
1466
 
        """Format 4 is not supported.
1467
 
 
1468
 
        It is not supported because the model changed from 4 to 5 and the
1469
 
        conversion logic is expensive - so doing it on the fly was not 
1470
 
        feasible.
1471
 
        """
1472
 
        return False
1473
 
 
1474
 
    def _get_control_store(self, repo_transport, control_files):
1475
 
        """Format 4 repositories have no formal control store at this point.
1476
 
        
1477
 
        This will cause any control-file-needing apis to fail - this is desired.
1478
 
        """
1479
 
        return None
1480
 
    
1481
 
    def _get_revision_store(self, repo_transport, control_files):
1482
 
        """See RepositoryFormat._get_revision_store()."""
1483
 
        from bzrlib.xml4 import serializer_v4
1484
 
        return self._get_text_rev_store(repo_transport,
1485
 
                                        control_files,
1486
 
                                        'revision-store',
1487
 
                                        serializer=serializer_v4)
1488
 
 
1489
 
    def _get_text_store(self, transport, control_files):
1490
 
        """See RepositoryFormat._get_text_store()."""
1491
 
 
1492
 
 
1493
 
class RepositoryFormat5(PreSplitOutRepositoryFormat):
1494
 
    """Bzr control format 5.
1495
 
 
1496
 
    This repository format has:
1497
 
     - weaves for file texts and inventory
1498
 
     - flat stores
1499
 
     - TextStores for revisions and signatures.
1500
 
    """
1501
 
 
1502
 
    def __init__(self):
1503
 
        super(RepositoryFormat5, self).__init__()
1504
 
        self._matchingbzrdir = bzrdir.BzrDirFormat5()
1505
 
 
1506
 
    def get_format_description(self):
1507
 
        """See RepositoryFormat.get_format_description()."""
1508
 
        return "Weave repository format 5"
1509
 
 
1510
 
    def _get_revision_store(self, repo_transport, control_files):
1511
 
        """See RepositoryFormat._get_revision_store()."""
1512
 
        """Return the revision store object for this a_bzrdir."""
1513
 
        return self._get_text_rev_store(repo_transport,
1514
 
                                        control_files,
1515
 
                                        'revision-store',
1516
 
                                        compressed=False)
1517
 
 
1518
 
    def _get_text_store(self, transport, control_files):
1519
 
        """See RepositoryFormat._get_text_store()."""
1520
 
        return self._get_versioned_file_store('weaves', transport, control_files, prefixed=False)
1521
 
 
1522
 
 
1523
 
class RepositoryFormat6(PreSplitOutRepositoryFormat):
1524
 
    """Bzr control format 6.
1525
 
 
1526
 
    This repository format has:
1527
 
     - weaves for file texts and inventory
1528
 
     - hash subdirectory based stores.
1529
 
     - TextStores for revisions and signatures.
1530
 
    """
1531
 
 
1532
 
    def __init__(self):
1533
 
        super(RepositoryFormat6, self).__init__()
1534
 
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
1535
 
 
1536
 
    def get_format_description(self):
1537
 
        """See RepositoryFormat.get_format_description()."""
1538
 
        return "Weave repository format 6"
1539
 
 
1540
 
    def _get_revision_store(self, repo_transport, control_files):
1541
 
        """See RepositoryFormat._get_revision_store()."""
1542
 
        return self._get_text_rev_store(repo_transport,
1543
 
                                        control_files,
1544
 
                                        'revision-store',
1545
 
                                        compressed=False,
1546
 
                                        prefixed=True)
1547
 
 
1548
 
    def _get_text_store(self, transport, control_files):
1549
 
        """See RepositoryFormat._get_text_store()."""
1550
 
        return self._get_versioned_file_store('weaves', transport, control_files)
1551
 
 
1552
 
 
1553
1170
class MetaDirRepositoryFormat(RepositoryFormat):
1554
1171
    """Common base class for the new repositories using the metadir layout."""
1555
1172
 
1556
1173
    rich_root_data = False
 
1174
    _matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1557
1175
 
1558
1176
    def __init__(self):
1559
1177
        super(MetaDirRepositoryFormat, self).__init__()
1560
 
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1561
1178
 
1562
1179
    def _create_control_files(self, a_bzrdir):
1563
1180
        """Create the required files and the initial control_files object."""
1586
1203
            control_files.unlock()
1587
1204
 
1588
1205
 
1589
 
class RepositoryFormat7(MetaDirRepositoryFormat):
1590
 
    """Bzr repository 7.
1591
 
 
1592
 
    This repository format has:
1593
 
     - weaves for file texts and inventory
1594
 
     - hash subdirectory based stores.
1595
 
     - TextStores for revisions and signatures.
1596
 
     - a format marker of its own
1597
 
     - an optional 'shared-storage' flag
1598
 
     - an optional 'no-working-trees' flag
1599
 
    """
1600
 
 
1601
 
    def _get_control_store(self, repo_transport, control_files):
1602
 
        """Return the control store for this repository."""
1603
 
        return self._get_versioned_file_store('',
1604
 
                                              repo_transport,
1605
 
                                              control_files,
1606
 
                                              prefixed=False)
1607
 
 
1608
 
    def get_format_string(self):
1609
 
        """See RepositoryFormat.get_format_string()."""
1610
 
        return "Bazaar-NG Repository format 7"
1611
 
 
1612
 
    def get_format_description(self):
1613
 
        """See RepositoryFormat.get_format_description()."""
1614
 
        return "Weave repository format 7"
1615
 
 
1616
 
    def check_conversion_target(self, target_format):
1617
 
        pass
1618
 
 
1619
 
    def _get_revision_store(self, repo_transport, control_files):
1620
 
        """See RepositoryFormat._get_revision_store()."""
1621
 
        return self._get_text_rev_store(repo_transport,
1622
 
                                        control_files,
1623
 
                                        'revision-store',
1624
 
                                        compressed=False,
1625
 
                                        prefixed=True,
1626
 
                                        )
1627
 
 
1628
 
    def _get_text_store(self, transport, control_files):
1629
 
        """See RepositoryFormat._get_text_store()."""
1630
 
        return self._get_versioned_file_store('weaves',
1631
 
                                              transport,
1632
 
                                              control_files)
1633
 
 
1634
 
    def initialize(self, a_bzrdir, shared=False):
1635
 
        """Create a weave repository.
1636
 
 
1637
 
        :param shared: If true the repository will be initialized as a shared
1638
 
                       repository.
1639
 
        """
1640
 
        # Create an empty weave
1641
 
        sio = StringIO()
1642
 
        weavefile.write_weave_v5(weave.Weave(), sio)
1643
 
        empty_weave = sio.getvalue()
1644
 
 
1645
 
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1646
 
        dirs = ['revision-store', 'weaves']
1647
 
        files = [('inventory.weave', StringIO(empty_weave)), 
1648
 
                 ]
1649
 
        utf8_files = [('format', self.get_format_string())]
1650
 
 
1651
 
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1652
 
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1653
 
 
1654
 
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1655
 
        """See RepositoryFormat.open().
1656
 
        
1657
 
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1658
 
                                    repository at a slightly different url
1659
 
                                    than normal. I.e. during 'upgrade'.
1660
 
        """
1661
 
        if not _found:
1662
 
            format = RepositoryFormat.find_format(a_bzrdir)
1663
 
            assert format.__class__ ==  self.__class__
1664
 
        if _override_transport is not None:
1665
 
            repo_transport = _override_transport
1666
 
        else:
1667
 
            repo_transport = a_bzrdir.get_repository_transport(None)
1668
 
        control_files = lockable_files.LockableFiles(repo_transport,
1669
 
                                'lock', lockdir.LockDir)
1670
 
        text_store = self._get_text_store(repo_transport, control_files)
1671
 
        control_store = self._get_control_store(repo_transport, control_files)
1672
 
        _revision_store = self._get_revision_store(repo_transport, control_files)
1673
 
        return WeaveMetaDirRepository(_format=self,
1674
 
            a_bzrdir=a_bzrdir,
1675
 
            control_files=control_files,
1676
 
            _revision_store=_revision_store,
1677
 
            control_store=control_store,
1678
 
            text_store=text_store)
1679
 
 
1680
 
 
1681
 
class RepositoryFormatKnit(MetaDirRepositoryFormat):
1682
 
    """Bzr repository knit format (generalized). 
1683
 
 
1684
 
    This repository format has:
1685
 
     - knits for file texts and inventory
1686
 
     - hash subdirectory based stores.
1687
 
     - knits for revisions and signatures
1688
 
     - TextStores for revisions and signatures.
1689
 
     - a format marker of its own
1690
 
     - an optional 'shared-storage' flag
1691
 
     - an optional 'no-working-trees' flag
1692
 
     - a LockDir lock
1693
 
    """
1694
 
 
1695
 
    def _get_control_store(self, repo_transport, control_files):
1696
 
        """Return the control store for this repository."""
1697
 
        return VersionedFileStore(
1698
 
            repo_transport,
1699
 
            prefixed=False,
1700
 
            file_mode=control_files._file_mode,
1701
 
            versionedfile_class=knit.KnitVersionedFile,
1702
 
            versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1703
 
            )
1704
 
 
1705
 
    def _get_revision_store(self, repo_transport, control_files):
1706
 
        """See RepositoryFormat._get_revision_store()."""
1707
 
        from bzrlib.store.revision.knit import KnitRevisionStore
1708
 
        versioned_file_store = VersionedFileStore(
1709
 
            repo_transport,
1710
 
            file_mode=control_files._file_mode,
1711
 
            prefixed=False,
1712
 
            precious=True,
1713
 
            versionedfile_class=knit.KnitVersionedFile,
1714
 
            versionedfile_kwargs={'delta':False,
1715
 
                                  'factory':knit.KnitPlainFactory(),
1716
 
                                 },
1717
 
            escaped=True,
1718
 
            )
1719
 
        return KnitRevisionStore(versioned_file_store)
1720
 
 
1721
 
    def _get_text_store(self, transport, control_files):
1722
 
        """See RepositoryFormat._get_text_store()."""
1723
 
        return self._get_versioned_file_store('knits',
1724
 
                                  transport,
1725
 
                                  control_files,
1726
 
                                  versionedfile_class=knit.KnitVersionedFile,
1727
 
                                  versionedfile_kwargs={
1728
 
                                      'create_parent_dir':True,
1729
 
                                      'delay_create':True,
1730
 
                                      'dir_mode':control_files._dir_mode,
1731
 
                                  },
1732
 
                                  escaped=True)
1733
 
 
1734
 
    def initialize(self, a_bzrdir, shared=False):
1735
 
        """Create a knit format 1 repository.
1736
 
 
1737
 
        :param a_bzrdir: bzrdir to contain the new repository; must already
1738
 
            be initialized.
1739
 
        :param shared: If true the repository will be initialized as a shared
1740
 
                       repository.
1741
 
        """
1742
 
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1743
 
        dirs = ['revision-store', 'knits']
1744
 
        files = []
1745
 
        utf8_files = [('format', self.get_format_string())]
1746
 
        
1747
 
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1748
 
        repo_transport = a_bzrdir.get_repository_transport(None)
1749
 
        control_files = lockable_files.LockableFiles(repo_transport,
1750
 
                                'lock', lockdir.LockDir)
1751
 
        control_store = self._get_control_store(repo_transport, control_files)
1752
 
        transaction = transactions.WriteTransaction()
1753
 
        # trigger a write of the inventory store.
1754
 
        control_store.get_weave_or_empty('inventory', transaction)
1755
 
        _revision_store = self._get_revision_store(repo_transport, control_files)
1756
 
        # the revision id here is irrelevant: it will not be stored, and cannot
1757
 
        # already exist.
1758
 
        _revision_store.has_revision_id('A', transaction)
1759
 
        _revision_store.get_signature_file(transaction)
1760
 
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1761
 
 
1762
 
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1763
 
        """See RepositoryFormat.open().
1764
 
        
1765
 
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1766
 
                                    repository at a slightly different url
1767
 
                                    than normal. I.e. during 'upgrade'.
1768
 
        """
1769
 
        if not _found:
1770
 
            format = RepositoryFormat.find_format(a_bzrdir)
1771
 
            assert format.__class__ ==  self.__class__
1772
 
        if _override_transport is not None:
1773
 
            repo_transport = _override_transport
1774
 
        else:
1775
 
            repo_transport = a_bzrdir.get_repository_transport(None)
1776
 
        control_files = lockable_files.LockableFiles(repo_transport,
1777
 
                                'lock', lockdir.LockDir)
1778
 
        text_store = self._get_text_store(repo_transport, control_files)
1779
 
        control_store = self._get_control_store(repo_transport, control_files)
1780
 
        _revision_store = self._get_revision_store(repo_transport, control_files)
1781
 
        return KnitRepository(_format=self,
1782
 
                              a_bzrdir=a_bzrdir,
1783
 
                              control_files=control_files,
1784
 
                              _revision_store=_revision_store,
1785
 
                              control_store=control_store,
1786
 
                              text_store=text_store)
1787
 
 
1788
 
 
1789
 
class RepositoryFormatKnit1(RepositoryFormatKnit):
1790
 
    """Bzr repository knit format 1.
1791
 
 
1792
 
    This repository format has:
1793
 
     - knits for file texts and inventory
1794
 
     - hash subdirectory based stores.
1795
 
     - knits for revisions and signatures
1796
 
     - TextStores for revisions and signatures.
1797
 
     - a format marker of its own
1798
 
     - an optional 'shared-storage' flag
1799
 
     - an optional 'no-working-trees' flag
1800
 
     - a LockDir lock
1801
 
 
1802
 
    This format was introduced in bzr 0.8.
1803
 
    """
1804
 
    def get_format_string(self):
1805
 
        """See RepositoryFormat.get_format_string()."""
1806
 
        return "Bazaar-NG Knit Repository Format 1"
1807
 
 
1808
 
    def get_format_description(self):
1809
 
        """See RepositoryFormat.get_format_description()."""
1810
 
        return "Knit repository format 1"
1811
 
 
1812
 
    def check_conversion_target(self, target_format):
1813
 
        pass
1814
 
 
1815
 
 
1816
 
class RepositoryFormatKnit2(RepositoryFormatKnit):
1817
 
    """Bzr repository knit format 2.
1818
 
 
1819
 
    THIS FORMAT IS EXPERIMENTAL
1820
 
    This repository format has:
1821
 
     - knits for file texts and inventory
1822
 
     - hash subdirectory based stores.
1823
 
     - knits for revisions and signatures
1824
 
     - TextStores for revisions and signatures.
1825
 
     - a format marker of its own
1826
 
     - an optional 'shared-storage' flag
1827
 
     - an optional 'no-working-trees' flag
1828
 
     - a LockDir lock
1829
 
     - Support for recording full info about the tree root
1830
 
 
1831
 
    """
1832
 
    
1833
 
    rich_root_data = True
1834
 
 
1835
 
    def get_format_string(self):
1836
 
        """See RepositoryFormat.get_format_string()."""
1837
 
        return "Bazaar Knit Repository Format 2\n"
1838
 
 
1839
 
    def get_format_description(self):
1840
 
        """See RepositoryFormat.get_format_description()."""
1841
 
        return "Knit repository format 2"
1842
 
 
1843
 
    def check_conversion_target(self, target_format):
1844
 
        if not target_format.rich_root_data:
1845
 
            raise errors.BadConversionTarget(
1846
 
                'Does not support rich root data.', target_format)
1847
 
 
1848
 
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1849
 
        """See RepositoryFormat.open().
1850
 
        
1851
 
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1852
 
                                    repository at a slightly different url
1853
 
                                    than normal. I.e. during 'upgrade'.
1854
 
        """
1855
 
        if not _found:
1856
 
            format = RepositoryFormat.find_format(a_bzrdir)
1857
 
            assert format.__class__ ==  self.__class__
1858
 
        if _override_transport is not None:
1859
 
            repo_transport = _override_transport
1860
 
        else:
1861
 
            repo_transport = a_bzrdir.get_repository_transport(None)
1862
 
        control_files = lockable_files.LockableFiles(repo_transport, 'lock',
1863
 
                                                     lockdir.LockDir)
1864
 
        text_store = self._get_text_store(repo_transport, control_files)
1865
 
        control_store = self._get_control_store(repo_transport, control_files)
1866
 
        _revision_store = self._get_revision_store(repo_transport, control_files)
1867
 
        return KnitRepository2(_format=self,
1868
 
                               a_bzrdir=a_bzrdir,
1869
 
                               control_files=control_files,
1870
 
                               _revision_store=_revision_store,
1871
 
                               control_store=control_store,
1872
 
                               text_store=text_store)
1873
 
 
1874
 
 
1875
 
 
1876
1206
# formats which have no format string are not discoverable
1877
 
# and not independently creatable, so are not registered.
1878
 
RepositoryFormat.register_format(RepositoryFormat7())
 
1207
# and not independently creatable, so are not registered.  They're 
 
1208
# all in bzrlib.repofmt.weaverepo now.  When an instance of one of these is
 
1209
# needed, it's constructed directly by the BzrDir.  Non-native formats where
 
1210
# the repository is not separately opened are similar.
 
1211
 
 
1212
format_registry.register_lazy(
 
1213
    'Bazaar-NG Repository format 7',
 
1214
    'bzrlib.repofmt.weaverepo',
 
1215
    'RepositoryFormat7'
 
1216
    )
1879
1217
# KEEP in sync with bzrdir.format_registry default, which controls the overall
1880
1218
# default control directory format
1881
 
_default_format = RepositoryFormatKnit1()
1882
 
RepositoryFormat.register_format(_default_format)
1883
 
RepositoryFormat.register_format(RepositoryFormatKnit2())
1884
 
RepositoryFormat._set_default_format(_default_format)
1885
 
_legacy_formats = [RepositoryFormat4(),
1886
 
                   RepositoryFormat5(),
1887
 
                   RepositoryFormat6()]
 
1219
 
 
1220
format_registry.register_lazy(
 
1221
    'Bazaar-NG Knit Repository Format 1',
 
1222
    'bzrlib.repofmt.knitrepo',
 
1223
    'RepositoryFormatKnit1',
 
1224
    )
 
1225
format_registry.default_key = 'Bazaar-NG Knit Repository Format 1'
 
1226
 
 
1227
format_registry.register_lazy(
 
1228
    'Bazaar Knit Repository Format 2\n',
 
1229
    'bzrlib.repofmt.knitrepo',
 
1230
    'RepositoryFormatKnit2',
 
1231
    )
1888
1232
 
1889
1233
 
1890
1234
class InterRepository(InterObject):
1953
1297
    Data format and model must match for this to work.
1954
1298
    """
1955
1299
 
1956
 
    _matching_repo_format = RepositoryFormat4()
1957
 
    """Repository format for testing with."""
 
1300
    @classmethod
 
1301
    def _get_repo_format_to_test(self):
 
1302
        """Repository format for testing with."""
 
1303
        return RepositoryFormat.get_default_format()
1958
1304
 
1959
1305
    @staticmethod
1960
1306
    def is_compatible(source, target):
2013
1359
class InterWeaveRepo(InterSameDataRepository):
2014
1360
    """Optimised code paths between Weave based repositories."""
2015
1361
 
2016
 
    _matching_repo_format = RepositoryFormat7()
2017
 
    """Repository format for testing with."""
 
1362
    @classmethod
 
1363
    def _get_repo_format_to_test(self):
 
1364
        from bzrlib.repofmt import weaverepo
 
1365
        return weaverepo.RepositoryFormat7()
2018
1366
 
2019
1367
    @staticmethod
2020
1368
    def is_compatible(source, target):
2024
1372
        could lead to confusing results, and there is no need to be 
2025
1373
        overly general.
2026
1374
        """
 
1375
        from bzrlib.repofmt.weaverepo import (
 
1376
                RepositoryFormat5,
 
1377
                RepositoryFormat6,
 
1378
                RepositoryFormat7,
 
1379
                )
2027
1380
        try:
2028
1381
            return (isinstance(source._format, (RepositoryFormat5,
2029
1382
                                                RepositoryFormat6,
2135
1488
class InterKnitRepo(InterSameDataRepository):
2136
1489
    """Optimised code paths between Knit based repositories."""
2137
1490
 
2138
 
    _matching_repo_format = RepositoryFormatKnit1()
2139
 
    """Repository format for testing with."""
 
1491
    @classmethod
 
1492
    def _get_repo_format_to_test(self):
 
1493
        from bzrlib.repofmt import knitrepo
 
1494
        return knitrepo.RepositoryFormatKnit1()
2140
1495
 
2141
1496
    @staticmethod
2142
1497
    def is_compatible(source, target):
2146
1501
        could lead to confusing results, and there is no need to be 
2147
1502
        overly general.
2148
1503
        """
 
1504
        from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
2149
1505
        try:
2150
1506
            return (isinstance(source._format, (RepositoryFormatKnit1)) and
2151
1507
                    isinstance(target._format, (RepositoryFormatKnit1)))
2199
1555
 
2200
1556
class InterModel1and2(InterRepository):
2201
1557
 
2202
 
    _matching_repo_format = None
 
1558
    @classmethod
 
1559
    def _get_repo_format_to_test(self):
 
1560
        return None
2203
1561
 
2204
1562
    @staticmethod
2205
1563
    def is_compatible(source, target):
2253
1611
 
2254
1612
class InterKnit1and2(InterKnitRepo):
2255
1613
 
2256
 
    _matching_repo_format = None
 
1614
    @classmethod
 
1615
    def _get_repo_format_to_test(self):
 
1616
        return None
2257
1617
 
2258
1618
    @staticmethod
2259
1619
    def is_compatible(source, target):
2260
1620
        """Be compatible with Knit1 source and Knit2 target"""
 
1621
        from bzrlib.repofmt.knitrepo import RepositoryFormatKnit2
2261
1622
        try:
 
1623
            from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1, \
 
1624
                    RepositoryFormatKnit2
2262
1625
            return (isinstance(source._format, (RepositoryFormatKnit1)) and
2263
1626
                    isinstance(target._format, (RepositoryFormatKnit2)))
2264
1627
        except AttributeError:
2304
1667
    def adapt(self, test):
2305
1668
        result = unittest.TestSuite()
2306
1669
        for repository_format, bzrdir_format in self._formats:
 
1670
            from copy import deepcopy
2307
1671
            new_test = deepcopy(test)
2308
1672
            new_test.transport_server = self._transport_server
2309
1673
            new_test.transport_readonly_server = self._transport_readonly_server
2334
1698
    def adapt(self, test):
2335
1699
        result = unittest.TestSuite()
2336
1700
        for interrepo_class, repository_format, repository_format_to in self._formats:
 
1701
            from copy import deepcopy
2337
1702
            new_test = deepcopy(test)
2338
1703
            new_test.transport_server = self._transport_server
2339
1704
            new_test.transport_readonly_server = self._transport_readonly_server
2350
1715
    @staticmethod
2351
1716
    def default_test_list():
2352
1717
        """Generate the default list of interrepo permutations to test."""
 
1718
        from bzrlib.repofmt import knitrepo, weaverepo
2353
1719
        result = []
2354
1720
        # test the default InterRepository between format 6 and the current 
2355
1721
        # default format.
2358
1724
        #result.append((InterRepository,
2359
1725
        #               RepositoryFormat6(),
2360
1726
        #               RepositoryFormatKnit1()))
2361
 
        for optimiser in InterRepository._optimisers:
2362
 
            if optimiser._matching_repo_format is not None:
2363
 
                result.append((optimiser,
2364
 
                               optimiser._matching_repo_format,
2365
 
                               optimiser._matching_repo_format
2366
 
                               ))
 
1727
        for optimiser_class in InterRepository._optimisers:
 
1728
            format_to_test = optimiser_class._get_repo_format_to_test()
 
1729
            if format_to_test is not None:
 
1730
                result.append((optimiser_class,
 
1731
                               format_to_test, format_to_test))
2367
1732
        # if there are specific combinations we want to use, we can add them 
2368
1733
        # here.
2369
 
        result.append((InterModel1and2, RepositoryFormat5(),
2370
 
                       RepositoryFormatKnit2()))
2371
 
        result.append((InterKnit1and2, RepositoryFormatKnit1(),
2372
 
                       RepositoryFormatKnit2()))
 
1734
        result.append((InterModel1and2,
 
1735
                       weaverepo.RepositoryFormat5(),
 
1736
                       knitrepo.RepositoryFormatKnit2()))
 
1737
        result.append((InterKnit1and2,
 
1738
                       knitrepo.RepositoryFormatKnit1(),
 
1739
                       knitrepo.RepositoryFormatKnit2()))
2373
1740
        return result
2374
1741
 
2375
1742
 
2470
1837
        self._timestamp = round(timestamp, 3)
2471
1838
 
2472
1839
        if timezone is None:
2473
 
            self._timezone = local_time_offset()
 
1840
            self._timezone = osutils.local_time_offset()
2474
1841
        else:
2475
1842
            self._timezone = int(timezone)
2476
1843