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
2036
def get_converter(self, format=None):
2037
"""See BzrDirFormat.get_converter()."""
2039
format = BzrDirFormat.get_default_format()
2040
if not isinstance(self, format.__class__):
2041
# converting away from metadir is not implemented
2042
raise NotImplementedError(self.get_converter)
2043
return ConvertMetaToMeta(format)
2045
def get_format_string(self):
2046
"""See BzrDirFormat.get_format_string()."""
2047
return "Bazaar-NG meta directory, format 1\n"
2049
def get_format_description(self):
2050
"""See BzrDirFormat.get_format_description()."""
2051
return "Meta directory format 1"
2053
def _open(self, transport):
2054
"""See BzrDirFormat._open."""
2055
return BzrDirMeta1(transport, self)
2057
def __return_repository_format(self):
2058
"""Circular import protection."""
2059
if getattr(self, '_repository_format', None):
2060
return self._repository_format
2061
from bzrlib.repository import RepositoryFormat
2062
return RepositoryFormat.get_default_format()
2064
def __set_repository_format(self, value):
2065
"""Allow changing the repository format for metadir formats."""
2066
self._repository_format = value
2068
repository_format = property(__return_repository_format, __set_repository_format)
2070
def __get_workingtree_format(self):
2071
if self._workingtree_format is None:
2072
from bzrlib.workingtree import WorkingTreeFormat
2073
self._workingtree_format = WorkingTreeFormat.get_default_format()
2074
return self._workingtree_format
2076
def __set_workingtree_format(self, wt_format):
2077
self._workingtree_format = wt_format
2079
workingtree_format = property(__get_workingtree_format,
2080
__set_workingtree_format)
2083
# Register bzr control format
2084
BzrDirFormat.register_control_format(BzrDirFormat)
2086
# Register bzr formats
2087
BzrDirFormat.register_format(BzrDirFormat4())
2088
BzrDirFormat.register_format(BzrDirFormat5())
2089
BzrDirFormat.register_format(BzrDirFormat6())
2090
__default_format = BzrDirMetaFormat1()
2091
BzrDirFormat.register_format(__default_format)
2092
BzrDirFormat._default_format = __default_format
2095
class Converter(object):
2096
"""Converts a disk format object from one format to another."""
2098
def convert(self, to_convert, pb):
2099
"""Perform the conversion of to_convert, giving feedback via pb.
2101
:param to_convert: The disk object to convert.
2102
:param pb: a progress bar to use for progress information.
2105
def step(self, message):
2106
"""Update the pb by a step."""
2108
self.pb.update(message, self.count, self.total)
2111
class ConvertBzrDir4To5(Converter):
2112
"""Converts format 4 bzr dirs to format 5."""
2115
super(ConvertBzrDir4To5, self).__init__()
2116
self.converted_revs = set()
2117
self.absent_revisions = set()
2121
def convert(self, to_convert, pb):
2122
"""See Converter.convert()."""
2123
self.bzrdir = to_convert
2125
self.pb.note('starting upgrade from format 4 to 5')
2126
if isinstance(self.bzrdir.transport, local.LocalTransport):
2127
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2128
self._convert_to_weaves()
2129
return BzrDir.open(self.bzrdir.root_transport.base)
2131
def _convert_to_weaves(self):
2132
self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2135
stat = self.bzrdir.transport.stat('weaves')
2136
if not S_ISDIR(stat.st_mode):
2137
self.bzrdir.transport.delete('weaves')
2138
self.bzrdir.transport.mkdir('weaves')
2139
except errors.NoSuchFile:
2140
self.bzrdir.transport.mkdir('weaves')
2141
# deliberately not a WeaveFile as we want to build it up slowly.
2142
self.inv_weave = Weave('inventory')
2143
# holds in-memory weaves for all files
2144
self.text_weaves = {}
2145
self.bzrdir.transport.delete('branch-format')
2146
self.branch = self.bzrdir.open_branch()
2147
self._convert_working_inv()
2148
rev_history = self.branch.revision_history()
2149
# to_read is a stack holding the revisions we still need to process;
2150
# appending to it adds new highest-priority revisions
2151
self.known_revisions = set(rev_history)
2152
self.to_read = rev_history[-1:]
2154
rev_id = self.to_read.pop()
2155
if (rev_id not in self.revisions
2156
and rev_id not in self.absent_revisions):
2157
self._load_one_rev(rev_id)
2159
to_import = self._make_order()
2160
for i, rev_id in enumerate(to_import):
2161
self.pb.update('converting revision', i, len(to_import))
2162
self._convert_one_rev(rev_id)
2164
self._write_all_weaves()
2165
self._write_all_revs()
2166
self.pb.note('upgraded to weaves:')
2167
self.pb.note(' %6d revisions and inventories', len(self.revisions))
2168
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
2169
self.pb.note(' %6d texts', self.text_count)
2170
self._cleanup_spare_files_after_format4()
2171
self.branch._transport.put_bytes(
2173
BzrDirFormat5().get_format_string(),
2174
mode=self.bzrdir._get_file_mode())
2176
def _cleanup_spare_files_after_format4(self):
2177
# FIXME working tree upgrade foo.
2178
for n in 'merged-patches', 'pending-merged-patches':
2180
## assert os.path.getsize(p) == 0
2181
self.bzrdir.transport.delete(n)
2182
except errors.NoSuchFile:
2184
self.bzrdir.transport.delete_tree('inventory-store')
2185
self.bzrdir.transport.delete_tree('text-store')
2187
def _convert_working_inv(self):
2188
inv = xml4.serializer_v4.read_inventory(
2189
self.branch._transport.get('inventory'))
2190
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2191
self.branch._transport.put_bytes('inventory', new_inv_xml,
2192
mode=self.bzrdir._get_file_mode())
2194
def _write_all_weaves(self):
2195
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2196
weave_transport = self.bzrdir.transport.clone('weaves')
2197
weaves = WeaveStore(weave_transport, prefixed=False)
2198
transaction = WriteTransaction()
2202
for file_id, file_weave in self.text_weaves.items():
2203
self.pb.update('writing weave', i, len(self.text_weaves))
2204
weaves._put_weave(file_id, file_weave, transaction)
2206
self.pb.update('inventory', 0, 1)
2207
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2208
self.pb.update('inventory', 1, 1)
2212
def _write_all_revs(self):
2213
"""Write all revisions out in new form."""
2214
self.bzrdir.transport.delete_tree('revision-store')
2215
self.bzrdir.transport.mkdir('revision-store')
2216
revision_transport = self.bzrdir.transport.clone('revision-store')
2218
from bzrlib.xml5 import serializer_v5
2219
from bzrlib.repofmt.weaverepo import RevisionTextStore
2220
revision_store = RevisionTextStore(revision_transport,
2221
serializer_v5, False, versionedfile.PrefixMapper(),
2222
lambda:True, lambda:True)
2224
for i, rev_id in enumerate(self.converted_revs):
2225
self.pb.update('write revision', i, len(self.converted_revs))
2226
text = serializer_v5.write_revision_to_string(
2227
self.revisions[rev_id])
2229
revision_store.add_lines(key, None, osutils.split_lines(text))
2233
def _load_one_rev(self, rev_id):
2234
"""Load a revision object into memory.
2236
Any parents not either loaded or abandoned get queued to be
2238
self.pb.update('loading revision',
2239
len(self.revisions),
2240
len(self.known_revisions))
2241
if not self.branch.repository.has_revision(rev_id):
2243
self.pb.note('revision {%s} not present in branch; '
2244
'will be converted as a ghost',
2246
self.absent_revisions.add(rev_id)
2248
rev = self.branch.repository.get_revision(rev_id)
2249
for parent_id in rev.parent_ids:
2250
self.known_revisions.add(parent_id)
2251
self.to_read.append(parent_id)
2252
self.revisions[rev_id] = rev
2254
def _load_old_inventory(self, rev_id):
2255
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2256
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2257
inv.revision_id = rev_id
2258
rev = self.revisions[rev_id]
2261
def _load_updated_inventory(self, rev_id):
2262
inv_xml = self.inv_weave.get_text(rev_id)
2263
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2266
def _convert_one_rev(self, rev_id):
2267
"""Convert revision and all referenced objects to new format."""
2268
rev = self.revisions[rev_id]
2269
inv = self._load_old_inventory(rev_id)
2270
present_parents = [p for p in rev.parent_ids
2271
if p not in self.absent_revisions]
2272
self._convert_revision_contents(rev, inv, present_parents)
2273
self._store_new_inv(rev, inv, present_parents)
2274
self.converted_revs.add(rev_id)
2276
def _store_new_inv(self, rev, inv, present_parents):
2277
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2278
new_inv_sha1 = sha_string(new_inv_xml)
2279
self.inv_weave.add_lines(rev.revision_id,
2281
new_inv_xml.splitlines(True))
2282
rev.inventory_sha1 = new_inv_sha1
2284
def _convert_revision_contents(self, rev, inv, present_parents):
2285
"""Convert all the files within a revision.
2287
Also upgrade the inventory to refer to the text revision ids."""
2288
rev_id = rev.revision_id
2289
mutter('converting texts of revision {%s}',
2291
parent_invs = map(self._load_updated_inventory, present_parents)
2292
entries = inv.iter_entries()
2294
for path, ie in entries:
2295
self._convert_file_version(rev, ie, parent_invs)
2297
def _convert_file_version(self, rev, ie, parent_invs):
2298
"""Convert one version of one file.
2300
The file needs to be added into the weave if it is a merge
2301
of >=2 parents or if it's changed from its parent.
2303
file_id = ie.file_id
2304
rev_id = rev.revision_id
2305
w = self.text_weaves.get(file_id)
2308
self.text_weaves[file_id] = w
2309
text_changed = False
2310
parent_candiate_entries = ie.parent_candidates(parent_invs)
2311
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2312
# XXX: Note that this is unordered - and this is tolerable because
2313
# the previous code was also unordered.
2314
previous_entries = dict((head, parent_candiate_entries[head]) for head
2316
self.snapshot_ie(previous_entries, ie, w, rev_id)
2319
@symbol_versioning.deprecated_method(symbol_versioning.one_one)
2320
def get_parents(self, revision_ids):
2321
for revision_id in revision_ids:
2322
yield self.revisions[revision_id].parent_ids
2324
def get_parent_map(self, revision_ids):
2325
"""See graph._StackedParentsProvider.get_parent_map"""
2326
return dict((revision_id, self.revisions[revision_id])
2327
for revision_id in revision_ids
2328
if revision_id in self.revisions)
2330
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2331
# TODO: convert this logic, which is ~= snapshot to
2332
# a call to:. This needs the path figured out. rather than a work_tree
2333
# a v4 revision_tree can be given, or something that looks enough like
2334
# one to give the file content to the entry if it needs it.
2335
# and we need something that looks like a weave store for snapshot to
2337
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2338
if len(previous_revisions) == 1:
2339
previous_ie = previous_revisions.values()[0]
2340
if ie._unchanged(previous_ie):
2341
ie.revision = previous_ie.revision
2344
text = self.branch.repository._text_store.get(ie.text_id)
2345
file_lines = text.readlines()
2346
w.add_lines(rev_id, previous_revisions, file_lines)
2347
self.text_count += 1
2349
w.add_lines(rev_id, previous_revisions, [])
2350
ie.revision = rev_id
2352
def _make_order(self):
2353
"""Return a suitable order for importing revisions.
2355
The order must be such that an revision is imported after all
2356
its (present) parents.
2358
todo = set(self.revisions.keys())
2359
done = self.absent_revisions.copy()
2362
# scan through looking for a revision whose parents
2364
for rev_id in sorted(list(todo)):
2365
rev = self.revisions[rev_id]
2366
parent_ids = set(rev.parent_ids)
2367
if parent_ids.issubset(done):
2368
# can take this one now
2369
order.append(rev_id)
2375
class ConvertBzrDir5To6(Converter):
2376
"""Converts format 5 bzr dirs to format 6."""
2378
def convert(self, to_convert, pb):
2379
"""See Converter.convert()."""
2380
self.bzrdir = to_convert
2382
self.pb.note('starting upgrade from format 5 to 6')
2383
self._convert_to_prefixed()
2384
return BzrDir.open(self.bzrdir.root_transport.base)
2386
def _convert_to_prefixed(self):
2387
from bzrlib.store import TransportStore
2388
self.bzrdir.transport.delete('branch-format')
2389
for store_name in ["weaves", "revision-store"]:
2390
self.pb.note("adding prefixes to %s" % store_name)
2391
store_transport = self.bzrdir.transport.clone(store_name)
2392
store = TransportStore(store_transport, prefixed=True)
2393
for urlfilename in store_transport.list_dir('.'):
2394
filename = urlutils.unescape(urlfilename)
2395
if (filename.endswith(".weave") or
2396
filename.endswith(".gz") or
2397
filename.endswith(".sig")):
2398
file_id, suffix = os.path.splitext(filename)
2402
new_name = store._mapper.map((file_id,)) + suffix
2403
# FIXME keep track of the dirs made RBC 20060121
2405
store_transport.move(filename, new_name)
2406
except errors.NoSuchFile: # catches missing dirs strangely enough
2407
store_transport.mkdir(osutils.dirname(new_name))
2408
store_transport.move(filename, new_name)
2409
self.bzrdir.transport.put_bytes(
2411
BzrDirFormat6().get_format_string(),
2412
mode=self.bzrdir._get_file_mode())
2415
class ConvertBzrDir6ToMeta(Converter):
2416
"""Converts format 6 bzr dirs to metadirs."""
2418
def convert(self, to_convert, pb):
2419
"""See Converter.convert()."""
2420
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2421
from bzrlib.branch import BzrBranchFormat5
2422
self.bzrdir = to_convert
2425
self.total = 20 # the steps we know about
2426
self.garbage_inventories = []
2427
self.dir_mode = self.bzrdir._get_dir_mode()
2428
self.file_mode = self.bzrdir._get_file_mode()
2430
self.pb.note('starting upgrade from format 6 to metadir')
2431
self.bzrdir.transport.put_bytes(
2433
"Converting to format 6",
2434
mode=self.file_mode)
2435
# its faster to move specific files around than to open and use the apis...
2436
# first off, nuke ancestry.weave, it was never used.
2438
self.step('Removing ancestry.weave')
2439
self.bzrdir.transport.delete('ancestry.weave')
2440
except errors.NoSuchFile:
2442
# find out whats there
2443
self.step('Finding branch files')
2444
last_revision = self.bzrdir.open_branch().last_revision()
2445
bzrcontents = self.bzrdir.transport.list_dir('.')
2446
for name in bzrcontents:
2447
if name.startswith('basis-inventory.'):
2448
self.garbage_inventories.append(name)
2449
# create new directories for repository, working tree and branch
2450
repository_names = [('inventory.weave', True),
2451
('revision-store', True),
2453
self.step('Upgrading repository ')
2454
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2455
self.make_lock('repository')
2456
# we hard code the formats here because we are converting into
2457
# the meta format. The meta format upgrader can take this to a
2458
# future format within each component.
2459
self.put_format('repository', RepositoryFormat7())
2460
for entry in repository_names:
2461
self.move_entry('repository', entry)
2463
self.step('Upgrading branch ')
2464
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2465
self.make_lock('branch')
2466
self.put_format('branch', BzrBranchFormat5())
2467
branch_files = [('revision-history', True),
2468
('branch-name', True),
2470
for entry in branch_files:
2471
self.move_entry('branch', entry)
2473
checkout_files = [('pending-merges', True),
2474
('inventory', True),
2475
('stat-cache', False)]
2476
# If a mandatory checkout file is not present, the branch does not have
2477
# a functional checkout. Do not create a checkout in the converted
2479
for name, mandatory in checkout_files:
2480
if mandatory and name not in bzrcontents:
2481
has_checkout = False
2485
if not has_checkout:
2486
self.pb.note('No working tree.')
2487
# If some checkout files are there, we may as well get rid of them.
2488
for name, mandatory in checkout_files:
2489
if name in bzrcontents:
2490
self.bzrdir.transport.delete(name)
2492
from bzrlib.workingtree import WorkingTreeFormat3
2493
self.step('Upgrading working tree')
2494
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2495
self.make_lock('checkout')
2497
'checkout', WorkingTreeFormat3())
2498
self.bzrdir.transport.delete_multi(
2499
self.garbage_inventories, self.pb)
2500
for entry in checkout_files:
2501
self.move_entry('checkout', entry)
2502
if last_revision is not None:
2503
self.bzrdir.transport.put_bytes(
2504
'checkout/last-revision', last_revision)
2505
self.bzrdir.transport.put_bytes(
2507
BzrDirMetaFormat1().get_format_string(),
2508
mode=self.file_mode)
2509
return BzrDir.open(self.bzrdir.root_transport.base)
2511
def make_lock(self, name):
2512
"""Make a lock for the new control dir name."""
2513
self.step('Make %s lock' % name)
2514
ld = lockdir.LockDir(self.bzrdir.transport,
2516
file_modebits=self.file_mode,
2517
dir_modebits=self.dir_mode)
2520
def move_entry(self, new_dir, entry):
2521
"""Move then entry name into new_dir."""
2523
mandatory = entry[1]
2524
self.step('Moving %s' % name)
2526
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2527
except errors.NoSuchFile:
2531
def put_format(self, dirname, format):
2532
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2533
format.get_format_string(),
2537
class ConvertMetaToMeta(Converter):
2538
"""Converts the components of metadirs."""
2540
def __init__(self, target_format):
2541
"""Create a metadir to metadir converter.
2543
:param target_format: The final metadir format that is desired.
2545
self.target_format = target_format
2547
def convert(self, to_convert, pb):
2548
"""See Converter.convert()."""
2549
self.bzrdir = to_convert
2553
self.step('checking repository format')
2555
repo = self.bzrdir.open_repository()
2556
except errors.NoRepositoryPresent:
2559
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2560
from bzrlib.repository import CopyConverter
2561
self.pb.note('starting repository conversion')
2562
converter = CopyConverter(self.target_format.repository_format)
2563
converter.convert(repo, pb)
2565
branch = self.bzrdir.open_branch()
2566
except errors.NotBranchError:
2569
# TODO: conversions of Branch and Tree should be done by
2570
# InterXFormat lookups/some sort of registry.
2571
# Avoid circular imports
2572
from bzrlib import branch as _mod_branch
2573
old = branch._format.__class__
2574
new = self.target_format.get_branch_format().__class__
2576
if (old == _mod_branch.BzrBranchFormat5 and
2577
new in (_mod_branch.BzrBranchFormat6,
2578
_mod_branch.BzrBranchFormat7)):
2579
branch_converter = _mod_branch.Converter5to6()
2580
elif (old == _mod_branch.BzrBranchFormat6 and
2581
new == _mod_branch.BzrBranchFormat7):
2582
branch_converter = _mod_branch.Converter6to7()
2584
raise errors.BadConversionTarget("No converter", new)
2585
branch_converter.convert(branch)
2586
branch = self.bzrdir.open_branch()
2587
old = branch._format.__class__
2589
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2590
except (errors.NoWorkingTree, errors.NotLocalUrl):
2593
# TODO: conversions of Branch and Tree should be done by
2594
# InterXFormat lookups
2595
if (isinstance(tree, workingtree.WorkingTree3) and
2596
not isinstance(tree, workingtree_4.WorkingTree4) and
2597
isinstance(self.target_format.workingtree_format,
2598
workingtree_4.WorkingTreeFormat4)):
2599
workingtree_4.Converter3to4().convert(tree)
2603
# This is not in remote.py because it's small, and needs to be registered.
2604
# Putting it in remote.py creates a circular import problem.
2605
# we can make it a lazy object if the control formats is turned into something
2607
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2608
"""Format representing bzrdirs accessed via a smart server"""
2610
def get_format_description(self):
2611
return 'bzr remote bzrdir'
2614
def probe_transport(klass, transport):
2615
"""Return a RemoteBzrDirFormat object if it looks possible."""
2617
medium = transport.get_smart_medium()
2618
except (NotImplementedError, AttributeError,
2619
errors.TransportNotPossible, errors.NoSmartMedium,
2620
errors.SmartProtocolError):
2621
# no smart server, so not a branch for this format type.
2622
raise errors.NotBranchError(path=transport.base)
2624
# Decline to open it if the server doesn't support our required
2625
# version (3) so that the VFS-based transport will do it.
2626
if medium.should_probe():
2628
server_version = medium.protocol_version()
2629
except errors.SmartProtocolError:
2630
# Apparently there's no usable smart server there, even though
2631
# the medium supports the smart protocol.
2632
raise errors.NotBranchError(path=transport.base)
2633
if server_version != '2':
2634
raise errors.NotBranchError(path=transport.base)
2637
def initialize_on_transport(self, transport):
2639
# hand off the request to the smart server
2640
client_medium = transport.get_smart_medium()
2641
except errors.NoSmartMedium:
2642
# TODO: lookup the local format from a server hint.
2643
local_dir_format = BzrDirMetaFormat1()
2644
return local_dir_format.initialize_on_transport(transport)
2645
client = _SmartClient(client_medium)
2646
path = client.remote_path_from_transport(transport)
2647
response = client.call('BzrDirFormat.initialize', path)
2648
if response[0] != 'ok':
2649
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2650
return remote.RemoteBzrDir(transport)
2652
def _open(self, transport):
2653
return remote.RemoteBzrDir(transport)
2655
def __eq__(self, other):
2656
if not isinstance(other, RemoteBzrDirFormat):
2658
return self.get_format_description() == other.get_format_description()
2661
def repository_format(self):
2662
# Using a property to avoid early loading of remote
2663
return remote.RemoteRepositoryFormat()
2666
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2669
class BzrDirFormatInfo(object):
2671
def __init__(self, native, deprecated, hidden, experimental):
2672
self.deprecated = deprecated
2673
self.native = native
2674
self.hidden = hidden
2675
self.experimental = experimental
2678
class BzrDirFormatRegistry(registry.Registry):
2679
"""Registry of user-selectable BzrDir subformats.
2681
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2682
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2686
"""Create a BzrDirFormatRegistry."""
2687
self._aliases = set()
2688
super(BzrDirFormatRegistry, self).__init__()
2691
"""Return a set of the format names which are aliases."""
2692
return frozenset(self._aliases)
2694
def register_metadir(self, key,
2695
repository_format, help, native=True, deprecated=False,
2701
"""Register a metadir subformat.
2703
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2704
by the Repository format.
2706
:param repository_format: The fully-qualified repository format class
2708
:param branch_format: Fully-qualified branch format class name as
2710
:param tree_format: Fully-qualified tree format class name as
2713
# This should be expanded to support setting WorkingTree and Branch
2714
# formats, once BzrDirMetaFormat1 supports that.
2715
def _load(full_name):
2716
mod_name, factory_name = full_name.rsplit('.', 1)
2718
mod = __import__(mod_name, globals(), locals(),
2720
except ImportError, e:
2721
raise ImportError('failed to load %s: %s' % (full_name, e))
2723
factory = getattr(mod, factory_name)
2724
except AttributeError:
2725
raise AttributeError('no factory %s in module %r'
2730
bd = BzrDirMetaFormat1()
2731
if branch_format is not None:
2732
bd.set_branch_format(_load(branch_format))
2733
if tree_format is not None:
2734
bd.workingtree_format = _load(tree_format)
2735
if repository_format is not None:
2736
bd.repository_format = _load(repository_format)
2738
self.register(key, helper, help, native, deprecated, hidden,
2739
experimental, alias)
2741
def register(self, key, factory, help, native=True, deprecated=False,
2742
hidden=False, experimental=False, alias=False):
2743
"""Register a BzrDirFormat factory.
2745
The factory must be a callable that takes one parameter: the key.
2746
It must produce an instance of the BzrDirFormat when called.
2748
This function mainly exists to prevent the info object from being
2751
registry.Registry.register(self, key, factory, help,
2752
BzrDirFormatInfo(native, deprecated, hidden, experimental))
2754
self._aliases.add(key)
2756
def register_lazy(self, key, module_name, member_name, help, native=True,
2757
deprecated=False, hidden=False, experimental=False, alias=False):
2758
registry.Registry.register_lazy(self, key, module_name, member_name,
2759
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
2761
self._aliases.add(key)
2763
def set_default(self, key):
2764
"""Set the 'default' key to be a clone of the supplied key.
2766
This method must be called once and only once.
2768
registry.Registry.register(self, 'default', self.get(key),
2769
self.get_help(key), info=self.get_info(key))
2770
self._aliases.add('default')
2772
def set_default_repository(self, key):
2773
"""Set the FormatRegistry default and Repository default.
2775
This is a transitional method while Repository.set_default_format
2778
if 'default' in self:
2779
self.remove('default')
2780
self.set_default(key)
2781
format = self.get('default')()
2783
def make_bzrdir(self, key):
2784
return self.get(key)()
2786
def help_topic(self, topic):
2787
output = textwrap.dedent("""\
2788
These formats can be used for creating branches, working trees, and
2792
default_realkey = None
2793
default_help = self.get_help('default')
2795
for key in self.keys():
2796
if key == 'default':
2798
help = self.get_help(key)
2799
if help == default_help:
2800
default_realkey = key
2802
help_pairs.append((key, help))
2804
def wrapped(key, help, info):
2806
help = '(native) ' + help
2807
return ':%s:\n%s\n\n' % (key,
2808
textwrap.fill(help, initial_indent=' ',
2809
subsequent_indent=' '))
2810
if default_realkey is not None:
2811
output += wrapped(default_realkey, '(default) %s' % default_help,
2812
self.get_info('default'))
2813
deprecated_pairs = []
2814
experimental_pairs = []
2815
for key, help in help_pairs:
2816
info = self.get_info(key)
2819
elif info.deprecated:
2820
deprecated_pairs.append((key, help))
2821
elif info.experimental:
2822
experimental_pairs.append((key, help))
2824
output += wrapped(key, help, info)
2825
if len(experimental_pairs) > 0:
2826
output += "Experimental formats are shown below.\n\n"
2827
for key, help in experimental_pairs:
2828
info = self.get_info(key)
2829
output += wrapped(key, help, info)
2830
if len(deprecated_pairs) > 0:
2831
output += "Deprecated formats are shown below.\n\n"
2832
for key, help in deprecated_pairs:
2833
info = self.get_info(key)
2834
output += wrapped(key, help, info)
2839
class RepositoryAcquisitionPolicy(object):
2840
"""Abstract base class for repository acquisition policies.
2842
A repository acquisition policy decides how a BzrDir acquires a repository
2843
for a branch that is being created. The most basic policy decision is
2844
whether to create a new repository or use an existing one.
2846
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2849
:param stack_on: A location to stack on
2850
:param stack_on_pwd: If stack_on is relative, the location it is
2852
:param require_stacking: If True, it is a failure to not stack.
2854
self._stack_on = stack_on
2855
self._stack_on_pwd = stack_on_pwd
2856
self._require_stacking = require_stacking
2858
def configure_branch(self, branch):
2859
"""Apply any configuration data from this policy to the branch.
2861
Default implementation sets repository stacking.
2863
if self._stack_on is None:
2865
if self._stack_on_pwd is None:
2866
stack_on = self._stack_on
2869
stack_on = urlutils.rebase_url(self._stack_on,
2871
branch.bzrdir.root_transport.base)
2872
except errors.InvalidRebaseURLs:
2873
stack_on = self._get_full_stack_on()
2875
branch.set_stacked_on_url(stack_on)
2876
except errors.UnstackableBranchFormat:
2877
if self._require_stacking:
2880
def _get_full_stack_on(self):
2881
"""Get a fully-qualified URL for the stack_on location."""
2882
if self._stack_on is None:
2884
if self._stack_on_pwd is None:
2885
return self._stack_on
2887
return urlutils.join(self._stack_on_pwd, self._stack_on)
2889
def _add_fallback(self, repository):
2890
"""Add a fallback to the supplied repository, if stacking is set."""
2891
stack_on = self._get_full_stack_on()
2892
if stack_on is None:
2894
stacked_dir = BzrDir.open(stack_on)
2896
stacked_repo = stacked_dir.open_branch().repository
2897
except errors.NotBranchError:
2898
stacked_repo = stacked_dir.open_repository()
2900
repository.add_fallback_repository(stacked_repo)
2901
except errors.UnstackableRepositoryFormat:
2902
if self._require_stacking:
2905
self._require_stacking = True
2907
def acquire_repository(self, make_working_trees=None, shared=False):
2908
"""Acquire a repository for this bzrdir.
2910
Implementations may create a new repository or use a pre-exising
2912
:param make_working_trees: If creating a repository, set
2913
make_working_trees to this value (if non-None)
2914
:param shared: If creating a repository, make it shared if True
2915
:return: A repository
2917
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
2920
class CreateRepository(RepositoryAcquisitionPolicy):
2921
"""A policy of creating a new repository"""
2923
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
2924
require_stacking=False):
2927
:param bzrdir: The bzrdir to create the repository on.
2928
:param stack_on: A location to stack on
2929
:param stack_on_pwd: If stack_on is relative, the location it is
2932
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2934
self._bzrdir = bzrdir
2936
def acquire_repository(self, make_working_trees=None, shared=False):
2937
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2939
Creates the desired repository in the bzrdir we already have.
2941
repository = self._bzrdir.create_repository(shared=shared)
2942
self._add_fallback(repository)
2943
if make_working_trees is not None:
2944
repository.set_make_working_trees(make_working_trees)
2948
class UseExistingRepository(RepositoryAcquisitionPolicy):
2949
"""A policy of reusing an existing repository"""
2951
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
2952
require_stacking=False):
2955
:param repository: The repository to use.
2956
:param stack_on: A location to stack on
2957
:param stack_on_pwd: If stack_on is relative, the location it is
2960
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
2962
self._repository = repository
2964
def acquire_repository(self, make_working_trees=None, shared=False):
2965
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
2967
Returns an existing repository to use
2969
self._add_fallback(self._repository)
2970
return self._repository
2973
format_registry = BzrDirFormatRegistry()
2974
format_registry.register('weave', BzrDirFormat6,
2975
'Pre-0.8 format. Slower than knit and does not'
2976
' support checkouts or shared repositories.',
2978
format_registry.register_metadir('knit',
2979
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2980
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
2981
branch_format='bzrlib.branch.BzrBranchFormat5',
2982
tree_format='bzrlib.workingtree.WorkingTreeFormat3')
2983
format_registry.register_metadir('metaweave',
2984
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
2985
'Transitional format in 0.8. Slower than knit.',
2986
branch_format='bzrlib.branch.BzrBranchFormat5',
2987
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
2989
format_registry.register_metadir('dirstate',
2990
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
2991
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
2992
'above when accessed over the network.',
2993
branch_format='bzrlib.branch.BzrBranchFormat5',
2994
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
2995
# directly from workingtree_4 triggers a circular import.
2996
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2998
format_registry.register_metadir('dirstate-tags',
2999
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3000
help='New in 0.15: Fast local operations and improved scaling for '
3001
'network operations. Additionally adds support for tags.'
3002
' Incompatible with bzr < 0.15.',
3003
branch_format='bzrlib.branch.BzrBranchFormat6',
3004
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3006
format_registry.register_metadir('rich-root',
3007
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3008
help='New in 1.0. Better handling of tree roots. Incompatible with'
3010
branch_format='bzrlib.branch.BzrBranchFormat6',
3011
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3013
format_registry.register_metadir('dirstate-with-subtree',
3014
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3015
help='New in 0.15: Fast local operations and improved scaling for '
3016
'network operations. Additionally adds support for versioning nested '
3017
'bzr branches. Incompatible with bzr < 0.15.',
3018
branch_format='bzrlib.branch.BzrBranchFormat6',
3019
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3023
format_registry.register_metadir('pack-0.92',
3024
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3025
help='New in 0.92: Pack-based format with data compatible with '
3026
'dirstate-tags format repositories. Interoperates with '
3027
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3028
'Previously called knitpack-experimental. '
3029
'For more information, see '
3030
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3031
branch_format='bzrlib.branch.BzrBranchFormat6',
3032
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3034
format_registry.register_metadir('pack-0.92-subtree',
3035
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3036
help='New in 0.92: Pack-based format with data compatible with '
3037
'dirstate-with-subtree format repositories. Interoperates with '
3038
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3039
'Previously called knitpack-experimental. '
3040
'For more information, see '
3041
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3042
branch_format='bzrlib.branch.BzrBranchFormat6',
3043
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3047
format_registry.register_metadir('rich-root-pack',
3048
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3049
help='New in 1.0: Pack-based format with data compatible with '
3050
'rich-root format repositories. Incompatible with'
3052
branch_format='bzrlib.branch.BzrBranchFormat6',
3053
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3055
format_registry.register_metadir('1.6',
3056
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3057
help='A branch and pack based repository that supports stacking. ',
3058
branch_format='bzrlib.branch.BzrBranchFormat7',
3059
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3061
format_registry.register_metadir('1.6.1-rich-root',
3062
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3063
help='A branch and pack based repository that supports stacking '
3064
'and rich root data (needed for bzr-svn). ',
3065
branch_format='bzrlib.branch.BzrBranchFormat7',
3066
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3068
format_registry.register_metadir('1.9',
3069
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3070
help='A branch and pack based repository that uses btree indexes. ',
3071
branch_format='bzrlib.branch.BzrBranchFormat7',
3072
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3074
format_registry.register_metadir('1.9-rich-root',
3075
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3076
help='A branch and pack based repository that uses btree indexes '
3077
'and rich root data (needed for bzr-svn). ',
3078
branch_format='bzrlib.branch.BzrBranchFormat7',
3079
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3081
# The following two formats should always just be aliases.
3082
format_registry.register_metadir('development',
3083
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3084
help='Current development format. Can convert data to and from pack-0.92 '
3085
'(and anything compatible with pack-0.92) format repositories. '
3086
'Repositories and branches in this format can only be read by bzr.dev. '
3088
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3090
branch_format='bzrlib.branch.BzrBranchFormat7',
3091
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3095
format_registry.register_metadir('development-subtree',
3096
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3097
help='Current development format, subtree variant. Can convert data to and '
3098
'from pack-0.92-subtree (and anything compatible with '
3099
'pack-0.92-subtree) format repositories. Repositories and branches in '
3100
'this format can only be read by bzr.dev. Please read '
3101
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3103
branch_format='bzrlib.branch.BzrBranchFormat7',
3104
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3108
# And the development formats above will have aliased one of the following:
3109
format_registry.register_metadir('development2',
3110
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3111
help='1.6.1 with B+Tree based index. '
3113
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3115
branch_format='bzrlib.branch.BzrBranchFormat7',
3116
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3120
format_registry.register_metadir('development2-subtree',
3121
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3122
help='1.6.1-subtree with B+Tree based index. '
3124
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3126
branch_format='bzrlib.branch.BzrBranchFormat7',
3127
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3131
# The current format that is made on 'bzr init'.
3132
format_registry.set_default('pack-0.92')