1
# Copyright (C) 2006-2010 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""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.
34
from bzrlib.lazy_import import lazy_import
35
lazy_import(globals(), """
36
from stat import S_ISDIR
50
revision as _mod_revision,
60
from bzrlib.osutils import (
63
from bzrlib.push import (
66
from bzrlib.repofmt import pack_repo
67
from bzrlib.smart.client import _SmartClient
68
from bzrlib.store.versioned import WeaveStore
69
from bzrlib.transactions import WriteTransaction
70
from bzrlib.transport import (
71
do_catching_redirections,
75
from bzrlib.weave import Weave
78
from bzrlib.trace import (
92
"""A .bzr control diretory.
94
BzrDir instances let you create or open any of the things that can be
95
found within .bzr - checkouts, branches and repositories.
98
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
100
a transport connected to the directory this bzr was opened from
101
(i.e. the parent directory holding the .bzr directory).
103
Everything in the bzrdir should have the same file permissions.
105
:cvar hooks: An instance of BzrDirHooks.
108
def break_lock(self):
109
"""Invoke break_lock on the first object in the bzrdir.
111
If there is a tree, the tree is opened and break_lock() called.
112
Otherwise, branch is tried, and finally repository.
114
# XXX: This seems more like a UI function than something that really
115
# belongs in this class.
117
thing_to_unlock = self.open_workingtree()
118
except (errors.NotLocalUrl, errors.NoWorkingTree):
120
thing_to_unlock = self.open_branch()
121
except errors.NotBranchError:
123
thing_to_unlock = self.open_repository()
124
except errors.NoRepositoryPresent:
126
thing_to_unlock.break_lock()
128
def can_convert_format(self):
129
"""Return true if this bzrdir is one whose format we can convert from."""
132
def check_conversion_target(self, target_format):
133
"""Check that a bzrdir as a whole can be converted to a new format."""
134
# The only current restriction is that the repository content can be
135
# fetched compatibly with the target.
136
target_repo_format = target_format.repository_format
138
self.open_repository()._format.check_conversion_target(
140
except errors.NoRepositoryPresent:
141
# No repo, no problem.
145
def _check_supported(format, allow_unsupported,
146
recommend_upgrade=True,
148
"""Give an error or warning on old formats.
150
:param format: may be any kind of format - workingtree, branch,
153
:param allow_unsupported: If true, allow opening
154
formats that are strongly deprecated, and which may
155
have limited functionality.
157
:param recommend_upgrade: If true (default), warn
158
the user through the ui object that they may wish
159
to upgrade the object.
161
# TODO: perhaps move this into a base Format class; it's not BzrDir
162
# specific. mbp 20070323
163
if not allow_unsupported and not format.is_supported():
164
# see open_downlevel to open legacy branches.
165
raise errors.UnsupportedFormatError(format=format)
166
if recommend_upgrade \
167
and getattr(format, 'upgrade_recommended', False):
168
ui.ui_factory.recommend_upgrade(
169
format.get_format_description(),
172
def clone(self, url, revision_id=None, force_new_repo=False,
173
preserve_stacking=False):
174
"""Clone this bzrdir and its contents to url verbatim.
176
:param url: The url create the clone at. If url's last component does
177
not exist, it will be created.
178
:param revision_id: The tip revision-id to use for any branch or
179
working tree. If not None, then the clone operation may tune
180
itself to download less data.
181
:param force_new_repo: Do not use a shared repository for the target
182
even if one is available.
183
:param preserve_stacking: When cloning a stacked branch, stack the
184
new branch on top of the other branch's stacked-on branch.
186
return self.clone_on_transport(get_transport(url),
187
revision_id=revision_id,
188
force_new_repo=force_new_repo,
189
preserve_stacking=preserve_stacking)
191
def clone_on_transport(self, transport, revision_id=None,
192
force_new_repo=False, preserve_stacking=False, stacked_on=None,
193
create_prefix=False, use_existing_dir=True):
194
"""Clone this bzrdir and its contents to transport verbatim.
196
:param transport: The transport for the location to produce the clone
197
at. If the target directory does not exist, it will be created.
198
:param revision_id: The tip revision-id to use for any branch or
199
working tree. If not None, then the clone operation may tune
200
itself to download less data.
201
:param force_new_repo: Do not use a shared repository for the target,
202
even if one is available.
203
:param preserve_stacking: When cloning a stacked branch, stack the
204
new branch on top of the other branch's stacked-on branch.
205
:param create_prefix: Create any missing directories leading up to
207
:param use_existing_dir: Use an existing directory if one exists.
209
# Overview: put together a broad description of what we want to end up
210
# with; then make as few api calls as possible to do it.
212
# We may want to create a repo/branch/tree, if we do so what format
213
# would we want for each:
214
require_stacking = (stacked_on is not None)
215
format = self.cloning_metadir(require_stacking)
217
# Figure out what objects we want:
219
local_repo = self.find_repository()
220
except errors.NoRepositoryPresent:
223
local_branch = self.open_branch()
224
except errors.NotBranchError:
227
# enable fallbacks when branch is not a branch reference
228
if local_branch.repository.has_same_location(local_repo):
229
local_repo = local_branch.repository
230
if preserve_stacking:
232
stacked_on = local_branch.get_stacked_on_url()
233
except (errors.UnstackableBranchFormat,
234
errors.UnstackableRepositoryFormat,
237
# Bug: We create a metadir without knowing if it can support stacking,
238
# we should look up the policy needs first, or just use it as a hint,
241
make_working_trees = local_repo.make_working_trees()
242
want_shared = local_repo.is_shared()
243
repo_format_name = format.repository_format.network_name()
245
make_working_trees = False
247
repo_format_name = None
249
result_repo, result, require_stacking, repository_policy = \
250
format.initialize_on_transport_ex(transport,
251
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
252
force_new_repo=force_new_repo, stacked_on=stacked_on,
253
stack_on_pwd=self.root_transport.base,
254
repo_format_name=repo_format_name,
255
make_working_trees=make_working_trees, shared_repo=want_shared)
258
# If the result repository is in the same place as the
259
# resulting bzr dir, it will have no content, further if the
260
# result is not stacked then we know all content should be
261
# copied, and finally if we are copying up to a specific
262
# revision_id then we can use the pending-ancestry-result which
263
# does not require traversing all of history to describe it.
264
if (result_repo.bzrdir.root_transport.base ==
265
result.root_transport.base and not require_stacking and
266
revision_id is not None):
267
fetch_spec = graph.PendingAncestryResult(
268
[revision_id], local_repo)
269
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
271
result_repo.fetch(local_repo, revision_id=revision_id)
275
if result_repo is not None:
276
raise AssertionError('result_repo not None(%r)' % result_repo)
277
# 1 if there is a branch present
278
# make sure its content is available in the target repository
280
if local_branch is not None:
281
result_branch = local_branch.clone(result, revision_id=revision_id,
282
repository_policy=repository_policy)
284
# Cheaper to check if the target is not local, than to try making
286
result.root_transport.local_abspath('.')
287
if result_repo is None or result_repo.make_working_trees():
288
self.open_workingtree().clone(result)
289
except (errors.NoWorkingTree, errors.NotLocalUrl):
293
# TODO: This should be given a Transport, and should chdir up; otherwise
294
# this will open a new connection.
295
def _make_tail(self, url):
296
t = get_transport(url)
300
def create(cls, base, format=None, possible_transports=None):
301
"""Create a new BzrDir at the url 'base'.
303
:param format: If supplied, the format of branch to create. If not
304
supplied, the default is used.
305
:param possible_transports: If supplied, a list of transports that
306
can be reused to share a remote connection.
308
if cls is not BzrDir:
309
raise AssertionError("BzrDir.create always creates the default"
310
" format, not one of %r" % cls)
311
t = get_transport(base, possible_transports)
314
format = BzrDirFormat.get_default_format()
315
return format.initialize_on_transport(t)
318
def find_bzrdirs(transport, evaluate=None, list_current=None):
319
"""Find bzrdirs recursively from current location.
321
This is intended primarily as a building block for more sophisticated
322
functionality, like finding trees under a directory, or finding
323
branches that use a given repository.
324
:param evaluate: An optional callable that yields recurse, value,
325
where recurse controls whether this bzrdir is recursed into
326
and value is the value to yield. By default, all bzrdirs
327
are recursed into, and the return value is the bzrdir.
328
:param list_current: if supplied, use this function to list the current
329
directory, instead of Transport.list_dir
330
:return: a generator of found bzrdirs, or whatever evaluate returns.
332
if list_current is None:
333
def list_current(transport):
334
return transport.list_dir('')
336
def evaluate(bzrdir):
339
pending = [transport]
340
while len(pending) > 0:
341
current_transport = pending.pop()
344
bzrdir = BzrDir.open_from_transport(current_transport)
345
except errors.NotBranchError:
348
recurse, value = evaluate(bzrdir)
351
subdirs = list_current(current_transport)
352
except errors.NoSuchFile:
355
for subdir in sorted(subdirs, reverse=True):
356
pending.append(current_transport.clone(subdir))
358
def list_branches(self):
359
"""Return a sequence of all branches local to this control directory.
363
return [self.open_branch()]
364
except errors.NotBranchError:
368
def find_branches(transport):
369
"""Find all branches under a transport.
371
This will find all branches below the transport, including branches
372
inside other branches. Where possible, it will use
373
Repository.find_branches.
375
To list all the branches that use a particular Repository, see
376
Repository.find_branches
378
def evaluate(bzrdir):
380
repository = bzrdir.open_repository()
381
except errors.NoRepositoryPresent:
384
return False, ([], repository)
385
return True, (bzrdir.list_branches(), None)
387
for branches, repo in BzrDir.find_bzrdirs(transport,
390
ret.extend(repo.find_branches())
391
if branches is not None:
395
def destroy_repository(self):
396
"""Destroy the repository in this BzrDir"""
397
raise NotImplementedError(self.destroy_repository)
399
def create_branch(self):
400
"""Create a branch in this BzrDir.
402
The bzrdir's format will control what branch format is created.
403
For more control see BranchFormatXX.create(a_bzrdir).
405
raise NotImplementedError(self.create_branch)
407
def destroy_branch(self):
408
"""Destroy the branch in this BzrDir"""
409
raise NotImplementedError(self.destroy_branch)
412
def create_branch_and_repo(base, force_new_repo=False, format=None):
413
"""Create a new BzrDir, Branch and Repository at the url 'base'.
415
This will use the current default BzrDirFormat unless one is
416
specified, and use whatever
417
repository format that that uses via bzrdir.create_branch and
418
create_repository. If a shared repository is available that is used
421
The created Branch object is returned.
423
:param base: The URL to create the branch at.
424
:param force_new_repo: If True a new repository is always created.
425
:param format: If supplied, the format of branch to create. If not
426
supplied, the default is used.
428
bzrdir = BzrDir.create(base, format)
429
bzrdir._find_or_create_repository(force_new_repo)
430
return bzrdir.create_branch()
432
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
433
stack_on_pwd=None, require_stacking=False):
434
"""Return an object representing a policy to use.
436
This controls whether a new repository is created, and the format of
437
that repository, or some existing shared repository used instead.
439
If stack_on is supplied, will not seek a containing shared repo.
441
:param force_new_repo: If True, require a new repository to be created.
442
:param stack_on: If supplied, the location to stack on. If not
443
supplied, a default_stack_on location may be used.
444
:param stack_on_pwd: If stack_on is relative, the location it is
447
def repository_policy(found_bzrdir):
450
config = found_bzrdir.get_config()
452
stack_on = config.get_default_stack_on()
453
if stack_on is not None:
454
stack_on_pwd = found_bzrdir.root_transport.base
456
# does it have a repository ?
458
repository = found_bzrdir.open_repository()
459
except errors.NoRepositoryPresent:
462
if ((found_bzrdir.root_transport.base !=
463
self.root_transport.base) and not repository.is_shared()):
464
# Don't look higher, can't use a higher shared repo.
472
return UseExistingRepository(repository, stack_on,
473
stack_on_pwd, require_stacking=require_stacking), True
475
return CreateRepository(self, stack_on, stack_on_pwd,
476
require_stacking=require_stacking), True
478
if not force_new_repo:
480
policy = self._find_containing(repository_policy)
481
if policy is not None:
485
return UseExistingRepository(self.open_repository(),
486
stack_on, stack_on_pwd,
487
require_stacking=require_stacking)
488
except errors.NoRepositoryPresent:
490
return CreateRepository(self, stack_on, stack_on_pwd,
491
require_stacking=require_stacking)
493
def _find_or_create_repository(self, force_new_repo):
494
"""Create a new repository if needed, returning the repository."""
495
policy = self.determine_repository_policy(force_new_repo)
496
return policy.acquire_repository()[0]
499
def create_branch_convenience(base, force_new_repo=False,
500
force_new_tree=None, format=None,
501
possible_transports=None):
502
"""Create a new BzrDir, Branch and Repository at the url 'base'.
504
This is a convenience function - it will use an existing repository
505
if possible, can be told explicitly whether to create a working tree or
508
This will use the current default BzrDirFormat unless one is
509
specified, and use whatever
510
repository format that that uses via bzrdir.create_branch and
511
create_repository. If a shared repository is available that is used
512
preferentially. Whatever repository is used, its tree creation policy
515
The created Branch object is returned.
516
If a working tree cannot be made due to base not being a file:// url,
517
no error is raised unless force_new_tree is True, in which case no
518
data is created on disk and NotLocalUrl is raised.
520
:param base: The URL to create the branch at.
521
:param force_new_repo: If True a new repository is always created.
522
:param force_new_tree: If True or False force creation of a tree or
523
prevent such creation respectively.
524
:param format: Override for the bzrdir format to create.
525
:param possible_transports: An optional reusable transports list.
528
# check for non local urls
529
t = get_transport(base, possible_transports)
530
if not isinstance(t, local.LocalTransport):
531
raise errors.NotLocalUrl(base)
532
bzrdir = BzrDir.create(base, format, possible_transports)
533
repo = bzrdir._find_or_create_repository(force_new_repo)
534
result = bzrdir.create_branch()
535
if force_new_tree or (repo.make_working_trees() and
536
force_new_tree is None):
538
bzrdir.create_workingtree()
539
except errors.NotLocalUrl:
544
def create_standalone_workingtree(base, format=None):
545
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
547
'base' must be a local path or a file:// url.
549
This will use the current default BzrDirFormat unless one is
550
specified, and use whatever
551
repository format that that uses for bzrdirformat.create_workingtree,
552
create_branch and create_repository.
554
:param format: Override for the bzrdir format to create.
555
:return: The WorkingTree object.
557
t = get_transport(base)
558
if not isinstance(t, local.LocalTransport):
559
raise errors.NotLocalUrl(base)
560
bzrdir = BzrDir.create_branch_and_repo(base,
562
format=format).bzrdir
563
return bzrdir.create_workingtree()
565
def create_workingtree(self, revision_id=None, from_branch=None,
566
accelerator_tree=None, hardlink=False):
567
"""Create a working tree at this BzrDir.
569
:param revision_id: create it as of this revision id.
570
:param from_branch: override bzrdir branch (for lightweight checkouts)
571
:param accelerator_tree: A tree which can be used for retrieving file
572
contents more quickly than the revision tree, i.e. a workingtree.
573
The revision tree will be used for cases where accelerator_tree's
574
content is different.
576
raise NotImplementedError(self.create_workingtree)
578
def backup_bzrdir(self):
579
"""Backup this bzr control directory.
581
:return: Tuple with old path name and new path name
583
def name_gen(base='backup.bzr'):
585
name = "%s.~%d~" % (base, counter)
586
while self.root_transport.has(name):
588
name = "%s.~%d~" % (base, counter)
591
backup_dir=name_gen()
592
pb = ui.ui_factory.nested_progress_bar()
594
# FIXME: bug 300001 -- the backup fails if the backup directory
595
# already exists, but it should instead either remove it or make
596
# a new backup directory.
598
# FIXME: bug 262450 -- the backup directory should have the same
599
# permissions as the .bzr directory (probably a bug in copy_tree)
600
old_path = self.root_transport.abspath('.bzr')
601
new_path = self.root_transport.abspath(backup_dir)
602
ui.ui_factory.note('making backup of %s\n to %s' % (old_path, new_path,))
603
self.root_transport.copy_tree('.bzr', backup_dir)
604
return (old_path, new_path)
608
def retire_bzrdir(self, limit=10000):
609
"""Permanently disable the bzrdir.
611
This is done by renaming it to give the user some ability to recover
612
if there was a problem.
614
This will have horrible consequences if anyone has anything locked or
616
:param limit: number of times to retry
621
to_path = '.bzr.retired.%d' % i
622
self.root_transport.rename('.bzr', to_path)
623
note("renamed %s to %s"
624
% (self.root_transport.abspath('.bzr'), to_path))
626
except (errors.TransportError, IOError, errors.PathError):
633
def destroy_workingtree(self):
634
"""Destroy the working tree at this BzrDir.
636
Formats that do not support this may raise UnsupportedOperation.
638
raise NotImplementedError(self.destroy_workingtree)
640
def destroy_workingtree_metadata(self):
641
"""Destroy the control files for the working tree at this BzrDir.
643
The contents of working tree files are not affected.
644
Formats that do not support this may raise UnsupportedOperation.
646
raise NotImplementedError(self.destroy_workingtree_metadata)
648
def _find_containing(self, evaluate):
649
"""Find something in a containing control directory.
651
This method will scan containing control dirs, until it finds what
652
it is looking for, decides that it will never find it, or runs out
653
of containing control directories to check.
655
It is used to implement find_repository and
656
determine_repository_policy.
658
:param evaluate: A function returning (value, stop). If stop is True,
659
the value will be returned.
663
result, stop = evaluate(found_bzrdir)
666
next_transport = found_bzrdir.root_transport.clone('..')
667
if (found_bzrdir.root_transport.base == next_transport.base):
668
# top of the file system
670
# find the next containing bzrdir
672
found_bzrdir = BzrDir.open_containing_from_transport(
674
except errors.NotBranchError:
677
def find_repository(self):
678
"""Find the repository that should be used.
680
This does not require a branch as we use it to find the repo for
681
new branches as well as to hook existing branches up to their
684
def usable_repository(found_bzrdir):
685
# does it have a repository ?
687
repository = found_bzrdir.open_repository()
688
except errors.NoRepositoryPresent:
690
if found_bzrdir.root_transport.base == self.root_transport.base:
691
return repository, True
692
elif repository.is_shared():
693
return repository, True
697
found_repo = self._find_containing(usable_repository)
698
if found_repo is None:
699
raise errors.NoRepositoryPresent(self)
702
def get_branch_reference(self):
703
"""Return the referenced URL for the branch in this bzrdir.
705
:raises NotBranchError: If there is no Branch.
706
:return: The URL the branch in this bzrdir references if it is a
707
reference branch, or None for regular branches.
711
def get_branch_transport(self, branch_format):
712
"""Get the transport for use by branch format in this BzrDir.
714
Note that bzr dirs that do not support format strings will raise
715
IncompatibleFormat if the branch format they are given has
716
a format string, and vice versa.
718
If branch_format is None, the transport is returned with no
719
checking. If it is not None, then the returned transport is
720
guaranteed to point to an existing directory ready for use.
722
raise NotImplementedError(self.get_branch_transport)
724
def _find_creation_modes(self):
725
"""Determine the appropriate modes for files and directories.
727
They're always set to be consistent with the base directory,
728
assuming that this transport allows setting modes.
730
# TODO: Do we need or want an option (maybe a config setting) to turn
731
# this off or override it for particular locations? -- mbp 20080512
732
if self._mode_check_done:
734
self._mode_check_done = True
736
st = self.transport.stat('.')
737
except errors.TransportNotPossible:
738
self._dir_mode = None
739
self._file_mode = None
741
# Check the directory mode, but also make sure the created
742
# directories and files are read-write for this user. This is
743
# mostly a workaround for filesystems which lie about being able to
744
# write to a directory (cygwin & win32)
745
if (st.st_mode & 07777 == 00000):
746
# FTP allows stat but does not return dir/file modes
747
self._dir_mode = None
748
self._file_mode = None
750
self._dir_mode = (st.st_mode & 07777) | 00700
751
# Remove the sticky and execute bits for files
752
self._file_mode = self._dir_mode & ~07111
754
def _get_file_mode(self):
755
"""Return Unix mode for newly created files, or None.
757
if not self._mode_check_done:
758
self._find_creation_modes()
759
return self._file_mode
761
def _get_dir_mode(self):
762
"""Return Unix mode for newly created directories, or None.
764
if not self._mode_check_done:
765
self._find_creation_modes()
766
return self._dir_mode
768
def get_repository_transport(self, repository_format):
769
"""Get the transport for use by repository format in this BzrDir.
771
Note that bzr dirs that do not support format strings will raise
772
IncompatibleFormat if the repository format they are given has
773
a format string, and vice versa.
775
If repository_format is None, the transport is returned with no
776
checking. If it is not None, then the returned transport is
777
guaranteed to point to an existing directory ready for use.
779
raise NotImplementedError(self.get_repository_transport)
781
def get_workingtree_transport(self, tree_format):
782
"""Get the transport for use by workingtree format in this BzrDir.
784
Note that bzr dirs that do not support format strings will raise
785
IncompatibleFormat if the workingtree format they are given has a
786
format string, and vice versa.
788
If workingtree_format is None, the transport is returned with no
789
checking. If it is not None, then the returned transport is
790
guaranteed to point to an existing directory ready for use.
792
raise NotImplementedError(self.get_workingtree_transport)
794
def get_config(self):
795
"""Get configuration for this BzrDir."""
796
return config.BzrDirConfig(self)
798
def _get_config(self):
799
"""By default, no configuration is available."""
802
def __init__(self, _transport, _format):
803
"""Initialize a Bzr control dir object.
805
Only really common logic should reside here, concrete classes should be
806
made with varying behaviours.
808
:param _format: the format that is creating this BzrDir instance.
809
:param _transport: the transport this dir is based at.
811
self._format = _format
812
self.transport = _transport.clone('.bzr')
813
self.root_transport = _transport
814
self._mode_check_done = False
816
def is_control_filename(self, filename):
817
"""True if filename is the name of a path which is reserved for bzrdir's.
819
:param filename: A filename within the root transport of this bzrdir.
821
This is true IF and ONLY IF the filename is part of the namespace reserved
822
for bzr control dirs. Currently this is the '.bzr' directory in the root
823
of the root_transport. it is expected that plugins will need to extend
824
this in the future - for instance to make bzr talk with svn working
827
# this might be better on the BzrDirFormat class because it refers to
828
# all the possible bzrdir disk formats.
829
# This method is tested via the workingtree is_control_filename tests-
830
# it was extracted from WorkingTree.is_control_filename. If the method's
831
# contract is extended beyond the current trivial implementation, please
832
# add new tests for it to the appropriate place.
833
return filename == '.bzr' or filename.startswith('.bzr/')
835
def needs_format_conversion(self, format=None):
836
"""Return true if this bzrdir needs convert_format run on it.
838
For instance, if the repository format is out of date but the
839
branch and working tree are not, this should return True.
841
:param format: Optional parameter indicating a specific desired
842
format we plan to arrive at.
844
raise NotImplementedError(self.needs_format_conversion)
847
def open_unsupported(base):
848
"""Open a branch which is not supported."""
849
return BzrDir.open(base, _unsupported=True)
852
def open(base, _unsupported=False, possible_transports=None):
853
"""Open an existing bzrdir, rooted at 'base' (url).
855
:param _unsupported: a private parameter to the BzrDir class.
857
t = get_transport(base, possible_transports=possible_transports)
858
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
861
def open_from_transport(transport, _unsupported=False,
862
_server_formats=True):
863
"""Open a bzrdir within a particular directory.
865
:param transport: Transport containing the bzrdir.
866
:param _unsupported: private.
868
for hook in BzrDir.hooks['pre_open']:
870
# Keep initial base since 'transport' may be modified while following
872
base = transport.base
873
def find_format(transport):
874
return transport, BzrDirFormat.find_format(
875
transport, _server_formats=_server_formats)
877
def redirected(transport, e, redirection_notice):
878
redirected_transport = transport._redirected_to(e.source, e.target)
879
if redirected_transport is None:
880
raise errors.NotBranchError(base)
881
note('%s is%s redirected to %s',
882
transport.base, e.permanently, redirected_transport.base)
883
return redirected_transport
886
transport, format = do_catching_redirections(find_format,
889
except errors.TooManyRedirections:
890
raise errors.NotBranchError(base)
892
BzrDir._check_supported(format, _unsupported)
893
return format.open(transport, _found=True)
895
def open_branch(self, unsupported=False, ignore_fallbacks=False):
896
"""Open the branch object at this BzrDir if one is present.
898
If unsupported is True, then no longer supported branch formats can
901
TODO: static convenience version of this?
903
raise NotImplementedError(self.open_branch)
906
def open_containing(url, possible_transports=None):
907
"""Open an existing branch which contains url.
909
:param url: url to search from.
910
See open_containing_from_transport for more detail.
912
transport = get_transport(url, possible_transports)
913
return BzrDir.open_containing_from_transport(transport)
916
def open_containing_from_transport(a_transport):
917
"""Open an existing branch which contains a_transport.base.
919
This probes for a branch at a_transport, and searches upwards from there.
921
Basically we keep looking up until we find the control directory or
922
run into the root. If there isn't one, raises NotBranchError.
923
If there is one and it is either an unrecognised format or an unsupported
924
format, UnknownFormatError or UnsupportedFormatError are raised.
925
If there is one, it is returned, along with the unused portion of url.
927
:return: The BzrDir that contains the path, and a Unicode path
928
for the rest of the URL.
930
# this gets the normalised url back. I.e. '.' -> the full path.
931
url = a_transport.base
934
result = BzrDir.open_from_transport(a_transport)
935
return result, urlutils.unescape(a_transport.relpath(url))
936
except errors.NotBranchError, e:
939
new_t = a_transport.clone('..')
940
except errors.InvalidURLJoin:
941
# reached the root, whatever that may be
942
raise errors.NotBranchError(path=url)
943
if new_t.base == a_transport.base:
944
# reached the root, whatever that may be
945
raise errors.NotBranchError(path=url)
948
def _get_tree_branch(self):
949
"""Return the branch and tree, if any, for this bzrdir.
951
Return None for tree if not present or inaccessible.
952
Raise NotBranchError if no branch is present.
953
:return: (tree, branch)
956
tree = self.open_workingtree()
957
except (errors.NoWorkingTree, errors.NotLocalUrl):
959
branch = self.open_branch()
965
def open_tree_or_branch(klass, location):
966
"""Return the branch and working tree at a location.
968
If there is no tree at the location, tree will be None.
969
If there is no branch at the location, an exception will be
971
:return: (tree, branch)
973
bzrdir = klass.open(location)
974
return bzrdir._get_tree_branch()
977
def open_containing_tree_or_branch(klass, location):
978
"""Return the branch and working tree contained by a location.
980
Returns (tree, branch, relpath).
981
If there is no tree at containing the location, tree will be None.
982
If there is no branch containing the location, an exception will be
984
relpath is the portion of the path that is contained by the branch.
986
bzrdir, relpath = klass.open_containing(location)
987
tree, branch = bzrdir._get_tree_branch()
988
return tree, branch, relpath
991
def open_containing_tree_branch_or_repository(klass, location):
992
"""Return the working tree, branch and repo contained by a location.
994
Returns (tree, branch, repository, relpath).
995
If there is no tree containing the location, tree will be None.
996
If there is no branch containing the location, branch will be None.
997
If there is no repository containing the location, repository will be
999
relpath is the portion of the path that is contained by the innermost
1002
If no tree, branch or repository is found, a NotBranchError is raised.
1004
bzrdir, relpath = klass.open_containing(location)
1006
tree, branch = bzrdir._get_tree_branch()
1007
except errors.NotBranchError:
1009
repo = bzrdir.find_repository()
1010
return None, None, repo, relpath
1011
except (errors.NoRepositoryPresent):
1012
raise errors.NotBranchError(location)
1013
return tree, branch, branch.repository, relpath
1015
def open_repository(self, _unsupported=False):
1016
"""Open the repository object at this BzrDir if one is present.
1018
This will not follow the Branch object pointer - it's strictly a direct
1019
open facility. Most client code should use open_branch().repository to
1020
get at a repository.
1022
:param _unsupported: a private parameter, not part of the api.
1023
TODO: static convenience version of this?
1025
raise NotImplementedError(self.open_repository)
1027
def open_workingtree(self, _unsupported=False,
1028
recommend_upgrade=True, from_branch=None):
1029
"""Open the workingtree object at this BzrDir if one is present.
1031
:param recommend_upgrade: Optional keyword parameter, when True (the
1032
default), emit through the ui module a recommendation that the user
1033
upgrade the working tree when the workingtree being opened is old
1034
(but still fully supported).
1035
:param from_branch: override bzrdir branch (for lightweight checkouts)
1037
raise NotImplementedError(self.open_workingtree)
1039
def has_branch(self):
1040
"""Tell if this bzrdir contains a branch.
1042
Note: if you're going to open the branch, you should just go ahead
1043
and try, and not ask permission first. (This method just opens the
1044
branch and discards it, and that's somewhat expensive.)
1049
except errors.NotBranchError:
1052
def has_workingtree(self):
1053
"""Tell if this bzrdir contains a working tree.
1055
This will still raise an exception if the bzrdir has a workingtree that
1056
is remote & inaccessible.
1058
Note: if you're going to open the working tree, you should just go ahead
1059
and try, and not ask permission first. (This method just opens the
1060
workingtree and discards it, and that's somewhat expensive.)
1063
self.open_workingtree(recommend_upgrade=False)
1065
except errors.NoWorkingTree:
1068
def _cloning_metadir(self):
1069
"""Produce a metadir suitable for cloning with.
1071
:returns: (destination_bzrdir_format, source_repository)
1073
result_format = self._format.__class__()
1076
branch = self.open_branch(ignore_fallbacks=True)
1077
source_repository = branch.repository
1078
result_format._branch_format = branch._format
1079
except errors.NotBranchError:
1080
source_branch = None
1081
source_repository = self.open_repository()
1082
except errors.NoRepositoryPresent:
1083
source_repository = None
1085
# XXX TODO: This isinstance is here because we have not implemented
1086
# the fix recommended in bug # 103195 - to delegate this choice the
1087
# repository itself.
1088
repo_format = source_repository._format
1089
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1090
source_repository._ensure_real()
1091
repo_format = source_repository._real_repository._format
1092
result_format.repository_format = repo_format
1094
# TODO: Couldn't we just probe for the format in these cases,
1095
# rather than opening the whole tree? It would be a little
1096
# faster. mbp 20070401
1097
tree = self.open_workingtree(recommend_upgrade=False)
1098
except (errors.NoWorkingTree, errors.NotLocalUrl):
1099
result_format.workingtree_format = None
1101
result_format.workingtree_format = tree._format.__class__()
1102
return result_format, source_repository
1104
def cloning_metadir(self, require_stacking=False):
1105
"""Produce a metadir suitable for cloning or sprouting with.
1107
These operations may produce workingtrees (yes, even though they're
1108
"cloning" something that doesn't have a tree), so a viable workingtree
1109
format must be selected.
1111
:require_stacking: If True, non-stackable formats will be upgraded
1112
to similar stackable formats.
1113
:returns: a BzrDirFormat with all component formats either set
1114
appropriately or set to None if that component should not be
1117
format, repository = self._cloning_metadir()
1118
if format._workingtree_format is None:
1120
if repository is None:
1121
# No repository either
1123
# We have a repository, so set a working tree? (Why? This seems to
1124
# contradict the stated return value in the docstring).
1125
tree_format = repository._format._matchingbzrdir.workingtree_format
1126
format.workingtree_format = tree_format.__class__()
1127
if require_stacking:
1128
format.require_stacking()
1131
def checkout_metadir(self):
1132
return self.cloning_metadir()
1134
def sprout(self, url, revision_id=None, force_new_repo=False,
1135
recurse='down', possible_transports=None,
1136
accelerator_tree=None, hardlink=False, stacked=False,
1137
source_branch=None, create_tree_if_local=True):
1138
"""Create a copy of this bzrdir prepared for use as a new line of
1141
If url's last component does not exist, it will be created.
1143
Attributes related to the identity of the source branch like
1144
branch nickname will be cleaned, a working tree is created
1145
whether one existed before or not; and a local branch is always
1148
if revision_id is not None, then the clone operation may tune
1149
itself to download less data.
1150
:param accelerator_tree: A tree which can be used for retrieving file
1151
contents more quickly than the revision tree, i.e. a workingtree.
1152
The revision tree will be used for cases where accelerator_tree's
1153
content is different.
1154
:param hardlink: If true, hard-link files from accelerator_tree,
1156
:param stacked: If true, create a stacked branch referring to the
1157
location of this control directory.
1158
:param create_tree_if_local: If true, a working-tree will be created
1159
when working locally.
1161
target_transport = get_transport(url, possible_transports)
1162
target_transport.ensure_base()
1163
cloning_format = self.cloning_metadir(stacked)
1164
# Create/update the result branch
1165
result = cloning_format.initialize_on_transport(target_transport)
1166
# if a stacked branch wasn't requested, we don't create one
1167
# even if the origin was stacked
1168
stacked_branch_url = None
1169
if source_branch is not None:
1171
stacked_branch_url = self.root_transport.base
1172
source_repository = source_branch.repository
1175
source_branch = self.open_branch()
1176
source_repository = source_branch.repository
1178
stacked_branch_url = self.root_transport.base
1179
except errors.NotBranchError:
1180
source_branch = None
1182
source_repository = self.open_repository()
1183
except errors.NoRepositoryPresent:
1184
source_repository = None
1185
repository_policy = result.determine_repository_policy(
1186
force_new_repo, stacked_branch_url, require_stacking=stacked)
1187
result_repo, is_new_repo = repository_policy.acquire_repository()
1188
if is_new_repo and revision_id is not None and not stacked:
1189
fetch_spec = graph.PendingAncestryResult(
1190
[revision_id], source_repository)
1193
if source_repository is not None:
1194
# Fetch while stacked to prevent unstacked fetch from
1196
if fetch_spec is None:
1197
result_repo.fetch(source_repository, revision_id=revision_id)
1199
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
1201
if source_branch is None:
1202
# this is for sprouting a bzrdir without a branch; is that
1204
# Not especially, but it's part of the contract.
1205
result_branch = result.create_branch()
1207
result_branch = source_branch.sprout(result,
1208
revision_id=revision_id, repository_policy=repository_policy)
1209
mutter("created new branch %r" % (result_branch,))
1211
# Create/update the result working tree
1212
if (create_tree_if_local and
1213
isinstance(target_transport, local.LocalTransport) and
1214
(result_repo is None or result_repo.make_working_trees())):
1215
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1219
if wt.path2id('') is None:
1221
wt.set_root_id(self.open_workingtree.get_root_id())
1222
except errors.NoWorkingTree:
1228
if recurse == 'down':
1230
basis = wt.basis_tree()
1232
subtrees = basis.iter_references()
1233
elif result_branch is not None:
1234
basis = result_branch.basis_tree()
1236
subtrees = basis.iter_references()
1237
elif source_branch is not None:
1238
basis = source_branch.basis_tree()
1240
subtrees = basis.iter_references()
1245
for path, file_id in subtrees:
1246
target = urlutils.join(url, urlutils.escape(path))
1247
sublocation = source_branch.reference_parent(file_id, path)
1248
sublocation.bzrdir.sprout(target,
1249
basis.get_reference_revision(file_id, path),
1250
force_new_repo=force_new_repo, recurse=recurse,
1253
if basis is not None:
1257
def push_branch(self, source, revision_id=None, overwrite=False,
1258
remember=False, create_prefix=False):
1259
"""Push the source branch into this BzrDir."""
1261
# If we can open a branch, use its direct repository, otherwise see
1262
# if there is a repository without a branch.
1264
br_to = self.open_branch()
1265
except errors.NotBranchError:
1266
# Didn't find a branch, can we find a repository?
1267
repository_to = self.find_repository()
1269
# Found a branch, so we must have found a repository
1270
repository_to = br_to.repository
1272
push_result = PushResult()
1273
push_result.source_branch = source
1275
# We have a repository but no branch, copy the revisions, and then
1277
repository_to.fetch(source.repository, revision_id=revision_id)
1278
br_to = source.clone(self, revision_id=revision_id)
1279
if source.get_push_location() is None or remember:
1280
source.set_push_location(br_to.base)
1281
push_result.stacked_on = None
1282
push_result.branch_push_result = None
1283
push_result.old_revno = None
1284
push_result.old_revid = _mod_revision.NULL_REVISION
1285
push_result.target_branch = br_to
1286
push_result.master_branch = None
1287
push_result.workingtree_updated = False
1289
# We have successfully opened the branch, remember if necessary:
1290
if source.get_push_location() is None or remember:
1291
source.set_push_location(br_to.base)
1293
tree_to = self.open_workingtree()
1294
except errors.NotLocalUrl:
1295
push_result.branch_push_result = source.push(br_to,
1296
overwrite, stop_revision=revision_id)
1297
push_result.workingtree_updated = False
1298
except errors.NoWorkingTree:
1299
push_result.branch_push_result = source.push(br_to,
1300
overwrite, stop_revision=revision_id)
1301
push_result.workingtree_updated = None # Not applicable
1303
tree_to.lock_write()
1305
push_result.branch_push_result = source.push(
1306
tree_to.branch, overwrite, stop_revision=revision_id)
1310
push_result.workingtree_updated = True
1311
push_result.old_revno = push_result.branch_push_result.old_revno
1312
push_result.old_revid = push_result.branch_push_result.old_revid
1313
push_result.target_branch = \
1314
push_result.branch_push_result.target_branch
1318
class BzrDirHooks(hooks.Hooks):
1319
"""Hooks for BzrDir operations."""
1322
"""Create the default hooks."""
1323
hooks.Hooks.__init__(self)
1324
self.create_hook(hooks.HookPoint('pre_open',
1325
"Invoked before attempting to open a BzrDir with the transport "
1326
"that the open will use.", (1, 14), None))
1328
# install the default hooks
1329
BzrDir.hooks = BzrDirHooks()
1332
class BzrDirPreSplitOut(BzrDir):
1333
"""A common class for the all-in-one formats."""
1335
def __init__(self, _transport, _format):
1336
"""See BzrDir.__init__."""
1337
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1338
self._control_files = lockable_files.LockableFiles(
1339
self.get_branch_transport(None),
1340
self._format._lock_file_name,
1341
self._format._lock_class)
1343
def break_lock(self):
1344
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1345
raise NotImplementedError(self.break_lock)
1347
def cloning_metadir(self, require_stacking=False):
1348
"""Produce a metadir suitable for cloning with."""
1349
if require_stacking:
1350
return format_registry.make_bzrdir('1.6')
1351
return self._format.__class__()
1353
def clone(self, url, revision_id=None, force_new_repo=False,
1354
preserve_stacking=False):
1355
"""See BzrDir.clone().
1357
force_new_repo has no effect, since this family of formats always
1358
require a new repository.
1359
preserve_stacking has no effect, since no source branch using this
1360
family of formats can be stacked, so there is no stacking to preserve.
1362
self._make_tail(url)
1363
result = self._format._initialize_for_clone(url)
1364
self.open_repository().clone(result, revision_id=revision_id)
1365
from_branch = self.open_branch()
1366
from_branch.clone(result, revision_id=revision_id)
1368
tree = self.open_workingtree()
1369
except errors.NotLocalUrl:
1370
# make a new one, this format always has to have one.
1371
result._init_workingtree()
1376
def create_branch(self):
1377
"""See BzrDir.create_branch."""
1378
return self._format.get_branch_format().initialize(self)
1380
def destroy_branch(self):
1381
"""See BzrDir.destroy_branch."""
1382
raise errors.UnsupportedOperation(self.destroy_branch, self)
1384
def create_repository(self, shared=False):
1385
"""See BzrDir.create_repository."""
1387
raise errors.IncompatibleFormat('shared repository', self._format)
1388
return self.open_repository()
1390
def destroy_repository(self):
1391
"""See BzrDir.destroy_repository."""
1392
raise errors.UnsupportedOperation(self.destroy_repository, self)
1394
def create_workingtree(self, revision_id=None, from_branch=None,
1395
accelerator_tree=None, hardlink=False):
1396
"""See BzrDir.create_workingtree."""
1397
# The workingtree is sometimes created when the bzrdir is created,
1398
# but not when cloning.
1400
# this looks buggy but is not -really-
1401
# because this format creates the workingtree when the bzrdir is
1403
# clone and sprout will have set the revision_id
1404
# and that will have set it for us, its only
1405
# specific uses of create_workingtree in isolation
1406
# that can do wonky stuff here, and that only
1407
# happens for creating checkouts, which cannot be
1408
# done on this format anyway. So - acceptable wart.
1410
warning("can't support hardlinked working trees in %r"
1413
result = self.open_workingtree(recommend_upgrade=False)
1414
except errors.NoSuchFile:
1415
result = self._init_workingtree()
1416
if revision_id is not None:
1417
if revision_id == _mod_revision.NULL_REVISION:
1418
result.set_parent_ids([])
1420
result.set_parent_ids([revision_id])
1423
def _init_workingtree(self):
1424
from bzrlib.workingtree import WorkingTreeFormat2
1426
return WorkingTreeFormat2().initialize(self)
1427
except errors.NotLocalUrl:
1428
# Even though we can't access the working tree, we need to
1429
# create its control files.
1430
return WorkingTreeFormat2()._stub_initialize_on_transport(
1431
self.transport, self._control_files._file_mode)
1433
def destroy_workingtree(self):
1434
"""See BzrDir.destroy_workingtree."""
1435
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1437
def destroy_workingtree_metadata(self):
1438
"""See BzrDir.destroy_workingtree_metadata."""
1439
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1442
def get_branch_transport(self, branch_format):
1443
"""See BzrDir.get_branch_transport()."""
1444
if branch_format is None:
1445
return self.transport
1447
branch_format.get_format_string()
1448
except NotImplementedError:
1449
return self.transport
1450
raise errors.IncompatibleFormat(branch_format, self._format)
1452
def get_repository_transport(self, repository_format):
1453
"""See BzrDir.get_repository_transport()."""
1454
if repository_format is None:
1455
return self.transport
1457
repository_format.get_format_string()
1458
except NotImplementedError:
1459
return self.transport
1460
raise errors.IncompatibleFormat(repository_format, self._format)
1462
def get_workingtree_transport(self, workingtree_format):
1463
"""See BzrDir.get_workingtree_transport()."""
1464
if workingtree_format is None:
1465
return self.transport
1467
workingtree_format.get_format_string()
1468
except NotImplementedError:
1469
return self.transport
1470
raise errors.IncompatibleFormat(workingtree_format, self._format)
1472
def needs_format_conversion(self, format=None):
1473
"""See BzrDir.needs_format_conversion()."""
1474
# if the format is not the same as the system default,
1475
# an upgrade is needed.
1477
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1478
% 'needs_format_conversion(format=None)')
1479
format = BzrDirFormat.get_default_format()
1480
return not isinstance(self._format, format.__class__)
1482
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1483
"""See BzrDir.open_branch."""
1484
from bzrlib.branch import BzrBranchFormat4
1485
format = BzrBranchFormat4()
1486
self._check_supported(format, unsupported)
1487
return format.open(self, _found=True)
1489
def sprout(self, url, revision_id=None, force_new_repo=False,
1490
possible_transports=None, accelerator_tree=None,
1491
hardlink=False, stacked=False, create_tree_if_local=True,
1492
source_branch=None):
1493
"""See BzrDir.sprout()."""
1494
if source_branch is not None:
1495
my_branch = self.open_branch()
1496
if source_branch.base != my_branch.base:
1497
raise AssertionError(
1498
"source branch %r is not within %r with branch %r" %
1499
(source_branch, self, my_branch))
1501
raise errors.UnstackableBranchFormat(
1502
self._format, self.root_transport.base)
1503
if not create_tree_if_local:
1504
raise errors.MustHaveWorkingTree(
1505
self._format, self.root_transport.base)
1506
from bzrlib.workingtree import WorkingTreeFormat2
1507
self._make_tail(url)
1508
result = self._format._initialize_for_clone(url)
1510
self.open_repository().clone(result, revision_id=revision_id)
1511
except errors.NoRepositoryPresent:
1514
self.open_branch().sprout(result, revision_id=revision_id)
1515
except errors.NotBranchError:
1518
# we always want a working tree
1519
WorkingTreeFormat2().initialize(result,
1520
accelerator_tree=accelerator_tree,
1525
class BzrDir4(BzrDirPreSplitOut):
1526
"""A .bzr version 4 control object.
1528
This is a deprecated format and may be removed after sept 2006.
1531
def create_repository(self, shared=False):
1532
"""See BzrDir.create_repository."""
1533
return self._format.repository_format.initialize(self, shared)
1535
def needs_format_conversion(self, format=None):
1536
"""Format 4 dirs are always in need of conversion."""
1538
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1539
% 'needs_format_conversion(format=None)')
1542
def open_repository(self):
1543
"""See BzrDir.open_repository."""
1544
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1545
return RepositoryFormat4().open(self, _found=True)
1548
class BzrDir5(BzrDirPreSplitOut):
1549
"""A .bzr version 5 control object.
1551
This is a deprecated format and may be removed after sept 2006.
1554
def has_workingtree(self):
1555
"""See BzrDir.has_workingtree."""
1558
def open_repository(self):
1559
"""See BzrDir.open_repository."""
1560
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1561
return RepositoryFormat5().open(self, _found=True)
1563
def open_workingtree(self, _unsupported=False,
1564
recommend_upgrade=True):
1565
"""See BzrDir.create_workingtree."""
1566
from bzrlib.workingtree import WorkingTreeFormat2
1567
wt_format = WorkingTreeFormat2()
1568
# we don't warn here about upgrades; that ought to be handled for the
1570
return wt_format.open(self, _found=True)
1573
class BzrDir6(BzrDirPreSplitOut):
1574
"""A .bzr version 6 control object.
1576
This is a deprecated format and may be removed after sept 2006.
1579
def has_workingtree(self):
1580
"""See BzrDir.has_workingtree."""
1583
def open_repository(self):
1584
"""See BzrDir.open_repository."""
1585
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1586
return RepositoryFormat6().open(self, _found=True)
1588
def open_workingtree(self, _unsupported=False,
1589
recommend_upgrade=True):
1590
"""See BzrDir.create_workingtree."""
1591
# we don't warn here about upgrades; that ought to be handled for the
1593
from bzrlib.workingtree import WorkingTreeFormat2
1594
return WorkingTreeFormat2().open(self, _found=True)
1597
class BzrDirMeta1(BzrDir):
1598
"""A .bzr meta version 1 control object.
1600
This is the first control object where the
1601
individual aspects are really split out: there are separate repository,
1602
workingtree and branch subdirectories and any subset of the three can be
1603
present within a BzrDir.
1606
def can_convert_format(self):
1607
"""See BzrDir.can_convert_format()."""
1610
def create_branch(self):
1611
"""See BzrDir.create_branch."""
1612
return self._format.get_branch_format().initialize(self)
1614
def destroy_branch(self):
1615
"""See BzrDir.create_branch."""
1616
self.transport.delete_tree('branch')
1618
def create_repository(self, shared=False):
1619
"""See BzrDir.create_repository."""
1620
return self._format.repository_format.initialize(self, shared)
1622
def destroy_repository(self):
1623
"""See BzrDir.destroy_repository."""
1624
self.transport.delete_tree('repository')
1626
def create_workingtree(self, revision_id=None, from_branch=None,
1627
accelerator_tree=None, hardlink=False):
1628
"""See BzrDir.create_workingtree."""
1629
return self._format.workingtree_format.initialize(
1630
self, revision_id, from_branch=from_branch,
1631
accelerator_tree=accelerator_tree, hardlink=hardlink)
1633
def destroy_workingtree(self):
1634
"""See BzrDir.destroy_workingtree."""
1635
wt = self.open_workingtree(recommend_upgrade=False)
1636
repository = wt.branch.repository
1637
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1638
wt.revert(old_tree=empty)
1639
self.destroy_workingtree_metadata()
1641
def destroy_workingtree_metadata(self):
1642
self.transport.delete_tree('checkout')
1644
def find_branch_format(self):
1645
"""Find the branch 'format' for this bzrdir.
1647
This might be a synthetic object for e.g. RemoteBranch and SVN.
1649
from bzrlib.branch import BranchFormat
1650
return BranchFormat.find_format(self)
1652
def _get_mkdir_mode(self):
1653
"""Figure out the mode to use when creating a bzrdir subdir."""
1654
temp_control = lockable_files.LockableFiles(self.transport, '',
1655
lockable_files.TransportLock)
1656
return temp_control._dir_mode
1658
def get_branch_reference(self):
1659
"""See BzrDir.get_branch_reference()."""
1660
from bzrlib.branch import BranchFormat
1661
format = BranchFormat.find_format(self)
1662
return format.get_reference(self)
1664
def get_branch_transport(self, branch_format):
1665
"""See BzrDir.get_branch_transport()."""
1666
# XXX: this shouldn't implicitly create the directory if it's just
1667
# promising to get a transport -- mbp 20090727
1668
if branch_format is None:
1669
return self.transport.clone('branch')
1671
branch_format.get_format_string()
1672
except NotImplementedError:
1673
raise errors.IncompatibleFormat(branch_format, self._format)
1675
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1676
except errors.FileExists:
1678
return self.transport.clone('branch')
1680
def get_repository_transport(self, repository_format):
1681
"""See BzrDir.get_repository_transport()."""
1682
if repository_format is None:
1683
return self.transport.clone('repository')
1685
repository_format.get_format_string()
1686
except NotImplementedError:
1687
raise errors.IncompatibleFormat(repository_format, self._format)
1689
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1690
except errors.FileExists:
1692
return self.transport.clone('repository')
1694
def get_workingtree_transport(self, workingtree_format):
1695
"""See BzrDir.get_workingtree_transport()."""
1696
if workingtree_format is None:
1697
return self.transport.clone('checkout')
1699
workingtree_format.get_format_string()
1700
except NotImplementedError:
1701
raise errors.IncompatibleFormat(workingtree_format, self._format)
1703
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1704
except errors.FileExists:
1706
return self.transport.clone('checkout')
1708
def has_workingtree(self):
1709
"""Tell if this bzrdir contains a working tree.
1711
This will still raise an exception if the bzrdir has a workingtree that
1712
is remote & inaccessible.
1714
Note: if you're going to open the working tree, you should just go
1715
ahead and try, and not ask permission first.
1717
from bzrlib.workingtree import WorkingTreeFormat
1719
WorkingTreeFormat.find_format(self)
1720
except errors.NoWorkingTree:
1724
def needs_format_conversion(self, format=None):
1725
"""See BzrDir.needs_format_conversion()."""
1727
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1728
% 'needs_format_conversion(format=None)')
1730
format = BzrDirFormat.get_default_format()
1731
if not isinstance(self._format, format.__class__):
1732
# it is not a meta dir format, conversion is needed.
1734
# we might want to push this down to the repository?
1736
if not isinstance(self.open_repository()._format,
1737
format.repository_format.__class__):
1738
# the repository needs an upgrade.
1740
except errors.NoRepositoryPresent:
1743
if not isinstance(self.open_branch()._format,
1744
format.get_branch_format().__class__):
1745
# the branch needs an upgrade.
1747
except errors.NotBranchError:
1750
my_wt = self.open_workingtree(recommend_upgrade=False)
1751
if not isinstance(my_wt._format,
1752
format.workingtree_format.__class__):
1753
# the workingtree needs an upgrade.
1755
except (errors.NoWorkingTree, errors.NotLocalUrl):
1759
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1760
"""See BzrDir.open_branch."""
1761
format = self.find_branch_format()
1762
self._check_supported(format, unsupported)
1763
return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1765
def open_repository(self, unsupported=False):
1766
"""See BzrDir.open_repository."""
1767
from bzrlib.repository import RepositoryFormat
1768
format = RepositoryFormat.find_format(self)
1769
self._check_supported(format, unsupported)
1770
return format.open(self, _found=True)
1772
def open_workingtree(self, unsupported=False,
1773
recommend_upgrade=True):
1774
"""See BzrDir.open_workingtree."""
1775
from bzrlib.workingtree import WorkingTreeFormat
1776
format = WorkingTreeFormat.find_format(self)
1777
self._check_supported(format, unsupported,
1779
basedir=self.root_transport.base)
1780
return format.open(self, _found=True)
1782
def _get_config(self):
1783
return config.TransportConfig(self.transport, 'control.conf')
1786
class BzrDirFormat(object):
1787
"""An encapsulation of the initialization and open routines for a format.
1789
Formats provide three things:
1790
* An initialization routine,
1794
Formats are placed in a dict by their format string for reference
1795
during bzrdir opening. These should be subclasses of BzrDirFormat
1798
Once a format is deprecated, just deprecate the initialize and open
1799
methods on the format class. Do not deprecate the object, as the
1800
object will be created every system load.
1803
_default_format = None
1804
"""The default format used for new .bzr dirs."""
1807
"""The known formats."""
1809
_control_formats = []
1810
"""The registered control formats - .bzr, ....
1812
This is a list of BzrDirFormat objects.
1815
_control_server_formats = []
1816
"""The registered control server formats, e.g. RemoteBzrDirs.
1818
This is a list of BzrDirFormat objects.
1821
_lock_file_name = 'branch-lock'
1823
# _lock_class must be set in subclasses to the lock type, typ.
1824
# TransportLock or LockDir
1827
def find_format(klass, transport, _server_formats=True):
1828
"""Return the format present at transport."""
1830
formats = klass._control_server_formats + klass._control_formats
1832
formats = klass._control_formats
1833
for format in formats:
1835
return format.probe_transport(transport)
1836
except errors.NotBranchError:
1837
# this format does not find a control dir here.
1839
raise errors.NotBranchError(path=transport.base)
1842
def probe_transport(klass, transport):
1843
"""Return the .bzrdir style format present in a directory."""
1845
format_string = transport.get_bytes(".bzr/branch-format")
1846
except errors.NoSuchFile:
1847
raise errors.NotBranchError(path=transport.base)
1850
return klass._formats[format_string]
1852
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1855
def get_default_format(klass):
1856
"""Return the current default format."""
1857
return klass._default_format
1859
def get_format_string(self):
1860
"""Return the ASCII format string that identifies this format."""
1861
raise NotImplementedError(self.get_format_string)
1863
def get_format_description(self):
1864
"""Return the short description for this format."""
1865
raise NotImplementedError(self.get_format_description)
1867
def get_converter(self, format=None):
1868
"""Return the converter to use to convert bzrdirs needing converts.
1870
This returns a bzrlib.bzrdir.Converter object.
1872
This should return the best upgrader to step this format towards the
1873
current default format. In the case of plugins we can/should provide
1874
some means for them to extend the range of returnable converters.
1876
:param format: Optional format to override the default format of the
1879
raise NotImplementedError(self.get_converter)
1881
def initialize(self, url, possible_transports=None):
1882
"""Create a bzr control dir at this url and return an opened copy.
1884
While not deprecated, this method is very specific and its use will
1885
lead to many round trips to setup a working environment. See
1886
initialize_on_transport_ex for a [nearly] all-in-one method.
1888
Subclasses should typically override initialize_on_transport
1889
instead of this method.
1891
return self.initialize_on_transport(get_transport(url,
1892
possible_transports))
1894
def initialize_on_transport(self, transport):
1895
"""Initialize a new bzrdir in the base directory of a Transport."""
1897
# can we hand off the request to the smart server rather than using
1899
client_medium = transport.get_smart_medium()
1900
except errors.NoSmartMedium:
1901
return self._initialize_on_transport_vfs(transport)
1903
# Current RPC's only know how to create bzr metadir1 instances, so
1904
# we still delegate to vfs methods if the requested format is not a
1906
if type(self) != BzrDirMetaFormat1:
1907
return self._initialize_on_transport_vfs(transport)
1908
remote_format = RemoteBzrDirFormat()
1909
self._supply_sub_formats_to(remote_format)
1910
return remote_format.initialize_on_transport(transport)
1912
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1913
create_prefix=False, force_new_repo=False, stacked_on=None,
1914
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1915
shared_repo=False, vfs_only=False):
1916
"""Create this format on transport.
1918
The directory to initialize will be created.
1920
:param force_new_repo: Do not use a shared repository for the target,
1921
even if one is available.
1922
:param create_prefix: Create any missing directories leading up to
1924
:param use_existing_dir: Use an existing directory if one exists.
1925
:param stacked_on: A url to stack any created branch on, None to follow
1926
any target stacking policy.
1927
:param stack_on_pwd: If stack_on is relative, the location it is
1929
:param repo_format_name: If non-None, a repository will be
1930
made-or-found. Should none be found, or if force_new_repo is True
1931
the repo_format_name is used to select the format of repository to
1933
:param make_working_trees: Control the setting of make_working_trees
1934
for a new shared repository when one is made. None to use whatever
1935
default the format has.
1936
:param shared_repo: Control whether made repositories are shared or
1938
:param vfs_only: If True do not attempt to use a smart server
1939
:return: repo, bzrdir, require_stacking, repository_policy. repo is
1940
None if none was created or found, bzrdir is always valid.
1941
require_stacking is the result of examining the stacked_on
1942
parameter and any stacking policy found for the target.
1945
# Try to hand off to a smart server
1947
client_medium = transport.get_smart_medium()
1948
except errors.NoSmartMedium:
1951
# TODO: lookup the local format from a server hint.
1952
remote_dir_format = RemoteBzrDirFormat()
1953
remote_dir_format._network_name = self.network_name()
1954
self._supply_sub_formats_to(remote_dir_format)
1955
return remote_dir_format.initialize_on_transport_ex(transport,
1956
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1957
force_new_repo=force_new_repo, stacked_on=stacked_on,
1958
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1959
make_working_trees=make_working_trees, shared_repo=shared_repo)
1960
# XXX: Refactor the create_prefix/no_create_prefix code into a
1961
# common helper function
1962
# The destination may not exist - if so make it according to policy.
1963
def make_directory(transport):
1964
transport.mkdir('.')
1966
def redirected(transport, e, redirection_notice):
1967
note(redirection_notice)
1968
return transport._redirected_to(e.source, e.target)
1970
transport = do_catching_redirections(make_directory, transport,
1972
except errors.FileExists:
1973
if not use_existing_dir:
1975
except errors.NoSuchFile:
1976
if not create_prefix:
1978
transport.create_prefix()
1980
require_stacking = (stacked_on is not None)
1981
# Now the target directory exists, but doesn't have a .bzr
1982
# directory. So we need to create it, along with any work to create
1983
# all of the dependent branches, etc.
1985
result = self.initialize_on_transport(transport)
1986
if repo_format_name:
1988
# use a custom format
1989
result._format.repository_format = \
1990
repository.network_format_registry.get(repo_format_name)
1991
except AttributeError:
1992
# The format didn't permit it to be set.
1994
# A repository is desired, either in-place or shared.
1995
repository_policy = result.determine_repository_policy(
1996
force_new_repo, stacked_on, stack_on_pwd,
1997
require_stacking=require_stacking)
1998
result_repo, is_new_repo = repository_policy.acquire_repository(
1999
make_working_trees, shared_repo)
2000
if not require_stacking and repository_policy._require_stacking:
2001
require_stacking = True
2002
result._format.require_stacking()
2003
result_repo.lock_write()
2006
repository_policy = None
2007
return result_repo, result, require_stacking, repository_policy
2009
def _initialize_on_transport_vfs(self, transport):
2010
"""Initialize a new bzrdir using VFS calls.
2012
:param transport: The transport to create the .bzr directory in.
2015
# Since we are creating a .bzr directory, inherit the
2016
# mode from the root directory
2017
temp_control = lockable_files.LockableFiles(transport,
2018
'', lockable_files.TransportLock)
2019
temp_control._transport.mkdir('.bzr',
2020
# FIXME: RBC 20060121 don't peek under
2022
mode=temp_control._dir_mode)
2023
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
2024
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
2025
file_mode = temp_control._file_mode
2027
bzrdir_transport = transport.clone('.bzr')
2028
utf8_files = [('README',
2029
"This is a Bazaar control directory.\n"
2030
"Do not change any files in this directory.\n"
2031
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
2032
('branch-format', self.get_format_string()),
2034
# NB: no need to escape relative paths that are url safe.
2035
control_files = lockable_files.LockableFiles(bzrdir_transport,
2036
self._lock_file_name, self._lock_class)
2037
control_files.create_lock()
2038
control_files.lock_write()
2040
for (filename, content) in utf8_files:
2041
bzrdir_transport.put_bytes(filename, content,
2044
control_files.unlock()
2045
return self.open(transport, _found=True)
2047
def is_supported(self):
2048
"""Is this format supported?
2050
Supported formats must be initializable and openable.
2051
Unsupported formats may not support initialization or committing or
2052
some other features depending on the reason for not being supported.
2056
def network_name(self):
2057
"""A simple byte string uniquely identifying this format for RPC calls.
2059
Bzr control formats use thir disk format string to identify the format
2060
over the wire. Its possible that other control formats have more
2061
complex detection requirements, so we permit them to use any unique and
2062
immutable string they desire.
2064
raise NotImplementedError(self.network_name)
2066
def same_model(self, target_format):
2067
return (self.repository_format.rich_root_data ==
2068
target_format.rich_root_data)
2071
def known_formats(klass):
2072
"""Return all the known formats.
2074
Concrete formats should override _known_formats.
2076
# There is double indirection here to make sure that control
2077
# formats used by more than one dir format will only be probed
2078
# once. This can otherwise be quite expensive for remote connections.
2080
for format in klass._control_formats:
2081
result.update(format._known_formats())
2085
def _known_formats(klass):
2086
"""Return the known format instances for this control format."""
2087
return set(klass._formats.values())
2089
def open(self, transport, _found=False):
2090
"""Return an instance of this format for the dir transport points at.
2092
_found is a private parameter, do not use it.
2095
found_format = BzrDirFormat.find_format(transport)
2096
if not isinstance(found_format, self.__class__):
2097
raise AssertionError("%s was asked to open %s, but it seems to need "
2099
% (self, transport, found_format))
2100
# Allow subclasses - use the found format.
2101
self._supply_sub_formats_to(found_format)
2102
return found_format._open(transport)
2103
return self._open(transport)
2105
def _open(self, transport):
2106
"""Template method helper for opening BzrDirectories.
2108
This performs the actual open and any additional logic or parameter
2111
raise NotImplementedError(self._open)
2114
def register_format(klass, format):
2115
klass._formats[format.get_format_string()] = format
2116
# bzr native formats have a network name of their format string.
2117
network_format_registry.register(format.get_format_string(), format.__class__)
2120
def register_control_format(klass, format):
2121
"""Register a format that does not use '.bzr' for its control dir.
2123
TODO: This should be pulled up into a 'ControlDirFormat' base class
2124
which BzrDirFormat can inherit from, and renamed to register_format
2125
there. It has been done without that for now for simplicity of
2128
klass._control_formats.append(format)
2131
def register_control_server_format(klass, format):
2132
"""Register a control format for client-server environments.
2134
These formats will be tried before ones registered with
2135
register_control_format. This gives implementations that decide to the
2136
chance to grab it before anything looks at the contents of the format
2139
klass._control_server_formats.append(format)
2142
def _set_default_format(klass, format):
2143
"""Set default format (for testing behavior of defaults only)"""
2144
klass._default_format = format
2148
return self.get_format_description().rstrip()
2150
def _supply_sub_formats_to(self, other_format):
2151
"""Give other_format the same values for sub formats as this has.
2153
This method is expected to be used when parameterising a
2154
RemoteBzrDirFormat instance with the parameters from a
2155
BzrDirMetaFormat1 instance.
2157
:param other_format: other_format is a format which should be
2158
compatible with whatever sub formats are supported by self.
2163
def unregister_format(klass, format):
2164
del klass._formats[format.get_format_string()]
2167
def unregister_control_format(klass, format):
2168
klass._control_formats.remove(format)
2171
class BzrDirFormat4(BzrDirFormat):
2172
"""Bzr dir format 4.
2174
This format is a combined format for working tree, branch and repository.
2176
- Format 1 working trees [always]
2177
- Format 4 branches [always]
2178
- Format 4 repositories [always]
2180
This format is deprecated: it indexes texts using a text it which is
2181
removed in format 5; write support for this format has been removed.
2184
_lock_class = lockable_files.TransportLock
2186
def get_format_string(self):
2187
"""See BzrDirFormat.get_format_string()."""
2188
return "Bazaar-NG branch, format 0.0.4\n"
2190
def get_format_description(self):
2191
"""See BzrDirFormat.get_format_description()."""
2192
return "All-in-one format 4"
2194
def get_converter(self, format=None):
2195
"""See BzrDirFormat.get_converter()."""
2196
# there is one and only one upgrade path here.
2197
return ConvertBzrDir4To5()
2199
def initialize_on_transport(self, transport):
2200
"""Format 4 branches cannot be created."""
2201
raise errors.UninitializableFormat(self)
2203
def is_supported(self):
2204
"""Format 4 is not supported.
2206
It is not supported because the model changed from 4 to 5 and the
2207
conversion logic is expensive - so doing it on the fly was not
2212
def network_name(self):
2213
return self.get_format_string()
2215
def _open(self, transport):
2216
"""See BzrDirFormat._open."""
2217
return BzrDir4(transport, self)
2219
def __return_repository_format(self):
2220
"""Circular import protection."""
2221
from bzrlib.repofmt.weaverepo import RepositoryFormat4
2222
return RepositoryFormat4()
2223
repository_format = property(__return_repository_format)
2226
class BzrDirFormatAllInOne(BzrDirFormat):
2227
"""Common class for formats before meta-dirs."""
2229
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
2230
create_prefix=False, force_new_repo=False, stacked_on=None,
2231
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
2233
"""See BzrDirFormat.initialize_on_transport_ex."""
2234
require_stacking = (stacked_on is not None)
2235
# Format 5 cannot stack, but we've been asked to - actually init
2237
if require_stacking:
2238
format = BzrDirMetaFormat1()
2239
return format.initialize_on_transport_ex(transport,
2240
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2241
force_new_repo=force_new_repo, stacked_on=stacked_on,
2242
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2243
make_working_trees=make_working_trees, shared_repo=shared_repo)
2244
return BzrDirFormat.initialize_on_transport_ex(self, transport,
2245
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2246
force_new_repo=force_new_repo, stacked_on=stacked_on,
2247
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2248
make_working_trees=make_working_trees, shared_repo=shared_repo)
2251
class BzrDirFormat5(BzrDirFormatAllInOne):
2252
"""Bzr control format 5.
2254
This format is a combined format for working tree, branch and repository.
2256
- Format 2 working trees [always]
2257
- Format 4 branches [always]
2258
- Format 5 repositories [always]
2259
Unhashed stores in the repository.
2262
_lock_class = lockable_files.TransportLock
2264
def get_format_string(self):
2265
"""See BzrDirFormat.get_format_string()."""
2266
return "Bazaar-NG branch, format 5\n"
2268
def get_branch_format(self):
2269
from bzrlib import branch
2270
return branch.BzrBranchFormat4()
2272
def get_format_description(self):
2273
"""See BzrDirFormat.get_format_description()."""
2274
return "All-in-one format 5"
2276
def get_converter(self, format=None):
2277
"""See BzrDirFormat.get_converter()."""
2278
# there is one and only one upgrade path here.
2279
return ConvertBzrDir5To6()
2281
def _initialize_for_clone(self, url):
2282
return self.initialize_on_transport(get_transport(url), _cloning=True)
2284
def initialize_on_transport(self, transport, _cloning=False):
2285
"""Format 5 dirs always have working tree, branch and repository.
2287
Except when they are being cloned.
2289
from bzrlib.branch import BzrBranchFormat4
2290
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2291
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
2292
RepositoryFormat5().initialize(result, _internal=True)
2294
branch = BzrBranchFormat4().initialize(result)
2295
result._init_workingtree()
2298
def network_name(self):
2299
return self.get_format_string()
2301
def _open(self, transport):
2302
"""See BzrDirFormat._open."""
2303
return BzrDir5(transport, self)
2305
def __return_repository_format(self):
2306
"""Circular import protection."""
2307
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2308
return RepositoryFormat5()
2309
repository_format = property(__return_repository_format)
2312
class BzrDirFormat6(BzrDirFormatAllInOne):
2313
"""Bzr control format 6.
2315
This format is a combined format for working tree, branch and repository.
2317
- Format 2 working trees [always]
2318
- Format 4 branches [always]
2319
- Format 6 repositories [always]
2322
_lock_class = lockable_files.TransportLock
2324
def get_format_string(self):
2325
"""See BzrDirFormat.get_format_string()."""
2326
return "Bazaar-NG branch, format 6\n"
2328
def get_format_description(self):
2329
"""See BzrDirFormat.get_format_description()."""
2330
return "All-in-one format 6"
2332
def get_branch_format(self):
2333
from bzrlib import branch
2334
return branch.BzrBranchFormat4()
2336
def get_converter(self, format=None):
2337
"""See BzrDirFormat.get_converter()."""
2338
# there is one and only one upgrade path here.
2339
return ConvertBzrDir6ToMeta()
2341
def _initialize_for_clone(self, url):
2342
return self.initialize_on_transport(get_transport(url), _cloning=True)
2344
def initialize_on_transport(self, transport, _cloning=False):
2345
"""Format 6 dirs always have working tree, branch and repository.
2347
Except when they are being cloned.
2349
from bzrlib.branch import BzrBranchFormat4
2350
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2351
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
2352
RepositoryFormat6().initialize(result, _internal=True)
2354
branch = BzrBranchFormat4().initialize(result)
2355
result._init_workingtree()
2358
def network_name(self):
2359
return self.get_format_string()
2361
def _open(self, transport):
2362
"""See BzrDirFormat._open."""
2363
return BzrDir6(transport, self)
2365
def __return_repository_format(self):
2366
"""Circular import protection."""
2367
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2368
return RepositoryFormat6()
2369
repository_format = property(__return_repository_format)
2372
class BzrDirMetaFormat1(BzrDirFormat):
2373
"""Bzr meta control format 1
2375
This is the first format with split out working tree, branch and repository
2378
- Format 3 working trees [optional]
2379
- Format 5 branches [optional]
2380
- Format 7 repositories [optional]
2383
_lock_class = lockdir.LockDir
2386
self._workingtree_format = None
2387
self._branch_format = None
2388
self._repository_format = None
2390
def __eq__(self, other):
2391
if other.__class__ is not self.__class__:
2393
if other.repository_format != self.repository_format:
2395
if other.workingtree_format != self.workingtree_format:
2399
def __ne__(self, other):
2400
return not self == other
2402
def get_branch_format(self):
2403
if self._branch_format is None:
2404
from bzrlib.branch import BranchFormat
2405
self._branch_format = BranchFormat.get_default_format()
2406
return self._branch_format
2408
def set_branch_format(self, format):
2409
self._branch_format = format
2411
def require_stacking(self, stack_on=None, possible_transports=None,
2413
"""We have a request to stack, try to ensure the formats support it.
2415
:param stack_on: If supplied, it is the URL to a branch that we want to
2416
stack on. Check to see if that format supports stacking before
2419
# Stacking is desired. requested by the target, but does the place it
2420
# points at support stacking? If it doesn't then we should
2421
# not implicitly upgrade. We check this here.
2422
new_repo_format = None
2423
new_branch_format = None
2425
# a bit of state for get_target_branch so that we don't try to open it
2426
# 2 times, for both repo *and* branch
2427
target = [None, False, None] # target_branch, checked, upgrade anyway
2428
def get_target_branch():
2430
# We've checked, don't check again
2432
if stack_on is None:
2433
# No target format, that means we want to force upgrading
2434
target[:] = [None, True, True]
2437
target_dir = BzrDir.open(stack_on,
2438
possible_transports=possible_transports)
2439
except errors.NotBranchError:
2440
# Nothing there, don't change formats
2441
target[:] = [None, True, False]
2443
except errors.JailBreak:
2444
# JailBreak, JFDI and upgrade anyway
2445
target[:] = [None, True, True]
2448
target_branch = target_dir.open_branch()
2449
except errors.NotBranchError:
2450
# No branch, don't upgrade formats
2451
target[:] = [None, True, False]
2453
target[:] = [target_branch, True, False]
2456
if (not _skip_repo and
2457
not self.repository_format.supports_external_lookups):
2458
# We need to upgrade the Repository.
2459
target_branch, _, do_upgrade = get_target_branch()
2460
if target_branch is None:
2461
# We don't have a target branch, should we upgrade anyway?
2463
# stack_on is inaccessible, JFDI.
2464
# TODO: bad monkey, hard-coded formats...
2465
if self.repository_format.rich_root_data:
2466
new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2468
new_repo_format = pack_repo.RepositoryFormatKnitPack5()
2470
# If the target already supports stacking, then we know the
2471
# project is already able to use stacking, so auto-upgrade
2473
new_repo_format = target_branch.repository._format
2474
if not new_repo_format.supports_external_lookups:
2475
# target doesn't, source doesn't, so don't auto upgrade
2477
new_repo_format = None
2478
if new_repo_format is not None:
2479
self.repository_format = new_repo_format
2480
note('Source repository format does not support stacking,'
2481
' using format:\n %s',
2482
new_repo_format.get_format_description())
2484
if not self.get_branch_format().supports_stacking():
2485
# We just checked the repo, now lets check if we need to
2486
# upgrade the branch format
2487
target_branch, _, do_upgrade = get_target_branch()
2488
if target_branch is None:
2490
# TODO: bad monkey, hard-coded formats...
2491
new_branch_format = branch.BzrBranchFormat7()
2493
new_branch_format = target_branch._format
2494
if not new_branch_format.supports_stacking():
2495
new_branch_format = None
2496
if new_branch_format is not None:
2497
# Does support stacking, use its format.
2498
self.set_branch_format(new_branch_format)
2499
note('Source branch format does not support stacking,'
2500
' using format:\n %s',
2501
new_branch_format.get_format_description())
2503
def get_converter(self, format=None):
2504
"""See BzrDirFormat.get_converter()."""
2506
format = BzrDirFormat.get_default_format()
2507
if not isinstance(self, format.__class__):
2508
# converting away from metadir is not implemented
2509
raise NotImplementedError(self.get_converter)
2510
return ConvertMetaToMeta(format)
2512
def get_format_string(self):
2513
"""See BzrDirFormat.get_format_string()."""
2514
return "Bazaar-NG meta directory, format 1\n"
2516
def get_format_description(self):
2517
"""See BzrDirFormat.get_format_description()."""
2518
return "Meta directory format 1"
2520
def network_name(self):
2521
return self.get_format_string()
2523
def _open(self, transport):
2524
"""See BzrDirFormat._open."""
2525
# Create a new format instance because otherwise initialisation of new
2526
# metadirs share the global default format object leading to alias
2528
format = BzrDirMetaFormat1()
2529
self._supply_sub_formats_to(format)
2530
return BzrDirMeta1(transport, format)
2532
def __return_repository_format(self):
2533
"""Circular import protection."""
2534
if self._repository_format:
2535
return self._repository_format
2536
from bzrlib.repository import RepositoryFormat
2537
return RepositoryFormat.get_default_format()
2539
def _set_repository_format(self, value):
2540
"""Allow changing the repository format for metadir formats."""
2541
self._repository_format = value
2543
repository_format = property(__return_repository_format,
2544
_set_repository_format)
2546
def _supply_sub_formats_to(self, other_format):
2547
"""Give other_format the same values for sub formats as this has.
2549
This method is expected to be used when parameterising a
2550
RemoteBzrDirFormat instance with the parameters from a
2551
BzrDirMetaFormat1 instance.
2553
:param other_format: other_format is a format which should be
2554
compatible with whatever sub formats are supported by self.
2557
if getattr(self, '_repository_format', None) is not None:
2558
other_format.repository_format = self.repository_format
2559
if self._branch_format is not None:
2560
other_format._branch_format = self._branch_format
2561
if self._workingtree_format is not None:
2562
other_format.workingtree_format = self.workingtree_format
2564
def __get_workingtree_format(self):
2565
if self._workingtree_format is None:
2566
from bzrlib.workingtree import WorkingTreeFormat
2567
self._workingtree_format = WorkingTreeFormat.get_default_format()
2568
return self._workingtree_format
2570
def __set_workingtree_format(self, wt_format):
2571
self._workingtree_format = wt_format
2573
workingtree_format = property(__get_workingtree_format,
2574
__set_workingtree_format)
2577
network_format_registry = registry.FormatRegistry()
2578
"""Registry of formats indexed by their network name.
2580
The network name for a BzrDirFormat is an identifier that can be used when
2581
referring to formats with smart server operations. See
2582
BzrDirFormat.network_name() for more detail.
2586
# Register bzr control format
2587
BzrDirFormat.register_control_format(BzrDirFormat)
2589
# Register bzr formats
2590
BzrDirFormat.register_format(BzrDirFormat4())
2591
BzrDirFormat.register_format(BzrDirFormat5())
2592
BzrDirFormat.register_format(BzrDirFormat6())
2593
__default_format = BzrDirMetaFormat1()
2594
BzrDirFormat.register_format(__default_format)
2595
BzrDirFormat._default_format = __default_format
2598
class Converter(object):
2599
"""Converts a disk format object from one format to another."""
2601
def convert(self, to_convert, pb):
2602
"""Perform the conversion of to_convert, giving feedback via pb.
2604
:param to_convert: The disk object to convert.
2605
:param pb: a progress bar to use for progress information.
2608
def step(self, message):
2609
"""Update the pb by a step."""
2611
self.pb.update(message, self.count, self.total)
2614
class ConvertBzrDir4To5(Converter):
2615
"""Converts format 4 bzr dirs to format 5."""
2618
super(ConvertBzrDir4To5, self).__init__()
2619
self.converted_revs = set()
2620
self.absent_revisions = set()
2624
def convert(self, to_convert, pb):
2625
"""See Converter.convert()."""
2626
self.bzrdir = to_convert
2628
warnings.warn("pb parameter to convert() is deprecated")
2629
self.pb = ui.ui_factory.nested_progress_bar()
2631
ui.ui_factory.note('starting upgrade from format 4 to 5')
2632
if isinstance(self.bzrdir.transport, local.LocalTransport):
2633
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2634
self._convert_to_weaves()
2635
return BzrDir.open(self.bzrdir.root_transport.base)
2639
def _convert_to_weaves(self):
2640
ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
2643
stat = self.bzrdir.transport.stat('weaves')
2644
if not S_ISDIR(stat.st_mode):
2645
self.bzrdir.transport.delete('weaves')
2646
self.bzrdir.transport.mkdir('weaves')
2647
except errors.NoSuchFile:
2648
self.bzrdir.transport.mkdir('weaves')
2649
# deliberately not a WeaveFile as we want to build it up slowly.
2650
self.inv_weave = Weave('inventory')
2651
# holds in-memory weaves for all files
2652
self.text_weaves = {}
2653
self.bzrdir.transport.delete('branch-format')
2654
self.branch = self.bzrdir.open_branch()
2655
self._convert_working_inv()
2656
rev_history = self.branch.revision_history()
2657
# to_read is a stack holding the revisions we still need to process;
2658
# appending to it adds new highest-priority revisions
2659
self.known_revisions = set(rev_history)
2660
self.to_read = rev_history[-1:]
2662
rev_id = self.to_read.pop()
2663
if (rev_id not in self.revisions
2664
and rev_id not in self.absent_revisions):
2665
self._load_one_rev(rev_id)
2667
to_import = self._make_order()
2668
for i, rev_id in enumerate(to_import):
2669
self.pb.update('converting revision', i, len(to_import))
2670
self._convert_one_rev(rev_id)
2672
self._write_all_weaves()
2673
self._write_all_revs()
2674
ui.ui_factory.note('upgraded to weaves:')
2675
ui.ui_factory.note(' %6d revisions and inventories' % len(self.revisions))
2676
ui.ui_factory.note(' %6d revisions not present' % len(self.absent_revisions))
2677
ui.ui_factory.note(' %6d texts' % self.text_count)
2678
self._cleanup_spare_files_after_format4()
2679
self.branch._transport.put_bytes(
2681
BzrDirFormat5().get_format_string(),
2682
mode=self.bzrdir._get_file_mode())
2684
def _cleanup_spare_files_after_format4(self):
2685
# FIXME working tree upgrade foo.
2686
for n in 'merged-patches', 'pending-merged-patches':
2688
## assert os.path.getsize(p) == 0
2689
self.bzrdir.transport.delete(n)
2690
except errors.NoSuchFile:
2692
self.bzrdir.transport.delete_tree('inventory-store')
2693
self.bzrdir.transport.delete_tree('text-store')
2695
def _convert_working_inv(self):
2696
inv = xml4.serializer_v4.read_inventory(
2697
self.branch._transport.get('inventory'))
2698
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2699
self.branch._transport.put_bytes('inventory', new_inv_xml,
2700
mode=self.bzrdir._get_file_mode())
2702
def _write_all_weaves(self):
2703
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2704
weave_transport = self.bzrdir.transport.clone('weaves')
2705
weaves = WeaveStore(weave_transport, prefixed=False)
2706
transaction = WriteTransaction()
2710
for file_id, file_weave in self.text_weaves.items():
2711
self.pb.update('writing weave', i, len(self.text_weaves))
2712
weaves._put_weave(file_id, file_weave, transaction)
2714
self.pb.update('inventory', 0, 1)
2715
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2716
self.pb.update('inventory', 1, 1)
2720
def _write_all_revs(self):
2721
"""Write all revisions out in new form."""
2722
self.bzrdir.transport.delete_tree('revision-store')
2723
self.bzrdir.transport.mkdir('revision-store')
2724
revision_transport = self.bzrdir.transport.clone('revision-store')
2726
from bzrlib.xml5 import serializer_v5
2727
from bzrlib.repofmt.weaverepo import RevisionTextStore
2728
revision_store = RevisionTextStore(revision_transport,
2729
serializer_v5, False, versionedfile.PrefixMapper(),
2730
lambda:True, lambda:True)
2732
for i, rev_id in enumerate(self.converted_revs):
2733
self.pb.update('write revision', i, len(self.converted_revs))
2734
text = serializer_v5.write_revision_to_string(
2735
self.revisions[rev_id])
2737
revision_store.add_lines(key, None, osutils.split_lines(text))
2741
def _load_one_rev(self, rev_id):
2742
"""Load a revision object into memory.
2744
Any parents not either loaded or abandoned get queued to be
2746
self.pb.update('loading revision',
2747
len(self.revisions),
2748
len(self.known_revisions))
2749
if not self.branch.repository.has_revision(rev_id):
2751
ui.ui_factory.note('revision {%s} not present in branch; '
2752
'will be converted as a ghost' %
2754
self.absent_revisions.add(rev_id)
2756
rev = self.branch.repository.get_revision(rev_id)
2757
for parent_id in rev.parent_ids:
2758
self.known_revisions.add(parent_id)
2759
self.to_read.append(parent_id)
2760
self.revisions[rev_id] = rev
2762
def _load_old_inventory(self, rev_id):
2763
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2764
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2765
inv.revision_id = rev_id
2766
rev = self.revisions[rev_id]
2769
def _load_updated_inventory(self, rev_id):
2770
inv_xml = self.inv_weave.get_text(rev_id)
2771
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2774
def _convert_one_rev(self, rev_id):
2775
"""Convert revision and all referenced objects to new format."""
2776
rev = self.revisions[rev_id]
2777
inv = self._load_old_inventory(rev_id)
2778
present_parents = [p for p in rev.parent_ids
2779
if p not in self.absent_revisions]
2780
self._convert_revision_contents(rev, inv, present_parents)
2781
self._store_new_inv(rev, inv, present_parents)
2782
self.converted_revs.add(rev_id)
2784
def _store_new_inv(self, rev, inv, present_parents):
2785
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2786
new_inv_sha1 = sha_string(new_inv_xml)
2787
self.inv_weave.add_lines(rev.revision_id,
2789
new_inv_xml.splitlines(True))
2790
rev.inventory_sha1 = new_inv_sha1
2792
def _convert_revision_contents(self, rev, inv, present_parents):
2793
"""Convert all the files within a revision.
2795
Also upgrade the inventory to refer to the text revision ids."""
2796
rev_id = rev.revision_id
2797
mutter('converting texts of revision {%s}',
2799
parent_invs = map(self._load_updated_inventory, present_parents)
2800
entries = inv.iter_entries()
2802
for path, ie in entries:
2803
self._convert_file_version(rev, ie, parent_invs)
2805
def _convert_file_version(self, rev, ie, parent_invs):
2806
"""Convert one version of one file.
2808
The file needs to be added into the weave if it is a merge
2809
of >=2 parents or if it's changed from its parent.
2811
file_id = ie.file_id
2812
rev_id = rev.revision_id
2813
w = self.text_weaves.get(file_id)
2816
self.text_weaves[file_id] = w
2817
text_changed = False
2818
parent_candiate_entries = ie.parent_candidates(parent_invs)
2819
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2820
# XXX: Note that this is unordered - and this is tolerable because
2821
# the previous code was also unordered.
2822
previous_entries = dict((head, parent_candiate_entries[head]) for head
2824
self.snapshot_ie(previous_entries, ie, w, rev_id)
2827
def get_parent_map(self, revision_ids):
2828
"""See graph.StackedParentsProvider.get_parent_map"""
2829
return dict((revision_id, self.revisions[revision_id])
2830
for revision_id in revision_ids
2831
if revision_id in self.revisions)
2833
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2834
# TODO: convert this logic, which is ~= snapshot to
2835
# a call to:. This needs the path figured out. rather than a work_tree
2836
# a v4 revision_tree can be given, or something that looks enough like
2837
# one to give the file content to the entry if it needs it.
2838
# and we need something that looks like a weave store for snapshot to
2840
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2841
if len(previous_revisions) == 1:
2842
previous_ie = previous_revisions.values()[0]
2843
if ie._unchanged(previous_ie):
2844
ie.revision = previous_ie.revision
2847
text = self.branch.repository._text_store.get(ie.text_id)
2848
file_lines = text.readlines()
2849
w.add_lines(rev_id, previous_revisions, file_lines)
2850
self.text_count += 1
2852
w.add_lines(rev_id, previous_revisions, [])
2853
ie.revision = rev_id
2855
def _make_order(self):
2856
"""Return a suitable order for importing revisions.
2858
The order must be such that an revision is imported after all
2859
its (present) parents.
2861
todo = set(self.revisions.keys())
2862
done = self.absent_revisions.copy()
2865
# scan through looking for a revision whose parents
2867
for rev_id in sorted(list(todo)):
2868
rev = self.revisions[rev_id]
2869
parent_ids = set(rev.parent_ids)
2870
if parent_ids.issubset(done):
2871
# can take this one now
2872
order.append(rev_id)
2878
class ConvertBzrDir5To6(Converter):
2879
"""Converts format 5 bzr dirs to format 6."""
2881
def convert(self, to_convert, pb):
2882
"""See Converter.convert()."""
2883
self.bzrdir = to_convert
2884
pb = ui.ui_factory.nested_progress_bar()
2886
ui.ui_factory.note('starting upgrade from format 5 to 6')
2887
self._convert_to_prefixed()
2888
return BzrDir.open(self.bzrdir.root_transport.base)
2892
def _convert_to_prefixed(self):
2893
from bzrlib.store import TransportStore
2894
self.bzrdir.transport.delete('branch-format')
2895
for store_name in ["weaves", "revision-store"]:
2896
ui.ui_factory.note("adding prefixes to %s" % store_name)
2897
store_transport = self.bzrdir.transport.clone(store_name)
2898
store = TransportStore(store_transport, prefixed=True)
2899
for urlfilename in store_transport.list_dir('.'):
2900
filename = urlutils.unescape(urlfilename)
2901
if (filename.endswith(".weave") or
2902
filename.endswith(".gz") or
2903
filename.endswith(".sig")):
2904
file_id, suffix = os.path.splitext(filename)
2908
new_name = store._mapper.map((file_id,)) + suffix
2909
# FIXME keep track of the dirs made RBC 20060121
2911
store_transport.move(filename, new_name)
2912
except errors.NoSuchFile: # catches missing dirs strangely enough
2913
store_transport.mkdir(osutils.dirname(new_name))
2914
store_transport.move(filename, new_name)
2915
self.bzrdir.transport.put_bytes(
2917
BzrDirFormat6().get_format_string(),
2918
mode=self.bzrdir._get_file_mode())
2921
class ConvertBzrDir6ToMeta(Converter):
2922
"""Converts format 6 bzr dirs to metadirs."""
2924
def convert(self, to_convert, pb):
2925
"""See Converter.convert()."""
2926
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2927
from bzrlib.branch import BzrBranchFormat5
2928
self.bzrdir = to_convert
2929
self.pb = ui.ui_factory.nested_progress_bar()
2931
self.total = 20 # the steps we know about
2932
self.garbage_inventories = []
2933
self.dir_mode = self.bzrdir._get_dir_mode()
2934
self.file_mode = self.bzrdir._get_file_mode()
2936
ui.ui_factory.note('starting upgrade from format 6 to metadir')
2937
self.bzrdir.transport.put_bytes(
2939
"Converting to format 6",
2940
mode=self.file_mode)
2941
# its faster to move specific files around than to open and use the apis...
2942
# first off, nuke ancestry.weave, it was never used.
2944
self.step('Removing ancestry.weave')
2945
self.bzrdir.transport.delete('ancestry.weave')
2946
except errors.NoSuchFile:
2948
# find out whats there
2949
self.step('Finding branch files')
2950
last_revision = self.bzrdir.open_branch().last_revision()
2951
bzrcontents = self.bzrdir.transport.list_dir('.')
2952
for name in bzrcontents:
2953
if name.startswith('basis-inventory.'):
2954
self.garbage_inventories.append(name)
2955
# create new directories for repository, working tree and branch
2956
repository_names = [('inventory.weave', True),
2957
('revision-store', True),
2959
self.step('Upgrading repository ')
2960
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2961
self.make_lock('repository')
2962
# we hard code the formats here because we are converting into
2963
# the meta format. The meta format upgrader can take this to a
2964
# future format within each component.
2965
self.put_format('repository', RepositoryFormat7())
2966
for entry in repository_names:
2967
self.move_entry('repository', entry)
2969
self.step('Upgrading branch ')
2970
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2971
self.make_lock('branch')
2972
self.put_format('branch', BzrBranchFormat5())
2973
branch_files = [('revision-history', True),
2974
('branch-name', True),
2976
for entry in branch_files:
2977
self.move_entry('branch', entry)
2979
checkout_files = [('pending-merges', True),
2980
('inventory', True),
2981
('stat-cache', False)]
2982
# If a mandatory checkout file is not present, the branch does not have
2983
# a functional checkout. Do not create a checkout in the converted
2985
for name, mandatory in checkout_files:
2986
if mandatory and name not in bzrcontents:
2987
has_checkout = False
2991
if not has_checkout:
2992
ui.ui_factory.note('No working tree.')
2993
# If some checkout files are there, we may as well get rid of them.
2994
for name, mandatory in checkout_files:
2995
if name in bzrcontents:
2996
self.bzrdir.transport.delete(name)
2998
from bzrlib.workingtree import WorkingTreeFormat3
2999
self.step('Upgrading working tree')
3000
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
3001
self.make_lock('checkout')
3003
'checkout', WorkingTreeFormat3())
3004
self.bzrdir.transport.delete_multi(
3005
self.garbage_inventories, self.pb)
3006
for entry in checkout_files:
3007
self.move_entry('checkout', entry)
3008
if last_revision is not None:
3009
self.bzrdir.transport.put_bytes(
3010
'checkout/last-revision', last_revision)
3011
self.bzrdir.transport.put_bytes(
3013
BzrDirMetaFormat1().get_format_string(),
3014
mode=self.file_mode)
3016
return BzrDir.open(self.bzrdir.root_transport.base)
3018
def make_lock(self, name):
3019
"""Make a lock for the new control dir name."""
3020
self.step('Make %s lock' % name)
3021
ld = lockdir.LockDir(self.bzrdir.transport,
3023
file_modebits=self.file_mode,
3024
dir_modebits=self.dir_mode)
3027
def move_entry(self, new_dir, entry):
3028
"""Move then entry name into new_dir."""
3030
mandatory = entry[1]
3031
self.step('Moving %s' % name)
3033
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
3034
except errors.NoSuchFile:
3038
def put_format(self, dirname, format):
3039
self.bzrdir.transport.put_bytes('%s/format' % dirname,
3040
format.get_format_string(),
3044
class ConvertMetaToMeta(Converter):
3045
"""Converts the components of metadirs."""
3047
def __init__(self, target_format):
3048
"""Create a metadir to metadir converter.
3050
:param target_format: The final metadir format that is desired.
3052
self.target_format = target_format
3054
def convert(self, to_convert, pb):
3055
"""See Converter.convert()."""
3056
self.bzrdir = to_convert
3057
self.pb = ui.ui_factory.nested_progress_bar()
3060
self.step('checking repository format')
3062
repo = self.bzrdir.open_repository()
3063
except errors.NoRepositoryPresent:
3066
if not isinstance(repo._format, self.target_format.repository_format.__class__):
3067
from bzrlib.repository import CopyConverter
3068
ui.ui_factory.note('starting repository conversion')
3069
converter = CopyConverter(self.target_format.repository_format)
3070
converter.convert(repo, pb)
3071
for branch in self.bzrdir.list_branches():
3072
# TODO: conversions of Branch and Tree should be done by
3073
# InterXFormat lookups/some sort of registry.
3074
# Avoid circular imports
3075
from bzrlib import branch as _mod_branch
3076
old = branch._format.__class__
3077
new = self.target_format.get_branch_format().__class__
3079
if (old == _mod_branch.BzrBranchFormat5 and
3080
new in (_mod_branch.BzrBranchFormat6,
3081
_mod_branch.BzrBranchFormat7,
3082
_mod_branch.BzrBranchFormat8)):
3083
branch_converter = _mod_branch.Converter5to6()
3084
elif (old == _mod_branch.BzrBranchFormat6 and
3085
new in (_mod_branch.BzrBranchFormat7,
3086
_mod_branch.BzrBranchFormat8)):
3087
branch_converter = _mod_branch.Converter6to7()
3088
elif (old == _mod_branch.BzrBranchFormat7 and
3089
new is _mod_branch.BzrBranchFormat8):
3090
branch_converter = _mod_branch.Converter7to8()
3092
raise errors.BadConversionTarget("No converter", new,
3094
branch_converter.convert(branch)
3095
branch = self.bzrdir.open_branch()
3096
old = branch._format.__class__
3098
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
3099
except (errors.NoWorkingTree, errors.NotLocalUrl):
3102
# TODO: conversions of Branch and Tree should be done by
3103
# InterXFormat lookups
3104
if (isinstance(tree, workingtree.WorkingTree3) and
3105
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
3106
isinstance(self.target_format.workingtree_format,
3107
workingtree_4.DirStateWorkingTreeFormat)):
3108
workingtree_4.Converter3to4().convert(tree)
3109
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
3110
not isinstance(tree, workingtree_4.WorkingTree5) and
3111
isinstance(self.target_format.workingtree_format,
3112
workingtree_4.WorkingTreeFormat5)):
3113
workingtree_4.Converter4to5().convert(tree)
3114
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
3115
not isinstance(tree, workingtree_4.WorkingTree6) and
3116
isinstance(self.target_format.workingtree_format,
3117
workingtree_4.WorkingTreeFormat6)):
3118
workingtree_4.Converter4or5to6().convert(tree)
3123
# This is not in remote.py because it's relatively small, and needs to be
3124
# registered. Putting it in remote.py creates a circular import problem.
3125
# we can make it a lazy object if the control formats is turned into something
3127
class RemoteBzrDirFormat(BzrDirMetaFormat1):
3128
"""Format representing bzrdirs accessed via a smart server"""
3131
BzrDirMetaFormat1.__init__(self)
3132
# XXX: It's a bit ugly that the network name is here, because we'd
3133
# like to believe that format objects are stateless or at least
3134
# immutable, However, we do at least avoid mutating the name after
3135
# it's returned. See <https://bugs.edge.launchpad.net/bzr/+bug/504102>
3136
self._network_name = None
3139
return "%s(_network_name=%r)" % (self.__class__.__name__,
3142
def get_format_description(self):
3143
if self._network_name:
3144
real_format = network_format_registry.get(self._network_name)
3145
return 'Remote: ' + real_format.get_format_description()
3146
return 'bzr remote bzrdir'
3148
def get_format_string(self):
3149
raise NotImplementedError(self.get_format_string)
3151
def network_name(self):
3152
if self._network_name:
3153
return self._network_name
3155
raise AssertionError("No network name set.")
3158
def probe_transport(klass, transport):
3159
"""Return a RemoteBzrDirFormat object if it looks possible."""
3161
medium = transport.get_smart_medium()
3162
except (NotImplementedError, AttributeError,
3163
errors.TransportNotPossible, errors.NoSmartMedium,
3164
errors.SmartProtocolError):
3165
# no smart server, so not a branch for this format type.
3166
raise errors.NotBranchError(path=transport.base)
3168
# Decline to open it if the server doesn't support our required
3169
# version (3) so that the VFS-based transport will do it.
3170
if medium.should_probe():
3172
server_version = medium.protocol_version()
3173
except errors.SmartProtocolError:
3174
# Apparently there's no usable smart server there, even though
3175
# the medium supports the smart protocol.
3176
raise errors.NotBranchError(path=transport.base)
3177
if server_version != '2':
3178
raise errors.NotBranchError(path=transport.base)
3181
def initialize_on_transport(self, transport):
3183
# hand off the request to the smart server
3184
client_medium = transport.get_smart_medium()
3185
except errors.NoSmartMedium:
3186
# TODO: lookup the local format from a server hint.
3187
local_dir_format = BzrDirMetaFormat1()
3188
return local_dir_format.initialize_on_transport(transport)
3189
client = _SmartClient(client_medium)
3190
path = client.remote_path_from_transport(transport)
3192
response = client.call('BzrDirFormat.initialize', path)
3193
except errors.ErrorFromSmartServer, err:
3194
remote._translate_error(err, path=path)
3195
if response[0] != 'ok':
3196
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
3197
format = RemoteBzrDirFormat()
3198
self._supply_sub_formats_to(format)
3199
return remote.RemoteBzrDir(transport, format)
3201
def parse_NoneTrueFalse(self, arg):
3208
raise AssertionError("invalid arg %r" % arg)
3210
def _serialize_NoneTrueFalse(self, arg):
3217
def _serialize_NoneString(self, arg):
3220
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
3221
create_prefix=False, force_new_repo=False, stacked_on=None,
3222
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
3225
# hand off the request to the smart server
3226
client_medium = transport.get_smart_medium()
3227
except errors.NoSmartMedium:
3230
# Decline to open it if the server doesn't support our required
3231
# version (3) so that the VFS-based transport will do it.
3232
if client_medium.should_probe():
3234
server_version = client_medium.protocol_version()
3235
if server_version != '2':
3239
except errors.SmartProtocolError:
3240
# Apparently there's no usable smart server there, even though
3241
# the medium supports the smart protocol.
3246
client = _SmartClient(client_medium)
3247
path = client.remote_path_from_transport(transport)
3248
if client_medium._is_remote_before((1, 16)):
3251
# TODO: lookup the local format from a server hint.
3252
local_dir_format = BzrDirMetaFormat1()
3253
self._supply_sub_formats_to(local_dir_format)
3254
return local_dir_format.initialize_on_transport_ex(transport,
3255
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3256
force_new_repo=force_new_repo, stacked_on=stacked_on,
3257
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3258
make_working_trees=make_working_trees, shared_repo=shared_repo,
3260
return self._initialize_on_transport_ex_rpc(client, path, transport,
3261
use_existing_dir, create_prefix, force_new_repo, stacked_on,
3262
stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
3264
def _initialize_on_transport_ex_rpc(self, client, path, transport,
3265
use_existing_dir, create_prefix, force_new_repo, stacked_on,
3266
stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
3268
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
3269
args.append(self._serialize_NoneTrueFalse(create_prefix))
3270
args.append(self._serialize_NoneTrueFalse(force_new_repo))
3271
args.append(self._serialize_NoneString(stacked_on))
3272
# stack_on_pwd is often/usually our transport
3275
stack_on_pwd = transport.relpath(stack_on_pwd)
3276
if not stack_on_pwd:
3278
except errors.PathNotChild:
3280
args.append(self._serialize_NoneString(stack_on_pwd))
3281
args.append(self._serialize_NoneString(repo_format_name))
3282
args.append(self._serialize_NoneTrueFalse(make_working_trees))
3283
args.append(self._serialize_NoneTrueFalse(shared_repo))
3284
request_network_name = self._network_name or \
3285
BzrDirFormat.get_default_format().network_name()
3287
response = client.call('BzrDirFormat.initialize_ex_1.16',
3288
request_network_name, path, *args)
3289
except errors.UnknownSmartMethod:
3290
client._medium._remember_remote_is_before((1,16))
3291
local_dir_format = BzrDirMetaFormat1()
3292
self._supply_sub_formats_to(local_dir_format)
3293
return local_dir_format.initialize_on_transport_ex(transport,
3294
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3295
force_new_repo=force_new_repo, stacked_on=stacked_on,
3296
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3297
make_working_trees=make_working_trees, shared_repo=shared_repo,
3299
except errors.ErrorFromSmartServer, err:
3300
remote._translate_error(err, path=path)
3301
repo_path = response[0]
3302
bzrdir_name = response[6]
3303
require_stacking = response[7]
3304
require_stacking = self.parse_NoneTrueFalse(require_stacking)
3305
format = RemoteBzrDirFormat()
3306
format._network_name = bzrdir_name
3307
self._supply_sub_formats_to(format)
3308
bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
3310
repo_format = remote.response_tuple_to_repo_format(response[1:])
3311
if repo_path == '.':
3314
repo_bzrdir_format = RemoteBzrDirFormat()
3315
repo_bzrdir_format._network_name = response[5]
3316
repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
3320
final_stack = response[8] or None
3321
final_stack_pwd = response[9] or None
3323
final_stack_pwd = urlutils.join(
3324
transport.base, final_stack_pwd)
3325
remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
3326
if len(response) > 10:
3327
# Updated server verb that locks remotely.
3328
repo_lock_token = response[10] or None
3329
remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
3331
remote_repo.dont_leave_lock_in_place()
3333
remote_repo.lock_write()
3334
policy = UseExistingRepository(remote_repo, final_stack,
3335
final_stack_pwd, require_stacking)
3336
policy.acquire_repository()
3340
bzrdir._format.set_branch_format(self.get_branch_format())
3341
if require_stacking:
3342
# The repo has already been created, but we need to make sure that
3343
# we'll make a stackable branch.
3344
bzrdir._format.require_stacking(_skip_repo=True)
3345
return remote_repo, bzrdir, require_stacking, policy
3347
def _open(self, transport):
3348
return remote.RemoteBzrDir(transport, self)
3350
def __eq__(self, other):
3351
if not isinstance(other, RemoteBzrDirFormat):
3353
return self.get_format_description() == other.get_format_description()
3355
def __return_repository_format(self):
3356
# Always return a RemoteRepositoryFormat object, but if a specific bzr
3357
# repository format has been asked for, tell the RemoteRepositoryFormat
3358
# that it should use that for init() etc.
3359
result = remote.RemoteRepositoryFormat()
3360
custom_format = getattr(self, '_repository_format', None)
3362
if isinstance(custom_format, remote.RemoteRepositoryFormat):
3363
return custom_format
3365
# We will use the custom format to create repositories over the
3366
# wire; expose its details like rich_root_data for code to
3368
result._custom_format = custom_format
3371
def get_branch_format(self):
3372
result = BzrDirMetaFormat1.get_branch_format(self)
3373
if not isinstance(result, remote.RemoteBranchFormat):
3374
new_result = remote.RemoteBranchFormat()
3375
new_result._custom_format = result
3377
self.set_branch_format(new_result)
3381
repository_format = property(__return_repository_format,
3382
BzrDirMetaFormat1._set_repository_format) #.im_func)
3385
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
3388
class BzrDirFormatInfo(object):
3390
def __init__(self, native, deprecated, hidden, experimental):
3391
self.deprecated = deprecated
3392
self.native = native
3393
self.hidden = hidden
3394
self.experimental = experimental
3397
class BzrDirFormatRegistry(registry.Registry):
3398
"""Registry of user-selectable BzrDir subformats.
3400
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
3401
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
3405
"""Create a BzrDirFormatRegistry."""
3406
self._aliases = set()
3407
self._registration_order = list()
3408
super(BzrDirFormatRegistry, self).__init__()
3411
"""Return a set of the format names which are aliases."""
3412
return frozenset(self._aliases)
3414
def register_metadir(self, key,
3415
repository_format, help, native=True, deprecated=False,
3421
"""Register a metadir subformat.
3423
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3424
by the Repository/Branch/WorkingTreeformats.
3426
:param repository_format: The fully-qualified repository format class
3428
:param branch_format: Fully-qualified branch format class name as
3430
:param tree_format: Fully-qualified tree format class name as
3433
# This should be expanded to support setting WorkingTree and Branch
3434
# formats, once BzrDirMetaFormat1 supports that.
3435
def _load(full_name):
3436
mod_name, factory_name = full_name.rsplit('.', 1)
3438
mod = __import__(mod_name, globals(), locals(),
3440
except ImportError, e:
3441
raise ImportError('failed to load %s: %s' % (full_name, e))
3443
factory = getattr(mod, factory_name)
3444
except AttributeError:
3445
raise AttributeError('no factory %s in module %r'
3450
bd = BzrDirMetaFormat1()
3451
if branch_format is not None:
3452
bd.set_branch_format(_load(branch_format))
3453
if tree_format is not None:
3454
bd.workingtree_format = _load(tree_format)
3455
if repository_format is not None:
3456
bd.repository_format = _load(repository_format)
3458
self.register(key, helper, help, native, deprecated, hidden,
3459
experimental, alias)
3461
def register(self, key, factory, help, native=True, deprecated=False,
3462
hidden=False, experimental=False, alias=False):
3463
"""Register a BzrDirFormat factory.
3465
The factory must be a callable that takes one parameter: the key.
3466
It must produce an instance of the BzrDirFormat when called.
3468
This function mainly exists to prevent the info object from being
3471
registry.Registry.register(self, key, factory, help,
3472
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3474
self._aliases.add(key)
3475
self._registration_order.append(key)
3477
def register_lazy(self, key, module_name, member_name, help, native=True,
3478
deprecated=False, hidden=False, experimental=False, alias=False):
3479
registry.Registry.register_lazy(self, key, module_name, member_name,
3480
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3482
self._aliases.add(key)
3483
self._registration_order.append(key)
3485
def set_default(self, key):
3486
"""Set the 'default' key to be a clone of the supplied key.
3488
This method must be called once and only once.
3490
registry.Registry.register(self, 'default', self.get(key),
3491
self.get_help(key), info=self.get_info(key))
3492
self._aliases.add('default')
3494
def set_default_repository(self, key):
3495
"""Set the FormatRegistry default and Repository default.
3497
This is a transitional method while Repository.set_default_format
3500
if 'default' in self:
3501
self.remove('default')
3502
self.set_default(key)
3503
format = self.get('default')()
3505
def make_bzrdir(self, key):
3506
return self.get(key)()
3508
def help_topic(self, topic):
3510
default_realkey = None
3511
default_help = self.get_help('default')
3513
for key in self._registration_order:
3514
if key == 'default':
3516
help = self.get_help(key)
3517
if help == default_help:
3518
default_realkey = key
3520
help_pairs.append((key, help))
3522
def wrapped(key, help, info):
3524
help = '(native) ' + help
3525
return ':%s:\n%s\n\n' % (key,
3526
textwrap.fill(help, initial_indent=' ',
3527
subsequent_indent=' ',
3528
break_long_words=False))
3529
if default_realkey is not None:
3530
output += wrapped(default_realkey, '(default) %s' % default_help,
3531
self.get_info('default'))
3532
deprecated_pairs = []
3533
experimental_pairs = []
3534
for key, help in help_pairs:
3535
info = self.get_info(key)
3538
elif info.deprecated:
3539
deprecated_pairs.append((key, help))
3540
elif info.experimental:
3541
experimental_pairs.append((key, help))
3543
output += wrapped(key, help, info)
3544
output += "\nSee :doc:`formats-help` for more about storage formats."
3546
if len(experimental_pairs) > 0:
3547
other_output += "Experimental formats are shown below.\n\n"
3548
for key, help in experimental_pairs:
3549
info = self.get_info(key)
3550
other_output += wrapped(key, help, info)
3553
"No experimental formats are available.\n\n"
3554
if len(deprecated_pairs) > 0:
3555
other_output += "\nDeprecated formats are shown below.\n\n"
3556
for key, help in deprecated_pairs:
3557
info = self.get_info(key)
3558
other_output += wrapped(key, help, info)
3561
"\nNo deprecated formats are available.\n\n"
3563
"\nSee :doc:`formats-help` for more about storage formats."
3565
if topic == 'other-formats':
3571
class RepositoryAcquisitionPolicy(object):
3572
"""Abstract base class for repository acquisition policies.
3574
A repository acquisition policy decides how a BzrDir acquires a repository
3575
for a branch that is being created. The most basic policy decision is
3576
whether to create a new repository or use an existing one.
3578
def __init__(self, stack_on, stack_on_pwd, require_stacking):
3581
:param stack_on: A location to stack on
3582
:param stack_on_pwd: If stack_on is relative, the location it is
3584
:param require_stacking: If True, it is a failure to not stack.
3586
self._stack_on = stack_on
3587
self._stack_on_pwd = stack_on_pwd
3588
self._require_stacking = require_stacking
3590
def configure_branch(self, branch):
3591
"""Apply any configuration data from this policy to the branch.
3593
Default implementation sets repository stacking.
3595
if self._stack_on is None:
3597
if self._stack_on_pwd is None:
3598
stack_on = self._stack_on
3601
stack_on = urlutils.rebase_url(self._stack_on,
3603
branch.bzrdir.root_transport.base)
3604
except errors.InvalidRebaseURLs:
3605
stack_on = self._get_full_stack_on()
3607
branch.set_stacked_on_url(stack_on)
3608
except (errors.UnstackableBranchFormat,
3609
errors.UnstackableRepositoryFormat):
3610
if self._require_stacking:
3613
def requires_stacking(self):
3614
"""Return True if this policy requires stacking."""
3615
return self._stack_on is not None and self._require_stacking
3617
def _get_full_stack_on(self):
3618
"""Get a fully-qualified URL for the stack_on location."""
3619
if self._stack_on is None:
3621
if self._stack_on_pwd is None:
3622
return self._stack_on
3624
return urlutils.join(self._stack_on_pwd, self._stack_on)
3626
def _add_fallback(self, repository, possible_transports=None):
3627
"""Add a fallback to the supplied repository, if stacking is set."""
3628
stack_on = self._get_full_stack_on()
3629
if stack_on is None:
3632
stacked_dir = BzrDir.open(stack_on,
3633
possible_transports=possible_transports)
3634
except errors.JailBreak:
3635
# We keep the stacking details, but we are in the server code so
3636
# actually stacking is not needed.
3639
stacked_repo = stacked_dir.open_branch().repository
3640
except errors.NotBranchError:
3641
stacked_repo = stacked_dir.open_repository()
3643
repository.add_fallback_repository(stacked_repo)
3644
except errors.UnstackableRepositoryFormat:
3645
if self._require_stacking:
3648
self._require_stacking = True
3650
def acquire_repository(self, make_working_trees=None, shared=False):
3651
"""Acquire a repository for this bzrdir.
3653
Implementations may create a new repository or use a pre-exising
3655
:param make_working_trees: If creating a repository, set
3656
make_working_trees to this value (if non-None)
3657
:param shared: If creating a repository, make it shared if True
3658
:return: A repository, is_new_flag (True if the repository was
3661
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3664
class CreateRepository(RepositoryAcquisitionPolicy):
3665
"""A policy of creating a new repository"""
3667
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3668
require_stacking=False):
3671
:param bzrdir: The bzrdir to create the repository on.
3672
:param stack_on: A location to stack on
3673
:param stack_on_pwd: If stack_on is relative, the location it is
3676
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3678
self._bzrdir = bzrdir
3680
def acquire_repository(self, make_working_trees=None, shared=False):
3681
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3683
Creates the desired repository in the bzrdir we already have.
3685
stack_on = self._get_full_stack_on()
3687
format = self._bzrdir._format
3688
format.require_stacking(stack_on=stack_on,
3689
possible_transports=[self._bzrdir.root_transport])
3690
if not self._require_stacking:
3691
# We have picked up automatic stacking somewhere.
3692
note('Using default stacking branch %s at %s', self._stack_on,
3694
repository = self._bzrdir.create_repository(shared=shared)
3695
self._add_fallback(repository,
3696
possible_transports=[self._bzrdir.transport])
3697
if make_working_trees is not None:
3698
repository.set_make_working_trees(make_working_trees)
3699
return repository, True
3702
class UseExistingRepository(RepositoryAcquisitionPolicy):
3703
"""A policy of reusing an existing repository"""
3705
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3706
require_stacking=False):
3709
:param repository: The repository to use.
3710
:param stack_on: A location to stack on
3711
:param stack_on_pwd: If stack_on is relative, the location it is
3714
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3716
self._repository = repository
3718
def acquire_repository(self, make_working_trees=None, shared=False):
3719
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3721
Returns an existing repository to use.
3723
self._add_fallback(self._repository,
3724
possible_transports=[self._repository.bzrdir.transport])
3725
return self._repository, False
3728
# Please register new formats after old formats so that formats
3729
# appear in chronological order and format descriptions can build
3731
format_registry = BzrDirFormatRegistry()
3732
# The pre-0.8 formats have their repository format network name registered in
3733
# repository.py. MetaDir formats have their repository format network name
3734
# inferred from their disk format string.
3735
format_registry.register('weave', BzrDirFormat6,
3736
'Pre-0.8 format. Slower than knit and does not'
3737
' support checkouts or shared repositories.',
3740
format_registry.register_metadir('metaweave',
3741
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3742
'Transitional format in 0.8. Slower than knit.',
3743
branch_format='bzrlib.branch.BzrBranchFormat5',
3744
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3747
format_registry.register_metadir('knit',
3748
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3749
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3750
branch_format='bzrlib.branch.BzrBranchFormat5',
3751
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3754
format_registry.register_metadir('dirstate',
3755
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3756
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3757
'above when accessed over the network.',
3758
branch_format='bzrlib.branch.BzrBranchFormat5',
3759
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3760
# directly from workingtree_4 triggers a circular import.
3761
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3764
format_registry.register_metadir('dirstate-tags',
3765
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3766
help='New in 0.15: Fast local operations and improved scaling for '
3767
'network operations. Additionally adds support for tags.'
3768
' Incompatible with bzr < 0.15.',
3769
branch_format='bzrlib.branch.BzrBranchFormat6',
3770
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3773
format_registry.register_metadir('rich-root',
3774
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3775
help='New in 1.0. Better handling of tree roots. Incompatible with'
3777
branch_format='bzrlib.branch.BzrBranchFormat6',
3778
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3781
format_registry.register_metadir('dirstate-with-subtree',
3782
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3783
help='New in 0.15: Fast local operations and improved scaling for '
3784
'network operations. Additionally adds support for versioning nested '
3785
'bzr branches. Incompatible with bzr < 0.15.',
3786
branch_format='bzrlib.branch.BzrBranchFormat6',
3787
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3791
format_registry.register_metadir('pack-0.92',
3792
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3793
help='New in 0.92: Pack-based format with data compatible with '
3794
'dirstate-tags format repositories. Interoperates with '
3795
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3797
branch_format='bzrlib.branch.BzrBranchFormat6',
3798
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3800
format_registry.register_metadir('pack-0.92-subtree',
3801
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3802
help='New in 0.92: Pack-based format with data compatible with '
3803
'dirstate-with-subtree format repositories. Interoperates with '
3804
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3806
branch_format='bzrlib.branch.BzrBranchFormat6',
3807
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3811
format_registry.register_metadir('rich-root-pack',
3812
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3813
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3814
'(needed for bzr-svn and bzr-git).',
3815
branch_format='bzrlib.branch.BzrBranchFormat6',
3816
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3819
format_registry.register_metadir('1.6',
3820
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3821
help='A format that allows a branch to indicate that there is another '
3822
'(stacked) repository that should be used to access data that is '
3823
'not present locally.',
3824
branch_format='bzrlib.branch.BzrBranchFormat7',
3825
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3828
format_registry.register_metadir('1.6.1-rich-root',
3829
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3830
help='A variant of 1.6 that supports rich-root data '
3831
'(needed for bzr-svn and bzr-git).',
3832
branch_format='bzrlib.branch.BzrBranchFormat7',
3833
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3836
format_registry.register_metadir('1.9',
3837
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3838
help='A repository format using B+tree indexes. These indexes '
3839
'are smaller in size, have smarter caching and provide faster '
3840
'performance for most operations.',
3841
branch_format='bzrlib.branch.BzrBranchFormat7',
3842
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3845
format_registry.register_metadir('1.9-rich-root',
3846
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3847
help='A variant of 1.9 that supports rich-root data '
3848
'(needed for bzr-svn and bzr-git).',
3849
branch_format='bzrlib.branch.BzrBranchFormat7',
3850
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3853
format_registry.register_metadir('1.14',
3854
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3855
help='A working-tree format that supports content filtering.',
3856
branch_format='bzrlib.branch.BzrBranchFormat7',
3857
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3859
format_registry.register_metadir('1.14-rich-root',
3860
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3861
help='A variant of 1.14 that supports rich-root data '
3862
'(needed for bzr-svn and bzr-git).',
3863
branch_format='bzrlib.branch.BzrBranchFormat7',
3864
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3866
# The following un-numbered 'development' formats should always just be aliases.
3867
format_registry.register_metadir('development-rich-root',
3868
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3869
help='Current development format. Supports rich roots. Can convert data '
3870
'to and from rich-root-pack (and anything compatible with '
3871
'rich-root-pack) format repositories. Repositories and branches in '
3872
'this format can only be read by bzr.dev. Please read '
3873
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3875
branch_format='bzrlib.branch.BzrBranchFormat7',
3876
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3881
format_registry.register_metadir('development-subtree',
3882
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3883
help='Current development format, subtree variant. Can convert data to and '
3884
'from pack-0.92-subtree (and anything compatible with '
3885
'pack-0.92-subtree) format repositories. Repositories and branches in '
3886
'this format can only be read by bzr.dev. Please read '
3887
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3889
branch_format='bzrlib.branch.BzrBranchFormat7',
3890
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3893
alias=False, # Restore to being an alias when an actual development subtree format is added
3894
# This current non-alias status is simply because we did not introduce a
3895
# chk based subtree format.
3898
# And the development formats above will have aliased one of the following:
3899
format_registry.register_metadir('development6-rich-root',
3900
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3901
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3903
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3905
branch_format='bzrlib.branch.BzrBranchFormat7',
3906
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3911
format_registry.register_metadir('development7-rich-root',
3912
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3913
help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3914
'rich roots. Please read '
3915
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3917
branch_format='bzrlib.branch.BzrBranchFormat7',
3918
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3923
format_registry.register_metadir('2a',
3924
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3925
help='First format for bzr 2.0 series.\n'
3926
'Uses group-compress storage.\n'
3927
'Provides rich roots which are a one-way transition.\n',
3928
# 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
3929
# 'rich roots. Supported by bzr 1.16 and later.',
3930
branch_format='bzrlib.branch.BzrBranchFormat7',
3931
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3935
# The following format should be an alias for the rich root equivalent
3936
# of the default format
3937
format_registry.register_metadir('default-rich-root',
3938
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3939
branch_format='bzrlib.branch.BzrBranchFormat7',
3940
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3945
# The current format that is made on 'bzr init'.
3946
format_registry.set_default('2a')