1
# Copyright (C) 2006-2010 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
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
17
"""Weave-era BzrDir formats."""
19
from bzrlib.bzrdir import (
25
from bzrlib.transport import get_transport
26
from bzrlib.lazy_import import lazy_import
27
lazy_import(globals(), """
37
class BzrDirFormatAllInOne(BzrDirFormat):
38
"""Common class for formats before meta-dirs."""
40
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
41
create_prefix=False, force_new_repo=False, stacked_on=None,
42
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
44
"""See BzrDirFormat.initialize_on_transport_ex."""
45
require_stacking = (stacked_on is not None)
46
# Format 5 cannot stack, but we've been asked to - actually init
49
format = BzrDirMetaFormat1()
50
return format.initialize_on_transport_ex(transport,
51
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
52
force_new_repo=force_new_repo, stacked_on=stacked_on,
53
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
54
make_working_trees=make_working_trees, shared_repo=shared_repo)
55
return BzrDirFormat.initialize_on_transport_ex(self, transport,
56
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
57
force_new_repo=force_new_repo, stacked_on=stacked_on,
58
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
59
make_working_trees=make_working_trees, shared_repo=shared_repo)
62
class BzrDirFormat5(BzrDirFormatAllInOne):
63
"""Bzr control format 5.
65
This format is a combined format for working tree, branch and repository.
67
- Format 2 working trees [always]
68
- Format 4 branches [always]
69
- Format 5 repositories [always]
70
Unhashed stores in the repository.
73
_lock_class = lockable_files.TransportLock
75
def get_format_string(self):
76
"""See BzrDirFormat.get_format_string()."""
77
return "Bazaar-NG branch, format 5\n"
79
def get_branch_format(self):
80
from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
81
return BzrBranchFormat4()
83
def get_format_description(self):
84
"""See BzrDirFormat.get_format_description()."""
85
return "All-in-one format 5"
87
def get_converter(self, format=None):
88
"""See BzrDirFormat.get_converter()."""
89
# there is one and only one upgrade path here.
90
return ConvertBzrDir5To6()
92
def _initialize_for_clone(self, url):
93
return self.initialize_on_transport(get_transport(url), _cloning=True)
95
def initialize_on_transport(self, transport, _cloning=False):
96
"""Format 5 dirs always have working tree, branch and repository.
98
Except when they are being cloned.
100
from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
101
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
102
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
103
RepositoryFormat5().initialize(result, _internal=True)
105
branch = BzrBranchFormat4().initialize(result)
106
result._init_workingtree()
109
def network_name(self):
110
return self.get_format_string()
112
def _open(self, transport):
113
"""See BzrDirFormat._open."""
114
return BzrDir5(transport, self)
116
def __return_repository_format(self):
117
"""Circular import protection."""
118
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
119
return RepositoryFormat5()
120
repository_format = property(__return_repository_format)
123
class BzrDirFormat6(BzrDirFormatAllInOne):
124
"""Bzr control format 6.
126
This format is a combined format for working tree, branch and repository.
128
- Format 2 working trees [always]
129
- Format 4 branches [always]
130
- Format 6 repositories [always]
133
_lock_class = lockable_files.TransportLock
135
def get_format_string(self):
136
"""See BzrDirFormat.get_format_string()."""
137
return "Bazaar-NG branch, format 6\n"
139
def get_format_description(self):
140
"""See BzrDirFormat.get_format_description()."""
141
return "All-in-one format 6"
143
def get_branch_format(self):
144
from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
145
return BzrBranchFormat4()
147
def get_converter(self, format=None):
148
"""See BzrDirFormat.get_converter()."""
149
# there is one and only one upgrade path here.
150
return ConvertBzrDir6ToMeta()
152
def _initialize_for_clone(self, url):
153
return self.initialize_on_transport(get_transport(url), _cloning=True)
155
def initialize_on_transport(self, transport, _cloning=False):
156
"""Format 6 dirs always have working tree, branch and repository.
158
Except when they are being cloned.
160
from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
161
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
162
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
163
RepositoryFormat6().initialize(result, _internal=True)
165
branch = BzrBranchFormat4().initialize(result)
166
result._init_workingtree()
169
def network_name(self):
170
return self.get_format_string()
172
def _open(self, transport):
173
"""See BzrDirFormat._open."""
174
return BzrDir6(transport, self)
176
def __return_repository_format(self):
177
"""Circular import protection."""
178
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
179
return RepositoryFormat6()
180
repository_format = property(__return_repository_format)
183
class ConvertBzrDir4To5(Converter):
184
"""Converts format 4 bzr dirs to format 5."""
187
super(ConvertBzrDir4To5, self).__init__()
188
self.converted_revs = set()
189
self.absent_revisions = set()
193
def convert(self, to_convert, pb):
194
"""See Converter.convert()."""
195
self.bzrdir = to_convert
197
warnings.warn("pb parameter to convert() is deprecated")
198
self.pb = ui.ui_factory.nested_progress_bar()
200
ui.ui_factory.note('starting upgrade from format 4 to 5')
201
if isinstance(self.bzrdir.transport, local.LocalTransport):
202
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
203
self._convert_to_weaves()
204
return BzrDir.open(self.bzrdir.user_url)
208
def _convert_to_weaves(self):
209
ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
212
stat = self.bzrdir.transport.stat('weaves')
213
if not S_ISDIR(stat.st_mode):
214
self.bzrdir.transport.delete('weaves')
215
self.bzrdir.transport.mkdir('weaves')
216
except errors.NoSuchFile:
217
self.bzrdir.transport.mkdir('weaves')
218
# deliberately not a WeaveFile as we want to build it up slowly.
219
self.inv_weave = Weave('inventory')
220
# holds in-memory weaves for all files
221
self.text_weaves = {}
222
self.bzrdir.transport.delete('branch-format')
223
self.branch = self.bzrdir.open_branch()
224
self._convert_working_inv()
225
rev_history = self.branch.revision_history()
226
# to_read is a stack holding the revisions we still need to process;
227
# appending to it adds new highest-priority revisions
228
self.known_revisions = set(rev_history)
229
self.to_read = rev_history[-1:]
231
rev_id = self.to_read.pop()
232
if (rev_id not in self.revisions
233
and rev_id not in self.absent_revisions):
234
self._load_one_rev(rev_id)
236
to_import = self._make_order()
237
for i, rev_id in enumerate(to_import):
238
self.pb.update('converting revision', i, len(to_import))
239
self._convert_one_rev(rev_id)
241
self._write_all_weaves()
242
self._write_all_revs()
243
ui.ui_factory.note('upgraded to weaves:')
244
ui.ui_factory.note(' %6d revisions and inventories' % len(self.revisions))
245
ui.ui_factory.note(' %6d revisions not present' % len(self.absent_revisions))
246
ui.ui_factory.note(' %6d texts' % self.text_count)
247
self._cleanup_spare_files_after_format4()
248
self.branch._transport.put_bytes(
250
BzrDirFormat5().get_format_string(),
251
mode=self.bzrdir._get_file_mode())
253
def _cleanup_spare_files_after_format4(self):
254
# FIXME working tree upgrade foo.
255
for n in 'merged-patches', 'pending-merged-patches':
257
## assert os.path.getsize(p) == 0
258
self.bzrdir.transport.delete(n)
259
except errors.NoSuchFile:
261
self.bzrdir.transport.delete_tree('inventory-store')
262
self.bzrdir.transport.delete_tree('text-store')
264
def _convert_working_inv(self):
265
inv = xml4.serializer_v4.read_inventory(
266
self.branch._transport.get('inventory'))
267
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
268
self.branch._transport.put_bytes('inventory', new_inv_xml,
269
mode=self.bzrdir._get_file_mode())
271
def _write_all_weaves(self):
272
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
273
weave_transport = self.bzrdir.transport.clone('weaves')
274
weaves = WeaveStore(weave_transport, prefixed=False)
275
transaction = WriteTransaction()
279
for file_id, file_weave in self.text_weaves.items():
280
self.pb.update('writing weave', i, len(self.text_weaves))
281
weaves._put_weave(file_id, file_weave, transaction)
283
self.pb.update('inventory', 0, 1)
284
controlweaves._put_weave('inventory', self.inv_weave, transaction)
285
self.pb.update('inventory', 1, 1)
289
def _write_all_revs(self):
290
"""Write all revisions out in new form."""
291
self.bzrdir.transport.delete_tree('revision-store')
292
self.bzrdir.transport.mkdir('revision-store')
293
revision_transport = self.bzrdir.transport.clone('revision-store')
295
from bzrlib.xml5 import serializer_v5
296
from bzrlib.plugins.weave_fmt.repository import RevisionTextStore
297
revision_store = RevisionTextStore(revision_transport,
298
serializer_v5, False, versionedfile.PrefixMapper(),
299
lambda:True, lambda:True)
301
for i, rev_id in enumerate(self.converted_revs):
302
self.pb.update('write revision', i, len(self.converted_revs))
303
text = serializer_v5.write_revision_to_string(
304
self.revisions[rev_id])
306
revision_store.add_lines(key, None, osutils.split_lines(text))
310
def _load_one_rev(self, rev_id):
311
"""Load a revision object into memory.
313
Any parents not either loaded or abandoned get queued to be
315
self.pb.update('loading revision',
317
len(self.known_revisions))
318
if not self.branch.repository.has_revision(rev_id):
320
ui.ui_factory.note('revision {%s} not present in branch; '
321
'will be converted as a ghost' %
323
self.absent_revisions.add(rev_id)
325
rev = self.branch.repository.get_revision(rev_id)
326
for parent_id in rev.parent_ids:
327
self.known_revisions.add(parent_id)
328
self.to_read.append(parent_id)
329
self.revisions[rev_id] = rev
331
def _load_old_inventory(self, rev_id):
332
f = self.branch.repository.inventory_store.get(rev_id)
334
old_inv_xml = f.read()
337
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
338
inv.revision_id = rev_id
339
rev = self.revisions[rev_id]
342
def _load_updated_inventory(self, rev_id):
343
inv_xml = self.inv_weave.get_text(rev_id)
344
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
347
def _convert_one_rev(self, rev_id):
348
"""Convert revision and all referenced objects to new format."""
349
rev = self.revisions[rev_id]
350
inv = self._load_old_inventory(rev_id)
351
present_parents = [p for p in rev.parent_ids
352
if p not in self.absent_revisions]
353
self._convert_revision_contents(rev, inv, present_parents)
354
self._store_new_inv(rev, inv, present_parents)
355
self.converted_revs.add(rev_id)
357
def _store_new_inv(self, rev, inv, present_parents):
358
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
359
new_inv_sha1 = sha_string(new_inv_xml)
360
self.inv_weave.add_lines(rev.revision_id,
362
new_inv_xml.splitlines(True))
363
rev.inventory_sha1 = new_inv_sha1
365
def _convert_revision_contents(self, rev, inv, present_parents):
366
"""Convert all the files within a revision.
368
Also upgrade the inventory to refer to the text revision ids."""
369
rev_id = rev.revision_id
370
mutter('converting texts of revision {%s}',
372
parent_invs = map(self._load_updated_inventory, present_parents)
373
entries = inv.iter_entries()
375
for path, ie in entries:
376
self._convert_file_version(rev, ie, parent_invs)
378
def _convert_file_version(self, rev, ie, parent_invs):
379
"""Convert one version of one file.
381
The file needs to be added into the weave if it is a merge
382
of >=2 parents or if it's changed from its parent.
385
rev_id = rev.revision_id
386
w = self.text_weaves.get(file_id)
389
self.text_weaves[file_id] = w
391
parent_candiate_entries = ie.parent_candidates(parent_invs)
392
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
393
# XXX: Note that this is unordered - and this is tolerable because
394
# the previous code was also unordered.
395
previous_entries = dict((head, parent_candiate_entries[head]) for head
397
self.snapshot_ie(previous_entries, ie, w, rev_id)
399
def get_parent_map(self, revision_ids):
400
"""See graph.StackedParentsProvider.get_parent_map"""
401
return dict((revision_id, self.revisions[revision_id])
402
for revision_id in revision_ids
403
if revision_id in self.revisions)
405
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
406
# TODO: convert this logic, which is ~= snapshot to
407
# a call to:. This needs the path figured out. rather than a work_tree
408
# a v4 revision_tree can be given, or something that looks enough like
409
# one to give the file content to the entry if it needs it.
410
# and we need something that looks like a weave store for snapshot to
412
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
413
if len(previous_revisions) == 1:
414
previous_ie = previous_revisions.values()[0]
415
if ie._unchanged(previous_ie):
416
ie.revision = previous_ie.revision
419
f = self.branch.repository._text_store.get(ie.text_id)
421
file_lines = f.readlines()
424
w.add_lines(rev_id, previous_revisions, file_lines)
427
w.add_lines(rev_id, previous_revisions, [])
430
def _make_order(self):
431
"""Return a suitable order for importing revisions.
433
The order must be such that an revision is imported after all
434
its (present) parents.
436
todo = set(self.revisions.keys())
437
done = self.absent_revisions.copy()
440
# scan through looking for a revision whose parents
442
for rev_id in sorted(list(todo)):
443
rev = self.revisions[rev_id]
444
parent_ids = set(rev.parent_ids)
445
if parent_ids.issubset(done):
446
# can take this one now
455
class ConvertBzrDir5To6(Converter):
456
"""Converts format 5 bzr dirs to format 6."""
458
def convert(self, to_convert, pb):
459
"""See Converter.convert()."""
460
self.bzrdir = to_convert
461
pb = ui.ui_factory.nested_progress_bar()
463
ui.ui_factory.note('starting upgrade from format 5 to 6')
464
self._convert_to_prefixed()
465
return BzrDir.open(self.bzrdir.user_url)
469
def _convert_to_prefixed(self):
470
from bzrlib.store import TransportStore
471
self.bzrdir.transport.delete('branch-format')
472
for store_name in ["weaves", "revision-store"]:
473
ui.ui_factory.note("adding prefixes to %s" % store_name)
474
store_transport = self.bzrdir.transport.clone(store_name)
475
store = TransportStore(store_transport, prefixed=True)
476
for urlfilename in store_transport.list_dir('.'):
477
filename = urlutils.unescape(urlfilename)
478
if (filename.endswith(".weave") or
479
filename.endswith(".gz") or
480
filename.endswith(".sig")):
481
file_id, suffix = os.path.splitext(filename)
485
new_name = store._mapper.map((file_id,)) + suffix
486
# FIXME keep track of the dirs made RBC 20060121
488
store_transport.move(filename, new_name)
489
except errors.NoSuchFile: # catches missing dirs strangely enough
490
store_transport.mkdir(osutils.dirname(new_name))
491
store_transport.move(filename, new_name)
492
self.bzrdir.transport.put_bytes(
494
BzrDirFormat6().get_format_string(),
495
mode=self.bzrdir._get_file_mode())
498
class ConvertBzrDir6ToMeta(Converter):
499
"""Converts format 6 bzr dirs to metadirs."""
501
def convert(self, to_convert, pb):
502
"""See Converter.convert()."""
503
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat7
504
from bzrlib.branch import BzrBranchFormat5
505
self.bzrdir = to_convert
506
self.pb = ui.ui_factory.nested_progress_bar()
508
self.total = 20 # the steps we know about
509
self.garbage_inventories = []
510
self.dir_mode = self.bzrdir._get_dir_mode()
511
self.file_mode = self.bzrdir._get_file_mode()
513
ui.ui_factory.note('starting upgrade from format 6 to metadir')
514
self.bzrdir.transport.put_bytes(
516
"Converting to format 6",
518
# its faster to move specific files around than to open and use the apis...
519
# first off, nuke ancestry.weave, it was never used.
521
self.step('Removing ancestry.weave')
522
self.bzrdir.transport.delete('ancestry.weave')
523
except errors.NoSuchFile:
525
# find out whats there
526
self.step('Finding branch files')
527
last_revision = self.bzrdir.open_branch().last_revision()
528
bzrcontents = self.bzrdir.transport.list_dir('.')
529
for name in bzrcontents:
530
if name.startswith('basis-inventory.'):
531
self.garbage_inventories.append(name)
532
# create new directories for repository, working tree and branch
533
repository_names = [('inventory.weave', True),
534
('revision-store', True),
536
self.step('Upgrading repository ')
537
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
538
self.make_lock('repository')
539
# we hard code the formats here because we are converting into
540
# the meta format. The meta format upgrader can take this to a
541
# future format within each component.
542
self.put_format('repository', RepositoryFormat7())
543
for entry in repository_names:
544
self.move_entry('repository', entry)
546
self.step('Upgrading branch ')
547
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
548
self.make_lock('branch')
549
self.put_format('branch', BzrBranchFormat5())
550
branch_files = [('revision-history', True),
551
('branch-name', True),
553
for entry in branch_files:
554
self.move_entry('branch', entry)
556
checkout_files = [('pending-merges', True),
558
('stat-cache', False)]
559
# If a mandatory checkout file is not present, the branch does not have
560
# a functional checkout. Do not create a checkout in the converted
562
for name, mandatory in checkout_files:
563
if mandatory and name not in bzrcontents:
569
ui.ui_factory.note('No working tree.')
570
# If some checkout files are there, we may as well get rid of them.
571
for name, mandatory in checkout_files:
572
if name in bzrcontents:
573
self.bzrdir.transport.delete(name)
575
from bzrlib.workingtree import WorkingTreeFormat3
576
self.step('Upgrading working tree')
577
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
578
self.make_lock('checkout')
580
'checkout', WorkingTreeFormat3())
581
self.bzrdir.transport.delete_multi(
582
self.garbage_inventories, self.pb)
583
for entry in checkout_files:
584
self.move_entry('checkout', entry)
585
if last_revision is not None:
586
self.bzrdir.transport.put_bytes(
587
'checkout/last-revision', last_revision)
588
self.bzrdir.transport.put_bytes(
590
BzrDirMetaFormat1().get_format_string(),
593
return BzrDir.open(self.bzrdir.user_url)
595
def make_lock(self, name):
596
"""Make a lock for the new control dir name."""
597
self.step('Make %s lock' % name)
598
ld = lockdir.LockDir(self.bzrdir.transport,
600
file_modebits=self.file_mode,
601
dir_modebits=self.dir_mode)
604
def move_entry(self, new_dir, entry):
605
"""Move then entry name into new_dir."""
608
self.step('Moving %s' % name)
610
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
611
except errors.NoSuchFile:
615
def put_format(self, dirname, format):
616
self.bzrdir.transport.put_bytes('%s/format' % dirname,
617
format.get_format_string(),
621
class BzrDirFormat4(BzrDirFormat):
624
This format is a combined format for working tree, branch and repository.
626
- Format 1 working trees [always]
627
- Format 4 branches [always]
628
- Format 4 repositories [always]
630
This format is deprecated: it indexes texts using a text it which is
631
removed in format 5; write support for this format has been removed.
634
_lock_class = lockable_files.TransportLock
636
def get_format_string(self):
637
"""See BzrDirFormat.get_format_string()."""
638
return "Bazaar-NG branch, format 0.0.4\n"
640
def get_format_description(self):
641
"""See BzrDirFormat.get_format_description()."""
642
return "All-in-one format 4"
644
def get_converter(self, format=None):
645
"""See BzrDirFormat.get_converter()."""
646
# there is one and only one upgrade path here.
647
return ConvertBzrDir4To5()
649
def initialize_on_transport(self, transport):
650
"""Format 4 branches cannot be created."""
651
raise errors.UninitializableFormat(self)
653
def is_supported(self):
654
"""Format 4 is not supported.
656
It is not supported because the model changed from 4 to 5 and the
657
conversion logic is expensive - so doing it on the fly was not
662
def network_name(self):
663
return self.get_format_string()
665
def _open(self, transport):
666
"""See BzrDirFormat._open."""
667
return BzrDir4(transport, self)
669
def __return_repository_format(self):
670
"""Circular import protection."""
671
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat4
672
return RepositoryFormat4()
673
repository_format = property(__return_repository_format)
676
class BzrDirPreSplitOut(BzrDir):
677
"""A common class for the all-in-one formats."""
679
def __init__(self, _transport, _format):
680
"""See BzrDir.__init__."""
681
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
682
self._control_files = lockable_files.LockableFiles(
683
self.get_branch_transport(None),
684
self._format._lock_file_name,
685
self._format._lock_class)
687
def break_lock(self):
688
"""Pre-splitout bzrdirs do not suffer from stale locks."""
689
raise NotImplementedError(self.break_lock)
691
def cloning_metadir(self, require_stacking=False):
692
"""Produce a metadir suitable for cloning with."""
694
return controldir.format_registry.make_bzrdir('1.6')
695
return self._format.__class__()
697
def clone(self, url, revision_id=None, force_new_repo=False,
698
preserve_stacking=False):
699
"""See BzrDir.clone().
701
force_new_repo has no effect, since this family of formats always
702
require a new repository.
703
preserve_stacking has no effect, since no source branch using this
704
family of formats can be stacked, so there is no stacking to preserve.
707
result = self._format._initialize_for_clone(url)
708
self.open_repository().clone(result, revision_id=revision_id)
709
from_branch = self.open_branch()
710
from_branch.clone(result, revision_id=revision_id)
712
tree = self.open_workingtree()
713
except errors.NotLocalUrl:
714
# make a new one, this format always has to have one.
715
result._init_workingtree()
720
def create_branch(self, name=None, repository=None):
721
"""See BzrDir.create_branch."""
722
if repository is not None:
723
raise NotImplementedError(
724
"create_branch(repository=<not None>) on %r" % (self,))
725
return self._format.get_branch_format().initialize(self, name=name)
727
def destroy_branch(self, name=None):
728
"""See BzrDir.destroy_branch."""
729
raise errors.UnsupportedOperation(self.destroy_branch, self)
731
def create_repository(self, shared=False):
732
"""See BzrDir.create_repository."""
734
raise errors.IncompatibleFormat('shared repository', self._format)
735
return self.open_repository()
737
def destroy_repository(self):
738
"""See BzrDir.destroy_repository."""
739
raise errors.UnsupportedOperation(self.destroy_repository, self)
741
def create_workingtree(self, revision_id=None, from_branch=None,
742
accelerator_tree=None, hardlink=False):
743
"""See BzrDir.create_workingtree."""
744
# The workingtree is sometimes created when the bzrdir is created,
745
# but not when cloning.
747
# this looks buggy but is not -really-
748
# because this format creates the workingtree when the bzrdir is
750
# clone and sprout will have set the revision_id
751
# and that will have set it for us, its only
752
# specific uses of create_workingtree in isolation
753
# that can do wonky stuff here, and that only
754
# happens for creating checkouts, which cannot be
755
# done on this format anyway. So - acceptable wart.
757
warning("can't support hardlinked working trees in %r"
760
result = self.open_workingtree(recommend_upgrade=False)
761
except errors.NoSuchFile:
762
result = self._init_workingtree()
763
if revision_id is not None:
764
if revision_id == _mod_revision.NULL_REVISION:
765
result.set_parent_ids([])
767
result.set_parent_ids([revision_id])
770
def _init_workingtree(self):
771
from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
773
return WorkingTreeFormat2().initialize(self)
774
except errors.NotLocalUrl:
775
# Even though we can't access the working tree, we need to
776
# create its control files.
777
return WorkingTreeFormat2()._stub_initialize_on_transport(
778
self.transport, self._control_files._file_mode)
780
def destroy_workingtree(self):
781
"""See BzrDir.destroy_workingtree."""
782
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
784
def destroy_workingtree_metadata(self):
785
"""See BzrDir.destroy_workingtree_metadata."""
786
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
789
def get_branch_transport(self, branch_format, name=None):
790
"""See BzrDir.get_branch_transport()."""
792
raise errors.NoColocatedBranchSupport(self)
793
if branch_format is None:
794
return self.transport
796
branch_format.get_format_string()
797
except NotImplementedError:
798
return self.transport
799
raise errors.IncompatibleFormat(branch_format, self._format)
801
def get_repository_transport(self, repository_format):
802
"""See BzrDir.get_repository_transport()."""
803
if repository_format is None:
804
return self.transport
806
repository_format.get_format_string()
807
except NotImplementedError:
808
return self.transport
809
raise errors.IncompatibleFormat(repository_format, self._format)
811
def get_workingtree_transport(self, workingtree_format):
812
"""See BzrDir.get_workingtree_transport()."""
813
if workingtree_format is None:
814
return self.transport
816
workingtree_format.get_format_string()
817
except NotImplementedError:
818
return self.transport
819
raise errors.IncompatibleFormat(workingtree_format, self._format)
821
def needs_format_conversion(self, format=None):
822
"""See BzrDir.needs_format_conversion()."""
823
# if the format is not the same as the system default,
824
# an upgrade is needed.
826
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
827
% 'needs_format_conversion(format=None)')
828
format = BzrDirFormat.get_default_format()
829
return not isinstance(self._format, format.__class__)
831
def open_branch(self, name=None, unsupported=False,
832
ignore_fallbacks=False):
833
"""See BzrDir.open_branch."""
834
from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
835
format = BzrBranchFormat4()
836
self._check_supported(format, unsupported)
837
return format.open(self, name, _found=True)
839
def sprout(self, url, revision_id=None, force_new_repo=False,
840
possible_transports=None, accelerator_tree=None,
841
hardlink=False, stacked=False, create_tree_if_local=True,
843
"""See BzrDir.sprout()."""
844
if source_branch is not None:
845
my_branch = self.open_branch()
846
if source_branch.base != my_branch.base:
847
raise AssertionError(
848
"source branch %r is not within %r with branch %r" %
849
(source_branch, self, my_branch))
851
raise errors.UnstackableBranchFormat(
852
self._format, self.root_transport.base)
853
if not create_tree_if_local:
854
raise errors.MustHaveWorkingTree(
855
self._format, self.root_transport.base)
856
from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
858
result = self._format._initialize_for_clone(url)
860
self.open_repository().clone(result, revision_id=revision_id)
861
except errors.NoRepositoryPresent:
864
self.open_branch().sprout(result, revision_id=revision_id)
865
except errors.NotBranchError:
868
# we always want a working tree
869
WorkingTreeFormat2().initialize(result,
870
accelerator_tree=accelerator_tree,
875
class BzrDir4(BzrDirPreSplitOut):
876
"""A .bzr version 4 control object.
878
This is a deprecated format and may be removed after sept 2006.
881
def create_repository(self, shared=False):
882
"""See BzrDir.create_repository."""
883
return self._format.repository_format.initialize(self, shared)
885
def needs_format_conversion(self, format=None):
886
"""Format 4 dirs are always in need of conversion."""
888
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
889
% 'needs_format_conversion(format=None)')
892
def open_repository(self):
893
"""See BzrDir.open_repository."""
894
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat4
895
return RepositoryFormat4().open(self, _found=True)
900
class BzrDir5(BzrDirPreSplitOut):
901
"""A .bzr version 5 control object.
903
This is a deprecated format and may be removed after sept 2006.
906
def has_workingtree(self):
907
"""See BzrDir.has_workingtree."""
910
def open_repository(self):
911
"""See BzrDir.open_repository."""
912
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat5
913
return RepositoryFormat5().open(self, _found=True)
915
def open_workingtree(self, _unsupported=False,
916
recommend_upgrade=True):
917
"""See BzrDir.create_workingtree."""
918
from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
919
wt_format = WorkingTreeFormat2()
920
# we don't warn here about upgrades; that ought to be handled for the
922
return wt_format.open(self, _found=True)
925
class BzrDir6(BzrDirPreSplitOut):
926
"""A .bzr version 6 control object.
928
This is a deprecated format and may be removed after sept 2006.
931
def has_workingtree(self):
932
"""See BzrDir.has_workingtree."""
935
def open_repository(self):
936
"""See BzrDir.open_repository."""
937
from bzrlib.plugins.weave_fmt.repository import RepositoryFormat6
938
return RepositoryFormat6().open(self, _found=True)
940
def open_workingtree(self, _unsupported=False,
941
recommend_upgrade=True):
942
"""See BzrDir.create_workingtree."""
943
# we don't warn here about upgrades; that ought to be handled for the
945
from bzrlib.plugins.weave_fmt.workingtree import WorkingTreeFormat2
946
return WorkingTreeFormat2().open(self, _found=True)