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 do - 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
return BzrDirMeta1(transport, self)
2401
def __return_repository_format(self):
2402
"""Circular import protection."""
2403
if self._repository_format:
2404
return self._repository_format
2405
from bzrlib.repository import RepositoryFormat
2406
return RepositoryFormat.get_default_format()
2408
def _set_repository_format(self, value):
2409
"""Allow changing the repository format for metadir formats."""
2410
self._repository_format = value
2412
repository_format = property(__return_repository_format,
2413
_set_repository_format)
2415
def _supply_sub_formats_to(self, other_format):
2416
"""Give other_format the same values for sub formats as this has.
2418
This method is expected to be used when parameterising a
2419
RemoteBzrDirFormat instance with the parameters from a
2420
BzrDirMetaFormat1 instance.
2422
:param other_format: other_format is a format which should be
2423
compatible with whatever sub formats are supported by self.
2426
if getattr(self, '_repository_format', None) is not None:
2427
other_format.repository_format = self.repository_format
2428
if self._branch_format is not None:
2429
other_format._branch_format = self._branch_format
2430
if self._workingtree_format is not None:
2431
other_format.workingtree_format = self.workingtree_format
2433
def __get_workingtree_format(self):
2434
if self._workingtree_format is None:
2435
from bzrlib.workingtree import WorkingTreeFormat
2436
self._workingtree_format = WorkingTreeFormat.get_default_format()
2437
return self._workingtree_format
2439
def __set_workingtree_format(self, wt_format):
2440
self._workingtree_format = wt_format
2442
workingtree_format = property(__get_workingtree_format,
2443
__set_workingtree_format)
2446
network_format_registry = registry.FormatRegistry()
2447
"""Registry of formats indexed by their network name.
2449
The network name for a BzrDirFormat is an identifier that can be used when
2450
referring to formats with smart server operations. See
2451
BzrDirFormat.network_name() for more detail.
2455
# Register bzr control format
2456
BzrDirFormat.register_control_format(BzrDirFormat)
2458
# Register bzr formats
2459
BzrDirFormat.register_format(BzrDirFormat4())
2460
BzrDirFormat.register_format(BzrDirFormat5())
2461
BzrDirFormat.register_format(BzrDirFormat6())
2462
__default_format = BzrDirMetaFormat1()
2463
BzrDirFormat.register_format(__default_format)
2464
BzrDirFormat._default_format = __default_format
2467
class Converter(object):
2468
"""Converts a disk format object from one format to another."""
2470
def convert(self, to_convert, pb):
2471
"""Perform the conversion of to_convert, giving feedback via pb.
2473
:param to_convert: The disk object to convert.
2474
:param pb: a progress bar to use for progress information.
2477
def step(self, message):
2478
"""Update the pb by a step."""
2480
self.pb.update(message, self.count, self.total)
2483
class ConvertBzrDir4To5(Converter):
2484
"""Converts format 4 bzr dirs to format 5."""
2487
super(ConvertBzrDir4To5, self).__init__()
2488
self.converted_revs = set()
2489
self.absent_revisions = set()
2493
def convert(self, to_convert, pb):
2494
"""See Converter.convert()."""
2495
self.bzrdir = to_convert
2497
self.pb.note('starting upgrade from format 4 to 5')
2498
if isinstance(self.bzrdir.transport, local.LocalTransport):
2499
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2500
self._convert_to_weaves()
2501
return BzrDir.open(self.bzrdir.root_transport.base)
2503
def _convert_to_weaves(self):
2504
self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2507
stat = self.bzrdir.transport.stat('weaves')
2508
if not S_ISDIR(stat.st_mode):
2509
self.bzrdir.transport.delete('weaves')
2510
self.bzrdir.transport.mkdir('weaves')
2511
except errors.NoSuchFile:
2512
self.bzrdir.transport.mkdir('weaves')
2513
# deliberately not a WeaveFile as we want to build it up slowly.
2514
self.inv_weave = Weave('inventory')
2515
# holds in-memory weaves for all files
2516
self.text_weaves = {}
2517
self.bzrdir.transport.delete('branch-format')
2518
self.branch = self.bzrdir.open_branch()
2519
self._convert_working_inv()
2520
rev_history = self.branch.revision_history()
2521
# to_read is a stack holding the revisions we still need to process;
2522
# appending to it adds new highest-priority revisions
2523
self.known_revisions = set(rev_history)
2524
self.to_read = rev_history[-1:]
2526
rev_id = self.to_read.pop()
2527
if (rev_id not in self.revisions
2528
and rev_id not in self.absent_revisions):
2529
self._load_one_rev(rev_id)
2531
to_import = self._make_order()
2532
for i, rev_id in enumerate(to_import):
2533
self.pb.update('converting revision', i, len(to_import))
2534
self._convert_one_rev(rev_id)
2536
self._write_all_weaves()
2537
self._write_all_revs()
2538
self.pb.note('upgraded to weaves:')
2539
self.pb.note(' %6d revisions and inventories', len(self.revisions))
2540
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
2541
self.pb.note(' %6d texts', self.text_count)
2542
self._cleanup_spare_files_after_format4()
2543
self.branch._transport.put_bytes(
2545
BzrDirFormat5().get_format_string(),
2546
mode=self.bzrdir._get_file_mode())
2548
def _cleanup_spare_files_after_format4(self):
2549
# FIXME working tree upgrade foo.
2550
for n in 'merged-patches', 'pending-merged-patches':
2552
## assert os.path.getsize(p) == 0
2553
self.bzrdir.transport.delete(n)
2554
except errors.NoSuchFile:
2556
self.bzrdir.transport.delete_tree('inventory-store')
2557
self.bzrdir.transport.delete_tree('text-store')
2559
def _convert_working_inv(self):
2560
inv = xml4.serializer_v4.read_inventory(
2561
self.branch._transport.get('inventory'))
2562
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2563
self.branch._transport.put_bytes('inventory', new_inv_xml,
2564
mode=self.bzrdir._get_file_mode())
2566
def _write_all_weaves(self):
2567
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2568
weave_transport = self.bzrdir.transport.clone('weaves')
2569
weaves = WeaveStore(weave_transport, prefixed=False)
2570
transaction = WriteTransaction()
2574
for file_id, file_weave in self.text_weaves.items():
2575
self.pb.update('writing weave', i, len(self.text_weaves))
2576
weaves._put_weave(file_id, file_weave, transaction)
2578
self.pb.update('inventory', 0, 1)
2579
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2580
self.pb.update('inventory', 1, 1)
2584
def _write_all_revs(self):
2585
"""Write all revisions out in new form."""
2586
self.bzrdir.transport.delete_tree('revision-store')
2587
self.bzrdir.transport.mkdir('revision-store')
2588
revision_transport = self.bzrdir.transport.clone('revision-store')
2590
from bzrlib.xml5 import serializer_v5
2591
from bzrlib.repofmt.weaverepo import RevisionTextStore
2592
revision_store = RevisionTextStore(revision_transport,
2593
serializer_v5, False, versionedfile.PrefixMapper(),
2594
lambda:True, lambda:True)
2596
for i, rev_id in enumerate(self.converted_revs):
2597
self.pb.update('write revision', i, len(self.converted_revs))
2598
text = serializer_v5.write_revision_to_string(
2599
self.revisions[rev_id])
2601
revision_store.add_lines(key, None, osutils.split_lines(text))
2605
def _load_one_rev(self, rev_id):
2606
"""Load a revision object into memory.
2608
Any parents not either loaded or abandoned get queued to be
2610
self.pb.update('loading revision',
2611
len(self.revisions),
2612
len(self.known_revisions))
2613
if not self.branch.repository.has_revision(rev_id):
2615
self.pb.note('revision {%s} not present in branch; '
2616
'will be converted as a ghost',
2618
self.absent_revisions.add(rev_id)
2620
rev = self.branch.repository.get_revision(rev_id)
2621
for parent_id in rev.parent_ids:
2622
self.known_revisions.add(parent_id)
2623
self.to_read.append(parent_id)
2624
self.revisions[rev_id] = rev
2626
def _load_old_inventory(self, rev_id):
2627
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2628
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2629
inv.revision_id = rev_id
2630
rev = self.revisions[rev_id]
2633
def _load_updated_inventory(self, rev_id):
2634
inv_xml = self.inv_weave.get_text(rev_id)
2635
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2638
def _convert_one_rev(self, rev_id):
2639
"""Convert revision and all referenced objects to new format."""
2640
rev = self.revisions[rev_id]
2641
inv = self._load_old_inventory(rev_id)
2642
present_parents = [p for p in rev.parent_ids
2643
if p not in self.absent_revisions]
2644
self._convert_revision_contents(rev, inv, present_parents)
2645
self._store_new_inv(rev, inv, present_parents)
2646
self.converted_revs.add(rev_id)
2648
def _store_new_inv(self, rev, inv, present_parents):
2649
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2650
new_inv_sha1 = sha_string(new_inv_xml)
2651
self.inv_weave.add_lines(rev.revision_id,
2653
new_inv_xml.splitlines(True))
2654
rev.inventory_sha1 = new_inv_sha1
2656
def _convert_revision_contents(self, rev, inv, present_parents):
2657
"""Convert all the files within a revision.
2659
Also upgrade the inventory to refer to the text revision ids."""
2660
rev_id = rev.revision_id
2661
mutter('converting texts of revision {%s}',
2663
parent_invs = map(self._load_updated_inventory, present_parents)
2664
entries = inv.iter_entries()
2666
for path, ie in entries:
2667
self._convert_file_version(rev, ie, parent_invs)
2669
def _convert_file_version(self, rev, ie, parent_invs):
2670
"""Convert one version of one file.
2672
The file needs to be added into the weave if it is a merge
2673
of >=2 parents or if it's changed from its parent.
2675
file_id = ie.file_id
2676
rev_id = rev.revision_id
2677
w = self.text_weaves.get(file_id)
2680
self.text_weaves[file_id] = w
2681
text_changed = False
2682
parent_candiate_entries = ie.parent_candidates(parent_invs)
2683
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2684
# XXX: Note that this is unordered - and this is tolerable because
2685
# the previous code was also unordered.
2686
previous_entries = dict((head, parent_candiate_entries[head]) for head
2688
self.snapshot_ie(previous_entries, ie, w, rev_id)
2691
def get_parent_map(self, revision_ids):
2692
"""See graph._StackedParentsProvider.get_parent_map"""
2693
return dict((revision_id, self.revisions[revision_id])
2694
for revision_id in revision_ids
2695
if revision_id in self.revisions)
2697
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2698
# TODO: convert this logic, which is ~= snapshot to
2699
# a call to:. This needs the path figured out. rather than a work_tree
2700
# a v4 revision_tree can be given, or something that looks enough like
2701
# one to give the file content to the entry if it needs it.
2702
# and we need something that looks like a weave store for snapshot to
2704
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2705
if len(previous_revisions) == 1:
2706
previous_ie = previous_revisions.values()[0]
2707
if ie._unchanged(previous_ie):
2708
ie.revision = previous_ie.revision
2711
text = self.branch.repository._text_store.get(ie.text_id)
2712
file_lines = text.readlines()
2713
w.add_lines(rev_id, previous_revisions, file_lines)
2714
self.text_count += 1
2716
w.add_lines(rev_id, previous_revisions, [])
2717
ie.revision = rev_id
2719
def _make_order(self):
2720
"""Return a suitable order for importing revisions.
2722
The order must be such that an revision is imported after all
2723
its (present) parents.
2725
todo = set(self.revisions.keys())
2726
done = self.absent_revisions.copy()
2729
# scan through looking for a revision whose parents
2731
for rev_id in sorted(list(todo)):
2732
rev = self.revisions[rev_id]
2733
parent_ids = set(rev.parent_ids)
2734
if parent_ids.issubset(done):
2735
# can take this one now
2736
order.append(rev_id)
2742
class ConvertBzrDir5To6(Converter):
2743
"""Converts format 5 bzr dirs to format 6."""
2745
def convert(self, to_convert, pb):
2746
"""See Converter.convert()."""
2747
self.bzrdir = to_convert
2749
self.pb.note('starting upgrade from format 5 to 6')
2750
self._convert_to_prefixed()
2751
return BzrDir.open(self.bzrdir.root_transport.base)
2753
def _convert_to_prefixed(self):
2754
from bzrlib.store import TransportStore
2755
self.bzrdir.transport.delete('branch-format')
2756
for store_name in ["weaves", "revision-store"]:
2757
self.pb.note("adding prefixes to %s" % store_name)
2758
store_transport = self.bzrdir.transport.clone(store_name)
2759
store = TransportStore(store_transport, prefixed=True)
2760
for urlfilename in store_transport.list_dir('.'):
2761
filename = urlutils.unescape(urlfilename)
2762
if (filename.endswith(".weave") or
2763
filename.endswith(".gz") or
2764
filename.endswith(".sig")):
2765
file_id, suffix = os.path.splitext(filename)
2769
new_name = store._mapper.map((file_id,)) + suffix
2770
# FIXME keep track of the dirs made RBC 20060121
2772
store_transport.move(filename, new_name)
2773
except errors.NoSuchFile: # catches missing dirs strangely enough
2774
store_transport.mkdir(osutils.dirname(new_name))
2775
store_transport.move(filename, new_name)
2776
self.bzrdir.transport.put_bytes(
2778
BzrDirFormat6().get_format_string(),
2779
mode=self.bzrdir._get_file_mode())
2782
class ConvertBzrDir6ToMeta(Converter):
2783
"""Converts format 6 bzr dirs to metadirs."""
2785
def convert(self, to_convert, pb):
2786
"""See Converter.convert()."""
2787
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2788
from bzrlib.branch import BzrBranchFormat5
2789
self.bzrdir = to_convert
2792
self.total = 20 # the steps we know about
2793
self.garbage_inventories = []
2794
self.dir_mode = self.bzrdir._get_dir_mode()
2795
self.file_mode = self.bzrdir._get_file_mode()
2797
self.pb.note('starting upgrade from format 6 to metadir')
2798
self.bzrdir.transport.put_bytes(
2800
"Converting to format 6",
2801
mode=self.file_mode)
2802
# its faster to move specific files around than to open and use the apis...
2803
# first off, nuke ancestry.weave, it was never used.
2805
self.step('Removing ancestry.weave')
2806
self.bzrdir.transport.delete('ancestry.weave')
2807
except errors.NoSuchFile:
2809
# find out whats there
2810
self.step('Finding branch files')
2811
last_revision = self.bzrdir.open_branch().last_revision()
2812
bzrcontents = self.bzrdir.transport.list_dir('.')
2813
for name in bzrcontents:
2814
if name.startswith('basis-inventory.'):
2815
self.garbage_inventories.append(name)
2816
# create new directories for repository, working tree and branch
2817
repository_names = [('inventory.weave', True),
2818
('revision-store', True),
2820
self.step('Upgrading repository ')
2821
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2822
self.make_lock('repository')
2823
# we hard code the formats here because we are converting into
2824
# the meta format. The meta format upgrader can take this to a
2825
# future format within each component.
2826
self.put_format('repository', RepositoryFormat7())
2827
for entry in repository_names:
2828
self.move_entry('repository', entry)
2830
self.step('Upgrading branch ')
2831
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2832
self.make_lock('branch')
2833
self.put_format('branch', BzrBranchFormat5())
2834
branch_files = [('revision-history', True),
2835
('branch-name', True),
2837
for entry in branch_files:
2838
self.move_entry('branch', entry)
2840
checkout_files = [('pending-merges', True),
2841
('inventory', True),
2842
('stat-cache', False)]
2843
# If a mandatory checkout file is not present, the branch does not have
2844
# a functional checkout. Do not create a checkout in the converted
2846
for name, mandatory in checkout_files:
2847
if mandatory and name not in bzrcontents:
2848
has_checkout = False
2852
if not has_checkout:
2853
self.pb.note('No working tree.')
2854
# If some checkout files are there, we may as well get rid of them.
2855
for name, mandatory in checkout_files:
2856
if name in bzrcontents:
2857
self.bzrdir.transport.delete(name)
2859
from bzrlib.workingtree import WorkingTreeFormat3
2860
self.step('Upgrading working tree')
2861
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2862
self.make_lock('checkout')
2864
'checkout', WorkingTreeFormat3())
2865
self.bzrdir.transport.delete_multi(
2866
self.garbage_inventories, self.pb)
2867
for entry in checkout_files:
2868
self.move_entry('checkout', entry)
2869
if last_revision is not None:
2870
self.bzrdir.transport.put_bytes(
2871
'checkout/last-revision', last_revision)
2872
self.bzrdir.transport.put_bytes(
2874
BzrDirMetaFormat1().get_format_string(),
2875
mode=self.file_mode)
2876
return BzrDir.open(self.bzrdir.root_transport.base)
2878
def make_lock(self, name):
2879
"""Make a lock for the new control dir name."""
2880
self.step('Make %s lock' % name)
2881
ld = lockdir.LockDir(self.bzrdir.transport,
2883
file_modebits=self.file_mode,
2884
dir_modebits=self.dir_mode)
2887
def move_entry(self, new_dir, entry):
2888
"""Move then entry name into new_dir."""
2890
mandatory = entry[1]
2891
self.step('Moving %s' % name)
2893
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2894
except errors.NoSuchFile:
2898
def put_format(self, dirname, format):
2899
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2900
format.get_format_string(),
2904
class ConvertMetaToMeta(Converter):
2905
"""Converts the components of metadirs."""
2907
def __init__(self, target_format):
2908
"""Create a metadir to metadir converter.
2910
:param target_format: The final metadir format that is desired.
2912
self.target_format = target_format
2914
def convert(self, to_convert, pb):
2915
"""See Converter.convert()."""
2916
self.bzrdir = to_convert
2920
self.step('checking repository format')
2922
repo = self.bzrdir.open_repository()
2923
except errors.NoRepositoryPresent:
2926
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2927
from bzrlib.repository import CopyConverter
2928
self.pb.note('starting repository conversion')
2929
converter = CopyConverter(self.target_format.repository_format)
2930
converter.convert(repo, pb)
2932
branch = self.bzrdir.open_branch()
2933
except errors.NotBranchError:
2936
# TODO: conversions of Branch and Tree should be done by
2937
# InterXFormat lookups/some sort of registry.
2938
# Avoid circular imports
2939
from bzrlib import branch as _mod_branch
2940
old = branch._format.__class__
2941
new = self.target_format.get_branch_format().__class__
2943
if (old == _mod_branch.BzrBranchFormat5 and
2944
new in (_mod_branch.BzrBranchFormat6,
2945
_mod_branch.BzrBranchFormat7)):
2946
branch_converter = _mod_branch.Converter5to6()
2947
elif (old == _mod_branch.BzrBranchFormat6 and
2948
new == _mod_branch.BzrBranchFormat7):
2949
branch_converter = _mod_branch.Converter6to7()
2951
raise errors.BadConversionTarget("No converter", new)
2952
branch_converter.convert(branch)
2953
branch = self.bzrdir.open_branch()
2954
old = branch._format.__class__
2956
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2957
except (errors.NoWorkingTree, errors.NotLocalUrl):
2960
# TODO: conversions of Branch and Tree should be done by
2961
# InterXFormat lookups
2962
if (isinstance(tree, workingtree.WorkingTree3) and
2963
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2964
isinstance(self.target_format.workingtree_format,
2965
workingtree_4.DirStateWorkingTreeFormat)):
2966
workingtree_4.Converter3to4().convert(tree)
2967
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2968
not isinstance(tree, workingtree_4.WorkingTree5) and
2969
isinstance(self.target_format.workingtree_format,
2970
workingtree_4.WorkingTreeFormat5)):
2971
workingtree_4.Converter4to5().convert(tree)
2972
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2973
not isinstance(tree, workingtree_4.WorkingTree6) and
2974
isinstance(self.target_format.workingtree_format,
2975
workingtree_4.WorkingTreeFormat6)):
2976
workingtree_4.Converter4or5to6().convert(tree)
2980
# This is not in remote.py because it's relatively small, and needs to be
2981
# registered. Putting it in remote.py creates a circular import problem.
2982
# we can make it a lazy object if the control formats is turned into something
2984
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2985
"""Format representing bzrdirs accessed via a smart server"""
2988
BzrDirMetaFormat1.__init__(self)
2989
self._network_name = None
2991
def get_format_description(self):
2992
return 'bzr remote bzrdir'
2994
def get_format_string(self):
2995
raise NotImplementedError(self.get_format_string)
2997
def network_name(self):
2998
if self._network_name:
2999
return self._network_name
3001
raise AssertionError("No network name set.")
3004
def probe_transport(klass, transport):
3005
"""Return a RemoteBzrDirFormat object if it looks possible."""
3007
medium = transport.get_smart_medium()
3008
except (NotImplementedError, AttributeError,
3009
errors.TransportNotPossible, errors.NoSmartMedium,
3010
errors.SmartProtocolError):
3011
# no smart server, so not a branch for this format type.
3012
raise errors.NotBranchError(path=transport.base)
3014
# Decline to open it if the server doesn't support our required
3015
# version (3) so that the VFS-based transport will do it.
3016
if medium.should_probe():
3018
server_version = medium.protocol_version()
3019
except errors.SmartProtocolError:
3020
# Apparently there's no usable smart server there, even though
3021
# the medium supports the smart protocol.
3022
raise errors.NotBranchError(path=transport.base)
3023
if server_version != '2':
3024
raise errors.NotBranchError(path=transport.base)
3027
def initialize_on_transport(self, transport):
3029
# hand off the request to the smart server
3030
client_medium = transport.get_smart_medium()
3031
except errors.NoSmartMedium:
3032
# TODO: lookup the local format from a server hint.
3033
local_dir_format = BzrDirMetaFormat1()
3034
return local_dir_format.initialize_on_transport(transport)
3035
client = _SmartClient(client_medium)
3036
path = client.remote_path_from_transport(transport)
3037
response = client.call('BzrDirFormat.initialize', path)
3038
if response[0] != 'ok':
3039
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
3040
format = RemoteBzrDirFormat()
3041
self._supply_sub_formats_to(format)
3042
return remote.RemoteBzrDir(transport, format)
3044
def parse_NoneTrueFalse(self, arg):
3051
raise AssertionError("invalid arg %r" % arg)
3053
def _serialize_NoneTrueFalse(self, arg):
3060
def _serialize_NoneString(self, arg):
3063
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
3064
create_prefix=False, force_new_repo=False, stacked_on=None,
3065
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
3068
# hand off the request to the smart server
3069
client_medium = transport.get_smart_medium()
3070
except errors.NoSmartMedium:
3071
# TODO: lookup the local format from a server hint.
3072
local_dir_format = BzrDirMetaFormat1()
3073
self._supply_sub_formats_to(local_dir_format)
3074
return local_dir_format.initialize_on_transport_ex(transport,
3075
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3076
force_new_repo=force_new_repo, stacked_on=stacked_on,
3077
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3078
make_working_trees=make_working_trees, shared_repo=shared_repo)
3079
client = _SmartClient(client_medium)
3080
path = client.remote_path_from_transport(transport)
3081
if client_medium._is_remote_before((1, 15)):
3082
local_dir_format = BzrDirMetaFormat1()
3083
self._supply_sub_formats_to(local_dir_format)
3084
return local_dir_format.initialize_on_transport_ex(transport,
3085
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3086
force_new_repo=force_new_repo, stacked_on=stacked_on,
3087
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3088
make_working_trees=make_working_trees, shared_repo=shared_repo,
3091
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
3092
args.append(self._serialize_NoneTrueFalse(create_prefix))
3093
args.append(self._serialize_NoneTrueFalse(force_new_repo))
3094
args.append(self._serialize_NoneString(stacked_on))
3095
# stack_on_pwd is often/usually our transport
3098
stack_on_pwd = transport.relpath(stack_on_pwd)
3099
if not stack_on_pwd:
3101
except errors.PathNotChild:
3103
args.append(self._serialize_NoneString(stack_on_pwd))
3104
args.append(self._serialize_NoneString(repo_format_name))
3105
args.append(self._serialize_NoneTrueFalse(make_working_trees))
3106
args.append(self._serialize_NoneTrueFalse(shared_repo))
3107
if self._network_name is None:
3108
self._network_name = \
3109
BzrDirFormat.get_default_format().network_name()
3111
response = client.call('BzrDirFormat.initialize_ex',
3112
self.network_name(), path, *args)
3113
except errors.UnknownSmartMethod:
3114
local_dir_format = BzrDirMetaFormat1()
3115
self._supply_sub_formats_to(local_dir_format)
3116
return local_dir_format.initialize_on_transport_ex(transport,
3117
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3118
force_new_repo=force_new_repo, stacked_on=stacked_on,
3119
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3120
make_working_trees=make_working_trees, shared_repo=shared_repo,
3122
repo_path = response[0]
3123
bzrdir_name = response[6]
3124
require_stacking = response[7]
3125
require_stacking = self.parse_NoneTrueFalse(require_stacking)
3126
format = RemoteBzrDirFormat()
3127
format._network_name = bzrdir_name
3128
self._supply_sub_formats_to(format)
3129
bzrdir = remote.RemoteBzrDir(transport, format)
3131
repo_format = remote.response_tuple_to_repo_format(response[1:])
3132
if repo_path == '.':
3135
repo_bzrdir_format = RemoteBzrDirFormat()
3136
repo_bzrdir_format._network_name = response[5]
3137
repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
3141
final_stack = response[8] or None
3142
final_stack_pwd = response[9] or None
3143
remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
3144
policy = UseExistingRepository(remote_repo, final_stack,
3145
final_stack_pwd, require_stacking)
3146
policy.acquire_repository()
3150
return remote_repo, bzrdir, require_stacking, policy
3152
def _open(self, transport):
3153
return remote.RemoteBzrDir(transport, self)
3155
def __eq__(self, other):
3156
if not isinstance(other, RemoteBzrDirFormat):
3158
return self.get_format_description() == other.get_format_description()
3160
def __return_repository_format(self):
3161
# Always return a RemoteRepositoryFormat object, but if a specific bzr
3162
# repository format has been asked for, tell the RemoteRepositoryFormat
3163
# that it should use that for init() etc.
3164
result = remote.RemoteRepositoryFormat()
3165
custom_format = getattr(self, '_repository_format', None)
3167
if isinstance(custom_format, remote.RemoteRepositoryFormat):
3168
return custom_format
3170
# We will use the custom format to create repositories over the
3171
# wire; expose its details like rich_root_data for code to
3173
result._custom_format = custom_format
3176
def get_branch_format(self):
3177
result = BzrDirMetaFormat1.get_branch_format(self)
3178
if not isinstance(result, remote.RemoteBranchFormat):
3179
new_result = remote.RemoteBranchFormat()
3180
new_result._custom_format = result
3182
self.set_branch_format(new_result)
3186
repository_format = property(__return_repository_format,
3187
BzrDirMetaFormat1._set_repository_format) #.im_func)
3190
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
3193
class BzrDirFormatInfo(object):
3195
def __init__(self, native, deprecated, hidden, experimental):
3196
self.deprecated = deprecated
3197
self.native = native
3198
self.hidden = hidden
3199
self.experimental = experimental
3202
class BzrDirFormatRegistry(registry.Registry):
3203
"""Registry of user-selectable BzrDir subformats.
3205
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
3206
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
3210
"""Create a BzrDirFormatRegistry."""
3211
self._aliases = set()
3212
self._registration_order = list()
3213
super(BzrDirFormatRegistry, self).__init__()
3216
"""Return a set of the format names which are aliases."""
3217
return frozenset(self._aliases)
3219
def register_metadir(self, key,
3220
repository_format, help, native=True, deprecated=False,
3226
"""Register a metadir subformat.
3228
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3229
by the Repository/Branch/WorkingTreeformats.
3231
:param repository_format: The fully-qualified repository format class
3233
:param branch_format: Fully-qualified branch format class name as
3235
:param tree_format: Fully-qualified tree format class name as
3238
# This should be expanded to support setting WorkingTree and Branch
3239
# formats, once BzrDirMetaFormat1 supports that.
3240
def _load(full_name):
3241
mod_name, factory_name = full_name.rsplit('.', 1)
3243
mod = __import__(mod_name, globals(), locals(),
3245
except ImportError, e:
3246
raise ImportError('failed to load %s: %s' % (full_name, e))
3248
factory = getattr(mod, factory_name)
3249
except AttributeError:
3250
raise AttributeError('no factory %s in module %r'
3255
bd = BzrDirMetaFormat1()
3256
if branch_format is not None:
3257
bd.set_branch_format(_load(branch_format))
3258
if tree_format is not None:
3259
bd.workingtree_format = _load(tree_format)
3260
if repository_format is not None:
3261
bd.repository_format = _load(repository_format)
3263
self.register(key, helper, help, native, deprecated, hidden,
3264
experimental, alias)
3266
def register(self, key, factory, help, native=True, deprecated=False,
3267
hidden=False, experimental=False, alias=False):
3268
"""Register a BzrDirFormat factory.
3270
The factory must be a callable that takes one parameter: the key.
3271
It must produce an instance of the BzrDirFormat when called.
3273
This function mainly exists to prevent the info object from being
3276
registry.Registry.register(self, key, factory, help,
3277
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3279
self._aliases.add(key)
3280
self._registration_order.append(key)
3282
def register_lazy(self, key, module_name, member_name, help, native=True,
3283
deprecated=False, hidden=False, experimental=False, alias=False):
3284
registry.Registry.register_lazy(self, key, module_name, member_name,
3285
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3287
self._aliases.add(key)
3288
self._registration_order.append(key)
3290
def set_default(self, key):
3291
"""Set the 'default' key to be a clone of the supplied key.
3293
This method must be called once and only once.
3295
registry.Registry.register(self, 'default', self.get(key),
3296
self.get_help(key), info=self.get_info(key))
3297
self._aliases.add('default')
3299
def set_default_repository(self, key):
3300
"""Set the FormatRegistry default and Repository default.
3302
This is a transitional method while Repository.set_default_format
3305
if 'default' in self:
3306
self.remove('default')
3307
self.set_default(key)
3308
format = self.get('default')()
3310
def make_bzrdir(self, key):
3311
return self.get(key)()
3313
def help_topic(self, topic):
3315
default_realkey = None
3316
default_help = self.get_help('default')
3318
for key in self._registration_order:
3319
if key == 'default':
3321
help = self.get_help(key)
3322
if help == default_help:
3323
default_realkey = key
3325
help_pairs.append((key, help))
3327
def wrapped(key, help, info):
3329
help = '(native) ' + help
3330
return ':%s:\n%s\n\n' % (key,
3331
textwrap.fill(help, initial_indent=' ',
3332
subsequent_indent=' '))
3333
if default_realkey is not None:
3334
output += wrapped(default_realkey, '(default) %s' % default_help,
3335
self.get_info('default'))
3336
deprecated_pairs = []
3337
experimental_pairs = []
3338
for key, help in help_pairs:
3339
info = self.get_info(key)
3342
elif info.deprecated:
3343
deprecated_pairs.append((key, help))
3344
elif info.experimental:
3345
experimental_pairs.append((key, help))
3347
output += wrapped(key, help, info)
3348
output += "\nSee ``bzr help formats`` for more about storage formats."
3350
if len(experimental_pairs) > 0:
3351
other_output += "Experimental formats are shown below.\n\n"
3352
for key, help in experimental_pairs:
3353
info = self.get_info(key)
3354
other_output += wrapped(key, help, info)
3357
"No experimental formats are available.\n\n"
3358
if len(deprecated_pairs) > 0:
3359
other_output += "\nDeprecated formats are shown below.\n\n"
3360
for key, help in deprecated_pairs:
3361
info = self.get_info(key)
3362
other_output += wrapped(key, help, info)
3365
"\nNo deprecated formats are available.\n\n"
3367
"\nSee ``bzr help formats`` for more about storage formats."
3369
if topic == 'other-formats':
3375
class RepositoryAcquisitionPolicy(object):
3376
"""Abstract base class for repository acquisition policies.
3378
A repository acquisition policy decides how a BzrDir acquires a repository
3379
for a branch that is being created. The most basic policy decision is
3380
whether to create a new repository or use an existing one.
3382
def __init__(self, stack_on, stack_on_pwd, require_stacking):
3385
:param stack_on: A location to stack on
3386
:param stack_on_pwd: If stack_on is relative, the location it is
3388
:param require_stacking: If True, it is a failure to not stack.
3390
self._stack_on = stack_on
3391
self._stack_on_pwd = stack_on_pwd
3392
self._require_stacking = require_stacking
3394
def configure_branch(self, branch):
3395
"""Apply any configuration data from this policy to the branch.
3397
Default implementation sets repository stacking.
3399
if self._stack_on is None:
3401
if self._stack_on_pwd is None:
3402
stack_on = self._stack_on
3405
stack_on = urlutils.rebase_url(self._stack_on,
3407
branch.bzrdir.root_transport.base)
3408
except errors.InvalidRebaseURLs:
3409
stack_on = self._get_full_stack_on()
3411
branch.set_stacked_on_url(stack_on)
3412
except (errors.UnstackableBranchFormat,
3413
errors.UnstackableRepositoryFormat):
3414
if self._require_stacking:
3417
def _get_full_stack_on(self):
3418
"""Get a fully-qualified URL for the stack_on location."""
3419
if self._stack_on is None:
3421
if self._stack_on_pwd is None:
3422
return self._stack_on
3424
return urlutils.join(self._stack_on_pwd, self._stack_on)
3426
def _add_fallback(self, repository, possible_transports=None):
3427
"""Add a fallback to the supplied repository, if stacking is set."""
3428
stack_on = self._get_full_stack_on()
3429
if stack_on is None:
3432
stacked_dir = BzrDir.open(stack_on,
3433
possible_transports=possible_transports)
3434
except errors.JailBreak:
3435
# We keep the stacking details, but we are in the server code so
3436
# actually stacking is not needed.
3439
stacked_repo = stacked_dir.open_branch().repository
3440
except errors.NotBranchError:
3441
stacked_repo = stacked_dir.open_repository()
3443
repository.add_fallback_repository(stacked_repo)
3444
except errors.UnstackableRepositoryFormat:
3445
if self._require_stacking:
3448
self._require_stacking = True
3450
def acquire_repository(self, make_working_trees=None, shared=False):
3451
"""Acquire a repository for this bzrdir.
3453
Implementations may create a new repository or use a pre-exising
3455
:param make_working_trees: If creating a repository, set
3456
make_working_trees to this value (if non-None)
3457
:param shared: If creating a repository, make it shared if True
3458
:return: A repository, is_new_flag (True if the repository was
3461
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3464
class CreateRepository(RepositoryAcquisitionPolicy):
3465
"""A policy of creating a new repository"""
3467
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3468
require_stacking=False):
3471
:param bzrdir: The bzrdir to create the repository on.
3472
:param stack_on: A location to stack on
3473
:param stack_on_pwd: If stack_on is relative, the location it is
3476
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3478
self._bzrdir = bzrdir
3480
def acquire_repository(self, make_working_trees=None, shared=False):
3481
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3483
Creates the desired repository in the bzrdir we already have.
3485
stack_on = self._get_full_stack_on()
3487
# Stacking is desired. requested by the target, but does the place it
3488
# points at support stacking? If it doesn't then we should
3489
# not implicitly upgrade. We check this here.
3490
format = self._bzrdir._format
3491
if not (format.repository_format.supports_external_lookups
3492
and format.get_branch_format().supports_stacking()):
3493
# May need to upgrade - but only do if the target also
3494
# supports stacking. Note that this currently wastes
3495
# network round trips to check - but we only do this
3496
# when the source can't stack so it will fade away
3497
# as people do upgrade.
3498
branch_format = None
3501
target_dir = BzrDir.open(stack_on,
3502
possible_transports=[self._bzrdir.root_transport])
3503
except errors.NotBranchError:
3504
# Nothing there, don't change formats
3506
except errors.JailBreak:
3507
# stack_on is inaccessible, JFDI.
3508
if format.repository_format.rich_root_data:
3509
repo_format = pack_repo.RepositoryFormatKnitPack6RichRoot()
3511
repo_format = pack_repo.RepositoryFormatKnitPack6()
3512
branch_format = branch.BzrBranchFormat7()
3515
target_branch = target_dir.open_branch()
3516
except errors.NotBranchError:
3517
# No branch, don't change formats
3520
branch_format = target_branch._format
3521
repo_format = target_branch.repository._format
3522
if not (branch_format.supports_stacking()
3523
and repo_format.supports_external_lookups):
3524
# Doesn't stack itself, don't force an upgrade
3525
branch_format = None
3527
if branch_format and repo_format:
3528
# Does support stacking, use its format.
3529
format.repository_format = repo_format
3530
format.set_branch_format(branch_format)
3531
note('Source format does not support stacking, '
3532
'using format: \'%s\'\n %s\n',
3533
branch_format.get_format_description(),
3534
repo_format.get_format_description())
3535
if not self._require_stacking:
3536
# We have picked up automatic stacking somewhere.
3537
note('Using default stacking branch %s at %s', self._stack_on,
3539
repository = self._bzrdir.create_repository(shared=shared)
3540
self._add_fallback(repository,
3541
possible_transports=[self._bzrdir.transport])
3542
if make_working_trees is not None:
3543
repository.set_make_working_trees(make_working_trees)
3544
return repository, True
3547
class UseExistingRepository(RepositoryAcquisitionPolicy):
3548
"""A policy of reusing an existing repository"""
3550
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3551
require_stacking=False):
3554
:param repository: The repository to use.
3555
:param stack_on: A location to stack on
3556
:param stack_on_pwd: If stack_on is relative, the location it is
3559
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3561
self._repository = repository
3563
def acquire_repository(self, make_working_trees=None, shared=False):
3564
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3566
Returns an existing repository to use.
3568
self._add_fallback(self._repository,
3569
possible_transports=[self._repository.bzrdir.transport])
3570
return self._repository, False
3573
# Please register new formats after old formats so that formats
3574
# appear in chronological order and format descriptions can build
3576
format_registry = BzrDirFormatRegistry()
3577
# The pre-0.8 formats have their repository format network name registered in
3578
# repository.py. MetaDir formats have their repository format network name
3579
# inferred from their disk format string.
3580
format_registry.register('weave', BzrDirFormat6,
3581
'Pre-0.8 format. Slower than knit and does not'
3582
' support checkouts or shared repositories.',
3584
format_registry.register_metadir('metaweave',
3585
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3586
'Transitional format in 0.8. Slower than knit.',
3587
branch_format='bzrlib.branch.BzrBranchFormat5',
3588
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3590
format_registry.register_metadir('knit',
3591
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3592
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3593
branch_format='bzrlib.branch.BzrBranchFormat5',
3594
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3596
format_registry.register_metadir('dirstate',
3597
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3598
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3599
'above when accessed over the network.',
3600
branch_format='bzrlib.branch.BzrBranchFormat5',
3601
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3602
# directly from workingtree_4 triggers a circular import.
3603
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3605
format_registry.register_metadir('dirstate-tags',
3606
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3607
help='New in 0.15: Fast local operations and improved scaling for '
3608
'network operations. Additionally adds support for tags.'
3609
' Incompatible with bzr < 0.15.',
3610
branch_format='bzrlib.branch.BzrBranchFormat6',
3611
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3613
format_registry.register_metadir('rich-root',
3614
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3615
help='New in 1.0. Better handling of tree roots. Incompatible with'
3617
branch_format='bzrlib.branch.BzrBranchFormat6',
3618
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3620
format_registry.register_metadir('dirstate-with-subtree',
3621
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3622
help='New in 0.15: Fast local operations and improved scaling for '
3623
'network operations. Additionally adds support for versioning nested '
3624
'bzr branches. Incompatible with bzr < 0.15.',
3625
branch_format='bzrlib.branch.BzrBranchFormat6',
3626
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3630
format_registry.register_metadir('pack-0.92',
3631
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3632
help='New in 0.92: Pack-based format with data compatible with '
3633
'dirstate-tags format repositories. Interoperates with '
3634
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3635
'Previously called knitpack-experimental. '
3636
'For more information, see '
3637
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3638
branch_format='bzrlib.branch.BzrBranchFormat6',
3639
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3641
format_registry.register_metadir('pack-0.92-subtree',
3642
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3643
help='New in 0.92: Pack-based format with data compatible with '
3644
'dirstate-with-subtree format repositories. Interoperates with '
3645
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3646
'Previously called knitpack-experimental. '
3647
'For more information, see '
3648
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3649
branch_format='bzrlib.branch.BzrBranchFormat6',
3650
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3654
format_registry.register_metadir('rich-root-pack',
3655
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3656
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3657
'(needed for bzr-svn and bzr-git).',
3658
branch_format='bzrlib.branch.BzrBranchFormat6',
3659
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3661
format_registry.register_metadir('1.6',
3662
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3663
help='A format that allows a branch to indicate that there is another '
3664
'(stacked) repository that should be used to access data that is '
3665
'not present locally.',
3666
branch_format='bzrlib.branch.BzrBranchFormat7',
3667
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3669
format_registry.register_metadir('1.6.1-rich-root',
3670
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3671
help='A variant of 1.6 that supports rich-root data '
3672
'(needed for bzr-svn and bzr-git).',
3673
branch_format='bzrlib.branch.BzrBranchFormat7',
3674
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3676
format_registry.register_metadir('1.9',
3677
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3678
help='A repository format using B+tree indexes. These indexes '
3679
'are smaller in size, have smarter caching and provide faster '
3680
'performance for most operations.',
3681
branch_format='bzrlib.branch.BzrBranchFormat7',
3682
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3684
format_registry.register_metadir('1.9-rich-root',
3685
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3686
help='A variant of 1.9 that supports rich-root data '
3687
'(needed for bzr-svn and bzr-git).',
3688
branch_format='bzrlib.branch.BzrBranchFormat7',
3689
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3691
format_registry.register_metadir('1.14',
3692
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3693
help='A working-tree format that supports content filtering.',
3694
branch_format='bzrlib.branch.BzrBranchFormat7',
3695
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3697
format_registry.register_metadir('1.14-rich-root',
3698
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3699
help='A variant of 1.14 that supports rich-root data '
3700
'(needed for bzr-svn and bzr-git).',
3701
branch_format='bzrlib.branch.BzrBranchFormat7',
3702
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3704
# The following un-numbered 'development' formats should always just be aliases.
3705
format_registry.register_metadir('development-rich-root',
3706
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3707
help='Current development format. Supports rich roots. Can convert data '
3708
'to and from rich-root-pack (and anything compatible with '
3709
'rich-root-pack) format repositories. Repositories and branches in '
3710
'this format can only be read by bzr.dev. Please read '
3711
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3713
branch_format='bzrlib.branch.BzrBranchFormat7',
3714
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3718
format_registry.register_metadir('development-subtree',
3719
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3720
help='Current development format, subtree variant. Can convert data to and '
3721
'from pack-0.92-subtree (and anything compatible with '
3722
'pack-0.92-subtree) format repositories. Repositories and branches in '
3723
'this format can only be read by bzr.dev. Please read '
3724
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3726
branch_format='bzrlib.branch.BzrBranchFormat7',
3727
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3729
alias=False, # Restore to being an alias when an actual development subtree format is added
3730
# This current non-alias status is simply because we did not introduce a
3731
# chk based subtree format.
3734
# And the development formats above will have aliased one of the following:
3735
format_registry.register_metadir('development6-rich-root',
3736
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3737
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3739
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3741
branch_format='bzrlib.branch.BzrBranchFormat7',
3742
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3747
# The following format should be an alias for the rich root equivalent
3748
# of the default format
3749
format_registry.register_metadir('default-rich-root',
3750
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3751
help='Default format, rich root variant. (needed for bzr-svn and bzr-git).',
3752
branch_format='bzrlib.branch.BzrBranchFormat6',
3753
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3756
# The current format that is made on 'bzr init'.
3757
format_registry.set_default('pack-0.92')