1
# Copyright (C) 2005, 2006, 2007, 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""BzrDir logic. The BzrDir is the basic control directory used by bzr.
19
At format 7 this was split out into Branch, Repository and Checkout control
22
Note: This module has a lot of ``open`` functions/methods that return
23
references to in-memory objects. As a rule, there are no matching ``close``
24
methods. To free any associated resources, simply stop referencing the
28
# TODO: Move old formats into a plugin to make this file smaller.
33
from bzrlib.lazy_import import lazy_import
34
lazy_import(globals(), """
35
from stat import S_ISDIR
47
revision as _mod_revision,
57
from bzrlib.osutils import (
60
from bzrlib.smart.client import _SmartClient
61
from bzrlib.store.versioned import WeaveStore
62
from bzrlib.transactions import WriteTransaction
63
from bzrlib.transport import (
64
do_catching_redirections,
68
from bzrlib.weave import Weave
71
from bzrlib.trace import (
83
"""A .bzr control diretory.
85
BzrDir instances let you create or open any of the things that can be
86
found within .bzr - checkouts, branches and repositories.
89
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
91
a transport connected to the directory this bzr was opened from
92
(i.e. the parent directory holding the .bzr directory).
94
Everything in the bzrdir should have the same file permissions.
98
"""Invoke break_lock on the first object in the bzrdir.
100
If there is a tree, the tree is opened and break_lock() called.
101
Otherwise, branch is tried, and finally repository.
103
# XXX: This seems more like a UI function than something that really
104
# belongs in this class.
106
thing_to_unlock = self.open_workingtree()
107
except (errors.NotLocalUrl, errors.NoWorkingTree):
109
thing_to_unlock = self.open_branch()
110
except errors.NotBranchError:
112
thing_to_unlock = self.open_repository()
113
except errors.NoRepositoryPresent:
115
thing_to_unlock.break_lock()
117
def can_convert_format(self):
118
"""Return true if this bzrdir is one whose format we can convert from."""
121
def check_conversion_target(self, target_format):
122
target_repo_format = target_format.repository_format
123
source_repo_format = self._format.repository_format
124
source_repo_format.check_conversion_target(target_repo_format)
127
def _check_supported(format, allow_unsupported,
128
recommend_upgrade=True,
130
"""Give an error or warning on old formats.
132
:param format: may be any kind of format - workingtree, branch,
135
:param allow_unsupported: If true, allow opening
136
formats that are strongly deprecated, and which may
137
have limited functionality.
139
:param recommend_upgrade: If true (default), warn
140
the user through the ui object that they may wish
141
to upgrade the object.
143
# TODO: perhaps move this into a base Format class; it's not BzrDir
144
# specific. mbp 20070323
145
if not allow_unsupported and not format.is_supported():
146
# see open_downlevel to open legacy branches.
147
raise errors.UnsupportedFormatError(format=format)
148
if recommend_upgrade \
149
and getattr(format, 'upgrade_recommended', False):
150
ui.ui_factory.recommend_upgrade(
151
format.get_format_description(),
154
def clone(self, url, revision_id=None, force_new_repo=False,
155
preserve_stacking=False):
156
"""Clone this bzrdir and its contents to url verbatim.
158
:param url: The url create the clone at. If url's last component does
159
not exist, it will be created.
160
:param revision_id: The tip revision-id to use for any branch or
161
working tree. If not None, then the clone operation may tune
162
itself to download less data.
163
:param force_new_repo: Do not use a shared repository for the target
164
even if one is available.
165
:param preserve_stacking: When cloning a stacked branch, stack the
166
new branch on top of the other branch's stacked-on branch.
168
return self.clone_on_transport(get_transport(url),
169
revision_id=revision_id,
170
force_new_repo=force_new_repo,
171
preserve_stacking=preserve_stacking)
173
def clone_on_transport(self, transport, revision_id=None,
174
force_new_repo=False, preserve_stacking=False,
176
"""Clone this bzrdir and its contents to transport verbatim.
178
:param transport: The transport for the location to produce the clone
179
at. If the target directory does not exist, it will be created.
180
:param revision_id: The tip revision-id to use for any branch or
181
working tree. If not None, then the clone operation may tune
182
itself to download less data.
183
:param force_new_repo: Do not use a shared repository for the target,
184
even if one is available.
185
:param preserve_stacking: When cloning a stacked branch, stack the
186
new branch on top of the other branch's stacked-on branch.
188
transport.ensure_base()
189
require_stacking = (stacked_on is not None)
190
metadir = self.cloning_metadir(require_stacking)
191
result = metadir.initialize_on_transport(transport)
192
repository_policy = None
194
local_repo = self.find_repository()
195
except errors.NoRepositoryPresent:
198
local_branch = self.open_branch()
199
except errors.NotBranchError:
202
# enable fallbacks when branch is not a branch reference
203
if local_branch.repository.has_same_location(local_repo):
204
local_repo = local_branch.repository
205
if preserve_stacking:
207
stacked_on = local_branch.get_stacked_on_url()
208
except (errors.UnstackableBranchFormat,
209
errors.UnstackableRepositoryFormat,
214
# may need to copy content in
215
repository_policy = result.determine_repository_policy(
216
force_new_repo, stacked_on, self.root_transport.base,
217
require_stacking=require_stacking)
218
make_working_trees = local_repo.make_working_trees()
219
result_repo = repository_policy.acquire_repository(
220
make_working_trees, local_repo.is_shared())
221
if not require_stacking and repository_policy._require_stacking:
222
require_stacking = True
223
result._format.require_stacking()
224
result_repo.fetch(local_repo, revision_id=revision_id)
227
# 1 if there is a branch present
228
# make sure its content is available in the target repository
230
if local_branch is not None:
231
result_branch = local_branch.clone(result, revision_id=revision_id)
232
if repository_policy is not None:
233
repository_policy.configure_branch(result_branch)
234
if result_repo is None or result_repo.make_working_trees():
236
self.open_workingtree().clone(result)
237
except (errors.NoWorkingTree, errors.NotLocalUrl):
241
# TODO: This should be given a Transport, and should chdir up; otherwise
242
# this will open a new connection.
243
def _make_tail(self, url):
244
t = get_transport(url)
248
def create(cls, base, format=None, possible_transports=None):
249
"""Create a new BzrDir at the url 'base'.
251
:param format: If supplied, the format of branch to create. If not
252
supplied, the default is used.
253
:param possible_transports: If supplied, a list of transports that
254
can be reused to share a remote connection.
256
if cls is not BzrDir:
257
raise AssertionError("BzrDir.create always creates the default"
258
" format, not one of %r" % cls)
259
t = get_transport(base, possible_transports)
262
format = BzrDirFormat.get_default_format()
263
return format.initialize_on_transport(t)
266
def find_bzrdirs(transport, evaluate=None, list_current=None):
267
"""Find bzrdirs recursively from current location.
269
This is intended primarily as a building block for more sophisticated
270
functionality, like finding trees under a directory, or finding
271
branches that use a given repository.
272
:param evaluate: An optional callable that yields recurse, value,
273
where recurse controls whether this bzrdir is recursed into
274
and value is the value to yield. By default, all bzrdirs
275
are recursed into, and the return value is the bzrdir.
276
:param list_current: if supplied, use this function to list the current
277
directory, instead of Transport.list_dir
278
:return: a generator of found bzrdirs, or whatever evaluate returns.
280
if list_current is None:
281
def list_current(transport):
282
return transport.list_dir('')
284
def evaluate(bzrdir):
287
pending = [transport]
288
while len(pending) > 0:
289
current_transport = pending.pop()
292
bzrdir = BzrDir.open_from_transport(current_transport)
293
except errors.NotBranchError:
296
recurse, value = evaluate(bzrdir)
299
subdirs = list_current(current_transport)
300
except errors.NoSuchFile:
303
for subdir in sorted(subdirs, reverse=True):
304
pending.append(current_transport.clone(subdir))
307
def find_branches(transport):
308
"""Find all branches under a transport.
310
This will find all branches below the transport, including branches
311
inside other branches. Where possible, it will use
312
Repository.find_branches.
314
To list all the branches that use a particular Repository, see
315
Repository.find_branches
317
def evaluate(bzrdir):
319
repository = bzrdir.open_repository()
320
except errors.NoRepositoryPresent:
323
return False, (None, repository)
325
branch = bzrdir.open_branch()
326
except errors.NotBranchError:
327
return True, (None, None)
329
return True, (branch, None)
331
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
333
branches.extend(repo.find_branches())
334
if branch is not None:
335
branches.append(branch)
338
def destroy_repository(self):
339
"""Destroy the repository in this BzrDir"""
340
raise NotImplementedError(self.destroy_repository)
342
def create_branch(self):
343
"""Create a branch in this BzrDir.
345
The bzrdir's format will control what branch format is created.
346
For more control see BranchFormatXX.create(a_bzrdir).
348
raise NotImplementedError(self.create_branch)
350
def destroy_branch(self):
351
"""Destroy the branch in this BzrDir"""
352
raise NotImplementedError(self.destroy_branch)
355
def create_branch_and_repo(base, force_new_repo=False, format=None):
356
"""Create a new BzrDir, Branch and Repository at the url 'base'.
358
This will use the current default BzrDirFormat unless one is
359
specified, and use whatever
360
repository format that that uses via bzrdir.create_branch and
361
create_repository. If a shared repository is available that is used
364
The created Branch object is returned.
366
:param base: The URL to create the branch at.
367
:param force_new_repo: If True a new repository is always created.
368
:param format: If supplied, the format of branch to create. If not
369
supplied, the default is used.
371
bzrdir = BzrDir.create(base, format)
372
bzrdir._find_or_create_repository(force_new_repo)
373
return bzrdir.create_branch()
375
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
376
stack_on_pwd=None, require_stacking=False):
377
"""Return an object representing a policy to use.
379
This controls whether a new repository is created, or a shared
380
repository used instead.
382
If stack_on is supplied, will not seek a containing shared repo.
384
:param force_new_repo: If True, require a new repository to be created.
385
:param stack_on: If supplied, the location to stack on. If not
386
supplied, a default_stack_on location may be used.
387
:param stack_on_pwd: If stack_on is relative, the location it is
390
def repository_policy(found_bzrdir):
393
config = found_bzrdir.get_config()
395
if config is not None:
396
stack_on = config.get_default_stack_on()
397
if stack_on is not None:
398
stack_on_pwd = found_bzrdir.root_transport.base
400
note('Using default stacking branch %s at %s', stack_on,
402
# does it have a repository ?
404
repository = found_bzrdir.open_repository()
405
except errors.NoRepositoryPresent:
408
if ((found_bzrdir.root_transport.base !=
409
self.root_transport.base) and not repository.is_shared()):
416
return UseExistingRepository(repository, stack_on,
417
stack_on_pwd, require_stacking=require_stacking), True
419
return CreateRepository(self, stack_on, stack_on_pwd,
420
require_stacking=require_stacking), True
422
if not force_new_repo:
424
policy = self._find_containing(repository_policy)
425
if policy is not None:
429
return UseExistingRepository(self.open_repository(),
430
stack_on, stack_on_pwd,
431
require_stacking=require_stacking)
432
except errors.NoRepositoryPresent:
434
return CreateRepository(self, stack_on, stack_on_pwd,
435
require_stacking=require_stacking)
437
def _find_or_create_repository(self, force_new_repo):
438
"""Create a new repository if needed, returning the repository."""
439
policy = self.determine_repository_policy(force_new_repo)
440
return policy.acquire_repository()
443
def create_branch_convenience(base, force_new_repo=False,
444
force_new_tree=None, format=None,
445
possible_transports=None):
446
"""Create a new BzrDir, Branch and Repository at the url 'base'.
448
This is a convenience function - it will use an existing repository
449
if possible, can be told explicitly whether to create a working tree or
452
This will use the current default BzrDirFormat unless one is
453
specified, and use whatever
454
repository format that that uses via bzrdir.create_branch and
455
create_repository. If a shared repository is available that is used
456
preferentially. Whatever repository is used, its tree creation policy
459
The created Branch object is returned.
460
If a working tree cannot be made due to base not being a file:// url,
461
no error is raised unless force_new_tree is True, in which case no
462
data is created on disk and NotLocalUrl is raised.
464
:param base: The URL to create the branch at.
465
:param force_new_repo: If True a new repository is always created.
466
:param force_new_tree: If True or False force creation of a tree or
467
prevent such creation respectively.
468
:param format: Override for the bzrdir format to create.
469
:param possible_transports: An optional reusable transports list.
472
# check for non local urls
473
t = get_transport(base, possible_transports)
474
if not isinstance(t, local.LocalTransport):
475
raise errors.NotLocalUrl(base)
476
bzrdir = BzrDir.create(base, format, possible_transports)
477
repo = bzrdir._find_or_create_repository(force_new_repo)
478
result = bzrdir.create_branch()
479
if force_new_tree or (repo.make_working_trees() and
480
force_new_tree is None):
482
bzrdir.create_workingtree()
483
except errors.NotLocalUrl:
488
def create_standalone_workingtree(base, format=None):
489
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
491
'base' must be a local path or a file:// url.
493
This will use the current default BzrDirFormat unless one is
494
specified, and use whatever
495
repository format that that uses for bzrdirformat.create_workingtree,
496
create_branch and create_repository.
498
:param format: Override for the bzrdir format to create.
499
:return: The WorkingTree object.
501
t = get_transport(base)
502
if not isinstance(t, local.LocalTransport):
503
raise errors.NotLocalUrl(base)
504
bzrdir = BzrDir.create_branch_and_repo(base,
506
format=format).bzrdir
507
return bzrdir.create_workingtree()
509
def create_workingtree(self, revision_id=None, from_branch=None,
510
accelerator_tree=None, hardlink=False):
511
"""Create a working tree at this BzrDir.
513
:param revision_id: create it as of this revision id.
514
:param from_branch: override bzrdir branch (for lightweight checkouts)
515
:param accelerator_tree: A tree which can be used for retrieving file
516
contents more quickly than the revision tree, i.e. a workingtree.
517
The revision tree will be used for cases where accelerator_tree's
518
content is different.
520
raise NotImplementedError(self.create_workingtree)
522
def backup_bzrdir(self):
523
"""Backup this bzr control directory.
525
:return: Tuple with old path name and new path name
527
self.root_transport.copy_tree('.bzr', 'backup.bzr')
528
return (self.root_transport.abspath('.bzr'),
529
self.root_transport.abspath('backup.bzr'))
531
def retire_bzrdir(self, limit=10000):
532
"""Permanently disable the bzrdir.
534
This is done by renaming it to give the user some ability to recover
535
if there was a problem.
537
This will have horrible consequences if anyone has anything locked or
539
:param limit: number of times to retry
544
to_path = '.bzr.retired.%d' % i
545
self.root_transport.rename('.bzr', to_path)
546
note("renamed %s to %s"
547
% (self.root_transport.abspath('.bzr'), to_path))
549
except (errors.TransportError, IOError, errors.PathError):
556
def destroy_workingtree(self):
557
"""Destroy the working tree at this BzrDir.
559
Formats that do not support this may raise UnsupportedOperation.
561
raise NotImplementedError(self.destroy_workingtree)
563
def destroy_workingtree_metadata(self):
564
"""Destroy the control files for the working tree at this BzrDir.
566
The contents of working tree files are not affected.
567
Formats that do not support this may raise UnsupportedOperation.
569
raise NotImplementedError(self.destroy_workingtree_metadata)
571
def _find_containing(self, evaluate):
572
"""Find something in a containing control directory.
574
This method will scan containing control dirs, until it finds what
575
it is looking for, decides that it will never find it, or runs out
576
of containing control directories to check.
578
It is used to implement find_repository and
579
determine_repository_policy.
581
:param evaluate: A function returning (value, stop). If stop is True,
582
the value will be returned.
586
result, stop = evaluate(found_bzrdir)
589
next_transport = found_bzrdir.root_transport.clone('..')
590
if (found_bzrdir.root_transport.base == next_transport.base):
591
# top of the file system
593
# find the next containing bzrdir
595
found_bzrdir = BzrDir.open_containing_from_transport(
597
except errors.NotBranchError:
600
def find_repository(self):
601
"""Find the repository that should be used.
603
This does not require a branch as we use it to find the repo for
604
new branches as well as to hook existing branches up to their
607
def usable_repository(found_bzrdir):
608
# does it have a repository ?
610
repository = found_bzrdir.open_repository()
611
except errors.NoRepositoryPresent:
613
if found_bzrdir.root_transport.base == self.root_transport.base:
614
return repository, True
615
elif repository.is_shared():
616
return repository, True
620
found_repo = self._find_containing(usable_repository)
621
if found_repo is None:
622
raise errors.NoRepositoryPresent(self)
625
def get_branch_reference(self):
626
"""Return the referenced URL for the branch in this bzrdir.
628
:raises NotBranchError: If there is no Branch.
629
:return: The URL the branch in this bzrdir references if it is a
630
reference branch, or None for regular branches.
634
def get_branch_transport(self, branch_format):
635
"""Get the transport for use by branch format in this BzrDir.
637
Note that bzr dirs that do not support format strings will raise
638
IncompatibleFormat if the branch format they are given has
639
a format string, and vice versa.
641
If branch_format is None, the transport is returned with no
642
checking. If it is not None, then the returned transport is
643
guaranteed to point to an existing directory ready for use.
645
raise NotImplementedError(self.get_branch_transport)
647
def _find_creation_modes(self):
648
"""Determine the appropriate modes for files and directories.
650
They're always set to be consistent with the base directory,
651
assuming that this transport allows setting modes.
653
# TODO: Do we need or want an option (maybe a config setting) to turn
654
# this off or override it for particular locations? -- mbp 20080512
655
if self._mode_check_done:
657
self._mode_check_done = True
659
st = self.transport.stat('.')
660
except errors.TransportNotPossible:
661
self._dir_mode = None
662
self._file_mode = None
664
# Check the directory mode, but also make sure the created
665
# directories and files are read-write for this user. This is
666
# mostly a workaround for filesystems which lie about being able to
667
# write to a directory (cygwin & win32)
668
if (st.st_mode & 07777 == 00000):
669
# FTP allows stat but does not return dir/file modes
670
self._dir_mode = None
671
self._file_mode = None
673
self._dir_mode = (st.st_mode & 07777) | 00700
674
# Remove the sticky and execute bits for files
675
self._file_mode = self._dir_mode & ~07111
677
def _get_file_mode(self):
678
"""Return Unix mode for newly created files, or None.
680
if not self._mode_check_done:
681
self._find_creation_modes()
682
return self._file_mode
684
def _get_dir_mode(self):
685
"""Return Unix mode for newly created directories, or None.
687
if not self._mode_check_done:
688
self._find_creation_modes()
689
return self._dir_mode
691
def get_repository_transport(self, repository_format):
692
"""Get the transport for use by repository format in this BzrDir.
694
Note that bzr dirs that do not support format strings will raise
695
IncompatibleFormat if the repository format they are given has
696
a format string, and vice versa.
698
If repository_format is None, the transport is returned with no
699
checking. If it is not None, then the returned transport is
700
guaranteed to point to an existing directory ready for use.
702
raise NotImplementedError(self.get_repository_transport)
704
def get_workingtree_transport(self, tree_format):
705
"""Get the transport for use by workingtree format in this BzrDir.
707
Note that bzr dirs that do not support format strings will raise
708
IncompatibleFormat if the workingtree format they are given has a
709
format string, and vice versa.
711
If workingtree_format is None, the transport is returned with no
712
checking. If it is not None, then the returned transport is
713
guaranteed to point to an existing directory ready for use.
715
raise NotImplementedError(self.get_workingtree_transport)
717
def get_config(self):
718
if getattr(self, '_get_config', None) is None:
720
return self._get_config()
722
def __init__(self, _transport, _format):
723
"""Initialize a Bzr control dir object.
725
Only really common logic should reside here, concrete classes should be
726
made with varying behaviours.
728
:param _format: the format that is creating this BzrDir instance.
729
:param _transport: the transport this dir is based at.
731
self._format = _format
732
self.transport = _transport.clone('.bzr')
733
self.root_transport = _transport
734
self._mode_check_done = False
736
def is_control_filename(self, filename):
737
"""True if filename is the name of a path which is reserved for bzrdir's.
739
:param filename: A filename within the root transport of this bzrdir.
741
This is true IF and ONLY IF the filename is part of the namespace reserved
742
for bzr control dirs. Currently this is the '.bzr' directory in the root
743
of the root_transport. it is expected that plugins will need to extend
744
this in the future - for instance to make bzr talk with svn working
747
# this might be better on the BzrDirFormat class because it refers to
748
# all the possible bzrdir disk formats.
749
# This method is tested via the workingtree is_control_filename tests-
750
# it was extracted from WorkingTree.is_control_filename. If the method's
751
# contract is extended beyond the current trivial implementation, please
752
# add new tests for it to the appropriate place.
753
return filename == '.bzr' or filename.startswith('.bzr/')
755
def needs_format_conversion(self, format=None):
756
"""Return true if this bzrdir needs convert_format run on it.
758
For instance, if the repository format is out of date but the
759
branch and working tree are not, this should return True.
761
:param format: Optional parameter indicating a specific desired
762
format we plan to arrive at.
764
raise NotImplementedError(self.needs_format_conversion)
767
def open_unsupported(base):
768
"""Open a branch which is not supported."""
769
return BzrDir.open(base, _unsupported=True)
772
def open(base, _unsupported=False, possible_transports=None):
773
"""Open an existing bzrdir, rooted at 'base' (url).
775
:param _unsupported: a private parameter to the BzrDir class.
777
t = get_transport(base, possible_transports=possible_transports)
778
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
781
def open_from_transport(transport, _unsupported=False,
782
_server_formats=True):
783
"""Open a bzrdir within a particular directory.
785
:param transport: Transport containing the bzrdir.
786
:param _unsupported: private.
788
# Keep initial base since 'transport' may be modified while following
790
base = transport.base
791
def find_format(transport):
792
return transport, BzrDirFormat.find_format(
793
transport, _server_formats=_server_formats)
795
def redirected(transport, e, redirection_notice):
796
redirected_transport = transport._redirected_to(e.source, e.target)
797
if redirected_transport is None:
798
raise errors.NotBranchError(base)
799
note('%s is%s redirected to %s',
800
transport.base, e.permanently, redirected_transport.base)
801
return redirected_transport
804
transport, format = do_catching_redirections(find_format,
807
except errors.TooManyRedirections:
808
raise errors.NotBranchError(base)
810
BzrDir._check_supported(format, _unsupported)
811
return format.open(transport, _found=True)
813
def open_branch(self, unsupported=False):
814
"""Open the branch object at this BzrDir if one is present.
816
If unsupported is True, then no longer supported branch formats can
819
TODO: static convenience version of this?
821
raise NotImplementedError(self.open_branch)
824
def open_containing(url, possible_transports=None):
825
"""Open an existing branch which contains url.
827
:param url: url to search from.
828
See open_containing_from_transport for more detail.
830
transport = get_transport(url, possible_transports)
831
return BzrDir.open_containing_from_transport(transport)
834
def open_containing_from_transport(a_transport):
835
"""Open an existing branch which contains a_transport.base.
837
This probes for a branch at a_transport, and searches upwards from there.
839
Basically we keep looking up until we find the control directory or
840
run into the root. If there isn't one, raises NotBranchError.
841
If there is one and it is either an unrecognised format or an unsupported
842
format, UnknownFormatError or UnsupportedFormatError are raised.
843
If there is one, it is returned, along with the unused portion of url.
845
:return: The BzrDir that contains the path, and a Unicode path
846
for the rest of the URL.
848
# this gets the normalised url back. I.e. '.' -> the full path.
849
url = a_transport.base
852
result = BzrDir.open_from_transport(a_transport)
853
return result, urlutils.unescape(a_transport.relpath(url))
854
except errors.NotBranchError, e:
857
new_t = a_transport.clone('..')
858
except errors.InvalidURLJoin:
859
# reached the root, whatever that may be
860
raise errors.NotBranchError(path=url)
861
if new_t.base == a_transport.base:
862
# reached the root, whatever that may be
863
raise errors.NotBranchError(path=url)
866
def _get_tree_branch(self):
867
"""Return the branch and tree, if any, for this bzrdir.
869
Return None for tree if not present or inaccessible.
870
Raise NotBranchError if no branch is present.
871
:return: (tree, branch)
874
tree = self.open_workingtree()
875
except (errors.NoWorkingTree, errors.NotLocalUrl):
877
branch = self.open_branch()
883
def open_tree_or_branch(klass, location):
884
"""Return the branch and working tree at a location.
886
If there is no tree at the location, tree will be None.
887
If there is no branch at the location, an exception will be
889
:return: (tree, branch)
891
bzrdir = klass.open(location)
892
return bzrdir._get_tree_branch()
895
def open_containing_tree_or_branch(klass, location):
896
"""Return the branch and working tree contained by a location.
898
Returns (tree, branch, relpath).
899
If there is no tree at containing the location, tree will be None.
900
If there is no branch containing the location, an exception will be
902
relpath is the portion of the path that is contained by the branch.
904
bzrdir, relpath = klass.open_containing(location)
905
tree, branch = bzrdir._get_tree_branch()
906
return tree, branch, relpath
909
def open_containing_tree_branch_or_repository(klass, location):
910
"""Return the working tree, branch and repo contained by a location.
912
Returns (tree, branch, repository, relpath).
913
If there is no tree containing the location, tree will be None.
914
If there is no branch containing the location, branch will be None.
915
If there is no repository containing the location, repository will be
917
relpath is the portion of the path that is contained by the innermost
920
If no tree, branch or repository is found, a NotBranchError is raised.
922
bzrdir, relpath = klass.open_containing(location)
924
tree, branch = bzrdir._get_tree_branch()
925
except errors.NotBranchError:
927
repo = bzrdir.find_repository()
928
return None, None, repo, relpath
929
except (errors.NoRepositoryPresent):
930
raise errors.NotBranchError(location)
931
return tree, branch, branch.repository, relpath
933
def open_repository(self, _unsupported=False):
934
"""Open the repository object at this BzrDir if one is present.
936
This will not follow the Branch object pointer - it's strictly a direct
937
open facility. Most client code should use open_branch().repository to
940
:param _unsupported: a private parameter, not part of the api.
941
TODO: static convenience version of this?
943
raise NotImplementedError(self.open_repository)
945
def open_workingtree(self, _unsupported=False,
946
recommend_upgrade=True, from_branch=None):
947
"""Open the workingtree object at this BzrDir if one is present.
949
:param recommend_upgrade: Optional keyword parameter, when True (the
950
default), emit through the ui module a recommendation that the user
951
upgrade the working tree when the workingtree being opened is old
952
(but still fully supported).
953
:param from_branch: override bzrdir branch (for lightweight checkouts)
955
raise NotImplementedError(self.open_workingtree)
957
def has_branch(self):
958
"""Tell if this bzrdir contains a branch.
960
Note: if you're going to open the branch, you should just go ahead
961
and try, and not ask permission first. (This method just opens the
962
branch and discards it, and that's somewhat expensive.)
967
except errors.NotBranchError:
970
def has_workingtree(self):
971
"""Tell if this bzrdir contains a working tree.
973
This will still raise an exception if the bzrdir has a workingtree that
974
is remote & inaccessible.
976
Note: if you're going to open the working tree, you should just go ahead
977
and try, and not ask permission first. (This method just opens the
978
workingtree and discards it, and that's somewhat expensive.)
981
self.open_workingtree(recommend_upgrade=False)
983
except errors.NoWorkingTree:
986
def _cloning_metadir(self):
987
"""Produce a metadir suitable for cloning with.
989
:returns: (destination_bzrdir_format, source_repository)
991
result_format = self._format.__class__()
994
branch = self.open_branch()
995
source_repository = branch.repository
996
result_format._branch_format = branch._format
997
except errors.NotBranchError:
999
source_repository = self.open_repository()
1000
except errors.NoRepositoryPresent:
1001
source_repository = None
1003
# XXX TODO: This isinstance is here because we have not implemented
1004
# the fix recommended in bug # 103195 - to delegate this choice the
1005
# repository itself.
1006
repo_format = source_repository._format
1007
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1008
source_repository._ensure_real()
1009
repo_format = source_repository._real_repository._format
1010
result_format.repository_format = repo_format
1012
# TODO: Couldn't we just probe for the format in these cases,
1013
# rather than opening the whole tree? It would be a little
1014
# faster. mbp 20070401
1015
tree = self.open_workingtree(recommend_upgrade=False)
1016
except (errors.NoWorkingTree, errors.NotLocalUrl):
1017
result_format.workingtree_format = None
1019
result_format.workingtree_format = tree._format.__class__()
1020
return result_format, source_repository
1022
def cloning_metadir(self, require_stacking=False):
1023
"""Produce a metadir suitable for cloning or sprouting with.
1025
These operations may produce workingtrees (yes, even though they're
1026
"cloning" something that doesn't have a tree), so a viable workingtree
1027
format must be selected.
1029
:require_stacking: If True, non-stackable formats will be upgraded
1030
to similar stackable formats.
1031
:returns: a BzrDirFormat with all component formats either set
1032
appropriately or set to None if that component should not be
1035
format, repository = self._cloning_metadir()
1036
if format._workingtree_format is None:
1037
if repository is None:
1039
tree_format = repository._format._matchingbzrdir.workingtree_format
1040
format.workingtree_format = tree_format.__class__()
1041
if require_stacking:
1042
format.require_stacking()
1045
def checkout_metadir(self):
1046
return self.cloning_metadir()
1048
def sprout(self, url, revision_id=None, force_new_repo=False,
1049
recurse='down', possible_transports=None,
1050
accelerator_tree=None, hardlink=False, stacked=False,
1051
source_branch=None):
1052
"""Create a copy of this bzrdir prepared for use as a new line of
1055
If url's last component does not exist, it will be created.
1057
Attributes related to the identity of the source branch like
1058
branch nickname will be cleaned, a working tree is created
1059
whether one existed before or not; and a local branch is always
1062
if revision_id is not None, then the clone operation may tune
1063
itself to download less data.
1064
:param accelerator_tree: A tree which can be used for retrieving file
1065
contents more quickly than the revision tree, i.e. a workingtree.
1066
The revision tree will be used for cases where accelerator_tree's
1067
content is different.
1068
:param hardlink: If true, hard-link files from accelerator_tree,
1070
:param stacked: If true, create a stacked branch referring to the
1071
location of this control directory.
1073
target_transport = get_transport(url, possible_transports)
1074
target_transport.ensure_base()
1075
cloning_format = self.cloning_metadir(stacked)
1076
# Create/update the result branch
1077
result = cloning_format.initialize_on_transport(target_transport)
1078
# if a stacked branch wasn't requested, we don't create one
1079
# even if the origin was stacked
1080
stacked_branch_url = None
1081
if source_branch is not None:
1083
stacked_branch_url = self.root_transport.base
1084
source_repository = source_branch.repository
1087
source_branch = self.open_branch()
1088
source_repository = source_branch.repository
1090
stacked_branch_url = self.root_transport.base
1091
except errors.NotBranchError:
1092
source_branch = None
1094
source_repository = self.open_repository()
1095
except errors.NoRepositoryPresent:
1096
source_repository = None
1097
repository_policy = result.determine_repository_policy(
1098
force_new_repo, stacked_branch_url, require_stacking=stacked)
1099
result_repo = repository_policy.acquire_repository()
1100
if source_repository is not None:
1101
# Fetch while stacked to prevent unstacked fetch from
1103
result_repo.fetch(source_repository, revision_id=revision_id)
1105
if source_branch is None:
1106
# this is for sprouting a bzrdir without a branch; is that
1108
# Not especially, but it's part of the contract.
1109
result_branch = result.create_branch()
1111
# Force NULL revision to avoid using repository before stacking
1113
result_branch = source_branch.sprout(
1114
result, revision_id=_mod_revision.NULL_REVISION)
1115
parent_location = result_branch.get_parent()
1116
mutter("created new branch %r" % (result_branch,))
1117
repository_policy.configure_branch(result_branch)
1118
if source_branch is not None:
1119
source_branch.copy_content_into(result_branch, revision_id)
1120
# Override copy_content_into
1121
result_branch.set_parent(parent_location)
1123
# Create/update the result working tree
1124
if isinstance(target_transport, local.LocalTransport) and (
1125
result_repo is None or result_repo.make_working_trees()):
1126
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1130
if wt.path2id('') is None:
1132
wt.set_root_id(self.open_workingtree.get_root_id())
1133
except errors.NoWorkingTree:
1139
if recurse == 'down':
1141
basis = wt.basis_tree()
1143
subtrees = basis.iter_references()
1144
elif result_branch is not None:
1145
basis = result_branch.basis_tree()
1147
subtrees = basis.iter_references()
1148
elif source_branch is not None:
1149
basis = source_branch.basis_tree()
1151
subtrees = basis.iter_references()
1156
for path, file_id in subtrees:
1157
target = urlutils.join(url, urlutils.escape(path))
1158
sublocation = source_branch.reference_parent(file_id, path)
1159
sublocation.bzrdir.sprout(target,
1160
basis.get_reference_revision(file_id, path),
1161
force_new_repo=force_new_repo, recurse=recurse,
1164
if basis is not None:
1169
class BzrDirPreSplitOut(BzrDir):
1170
"""A common class for the all-in-one formats."""
1172
def __init__(self, _transport, _format):
1173
"""See BzrDir.__init__."""
1174
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1175
self._control_files = lockable_files.LockableFiles(
1176
self.get_branch_transport(None),
1177
self._format._lock_file_name,
1178
self._format._lock_class)
1180
def break_lock(self):
1181
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1182
raise NotImplementedError(self.break_lock)
1184
def cloning_metadir(self, require_stacking=False):
1185
"""Produce a metadir suitable for cloning with."""
1186
if require_stacking:
1187
return format_registry.make_bzrdir('1.6')
1188
return self._format.__class__()
1190
def clone(self, url, revision_id=None, force_new_repo=False,
1191
preserve_stacking=False):
1192
"""See BzrDir.clone().
1194
force_new_repo has no effect, since this family of formats always
1195
require a new repository.
1196
preserve_stacking has no effect, since no source branch using this
1197
family of formats can be stacked, so there is no stacking to preserve.
1199
self._make_tail(url)
1200
result = self._format._initialize_for_clone(url)
1201
self.open_repository().clone(result, revision_id=revision_id)
1202
from_branch = self.open_branch()
1203
from_branch.clone(result, revision_id=revision_id)
1205
tree = self.open_workingtree()
1206
except errors.NotLocalUrl:
1207
# make a new one, this format always has to have one.
1208
result._init_workingtree()
1213
def create_branch(self):
1214
"""See BzrDir.create_branch."""
1215
return self._format.get_branch_format().initialize(self)
1217
def destroy_branch(self):
1218
"""See BzrDir.destroy_branch."""
1219
raise errors.UnsupportedOperation(self.destroy_branch, self)
1221
def create_repository(self, shared=False):
1222
"""See BzrDir.create_repository."""
1224
raise errors.IncompatibleFormat('shared repository', self._format)
1225
return self.open_repository()
1227
def destroy_repository(self):
1228
"""See BzrDir.destroy_repository."""
1229
raise errors.UnsupportedOperation(self.destroy_repository, self)
1231
def create_workingtree(self, revision_id=None, from_branch=None,
1232
accelerator_tree=None, hardlink=False):
1233
"""See BzrDir.create_workingtree."""
1234
# The workingtree is sometimes created when the bzrdir is created,
1235
# but not when cloning.
1237
# this looks buggy but is not -really-
1238
# because this format creates the workingtree when the bzrdir is
1240
# clone and sprout will have set the revision_id
1241
# and that will have set it for us, its only
1242
# specific uses of create_workingtree in isolation
1243
# that can do wonky stuff here, and that only
1244
# happens for creating checkouts, which cannot be
1245
# done on this format anyway. So - acceptable wart.
1247
result = self.open_workingtree(recommend_upgrade=False)
1248
except errors.NoSuchFile:
1249
result = self._init_workingtree()
1250
if revision_id is not None:
1251
if revision_id == _mod_revision.NULL_REVISION:
1252
result.set_parent_ids([])
1254
result.set_parent_ids([revision_id])
1257
def _init_workingtree(self):
1258
from bzrlib.workingtree import WorkingTreeFormat2
1260
return WorkingTreeFormat2().initialize(self)
1261
except errors.NotLocalUrl:
1262
# Even though we can't access the working tree, we need to
1263
# create its control files.
1264
return WorkingTreeFormat2()._stub_initialize_on_transport(
1265
self.transport, self._control_files._file_mode)
1267
def destroy_workingtree(self):
1268
"""See BzrDir.destroy_workingtree."""
1269
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1271
def destroy_workingtree_metadata(self):
1272
"""See BzrDir.destroy_workingtree_metadata."""
1273
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1276
def get_branch_transport(self, branch_format):
1277
"""See BzrDir.get_branch_transport()."""
1278
if branch_format is None:
1279
return self.transport
1281
branch_format.get_format_string()
1282
except NotImplementedError:
1283
return self.transport
1284
raise errors.IncompatibleFormat(branch_format, self._format)
1286
def get_repository_transport(self, repository_format):
1287
"""See BzrDir.get_repository_transport()."""
1288
if repository_format is None:
1289
return self.transport
1291
repository_format.get_format_string()
1292
except NotImplementedError:
1293
return self.transport
1294
raise errors.IncompatibleFormat(repository_format, self._format)
1296
def get_workingtree_transport(self, workingtree_format):
1297
"""See BzrDir.get_workingtree_transport()."""
1298
if workingtree_format is None:
1299
return self.transport
1301
workingtree_format.get_format_string()
1302
except NotImplementedError:
1303
return self.transport
1304
raise errors.IncompatibleFormat(workingtree_format, self._format)
1306
def needs_format_conversion(self, format=None):
1307
"""See BzrDir.needs_format_conversion()."""
1308
# if the format is not the same as the system default,
1309
# an upgrade is needed.
1311
format = BzrDirFormat.get_default_format()
1312
return not isinstance(self._format, format.__class__)
1314
def open_branch(self, unsupported=False):
1315
"""See BzrDir.open_branch."""
1316
from bzrlib.branch import BzrBranchFormat4
1317
format = BzrBranchFormat4()
1318
self._check_supported(format, unsupported)
1319
return format.open(self, _found=True)
1321
def sprout(self, url, revision_id=None, force_new_repo=False,
1322
possible_transports=None, accelerator_tree=None,
1323
hardlink=False, stacked=False):
1324
"""See BzrDir.sprout()."""
1326
raise errors.UnstackableBranchFormat(
1327
self._format, self.root_transport.base)
1328
from bzrlib.workingtree import WorkingTreeFormat2
1329
self._make_tail(url)
1330
result = self._format._initialize_for_clone(url)
1332
self.open_repository().clone(result, revision_id=revision_id)
1333
except errors.NoRepositoryPresent:
1336
self.open_branch().sprout(result, revision_id=revision_id)
1337
except errors.NotBranchError:
1339
# we always want a working tree
1340
WorkingTreeFormat2().initialize(result,
1341
accelerator_tree=accelerator_tree,
1346
class BzrDir4(BzrDirPreSplitOut):
1347
"""A .bzr version 4 control object.
1349
This is a deprecated format and may be removed after sept 2006.
1352
def create_repository(self, shared=False):
1353
"""See BzrDir.create_repository."""
1354
return self._format.repository_format.initialize(self, shared)
1356
def needs_format_conversion(self, format=None):
1357
"""Format 4 dirs are always in need of conversion."""
1360
def open_repository(self):
1361
"""See BzrDir.open_repository."""
1362
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1363
return RepositoryFormat4().open(self, _found=True)
1366
class BzrDir5(BzrDirPreSplitOut):
1367
"""A .bzr version 5 control object.
1369
This is a deprecated format and may be removed after sept 2006.
1372
def open_repository(self):
1373
"""See BzrDir.open_repository."""
1374
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1375
return RepositoryFormat5().open(self, _found=True)
1377
def open_workingtree(self, _unsupported=False,
1378
recommend_upgrade=True):
1379
"""See BzrDir.create_workingtree."""
1380
from bzrlib.workingtree import WorkingTreeFormat2
1381
wt_format = WorkingTreeFormat2()
1382
# we don't warn here about upgrades; that ought to be handled for the
1384
return wt_format.open(self, _found=True)
1387
class BzrDir6(BzrDirPreSplitOut):
1388
"""A .bzr version 6 control object.
1390
This is a deprecated format and may be removed after sept 2006.
1393
def open_repository(self):
1394
"""See BzrDir.open_repository."""
1395
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1396
return RepositoryFormat6().open(self, _found=True)
1398
def open_workingtree(self, _unsupported=False,
1399
recommend_upgrade=True):
1400
"""See BzrDir.create_workingtree."""
1401
# we don't warn here about upgrades; that ought to be handled for the
1403
from bzrlib.workingtree import WorkingTreeFormat2
1404
return WorkingTreeFormat2().open(self, _found=True)
1407
class BzrDirMeta1(BzrDir):
1408
"""A .bzr meta version 1 control object.
1410
This is the first control object where the
1411
individual aspects are really split out: there are separate repository,
1412
workingtree and branch subdirectories and any subset of the three can be
1413
present within a BzrDir.
1416
def can_convert_format(self):
1417
"""See BzrDir.can_convert_format()."""
1420
def create_branch(self):
1421
"""See BzrDir.create_branch."""
1422
return self._format.get_branch_format().initialize(self)
1424
def destroy_branch(self):
1425
"""See BzrDir.create_branch."""
1426
self.transport.delete_tree('branch')
1428
def create_repository(self, shared=False):
1429
"""See BzrDir.create_repository."""
1430
return self._format.repository_format.initialize(self, shared)
1432
def destroy_repository(self):
1433
"""See BzrDir.destroy_repository."""
1434
self.transport.delete_tree('repository')
1436
def create_workingtree(self, revision_id=None, from_branch=None,
1437
accelerator_tree=None, hardlink=False):
1438
"""See BzrDir.create_workingtree."""
1439
return self._format.workingtree_format.initialize(
1440
self, revision_id, from_branch=from_branch,
1441
accelerator_tree=accelerator_tree, hardlink=hardlink)
1443
def destroy_workingtree(self):
1444
"""See BzrDir.destroy_workingtree."""
1445
wt = self.open_workingtree(recommend_upgrade=False)
1446
repository = wt.branch.repository
1447
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1448
wt.revert(old_tree=empty)
1449
self.destroy_workingtree_metadata()
1451
def destroy_workingtree_metadata(self):
1452
self.transport.delete_tree('checkout')
1454
def find_branch_format(self):
1455
"""Find the branch 'format' for this bzrdir.
1457
This might be a synthetic object for e.g. RemoteBranch and SVN.
1459
from bzrlib.branch import BranchFormat
1460
return BranchFormat.find_format(self)
1462
def _get_mkdir_mode(self):
1463
"""Figure out the mode to use when creating a bzrdir subdir."""
1464
temp_control = lockable_files.LockableFiles(self.transport, '',
1465
lockable_files.TransportLock)
1466
return temp_control._dir_mode
1468
def get_branch_reference(self):
1469
"""See BzrDir.get_branch_reference()."""
1470
from bzrlib.branch import BranchFormat
1471
format = BranchFormat.find_format(self)
1472
return format.get_reference(self)
1474
def get_branch_transport(self, branch_format):
1475
"""See BzrDir.get_branch_transport()."""
1476
if branch_format is None:
1477
return self.transport.clone('branch')
1479
branch_format.get_format_string()
1480
except NotImplementedError:
1481
raise errors.IncompatibleFormat(branch_format, self._format)
1483
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1484
except errors.FileExists:
1486
return self.transport.clone('branch')
1488
def get_repository_transport(self, repository_format):
1489
"""See BzrDir.get_repository_transport()."""
1490
if repository_format is None:
1491
return self.transport.clone('repository')
1493
repository_format.get_format_string()
1494
except NotImplementedError:
1495
raise errors.IncompatibleFormat(repository_format, self._format)
1497
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1498
except errors.FileExists:
1500
return self.transport.clone('repository')
1502
def get_workingtree_transport(self, workingtree_format):
1503
"""See BzrDir.get_workingtree_transport()."""
1504
if workingtree_format is None:
1505
return self.transport.clone('checkout')
1507
workingtree_format.get_format_string()
1508
except NotImplementedError:
1509
raise errors.IncompatibleFormat(workingtree_format, self._format)
1511
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1512
except errors.FileExists:
1514
return self.transport.clone('checkout')
1516
def needs_format_conversion(self, format=None):
1517
"""See BzrDir.needs_format_conversion()."""
1519
format = BzrDirFormat.get_default_format()
1520
if not isinstance(self._format, format.__class__):
1521
# it is not a meta dir format, conversion is needed.
1523
# we might want to push this down to the repository?
1525
if not isinstance(self.open_repository()._format,
1526
format.repository_format.__class__):
1527
# the repository needs an upgrade.
1529
except errors.NoRepositoryPresent:
1532
if not isinstance(self.open_branch()._format,
1533
format.get_branch_format().__class__):
1534
# the branch needs an upgrade.
1536
except errors.NotBranchError:
1539
my_wt = self.open_workingtree(recommend_upgrade=False)
1540
if not isinstance(my_wt._format,
1541
format.workingtree_format.__class__):
1542
# the workingtree needs an upgrade.
1544
except (errors.NoWorkingTree, errors.NotLocalUrl):
1548
def open_branch(self, unsupported=False):
1549
"""See BzrDir.open_branch."""
1550
format = self.find_branch_format()
1551
self._check_supported(format, unsupported)
1552
return format.open(self, _found=True)
1554
def open_repository(self, unsupported=False):
1555
"""See BzrDir.open_repository."""
1556
from bzrlib.repository import RepositoryFormat
1557
format = RepositoryFormat.find_format(self)
1558
self._check_supported(format, unsupported)
1559
return format.open(self, _found=True)
1561
def open_workingtree(self, unsupported=False,
1562
recommend_upgrade=True):
1563
"""See BzrDir.open_workingtree."""
1564
from bzrlib.workingtree import WorkingTreeFormat
1565
format = WorkingTreeFormat.find_format(self)
1566
self._check_supported(format, unsupported,
1568
basedir=self.root_transport.base)
1569
return format.open(self, _found=True)
1571
def _get_config(self):
1572
return config.BzrDirConfig(self.transport)
1575
class BzrDirFormat(object):
1576
"""An encapsulation of the initialization and open routines for a format.
1578
Formats provide three things:
1579
* An initialization routine,
1583
Formats are placed in a dict by their format string for reference
1584
during bzrdir opening. These should be subclasses of BzrDirFormat
1587
Once a format is deprecated, just deprecate the initialize and open
1588
methods on the format class. Do not deprecate the object, as the
1589
object will be created every system load.
1592
_default_format = None
1593
"""The default format used for new .bzr dirs."""
1596
"""The known formats."""
1598
_control_formats = []
1599
"""The registered control formats - .bzr, ....
1601
This is a list of BzrDirFormat objects.
1604
_control_server_formats = []
1605
"""The registered control server formats, e.g. RemoteBzrDirs.
1607
This is a list of BzrDirFormat objects.
1610
_lock_file_name = 'branch-lock'
1612
# _lock_class must be set in subclasses to the lock type, typ.
1613
# TransportLock or LockDir
1616
def find_format(klass, transport, _server_formats=True):
1617
"""Return the format present at transport."""
1619
formats = klass._control_server_formats + klass._control_formats
1621
formats = klass._control_formats
1622
for format in formats:
1624
return format.probe_transport(transport)
1625
except errors.NotBranchError:
1626
# this format does not find a control dir here.
1628
raise errors.NotBranchError(path=transport.base)
1631
def probe_transport(klass, transport):
1632
"""Return the .bzrdir style format present in a directory."""
1634
format_string = transport.get(".bzr/branch-format").read()
1635
except errors.NoSuchFile:
1636
raise errors.NotBranchError(path=transport.base)
1639
return klass._formats[format_string]
1641
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1644
def get_default_format(klass):
1645
"""Return the current default format."""
1646
return klass._default_format
1648
def get_format_string(self):
1649
"""Return the ASCII format string that identifies this format."""
1650
raise NotImplementedError(self.get_format_string)
1652
def get_format_description(self):
1653
"""Return the short description for this format."""
1654
raise NotImplementedError(self.get_format_description)
1656
def get_converter(self, format=None):
1657
"""Return the converter to use to convert bzrdirs needing converts.
1659
This returns a bzrlib.bzrdir.Converter object.
1661
This should return the best upgrader to step this format towards the
1662
current default format. In the case of plugins we can/should provide
1663
some means for them to extend the range of returnable converters.
1665
:param format: Optional format to override the default format of the
1668
raise NotImplementedError(self.get_converter)
1670
def initialize(self, url, possible_transports=None):
1671
"""Create a bzr control dir at this url and return an opened copy.
1673
Subclasses should typically override initialize_on_transport
1674
instead of this method.
1676
return self.initialize_on_transport(get_transport(url,
1677
possible_transports))
1679
def initialize_on_transport(self, transport):
1680
"""Initialize a new bzrdir in the base directory of a Transport."""
1681
# Since we don't have a .bzr directory, inherit the
1682
# mode from the root directory
1683
temp_control = lockable_files.LockableFiles(transport,
1684
'', lockable_files.TransportLock)
1685
temp_control._transport.mkdir('.bzr',
1686
# FIXME: RBC 20060121 don't peek under
1688
mode=temp_control._dir_mode)
1689
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1690
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1691
file_mode = temp_control._file_mode
1693
bzrdir_transport = transport.clone('.bzr')
1694
utf8_files = [('README',
1695
"This is a Bazaar control directory.\n"
1696
"Do not change any files in this directory.\n"
1697
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1698
('branch-format', self.get_format_string()),
1700
# NB: no need to escape relative paths that are url safe.
1701
control_files = lockable_files.LockableFiles(bzrdir_transport,
1702
self._lock_file_name, self._lock_class)
1703
control_files.create_lock()
1704
control_files.lock_write()
1706
for (filename, content) in utf8_files:
1707
bzrdir_transport.put_bytes(filename, content,
1710
control_files.unlock()
1711
return self.open(transport, _found=True)
1713
def is_supported(self):
1714
"""Is this format supported?
1716
Supported formats must be initializable and openable.
1717
Unsupported formats may not support initialization or committing or
1718
some other features depending on the reason for not being supported.
1722
def same_model(self, target_format):
1723
return (self.repository_format.rich_root_data ==
1724
target_format.rich_root_data)
1727
def known_formats(klass):
1728
"""Return all the known formats.
1730
Concrete formats should override _known_formats.
1732
# There is double indirection here to make sure that control
1733
# formats used by more than one dir format will only be probed
1734
# once. This can otherwise be quite expensive for remote connections.
1736
for format in klass._control_formats:
1737
result.update(format._known_formats())
1741
def _known_formats(klass):
1742
"""Return the known format instances for this control format."""
1743
return set(klass._formats.values())
1745
def open(self, transport, _found=False):
1746
"""Return an instance of this format for the dir transport points at.
1748
_found is a private parameter, do not use it.
1751
found_format = BzrDirFormat.find_format(transport)
1752
if not isinstance(found_format, self.__class__):
1753
raise AssertionError("%s was asked to open %s, but it seems to need "
1755
% (self, transport, found_format))
1756
return self._open(transport)
1758
def _open(self, transport):
1759
"""Template method helper for opening BzrDirectories.
1761
This performs the actual open and any additional logic or parameter
1764
raise NotImplementedError(self._open)
1767
def register_format(klass, format):
1768
klass._formats[format.get_format_string()] = format
1771
def register_control_format(klass, format):
1772
"""Register a format that does not use '.bzr' for its control dir.
1774
TODO: This should be pulled up into a 'ControlDirFormat' base class
1775
which BzrDirFormat can inherit from, and renamed to register_format
1776
there. It has been done without that for now for simplicity of
1779
klass._control_formats.append(format)
1782
def register_control_server_format(klass, format):
1783
"""Register a control format for client-server environments.
1785
These formats will be tried before ones registered with
1786
register_control_format. This gives implementations that decide to the
1787
chance to grab it before anything looks at the contents of the format
1790
klass._control_server_formats.append(format)
1793
def _set_default_format(klass, format):
1794
"""Set default format (for testing behavior of defaults only)"""
1795
klass._default_format = format
1799
return self.get_format_string().rstrip()
1802
def unregister_format(klass, format):
1803
del klass._formats[format.get_format_string()]
1806
def unregister_control_format(klass, format):
1807
klass._control_formats.remove(format)
1810
class BzrDirFormat4(BzrDirFormat):
1811
"""Bzr dir format 4.
1813
This format is a combined format for working tree, branch and repository.
1815
- Format 1 working trees [always]
1816
- Format 4 branches [always]
1817
- Format 4 repositories [always]
1819
This format is deprecated: it indexes texts using a text it which is
1820
removed in format 5; write support for this format has been removed.
1823
_lock_class = lockable_files.TransportLock
1825
def get_format_string(self):
1826
"""See BzrDirFormat.get_format_string()."""
1827
return "Bazaar-NG branch, format 0.0.4\n"
1829
def get_format_description(self):
1830
"""See BzrDirFormat.get_format_description()."""
1831
return "All-in-one format 4"
1833
def get_converter(self, format=None):
1834
"""See BzrDirFormat.get_converter()."""
1835
# there is one and only one upgrade path here.
1836
return ConvertBzrDir4To5()
1838
def initialize_on_transport(self, transport):
1839
"""Format 4 branches cannot be created."""
1840
raise errors.UninitializableFormat(self)
1842
def is_supported(self):
1843
"""Format 4 is not supported.
1845
It is not supported because the model changed from 4 to 5 and the
1846
conversion logic is expensive - so doing it on the fly was not
1851
def _open(self, transport):
1852
"""See BzrDirFormat._open."""
1853
return BzrDir4(transport, self)
1855
def __return_repository_format(self):
1856
"""Circular import protection."""
1857
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1858
return RepositoryFormat4()
1859
repository_format = property(__return_repository_format)
1862
class BzrDirFormat5(BzrDirFormat):
1863
"""Bzr control format 5.
1865
This format is a combined format for working tree, branch and repository.
1867
- Format 2 working trees [always]
1868
- Format 4 branches [always]
1869
- Format 5 repositories [always]
1870
Unhashed stores in the repository.
1873
_lock_class = lockable_files.TransportLock
1875
def get_format_string(self):
1876
"""See BzrDirFormat.get_format_string()."""
1877
return "Bazaar-NG branch, format 5\n"
1879
def get_branch_format(self):
1880
from bzrlib import branch
1881
return branch.BzrBranchFormat4()
1883
def get_format_description(self):
1884
"""See BzrDirFormat.get_format_description()."""
1885
return "All-in-one format 5"
1887
def get_converter(self, format=None):
1888
"""See BzrDirFormat.get_converter()."""
1889
# there is one and only one upgrade path here.
1890
return ConvertBzrDir5To6()
1892
def _initialize_for_clone(self, url):
1893
return self.initialize_on_transport(get_transport(url), _cloning=True)
1895
def initialize_on_transport(self, transport, _cloning=False):
1896
"""Format 5 dirs always have working tree, branch and repository.
1898
Except when they are being cloned.
1900
from bzrlib.branch import BzrBranchFormat4
1901
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1902
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1903
RepositoryFormat5().initialize(result, _internal=True)
1905
branch = BzrBranchFormat4().initialize(result)
1906
result._init_workingtree()
1909
def _open(self, transport):
1910
"""See BzrDirFormat._open."""
1911
return BzrDir5(transport, self)
1913
def __return_repository_format(self):
1914
"""Circular import protection."""
1915
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1916
return RepositoryFormat5()
1917
repository_format = property(__return_repository_format)
1920
class BzrDirFormat6(BzrDirFormat):
1921
"""Bzr control format 6.
1923
This format is a combined format for working tree, branch and repository.
1925
- Format 2 working trees [always]
1926
- Format 4 branches [always]
1927
- Format 6 repositories [always]
1930
_lock_class = lockable_files.TransportLock
1932
def get_format_string(self):
1933
"""See BzrDirFormat.get_format_string()."""
1934
return "Bazaar-NG branch, format 6\n"
1936
def get_format_description(self):
1937
"""See BzrDirFormat.get_format_description()."""
1938
return "All-in-one format 6"
1940
def get_branch_format(self):
1941
from bzrlib import branch
1942
return branch.BzrBranchFormat4()
1944
def get_converter(self, format=None):
1945
"""See BzrDirFormat.get_converter()."""
1946
# there is one and only one upgrade path here.
1947
return ConvertBzrDir6ToMeta()
1949
def _initialize_for_clone(self, url):
1950
return self.initialize_on_transport(get_transport(url), _cloning=True)
1952
def initialize_on_transport(self, transport, _cloning=False):
1953
"""Format 6 dirs always have working tree, branch and repository.
1955
Except when they are being cloned.
1957
from bzrlib.branch import BzrBranchFormat4
1958
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1959
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1960
RepositoryFormat6().initialize(result, _internal=True)
1962
branch = BzrBranchFormat4().initialize(result)
1963
result._init_workingtree()
1966
def _open(self, transport):
1967
"""See BzrDirFormat._open."""
1968
return BzrDir6(transport, self)
1970
def __return_repository_format(self):
1971
"""Circular import protection."""
1972
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1973
return RepositoryFormat6()
1974
repository_format = property(__return_repository_format)
1977
class BzrDirMetaFormat1(BzrDirFormat):
1978
"""Bzr meta control format 1
1980
This is the first format with split out working tree, branch and repository
1983
- Format 3 working trees [optional]
1984
- Format 5 branches [optional]
1985
- Format 7 repositories [optional]
1988
_lock_class = lockdir.LockDir
1991
self._workingtree_format = None
1992
self._branch_format = None
1994
def __eq__(self, other):
1995
if other.__class__ is not self.__class__:
1997
if other.repository_format != self.repository_format:
1999
if other.workingtree_format != self.workingtree_format:
2003
def __ne__(self, other):
2004
return not self == other
2006
def get_branch_format(self):
2007
if self._branch_format is None:
2008
from bzrlib.branch import BranchFormat
2009
self._branch_format = BranchFormat.get_default_format()
2010
return self._branch_format
2012
def set_branch_format(self, format):
2013
self._branch_format = format
2015
def require_stacking(self):
2016
if not self.get_branch_format().supports_stacking():
2017
# We need to make a stacked branch, but the default format for the
2018
# target doesn't support stacking. So force a branch that *can*
2020
from bzrlib.branch import BzrBranchFormat7
2021
self._branch_format = BzrBranchFormat7()
2022
mutter("using %r for stacking" % (self._branch_format,))
2023
from bzrlib.repofmt import pack_repo
2024
if self.repository_format.rich_root_data:
2025
bzrdir_format_name = '1.6.1-rich-root'
2026
repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2028
bzrdir_format_name = '1.6'
2029
repo_format = pack_repo.RepositoryFormatKnitPack5()
2030
note('Source format does not support stacking, using format:'
2032
bzrdir_format_name, repo_format.get_format_description())
2033
self.repository_format = repo_format
2035
def get_converter(self, format=None):
2036
"""See BzrDirFormat.get_converter()."""
2038
format = BzrDirFormat.get_default_format()
2039
if not isinstance(self, format.__class__):
2040
# converting away from metadir is not implemented
2041
raise NotImplementedError(self.get_converter)
2042
return ConvertMetaToMeta(format)
2044
def get_format_string(self):
2045
"""See BzrDirFormat.get_format_string()."""
2046
return "Bazaar-NG meta directory, format 1\n"
2048
def get_format_description(self):
2049
"""See BzrDirFormat.get_format_description()."""
2050
return "Meta directory format 1"
2052
def _open(self, transport):
2053
"""See BzrDirFormat._open."""
2054
return BzrDirMeta1(transport, self)
2056
def __return_repository_format(self):
2057
"""Circular import protection."""
2058
if getattr(self, '_repository_format', None):
2059
return self._repository_format
2060
from bzrlib.repository import RepositoryFormat
2061
return RepositoryFormat.get_default_format()
2063
def __set_repository_format(self, value):
2064
"""Allow changing the repository format for metadir formats."""
2065
self._repository_format = value
2067
repository_format = property(__return_repository_format, __set_repository_format)
2069
def __get_workingtree_format(self):
2070
if self._workingtree_format is None:
2071
from bzrlib.workingtree import WorkingTreeFormat
2072
self._workingtree_format = WorkingTreeFormat.get_default_format()
2073
return self._workingtree_format
2075
def __set_workingtree_format(self, wt_format):
2076
self._workingtree_format = wt_format
2078
workingtree_format = property(__get_workingtree_format,
2079
__set_workingtree_format)
2082
# Register bzr control format
2083
BzrDirFormat.register_control_format(BzrDirFormat)
2085
# Register bzr formats
2086
BzrDirFormat.register_format(BzrDirFormat4())
2087
BzrDirFormat.register_format(BzrDirFormat5())
2088
BzrDirFormat.register_format(BzrDirFormat6())
2089
__default_format = BzrDirMetaFormat1()
2090
BzrDirFormat.register_format(__default_format)
2091
BzrDirFormat._default_format = __default_format
2094
class Converter(object):
2095
"""Converts a disk format object from one format to another."""
2097
def convert(self, to_convert, pb):
2098
"""Perform the conversion of to_convert, giving feedback via pb.
2100
:param to_convert: The disk object to convert.
2101
:param pb: a progress bar to use for progress information.
2104
def step(self, message):
2105
"""Update the pb by a step."""
2107
self.pb.update(message, self.count, self.total)
2110
class ConvertBzrDir4To5(Converter):
2111
"""Converts format 4 bzr dirs to format 5."""
2114
super(ConvertBzrDir4To5, self).__init__()
2115
self.converted_revs = set()
2116
self.absent_revisions = set()
2120
def convert(self, to_convert, pb):
2121
"""See Converter.convert()."""
2122
self.bzrdir = to_convert
2124
self.pb.note('starting upgrade from format 4 to 5')
2125
if isinstance(self.bzrdir.transport, local.LocalTransport):
2126
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2127
self._convert_to_weaves()
2128
return BzrDir.open(self.bzrdir.root_transport.base)
2130
def _convert_to_weaves(self):
2131
self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2134
stat = self.bzrdir.transport.stat('weaves')
2135
if not S_ISDIR(stat.st_mode):
2136
self.bzrdir.transport.delete('weaves')
2137
self.bzrdir.transport.mkdir('weaves')
2138
except errors.NoSuchFile:
2139
self.bzrdir.transport.mkdir('weaves')
2140
# deliberately not a WeaveFile as we want to build it up slowly.
2141
self.inv_weave = Weave('inventory')
2142
# holds in-memory weaves for all files
2143
self.text_weaves = {}
2144
self.bzrdir.transport.delete('branch-format')
2145
self.branch = self.bzrdir.open_branch()
2146
self._convert_working_inv()
2147
rev_history = self.branch.revision_history()
2148
# to_read is a stack holding the revisions we still need to process;
2149
# appending to it adds new highest-priority revisions
2150
self.known_revisions = set(rev_history)
2151
self.to_read = rev_history[-1:]
2153
rev_id = self.to_read.pop()
2154
if (rev_id not in self.revisions
2155
and rev_id not in self.absent_revisions):
2156
self._load_one_rev(rev_id)
2158
to_import = self._make_order()
2159
for i, rev_id in enumerate(to_import):
2160
self.pb.update('converting revision', i, len(to_import))
2161
self._convert_one_rev(rev_id)
2163
self._write_all_weaves()
2164
self._write_all_revs()
2165
self.pb.note('upgraded to weaves:')
2166
self.pb.note(' %6d revisions and inventories', len(self.revisions))
2167
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
2168
self.pb.note(' %6d texts', self.text_count)
2169
self._cleanup_spare_files_after_format4()
2170
self.branch._transport.put_bytes(
2172
BzrDirFormat5().get_format_string(),
2173
mode=self.bzrdir._get_file_mode())
2175
def _cleanup_spare_files_after_format4(self):
2176
# FIXME working tree upgrade foo.
2177
for n in 'merged-patches', 'pending-merged-patches':
2179
## assert os.path.getsize(p) == 0
2180
self.bzrdir.transport.delete(n)
2181
except errors.NoSuchFile:
2183
self.bzrdir.transport.delete_tree('inventory-store')
2184
self.bzrdir.transport.delete_tree('text-store')
2186
def _convert_working_inv(self):
2187
inv = xml4.serializer_v4.read_inventory(
2188
self.branch._transport.get('inventory'))
2189
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2190
self.branch._transport.put_bytes('inventory', new_inv_xml,
2191
mode=self.bzrdir._get_file_mode())
2193
def _write_all_weaves(self):
2194
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2195
weave_transport = self.bzrdir.transport.clone('weaves')
2196
weaves = WeaveStore(weave_transport, prefixed=False)
2197
transaction = WriteTransaction()
2201
for file_id, file_weave in self.text_weaves.items():
2202
self.pb.update('writing weave', i, len(self.text_weaves))
2203
weaves._put_weave(file_id, file_weave, transaction)
2205
self.pb.update('inventory', 0, 1)
2206
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2207
self.pb.update('inventory', 1, 1)
2211
def _write_all_revs(self):
2212
"""Write all revisions out in new form."""
2213
self.bzrdir.transport.delete_tree('revision-store')
2214
self.bzrdir.transport.mkdir('revision-store')
2215
revision_transport = self.bzrdir.transport.clone('revision-store')
2217
from bzrlib.xml5 import serializer_v5
2218
from bzrlib.repofmt.weaverepo import RevisionTextStore
2219
revision_store = RevisionTextStore(revision_transport,
2220
serializer_v5, False, versionedfile.PrefixMapper(),
2221
lambda:True, lambda:True)
2223
for i, rev_id in enumerate(self.converted_revs):
2224
self.pb.update('write revision', i, len(self.converted_revs))
2225
text = serializer_v5.write_revision_to_string(
2226
self.revisions[rev_id])
2228
revision_store.add_lines(key, None, osutils.split_lines(text))
2232
def _load_one_rev(self, rev_id):
2233
"""Load a revision object into memory.
2235
Any parents not either loaded or abandoned get queued to be
2237
self.pb.update('loading revision',
2238
len(self.revisions),
2239
len(self.known_revisions))
2240
if not self.branch.repository.has_revision(rev_id):
2242
self.pb.note('revision {%s} not present in branch; '
2243
'will be converted as a ghost',
2245
self.absent_revisions.add(rev_id)
2247
rev = self.branch.repository.get_revision(rev_id)
2248
for parent_id in rev.parent_ids:
2249
self.known_revisions.add(parent_id)
2250
self.to_read.append(parent_id)
2251
self.revisions[rev_id] = rev
2253
def _load_old_inventory(self, rev_id):
2254
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2255
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2256
inv.revision_id = rev_id
2257
rev = self.revisions[rev_id]
2260
def _load_updated_inventory(self, rev_id):
2261
inv_xml = self.inv_weave.get_text(rev_id)
2262
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2265
def _convert_one_rev(self, rev_id):
2266
"""Convert revision and all referenced objects to new format."""
2267
rev = self.revisions[rev_id]
2268
inv = self._load_old_inventory(rev_id)
2269
present_parents = [p for p in rev.parent_ids
2270
if p not in self.absent_revisions]
2271
self._convert_revision_contents(rev, inv, present_parents)
2272
self._store_new_inv(rev, inv, present_parents)
2273
self.converted_revs.add(rev_id)
2275
def _store_new_inv(self, rev, inv, present_parents):
2276
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2277
new_inv_sha1 = sha_string(new_inv_xml)
2278
self.inv_weave.add_lines(rev.revision_id,
2280
new_inv_xml.splitlines(True))
2281
rev.inventory_sha1 = new_inv_sha1
2283
def _convert_revision_contents(self, rev, inv, present_parents):
2284
"""Convert all the files within a revision.
2286
Also upgrade the inventory to refer to the text revision ids."""
2287
rev_id = rev.revision_id
2288
mutter('converting texts of revision {%s}',
2290
parent_invs = map(self._load_updated_inventory, present_parents)
2291
entries = inv.iter_entries()
2293
for path, ie in entries:
2294
self._convert_file_version(rev, ie, parent_invs)
2296
def _convert_file_version(self, rev, ie, parent_invs):
2297
"""Convert one version of one file.
2299
The file needs to be added into the weave if it is a merge
2300
of >=2 parents or if it's changed from its parent.
2302
file_id = ie.file_id
2303
rev_id = rev.revision_id
2304
w = self.text_weaves.get(file_id)
2307
self.text_weaves[file_id] = w
2308
text_changed = False
2309
parent_candiate_entries = ie.parent_candidates(parent_invs)
2310
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2311
# XXX: Note that this is unordered - and this is tolerable because
2312
# the previous code was also unordered.
2313
previous_entries = dict((head, parent_candiate_entries[head]) for head
2315
self.snapshot_ie(previous_entries, ie, w, rev_id)
2318
@symbol_versioning.deprecated_method(symbol_versioning.one_one)
2319
def get_parents(self, revision_ids):
2320
for revision_id in revision_ids:
2321
yield self.revisions[revision_id].parent_ids
2323
def get_parent_map(self, revision_ids):
2324
"""See graph._StackedParentsProvider.get_parent_map"""
2325
return dict((revision_id, self.revisions[revision_id])
2326
for revision_id in revision_ids
2327
if revision_id in self.revisions)
2329
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2330
# TODO: convert this logic, which is ~= snapshot to
2331
# a call to:. This needs the path figured out. rather than a work_tree
2332
# a v4 revision_tree can be given, or something that looks enough like
2333
# one to give the file content to the entry if it needs it.
2334
# and we need something that looks like a weave store for snapshot to
2336
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2337
if len(previous_revisions) == 1:
2338
previous_ie = previous_revisions.values()[0]
2339
if ie._unchanged(previous_ie):
2340
ie.revision = previous_ie.revision
2343
text = self.branch.repository._text_store.get(ie.text_id)
2344
file_lines = text.readlines()
2345
w.add_lines(rev_id, previous_revisions, file_lines)
2346
self.text_count += 1
2348
w.add_lines(rev_id, previous_revisions, [])
2349
ie.revision = rev_id
2351
def _make_order(self):
2352
"""Return a suitable order for importing revisions.
2354
The order must be such that an revision is imported after all
2355
its (present) parents.
2357
todo = set(self.revisions.keys())
2358
done = self.absent_revisions.copy()
2361
# scan through looking for a revision whose parents
2363
for rev_id in sorted(list(todo)):
2364
rev = self.revisions[rev_id]
2365
parent_ids = set(rev.parent_ids)
2366
if parent_ids.issubset(done):
2367
# can take this one now
2368
order.append(rev_id)
2374
class ConvertBzrDir5To6(Converter):
2375
"""Converts format 5 bzr dirs to format 6."""
2377
def convert(self, to_convert, pb):
2378
"""See Converter.convert()."""
2379
self.bzrdir = to_convert
2381
self.pb.note('starting upgrade from format 5 to 6')
2382
self._convert_to_prefixed()
2383
return BzrDir.open(self.bzrdir.root_transport.base)
2385
def _convert_to_prefixed(self):
2386
from bzrlib.store import TransportStore
2387
self.bzrdir.transport.delete('branch-format')
2388
for store_name in ["weaves", "revision-store"]:
2389
self.pb.note("adding prefixes to %s" % store_name)
2390
store_transport = self.bzrdir.transport.clone(store_name)
2391
store = TransportStore(store_transport, prefixed=True)
2392
for urlfilename in store_transport.list_dir('.'):
2393
filename = urlutils.unescape(urlfilename)
2394
if (filename.endswith(".weave") or
2395
filename.endswith(".gz") or
2396
filename.endswith(".sig")):
2397
file_id, suffix = os.path.splitext(filename)
2401
new_name = store._mapper.map((file_id,)) + suffix
2402
# FIXME keep track of the dirs made RBC 20060121
2404
store_transport.move(filename, new_name)
2405
except errors.NoSuchFile: # catches missing dirs strangely enough
2406
store_transport.mkdir(osutils.dirname(new_name))
2407
store_transport.move(filename, new_name)
2408
self.bzrdir.transport.put_bytes(
2410
BzrDirFormat6().get_format_string(),
2411
mode=self.bzrdir._get_file_mode())
2414
class ConvertBzrDir6ToMeta(Converter):
2415
"""Converts format 6 bzr dirs to metadirs."""
2417
def convert(self, to_convert, pb):
2418
"""See Converter.convert()."""
2419
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2420
from bzrlib.branch import BzrBranchFormat5
2421
self.bzrdir = to_convert
2424
self.total = 20 # the steps we know about
2425
self.garbage_inventories = []
2426
self.dir_mode = self.bzrdir._get_dir_mode()
2427
self.file_mode = self.bzrdir._get_file_mode()
2429
self.pb.note('starting upgrade from format 6 to metadir')
2430
self.bzrdir.transport.put_bytes(
2432
"Converting to format 6",
2433
mode=self.file_mode)
2434
# its faster to move specific files around than to open and use the apis...
2435
# first off, nuke ancestry.weave, it was never used.
2437
self.step('Removing ancestry.weave')
2438
self.bzrdir.transport.delete('ancestry.weave')
2439
except errors.NoSuchFile:
2441
# find out whats there
2442
self.step('Finding branch files')
2443
last_revision = self.bzrdir.open_branch().last_revision()
2444
bzrcontents = self.bzrdir.transport.list_dir('.')
2445
for name in bzrcontents:
2446
if name.startswith('basis-inventory.'):
2447
self.garbage_inventories.append(name)
2448
# create new directories for repository, working tree and branch
2449
repository_names = [('inventory.weave', True),
2450
('revision-store', True),
2452
self.step('Upgrading repository ')
2453
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2454
self.make_lock('repository')
2455
# we hard code the formats here because we are converting into
2456
# the meta format. The meta format upgrader can take this to a
2457
# future format within each component.
2458
self.put_format('repository', RepositoryFormat7())
2459
for entry in repository_names:
2460
self.move_entry('repository', entry)
2462
self.step('Upgrading branch ')
2463
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2464
self.make_lock('branch')
2465
self.put_format('branch', BzrBranchFormat5())
2466
branch_files = [('revision-history', True),
2467
('branch-name', True),
2469
for entry in branch_files:
2470
self.move_entry('branch', entry)
2472
checkout_files = [('pending-merges', True),
2473
('inventory', True),
2474
('stat-cache', False)]
2475
# If a mandatory checkout file is not present, the branch does not have
2476
# a functional checkout. Do not create a checkout in the converted
2478
for name, mandatory in checkout_files:
2479
if mandatory and name not in bzrcontents:
2480
has_checkout = False
2484
if not has_checkout:
2485
self.pb.note('No working tree.')
2486
# If some checkout files are there, we may as well get rid of them.
2487
for name, mandatory in checkout_files:
2488
if name in bzrcontents:
2489
self.bzrdir.transport.delete(name)
2491
from bzrlib.workingtree import WorkingTreeFormat3
2492
self.step('Upgrading working tree')
2493
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2494
self.make_lock('checkout')
2496
'checkout', WorkingTreeFormat3())
2497
self.bzrdir.transport.delete_multi(
2498
self.garbage_inventories, self.pb)
2499
for entry in checkout_files:
2500
self.move_entry('checkout', entry)
2501
if last_revision is not None:
2502
self.bzrdir.transport.put_bytes(
2503
'checkout/last-revision', last_revision)
2504
self.bzrdir.transport.put_bytes(
2506
BzrDirMetaFormat1().get_format_string(),
2507
mode=self.file_mode)
2508
return BzrDir.open(self.bzrdir.root_transport.base)
2510
def make_lock(self, name):
2511
"""Make a lock for the new control dir name."""
2512
self.step('Make %s lock' % name)
2513
ld = lockdir.LockDir(self.bzrdir.transport,
2515
file_modebits=self.file_mode,
2516
dir_modebits=self.dir_mode)
2519
def move_entry(self, new_dir, entry):
2520
"""Move then entry name into new_dir."""
2522
mandatory = entry[1]
2523
self.step('Moving %s' % name)
2525
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2526
except errors.NoSuchFile:
2530
def put_format(self, dirname, format):
2531
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2532
format.get_format_string(),
2536
class ConvertMetaToMeta(Converter):
2537
"""Converts the components of metadirs."""
2539
def __init__(self, target_format):
2540
"""Create a metadir to metadir converter.
2542
:param target_format: The final metadir format that is desired.
2544
self.target_format = target_format
2546
def convert(self, to_convert, pb):
2547
"""See Converter.convert()."""
2548
self.bzrdir = to_convert
2552
self.step('checking repository format')
2554
repo = self.bzrdir.open_repository()
2555
except errors.NoRepositoryPresent:
2558
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2559
from bzrlib.repository import CopyConverter
2560
self.pb.note('starting repository conversion')
2561
converter = CopyConverter(self.target_format.repository_format)
2562
converter.convert(repo, pb)
2564
branch = self.bzrdir.open_branch()
2565
except errors.NotBranchError:
2568
# TODO: conversions of Branch and Tree should be done by
2569
# InterXFormat lookups/some sort of registry.
2570
# Avoid circular imports
2571
from bzrlib import branch as _mod_branch
2572
old = branch._format.__class__
2573
new = self.target_format.get_branch_format().__class__
2575
if (old == _mod_branch.BzrBranchFormat5 and
2576
new in (_mod_branch.BzrBranchFormat6,
2577
_mod_branch.BzrBranchFormat7)):
2578
branch_converter = _mod_branch.Converter5to6()
2579
elif (old == _mod_branch.BzrBranchFormat6 and
2580
new == _mod_branch.BzrBranchFormat7):
2581
branch_converter = _mod_branch.Converter6to7()
2583
raise errors.BadConversionTarget("No converter", new)
2584
branch_converter.convert(branch)
2585
branch = self.bzrdir.open_branch()
2586
old = branch._format.__class__
2588
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2589
except (errors.NoWorkingTree, errors.NotLocalUrl):
2592
# TODO: conversions of Branch and Tree should be done by
2593
# InterXFormat lookups
2594
if (isinstance(tree, workingtree.WorkingTree3) and
2595
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2596
isinstance(self.target_format.workingtree_format,
2597
workingtree_4.DirStateWorkingTreeFormat)):
2598
workingtree_4.Converter3to4().convert(tree)
2599
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2600
not isinstance(tree, workingtree_4.WorkingTree5) and
2601
isinstance(self.target_format.workingtree_format,
2602
workingtree_4.WorkingTreeFormat5)):
2603
workingtree_4.Converter4to5().convert(tree)
2607
# This is not in remote.py because it's small, and needs to be registered.
2608
# Putting it in remote.py creates a circular import problem.
2609
# we can make it a lazy object if the control formats is turned into something
2611
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2612
"""Format representing bzrdirs accessed via a smart server"""
2614
def get_format_description(self):
2615
return 'bzr remote bzrdir'
2618
def probe_transport(klass, transport):
2619
"""Return a RemoteBzrDirFormat object if it looks possible."""
2621
medium = transport.get_smart_medium()
2622
except (NotImplementedError, AttributeError,
2623
errors.TransportNotPossible, errors.NoSmartMedium,
2624
errors.SmartProtocolError):
2625
# no smart server, so not a branch for this format type.
2626
raise errors.NotBranchError(path=transport.base)
2628
# Decline to open it if the server doesn't support our required
2629
# version (3) so that the VFS-based transport will do it.
2630
if medium.should_probe():
2632
server_version = medium.protocol_version()
2633
except errors.SmartProtocolError:
2634
# Apparently there's no usable smart server there, even though
2635
# the medium supports the smart protocol.
2636
raise errors.NotBranchError(path=transport.base)
2637
if server_version != '2':
2638
raise errors.NotBranchError(path=transport.base)
2641
def initialize_on_transport(self, transport):
2643
# hand off the request to the smart server
2644
client_medium = transport.get_smart_medium()
2645
except errors.NoSmartMedium:
2646
# TODO: lookup the local format from a server hint.
2647
local_dir_format = BzrDirMetaFormat1()
2648
return local_dir_format.initialize_on_transport(transport)
2649
client = _SmartClient(client_medium)
2650
path = client.remote_path_from_transport(transport)
2651
response = client.call('BzrDirFormat.initialize', path)
2652
if response[0] != 'ok':
2653
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2654
return remote.RemoteBzrDir(transport)
2656
def _open(self, transport):
2657
return remote.RemoteBzrDir(transport)
2659
def __eq__(self, other):
2660
if not isinstance(other, RemoteBzrDirFormat):
2662
return self.get_format_description() == other.get_format_description()
2665
def repository_format(self):
2666
# Using a property to avoid early loading of remote
2667
return remote.RemoteRepositoryFormat()
2670
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2673
class BzrDirFormatInfo(object):
2675
def __init__(self, native, deprecated, hidden, experimental):
2676
self.deprecated = deprecated
2677
self.native = native
2678
self.hidden = hidden
2679
self.experimental = experimental
2682
class BzrDirFormatRegistry(registry.Registry):
2683
"""Registry of user-selectable BzrDir subformats.
2685
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2686
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2690
"""Create a BzrDirFormatRegistry."""
2691
self._aliases = set()
2692
self._registration_order = list()
2693
super(BzrDirFormatRegistry, self).__init__()
2696
"""Return a set of the format names which are aliases."""
2697
return frozenset(self._aliases)
2699
def register_metadir(self, key,
2700
repository_format, help, native=True, deprecated=False,
2706
"""Register a metadir subformat.
2708
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2709
by the Repository format.
2711
:param repository_format: The fully-qualified repository format class
2713
:param branch_format: Fully-qualified branch format class name as
2715
:param tree_format: Fully-qualified tree format class name as
2718
# This should be expanded to support setting WorkingTree and Branch
2719
# formats, once BzrDirMetaFormat1 supports that.
2720
def _load(full_name):
2721
mod_name, factory_name = full_name.rsplit('.', 1)
2723
mod = __import__(mod_name, globals(), locals(),
2725
except ImportError, e:
2726
raise ImportError('failed to load %s: %s' % (full_name, e))
2728
factory = getattr(mod, factory_name)
2729
except AttributeError:
2730
raise AttributeError('no factory %s in module %r'
2735
bd = BzrDirMetaFormat1()
2736
if branch_format is not None:
2737
bd.set_branch_format(_load(branch_format))
2738
if tree_format is not None:
2739
bd.workingtree_format = _load(tree_format)
2740
if repository_format is not None:
2741
bd.repository_format = _load(repository_format)
2743
self.register(key, helper, help, native, deprecated, hidden,
2744
experimental, alias)
2746
def register(self, key, factory, help, native=True, deprecated=False,
2747
hidden=False, experimental=False, alias=False):
2748
"""Register a BzrDirFormat factory.
2750
The factory must be a callable that takes one parameter: the key.
2751
It must produce an instance of the BzrDirFormat when called.
2753
This function mainly exists to prevent the info object from being
2756
registry.Registry.register(self, key, factory, help,
2757
BzrDirFormatInfo(native, deprecated, hidden, experimental))
2759
self._aliases.add(key)
2760
self._registration_order.append(key)
2762
def register_lazy(self, key, module_name, member_name, help, native=True,
2763
deprecated=False, hidden=False, experimental=False, alias=False):
2764
registry.Registry.register_lazy(self, key, module_name, member_name,
2765
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
2767
self._aliases.add(key)
2768
self._registration_order.append(key)
2770
def set_default(self, key):
2771
"""Set the 'default' key to be a clone of the supplied key.
2773
This method must be called once and only once.
2775
registry.Registry.register(self, 'default', self.get(key),
2776
self.get_help(key), info=self.get_info(key))
2777
self._aliases.add('default')
2779
def set_default_repository(self, key):
2780
"""Set the FormatRegistry default and Repository default.
2782
This is a transitional method while Repository.set_default_format
2785
if 'default' in self:
2786
self.remove('default')
2787
self.set_default(key)
2788
format = self.get('default')()
2790
def make_bzrdir(self, key):
2791
return self.get(key)()
2793
def help_topic(self, topic):
2795
default_realkey = None
2796
default_help = self.get_help('default')
2798
for key in self._registration_order:
2799
if key == 'default':
2801
help = self.get_help(key)
2802
if help == default_help:
2803
default_realkey = key
2805
help_pairs.append((key, help))
2807
def wrapped(key, help, info):
2809
help = '(native) ' + help
2810
return ':%s:\n%s\n\n' % (key,
2811
textwrap.fill(help, initial_indent=' ',
2812
subsequent_indent=' '))
2813
if default_realkey is not None:
2814
output += wrapped(default_realkey, '(default) %s' % default_help,
2815
self.get_info('default'))
2816
deprecated_pairs = []
2817
experimental_pairs = []
2818
for key, help in help_pairs:
2819
info = self.get_info(key)
2822
elif info.deprecated:
2823
deprecated_pairs.append((key, help))
2824
elif info.experimental:
2825
experimental_pairs.append((key, help))
2827
output += wrapped(key, help, info)
2828
output += "\nSee ``bzr help formats`` for more about storage formats."
2830
if len(experimental_pairs) > 0:
2831
other_output += "Experimental formats are shown below.\n\n"
2832
for key, help in experimental_pairs:
2833
info = self.get_info(key)
2834
other_output += wrapped(key, help, info)
2837
"No experimental formats are available.\n\n"
2838
if len(deprecated_pairs) > 0:
2839
other_output += "\nDeprecated formats are shown below.\n\n"
2840
for key, help in deprecated_pairs:
2841
info = self.get_info(key)
2842
other_output += wrapped(key, help, info)
2845
"\nNo deprecated formats are available.\n\n"
2847
"\nSee ``bzr help formats`` for more about storage formats."
2849
if topic == 'other-formats':
2855
class RepositoryAcquisitionPolicy(object):
2856
"""Abstract base class for repository acquisition policies.
2858
A repository acquisition policy decides how a BzrDir acquires a repository
2859
for a branch that is being created. The most basic policy decision is
2860
whether to create a new repository or use an existing one.
2862
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2865
:param stack_on: A location to stack on
2866
:param stack_on_pwd: If stack_on is relative, the location it is
2868
:param require_stacking: If True, it is a failure to not stack.
2870
self._stack_on = stack_on
2871
self._stack_on_pwd = stack_on_pwd
2872
self._require_stacking = require_stacking
2874
def configure_branch(self, branch):
2875
"""Apply any configuration data from this policy to the branch.
2877
Default implementation sets repository stacking.
2879
if self._stack_on is None:
2881
if self._stack_on_pwd is None:
2882
stack_on = self._stack_on
2885
stack_on = urlutils.rebase_url(self._stack_on,
2887
branch.bzrdir.root_transport.base)
2888
except errors.InvalidRebaseURLs:
2889
stack_on = self._get_full_stack_on()
2891
branch.set_stacked_on_url(stack_on)
2892
except errors.UnstackableBranchFormat:
2893
if self._require_stacking:
2896
def _get_full_stack_on(self):
2897
"""Get a fully-qualified URL for the stack_on location."""
2898
if self._stack_on is None:
2900
if self._stack_on_pwd is None:
2901
return self._stack_on
2903
return urlutils.join(self._stack_on_pwd, self._stack_on)
2905
def _add_fallback(self, repository, possible_transports=None):
2906
"""Add a fallback to the supplied repository, if stacking is set."""
2907
stack_on = self._get_full_stack_on()
2908
if stack_on is None:
2910
stacked_dir = BzrDir.open(stack_on,
2911
possible_transports=possible_transports)
2913
stacked_repo = stacked_dir.open_branch().repository
2914
except errors.NotBranchError:
2915
stacked_repo = stacked_dir.open_repository()
2917
repository.add_fallback_repository(stacked_repo)
2918
except errors.UnstackableRepositoryFormat:
2919
if self._require_stacking:
2922
self._require_stacking = True
2924
def acquire_repository(self, make_working_trees=None, shared=False):
2925
"""Acquire a repository for this bzrdir.
2927
Implementations may create a new repository or use a pre-exising
2929
:param make_working_trees: If creating a repository, set
2930
make_working_trees to this value (if non-None)
2931
:param shared: If creating a repository, make it shared if True
2932
:return: A repository
2934
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
2937
class CreateRepository(RepositoryAcquisitionPolicy):
2938
"""A policy of creating a new repository"""
2940
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
2941
require_stacking=False):
2944
:param bzrdir: The bzrdir to create the repository on.
2945
:param stack_on: A location to stack on
2946
:param stack_on_pwd: If stack_on is relative, the location it is
2949
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2951
self._bzrdir = bzrdir
2953
def acquire_repository(self, make_working_trees=None, shared=False):
2954
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2956
Creates the desired repository in the bzrdir we already have.
2958
repository = self._bzrdir.create_repository(shared=shared)
2959
self._add_fallback(repository,
2960
possible_transports=[self._bzrdir.transport])
2961
if make_working_trees is not None:
2962
repository.set_make_working_trees(make_working_trees)
2966
class UseExistingRepository(RepositoryAcquisitionPolicy):
2967
"""A policy of reusing an existing repository"""
2969
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
2970
require_stacking=False):
2973
:param repository: The repository to use.
2974
:param stack_on: A location to stack on
2975
:param stack_on_pwd: If stack_on is relative, the location it is
2978
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2980
self._repository = repository
2982
def acquire_repository(self, make_working_trees=None, shared=False):
2983
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2985
Returns an existing repository to use
2987
self._add_fallback(self._repository,
2988
possible_transports=[self._repository.bzrdir.transport])
2989
return self._repository
2992
# Please register new formats after old formats so that formats
2993
# appear in chronological order and format descriptions can build
2995
format_registry = BzrDirFormatRegistry()
2996
format_registry.register('weave', BzrDirFormat6,
2997
'Pre-0.8 format. Slower than knit and does not'
2998
' support checkouts or shared repositories.',
3000
format_registry.register_metadir('metaweave',
3001
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3002
'Transitional format in 0.8. Slower than knit.',
3003
branch_format='bzrlib.branch.BzrBranchFormat5',
3004
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3006
format_registry.register_metadir('knit',
3007
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3008
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3009
branch_format='bzrlib.branch.BzrBranchFormat5',
3010
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3012
format_registry.register_metadir('dirstate',
3013
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3014
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3015
'above when accessed over the network.',
3016
branch_format='bzrlib.branch.BzrBranchFormat5',
3017
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3018
# directly from workingtree_4 triggers a circular import.
3019
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3021
format_registry.register_metadir('dirstate-tags',
3022
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3023
help='New in 0.15: Fast local operations and improved scaling for '
3024
'network operations. Additionally adds support for tags.'
3025
' Incompatible with bzr < 0.15.',
3026
branch_format='bzrlib.branch.BzrBranchFormat6',
3027
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3029
format_registry.register_metadir('rich-root',
3030
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3031
help='New in 1.0. Better handling of tree roots. Incompatible with'
3033
branch_format='bzrlib.branch.BzrBranchFormat6',
3034
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3036
format_registry.register_metadir('dirstate-with-subtree',
3037
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3038
help='New in 0.15: Fast local operations and improved scaling for '
3039
'network operations. Additionally adds support for versioning nested '
3040
'bzr branches. Incompatible with bzr < 0.15.',
3041
branch_format='bzrlib.branch.BzrBranchFormat6',
3042
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3046
format_registry.register_metadir('pack-0.92',
3047
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3048
help='New in 0.92: Pack-based format with data compatible with '
3049
'dirstate-tags format repositories. Interoperates with '
3050
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3051
'Previously called knitpack-experimental. '
3052
'For more information, see '
3053
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3054
branch_format='bzrlib.branch.BzrBranchFormat6',
3055
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3057
format_registry.register_metadir('pack-0.92-subtree',
3058
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3059
help='New in 0.92: Pack-based format with data compatible with '
3060
'dirstate-with-subtree format repositories. Interoperates with '
3061
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3062
'Previously called knitpack-experimental. '
3063
'For more information, see '
3064
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3065
branch_format='bzrlib.branch.BzrBranchFormat6',
3066
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3070
format_registry.register_metadir('rich-root-pack',
3071
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3072
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3073
'(needed for bzr-svn).',
3074
branch_format='bzrlib.branch.BzrBranchFormat6',
3075
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3077
format_registry.register_metadir('1.6',
3078
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3079
help='A format that allows a branch to indicate that there is another '
3080
'(stacked) repository that should be used to access data that is '
3081
'not present locally.',
3082
branch_format='bzrlib.branch.BzrBranchFormat7',
3083
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3085
format_registry.register_metadir('1.6.1-rich-root',
3086
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3087
help='A variant of 1.6 that supports rich-root data '
3088
'(needed for bzr-svn).',
3089
branch_format='bzrlib.branch.BzrBranchFormat7',
3090
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3092
format_registry.register_metadir('1.9',
3093
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3094
help='A repository format using B+tree indexes. These indexes '
3095
'are smaller in size, have smarter caching and provide faster '
3096
'performance for most operations.',
3097
branch_format='bzrlib.branch.BzrBranchFormat7',
3098
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3100
format_registry.register_metadir('1.9-rich-root',
3101
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3102
help='A variant of 1.9 that supports rich-root data '
3103
'(needed for bzr-svn).',
3104
branch_format='bzrlib.branch.BzrBranchFormat7',
3105
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3107
format_registry.register_metadir('1.12-preview',
3108
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3109
help='A working-tree format that supports views and content filtering.',
3110
branch_format='bzrlib.branch.BzrBranchFormat7',
3111
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
3114
format_registry.register_metadir('1.12-preview-rich-root',
3115
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3116
help='A variant of 1.12-preview that supports rich-root data '
3117
'(needed for bzr-svn).',
3118
branch_format='bzrlib.branch.BzrBranchFormat7',
3119
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
3122
# The following two formats should always just be aliases.
3123
format_registry.register_metadir('development',
3124
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3125
help='Current development format. Can convert data to and from pack-0.92 '
3126
'(and anything compatible with pack-0.92) format repositories. '
3127
'Repositories and branches in this format can only be read by bzr.dev. '
3129
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3131
branch_format='bzrlib.branch.BzrBranchFormat7',
3132
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3136
format_registry.register_metadir('development-subtree',
3137
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3138
help='Current development format, subtree variant. Can convert data to and '
3139
'from pack-0.92-subtree (and anything compatible with '
3140
'pack-0.92-subtree) format repositories. Repositories and branches in '
3141
'this format can only be read by bzr.dev. Please read '
3142
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3144
branch_format='bzrlib.branch.BzrBranchFormat7',
3145
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3149
# And the development formats above will have aliased one of the following:
3150
format_registry.register_metadir('development2',
3151
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3152
help='1.6.1 with B+Tree based index. '
3154
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3156
branch_format='bzrlib.branch.BzrBranchFormat7',
3157
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3161
format_registry.register_metadir('development2-subtree',
3162
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3163
help='1.6.1-subtree with B+Tree based index. '
3165
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3167
branch_format='bzrlib.branch.BzrBranchFormat7',
3168
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3172
# The current format that is made on 'bzr init'.
3173
format_registry.set_default('pack-0.92')