1
# Copyright (C) 2007-2010 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
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
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Deprecated weave-based repository formats.
56
48
from bzrlib.store.text import TextStore
49
from bzrlib.trace import mutter
57
50
from bzrlib.tuned_gzip import GzipFile, bytes_to_gzip
58
51
from bzrlib.versionedfile import (
59
52
AbsentContentFactory,
65
58
class AllInOneRepository(Repository):
66
59
"""Legacy support - the repository behaviour for all-in-one branches."""
69
def _serializer(self):
70
return xml5.serializer_v5
72
def _escape(self, file_or_path):
73
if not isinstance(file_or_path, basestring):
74
file_or_path = '/'.join(file_or_path)
75
if file_or_path == '':
77
return urlutils.escape(osutils.safe_unicode(file_or_path))
61
_serializer = xml5.serializer_v5
79
63
def __init__(self, _format, a_bzrdir):
80
64
# we reuse one control files instance.
84
68
def get_store(name, compressed=True, prefixed=False):
85
69
# FIXME: This approach of assuming stores are all entirely compressed
86
# or entirely uncompressed is tidy, but breaks upgrade from
87
# some existing branches where there's a mixture; we probably
70
# or entirely uncompressed is tidy, but breaks upgrade from
71
# some existing branches where there's a mixture; we probably
88
72
# still want the option to look for both.
89
relpath = self._escape(name)
73
relpath = a_bzrdir._control_files._escape(name)
90
74
store = TextStore(a_bzrdir.transport.clone(relpath),
91
75
prefixed=prefixed, compressed=compressed,
96
80
# not broken out yet because the controlweaves|inventory_store
97
81
# and texts bits are still different.
98
82
if isinstance(_format, RepositoryFormat4):
99
# cannot remove these - there is still no consistent api
83
# cannot remove these - there is still no consistent api
100
84
# which allows access to this old info.
101
85
self.inventory_store = get_store('inventory-store')
102
86
self._text_store = get_store('text-store')
103
87
super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files)
88
self._fetch_order = 'topological'
89
self._fetch_reconcile = True
106
92
def _all_possible_ids(self):
107
93
"""Return all the possible revisions that we could find."""
108
94
if 'evil' in debug.debug_flags:
109
trace.mutter_callsite(
110
3, "_all_possible_ids scales with size of history.")
95
mutter_callsite(3, "_all_possible_ids scales with size of history.")
111
96
return [key[-1] for key in self.inventories.keys()]
114
99
def _all_revision_ids(self):
115
"""Returns a list of all the revision ids in the repository.
100
"""Returns a list of all the revision ids in the repository.
117
These are in as much topological order as the underlying store can
102
These are in as much topological order as the underlying store can
118
103
present: for weaves ghosts may lead to a lack of correctness until
119
104
the reweave updates the parents list.
177
162
:param new_value: True to restore the default, False to disable making
180
raise errors.RepositoryUpgradeRequired(self.user_url)
165
raise errors.RepositoryUpgradeRequired(self.bzrdir.root_transport.base)
182
167
def make_working_trees(self):
183
168
"""Returns the policy for making working trees on new branches."""
192
177
class WeaveMetaDirRepository(MetaDirVersionedFileRepository):
193
178
"""A subclass of MetaDirRepository to set weave specific policy."""
180
_serializer = xml5.serializer_v5
195
182
def __init__(self, _format, a_bzrdir, control_files):
196
183
super(WeaveMetaDirRepository, self).__init__(_format, a_bzrdir, control_files)
197
self._serializer = _format._serializer
184
self._fetch_order = 'topological'
185
self._fetch_reconcile = True
200
188
def _all_possible_ids(self):
201
189
"""Return all the possible revisions that we could find."""
202
190
if 'evil' in debug.debug_flags:
203
trace.mutter_callsite(
204
3, "_all_possible_ids scales with size of history.")
191
mutter_callsite(3, "_all_possible_ids scales with size of history.")
205
192
return [key[-1] for key in self.inventories.keys()]
208
195
def _all_revision_ids(self):
209
"""Returns a list of all the revision ids in the repository.
196
"""Returns a list of all the revision ids in the repository.
211
These are in as much topological order as the underlying store can
198
These are in as much topological order as the underlying store can
212
199
present: for weaves ghosts may lead to a lack of correctness until
213
200
the reweave updates the parents list.
269
256
supports_tree_reference = False
270
257
supports_ghosts = False
271
258
supports_external_lookups = False
272
supports_chks = False
273
_fetch_order = 'topological'
274
_fetch_reconcile = True
277
260
def initialize(self, a_bzrdir, shared=False, _internal=False):
278
261
"""Create a weave repository."""
282
265
if not _internal:
283
266
# always initialized when the bzrdir is.
284
267
return self.open(a_bzrdir, _found=True)
286
269
# Create an empty weave
288
271
weavefile.write_weave_v5(weave.Weave(), sio)
289
272
empty_weave = sio.getvalue()
291
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
274
mutter('creating repository in %s.', a_bzrdir.transport.base)
293
276
# FIXME: RBC 20060125 don't peek under the covers
294
277
# NB: no need to escape relative paths that are url safe.
295
278
control_files = lockable_files.LockableFiles(a_bzrdir.transport,
301
284
transport.mkdir_multi(['revision-store', 'weaves'],
302
285
mode=a_bzrdir._get_dir_mode())
303
transport.put_bytes_non_atomic('inventory.weave', empty_weave,
304
mode=a_bzrdir._get_file_mode())
286
transport.put_bytes_non_atomic('inventory.weave', empty_weave)
306
288
control_files.unlock()
307
repository = self.open(a_bzrdir, _found=True)
308
self._run_post_repo_init_hooks(repository, a_bzrdir, shared)
289
return self.open(a_bzrdir, _found=True)
311
291
def open(self, a_bzrdir, _found=False):
312
292
"""See RepositoryFormat.open()."""
321
301
result.signatures = self._get_signatures(repo_transport, result)
322
302
result.inventories = self._get_inventories(repo_transport, result)
323
303
result.texts = self._get_texts(repo_transport, result)
324
result.chk_bytes = None
306
def check_conversion_target(self, target_format):
328
310
class RepositoryFormat4(PreSplitOutRepositoryFormat):
329
311
"""Bzr repository format 4.
340
322
_matchingbzrdir = bzrdir.BzrDirFormat4()
325
super(RepositoryFormat4, self).__init__()
326
self._fetch_order = 'topological'
327
self._fetch_reconcile = True
342
329
def get_format_description(self):
343
330
"""See RepositoryFormat.get_format_description()."""
344
331
return "Repository format 4"
351
338
"""Format 4 is not supported.
353
340
It is not supported because the model changed from 4 to 5 and the
354
conversion logic is expensive - so doing it on the fly was not
341
conversion logic is expensive - so doing it on the fly was not
387
374
_versionedfile_class = weave.WeaveFile
388
375
_matchingbzrdir = bzrdir.BzrDirFormat5()
390
def _serializer(self):
391
return xml5.serializer_v5
378
super(RepositoryFormat5, self).__init__()
379
self._fetch_order = 'topological'
380
self._fetch_reconcile = True
393
382
def get_format_description(self):
394
383
"""See RepositoryFormat.get_format_description()."""
395
384
return "Weave repository format 5"
397
def network_name(self):
398
"""The network name for this format is the control dirs disk label."""
399
return self._matchingbzrdir.get_format_string()
401
386
def _get_inventories(self, repo_transport, repo, name='inventory'):
402
387
mapper = versionedfile.ConstantMapper(name)
403
388
return versionedfile.ThunkedVersionedFiles(repo_transport,
404
389
weave.WeaveFile, mapper, repo.is_locked)
406
391
def _get_revisions(self, repo_transport, repo):
392
from bzrlib.xml5 import serializer_v5
407
393
return RevisionTextStore(repo_transport.clone('revision-store'),
408
xml5.serializer_v5, False, versionedfile.PrefixMapper(),
394
serializer_v5, False, versionedfile.PrefixMapper(),
409
395
repo.is_locked, repo.is_write_locked)
411
397
def _get_signatures(self, repo_transport, repo):
432
418
_versionedfile_class = weave.WeaveFile
433
419
_matchingbzrdir = bzrdir.BzrDirFormat6()
435
def _serializer(self):
436
return xml5.serializer_v5
422
super(RepositoryFormat6, self).__init__()
423
self._fetch_order = 'topological'
424
self._fetch_reconcile = True
438
426
def get_format_description(self):
439
427
"""See RepositoryFormat.get_format_description()."""
440
428
return "Weave repository format 6"
442
def network_name(self):
443
"""The network name for this format is the control dirs disk label."""
444
return self._matchingbzrdir.get_format_string()
446
430
def _get_inventories(self, repo_transport, repo, name='inventory'):
447
431
mapper = versionedfile.ConstantMapper(name)
448
432
return versionedfile.ThunkedVersionedFiles(repo_transport,
449
433
weave.WeaveFile, mapper, repo.is_locked)
451
435
def _get_revisions(self, repo_transport, repo):
436
from bzrlib.xml5 import serializer_v5
452
437
return RevisionTextStore(repo_transport.clone('revision-store'),
453
xml5.serializer_v5, False, versionedfile.HashPrefixMapper(),
438
serializer_v5, False, versionedfile.HashPrefixMapper(),
454
439
repo.is_locked, repo.is_write_locked)
456
441
def _get_signatures(self, repo_transport, repo):
480
465
_versionedfile_class = weave.WeaveFile
481
466
supports_ghosts = False
482
supports_chks = False
484
_fetch_order = 'topological'
485
_fetch_reconcile = True
488
def _serializer(self):
489
return xml5.serializer_v5
491
468
def get_format_string(self):
492
469
"""See RepositoryFormat.get_format_string()."""
496
473
"""See RepositoryFormat.get_format_description()."""
497
474
return "Weave repository format 7"
476
def check_conversion_target(self, target_format):
499
479
def _get_inventories(self, repo_transport, repo, name='inventory'):
500
480
mapper = versionedfile.ConstantMapper(name)
501
481
return versionedfile.ThunkedVersionedFiles(repo_transport,
502
482
weave.WeaveFile, mapper, repo.is_locked)
504
484
def _get_revisions(self, repo_transport, repo):
485
from bzrlib.xml5 import serializer_v5
505
486
return RevisionTextStore(repo_transport.clone('revision-store'),
506
xml5.serializer_v5, True, versionedfile.HashPrefixMapper(),
487
serializer_v5, True, versionedfile.HashPrefixMapper(),
507
488
repo.is_locked, repo.is_write_locked)
509
490
def _get_signatures(self, repo_transport, repo):
528
509
weavefile.write_weave_v5(weave.Weave(), sio)
529
510
empty_weave = sio.getvalue()
531
trace.mutter('creating repository in %s.', a_bzrdir.transport.base)
512
mutter('creating repository in %s.', a_bzrdir.transport.base)
532
513
dirs = ['revision-store', 'weaves']
533
files = [('inventory.weave', StringIO(empty_weave)),
514
files = [('inventory.weave', StringIO(empty_weave)),
535
516
utf8_files = [('format', self.get_format_string())]
537
518
self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
538
519
return self.open(a_bzrdir=a_bzrdir, _found=True)
540
521
def open(self, a_bzrdir, _found=False, _override_transport=None):
541
522
"""See RepositoryFormat.open().
543
524
:param _override_transport: INTERNAL USE ONLY. Allows opening the
544
525
repository at a slightly different url
545
526
than normal. I.e. during 'upgrade'.
558
539
result.signatures = self._get_signatures(repo_transport, result)
559
540
result.inventories = self._get_inventories(repo_transport, result)
560
541
result.texts = self._get_texts(repo_transport, result)
561
result.chk_bytes = None
562
542
result._transport = repo_transport
668
648
result[key] = parents
671
def get_known_graph_ancestry(self, keys):
672
"""Get a KnownGraph instance with the ancestry of keys."""
674
parent_map = self.get_parent_map(keys)
675
kg = _mod_graph.KnownGraph(parent_map)
678
651
def get_record_stream(self, keys, sort_order, include_delta_closure):
680
653
text, parents = self._load_text_parents(key)
692
665
path, ext = os.path.splitext(relpath)
695
if not relpath.endswith('.sig'):
668
if '.sig' not in relpath:
696
669
relpaths.add(relpath)
697
670
paths = list(relpaths)
698
671
return set([self._mapper.unmap(path) for path in paths])