1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
"""BzrDir logic. The BzrDir is the basic control directory used by bzr.
19
At format 7 this was split out into Branch, Repository and Checkout control
22
Note: This module has a lot of ``open`` functions/methods that return
23
references to in-memory objects. As a rule, there are no matching ``close``
24
methods. To free any associated resources, simply stop referencing the
28
# TODO: Move old formats into a plugin to make this file smaller.
33
from bzrlib.lazy_import import lazy_import
34
lazy_import(globals(), """
35
from stat import S_ISDIR
49
revision as _mod_revision,
59
from bzrlib.osutils import (
62
from bzrlib.push import (
65
from bzrlib.repofmt import pack_repo
66
from bzrlib.smart.client import _SmartClient
67
from bzrlib.store.versioned import WeaveStore
68
from bzrlib.transactions import WriteTransaction
69
from bzrlib.transport import (
70
do_catching_redirections,
73
remote as remote_transport,
75
from bzrlib.weave import Weave
78
from bzrlib.trace import (
91
"""A .bzr control diretory.
93
BzrDir instances let you create or open any of the things that can be
94
found within .bzr - checkouts, branches and repositories.
97
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
99
a transport connected to the directory this bzr was opened from
100
(i.e. the parent directory holding the .bzr directory).
102
Everything in the bzrdir should have the same file permissions.
104
:cvar hooks: An instance of BzrDirHooks.
107
def break_lock(self):
108
"""Invoke break_lock on the first object in the bzrdir.
110
If there is a tree, the tree is opened and break_lock() called.
111
Otherwise, branch is tried, and finally repository.
113
# XXX: This seems more like a UI function than something that really
114
# belongs in this class.
116
thing_to_unlock = self.open_workingtree()
117
except (errors.NotLocalUrl, errors.NoWorkingTree):
119
thing_to_unlock = self.open_branch()
120
except errors.NotBranchError:
122
thing_to_unlock = self.open_repository()
123
except errors.NoRepositoryPresent:
125
thing_to_unlock.break_lock()
127
def can_convert_format(self):
128
"""Return true if this bzrdir is one whose format we can convert from."""
131
def check_conversion_target(self, target_format):
132
target_repo_format = target_format.repository_format
133
source_repo_format = self._format.repository_format
134
source_repo_format.check_conversion_target(target_repo_format)
137
def _check_supported(format, allow_unsupported,
138
recommend_upgrade=True,
140
"""Give an error or warning on old formats.
142
:param format: may be any kind of format - workingtree, branch,
145
:param allow_unsupported: If true, allow opening
146
formats that are strongly deprecated, and which may
147
have limited functionality.
149
:param recommend_upgrade: If true (default), warn
150
the user through the ui object that they may wish
151
to upgrade the object.
153
# TODO: perhaps move this into a base Format class; it's not BzrDir
154
# specific. mbp 20070323
155
if not allow_unsupported and not format.is_supported():
156
# see open_downlevel to open legacy branches.
157
raise errors.UnsupportedFormatError(format=format)
158
if recommend_upgrade \
159
and getattr(format, 'upgrade_recommended', False):
160
ui.ui_factory.recommend_upgrade(
161
format.get_format_description(),
164
def clone(self, url, revision_id=None, force_new_repo=False,
165
preserve_stacking=False):
166
"""Clone this bzrdir and its contents to url verbatim.
168
:param url: The url create the clone at. If url's last component does
169
not exist, it will be created.
170
:param revision_id: The tip revision-id to use for any branch or
171
working tree. If not None, then the clone operation may tune
172
itself to download less data.
173
:param force_new_repo: Do not use a shared repository for the target
174
even if one is available.
175
:param preserve_stacking: When cloning a stacked branch, stack the
176
new branch on top of the other branch's stacked-on branch.
178
return self.clone_on_transport(get_transport(url),
179
revision_id=revision_id,
180
force_new_repo=force_new_repo,
181
preserve_stacking=preserve_stacking)
183
def clone_on_transport(self, transport, revision_id=None,
184
force_new_repo=False, preserve_stacking=False, stacked_on=None,
185
create_prefix=False, use_existing_dir=True):
186
"""Clone this bzrdir and its contents to transport verbatim.
188
:param transport: The transport for the location to produce the clone
189
at. If the target directory does not exist, it will be created.
190
:param revision_id: The tip revision-id to use for any branch or
191
working tree. If not None, then the clone operation may tune
192
itself to download less data.
193
:param force_new_repo: Do not use a shared repository for the target,
194
even if one is available.
195
:param preserve_stacking: When cloning a stacked branch, stack the
196
new branch on top of the other branch's stacked-on branch.
197
:param create_prefix: Create any missing directories leading up to
199
:param use_existing_dir: Use an existing directory if one exists.
201
# Overview: put together a broad description of what we want to end up
202
# with; then make as few api calls as possible to do it.
204
# We may want to create a repo/branch/tree, if we do so what format
205
# would we want for each:
206
require_stacking = (stacked_on is not None)
207
format = self.cloning_metadir(require_stacking)
209
# Figure out what objects we want:
211
local_repo = self.find_repository()
212
except errors.NoRepositoryPresent:
215
local_branch = self.open_branch()
216
except errors.NotBranchError:
219
# enable fallbacks when branch is not a branch reference
220
if local_branch.repository.has_same_location(local_repo):
221
local_repo = local_branch.repository
222
if preserve_stacking:
224
stacked_on = local_branch.get_stacked_on_url()
225
except (errors.UnstackableBranchFormat,
226
errors.UnstackableRepositoryFormat,
229
# Bug: We create a metadir without knowing if it can support stacking,
230
# we should look up the policy needs first, or just use it as a hint,
233
make_working_trees = local_repo.make_working_trees()
234
want_shared = local_repo.is_shared()
235
repo_format_name = format.repository_format.network_name()
237
make_working_trees = False
239
repo_format_name = None
241
result_repo, result, require_stacking, repository_policy = \
242
format.initialize_on_transport_ex(transport,
243
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
244
force_new_repo=force_new_repo, stacked_on=stacked_on,
245
stack_on_pwd=self.root_transport.base,
246
repo_format_name=repo_format_name,
247
make_working_trees=make_working_trees, shared_repo=want_shared)
249
# If the result repository is in the same place as the resulting
250
# bzr dir, it will have no content, further if the result is not stacked
251
# then we know all content should be copied, and finally if we are
252
# copying up to a specific revision_id then we can use the
253
# pending-ancestry-result which does not require traversing all of
254
# history to describe it.
255
if (result_repo.bzrdir.root_transport.base ==
256
result.root_transport.base and not require_stacking and
257
revision_id is not None):
258
fetch_spec = graph.PendingAncestryResult(
259
[revision_id], local_repo)
260
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
262
result_repo.fetch(local_repo, revision_id=revision_id)
265
# 1 if there is a branch present
266
# make sure its content is available in the target repository
268
if local_branch is not None:
269
result_branch = local_branch.clone(result, revision_id=revision_id,
270
repository_policy=repository_policy)
272
# Cheaper to check if the target is not local, than to try making
274
result.root_transport.local_abspath('.')
275
if result_repo is None or result_repo.make_working_trees():
276
self.open_workingtree().clone(result)
277
except (errors.NoWorkingTree, errors.NotLocalUrl):
281
# TODO: This should be given a Transport, and should chdir up; otherwise
282
# this will open a new connection.
283
def _make_tail(self, url):
284
t = get_transport(url)
288
def create(cls, base, format=None, possible_transports=None):
289
"""Create a new BzrDir at the url 'base'.
291
:param format: If supplied, the format of branch to create. If not
292
supplied, the default is used.
293
:param possible_transports: If supplied, a list of transports that
294
can be reused to share a remote connection.
296
if cls is not BzrDir:
297
raise AssertionError("BzrDir.create always creates the default"
298
" format, not one of %r" % cls)
299
t = get_transport(base, possible_transports)
302
format = BzrDirFormat.get_default_format()
303
return format.initialize_on_transport(t)
306
def find_bzrdirs(transport, evaluate=None, list_current=None):
307
"""Find bzrdirs recursively from current location.
309
This is intended primarily as a building block for more sophisticated
310
functionality, like finding trees under a directory, or finding
311
branches that use a given repository.
312
:param evaluate: An optional callable that yields recurse, value,
313
where recurse controls whether this bzrdir is recursed into
314
and value is the value to yield. By default, all bzrdirs
315
are recursed into, and the return value is the bzrdir.
316
:param list_current: if supplied, use this function to list the current
317
directory, instead of Transport.list_dir
318
:return: a generator of found bzrdirs, or whatever evaluate returns.
320
if list_current is None:
321
def list_current(transport):
322
return transport.list_dir('')
324
def evaluate(bzrdir):
327
pending = [transport]
328
while len(pending) > 0:
329
current_transport = pending.pop()
332
bzrdir = BzrDir.open_from_transport(current_transport)
333
except errors.NotBranchError:
336
recurse, value = evaluate(bzrdir)
339
subdirs = list_current(current_transport)
340
except errors.NoSuchFile:
343
for subdir in sorted(subdirs, reverse=True):
344
pending.append(current_transport.clone(subdir))
347
def find_branches(transport):
348
"""Find all branches under a transport.
350
This will find all branches below the transport, including branches
351
inside other branches. Where possible, it will use
352
Repository.find_branches.
354
To list all the branches that use a particular Repository, see
355
Repository.find_branches
357
def evaluate(bzrdir):
359
repository = bzrdir.open_repository()
360
except errors.NoRepositoryPresent:
363
return False, (None, repository)
365
branch = bzrdir.open_branch()
366
except errors.NotBranchError:
367
return True, (None, None)
369
return True, (branch, None)
371
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
373
branches.extend(repo.find_branches())
374
if branch is not None:
375
branches.append(branch)
378
def destroy_repository(self):
379
"""Destroy the repository in this BzrDir"""
380
raise NotImplementedError(self.destroy_repository)
382
def create_branch(self):
383
"""Create a branch in this BzrDir.
385
The bzrdir's format will control what branch format is created.
386
For more control see BranchFormatXX.create(a_bzrdir).
388
raise NotImplementedError(self.create_branch)
390
def destroy_branch(self):
391
"""Destroy the branch in this BzrDir"""
392
raise NotImplementedError(self.destroy_branch)
395
def create_branch_and_repo(base, force_new_repo=False, format=None):
396
"""Create a new BzrDir, Branch and Repository at the url 'base'.
398
This will use the current default BzrDirFormat unless one is
399
specified, and use whatever
400
repository format that that uses via bzrdir.create_branch and
401
create_repository. If a shared repository is available that is used
404
The created Branch object is returned.
406
:param base: The URL to create the branch at.
407
:param force_new_repo: If True a new repository is always created.
408
:param format: If supplied, the format of branch to create. If not
409
supplied, the default is used.
411
bzrdir = BzrDir.create(base, format)
412
bzrdir._find_or_create_repository(force_new_repo)
413
return bzrdir.create_branch()
415
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
416
stack_on_pwd=None, require_stacking=False):
417
"""Return an object representing a policy to use.
419
This controls whether a new repository is created, and the format of
420
that repository, or some existing shared repository used instead.
422
If stack_on is supplied, will not seek a containing shared repo.
424
:param force_new_repo: If True, require a new repository to be created.
425
:param stack_on: If supplied, the location to stack on. If not
426
supplied, a default_stack_on location may be used.
427
:param stack_on_pwd: If stack_on is relative, the location it is
430
def repository_policy(found_bzrdir):
433
config = found_bzrdir.get_config()
435
stack_on = config.get_default_stack_on()
436
if stack_on is not None:
437
stack_on_pwd = found_bzrdir.root_transport.base
439
# does it have a repository ?
441
repository = found_bzrdir.open_repository()
442
except errors.NoRepositoryPresent:
445
if ((found_bzrdir.root_transport.base !=
446
self.root_transport.base) and not repository.is_shared()):
447
# Don't look higher, can't use a higher shared repo.
455
return UseExistingRepository(repository, stack_on,
456
stack_on_pwd, require_stacking=require_stacking), True
458
return CreateRepository(self, stack_on, stack_on_pwd,
459
require_stacking=require_stacking), True
461
if not force_new_repo:
463
policy = self._find_containing(repository_policy)
464
if policy is not None:
468
return UseExistingRepository(self.open_repository(),
469
stack_on, stack_on_pwd,
470
require_stacking=require_stacking)
471
except errors.NoRepositoryPresent:
473
return CreateRepository(self, stack_on, stack_on_pwd,
474
require_stacking=require_stacking)
476
def _find_or_create_repository(self, force_new_repo):
477
"""Create a new repository if needed, returning the repository."""
478
policy = self.determine_repository_policy(force_new_repo)
479
return policy.acquire_repository()[0]
482
def create_branch_convenience(base, force_new_repo=False,
483
force_new_tree=None, format=None,
484
possible_transports=None):
485
"""Create a new BzrDir, Branch and Repository at the url 'base'.
487
This is a convenience function - it will use an existing repository
488
if possible, can be told explicitly whether to create a working tree or
491
This will use the current default BzrDirFormat unless one is
492
specified, and use whatever
493
repository format that that uses via bzrdir.create_branch and
494
create_repository. If a shared repository is available that is used
495
preferentially. Whatever repository is used, its tree creation policy
498
The created Branch object is returned.
499
If a working tree cannot be made due to base not being a file:// url,
500
no error is raised unless force_new_tree is True, in which case no
501
data is created on disk and NotLocalUrl is raised.
503
:param base: The URL to create the branch at.
504
:param force_new_repo: If True a new repository is always created.
505
:param force_new_tree: If True or False force creation of a tree or
506
prevent such creation respectively.
507
:param format: Override for the bzrdir format to create.
508
:param possible_transports: An optional reusable transports list.
511
# check for non local urls
512
t = get_transport(base, possible_transports)
513
if not isinstance(t, local.LocalTransport):
514
raise errors.NotLocalUrl(base)
515
bzrdir = BzrDir.create(base, format, possible_transports)
516
repo = bzrdir._find_or_create_repository(force_new_repo)
517
result = bzrdir.create_branch()
518
if force_new_tree or (repo.make_working_trees() and
519
force_new_tree is None):
521
bzrdir.create_workingtree()
522
except errors.NotLocalUrl:
527
def create_standalone_workingtree(base, format=None):
528
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
530
'base' must be a local path or a file:// url.
532
This will use the current default BzrDirFormat unless one is
533
specified, and use whatever
534
repository format that that uses for bzrdirformat.create_workingtree,
535
create_branch and create_repository.
537
:param format: Override for the bzrdir format to create.
538
:return: The WorkingTree object.
540
t = get_transport(base)
541
if not isinstance(t, local.LocalTransport):
542
raise errors.NotLocalUrl(base)
543
bzrdir = BzrDir.create_branch_and_repo(base,
545
format=format).bzrdir
546
return bzrdir.create_workingtree()
548
def create_workingtree(self, revision_id=None, from_branch=None,
549
accelerator_tree=None, hardlink=False):
550
"""Create a working tree at this BzrDir.
552
:param revision_id: create it as of this revision id.
553
:param from_branch: override bzrdir branch (for lightweight checkouts)
554
:param accelerator_tree: A tree which can be used for retrieving file
555
contents more quickly than the revision tree, i.e. a workingtree.
556
The revision tree will be used for cases where accelerator_tree's
557
content is different.
559
raise NotImplementedError(self.create_workingtree)
561
def backup_bzrdir(self):
562
"""Backup this bzr control directory.
564
:return: Tuple with old path name and new path name
566
pb = ui.ui_factory.nested_progress_bar()
568
# FIXME: bug 300001 -- the backup fails if the backup directory
569
# already exists, but it should instead either remove it or make
570
# a new backup directory.
572
# FIXME: bug 262450 -- the backup directory should have the same
573
# permissions as the .bzr directory (probably a bug in copy_tree)
574
old_path = self.root_transport.abspath('.bzr')
575
new_path = self.root_transport.abspath('backup.bzr')
576
pb.note('making backup of %s' % (old_path,))
577
pb.note(' to %s' % (new_path,))
578
self.root_transport.copy_tree('.bzr', 'backup.bzr')
579
return (old_path, new_path)
583
def retire_bzrdir(self, limit=10000):
584
"""Permanently disable the bzrdir.
586
This is done by renaming it to give the user some ability to recover
587
if there was a problem.
589
This will have horrible consequences if anyone has anything locked or
591
:param limit: number of times to retry
596
to_path = '.bzr.retired.%d' % i
597
self.root_transport.rename('.bzr', to_path)
598
note("renamed %s to %s"
599
% (self.root_transport.abspath('.bzr'), to_path))
601
except (errors.TransportError, IOError, errors.PathError):
608
def destroy_workingtree(self):
609
"""Destroy the working tree at this BzrDir.
611
Formats that do not support this may raise UnsupportedOperation.
613
raise NotImplementedError(self.destroy_workingtree)
615
def destroy_workingtree_metadata(self):
616
"""Destroy the control files for the working tree at this BzrDir.
618
The contents of working tree files are not affected.
619
Formats that do not support this may raise UnsupportedOperation.
621
raise NotImplementedError(self.destroy_workingtree_metadata)
623
def _find_containing(self, evaluate):
624
"""Find something in a containing control directory.
626
This method will scan containing control dirs, until it finds what
627
it is looking for, decides that it will never find it, or runs out
628
of containing control directories to check.
630
It is used to implement find_repository and
631
determine_repository_policy.
633
:param evaluate: A function returning (value, stop). If stop is True,
634
the value will be returned.
638
result, stop = evaluate(found_bzrdir)
641
next_transport = found_bzrdir.root_transport.clone('..')
642
if (found_bzrdir.root_transport.base == next_transport.base):
643
# top of the file system
645
# find the next containing bzrdir
647
found_bzrdir = BzrDir.open_containing_from_transport(
649
except errors.NotBranchError:
652
def find_repository(self):
653
"""Find the repository that should be used.
655
This does not require a branch as we use it to find the repo for
656
new branches as well as to hook existing branches up to their
659
def usable_repository(found_bzrdir):
660
# does it have a repository ?
662
repository = found_bzrdir.open_repository()
663
except errors.NoRepositoryPresent:
665
if found_bzrdir.root_transport.base == self.root_transport.base:
666
return repository, True
667
elif repository.is_shared():
668
return repository, True
672
found_repo = self._find_containing(usable_repository)
673
if found_repo is None:
674
raise errors.NoRepositoryPresent(self)
677
def get_branch_reference(self):
678
"""Return the referenced URL for the branch in this bzrdir.
680
:raises NotBranchError: If there is no Branch.
681
:return: The URL the branch in this bzrdir references if it is a
682
reference branch, or None for regular branches.
686
def get_branch_transport(self, branch_format):
687
"""Get the transport for use by branch format in this BzrDir.
689
Note that bzr dirs that do not support format strings will raise
690
IncompatibleFormat if the branch format they are given has
691
a format string, and vice versa.
693
If branch_format is None, the transport is returned with no
694
checking. If it is not None, then the returned transport is
695
guaranteed to point to an existing directory ready for use.
697
raise NotImplementedError(self.get_branch_transport)
699
def _find_creation_modes(self):
700
"""Determine the appropriate modes for files and directories.
702
They're always set to be consistent with the base directory,
703
assuming that this transport allows setting modes.
705
# TODO: Do we need or want an option (maybe a config setting) to turn
706
# this off or override it for particular locations? -- mbp 20080512
707
if self._mode_check_done:
709
self._mode_check_done = True
711
st = self.transport.stat('.')
712
except errors.TransportNotPossible:
713
self._dir_mode = None
714
self._file_mode = None
716
# Check the directory mode, but also make sure the created
717
# directories and files are read-write for this user. This is
718
# mostly a workaround for filesystems which lie about being able to
719
# write to a directory (cygwin & win32)
720
if (st.st_mode & 07777 == 00000):
721
# FTP allows stat but does not return dir/file modes
722
self._dir_mode = None
723
self._file_mode = None
725
self._dir_mode = (st.st_mode & 07777) | 00700
726
# Remove the sticky and execute bits for files
727
self._file_mode = self._dir_mode & ~07111
729
def _get_file_mode(self):
730
"""Return Unix mode for newly created files, or None.
732
if not self._mode_check_done:
733
self._find_creation_modes()
734
return self._file_mode
736
def _get_dir_mode(self):
737
"""Return Unix mode for newly created directories, or None.
739
if not self._mode_check_done:
740
self._find_creation_modes()
741
return self._dir_mode
743
def get_repository_transport(self, repository_format):
744
"""Get the transport for use by repository format in this BzrDir.
746
Note that bzr dirs that do not support format strings will raise
747
IncompatibleFormat if the repository format they are given has
748
a format string, and vice versa.
750
If repository_format is None, the transport is returned with no
751
checking. If it is not None, then the returned transport is
752
guaranteed to point to an existing directory ready for use.
754
raise NotImplementedError(self.get_repository_transport)
756
def get_workingtree_transport(self, tree_format):
757
"""Get the transport for use by workingtree format in this BzrDir.
759
Note that bzr dirs that do not support format strings will raise
760
IncompatibleFormat if the workingtree format they are given has a
761
format string, and vice versa.
763
If workingtree_format is None, the transport is returned with no
764
checking. If it is not None, then the returned transport is
765
guaranteed to point to an existing directory ready for use.
767
raise NotImplementedError(self.get_workingtree_transport)
769
def get_config(self):
770
"""Get configuration for this BzrDir."""
771
return config.BzrDirConfig(self)
773
def _get_config(self):
774
"""By default, no configuration is available."""
777
def __init__(self, _transport, _format):
778
"""Initialize a Bzr control dir object.
780
Only really common logic should reside here, concrete classes should be
781
made with varying behaviours.
783
:param _format: the format that is creating this BzrDir instance.
784
:param _transport: the transport this dir is based at.
786
self._format = _format
787
self.transport = _transport.clone('.bzr')
788
self.root_transport = _transport
789
self._mode_check_done = False
791
def is_control_filename(self, filename):
792
"""True if filename is the name of a path which is reserved for bzrdir's.
794
:param filename: A filename within the root transport of this bzrdir.
796
This is true IF and ONLY IF the filename is part of the namespace reserved
797
for bzr control dirs. Currently this is the '.bzr' directory in the root
798
of the root_transport. it is expected that plugins will need to extend
799
this in the future - for instance to make bzr talk with svn working
802
# this might be better on the BzrDirFormat class because it refers to
803
# all the possible bzrdir disk formats.
804
# This method is tested via the workingtree is_control_filename tests-
805
# it was extracted from WorkingTree.is_control_filename. If the method's
806
# contract is extended beyond the current trivial implementation, please
807
# add new tests for it to the appropriate place.
808
return filename == '.bzr' or filename.startswith('.bzr/')
810
def needs_format_conversion(self, format=None):
811
"""Return true if this bzrdir needs convert_format run on it.
813
For instance, if the repository format is out of date but the
814
branch and working tree are not, this should return True.
816
:param format: Optional parameter indicating a specific desired
817
format we plan to arrive at.
819
raise NotImplementedError(self.needs_format_conversion)
822
def open_unsupported(base):
823
"""Open a branch which is not supported."""
824
return BzrDir.open(base, _unsupported=True)
827
def open(base, _unsupported=False, possible_transports=None):
828
"""Open an existing bzrdir, rooted at 'base' (url).
830
:param _unsupported: a private parameter to the BzrDir class.
832
t = get_transport(base, possible_transports=possible_transports)
833
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
836
def open_from_transport(transport, _unsupported=False,
837
_server_formats=True):
838
"""Open a bzrdir within a particular directory.
840
:param transport: Transport containing the bzrdir.
841
:param _unsupported: private.
843
for hook in BzrDir.hooks['pre_open']:
845
# Keep initial base since 'transport' may be modified while following
847
base = transport.base
848
def find_format(transport):
849
return transport, BzrDirFormat.find_format(
850
transport, _server_formats=_server_formats)
852
def redirected(transport, e, redirection_notice):
853
redirected_transport = transport._redirected_to(e.source, e.target)
854
if redirected_transport is None:
855
raise errors.NotBranchError(base)
856
note('%s is%s redirected to %s',
857
transport.base, e.permanently, redirected_transport.base)
858
return redirected_transport
861
transport, format = do_catching_redirections(find_format,
864
except errors.TooManyRedirections:
865
raise errors.NotBranchError(base)
867
BzrDir._check_supported(format, _unsupported)
868
return format.open(transport, _found=True)
870
def open_branch(self, unsupported=False, ignore_fallbacks=False):
871
"""Open the branch object at this BzrDir if one is present.
873
If unsupported is True, then no longer supported branch formats can
876
TODO: static convenience version of this?
878
raise NotImplementedError(self.open_branch)
881
def open_containing(url, possible_transports=None):
882
"""Open an existing branch which contains url.
884
:param url: url to search from.
885
See open_containing_from_transport for more detail.
887
transport = get_transport(url, possible_transports)
888
return BzrDir.open_containing_from_transport(transport)
891
def open_containing_from_transport(a_transport):
892
"""Open an existing branch which contains a_transport.base.
894
This probes for a branch at a_transport, and searches upwards from there.
896
Basically we keep looking up until we find the control directory or
897
run into the root. If there isn't one, raises NotBranchError.
898
If there is one and it is either an unrecognised format or an unsupported
899
format, UnknownFormatError or UnsupportedFormatError are raised.
900
If there is one, it is returned, along with the unused portion of url.
902
:return: The BzrDir that contains the path, and a Unicode path
903
for the rest of the URL.
905
# this gets the normalised url back. I.e. '.' -> the full path.
906
url = a_transport.base
909
result = BzrDir.open_from_transport(a_transport)
910
return result, urlutils.unescape(a_transport.relpath(url))
911
except errors.NotBranchError, e:
914
new_t = a_transport.clone('..')
915
except errors.InvalidURLJoin:
916
# reached the root, whatever that may be
917
raise errors.NotBranchError(path=url)
918
if new_t.base == a_transport.base:
919
# reached the root, whatever that may be
920
raise errors.NotBranchError(path=url)
923
def _get_tree_branch(self):
924
"""Return the branch and tree, if any, for this bzrdir.
926
Return None for tree if not present or inaccessible.
927
Raise NotBranchError if no branch is present.
928
:return: (tree, branch)
931
tree = self.open_workingtree()
932
except (errors.NoWorkingTree, errors.NotLocalUrl):
934
branch = self.open_branch()
940
def open_tree_or_branch(klass, location):
941
"""Return the branch and working tree at a location.
943
If there is no tree at the location, tree will be None.
944
If there is no branch at the location, an exception will be
946
:return: (tree, branch)
948
bzrdir = klass.open(location)
949
return bzrdir._get_tree_branch()
952
def open_containing_tree_or_branch(klass, location):
953
"""Return the branch and working tree contained by a location.
955
Returns (tree, branch, relpath).
956
If there is no tree at containing the location, tree will be None.
957
If there is no branch containing the location, an exception will be
959
relpath is the portion of the path that is contained by the branch.
961
bzrdir, relpath = klass.open_containing(location)
962
tree, branch = bzrdir._get_tree_branch()
963
return tree, branch, relpath
966
def open_containing_tree_branch_or_repository(klass, location):
967
"""Return the working tree, branch and repo contained by a location.
969
Returns (tree, branch, repository, relpath).
970
If there is no tree containing the location, tree will be None.
971
If there is no branch containing the location, branch will be None.
972
If there is no repository containing the location, repository will be
974
relpath is the portion of the path that is contained by the innermost
977
If no tree, branch or repository is found, a NotBranchError is raised.
979
bzrdir, relpath = klass.open_containing(location)
981
tree, branch = bzrdir._get_tree_branch()
982
except errors.NotBranchError:
984
repo = bzrdir.find_repository()
985
return None, None, repo, relpath
986
except (errors.NoRepositoryPresent):
987
raise errors.NotBranchError(location)
988
return tree, branch, branch.repository, relpath
990
def open_repository(self, _unsupported=False):
991
"""Open the repository object at this BzrDir if one is present.
993
This will not follow the Branch object pointer - it's strictly a direct
994
open facility. Most client code should use open_branch().repository to
997
:param _unsupported: a private parameter, not part of the api.
998
TODO: static convenience version of this?
1000
raise NotImplementedError(self.open_repository)
1002
def open_workingtree(self, _unsupported=False,
1003
recommend_upgrade=True, from_branch=None):
1004
"""Open the workingtree object at this BzrDir if one is present.
1006
:param recommend_upgrade: Optional keyword parameter, when True (the
1007
default), emit through the ui module a recommendation that the user
1008
upgrade the working tree when the workingtree being opened is old
1009
(but still fully supported).
1010
:param from_branch: override bzrdir branch (for lightweight checkouts)
1012
raise NotImplementedError(self.open_workingtree)
1014
def has_branch(self):
1015
"""Tell if this bzrdir contains a branch.
1017
Note: if you're going to open the branch, you should just go ahead
1018
and try, and not ask permission first. (This method just opens the
1019
branch and discards it, and that's somewhat expensive.)
1024
except errors.NotBranchError:
1027
def has_workingtree(self):
1028
"""Tell if this bzrdir contains a working tree.
1030
This will still raise an exception if the bzrdir has a workingtree that
1031
is remote & inaccessible.
1033
Note: if you're going to open the working tree, you should just go ahead
1034
and try, and not ask permission first. (This method just opens the
1035
workingtree and discards it, and that's somewhat expensive.)
1038
self.open_workingtree(recommend_upgrade=False)
1040
except errors.NoWorkingTree:
1043
def _cloning_metadir(self):
1044
"""Produce a metadir suitable for cloning with.
1046
:returns: (destination_bzrdir_format, source_repository)
1048
result_format = self._format.__class__()
1051
branch = self.open_branch(ignore_fallbacks=True)
1052
source_repository = branch.repository
1053
result_format._branch_format = branch._format
1054
except errors.NotBranchError:
1055
source_branch = None
1056
source_repository = self.open_repository()
1057
except errors.NoRepositoryPresent:
1058
source_repository = None
1060
# XXX TODO: This isinstance is here because we have not implemented
1061
# the fix recommended in bug # 103195 - to delegate this choice the
1062
# repository itself.
1063
repo_format = source_repository._format
1064
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1065
source_repository._ensure_real()
1066
repo_format = source_repository._real_repository._format
1067
result_format.repository_format = repo_format
1069
# TODO: Couldn't we just probe for the format in these cases,
1070
# rather than opening the whole tree? It would be a little
1071
# faster. mbp 20070401
1072
tree = self.open_workingtree(recommend_upgrade=False)
1073
except (errors.NoWorkingTree, errors.NotLocalUrl):
1074
result_format.workingtree_format = None
1076
result_format.workingtree_format = tree._format.__class__()
1077
return result_format, source_repository
1079
def cloning_metadir(self, require_stacking=False):
1080
"""Produce a metadir suitable for cloning or sprouting with.
1082
These operations may produce workingtrees (yes, even though they're
1083
"cloning" something that doesn't have a tree), so a viable workingtree
1084
format must be selected.
1086
:require_stacking: If True, non-stackable formats will be upgraded
1087
to similar stackable formats.
1088
:returns: a BzrDirFormat with all component formats either set
1089
appropriately or set to None if that component should not be
1092
format, repository = self._cloning_metadir()
1093
if format._workingtree_format is None:
1095
if repository is None:
1096
# No repository either
1098
# We have a repository, so set a working tree? (Why? This seems to
1099
# contradict the stated return value in the docstring).
1100
tree_format = repository._format._matchingbzrdir.workingtree_format
1101
format.workingtree_format = tree_format.__class__()
1102
if require_stacking:
1103
format.require_stacking()
1106
def checkout_metadir(self):
1107
return self.cloning_metadir()
1109
def sprout(self, url, revision_id=None, force_new_repo=False,
1110
recurse='down', possible_transports=None,
1111
accelerator_tree=None, hardlink=False, stacked=False,
1112
source_branch=None, create_tree_if_local=True):
1113
"""Create a copy of this bzrdir prepared for use as a new line of
1116
If url's last component does not exist, it will be created.
1118
Attributes related to the identity of the source branch like
1119
branch nickname will be cleaned, a working tree is created
1120
whether one existed before or not; and a local branch is always
1123
if revision_id is not None, then the clone operation may tune
1124
itself to download less data.
1125
:param accelerator_tree: A tree which can be used for retrieving file
1126
contents more quickly than the revision tree, i.e. a workingtree.
1127
The revision tree will be used for cases where accelerator_tree's
1128
content is different.
1129
:param hardlink: If true, hard-link files from accelerator_tree,
1131
:param stacked: If true, create a stacked branch referring to the
1132
location of this control directory.
1133
:param create_tree_if_local: If true, a working-tree will be created
1134
when working locally.
1136
target_transport = get_transport(url, possible_transports)
1137
target_transport.ensure_base()
1138
cloning_format = self.cloning_metadir(stacked)
1139
# Create/update the result branch
1140
result = cloning_format.initialize_on_transport(target_transport)
1141
# if a stacked branch wasn't requested, we don't create one
1142
# even if the origin was stacked
1143
stacked_branch_url = None
1144
if source_branch is not None:
1146
stacked_branch_url = self.root_transport.base
1147
source_repository = source_branch.repository
1150
source_branch = self.open_branch()
1151
source_repository = source_branch.repository
1153
stacked_branch_url = self.root_transport.base
1154
except errors.NotBranchError:
1155
source_branch = None
1157
source_repository = self.open_repository()
1158
except errors.NoRepositoryPresent:
1159
source_repository = None
1160
repository_policy = result.determine_repository_policy(
1161
force_new_repo, stacked_branch_url, require_stacking=stacked)
1162
result_repo, is_new_repo = repository_policy.acquire_repository()
1163
if is_new_repo and revision_id is not None and not stacked:
1164
fetch_spec = graph.PendingAncestryResult(
1165
[revision_id], source_repository)
1168
if source_repository is not None:
1169
# Fetch while stacked to prevent unstacked fetch from
1171
if fetch_spec is None:
1172
result_repo.fetch(source_repository, revision_id=revision_id)
1174
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
1176
if source_branch is None:
1177
# this is for sprouting a bzrdir without a branch; is that
1179
# Not especially, but it's part of the contract.
1180
result_branch = result.create_branch()
1182
result_branch = source_branch.sprout(result,
1183
revision_id=revision_id, repository_policy=repository_policy)
1184
mutter("created new branch %r" % (result_branch,))
1186
# Create/update the result working tree
1187
if (create_tree_if_local and
1188
isinstance(target_transport, local.LocalTransport) and
1189
(result_repo is None or result_repo.make_working_trees())):
1190
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1194
if wt.path2id('') is None:
1196
wt.set_root_id(self.open_workingtree.get_root_id())
1197
except errors.NoWorkingTree:
1203
if recurse == 'down':
1205
basis = wt.basis_tree()
1207
subtrees = basis.iter_references()
1208
elif result_branch is not None:
1209
basis = result_branch.basis_tree()
1211
subtrees = basis.iter_references()
1212
elif source_branch is not None:
1213
basis = source_branch.basis_tree()
1215
subtrees = basis.iter_references()
1220
for path, file_id in subtrees:
1221
target = urlutils.join(url, urlutils.escape(path))
1222
sublocation = source_branch.reference_parent(file_id, path)
1223
sublocation.bzrdir.sprout(target,
1224
basis.get_reference_revision(file_id, path),
1225
force_new_repo=force_new_repo, recurse=recurse,
1228
if basis is not None:
1232
def push_branch(self, source, revision_id=None, overwrite=False,
1234
"""Push the source branch into this BzrDir."""
1236
# If we can open a branch, use its direct repository, otherwise see
1237
# if there is a repository without a branch.
1239
br_to = self.open_branch()
1240
except errors.NotBranchError:
1241
# Didn't find a branch, can we find a repository?
1242
repository_to = self.find_repository()
1244
# Found a branch, so we must have found a repository
1245
repository_to = br_to.repository
1247
push_result = PushResult()
1248
push_result.source_branch = source
1250
# We have a repository but no branch, copy the revisions, and then
1252
repository_to.fetch(source.repository, revision_id=revision_id)
1253
br_to = source.clone(self, revision_id=revision_id)
1254
if source.get_push_location() is None or remember:
1255
source.set_push_location(br_to.base)
1256
push_result.stacked_on = None
1257
push_result.branch_push_result = None
1258
push_result.old_revno = None
1259
push_result.old_revid = _mod_revision.NULL_REVISION
1260
push_result.target_branch = br_to
1261
push_result.master_branch = None
1262
push_result.workingtree_updated = False
1264
# We have successfully opened the branch, remember if necessary:
1265
if source.get_push_location() is None or remember:
1266
source.set_push_location(br_to.base)
1268
tree_to = self.open_workingtree()
1269
except errors.NotLocalUrl:
1270
push_result.branch_push_result = source.push(br_to,
1271
overwrite, stop_revision=revision_id)
1272
push_result.workingtree_updated = False
1273
except errors.NoWorkingTree:
1274
push_result.branch_push_result = source.push(br_to,
1275
overwrite, stop_revision=revision_id)
1276
push_result.workingtree_updated = None # Not applicable
1278
tree_to.lock_write()
1280
push_result.branch_push_result = source.push(
1281
tree_to.branch, overwrite, stop_revision=revision_id)
1285
push_result.workingtree_updated = True
1286
push_result.old_revno = push_result.branch_push_result.old_revno
1287
push_result.old_revid = push_result.branch_push_result.old_revid
1288
push_result.target_branch = \
1289
push_result.branch_push_result.target_branch
1293
class BzrDirHooks(hooks.Hooks):
1294
"""Hooks for BzrDir operations."""
1297
"""Create the default hooks."""
1298
hooks.Hooks.__init__(self)
1299
self.create_hook(hooks.HookPoint('pre_open',
1300
"Invoked before attempting to open a BzrDir with the transport "
1301
"that the open will use.", (1, 14), None))
1303
# install the default hooks
1304
BzrDir.hooks = BzrDirHooks()
1307
class BzrDirPreSplitOut(BzrDir):
1308
"""A common class for the all-in-one formats."""
1310
def __init__(self, _transport, _format):
1311
"""See BzrDir.__init__."""
1312
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1313
self._control_files = lockable_files.LockableFiles(
1314
self.get_branch_transport(None),
1315
self._format._lock_file_name,
1316
self._format._lock_class)
1318
def break_lock(self):
1319
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1320
raise NotImplementedError(self.break_lock)
1322
def cloning_metadir(self, require_stacking=False):
1323
"""Produce a metadir suitable for cloning with."""
1324
if require_stacking:
1325
return format_registry.make_bzrdir('1.6')
1326
return self._format.__class__()
1328
def clone(self, url, revision_id=None, force_new_repo=False,
1329
preserve_stacking=False):
1330
"""See BzrDir.clone().
1332
force_new_repo has no effect, since this family of formats always
1333
require a new repository.
1334
preserve_stacking has no effect, since no source branch using this
1335
family of formats can be stacked, so there is no stacking to preserve.
1337
self._make_tail(url)
1338
result = self._format._initialize_for_clone(url)
1339
self.open_repository().clone(result, revision_id=revision_id)
1340
from_branch = self.open_branch()
1341
from_branch.clone(result, revision_id=revision_id)
1343
tree = self.open_workingtree()
1344
except errors.NotLocalUrl:
1345
# make a new one, this format always has to have one.
1346
result._init_workingtree()
1351
def create_branch(self):
1352
"""See BzrDir.create_branch."""
1353
return self._format.get_branch_format().initialize(self)
1355
def destroy_branch(self):
1356
"""See BzrDir.destroy_branch."""
1357
raise errors.UnsupportedOperation(self.destroy_branch, self)
1359
def create_repository(self, shared=False):
1360
"""See BzrDir.create_repository."""
1362
raise errors.IncompatibleFormat('shared repository', self._format)
1363
return self.open_repository()
1365
def destroy_repository(self):
1366
"""See BzrDir.destroy_repository."""
1367
raise errors.UnsupportedOperation(self.destroy_repository, self)
1369
def create_workingtree(self, revision_id=None, from_branch=None,
1370
accelerator_tree=None, hardlink=False):
1371
"""See BzrDir.create_workingtree."""
1372
# The workingtree is sometimes created when the bzrdir is created,
1373
# but not when cloning.
1375
# this looks buggy but is not -really-
1376
# because this format creates the workingtree when the bzrdir is
1378
# clone and sprout will have set the revision_id
1379
# and that will have set it for us, its only
1380
# specific uses of create_workingtree in isolation
1381
# that can do wonky stuff here, and that only
1382
# happens for creating checkouts, which cannot be
1383
# done on this format anyway. So - acceptable wart.
1385
result = self.open_workingtree(recommend_upgrade=False)
1386
except errors.NoSuchFile:
1387
result = self._init_workingtree()
1388
if revision_id is not None:
1389
if revision_id == _mod_revision.NULL_REVISION:
1390
result.set_parent_ids([])
1392
result.set_parent_ids([revision_id])
1395
def _init_workingtree(self):
1396
from bzrlib.workingtree import WorkingTreeFormat2
1398
return WorkingTreeFormat2().initialize(self)
1399
except errors.NotLocalUrl:
1400
# Even though we can't access the working tree, we need to
1401
# create its control files.
1402
return WorkingTreeFormat2()._stub_initialize_on_transport(
1403
self.transport, self._control_files._file_mode)
1405
def destroy_workingtree(self):
1406
"""See BzrDir.destroy_workingtree."""
1407
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1409
def destroy_workingtree_metadata(self):
1410
"""See BzrDir.destroy_workingtree_metadata."""
1411
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1414
def get_branch_transport(self, branch_format):
1415
"""See BzrDir.get_branch_transport()."""
1416
if branch_format is None:
1417
return self.transport
1419
branch_format.get_format_string()
1420
except NotImplementedError:
1421
return self.transport
1422
raise errors.IncompatibleFormat(branch_format, self._format)
1424
def get_repository_transport(self, repository_format):
1425
"""See BzrDir.get_repository_transport()."""
1426
if repository_format is None:
1427
return self.transport
1429
repository_format.get_format_string()
1430
except NotImplementedError:
1431
return self.transport
1432
raise errors.IncompatibleFormat(repository_format, self._format)
1434
def get_workingtree_transport(self, workingtree_format):
1435
"""See BzrDir.get_workingtree_transport()."""
1436
if workingtree_format is None:
1437
return self.transport
1439
workingtree_format.get_format_string()
1440
except NotImplementedError:
1441
return self.transport
1442
raise errors.IncompatibleFormat(workingtree_format, self._format)
1444
def needs_format_conversion(self, format=None):
1445
"""See BzrDir.needs_format_conversion()."""
1446
# if the format is not the same as the system default,
1447
# an upgrade is needed.
1449
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1450
% 'needs_format_conversion(format=None)')
1451
format = BzrDirFormat.get_default_format()
1452
return not isinstance(self._format, format.__class__)
1454
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1455
"""See BzrDir.open_branch."""
1456
from bzrlib.branch import BzrBranchFormat4
1457
format = BzrBranchFormat4()
1458
self._check_supported(format, unsupported)
1459
return format.open(self, _found=True)
1461
def sprout(self, url, revision_id=None, force_new_repo=False,
1462
possible_transports=None, accelerator_tree=None,
1463
hardlink=False, stacked=False, create_tree_if_local=True,
1464
source_branch=None):
1465
"""See BzrDir.sprout()."""
1466
if source_branch is not None:
1467
my_branch = self.open_branch()
1468
if source_branch.base != my_branch.base:
1469
raise AssertionError(
1470
"source branch %r is not within %r with branch %r" %
1471
(source_branch, self, my_branch))
1473
raise errors.UnstackableBranchFormat(
1474
self._format, self.root_transport.base)
1475
if not create_tree_if_local:
1476
raise errors.MustHaveWorkingTree(
1477
self._format, self.root_transport.base)
1478
from bzrlib.workingtree import WorkingTreeFormat2
1479
self._make_tail(url)
1480
result = self._format._initialize_for_clone(url)
1482
self.open_repository().clone(result, revision_id=revision_id)
1483
except errors.NoRepositoryPresent:
1486
self.open_branch().sprout(result, revision_id=revision_id)
1487
except errors.NotBranchError:
1490
# we always want a working tree
1491
WorkingTreeFormat2().initialize(result,
1492
accelerator_tree=accelerator_tree,
1497
class BzrDir4(BzrDirPreSplitOut):
1498
"""A .bzr version 4 control object.
1500
This is a deprecated format and may be removed after sept 2006.
1503
def create_repository(self, shared=False):
1504
"""See BzrDir.create_repository."""
1505
return self._format.repository_format.initialize(self, shared)
1507
def needs_format_conversion(self, format=None):
1508
"""Format 4 dirs are always in need of conversion."""
1510
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1511
% 'needs_format_conversion(format=None)')
1514
def open_repository(self):
1515
"""See BzrDir.open_repository."""
1516
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1517
return RepositoryFormat4().open(self, _found=True)
1520
class BzrDir5(BzrDirPreSplitOut):
1521
"""A .bzr version 5 control object.
1523
This is a deprecated format and may be removed after sept 2006.
1526
def open_repository(self):
1527
"""See BzrDir.open_repository."""
1528
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1529
return RepositoryFormat5().open(self, _found=True)
1531
def open_workingtree(self, _unsupported=False,
1532
recommend_upgrade=True):
1533
"""See BzrDir.create_workingtree."""
1534
from bzrlib.workingtree import WorkingTreeFormat2
1535
wt_format = WorkingTreeFormat2()
1536
# we don't warn here about upgrades; that ought to be handled for the
1538
return wt_format.open(self, _found=True)
1541
class BzrDir6(BzrDirPreSplitOut):
1542
"""A .bzr version 6 control object.
1544
This is a deprecated format and may be removed after sept 2006.
1547
def open_repository(self):
1548
"""See BzrDir.open_repository."""
1549
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1550
return RepositoryFormat6().open(self, _found=True)
1552
def open_workingtree(self, _unsupported=False,
1553
recommend_upgrade=True):
1554
"""See BzrDir.create_workingtree."""
1555
# we don't warn here about upgrades; that ought to be handled for the
1557
from bzrlib.workingtree import WorkingTreeFormat2
1558
return WorkingTreeFormat2().open(self, _found=True)
1561
class BzrDirMeta1(BzrDir):
1562
"""A .bzr meta version 1 control object.
1564
This is the first control object where the
1565
individual aspects are really split out: there are separate repository,
1566
workingtree and branch subdirectories and any subset of the three can be
1567
present within a BzrDir.
1570
def can_convert_format(self):
1571
"""See BzrDir.can_convert_format()."""
1574
def create_branch(self):
1575
"""See BzrDir.create_branch."""
1576
return self._format.get_branch_format().initialize(self)
1578
def destroy_branch(self):
1579
"""See BzrDir.create_branch."""
1580
self.transport.delete_tree('branch')
1582
def create_repository(self, shared=False):
1583
"""See BzrDir.create_repository."""
1584
return self._format.repository_format.initialize(self, shared)
1586
def destroy_repository(self):
1587
"""See BzrDir.destroy_repository."""
1588
self.transport.delete_tree('repository')
1590
def create_workingtree(self, revision_id=None, from_branch=None,
1591
accelerator_tree=None, hardlink=False):
1592
"""See BzrDir.create_workingtree."""
1593
return self._format.workingtree_format.initialize(
1594
self, revision_id, from_branch=from_branch,
1595
accelerator_tree=accelerator_tree, hardlink=hardlink)
1597
def destroy_workingtree(self):
1598
"""See BzrDir.destroy_workingtree."""
1599
wt = self.open_workingtree(recommend_upgrade=False)
1600
repository = wt.branch.repository
1601
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1602
wt.revert(old_tree=empty)
1603
self.destroy_workingtree_metadata()
1605
def destroy_workingtree_metadata(self):
1606
self.transport.delete_tree('checkout')
1608
def find_branch_format(self):
1609
"""Find the branch 'format' for this bzrdir.
1611
This might be a synthetic object for e.g. RemoteBranch and SVN.
1613
from bzrlib.branch import BranchFormat
1614
return BranchFormat.find_format(self)
1616
def _get_mkdir_mode(self):
1617
"""Figure out the mode to use when creating a bzrdir subdir."""
1618
temp_control = lockable_files.LockableFiles(self.transport, '',
1619
lockable_files.TransportLock)
1620
return temp_control._dir_mode
1622
def get_branch_reference(self):
1623
"""See BzrDir.get_branch_reference()."""
1624
from bzrlib.branch import BranchFormat
1625
format = BranchFormat.find_format(self)
1626
return format.get_reference(self)
1628
def get_branch_transport(self, branch_format):
1629
"""See BzrDir.get_branch_transport()."""
1630
if branch_format is None:
1631
return self.transport.clone('branch')
1633
branch_format.get_format_string()
1634
except NotImplementedError:
1635
raise errors.IncompatibleFormat(branch_format, self._format)
1637
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1638
except errors.FileExists:
1640
return self.transport.clone('branch')
1642
def get_repository_transport(self, repository_format):
1643
"""See BzrDir.get_repository_transport()."""
1644
if repository_format is None:
1645
return self.transport.clone('repository')
1647
repository_format.get_format_string()
1648
except NotImplementedError:
1649
raise errors.IncompatibleFormat(repository_format, self._format)
1651
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1652
except errors.FileExists:
1654
return self.transport.clone('repository')
1656
def get_workingtree_transport(self, workingtree_format):
1657
"""See BzrDir.get_workingtree_transport()."""
1658
if workingtree_format is None:
1659
return self.transport.clone('checkout')
1661
workingtree_format.get_format_string()
1662
except NotImplementedError:
1663
raise errors.IncompatibleFormat(workingtree_format, self._format)
1665
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1666
except errors.FileExists:
1668
return self.transport.clone('checkout')
1670
def needs_format_conversion(self, format=None):
1671
"""See BzrDir.needs_format_conversion()."""
1673
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1674
% 'needs_format_conversion(format=None)')
1676
format = BzrDirFormat.get_default_format()
1677
if not isinstance(self._format, format.__class__):
1678
# it is not a meta dir format, conversion is needed.
1680
# we might want to push this down to the repository?
1682
if not isinstance(self.open_repository()._format,
1683
format.repository_format.__class__):
1684
# the repository needs an upgrade.
1686
except errors.NoRepositoryPresent:
1689
if not isinstance(self.open_branch()._format,
1690
format.get_branch_format().__class__):
1691
# the branch needs an upgrade.
1693
except errors.NotBranchError:
1696
my_wt = self.open_workingtree(recommend_upgrade=False)
1697
if not isinstance(my_wt._format,
1698
format.workingtree_format.__class__):
1699
# the workingtree needs an upgrade.
1701
except (errors.NoWorkingTree, errors.NotLocalUrl):
1705
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1706
"""See BzrDir.open_branch."""
1707
format = self.find_branch_format()
1708
self._check_supported(format, unsupported)
1709
return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1711
def open_repository(self, unsupported=False):
1712
"""See BzrDir.open_repository."""
1713
from bzrlib.repository import RepositoryFormat
1714
format = RepositoryFormat.find_format(self)
1715
self._check_supported(format, unsupported)
1716
return format.open(self, _found=True)
1718
def open_workingtree(self, unsupported=False,
1719
recommend_upgrade=True):
1720
"""See BzrDir.open_workingtree."""
1721
from bzrlib.workingtree import WorkingTreeFormat
1722
format = WorkingTreeFormat.find_format(self)
1723
self._check_supported(format, unsupported,
1725
basedir=self.root_transport.base)
1726
return format.open(self, _found=True)
1728
def _get_config(self):
1729
return config.TransportConfig(self.transport, 'control.conf')
1732
class BzrDirFormat(object):
1733
"""An encapsulation of the initialization and open routines for a format.
1735
Formats provide three things:
1736
* An initialization routine,
1740
Formats are placed in a dict by their format string for reference
1741
during bzrdir opening. These should be subclasses of BzrDirFormat
1744
Once a format is deprecated, just deprecate the initialize and open
1745
methods on the format class. Do not deprecate the object, as the
1746
object will be created every system load.
1749
_default_format = None
1750
"""The default format used for new .bzr dirs."""
1753
"""The known formats."""
1755
_control_formats = []
1756
"""The registered control formats - .bzr, ....
1758
This is a list of BzrDirFormat objects.
1761
_control_server_formats = []
1762
"""The registered control server formats, e.g. RemoteBzrDirs.
1764
This is a list of BzrDirFormat objects.
1767
_lock_file_name = 'branch-lock'
1769
# _lock_class must be set in subclasses to the lock type, typ.
1770
# TransportLock or LockDir
1773
def find_format(klass, transport, _server_formats=True):
1774
"""Return the format present at transport."""
1776
formats = klass._control_server_formats + klass._control_formats
1778
formats = klass._control_formats
1779
for format in formats:
1781
return format.probe_transport(transport)
1782
except errors.NotBranchError:
1783
# this format does not find a control dir here.
1785
raise errors.NotBranchError(path=transport.base)
1788
def probe_transport(klass, transport):
1789
"""Return the .bzrdir style format present in a directory."""
1791
format_string = transport.get(".bzr/branch-format").read()
1792
except errors.NoSuchFile:
1793
raise errors.NotBranchError(path=transport.base)
1796
return klass._formats[format_string]
1798
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1801
def get_default_format(klass):
1802
"""Return the current default format."""
1803
return klass._default_format
1805
def get_format_string(self):
1806
"""Return the ASCII format string that identifies this format."""
1807
raise NotImplementedError(self.get_format_string)
1809
def get_format_description(self):
1810
"""Return the short description for this format."""
1811
raise NotImplementedError(self.get_format_description)
1813
def get_converter(self, format=None):
1814
"""Return the converter to use to convert bzrdirs needing converts.
1816
This returns a bzrlib.bzrdir.Converter object.
1818
This should return the best upgrader to step this format towards the
1819
current default format. In the case of plugins we can/should provide
1820
some means for them to extend the range of returnable converters.
1822
:param format: Optional format to override the default format of the
1825
raise NotImplementedError(self.get_converter)
1827
def initialize(self, url, possible_transports=None):
1828
"""Create a bzr control dir at this url and return an opened copy.
1830
While not deprecated, this method is very specific and its use will
1831
lead to many round trips to setup a working environment. See
1832
initialize_on_transport_ex for a [nearly] all-in-one method.
1834
Subclasses should typically override initialize_on_transport
1835
instead of this method.
1837
return self.initialize_on_transport(get_transport(url,
1838
possible_transports))
1840
def initialize_on_transport(self, transport):
1841
"""Initialize a new bzrdir in the base directory of a Transport."""
1843
# can we hand off the request to the smart server rather than using
1845
client_medium = transport.get_smart_medium()
1846
except errors.NoSmartMedium:
1847
return self._initialize_on_transport_vfs(transport)
1849
# Current RPC's only know how to create bzr metadir1 instances, so
1850
# we still delegate to vfs methods if the requested format is not a
1852
if type(self) != BzrDirMetaFormat1:
1853
return self._initialize_on_transport_vfs(transport)
1854
remote_format = RemoteBzrDirFormat()
1855
self._supply_sub_formats_to(remote_format)
1856
return remote_format.initialize_on_transport(transport)
1858
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1859
create_prefix=False, force_new_repo=False, stacked_on=None,
1860
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1861
shared_repo=False, vfs_only=False):
1862
"""Create this format on transport.
1864
The directory to initialize will be created.
1866
:param force_new_repo: Do not use a shared repository for the target,
1867
even if one is available.
1868
:param create_prefix: Create any missing directories leading up to
1870
:param use_existing_dir: Use an existing directory if one exists.
1871
:param stacked_on: A url to stack any created branch on, None to follow
1872
any target stacking policy.
1873
:param stack_on_pwd: If stack_on is relative, the location it is
1875
:param repo_format_name: If non-None, a repository will be
1876
made-or-found. Should none be found, or if force_new_repo is True
1877
the repo_format_name is used to select the format of repository to
1879
:param make_working_trees: Control the setting of make_working_trees
1880
for a new shared repository when one is made. None to use whatever
1881
default the format has.
1882
:param shared_repo: Control whether made repositories are shared or
1884
:param vfs_only: If True do not attempt to use a smart server
1885
:return: repo, bzrdir, require_stacking, repository_policy. repo is
1886
None if none was created or found, bzrdir is always valid.
1887
require_stacking is the result of examining the stacked_on
1888
parameter and any stacking policy found for the target.
1891
# Try to hand off to a smart server
1893
client_medium = transport.get_smart_medium()
1894
except errors.NoSmartMedium:
1897
# TODO: lookup the local format from a server hint.
1898
remote_dir_format = RemoteBzrDirFormat()
1899
remote_dir_format._network_name = self.network_name()
1900
self._supply_sub_formats_to(remote_dir_format)
1901
return remote_dir_format.initialize_on_transport_ex(transport,
1902
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1903
force_new_repo=force_new_repo, stacked_on=stacked_on,
1904
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1905
make_working_trees=make_working_trees, shared_repo=shared_repo)
1906
# XXX: Refactor the create_prefix/no_create_prefix code into a
1907
# common helper function
1908
# The destination may not exist - if so make it according to policy.
1909
def make_directory(transport):
1910
transport.mkdir('.')
1912
def redirected(transport, e, redirection_notice):
1913
note(redirection_notice)
1914
return transport._redirected_to(e.source, e.target)
1916
transport = do_catching_redirections(make_directory, transport,
1918
except errors.FileExists:
1919
if not use_existing_dir:
1921
except errors.NoSuchFile:
1922
if not create_prefix:
1924
transport.create_prefix()
1926
require_stacking = (stacked_on is not None)
1927
# Now the target directory exists, but doesn't have a .bzr
1928
# directory. So we need to create it, along with any work to create
1929
# all of the dependent branches, etc.
1931
result = self.initialize_on_transport(transport)
1932
if repo_format_name:
1934
# use a custom format
1935
result._format.repository_format = \
1936
repository.network_format_registry.get(repo_format_name)
1937
except AttributeError:
1938
# The format didn't permit it to be set.
1940
# A repository is desired, either in-place or shared.
1941
repository_policy = result.determine_repository_policy(
1942
force_new_repo, stacked_on, stack_on_pwd,
1943
require_stacking=require_stacking)
1944
result_repo, is_new_repo = repository_policy.acquire_repository(
1945
make_working_trees, shared_repo)
1946
if not require_stacking and repository_policy._require_stacking:
1947
require_stacking = True
1948
result._format.require_stacking()
1951
repository_policy = None
1952
return result_repo, result, require_stacking, repository_policy
1954
def _initialize_on_transport_vfs(self, transport):
1955
"""Initialize a new bzrdir using VFS calls.
1957
:param transport: The transport to create the .bzr directory in.
1960
# Since we are creating a .bzr directory, inherit the
1961
# mode from the root directory
1962
temp_control = lockable_files.LockableFiles(transport,
1963
'', lockable_files.TransportLock)
1964
temp_control._transport.mkdir('.bzr',
1965
# FIXME: RBC 20060121 don't peek under
1967
mode=temp_control._dir_mode)
1968
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1969
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1970
file_mode = temp_control._file_mode
1972
bzrdir_transport = transport.clone('.bzr')
1973
utf8_files = [('README',
1974
"This is a Bazaar control directory.\n"
1975
"Do not change any files in this directory.\n"
1976
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1977
('branch-format', self.get_format_string()),
1979
# NB: no need to escape relative paths that are url safe.
1980
control_files = lockable_files.LockableFiles(bzrdir_transport,
1981
self._lock_file_name, self._lock_class)
1982
control_files.create_lock()
1983
control_files.lock_write()
1985
for (filename, content) in utf8_files:
1986
bzrdir_transport.put_bytes(filename, content,
1989
control_files.unlock()
1990
return self.open(transport, _found=True)
1992
def is_supported(self):
1993
"""Is this format supported?
1995
Supported formats must be initializable and openable.
1996
Unsupported formats may not support initialization or committing or
1997
some other features depending on the reason for not being supported.
2001
def network_name(self):
2002
"""A simple byte string uniquely identifying this format for RPC calls.
2004
Bzr control formats use thir disk format string to identify the format
2005
over the wire. Its possible that other control formats have more
2006
complex detection requirements, so we permit them to use any unique and
2007
immutable string they desire.
2009
raise NotImplementedError(self.network_name)
2011
def same_model(self, target_format):
2012
return (self.repository_format.rich_root_data ==
2013
target_format.rich_root_data)
2016
def known_formats(klass):
2017
"""Return all the known formats.
2019
Concrete formats should override _known_formats.
2021
# There is double indirection here to make sure that control
2022
# formats used by more than one dir format will only be probed
2023
# once. This can otherwise be quite expensive for remote connections.
2025
for format in klass._control_formats:
2026
result.update(format._known_formats())
2030
def _known_formats(klass):
2031
"""Return the known format instances for this control format."""
2032
return set(klass._formats.values())
2034
def open(self, transport, _found=False):
2035
"""Return an instance of this format for the dir transport points at.
2037
_found is a private parameter, do not use it.
2040
found_format = BzrDirFormat.find_format(transport)
2041
if not isinstance(found_format, self.__class__):
2042
raise AssertionError("%s was asked to open %s, but it seems to need "
2044
% (self, transport, found_format))
2045
# Allow subclasses - use the found format.
2046
self._supply_sub_formats_to(found_format)
2047
return found_format._open(transport)
2048
return self._open(transport)
2050
def _open(self, transport):
2051
"""Template method helper for opening BzrDirectories.
2053
This performs the actual open and any additional logic or parameter
2056
raise NotImplementedError(self._open)
2059
def register_format(klass, format):
2060
klass._formats[format.get_format_string()] = format
2061
# bzr native formats have a network name of their format string.
2062
network_format_registry.register(format.get_format_string(), format.__class__)
2065
def register_control_format(klass, format):
2066
"""Register a format that does not use '.bzr' for its control dir.
2068
TODO: This should be pulled up into a 'ControlDirFormat' base class
2069
which BzrDirFormat can inherit from, and renamed to register_format
2070
there. It has been done without that for now for simplicity of
2073
klass._control_formats.append(format)
2076
def register_control_server_format(klass, format):
2077
"""Register a control format for client-server environments.
2079
These formats will be tried before ones registered with
2080
register_control_format. This gives implementations that decide to the
2081
chance to grab it before anything looks at the contents of the format
2084
klass._control_server_formats.append(format)
2087
def _set_default_format(klass, format):
2088
"""Set default format (for testing behavior of defaults only)"""
2089
klass._default_format = format
2093
return self.get_format_description().rstrip()
2095
def _supply_sub_formats_to(self, other_format):
2096
"""Give other_format the same values for sub formats as this has.
2098
This method is expected to be used when parameterising a
2099
RemoteBzrDirFormat instance with the parameters from a
2100
BzrDirMetaFormat1 instance.
2102
:param other_format: other_format is a format which should be
2103
compatible with whatever sub formats are supported by self.
2108
def unregister_format(klass, format):
2109
del klass._formats[format.get_format_string()]
2112
def unregister_control_format(klass, format):
2113
klass._control_formats.remove(format)
2116
class BzrDirFormat4(BzrDirFormat):
2117
"""Bzr dir format 4.
2119
This format is a combined format for working tree, branch and repository.
2121
- Format 1 working trees [always]
2122
- Format 4 branches [always]
2123
- Format 4 repositories [always]
2125
This format is deprecated: it indexes texts using a text it which is
2126
removed in format 5; write support for this format has been removed.
2129
_lock_class = lockable_files.TransportLock
2131
def get_format_string(self):
2132
"""See BzrDirFormat.get_format_string()."""
2133
return "Bazaar-NG branch, format 0.0.4\n"
2135
def get_format_description(self):
2136
"""See BzrDirFormat.get_format_description()."""
2137
return "All-in-one format 4"
2139
def get_converter(self, format=None):
2140
"""See BzrDirFormat.get_converter()."""
2141
# there is one and only one upgrade path here.
2142
return ConvertBzrDir4To5()
2144
def initialize_on_transport(self, transport):
2145
"""Format 4 branches cannot be created."""
2146
raise errors.UninitializableFormat(self)
2148
def is_supported(self):
2149
"""Format 4 is not supported.
2151
It is not supported because the model changed from 4 to 5 and the
2152
conversion logic is expensive - so doing it on the fly was not
2157
def network_name(self):
2158
return self.get_format_string()
2160
def _open(self, transport):
2161
"""See BzrDirFormat._open."""
2162
return BzrDir4(transport, self)
2164
def __return_repository_format(self):
2165
"""Circular import protection."""
2166
from bzrlib.repofmt.weaverepo import RepositoryFormat4
2167
return RepositoryFormat4()
2168
repository_format = property(__return_repository_format)
2171
class BzrDirFormatAllInOne(BzrDirFormat):
2172
"""Common class for formats before meta-dirs."""
2174
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
2175
create_prefix=False, force_new_repo=False, stacked_on=None,
2176
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
2178
"""See BzrDirFormat.initialize_on_transport_ex."""
2179
require_stacking = (stacked_on is not None)
2180
# Format 5 cannot stack, but we've been asked to - actually init
2182
if require_stacking:
2183
format = BzrDirMetaFormat1()
2184
return format.initialize_on_transport_ex(transport,
2185
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2186
force_new_repo=force_new_repo, stacked_on=stacked_on,
2187
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2188
make_working_trees=make_working_trees, shared_repo=shared_repo)
2189
return BzrDirFormat.initialize_on_transport_ex(self, transport,
2190
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2191
force_new_repo=force_new_repo, stacked_on=stacked_on,
2192
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2193
make_working_trees=make_working_trees, shared_repo=shared_repo)
2196
class BzrDirFormat5(BzrDirFormatAllInOne):
2197
"""Bzr control format 5.
2199
This format is a combined format for working tree, branch and repository.
2201
- Format 2 working trees [always]
2202
- Format 4 branches [always]
2203
- Format 5 repositories [always]
2204
Unhashed stores in the repository.
2207
_lock_class = lockable_files.TransportLock
2209
def get_format_string(self):
2210
"""See BzrDirFormat.get_format_string()."""
2211
return "Bazaar-NG branch, format 5\n"
2213
def get_branch_format(self):
2214
from bzrlib import branch
2215
return branch.BzrBranchFormat4()
2217
def get_format_description(self):
2218
"""See BzrDirFormat.get_format_description()."""
2219
return "All-in-one format 5"
2221
def get_converter(self, format=None):
2222
"""See BzrDirFormat.get_converter()."""
2223
# there is one and only one upgrade path here.
2224
return ConvertBzrDir5To6()
2226
def _initialize_for_clone(self, url):
2227
return self.initialize_on_transport(get_transport(url), _cloning=True)
2229
def initialize_on_transport(self, transport, _cloning=False):
2230
"""Format 5 dirs always have working tree, branch and repository.
2232
Except when they are being cloned.
2234
from bzrlib.branch import BzrBranchFormat4
2235
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2236
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
2237
RepositoryFormat5().initialize(result, _internal=True)
2239
branch = BzrBranchFormat4().initialize(result)
2240
result._init_workingtree()
2243
def network_name(self):
2244
return self.get_format_string()
2246
def _open(self, transport):
2247
"""See BzrDirFormat._open."""
2248
return BzrDir5(transport, self)
2250
def __return_repository_format(self):
2251
"""Circular import protection."""
2252
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2253
return RepositoryFormat5()
2254
repository_format = property(__return_repository_format)
2257
class BzrDirFormat6(BzrDirFormatAllInOne):
2258
"""Bzr control format 6.
2260
This format is a combined format for working tree, branch and repository.
2262
- Format 2 working trees [always]
2263
- Format 4 branches [always]
2264
- Format 6 repositories [always]
2267
_lock_class = lockable_files.TransportLock
2269
def get_format_string(self):
2270
"""See BzrDirFormat.get_format_string()."""
2271
return "Bazaar-NG branch, format 6\n"
2273
def get_format_description(self):
2274
"""See BzrDirFormat.get_format_description()."""
2275
return "All-in-one format 6"
2277
def get_branch_format(self):
2278
from bzrlib import branch
2279
return branch.BzrBranchFormat4()
2281
def get_converter(self, format=None):
2282
"""See BzrDirFormat.get_converter()."""
2283
# there is one and only one upgrade path here.
2284
return ConvertBzrDir6ToMeta()
2286
def _initialize_for_clone(self, url):
2287
return self.initialize_on_transport(get_transport(url), _cloning=True)
2289
def initialize_on_transport(self, transport, _cloning=False):
2290
"""Format 6 dirs always have working tree, branch and repository.
2292
Except when they are being cloned.
2294
from bzrlib.branch import BzrBranchFormat4
2295
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2296
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
2297
RepositoryFormat6().initialize(result, _internal=True)
2299
branch = BzrBranchFormat4().initialize(result)
2300
result._init_workingtree()
2303
def network_name(self):
2304
return self.get_format_string()
2306
def _open(self, transport):
2307
"""See BzrDirFormat._open."""
2308
return BzrDir6(transport, self)
2310
def __return_repository_format(self):
2311
"""Circular import protection."""
2312
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2313
return RepositoryFormat6()
2314
repository_format = property(__return_repository_format)
2317
class BzrDirMetaFormat1(BzrDirFormat):
2318
"""Bzr meta control format 1
2320
This is the first format with split out working tree, branch and repository
2323
- Format 3 working trees [optional]
2324
- Format 5 branches [optional]
2325
- Format 7 repositories [optional]
2328
_lock_class = lockdir.LockDir
2331
self._workingtree_format = None
2332
self._branch_format = None
2333
self._repository_format = None
2335
def __eq__(self, other):
2336
if other.__class__ is not self.__class__:
2338
if other.repository_format != self.repository_format:
2340
if other.workingtree_format != self.workingtree_format:
2344
def __ne__(self, other):
2345
return not self == other
2347
def get_branch_format(self):
2348
if self._branch_format is None:
2349
from bzrlib.branch import BranchFormat
2350
self._branch_format = BranchFormat.get_default_format()
2351
return self._branch_format
2353
def set_branch_format(self, format):
2354
self._branch_format = format
2356
def require_stacking(self):
2357
if not self.get_branch_format().supports_stacking():
2358
# We need to make a stacked branch, but the default format for the
2359
# target doesn't support stacking. So force a branch that *can*
2361
from bzrlib.branch import BzrBranchFormat7
2362
branch_format = BzrBranchFormat7()
2363
self.set_branch_format(branch_format)
2364
mutter("using %r for stacking" % (branch_format,))
2365
from bzrlib.repofmt import pack_repo
2366
if self.repository_format.rich_root_data:
2367
bzrdir_format_name = '1.6.1-rich-root'
2368
repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2370
bzrdir_format_name = '1.6'
2371
repo_format = pack_repo.RepositoryFormatKnitPack5()
2372
note('Source format does not support stacking, using format:'
2374
bzrdir_format_name, repo_format.get_format_description())
2375
self.repository_format = repo_format
2377
def get_converter(self, format=None):
2378
"""See BzrDirFormat.get_converter()."""
2380
format = BzrDirFormat.get_default_format()
2381
if not isinstance(self, format.__class__):
2382
# converting away from metadir is not implemented
2383
raise NotImplementedError(self.get_converter)
2384
return ConvertMetaToMeta(format)
2386
def get_format_string(self):
2387
"""See BzrDirFormat.get_format_string()."""
2388
return "Bazaar-NG meta directory, format 1\n"
2390
def get_format_description(self):
2391
"""See BzrDirFormat.get_format_description()."""
2392
return "Meta directory format 1"
2394
def network_name(self):
2395
return self.get_format_string()
2397
def _open(self, transport):
2398
"""See BzrDirFormat._open."""
2399
# Create a new format instance because otherwise initialisation of new
2400
# metadirs share the global default format object leading to alias
2402
format = BzrDirMetaFormat1()
2403
self._supply_sub_formats_to(format)
2404
return BzrDirMeta1(transport, format)
2406
def __return_repository_format(self):
2407
"""Circular import protection."""
2408
if self._repository_format:
2409
return self._repository_format
2410
from bzrlib.repository import RepositoryFormat
2411
return RepositoryFormat.get_default_format()
2413
def _set_repository_format(self, value):
2414
"""Allow changing the repository format for metadir formats."""
2415
self._repository_format = value
2417
repository_format = property(__return_repository_format,
2418
_set_repository_format)
2420
def _supply_sub_formats_to(self, other_format):
2421
"""Give other_format the same values for sub formats as this has.
2423
This method is expected to be used when parameterising a
2424
RemoteBzrDirFormat instance with the parameters from a
2425
BzrDirMetaFormat1 instance.
2427
:param other_format: other_format is a format which should be
2428
compatible with whatever sub formats are supported by self.
2431
if getattr(self, '_repository_format', None) is not None:
2432
other_format.repository_format = self.repository_format
2433
if self._branch_format is not None:
2434
other_format._branch_format = self._branch_format
2435
if self._workingtree_format is not None:
2436
other_format.workingtree_format = self.workingtree_format
2438
def __get_workingtree_format(self):
2439
if self._workingtree_format is None:
2440
from bzrlib.workingtree import WorkingTreeFormat
2441
self._workingtree_format = WorkingTreeFormat.get_default_format()
2442
return self._workingtree_format
2444
def __set_workingtree_format(self, wt_format):
2445
self._workingtree_format = wt_format
2447
workingtree_format = property(__get_workingtree_format,
2448
__set_workingtree_format)
2451
network_format_registry = registry.FormatRegistry()
2452
"""Registry of formats indexed by their network name.
2454
The network name for a BzrDirFormat is an identifier that can be used when
2455
referring to formats with smart server operations. See
2456
BzrDirFormat.network_name() for more detail.
2460
# Register bzr control format
2461
BzrDirFormat.register_control_format(BzrDirFormat)
2463
# Register bzr formats
2464
BzrDirFormat.register_format(BzrDirFormat4())
2465
BzrDirFormat.register_format(BzrDirFormat5())
2466
BzrDirFormat.register_format(BzrDirFormat6())
2467
__default_format = BzrDirMetaFormat1()
2468
BzrDirFormat.register_format(__default_format)
2469
BzrDirFormat._default_format = __default_format
2472
class Converter(object):
2473
"""Converts a disk format object from one format to another."""
2475
def convert(self, to_convert, pb):
2476
"""Perform the conversion of to_convert, giving feedback via pb.
2478
:param to_convert: The disk object to convert.
2479
:param pb: a progress bar to use for progress information.
2482
def step(self, message):
2483
"""Update the pb by a step."""
2485
self.pb.update(message, self.count, self.total)
2488
class ConvertBzrDir4To5(Converter):
2489
"""Converts format 4 bzr dirs to format 5."""
2492
super(ConvertBzrDir4To5, self).__init__()
2493
self.converted_revs = set()
2494
self.absent_revisions = set()
2498
def convert(self, to_convert, pb):
2499
"""See Converter.convert()."""
2500
self.bzrdir = to_convert
2502
self.pb.note('starting upgrade from format 4 to 5')
2503
if isinstance(self.bzrdir.transport, local.LocalTransport):
2504
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2505
self._convert_to_weaves()
2506
return BzrDir.open(self.bzrdir.root_transport.base)
2508
def _convert_to_weaves(self):
2509
self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2512
stat = self.bzrdir.transport.stat('weaves')
2513
if not S_ISDIR(stat.st_mode):
2514
self.bzrdir.transport.delete('weaves')
2515
self.bzrdir.transport.mkdir('weaves')
2516
except errors.NoSuchFile:
2517
self.bzrdir.transport.mkdir('weaves')
2518
# deliberately not a WeaveFile as we want to build it up slowly.
2519
self.inv_weave = Weave('inventory')
2520
# holds in-memory weaves for all files
2521
self.text_weaves = {}
2522
self.bzrdir.transport.delete('branch-format')
2523
self.branch = self.bzrdir.open_branch()
2524
self._convert_working_inv()
2525
rev_history = self.branch.revision_history()
2526
# to_read is a stack holding the revisions we still need to process;
2527
# appending to it adds new highest-priority revisions
2528
self.known_revisions = set(rev_history)
2529
self.to_read = rev_history[-1:]
2531
rev_id = self.to_read.pop()
2532
if (rev_id not in self.revisions
2533
and rev_id not in self.absent_revisions):
2534
self._load_one_rev(rev_id)
2536
to_import = self._make_order()
2537
for i, rev_id in enumerate(to_import):
2538
self.pb.update('converting revision', i, len(to_import))
2539
self._convert_one_rev(rev_id)
2541
self._write_all_weaves()
2542
self._write_all_revs()
2543
self.pb.note('upgraded to weaves:')
2544
self.pb.note(' %6d revisions and inventories', len(self.revisions))
2545
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
2546
self.pb.note(' %6d texts', self.text_count)
2547
self._cleanup_spare_files_after_format4()
2548
self.branch._transport.put_bytes(
2550
BzrDirFormat5().get_format_string(),
2551
mode=self.bzrdir._get_file_mode())
2553
def _cleanup_spare_files_after_format4(self):
2554
# FIXME working tree upgrade foo.
2555
for n in 'merged-patches', 'pending-merged-patches':
2557
## assert os.path.getsize(p) == 0
2558
self.bzrdir.transport.delete(n)
2559
except errors.NoSuchFile:
2561
self.bzrdir.transport.delete_tree('inventory-store')
2562
self.bzrdir.transport.delete_tree('text-store')
2564
def _convert_working_inv(self):
2565
inv = xml4.serializer_v4.read_inventory(
2566
self.branch._transport.get('inventory'))
2567
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2568
self.branch._transport.put_bytes('inventory', new_inv_xml,
2569
mode=self.bzrdir._get_file_mode())
2571
def _write_all_weaves(self):
2572
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2573
weave_transport = self.bzrdir.transport.clone('weaves')
2574
weaves = WeaveStore(weave_transport, prefixed=False)
2575
transaction = WriteTransaction()
2579
for file_id, file_weave in self.text_weaves.items():
2580
self.pb.update('writing weave', i, len(self.text_weaves))
2581
weaves._put_weave(file_id, file_weave, transaction)
2583
self.pb.update('inventory', 0, 1)
2584
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2585
self.pb.update('inventory', 1, 1)
2589
def _write_all_revs(self):
2590
"""Write all revisions out in new form."""
2591
self.bzrdir.transport.delete_tree('revision-store')
2592
self.bzrdir.transport.mkdir('revision-store')
2593
revision_transport = self.bzrdir.transport.clone('revision-store')
2595
from bzrlib.xml5 import serializer_v5
2596
from bzrlib.repofmt.weaverepo import RevisionTextStore
2597
revision_store = RevisionTextStore(revision_transport,
2598
serializer_v5, False, versionedfile.PrefixMapper(),
2599
lambda:True, lambda:True)
2601
for i, rev_id in enumerate(self.converted_revs):
2602
self.pb.update('write revision', i, len(self.converted_revs))
2603
text = serializer_v5.write_revision_to_string(
2604
self.revisions[rev_id])
2606
revision_store.add_lines(key, None, osutils.split_lines(text))
2610
def _load_one_rev(self, rev_id):
2611
"""Load a revision object into memory.
2613
Any parents not either loaded or abandoned get queued to be
2615
self.pb.update('loading revision',
2616
len(self.revisions),
2617
len(self.known_revisions))
2618
if not self.branch.repository.has_revision(rev_id):
2620
self.pb.note('revision {%s} not present in branch; '
2621
'will be converted as a ghost',
2623
self.absent_revisions.add(rev_id)
2625
rev = self.branch.repository.get_revision(rev_id)
2626
for parent_id in rev.parent_ids:
2627
self.known_revisions.add(parent_id)
2628
self.to_read.append(parent_id)
2629
self.revisions[rev_id] = rev
2631
def _load_old_inventory(self, rev_id):
2632
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2633
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2634
inv.revision_id = rev_id
2635
rev = self.revisions[rev_id]
2638
def _load_updated_inventory(self, rev_id):
2639
inv_xml = self.inv_weave.get_text(rev_id)
2640
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2643
def _convert_one_rev(self, rev_id):
2644
"""Convert revision and all referenced objects to new format."""
2645
rev = self.revisions[rev_id]
2646
inv = self._load_old_inventory(rev_id)
2647
present_parents = [p for p in rev.parent_ids
2648
if p not in self.absent_revisions]
2649
self._convert_revision_contents(rev, inv, present_parents)
2650
self._store_new_inv(rev, inv, present_parents)
2651
self.converted_revs.add(rev_id)
2653
def _store_new_inv(self, rev, inv, present_parents):
2654
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2655
new_inv_sha1 = sha_string(new_inv_xml)
2656
self.inv_weave.add_lines(rev.revision_id,
2658
new_inv_xml.splitlines(True))
2659
rev.inventory_sha1 = new_inv_sha1
2661
def _convert_revision_contents(self, rev, inv, present_parents):
2662
"""Convert all the files within a revision.
2664
Also upgrade the inventory to refer to the text revision ids."""
2665
rev_id = rev.revision_id
2666
mutter('converting texts of revision {%s}',
2668
parent_invs = map(self._load_updated_inventory, present_parents)
2669
entries = inv.iter_entries()
2671
for path, ie in entries:
2672
self._convert_file_version(rev, ie, parent_invs)
2674
def _convert_file_version(self, rev, ie, parent_invs):
2675
"""Convert one version of one file.
2677
The file needs to be added into the weave if it is a merge
2678
of >=2 parents or if it's changed from its parent.
2680
file_id = ie.file_id
2681
rev_id = rev.revision_id
2682
w = self.text_weaves.get(file_id)
2685
self.text_weaves[file_id] = w
2686
text_changed = False
2687
parent_candiate_entries = ie.parent_candidates(parent_invs)
2688
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2689
# XXX: Note that this is unordered - and this is tolerable because
2690
# the previous code was also unordered.
2691
previous_entries = dict((head, parent_candiate_entries[head]) for head
2693
self.snapshot_ie(previous_entries, ie, w, rev_id)
2696
def get_parent_map(self, revision_ids):
2697
"""See graph._StackedParentsProvider.get_parent_map"""
2698
return dict((revision_id, self.revisions[revision_id])
2699
for revision_id in revision_ids
2700
if revision_id in self.revisions)
2702
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2703
# TODO: convert this logic, which is ~= snapshot to
2704
# a call to:. This needs the path figured out. rather than a work_tree
2705
# a v4 revision_tree can be given, or something that looks enough like
2706
# one to give the file content to the entry if it needs it.
2707
# and we need something that looks like a weave store for snapshot to
2709
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2710
if len(previous_revisions) == 1:
2711
previous_ie = previous_revisions.values()[0]
2712
if ie._unchanged(previous_ie):
2713
ie.revision = previous_ie.revision
2716
text = self.branch.repository._text_store.get(ie.text_id)
2717
file_lines = text.readlines()
2718
w.add_lines(rev_id, previous_revisions, file_lines)
2719
self.text_count += 1
2721
w.add_lines(rev_id, previous_revisions, [])
2722
ie.revision = rev_id
2724
def _make_order(self):
2725
"""Return a suitable order for importing revisions.
2727
The order must be such that an revision is imported after all
2728
its (present) parents.
2730
todo = set(self.revisions.keys())
2731
done = self.absent_revisions.copy()
2734
# scan through looking for a revision whose parents
2736
for rev_id in sorted(list(todo)):
2737
rev = self.revisions[rev_id]
2738
parent_ids = set(rev.parent_ids)
2739
if parent_ids.issubset(done):
2740
# can take this one now
2741
order.append(rev_id)
2747
class ConvertBzrDir5To6(Converter):
2748
"""Converts format 5 bzr dirs to format 6."""
2750
def convert(self, to_convert, pb):
2751
"""See Converter.convert()."""
2752
self.bzrdir = to_convert
2754
self.pb.note('starting upgrade from format 5 to 6')
2755
self._convert_to_prefixed()
2756
return BzrDir.open(self.bzrdir.root_transport.base)
2758
def _convert_to_prefixed(self):
2759
from bzrlib.store import TransportStore
2760
self.bzrdir.transport.delete('branch-format')
2761
for store_name in ["weaves", "revision-store"]:
2762
self.pb.note("adding prefixes to %s" % store_name)
2763
store_transport = self.bzrdir.transport.clone(store_name)
2764
store = TransportStore(store_transport, prefixed=True)
2765
for urlfilename in store_transport.list_dir('.'):
2766
filename = urlutils.unescape(urlfilename)
2767
if (filename.endswith(".weave") or
2768
filename.endswith(".gz") or
2769
filename.endswith(".sig")):
2770
file_id, suffix = os.path.splitext(filename)
2774
new_name = store._mapper.map((file_id,)) + suffix
2775
# FIXME keep track of the dirs made RBC 20060121
2777
store_transport.move(filename, new_name)
2778
except errors.NoSuchFile: # catches missing dirs strangely enough
2779
store_transport.mkdir(osutils.dirname(new_name))
2780
store_transport.move(filename, new_name)
2781
self.bzrdir.transport.put_bytes(
2783
BzrDirFormat6().get_format_string(),
2784
mode=self.bzrdir._get_file_mode())
2787
class ConvertBzrDir6ToMeta(Converter):
2788
"""Converts format 6 bzr dirs to metadirs."""
2790
def convert(self, to_convert, pb):
2791
"""See Converter.convert()."""
2792
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2793
from bzrlib.branch import BzrBranchFormat5
2794
self.bzrdir = to_convert
2797
self.total = 20 # the steps we know about
2798
self.garbage_inventories = []
2799
self.dir_mode = self.bzrdir._get_dir_mode()
2800
self.file_mode = self.bzrdir._get_file_mode()
2802
self.pb.note('starting upgrade from format 6 to metadir')
2803
self.bzrdir.transport.put_bytes(
2805
"Converting to format 6",
2806
mode=self.file_mode)
2807
# its faster to move specific files around than to open and use the apis...
2808
# first off, nuke ancestry.weave, it was never used.
2810
self.step('Removing ancestry.weave')
2811
self.bzrdir.transport.delete('ancestry.weave')
2812
except errors.NoSuchFile:
2814
# find out whats there
2815
self.step('Finding branch files')
2816
last_revision = self.bzrdir.open_branch().last_revision()
2817
bzrcontents = self.bzrdir.transport.list_dir('.')
2818
for name in bzrcontents:
2819
if name.startswith('basis-inventory.'):
2820
self.garbage_inventories.append(name)
2821
# create new directories for repository, working tree and branch
2822
repository_names = [('inventory.weave', True),
2823
('revision-store', True),
2825
self.step('Upgrading repository ')
2826
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2827
self.make_lock('repository')
2828
# we hard code the formats here because we are converting into
2829
# the meta format. The meta format upgrader can take this to a
2830
# future format within each component.
2831
self.put_format('repository', RepositoryFormat7())
2832
for entry in repository_names:
2833
self.move_entry('repository', entry)
2835
self.step('Upgrading branch ')
2836
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2837
self.make_lock('branch')
2838
self.put_format('branch', BzrBranchFormat5())
2839
branch_files = [('revision-history', True),
2840
('branch-name', True),
2842
for entry in branch_files:
2843
self.move_entry('branch', entry)
2845
checkout_files = [('pending-merges', True),
2846
('inventory', True),
2847
('stat-cache', False)]
2848
# If a mandatory checkout file is not present, the branch does not have
2849
# a functional checkout. Do not create a checkout in the converted
2851
for name, mandatory in checkout_files:
2852
if mandatory and name not in bzrcontents:
2853
has_checkout = False
2857
if not has_checkout:
2858
self.pb.note('No working tree.')
2859
# If some checkout files are there, we may as well get rid of them.
2860
for name, mandatory in checkout_files:
2861
if name in bzrcontents:
2862
self.bzrdir.transport.delete(name)
2864
from bzrlib.workingtree import WorkingTreeFormat3
2865
self.step('Upgrading working tree')
2866
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2867
self.make_lock('checkout')
2869
'checkout', WorkingTreeFormat3())
2870
self.bzrdir.transport.delete_multi(
2871
self.garbage_inventories, self.pb)
2872
for entry in checkout_files:
2873
self.move_entry('checkout', entry)
2874
if last_revision is not None:
2875
self.bzrdir.transport.put_bytes(
2876
'checkout/last-revision', last_revision)
2877
self.bzrdir.transport.put_bytes(
2879
BzrDirMetaFormat1().get_format_string(),
2880
mode=self.file_mode)
2881
return BzrDir.open(self.bzrdir.root_transport.base)
2883
def make_lock(self, name):
2884
"""Make a lock for the new control dir name."""
2885
self.step('Make %s lock' % name)
2886
ld = lockdir.LockDir(self.bzrdir.transport,
2888
file_modebits=self.file_mode,
2889
dir_modebits=self.dir_mode)
2892
def move_entry(self, new_dir, entry):
2893
"""Move then entry name into new_dir."""
2895
mandatory = entry[1]
2896
self.step('Moving %s' % name)
2898
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2899
except errors.NoSuchFile:
2903
def put_format(self, dirname, format):
2904
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2905
format.get_format_string(),
2909
class ConvertMetaToMeta(Converter):
2910
"""Converts the components of metadirs."""
2912
def __init__(self, target_format):
2913
"""Create a metadir to metadir converter.
2915
:param target_format: The final metadir format that is desired.
2917
self.target_format = target_format
2919
def convert(self, to_convert, pb):
2920
"""See Converter.convert()."""
2921
self.bzrdir = to_convert
2925
self.step('checking repository format')
2927
repo = self.bzrdir.open_repository()
2928
except errors.NoRepositoryPresent:
2931
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2932
from bzrlib.repository import CopyConverter
2933
self.pb.note('starting repository conversion')
2934
converter = CopyConverter(self.target_format.repository_format)
2935
converter.convert(repo, pb)
2937
branch = self.bzrdir.open_branch()
2938
except errors.NotBranchError:
2941
# TODO: conversions of Branch and Tree should be done by
2942
# InterXFormat lookups/some sort of registry.
2943
# Avoid circular imports
2944
from bzrlib import branch as _mod_branch
2945
old = branch._format.__class__
2946
new = self.target_format.get_branch_format().__class__
2948
if (old == _mod_branch.BzrBranchFormat5 and
2949
new in (_mod_branch.BzrBranchFormat6,
2950
_mod_branch.BzrBranchFormat7,
2951
_mod_branch.BzrBranchFormat8)):
2952
branch_converter = _mod_branch.Converter5to6()
2953
elif (old == _mod_branch.BzrBranchFormat6 and
2954
new in (_mod_branch.BzrBranchFormat7,
2955
_mod_branch.BzrBranchFormat8)):
2956
branch_converter = _mod_branch.Converter6to7()
2957
elif (old == _mod_branch.BzrBranchFormat7 and
2958
new is _mod_branch.BzrBranchFormat8):
2959
branch_converter = _mod_branch.Converter7to8()
2961
raise errors.BadConversionTarget("No converter", new)
2962
branch_converter.convert(branch)
2963
branch = self.bzrdir.open_branch()
2964
old = branch._format.__class__
2966
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2967
except (errors.NoWorkingTree, errors.NotLocalUrl):
2970
# TODO: conversions of Branch and Tree should be done by
2971
# InterXFormat lookups
2972
if (isinstance(tree, workingtree.WorkingTree3) and
2973
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2974
isinstance(self.target_format.workingtree_format,
2975
workingtree_4.DirStateWorkingTreeFormat)):
2976
workingtree_4.Converter3to4().convert(tree)
2977
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2978
not isinstance(tree, workingtree_4.WorkingTree5) and
2979
isinstance(self.target_format.workingtree_format,
2980
workingtree_4.WorkingTreeFormat5)):
2981
workingtree_4.Converter4to5().convert(tree)
2982
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2983
not isinstance(tree, workingtree_4.WorkingTree6) and
2984
isinstance(self.target_format.workingtree_format,
2985
workingtree_4.WorkingTreeFormat6)):
2986
workingtree_4.Converter4or5to6().convert(tree)
2990
# This is not in remote.py because it's relatively small, and needs to be
2991
# registered. Putting it in remote.py creates a circular import problem.
2992
# we can make it a lazy object if the control formats is turned into something
2994
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2995
"""Format representing bzrdirs accessed via a smart server"""
2998
BzrDirMetaFormat1.__init__(self)
2999
self._network_name = None
3001
def get_format_description(self):
3002
return 'bzr remote bzrdir'
3004
def get_format_string(self):
3005
raise NotImplementedError(self.get_format_string)
3007
def network_name(self):
3008
if self._network_name:
3009
return self._network_name
3011
raise AssertionError("No network name set.")
3014
def probe_transport(klass, transport):
3015
"""Return a RemoteBzrDirFormat object if it looks possible."""
3017
medium = transport.get_smart_medium()
3018
except (NotImplementedError, AttributeError,
3019
errors.TransportNotPossible, errors.NoSmartMedium,
3020
errors.SmartProtocolError):
3021
# no smart server, so not a branch for this format type.
3022
raise errors.NotBranchError(path=transport.base)
3024
# Decline to open it if the server doesn't support our required
3025
# version (3) so that the VFS-based transport will do it.
3026
if medium.should_probe():
3028
server_version = medium.protocol_version()
3029
except errors.SmartProtocolError:
3030
# Apparently there's no usable smart server there, even though
3031
# the medium supports the smart protocol.
3032
raise errors.NotBranchError(path=transport.base)
3033
if server_version != '2':
3034
raise errors.NotBranchError(path=transport.base)
3037
def initialize_on_transport(self, transport):
3039
# hand off the request to the smart server
3040
client_medium = transport.get_smart_medium()
3041
except errors.NoSmartMedium:
3042
# TODO: lookup the local format from a server hint.
3043
local_dir_format = BzrDirMetaFormat1()
3044
return local_dir_format.initialize_on_transport(transport)
3045
client = _SmartClient(client_medium)
3046
path = client.remote_path_from_transport(transport)
3047
response = client.call('BzrDirFormat.initialize', path)
3048
if response[0] != 'ok':
3049
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
3050
format = RemoteBzrDirFormat()
3051
self._supply_sub_formats_to(format)
3052
return remote.RemoteBzrDir(transport, format)
3054
def parse_NoneTrueFalse(self, arg):
3061
raise AssertionError("invalid arg %r" % arg)
3063
def _serialize_NoneTrueFalse(self, arg):
3070
def _serialize_NoneString(self, arg):
3073
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
3074
create_prefix=False, force_new_repo=False, stacked_on=None,
3075
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
3078
# hand off the request to the smart server
3079
client_medium = transport.get_smart_medium()
3080
except errors.NoSmartMedium:
3083
# Decline to open it if the server doesn't support our required
3084
# version (3) so that the VFS-based transport will do it.
3085
if client_medium.should_probe():
3087
server_version = client_medium.protocol_version()
3088
if server_version != '2':
3092
except errors.SmartProtocolError:
3093
# Apparently there's no usable smart server there, even though
3094
# the medium supports the smart protocol.
3099
client = _SmartClient(client_medium)
3100
path = client.remote_path_from_transport(transport)
3101
if client_medium._is_remote_before((1, 15)):
3104
# TODO: lookup the local format from a server hint.
3105
local_dir_format = BzrDirMetaFormat1()
3106
self._supply_sub_formats_to(local_dir_format)
3107
return local_dir_format.initialize_on_transport_ex(transport,
3108
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3109
force_new_repo=force_new_repo, stacked_on=stacked_on,
3110
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3111
make_working_trees=make_working_trees, shared_repo=shared_repo,
3114
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
3115
args.append(self._serialize_NoneTrueFalse(create_prefix))
3116
args.append(self._serialize_NoneTrueFalse(force_new_repo))
3117
args.append(self._serialize_NoneString(stacked_on))
3118
# stack_on_pwd is often/usually our transport
3121
stack_on_pwd = transport.relpath(stack_on_pwd)
3122
if not stack_on_pwd:
3124
except errors.PathNotChild:
3126
args.append(self._serialize_NoneString(stack_on_pwd))
3127
args.append(self._serialize_NoneString(repo_format_name))
3128
args.append(self._serialize_NoneTrueFalse(make_working_trees))
3129
args.append(self._serialize_NoneTrueFalse(shared_repo))
3130
if self._network_name is None:
3131
self._network_name = \
3132
BzrDirFormat.get_default_format().network_name()
3134
response = client.call('BzrDirFormat.initialize_ex',
3135
self.network_name(), path, *args)
3136
except errors.UnknownSmartMethod:
3137
local_dir_format = BzrDirMetaFormat1()
3138
self._supply_sub_formats_to(local_dir_format)
3139
return local_dir_format.initialize_on_transport_ex(transport,
3140
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3141
force_new_repo=force_new_repo, stacked_on=stacked_on,
3142
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3143
make_working_trees=make_working_trees, shared_repo=shared_repo,
3145
repo_path = response[0]
3146
bzrdir_name = response[6]
3147
require_stacking = response[7]
3148
require_stacking = self.parse_NoneTrueFalse(require_stacking)
3149
format = RemoteBzrDirFormat()
3150
format._network_name = bzrdir_name
3151
self._supply_sub_formats_to(format)
3152
bzrdir = remote.RemoteBzrDir(transport, format)
3154
repo_format = remote.response_tuple_to_repo_format(response[1:])
3155
if repo_path == '.':
3158
repo_bzrdir_format = RemoteBzrDirFormat()
3159
repo_bzrdir_format._network_name = response[5]
3160
repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
3164
final_stack = response[8] or None
3165
final_stack_pwd = response[9] or None
3166
remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
3167
policy = UseExistingRepository(remote_repo, final_stack,
3168
final_stack_pwd, require_stacking)
3169
policy.acquire_repository()
3173
return remote_repo, bzrdir, require_stacking, policy
3175
def _open(self, transport):
3176
return remote.RemoteBzrDir(transport, self)
3178
def __eq__(self, other):
3179
if not isinstance(other, RemoteBzrDirFormat):
3181
return self.get_format_description() == other.get_format_description()
3183
def __return_repository_format(self):
3184
# Always return a RemoteRepositoryFormat object, but if a specific bzr
3185
# repository format has been asked for, tell the RemoteRepositoryFormat
3186
# that it should use that for init() etc.
3187
result = remote.RemoteRepositoryFormat()
3188
custom_format = getattr(self, '_repository_format', None)
3190
if isinstance(custom_format, remote.RemoteRepositoryFormat):
3191
return custom_format
3193
# We will use the custom format to create repositories over the
3194
# wire; expose its details like rich_root_data for code to
3196
result._custom_format = custom_format
3199
def get_branch_format(self):
3200
result = BzrDirMetaFormat1.get_branch_format(self)
3201
if not isinstance(result, remote.RemoteBranchFormat):
3202
new_result = remote.RemoteBranchFormat()
3203
new_result._custom_format = result
3205
self.set_branch_format(new_result)
3209
repository_format = property(__return_repository_format,
3210
BzrDirMetaFormat1._set_repository_format) #.im_func)
3213
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
3216
class BzrDirFormatInfo(object):
3218
def __init__(self, native, deprecated, hidden, experimental):
3219
self.deprecated = deprecated
3220
self.native = native
3221
self.hidden = hidden
3222
self.experimental = experimental
3225
class BzrDirFormatRegistry(registry.Registry):
3226
"""Registry of user-selectable BzrDir subformats.
3228
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
3229
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
3233
"""Create a BzrDirFormatRegistry."""
3234
self._aliases = set()
3235
self._registration_order = list()
3236
super(BzrDirFormatRegistry, self).__init__()
3239
"""Return a set of the format names which are aliases."""
3240
return frozenset(self._aliases)
3242
def register_metadir(self, key,
3243
repository_format, help, native=True, deprecated=False,
3249
"""Register a metadir subformat.
3251
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3252
by the Repository/Branch/WorkingTreeformats.
3254
:param repository_format: The fully-qualified repository format class
3256
:param branch_format: Fully-qualified branch format class name as
3258
:param tree_format: Fully-qualified tree format class name as
3261
# This should be expanded to support setting WorkingTree and Branch
3262
# formats, once BzrDirMetaFormat1 supports that.
3263
def _load(full_name):
3264
mod_name, factory_name = full_name.rsplit('.', 1)
3266
mod = __import__(mod_name, globals(), locals(),
3268
except ImportError, e:
3269
raise ImportError('failed to load %s: %s' % (full_name, e))
3271
factory = getattr(mod, factory_name)
3272
except AttributeError:
3273
raise AttributeError('no factory %s in module %r'
3278
bd = BzrDirMetaFormat1()
3279
if branch_format is not None:
3280
bd.set_branch_format(_load(branch_format))
3281
if tree_format is not None:
3282
bd.workingtree_format = _load(tree_format)
3283
if repository_format is not None:
3284
bd.repository_format = _load(repository_format)
3286
self.register(key, helper, help, native, deprecated, hidden,
3287
experimental, alias)
3289
def register(self, key, factory, help, native=True, deprecated=False,
3290
hidden=False, experimental=False, alias=False):
3291
"""Register a BzrDirFormat factory.
3293
The factory must be a callable that takes one parameter: the key.
3294
It must produce an instance of the BzrDirFormat when called.
3296
This function mainly exists to prevent the info object from being
3299
registry.Registry.register(self, key, factory, help,
3300
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3302
self._aliases.add(key)
3303
self._registration_order.append(key)
3305
def register_lazy(self, key, module_name, member_name, help, native=True,
3306
deprecated=False, hidden=False, experimental=False, alias=False):
3307
registry.Registry.register_lazy(self, key, module_name, member_name,
3308
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3310
self._aliases.add(key)
3311
self._registration_order.append(key)
3313
def set_default(self, key):
3314
"""Set the 'default' key to be a clone of the supplied key.
3316
This method must be called once and only once.
3318
registry.Registry.register(self, 'default', self.get(key),
3319
self.get_help(key), info=self.get_info(key))
3320
self._aliases.add('default')
3322
def set_default_repository(self, key):
3323
"""Set the FormatRegistry default and Repository default.
3325
This is a transitional method while Repository.set_default_format
3328
if 'default' in self:
3329
self.remove('default')
3330
self.set_default(key)
3331
format = self.get('default')()
3333
def make_bzrdir(self, key):
3334
return self.get(key)()
3336
def help_topic(self, topic):
3338
default_realkey = None
3339
default_help = self.get_help('default')
3341
for key in self._registration_order:
3342
if key == 'default':
3344
help = self.get_help(key)
3345
if help == default_help:
3346
default_realkey = key
3348
help_pairs.append((key, help))
3350
def wrapped(key, help, info):
3352
help = '(native) ' + help
3353
return ':%s:\n%s\n\n' % (key,
3354
textwrap.fill(help, initial_indent=' ',
3355
subsequent_indent=' '))
3356
if default_realkey is not None:
3357
output += wrapped(default_realkey, '(default) %s' % default_help,
3358
self.get_info('default'))
3359
deprecated_pairs = []
3360
experimental_pairs = []
3361
for key, help in help_pairs:
3362
info = self.get_info(key)
3365
elif info.deprecated:
3366
deprecated_pairs.append((key, help))
3367
elif info.experimental:
3368
experimental_pairs.append((key, help))
3370
output += wrapped(key, help, info)
3371
output += "\nSee ``bzr help formats`` for more about storage formats."
3373
if len(experimental_pairs) > 0:
3374
other_output += "Experimental formats are shown below.\n\n"
3375
for key, help in experimental_pairs:
3376
info = self.get_info(key)
3377
other_output += wrapped(key, help, info)
3380
"No experimental formats are available.\n\n"
3381
if len(deprecated_pairs) > 0:
3382
other_output += "\nDeprecated formats are shown below.\n\n"
3383
for key, help in deprecated_pairs:
3384
info = self.get_info(key)
3385
other_output += wrapped(key, help, info)
3388
"\nNo deprecated formats are available.\n\n"
3390
"\nSee ``bzr help formats`` for more about storage formats."
3392
if topic == 'other-formats':
3398
class RepositoryAcquisitionPolicy(object):
3399
"""Abstract base class for repository acquisition policies.
3401
A repository acquisition policy decides how a BzrDir acquires a repository
3402
for a branch that is being created. The most basic policy decision is
3403
whether to create a new repository or use an existing one.
3405
def __init__(self, stack_on, stack_on_pwd, require_stacking):
3408
:param stack_on: A location to stack on
3409
:param stack_on_pwd: If stack_on is relative, the location it is
3411
:param require_stacking: If True, it is a failure to not stack.
3413
self._stack_on = stack_on
3414
self._stack_on_pwd = stack_on_pwd
3415
self._require_stacking = require_stacking
3417
def configure_branch(self, branch):
3418
"""Apply any configuration data from this policy to the branch.
3420
Default implementation sets repository stacking.
3422
if self._stack_on is None:
3424
if self._stack_on_pwd is None:
3425
stack_on = self._stack_on
3428
stack_on = urlutils.rebase_url(self._stack_on,
3430
branch.bzrdir.root_transport.base)
3431
except errors.InvalidRebaseURLs:
3432
stack_on = self._get_full_stack_on()
3434
branch.set_stacked_on_url(stack_on)
3435
except (errors.UnstackableBranchFormat,
3436
errors.UnstackableRepositoryFormat):
3437
if self._require_stacking:
3440
def _get_full_stack_on(self):
3441
"""Get a fully-qualified URL for the stack_on location."""
3442
if self._stack_on is None:
3444
if self._stack_on_pwd is None:
3445
return self._stack_on
3447
return urlutils.join(self._stack_on_pwd, self._stack_on)
3449
def _add_fallback(self, repository, possible_transports=None):
3450
"""Add a fallback to the supplied repository, if stacking is set."""
3451
stack_on = self._get_full_stack_on()
3452
if stack_on is None:
3455
stacked_dir = BzrDir.open(stack_on,
3456
possible_transports=possible_transports)
3457
except errors.JailBreak:
3458
# We keep the stacking details, but we are in the server code so
3459
# actually stacking is not needed.
3462
stacked_repo = stacked_dir.open_branch().repository
3463
except errors.NotBranchError:
3464
stacked_repo = stacked_dir.open_repository()
3466
repository.add_fallback_repository(stacked_repo)
3467
except errors.UnstackableRepositoryFormat:
3468
if self._require_stacking:
3471
self._require_stacking = True
3473
def acquire_repository(self, make_working_trees=None, shared=False):
3474
"""Acquire a repository for this bzrdir.
3476
Implementations may create a new repository or use a pre-exising
3478
:param make_working_trees: If creating a repository, set
3479
make_working_trees to this value (if non-None)
3480
:param shared: If creating a repository, make it shared if True
3481
:return: A repository, is_new_flag (True if the repository was
3484
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3487
class CreateRepository(RepositoryAcquisitionPolicy):
3488
"""A policy of creating a new repository"""
3490
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3491
require_stacking=False):
3494
:param bzrdir: The bzrdir to create the repository on.
3495
:param stack_on: A location to stack on
3496
:param stack_on_pwd: If stack_on is relative, the location it is
3499
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3501
self._bzrdir = bzrdir
3503
def acquire_repository(self, make_working_trees=None, shared=False):
3504
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3506
Creates the desired repository in the bzrdir we already have.
3508
stack_on = self._get_full_stack_on()
3510
# Stacking is desired. requested by the target, but does the place it
3511
# points at support stacking? If it doesn't then we should
3512
# not implicitly upgrade. We check this here.
3513
format = self._bzrdir._format
3514
if not (format.repository_format.supports_external_lookups
3515
and format.get_branch_format().supports_stacking()):
3516
# May need to upgrade - but only do if the target also
3517
# supports stacking. Note that this currently wastes
3518
# network round trips to check - but we only do this
3519
# when the source can't stack so it will fade away
3520
# as people do upgrade.
3521
branch_format = None
3524
target_dir = BzrDir.open(stack_on,
3525
possible_transports=[self._bzrdir.root_transport])
3526
except errors.NotBranchError:
3527
# Nothing there, don't change formats
3529
except errors.JailBreak:
3530
# stack_on is inaccessible, JFDI.
3531
if format.repository_format.rich_root_data:
3532
repo_format = pack_repo.RepositoryFormatKnitPack6RichRoot()
3534
repo_format = pack_repo.RepositoryFormatKnitPack6()
3535
branch_format = branch.BzrBranchFormat7()
3538
target_branch = target_dir.open_branch()
3539
except errors.NotBranchError:
3540
# No branch, don't change formats
3543
branch_format = target_branch._format
3544
repo_format = target_branch.repository._format
3545
if not (branch_format.supports_stacking()
3546
and repo_format.supports_external_lookups):
3547
# Doesn't stack itself, don't force an upgrade
3548
branch_format = None
3550
if branch_format and repo_format:
3551
# Does support stacking, use its format.
3552
format.repository_format = repo_format
3553
format.set_branch_format(branch_format)
3554
note('Source format does not support stacking, '
3555
'using format: \'%s\'\n %s\n',
3556
branch_format.get_format_description(),
3557
repo_format.get_format_description())
3558
if not self._require_stacking:
3559
# We have picked up automatic stacking somewhere.
3560
note('Using default stacking branch %s at %s', self._stack_on,
3562
repository = self._bzrdir.create_repository(shared=shared)
3563
self._add_fallback(repository,
3564
possible_transports=[self._bzrdir.transport])
3565
if make_working_trees is not None:
3566
repository.set_make_working_trees(make_working_trees)
3567
return repository, True
3570
class UseExistingRepository(RepositoryAcquisitionPolicy):
3571
"""A policy of reusing an existing repository"""
3573
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3574
require_stacking=False):
3577
:param repository: The repository to use.
3578
:param stack_on: A location to stack on
3579
:param stack_on_pwd: If stack_on is relative, the location it is
3582
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3584
self._repository = repository
3586
def acquire_repository(self, make_working_trees=None, shared=False):
3587
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3589
Returns an existing repository to use.
3591
self._add_fallback(self._repository,
3592
possible_transports=[self._repository.bzrdir.transport])
3593
return self._repository, False
3596
# Please register new formats after old formats so that formats
3597
# appear in chronological order and format descriptions can build
3599
format_registry = BzrDirFormatRegistry()
3600
# The pre-0.8 formats have their repository format network name registered in
3601
# repository.py. MetaDir formats have their repository format network name
3602
# inferred from their disk format string.
3603
format_registry.register('weave', BzrDirFormat6,
3604
'Pre-0.8 format. Slower than knit and does not'
3605
' support checkouts or shared repositories.',
3607
format_registry.register_metadir('metaweave',
3608
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3609
'Transitional format in 0.8. Slower than knit.',
3610
branch_format='bzrlib.branch.BzrBranchFormat5',
3611
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3613
format_registry.register_metadir('knit',
3614
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3615
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3616
branch_format='bzrlib.branch.BzrBranchFormat5',
3617
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3619
format_registry.register_metadir('dirstate',
3620
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3621
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3622
'above when accessed over the network.',
3623
branch_format='bzrlib.branch.BzrBranchFormat5',
3624
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3625
# directly from workingtree_4 triggers a circular import.
3626
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3628
format_registry.register_metadir('dirstate-tags',
3629
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3630
help='New in 0.15: Fast local operations and improved scaling for '
3631
'network operations. Additionally adds support for tags.'
3632
' Incompatible with bzr < 0.15.',
3633
branch_format='bzrlib.branch.BzrBranchFormat6',
3634
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3636
format_registry.register_metadir('rich-root',
3637
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3638
help='New in 1.0. Better handling of tree roots. Incompatible with'
3640
branch_format='bzrlib.branch.BzrBranchFormat6',
3641
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3643
format_registry.register_metadir('dirstate-with-subtree',
3644
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3645
help='New in 0.15: Fast local operations and improved scaling for '
3646
'network operations. Additionally adds support for versioning nested '
3647
'bzr branches. Incompatible with bzr < 0.15.',
3648
branch_format='bzrlib.branch.BzrBranchFormat6',
3649
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3653
format_registry.register_metadir('pack-0.92',
3654
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3655
help='New in 0.92: Pack-based format with data compatible with '
3656
'dirstate-tags format repositories. Interoperates with '
3657
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3658
'Previously called knitpack-experimental. '
3659
'For more information, see '
3660
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3661
branch_format='bzrlib.branch.BzrBranchFormat6',
3662
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3664
format_registry.register_metadir('pack-0.92-subtree',
3665
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3666
help='New in 0.92: Pack-based format with data compatible with '
3667
'dirstate-with-subtree format repositories. Interoperates with '
3668
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3669
'Previously called knitpack-experimental. '
3670
'For more information, see '
3671
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3672
branch_format='bzrlib.branch.BzrBranchFormat6',
3673
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3677
format_registry.register_metadir('rich-root-pack',
3678
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3679
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3680
'(needed for bzr-svn and bzr-git).',
3681
branch_format='bzrlib.branch.BzrBranchFormat6',
3682
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3684
format_registry.register_metadir('1.6',
3685
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3686
help='A format that allows a branch to indicate that there is another '
3687
'(stacked) repository that should be used to access data that is '
3688
'not present locally.',
3689
branch_format='bzrlib.branch.BzrBranchFormat7',
3690
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3692
format_registry.register_metadir('1.6.1-rich-root',
3693
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3694
help='A variant of 1.6 that supports rich-root data '
3695
'(needed for bzr-svn and bzr-git).',
3696
branch_format='bzrlib.branch.BzrBranchFormat7',
3697
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3699
format_registry.register_metadir('1.9',
3700
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3701
help='A repository format using B+tree indexes. These indexes '
3702
'are smaller in size, have smarter caching and provide faster '
3703
'performance for most operations.',
3704
branch_format='bzrlib.branch.BzrBranchFormat7',
3705
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3707
format_registry.register_metadir('1.9-rich-root',
3708
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3709
help='A variant of 1.9 that supports rich-root data '
3710
'(needed for bzr-svn and bzr-git).',
3711
branch_format='bzrlib.branch.BzrBranchFormat7',
3712
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3714
format_registry.register_metadir('1.14',
3715
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3716
help='A working-tree format that supports content filtering.',
3717
branch_format='bzrlib.branch.BzrBranchFormat7',
3718
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3720
format_registry.register_metadir('1.14-rich-root',
3721
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3722
help='A variant of 1.14 that supports rich-root data '
3723
'(needed for bzr-svn and bzr-git).',
3724
branch_format='bzrlib.branch.BzrBranchFormat7',
3725
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3727
# The following un-numbered 'development' formats should always just be aliases.
3728
format_registry.register_metadir('development-rich-root',
3729
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3730
help='Current development format. Supports rich roots. Can convert data '
3731
'to and from rich-root-pack (and anything compatible with '
3732
'rich-root-pack) format repositories. Repositories and branches in '
3733
'this format can only be read by bzr.dev. Please read '
3734
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3736
branch_format='bzrlib.branch.BzrBranchFormat7',
3737
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3741
format_registry.register_metadir('development-subtree',
3742
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3743
help='Current development format, subtree variant. Can convert data to and '
3744
'from pack-0.92-subtree (and anything compatible with '
3745
'pack-0.92-subtree) format repositories. Repositories and branches in '
3746
'this format can only be read by bzr.dev. Please read '
3747
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3749
branch_format='bzrlib.branch.BzrBranchFormat7',
3750
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3752
alias=False, # Restore to being an alias when an actual development subtree format is added
3753
# This current non-alias status is simply because we did not introduce a
3754
# chk based subtree format.
3757
# And the development formats above will have aliased one of the following:
3758
format_registry.register_metadir('development6-rich-root',
3759
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3760
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3762
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3764
branch_format='bzrlib.branch.BzrBranchFormat7',
3765
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3770
# The following format should be an alias for the rich root equivalent
3771
# of the default format
3772
format_registry.register_metadir('default-rich-root',
3773
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3774
help='Default format, rich root variant. (needed for bzr-svn and bzr-git).',
3775
branch_format='bzrlib.branch.BzrBranchFormat6',
3776
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3779
# The current format that is made on 'bzr init'.
3780
format_registry.set_default('pack-0.92')