1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 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,
67
remote as remote_transport,
69
from bzrlib.weave import Weave
72
from bzrlib.trace import (
84
"""A .bzr control diretory.
86
BzrDir instances let you create or open any of the things that can be
87
found within .bzr - checkouts, branches and repositories.
90
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
92
a transport connected to the directory this bzr was opened from
93
(i.e. the parent directory holding the .bzr directory).
95
Everything in the bzrdir should have the same file permissions.
99
"""Invoke break_lock on the first object in the bzrdir.
101
If there is a tree, the tree is opened and break_lock() called.
102
Otherwise, branch is tried, and finally repository.
104
# XXX: This seems more like a UI function than something that really
105
# belongs in this class.
107
thing_to_unlock = self.open_workingtree()
108
except (errors.NotLocalUrl, errors.NoWorkingTree):
110
thing_to_unlock = self.open_branch()
111
except errors.NotBranchError:
113
thing_to_unlock = self.open_repository()
114
except errors.NoRepositoryPresent:
116
thing_to_unlock.break_lock()
118
def can_convert_format(self):
119
"""Return true if this bzrdir is one whose format we can convert from."""
122
def check_conversion_target(self, target_format):
123
target_repo_format = target_format.repository_format
124
source_repo_format = self._format.repository_format
125
source_repo_format.check_conversion_target(target_repo_format)
128
def _check_supported(format, allow_unsupported,
129
recommend_upgrade=True,
131
"""Give an error or warning on old formats.
133
:param format: may be any kind of format - workingtree, branch,
136
:param allow_unsupported: If true, allow opening
137
formats that are strongly deprecated, and which may
138
have limited functionality.
140
:param recommend_upgrade: If true (default), warn
141
the user through the ui object that they may wish
142
to upgrade the object.
144
# TODO: perhaps move this into a base Format class; it's not BzrDir
145
# specific. mbp 20070323
146
if not allow_unsupported and not format.is_supported():
147
# see open_downlevel to open legacy branches.
148
raise errors.UnsupportedFormatError(format=format)
149
if recommend_upgrade \
150
and getattr(format, 'upgrade_recommended', False):
151
ui.ui_factory.recommend_upgrade(
152
format.get_format_description(),
155
def clone(self, url, revision_id=None, force_new_repo=False,
156
preserve_stacking=False):
157
"""Clone this bzrdir and its contents to url verbatim.
159
:param url: The url create the clone at. If url's last component does
160
not exist, it will be created.
161
:param revision_id: The tip revision-id to use for any branch or
162
working tree. If not None, then the clone operation may tune
163
itself to download less data.
164
:param force_new_repo: Do not use a shared repository for the target
165
even if one is available.
166
:param preserve_stacking: When cloning a stacked branch, stack the
167
new branch on top of the other branch's stacked-on branch.
169
return self.clone_on_transport(get_transport(url),
170
revision_id=revision_id,
171
force_new_repo=force_new_repo,
172
preserve_stacking=preserve_stacking)
174
def clone_on_transport(self, transport, revision_id=None,
175
force_new_repo=False, preserve_stacking=False,
177
"""Clone this bzrdir and its contents to transport verbatim.
179
:param transport: The transport for the location to produce the clone
180
at. If the target directory does not exist, it will be created.
181
:param revision_id: The tip revision-id to use for any branch or
182
working tree. If not None, then the clone operation may tune
183
itself to download less data.
184
:param force_new_repo: Do not use a shared repository for the target,
185
even if one is available.
186
:param preserve_stacking: When cloning a stacked branch, stack the
187
new branch on top of the other branch's stacked-on branch.
189
transport.ensure_base()
190
require_stacking = (stacked_on is not None)
191
format = self.cloning_metadir(require_stacking)
192
result = format.initialize_on_transport(transport)
193
repository_policy = None
195
local_repo = self.find_repository()
196
except errors.NoRepositoryPresent:
199
local_branch = self.open_branch()
200
except errors.NotBranchError:
203
# enable fallbacks when branch is not a branch reference
204
if local_branch.repository.has_same_location(local_repo):
205
local_repo = local_branch.repository
206
if preserve_stacking:
208
stacked_on = local_branch.get_stacked_on_url()
209
except (errors.UnstackableBranchFormat,
210
errors.UnstackableRepositoryFormat,
215
# may need to copy content in
216
repository_policy = result.determine_repository_policy(
217
force_new_repo, stacked_on, self.root_transport.base,
218
require_stacking=require_stacking)
219
make_working_trees = local_repo.make_working_trees()
220
result_repo = repository_policy.acquire_repository(
221
make_working_trees, local_repo.is_shared())
222
if not require_stacking and repository_policy._require_stacking:
223
require_stacking = True
224
result._format.require_stacking()
225
result_repo.fetch(local_repo, revision_id=revision_id)
228
# 1 if there is a branch present
229
# make sure its content is available in the target repository
231
if local_branch is not None:
232
result_branch = local_branch.clone(result, revision_id=revision_id)
233
if repository_policy is not None:
234
repository_policy.configure_branch(result_branch)
236
# Cheaper to check if the target is not local, than to try making
238
result.root_transport.local_abspath('.')
239
if result_repo is None or result_repo.make_working_trees():
240
self.open_workingtree().clone(result)
241
except (errors.NoWorkingTree, errors.NotLocalUrl):
245
# TODO: This should be given a Transport, and should chdir up; otherwise
246
# this will open a new connection.
247
def _make_tail(self, url):
248
t = get_transport(url)
252
def create(cls, base, format=None, possible_transports=None):
253
"""Create a new BzrDir at the url 'base'.
255
:param format: If supplied, the format of branch to create. If not
256
supplied, the default is used.
257
:param possible_transports: If supplied, a list of transports that
258
can be reused to share a remote connection.
260
if cls is not BzrDir:
261
raise AssertionError("BzrDir.create always creates the default"
262
" format, not one of %r" % cls)
263
t = get_transport(base, possible_transports)
266
format = BzrDirFormat.get_default_format()
267
return format.initialize_on_transport(t)
270
def find_bzrdirs(transport, evaluate=None, list_current=None):
271
"""Find bzrdirs recursively from current location.
273
This is intended primarily as a building block for more sophisticated
274
functionality, like finding trees under a directory, or finding
275
branches that use a given repository.
276
:param evaluate: An optional callable that yields recurse, value,
277
where recurse controls whether this bzrdir is recursed into
278
and value is the value to yield. By default, all bzrdirs
279
are recursed into, and the return value is the bzrdir.
280
:param list_current: if supplied, use this function to list the current
281
directory, instead of Transport.list_dir
282
:return: a generator of found bzrdirs, or whatever evaluate returns.
284
if list_current is None:
285
def list_current(transport):
286
return transport.list_dir('')
288
def evaluate(bzrdir):
291
pending = [transport]
292
while len(pending) > 0:
293
current_transport = pending.pop()
296
bzrdir = BzrDir.open_from_transport(current_transport)
297
except errors.NotBranchError:
300
recurse, value = evaluate(bzrdir)
303
subdirs = list_current(current_transport)
304
except errors.NoSuchFile:
307
for subdir in sorted(subdirs, reverse=True):
308
pending.append(current_transport.clone(subdir))
311
def find_branches(transport):
312
"""Find all branches under a transport.
314
This will find all branches below the transport, including branches
315
inside other branches. Where possible, it will use
316
Repository.find_branches.
318
To list all the branches that use a particular Repository, see
319
Repository.find_branches
321
def evaluate(bzrdir):
323
repository = bzrdir.open_repository()
324
except errors.NoRepositoryPresent:
327
return False, (None, repository)
329
branch = bzrdir.open_branch()
330
except errors.NotBranchError:
331
return True, (None, None)
333
return True, (branch, None)
335
for branch, repo in BzrDir.find_bzrdirs(transport, evaluate=evaluate):
337
branches.extend(repo.find_branches())
338
if branch is not None:
339
branches.append(branch)
342
def destroy_repository(self):
343
"""Destroy the repository in this BzrDir"""
344
raise NotImplementedError(self.destroy_repository)
346
def create_branch(self):
347
"""Create a branch in this BzrDir.
349
The bzrdir's format will control what branch format is created.
350
For more control see BranchFormatXX.create(a_bzrdir).
352
raise NotImplementedError(self.create_branch)
354
def destroy_branch(self):
355
"""Destroy the branch in this BzrDir"""
356
raise NotImplementedError(self.destroy_branch)
359
def create_branch_and_repo(base, force_new_repo=False, format=None):
360
"""Create a new BzrDir, Branch and Repository at the url 'base'.
362
This will use the current default BzrDirFormat unless one is
363
specified, and use whatever
364
repository format that that uses via bzrdir.create_branch and
365
create_repository. If a shared repository is available that is used
368
The created Branch object is returned.
370
:param base: The URL to create the branch at.
371
:param force_new_repo: If True a new repository is always created.
372
:param format: If supplied, the format of branch to create. If not
373
supplied, the default is used.
375
bzrdir = BzrDir.create(base, format)
376
bzrdir._find_or_create_repository(force_new_repo)
377
return bzrdir.create_branch()
379
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
380
stack_on_pwd=None, require_stacking=False):
381
"""Return an object representing a policy to use.
383
This controls whether a new repository is created, or a shared
384
repository used instead.
386
If stack_on is supplied, will not seek a containing shared repo.
388
:param force_new_repo: If True, require a new repository to be created.
389
:param stack_on: If supplied, the location to stack on. If not
390
supplied, a default_stack_on location may be used.
391
:param stack_on_pwd: If stack_on is relative, the location it is
394
def repository_policy(found_bzrdir):
397
config = found_bzrdir.get_config()
399
if config is not None:
400
stack_on = config.get_default_stack_on()
401
if stack_on is not None:
402
stack_on_pwd = found_bzrdir.root_transport.base
404
note('Using default stacking branch %s at %s', stack_on,
406
# does it have a repository ?
408
repository = found_bzrdir.open_repository()
409
except errors.NoRepositoryPresent:
412
if ((found_bzrdir.root_transport.base !=
413
self.root_transport.base) and not repository.is_shared()):
420
return UseExistingRepository(repository, stack_on,
421
stack_on_pwd, require_stacking=require_stacking), True
423
return CreateRepository(self, stack_on, stack_on_pwd,
424
require_stacking=require_stacking), True
426
if not force_new_repo:
428
policy = self._find_containing(repository_policy)
429
if policy is not None:
433
return UseExistingRepository(self.open_repository(),
434
stack_on, stack_on_pwd,
435
require_stacking=require_stacking)
436
except errors.NoRepositoryPresent:
438
return CreateRepository(self, stack_on, stack_on_pwd,
439
require_stacking=require_stacking)
441
def _find_or_create_repository(self, force_new_repo):
442
"""Create a new repository if needed, returning the repository."""
443
policy = self.determine_repository_policy(force_new_repo)
444
return policy.acquire_repository()
447
def create_branch_convenience(base, force_new_repo=False,
448
force_new_tree=None, format=None,
449
possible_transports=None):
450
"""Create a new BzrDir, Branch and Repository at the url 'base'.
452
This is a convenience function - it will use an existing repository
453
if possible, can be told explicitly whether to create a working tree or
456
This will use the current default BzrDirFormat unless one is
457
specified, and use whatever
458
repository format that that uses via bzrdir.create_branch and
459
create_repository. If a shared repository is available that is used
460
preferentially. Whatever repository is used, its tree creation policy
463
The created Branch object is returned.
464
If a working tree cannot be made due to base not being a file:// url,
465
no error is raised unless force_new_tree is True, in which case no
466
data is created on disk and NotLocalUrl is raised.
468
:param base: The URL to create the branch at.
469
:param force_new_repo: If True a new repository is always created.
470
:param force_new_tree: If True or False force creation of a tree or
471
prevent such creation respectively.
472
:param format: Override for the bzrdir format to create.
473
:param possible_transports: An optional reusable transports list.
476
# check for non local urls
477
t = get_transport(base, possible_transports)
478
if not isinstance(t, local.LocalTransport):
479
raise errors.NotLocalUrl(base)
480
bzrdir = BzrDir.create(base, format, possible_transports)
481
repo = bzrdir._find_or_create_repository(force_new_repo)
482
result = bzrdir.create_branch()
483
if force_new_tree or (repo.make_working_trees() and
484
force_new_tree is None):
486
bzrdir.create_workingtree()
487
except errors.NotLocalUrl:
492
def create_standalone_workingtree(base, format=None):
493
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
495
'base' must be a local path or a file:// url.
497
This will use the current default BzrDirFormat unless one is
498
specified, and use whatever
499
repository format that that uses for bzrdirformat.create_workingtree,
500
create_branch and create_repository.
502
:param format: Override for the bzrdir format to create.
503
:return: The WorkingTree object.
505
t = get_transport(base)
506
if not isinstance(t, local.LocalTransport):
507
raise errors.NotLocalUrl(base)
508
bzrdir = BzrDir.create_branch_and_repo(base,
510
format=format).bzrdir
511
return bzrdir.create_workingtree()
513
def create_workingtree(self, revision_id=None, from_branch=None,
514
accelerator_tree=None, hardlink=False):
515
"""Create a working tree at this BzrDir.
517
:param revision_id: create it as of this revision id.
518
:param from_branch: override bzrdir branch (for lightweight checkouts)
519
:param accelerator_tree: A tree which can be used for retrieving file
520
contents more quickly than the revision tree, i.e. a workingtree.
521
The revision tree will be used for cases where accelerator_tree's
522
content is different.
524
raise NotImplementedError(self.create_workingtree)
526
def backup_bzrdir(self):
527
"""Backup this bzr control directory.
529
:return: Tuple with old path name and new path name
531
pb = ui.ui_factory.nested_progress_bar()
533
# FIXME: bug 300001 -- the backup fails if the backup directory
534
# already exists, but it should instead either remove it or make
535
# a new backup directory.
537
# FIXME: bug 262450 -- the backup directory should have the same
538
# permissions as the .bzr directory (probably a bug in copy_tree)
539
old_path = self.root_transport.abspath('.bzr')
540
new_path = self.root_transport.abspath('backup.bzr')
541
pb.note('making backup of %s' % (old_path,))
542
pb.note(' to %s' % (new_path,))
543
self.root_transport.copy_tree('.bzr', 'backup.bzr')
544
return (old_path, new_path)
548
def retire_bzrdir(self, limit=10000):
549
"""Permanently disable the bzrdir.
551
This is done by renaming it to give the user some ability to recover
552
if there was a problem.
554
This will have horrible consequences if anyone has anything locked or
556
:param limit: number of times to retry
561
to_path = '.bzr.retired.%d' % i
562
self.root_transport.rename('.bzr', to_path)
563
note("renamed %s to %s"
564
% (self.root_transport.abspath('.bzr'), to_path))
566
except (errors.TransportError, IOError, errors.PathError):
573
def destroy_workingtree(self):
574
"""Destroy the working tree at this BzrDir.
576
Formats that do not support this may raise UnsupportedOperation.
578
raise NotImplementedError(self.destroy_workingtree)
580
def destroy_workingtree_metadata(self):
581
"""Destroy the control files for the working tree at this BzrDir.
583
The contents of working tree files are not affected.
584
Formats that do not support this may raise UnsupportedOperation.
586
raise NotImplementedError(self.destroy_workingtree_metadata)
588
def _find_containing(self, evaluate):
589
"""Find something in a containing control directory.
591
This method will scan containing control dirs, until it finds what
592
it is looking for, decides that it will never find it, or runs out
593
of containing control directories to check.
595
It is used to implement find_repository and
596
determine_repository_policy.
598
:param evaluate: A function returning (value, stop). If stop is True,
599
the value will be returned.
603
result, stop = evaluate(found_bzrdir)
606
next_transport = found_bzrdir.root_transport.clone('..')
607
if (found_bzrdir.root_transport.base == next_transport.base):
608
# top of the file system
610
# find the next containing bzrdir
612
found_bzrdir = BzrDir.open_containing_from_transport(
614
except errors.NotBranchError:
617
def find_repository(self):
618
"""Find the repository that should be used.
620
This does not require a branch as we use it to find the repo for
621
new branches as well as to hook existing branches up to their
624
def usable_repository(found_bzrdir):
625
# does it have a repository ?
627
repository = found_bzrdir.open_repository()
628
except errors.NoRepositoryPresent:
630
if found_bzrdir.root_transport.base == self.root_transport.base:
631
return repository, True
632
elif repository.is_shared():
633
return repository, True
637
found_repo = self._find_containing(usable_repository)
638
if found_repo is None:
639
raise errors.NoRepositoryPresent(self)
642
def get_branch_reference(self):
643
"""Return the referenced URL for the branch in this bzrdir.
645
:raises NotBranchError: If there is no Branch.
646
:return: The URL the branch in this bzrdir references if it is a
647
reference branch, or None for regular branches.
651
def get_branch_transport(self, branch_format):
652
"""Get the transport for use by branch format in this BzrDir.
654
Note that bzr dirs that do not support format strings will raise
655
IncompatibleFormat if the branch format they are given has
656
a format string, and vice versa.
658
If branch_format is None, the transport is returned with no
659
checking. If it is not None, then the returned transport is
660
guaranteed to point to an existing directory ready for use.
662
raise NotImplementedError(self.get_branch_transport)
664
def _find_creation_modes(self):
665
"""Determine the appropriate modes for files and directories.
667
They're always set to be consistent with the base directory,
668
assuming that this transport allows setting modes.
670
# TODO: Do we need or want an option (maybe a config setting) to turn
671
# this off or override it for particular locations? -- mbp 20080512
672
if self._mode_check_done:
674
self._mode_check_done = True
676
st = self.transport.stat('.')
677
except errors.TransportNotPossible:
678
self._dir_mode = None
679
self._file_mode = None
681
# Check the directory mode, but also make sure the created
682
# directories and files are read-write for this user. This is
683
# mostly a workaround for filesystems which lie about being able to
684
# write to a directory (cygwin & win32)
685
if (st.st_mode & 07777 == 00000):
686
# FTP allows stat but does not return dir/file modes
687
self._dir_mode = None
688
self._file_mode = None
690
self._dir_mode = (st.st_mode & 07777) | 00700
691
# Remove the sticky and execute bits for files
692
self._file_mode = self._dir_mode & ~07111
694
def _get_file_mode(self):
695
"""Return Unix mode for newly created files, or None.
697
if not self._mode_check_done:
698
self._find_creation_modes()
699
return self._file_mode
701
def _get_dir_mode(self):
702
"""Return Unix mode for newly created directories, or None.
704
if not self._mode_check_done:
705
self._find_creation_modes()
706
return self._dir_mode
708
def get_repository_transport(self, repository_format):
709
"""Get the transport for use by repository format in this BzrDir.
711
Note that bzr dirs that do not support format strings will raise
712
IncompatibleFormat if the repository format they are given has
713
a format string, and vice versa.
715
If repository_format is None, the transport is returned with no
716
checking. If it is not None, then the returned transport is
717
guaranteed to point to an existing directory ready for use.
719
raise NotImplementedError(self.get_repository_transport)
721
def get_workingtree_transport(self, tree_format):
722
"""Get the transport for use by workingtree format in this BzrDir.
724
Note that bzr dirs that do not support format strings will raise
725
IncompatibleFormat if the workingtree format they are given has a
726
format string, and vice versa.
728
If workingtree_format is None, the transport is returned with no
729
checking. If it is not None, then the returned transport is
730
guaranteed to point to an existing directory ready for use.
732
raise NotImplementedError(self.get_workingtree_transport)
734
def get_config(self):
735
if getattr(self, '_get_config', None) is None:
737
return self._get_config()
739
def __init__(self, _transport, _format):
740
"""Initialize a Bzr control dir object.
742
Only really common logic should reside here, concrete classes should be
743
made with varying behaviours.
745
:param _format: the format that is creating this BzrDir instance.
746
:param _transport: the transport this dir is based at.
748
self._format = _format
749
self.transport = _transport.clone('.bzr')
750
self.root_transport = _transport
751
self._mode_check_done = False
753
def is_control_filename(self, filename):
754
"""True if filename is the name of a path which is reserved for bzrdir's.
756
:param filename: A filename within the root transport of this bzrdir.
758
This is true IF and ONLY IF the filename is part of the namespace reserved
759
for bzr control dirs. Currently this is the '.bzr' directory in the root
760
of the root_transport. it is expected that plugins will need to extend
761
this in the future - for instance to make bzr talk with svn working
764
# this might be better on the BzrDirFormat class because it refers to
765
# all the possible bzrdir disk formats.
766
# This method is tested via the workingtree is_control_filename tests-
767
# it was extracted from WorkingTree.is_control_filename. If the method's
768
# contract is extended beyond the current trivial implementation, please
769
# add new tests for it to the appropriate place.
770
return filename == '.bzr' or filename.startswith('.bzr/')
772
def needs_format_conversion(self, format=None):
773
"""Return true if this bzrdir needs convert_format run on it.
775
For instance, if the repository format is out of date but the
776
branch and working tree are not, this should return True.
778
:param format: Optional parameter indicating a specific desired
779
format we plan to arrive at.
781
raise NotImplementedError(self.needs_format_conversion)
784
def open_unsupported(base):
785
"""Open a branch which is not supported."""
786
return BzrDir.open(base, _unsupported=True)
789
def open(base, _unsupported=False, possible_transports=None):
790
"""Open an existing bzrdir, rooted at 'base' (url).
792
:param _unsupported: a private parameter to the BzrDir class.
794
t = get_transport(base, possible_transports=possible_transports)
795
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
798
def open_from_transport(transport, _unsupported=False,
799
_server_formats=True):
800
"""Open a bzrdir within a particular directory.
802
:param transport: Transport containing the bzrdir.
803
:param _unsupported: private.
805
# Keep initial base since 'transport' may be modified while following
807
base = transport.base
808
def find_format(transport):
809
return transport, BzrDirFormat.find_format(
810
transport, _server_formats=_server_formats)
812
def redirected(transport, e, redirection_notice):
813
redirected_transport = transport._redirected_to(e.source, e.target)
814
if redirected_transport is None:
815
raise errors.NotBranchError(base)
816
note('%s is%s redirected to %s',
817
transport.base, e.permanently, redirected_transport.base)
818
return redirected_transport
821
transport, format = do_catching_redirections(find_format,
824
except errors.TooManyRedirections:
825
raise errors.NotBranchError(base)
827
BzrDir._check_supported(format, _unsupported)
828
return format.open(transport, _found=True)
830
def open_branch(self, unsupported=False):
831
"""Open the branch object at this BzrDir if one is present.
833
If unsupported is True, then no longer supported branch formats can
836
TODO: static convenience version of this?
838
raise NotImplementedError(self.open_branch)
841
def open_containing(url, possible_transports=None):
842
"""Open an existing branch which contains url.
844
:param url: url to search from.
845
See open_containing_from_transport for more detail.
847
transport = get_transport(url, possible_transports)
848
return BzrDir.open_containing_from_transport(transport)
851
def open_containing_from_transport(a_transport):
852
"""Open an existing branch which contains a_transport.base.
854
This probes for a branch at a_transport, and searches upwards from there.
856
Basically we keep looking up until we find the control directory or
857
run into the root. If there isn't one, raises NotBranchError.
858
If there is one and it is either an unrecognised format or an unsupported
859
format, UnknownFormatError or UnsupportedFormatError are raised.
860
If there is one, it is returned, along with the unused portion of url.
862
:return: The BzrDir that contains the path, and a Unicode path
863
for the rest of the URL.
865
# this gets the normalised url back. I.e. '.' -> the full path.
866
url = a_transport.base
869
result = BzrDir.open_from_transport(a_transport)
870
return result, urlutils.unescape(a_transport.relpath(url))
871
except errors.NotBranchError, e:
874
new_t = a_transport.clone('..')
875
except errors.InvalidURLJoin:
876
# reached the root, whatever that may be
877
raise errors.NotBranchError(path=url)
878
if new_t.base == a_transport.base:
879
# reached the root, whatever that may be
880
raise errors.NotBranchError(path=url)
883
def _get_tree_branch(self):
884
"""Return the branch and tree, if any, for this bzrdir.
886
Return None for tree if not present or inaccessible.
887
Raise NotBranchError if no branch is present.
888
:return: (tree, branch)
891
tree = self.open_workingtree()
892
except (errors.NoWorkingTree, errors.NotLocalUrl):
894
branch = self.open_branch()
900
def open_tree_or_branch(klass, location):
901
"""Return the branch and working tree at a location.
903
If there is no tree at the location, tree will be None.
904
If there is no branch at the location, an exception will be
906
:return: (tree, branch)
908
bzrdir = klass.open(location)
909
return bzrdir._get_tree_branch()
912
def open_containing_tree_or_branch(klass, location):
913
"""Return the branch and working tree contained by a location.
915
Returns (tree, branch, relpath).
916
If there is no tree at containing the location, tree will be None.
917
If there is no branch containing the location, an exception will be
919
relpath is the portion of the path that is contained by the branch.
921
bzrdir, relpath = klass.open_containing(location)
922
tree, branch = bzrdir._get_tree_branch()
923
return tree, branch, relpath
926
def open_containing_tree_branch_or_repository(klass, location):
927
"""Return the working tree, branch and repo contained by a location.
929
Returns (tree, branch, repository, relpath).
930
If there is no tree containing the location, tree will be None.
931
If there is no branch containing the location, branch will be None.
932
If there is no repository containing the location, repository will be
934
relpath is the portion of the path that is contained by the innermost
937
If no tree, branch or repository is found, a NotBranchError is raised.
939
bzrdir, relpath = klass.open_containing(location)
941
tree, branch = bzrdir._get_tree_branch()
942
except errors.NotBranchError:
944
repo = bzrdir.find_repository()
945
return None, None, repo, relpath
946
except (errors.NoRepositoryPresent):
947
raise errors.NotBranchError(location)
948
return tree, branch, branch.repository, relpath
950
def open_repository(self, _unsupported=False):
951
"""Open the repository object at this BzrDir if one is present.
953
This will not follow the Branch object pointer - it's strictly a direct
954
open facility. Most client code should use open_branch().repository to
957
:param _unsupported: a private parameter, not part of the api.
958
TODO: static convenience version of this?
960
raise NotImplementedError(self.open_repository)
962
def open_workingtree(self, _unsupported=False,
963
recommend_upgrade=True, from_branch=None):
964
"""Open the workingtree object at this BzrDir if one is present.
966
:param recommend_upgrade: Optional keyword parameter, when True (the
967
default), emit through the ui module a recommendation that the user
968
upgrade the working tree when the workingtree being opened is old
969
(but still fully supported).
970
:param from_branch: override bzrdir branch (for lightweight checkouts)
972
raise NotImplementedError(self.open_workingtree)
974
def has_branch(self):
975
"""Tell if this bzrdir contains a branch.
977
Note: if you're going to open the branch, you should just go ahead
978
and try, and not ask permission first. (This method just opens the
979
branch and discards it, and that's somewhat expensive.)
984
except errors.NotBranchError:
987
def has_workingtree(self):
988
"""Tell if this bzrdir contains a working tree.
990
This will still raise an exception if the bzrdir has a workingtree that
991
is remote & inaccessible.
993
Note: if you're going to open the working tree, you should just go ahead
994
and try, and not ask permission first. (This method just opens the
995
workingtree and discards it, and that's somewhat expensive.)
998
self.open_workingtree(recommend_upgrade=False)
1000
except errors.NoWorkingTree:
1003
def _cloning_metadir(self):
1004
"""Produce a metadir suitable for cloning with.
1006
:returns: (destination_bzrdir_format, source_repository)
1008
result_format = self._format.__class__()
1011
branch = self.open_branch()
1012
source_repository = branch.repository
1013
result_format._branch_format = branch._format
1014
except errors.NotBranchError:
1015
source_branch = None
1016
source_repository = self.open_repository()
1017
except errors.NoRepositoryPresent:
1018
source_repository = None
1020
# XXX TODO: This isinstance is here because we have not implemented
1021
# the fix recommended in bug # 103195 - to delegate this choice the
1022
# repository itself.
1023
repo_format = source_repository._format
1024
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1025
source_repository._ensure_real()
1026
repo_format = source_repository._real_repository._format
1027
result_format.repository_format = repo_format
1029
# TODO: Couldn't we just probe for the format in these cases,
1030
# rather than opening the whole tree? It would be a little
1031
# faster. mbp 20070401
1032
tree = self.open_workingtree(recommend_upgrade=False)
1033
except (errors.NoWorkingTree, errors.NotLocalUrl):
1034
result_format.workingtree_format = None
1036
result_format.workingtree_format = tree._format.__class__()
1037
return result_format, source_repository
1039
def cloning_metadir(self, require_stacking=False):
1040
"""Produce a metadir suitable for cloning or sprouting with.
1042
These operations may produce workingtrees (yes, even though they're
1043
"cloning" something that doesn't have a tree), so a viable workingtree
1044
format must be selected.
1046
:require_stacking: If True, non-stackable formats will be upgraded
1047
to similar stackable formats.
1048
:returns: a BzrDirFormat with all component formats either set
1049
appropriately or set to None if that component should not be
1052
format, repository = self._cloning_metadir()
1053
if format._workingtree_format is None:
1054
if repository is None:
1056
tree_format = repository._format._matchingbzrdir.workingtree_format
1057
format.workingtree_format = tree_format.__class__()
1058
if require_stacking:
1059
format.require_stacking()
1062
def checkout_metadir(self):
1063
return self.cloning_metadir()
1065
def sprout(self, url, revision_id=None, force_new_repo=False,
1066
recurse='down', possible_transports=None,
1067
accelerator_tree=None, hardlink=False, stacked=False,
1068
source_branch=None, create_tree_if_local=True):
1069
"""Create a copy of this bzrdir prepared for use as a new line of
1072
If url's last component does not exist, it will be created.
1074
Attributes related to the identity of the source branch like
1075
branch nickname will be cleaned, a working tree is created
1076
whether one existed before or not; and a local branch is always
1079
if revision_id is not None, then the clone operation may tune
1080
itself to download less data.
1081
:param accelerator_tree: A tree which can be used for retrieving file
1082
contents more quickly than the revision tree, i.e. a workingtree.
1083
The revision tree will be used for cases where accelerator_tree's
1084
content is different.
1085
:param hardlink: If true, hard-link files from accelerator_tree,
1087
:param stacked: If true, create a stacked branch referring to the
1088
location of this control directory.
1089
:param create_tree_if_local: If true, a working-tree will be created
1090
when working locally.
1092
target_transport = get_transport(url, possible_transports)
1093
target_transport.ensure_base()
1094
cloning_format = self.cloning_metadir(stacked)
1095
# Create/update the result branch
1096
result = cloning_format.initialize_on_transport(target_transport)
1097
# if a stacked branch wasn't requested, we don't create one
1098
# even if the origin was stacked
1099
stacked_branch_url = None
1100
if source_branch is not None:
1102
stacked_branch_url = self.root_transport.base
1103
source_repository = source_branch.repository
1106
source_branch = self.open_branch()
1107
source_repository = source_branch.repository
1109
stacked_branch_url = self.root_transport.base
1110
except errors.NotBranchError:
1111
source_branch = None
1113
source_repository = self.open_repository()
1114
except errors.NoRepositoryPresent:
1115
source_repository = None
1116
repository_policy = result.determine_repository_policy(
1117
force_new_repo, stacked_branch_url, require_stacking=stacked)
1118
result_repo = repository_policy.acquire_repository()
1119
if source_repository is not None:
1120
# Fetch while stacked to prevent unstacked fetch from
1122
result_repo.fetch(source_repository, revision_id=revision_id)
1124
if source_branch is None:
1125
# this is for sprouting a bzrdir without a branch; is that
1127
# Not especially, but it's part of the contract.
1128
result_branch = result.create_branch()
1130
# Force NULL revision to avoid using repository before stacking
1132
result_branch = source_branch.sprout(
1133
result, revision_id=_mod_revision.NULL_REVISION)
1134
parent_location = result_branch.get_parent()
1135
mutter("created new branch %r" % (result_branch,))
1136
repository_policy.configure_branch(result_branch)
1137
if source_branch is not None:
1138
source_branch.copy_content_into(result_branch, revision_id)
1139
# Override copy_content_into
1140
result_branch.set_parent(parent_location)
1142
# Create/update the result working tree
1143
if (create_tree_if_local and
1144
isinstance(target_transport, local.LocalTransport) and
1145
(result_repo is None or result_repo.make_working_trees())):
1146
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1150
if wt.path2id('') is None:
1152
wt.set_root_id(self.open_workingtree.get_root_id())
1153
except errors.NoWorkingTree:
1159
if recurse == 'down':
1161
basis = wt.basis_tree()
1163
subtrees = basis.iter_references()
1164
elif result_branch is not None:
1165
basis = result_branch.basis_tree()
1167
subtrees = basis.iter_references()
1168
elif source_branch is not None:
1169
basis = source_branch.basis_tree()
1171
subtrees = basis.iter_references()
1176
for path, file_id in subtrees:
1177
target = urlutils.join(url, urlutils.escape(path))
1178
sublocation = source_branch.reference_parent(file_id, path)
1179
sublocation.bzrdir.sprout(target,
1180
basis.get_reference_revision(file_id, path),
1181
force_new_repo=force_new_repo, recurse=recurse,
1184
if basis is not None:
1189
class BzrDirPreSplitOut(BzrDir):
1190
"""A common class for the all-in-one formats."""
1192
def __init__(self, _transport, _format):
1193
"""See BzrDir.__init__."""
1194
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1195
self._control_files = lockable_files.LockableFiles(
1196
self.get_branch_transport(None),
1197
self._format._lock_file_name,
1198
self._format._lock_class)
1200
def break_lock(self):
1201
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1202
raise NotImplementedError(self.break_lock)
1204
def cloning_metadir(self, require_stacking=False):
1205
"""Produce a metadir suitable for cloning with."""
1206
if require_stacking:
1207
return format_registry.make_bzrdir('1.6')
1208
return self._format.__class__()
1210
def clone(self, url, revision_id=None, force_new_repo=False,
1211
preserve_stacking=False):
1212
"""See BzrDir.clone().
1214
force_new_repo has no effect, since this family of formats always
1215
require a new repository.
1216
preserve_stacking has no effect, since no source branch using this
1217
family of formats can be stacked, so there is no stacking to preserve.
1219
self._make_tail(url)
1220
result = self._format._initialize_for_clone(url)
1221
self.open_repository().clone(result, revision_id=revision_id)
1222
from_branch = self.open_branch()
1223
from_branch.clone(result, revision_id=revision_id)
1225
tree = self.open_workingtree()
1226
except errors.NotLocalUrl:
1227
# make a new one, this format always has to have one.
1228
result._init_workingtree()
1233
def create_branch(self):
1234
"""See BzrDir.create_branch."""
1235
return self._format.get_branch_format().initialize(self)
1237
def destroy_branch(self):
1238
"""See BzrDir.destroy_branch."""
1239
raise errors.UnsupportedOperation(self.destroy_branch, self)
1241
def create_repository(self, shared=False):
1242
"""See BzrDir.create_repository."""
1244
raise errors.IncompatibleFormat('shared repository', self._format)
1245
return self.open_repository()
1247
def destroy_repository(self):
1248
"""See BzrDir.destroy_repository."""
1249
raise errors.UnsupportedOperation(self.destroy_repository, self)
1251
def create_workingtree(self, revision_id=None, from_branch=None,
1252
accelerator_tree=None, hardlink=False):
1253
"""See BzrDir.create_workingtree."""
1254
# The workingtree is sometimes created when the bzrdir is created,
1255
# but not when cloning.
1257
# this looks buggy but is not -really-
1258
# because this format creates the workingtree when the bzrdir is
1260
# clone and sprout will have set the revision_id
1261
# and that will have set it for us, its only
1262
# specific uses of create_workingtree in isolation
1263
# that can do wonky stuff here, and that only
1264
# happens for creating checkouts, which cannot be
1265
# done on this format anyway. So - acceptable wart.
1267
result = self.open_workingtree(recommend_upgrade=False)
1268
except errors.NoSuchFile:
1269
result = self._init_workingtree()
1270
if revision_id is not None:
1271
if revision_id == _mod_revision.NULL_REVISION:
1272
result.set_parent_ids([])
1274
result.set_parent_ids([revision_id])
1277
def _init_workingtree(self):
1278
from bzrlib.workingtree import WorkingTreeFormat2
1280
return WorkingTreeFormat2().initialize(self)
1281
except errors.NotLocalUrl:
1282
# Even though we can't access the working tree, we need to
1283
# create its control files.
1284
return WorkingTreeFormat2()._stub_initialize_on_transport(
1285
self.transport, self._control_files._file_mode)
1287
def destroy_workingtree(self):
1288
"""See BzrDir.destroy_workingtree."""
1289
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1291
def destroy_workingtree_metadata(self):
1292
"""See BzrDir.destroy_workingtree_metadata."""
1293
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1296
def get_branch_transport(self, branch_format):
1297
"""See BzrDir.get_branch_transport()."""
1298
if branch_format is None:
1299
return self.transport
1301
branch_format.get_format_string()
1302
except NotImplementedError:
1303
return self.transport
1304
raise errors.IncompatibleFormat(branch_format, self._format)
1306
def get_repository_transport(self, repository_format):
1307
"""See BzrDir.get_repository_transport()."""
1308
if repository_format is None:
1309
return self.transport
1311
repository_format.get_format_string()
1312
except NotImplementedError:
1313
return self.transport
1314
raise errors.IncompatibleFormat(repository_format, self._format)
1316
def get_workingtree_transport(self, workingtree_format):
1317
"""See BzrDir.get_workingtree_transport()."""
1318
if workingtree_format is None:
1319
return self.transport
1321
workingtree_format.get_format_string()
1322
except NotImplementedError:
1323
return self.transport
1324
raise errors.IncompatibleFormat(workingtree_format, self._format)
1326
def needs_format_conversion(self, format=None):
1327
"""See BzrDir.needs_format_conversion()."""
1328
# if the format is not the same as the system default,
1329
# an upgrade is needed.
1331
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1332
% 'needs_format_conversion(format=None)')
1333
format = BzrDirFormat.get_default_format()
1334
return not isinstance(self._format, format.__class__)
1336
def open_branch(self, unsupported=False):
1337
"""See BzrDir.open_branch."""
1338
from bzrlib.branch import BzrBranchFormat4
1339
format = BzrBranchFormat4()
1340
self._check_supported(format, unsupported)
1341
return format.open(self, _found=True)
1343
def sprout(self, url, revision_id=None, force_new_repo=False,
1344
possible_transports=None, accelerator_tree=None,
1345
hardlink=False, stacked=False, create_tree_if_local=True):
1346
"""See BzrDir.sprout()."""
1348
raise errors.UnstackableBranchFormat(
1349
self._format, self.root_transport.base)
1350
if not create_tree_if_local:
1351
raise errors.MustHaveWorkingTree(
1352
self._format, self.root_transport.base)
1353
from bzrlib.workingtree import WorkingTreeFormat2
1354
self._make_tail(url)
1355
result = self._format._initialize_for_clone(url)
1357
self.open_repository().clone(result, revision_id=revision_id)
1358
except errors.NoRepositoryPresent:
1361
self.open_branch().sprout(result, revision_id=revision_id)
1362
except errors.NotBranchError:
1365
# we always want a working tree
1366
WorkingTreeFormat2().initialize(result,
1367
accelerator_tree=accelerator_tree,
1372
class BzrDir4(BzrDirPreSplitOut):
1373
"""A .bzr version 4 control object.
1375
This is a deprecated format and may be removed after sept 2006.
1378
def create_repository(self, shared=False):
1379
"""See BzrDir.create_repository."""
1380
return self._format.repository_format.initialize(self, shared)
1382
def needs_format_conversion(self, format=None):
1383
"""Format 4 dirs are always in need of conversion."""
1385
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1386
% 'needs_format_conversion(format=None)')
1389
def open_repository(self):
1390
"""See BzrDir.open_repository."""
1391
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1392
return RepositoryFormat4().open(self, _found=True)
1395
class BzrDir5(BzrDirPreSplitOut):
1396
"""A .bzr version 5 control object.
1398
This is a deprecated format and may be removed after sept 2006.
1401
def open_repository(self):
1402
"""See BzrDir.open_repository."""
1403
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1404
return RepositoryFormat5().open(self, _found=True)
1406
def open_workingtree(self, _unsupported=False,
1407
recommend_upgrade=True):
1408
"""See BzrDir.create_workingtree."""
1409
from bzrlib.workingtree import WorkingTreeFormat2
1410
wt_format = WorkingTreeFormat2()
1411
# we don't warn here about upgrades; that ought to be handled for the
1413
return wt_format.open(self, _found=True)
1416
class BzrDir6(BzrDirPreSplitOut):
1417
"""A .bzr version 6 control object.
1419
This is a deprecated format and may be removed after sept 2006.
1422
def open_repository(self):
1423
"""See BzrDir.open_repository."""
1424
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1425
return RepositoryFormat6().open(self, _found=True)
1427
def open_workingtree(self, _unsupported=False,
1428
recommend_upgrade=True):
1429
"""See BzrDir.create_workingtree."""
1430
# we don't warn here about upgrades; that ought to be handled for the
1432
from bzrlib.workingtree import WorkingTreeFormat2
1433
return WorkingTreeFormat2().open(self, _found=True)
1436
class BzrDirMeta1(BzrDir):
1437
"""A .bzr meta version 1 control object.
1439
This is the first control object where the
1440
individual aspects are really split out: there are separate repository,
1441
workingtree and branch subdirectories and any subset of the three can be
1442
present within a BzrDir.
1445
def can_convert_format(self):
1446
"""See BzrDir.can_convert_format()."""
1449
def create_branch(self):
1450
"""See BzrDir.create_branch."""
1451
return self._format.get_branch_format().initialize(self)
1453
def destroy_branch(self):
1454
"""See BzrDir.create_branch."""
1455
self.transport.delete_tree('branch')
1457
def create_repository(self, shared=False):
1458
"""See BzrDir.create_repository."""
1459
return self._format.repository_format.initialize(self, shared)
1461
def destroy_repository(self):
1462
"""See BzrDir.destroy_repository."""
1463
self.transport.delete_tree('repository')
1465
def create_workingtree(self, revision_id=None, from_branch=None,
1466
accelerator_tree=None, hardlink=False):
1467
"""See BzrDir.create_workingtree."""
1468
return self._format.workingtree_format.initialize(
1469
self, revision_id, from_branch=from_branch,
1470
accelerator_tree=accelerator_tree, hardlink=hardlink)
1472
def destroy_workingtree(self):
1473
"""See BzrDir.destroy_workingtree."""
1474
wt = self.open_workingtree(recommend_upgrade=False)
1475
repository = wt.branch.repository
1476
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1477
wt.revert(old_tree=empty)
1478
self.destroy_workingtree_metadata()
1480
def destroy_workingtree_metadata(self):
1481
self.transport.delete_tree('checkout')
1483
def find_branch_format(self):
1484
"""Find the branch 'format' for this bzrdir.
1486
This might be a synthetic object for e.g. RemoteBranch and SVN.
1488
from bzrlib.branch import BranchFormat
1489
return BranchFormat.find_format(self)
1491
def _get_mkdir_mode(self):
1492
"""Figure out the mode to use when creating a bzrdir subdir."""
1493
temp_control = lockable_files.LockableFiles(self.transport, '',
1494
lockable_files.TransportLock)
1495
return temp_control._dir_mode
1497
def get_branch_reference(self):
1498
"""See BzrDir.get_branch_reference()."""
1499
from bzrlib.branch import BranchFormat
1500
format = BranchFormat.find_format(self)
1501
return format.get_reference(self)
1503
def get_branch_transport(self, branch_format):
1504
"""See BzrDir.get_branch_transport()."""
1505
if branch_format is None:
1506
return self.transport.clone('branch')
1508
branch_format.get_format_string()
1509
except NotImplementedError:
1510
raise errors.IncompatibleFormat(branch_format, self._format)
1512
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1513
except errors.FileExists:
1515
return self.transport.clone('branch')
1517
def get_repository_transport(self, repository_format):
1518
"""See BzrDir.get_repository_transport()."""
1519
if repository_format is None:
1520
return self.transport.clone('repository')
1522
repository_format.get_format_string()
1523
except NotImplementedError:
1524
raise errors.IncompatibleFormat(repository_format, self._format)
1526
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1527
except errors.FileExists:
1529
return self.transport.clone('repository')
1531
def get_workingtree_transport(self, workingtree_format):
1532
"""See BzrDir.get_workingtree_transport()."""
1533
if workingtree_format is None:
1534
return self.transport.clone('checkout')
1536
workingtree_format.get_format_string()
1537
except NotImplementedError:
1538
raise errors.IncompatibleFormat(workingtree_format, self._format)
1540
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1541
except errors.FileExists:
1543
return self.transport.clone('checkout')
1545
def needs_format_conversion(self, format=None):
1546
"""See BzrDir.needs_format_conversion()."""
1548
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1549
% 'needs_format_conversion(format=None)')
1551
format = BzrDirFormat.get_default_format()
1552
if not isinstance(self._format, format.__class__):
1553
# it is not a meta dir format, conversion is needed.
1555
# we might want to push this down to the repository?
1557
if not isinstance(self.open_repository()._format,
1558
format.repository_format.__class__):
1559
# the repository needs an upgrade.
1561
except errors.NoRepositoryPresent:
1564
if not isinstance(self.open_branch()._format,
1565
format.get_branch_format().__class__):
1566
# the branch needs an upgrade.
1568
except errors.NotBranchError:
1571
my_wt = self.open_workingtree(recommend_upgrade=False)
1572
if not isinstance(my_wt._format,
1573
format.workingtree_format.__class__):
1574
# the workingtree needs an upgrade.
1576
except (errors.NoWorkingTree, errors.NotLocalUrl):
1580
def open_branch(self, unsupported=False):
1581
"""See BzrDir.open_branch."""
1582
format = self.find_branch_format()
1583
self._check_supported(format, unsupported)
1584
return format.open(self, _found=True)
1586
def open_repository(self, unsupported=False):
1587
"""See BzrDir.open_repository."""
1588
from bzrlib.repository import RepositoryFormat
1589
format = RepositoryFormat.find_format(self)
1590
self._check_supported(format, unsupported)
1591
return format.open(self, _found=True)
1593
def open_workingtree(self, unsupported=False,
1594
recommend_upgrade=True):
1595
"""See BzrDir.open_workingtree."""
1596
from bzrlib.workingtree import WorkingTreeFormat
1597
format = WorkingTreeFormat.find_format(self)
1598
self._check_supported(format, unsupported,
1600
basedir=self.root_transport.base)
1601
return format.open(self, _found=True)
1603
def _get_config(self):
1604
return config.BzrDirConfig(self.transport)
1607
class BzrDirFormat(object):
1608
"""An encapsulation of the initialization and open routines for a format.
1610
Formats provide three things:
1611
* An initialization routine,
1615
Formats are placed in a dict by their format string for reference
1616
during bzrdir opening. These should be subclasses of BzrDirFormat
1619
Once a format is deprecated, just deprecate the initialize and open
1620
methods on the format class. Do not deprecate the object, as the
1621
object will be created every system load.
1624
_default_format = None
1625
"""The default format used for new .bzr dirs."""
1628
"""The known formats."""
1630
_control_formats = []
1631
"""The registered control formats - .bzr, ....
1633
This is a list of BzrDirFormat objects.
1636
_control_server_formats = []
1637
"""The registered control server formats, e.g. RemoteBzrDirs.
1639
This is a list of BzrDirFormat objects.
1642
_lock_file_name = 'branch-lock'
1644
# _lock_class must be set in subclasses to the lock type, typ.
1645
# TransportLock or LockDir
1648
def find_format(klass, transport, _server_formats=True):
1649
"""Return the format present at transport."""
1651
formats = klass._control_server_formats + klass._control_formats
1653
formats = klass._control_formats
1654
for format in formats:
1656
return format.probe_transport(transport)
1657
except errors.NotBranchError:
1658
# this format does not find a control dir here.
1660
raise errors.NotBranchError(path=transport.base)
1663
def probe_transport(klass, transport):
1664
"""Return the .bzrdir style format present in a directory."""
1666
format_string = transport.get(".bzr/branch-format").read()
1667
except errors.NoSuchFile:
1668
raise errors.NotBranchError(path=transport.base)
1671
return klass._formats[format_string]
1673
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1676
def get_default_format(klass):
1677
"""Return the current default format."""
1678
return klass._default_format
1680
def get_format_string(self):
1681
"""Return the ASCII format string that identifies this format."""
1682
raise NotImplementedError(self.get_format_string)
1684
def get_format_description(self):
1685
"""Return the short description for this format."""
1686
raise NotImplementedError(self.get_format_description)
1688
def get_converter(self, format=None):
1689
"""Return the converter to use to convert bzrdirs needing converts.
1691
This returns a bzrlib.bzrdir.Converter object.
1693
This should return the best upgrader to step this format towards the
1694
current default format. In the case of plugins we can/should provide
1695
some means for them to extend the range of returnable converters.
1697
:param format: Optional format to override the default format of the
1700
raise NotImplementedError(self.get_converter)
1702
def initialize(self, url, possible_transports=None):
1703
"""Create a bzr control dir at this url and return an opened copy.
1705
Subclasses should typically override initialize_on_transport
1706
instead of this method.
1708
return self.initialize_on_transport(get_transport(url,
1709
possible_transports))
1711
def initialize_on_transport(self, transport):
1712
"""Initialize a new bzrdir in the base directory of a Transport."""
1714
# can we hand off the request to the smart server rather than using
1716
client_medium = transport.get_smart_medium()
1717
except errors.NoSmartMedium:
1718
return self._initialize_on_transport_vfs(transport)
1720
# Current RPC's only know how to create bzr metadir1 instances, so
1721
# we still delegate to vfs methods if the requested format is not a
1723
if type(self) != BzrDirMetaFormat1:
1724
return self._initialize_on_transport_vfs(transport)
1725
remote_format = RemoteBzrDirFormat()
1726
self._supply_sub_formats_to(remote_format)
1727
return remote_format.initialize_on_transport(transport)
1729
def _initialize_on_transport_vfs(self, transport):
1730
"""Initialize a new bzrdir using VFS calls.
1732
:param transport: The transport to create the .bzr directory in.
1735
# Since we are creating a .bzr directory, inherit the
1736
# mode from the root directory
1737
temp_control = lockable_files.LockableFiles(transport,
1738
'', lockable_files.TransportLock)
1739
temp_control._transport.mkdir('.bzr',
1740
# FIXME: RBC 20060121 don't peek under
1742
mode=temp_control._dir_mode)
1743
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1744
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1745
file_mode = temp_control._file_mode
1747
bzrdir_transport = transport.clone('.bzr')
1748
utf8_files = [('README',
1749
"This is a Bazaar control directory.\n"
1750
"Do not change any files in this directory.\n"
1751
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1752
('branch-format', self.get_format_string()),
1754
# NB: no need to escape relative paths that are url safe.
1755
control_files = lockable_files.LockableFiles(bzrdir_transport,
1756
self._lock_file_name, self._lock_class)
1757
control_files.create_lock()
1758
control_files.lock_write()
1760
for (filename, content) in utf8_files:
1761
bzrdir_transport.put_bytes(filename, content,
1764
control_files.unlock()
1765
return self.open(transport, _found=True)
1767
def is_supported(self):
1768
"""Is this format supported?
1770
Supported formats must be initializable and openable.
1771
Unsupported formats may not support initialization or committing or
1772
some other features depending on the reason for not being supported.
1776
def same_model(self, target_format):
1777
return (self.repository_format.rich_root_data ==
1778
target_format.rich_root_data)
1781
def known_formats(klass):
1782
"""Return all the known formats.
1784
Concrete formats should override _known_formats.
1786
# There is double indirection here to make sure that control
1787
# formats used by more than one dir format will only be probed
1788
# once. This can otherwise be quite expensive for remote connections.
1790
for format in klass._control_formats:
1791
result.update(format._known_formats())
1795
def _known_formats(klass):
1796
"""Return the known format instances for this control format."""
1797
return set(klass._formats.values())
1799
def open(self, transport, _found=False):
1800
"""Return an instance of this format for the dir transport points at.
1802
_found is a private parameter, do not use it.
1805
found_format = BzrDirFormat.find_format(transport)
1806
if not isinstance(found_format, self.__class__):
1807
raise AssertionError("%s was asked to open %s, but it seems to need "
1809
% (self, transport, found_format))
1810
# Allow subclasses - use the found format.
1811
self._supply_sub_formats_to(found_format)
1812
return found_format._open(transport)
1813
return self._open(transport)
1815
def _open(self, transport):
1816
"""Template method helper for opening BzrDirectories.
1818
This performs the actual open and any additional logic or parameter
1821
raise NotImplementedError(self._open)
1824
def register_format(klass, format):
1825
klass._formats[format.get_format_string()] = format
1828
def register_control_format(klass, format):
1829
"""Register a format that does not use '.bzr' for its control dir.
1831
TODO: This should be pulled up into a 'ControlDirFormat' base class
1832
which BzrDirFormat can inherit from, and renamed to register_format
1833
there. It has been done without that for now for simplicity of
1836
klass._control_formats.append(format)
1839
def register_control_server_format(klass, format):
1840
"""Register a control format for client-server environments.
1842
These formats will be tried before ones registered with
1843
register_control_format. This gives implementations that decide to the
1844
chance to grab it before anything looks at the contents of the format
1847
klass._control_server_formats.append(format)
1850
def _set_default_format(klass, format):
1851
"""Set default format (for testing behavior of defaults only)"""
1852
klass._default_format = format
1856
return self.get_format_description().rstrip()
1858
def _supply_sub_formats_to(self, other_format):
1859
"""Give other_format the same values for sub formats as this has.
1861
This method is expected to be used when parameterising a
1862
RemoteBzrDirFormat instance with the parameters from a
1863
BzrDirMetaFormat1 instance.
1865
:param other_format: other_format is a format which should be
1866
compatible with whatever sub formats are supported by self.
1871
def unregister_format(klass, format):
1872
del klass._formats[format.get_format_string()]
1875
def unregister_control_format(klass, format):
1876
klass._control_formats.remove(format)
1879
class BzrDirFormat4(BzrDirFormat):
1880
"""Bzr dir format 4.
1882
This format is a combined format for working tree, branch and repository.
1884
- Format 1 working trees [always]
1885
- Format 4 branches [always]
1886
- Format 4 repositories [always]
1888
This format is deprecated: it indexes texts using a text it which is
1889
removed in format 5; write support for this format has been removed.
1892
_lock_class = lockable_files.TransportLock
1894
def get_format_string(self):
1895
"""See BzrDirFormat.get_format_string()."""
1896
return "Bazaar-NG branch, format 0.0.4\n"
1898
def get_format_description(self):
1899
"""See BzrDirFormat.get_format_description()."""
1900
return "All-in-one format 4"
1902
def get_converter(self, format=None):
1903
"""See BzrDirFormat.get_converter()."""
1904
# there is one and only one upgrade path here.
1905
return ConvertBzrDir4To5()
1907
def initialize_on_transport(self, transport):
1908
"""Format 4 branches cannot be created."""
1909
raise errors.UninitializableFormat(self)
1911
def is_supported(self):
1912
"""Format 4 is not supported.
1914
It is not supported because the model changed from 4 to 5 and the
1915
conversion logic is expensive - so doing it on the fly was not
1920
def _open(self, transport):
1921
"""See BzrDirFormat._open."""
1922
return BzrDir4(transport, self)
1924
def __return_repository_format(self):
1925
"""Circular import protection."""
1926
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1927
return RepositoryFormat4()
1928
repository_format = property(__return_repository_format)
1931
class BzrDirFormat5(BzrDirFormat):
1932
"""Bzr control format 5.
1934
This format is a combined format for working tree, branch and repository.
1936
- Format 2 working trees [always]
1937
- Format 4 branches [always]
1938
- Format 5 repositories [always]
1939
Unhashed stores in the repository.
1942
_lock_class = lockable_files.TransportLock
1944
def get_format_string(self):
1945
"""See BzrDirFormat.get_format_string()."""
1946
return "Bazaar-NG branch, format 5\n"
1948
def get_branch_format(self):
1949
from bzrlib import branch
1950
return branch.BzrBranchFormat4()
1952
def get_format_description(self):
1953
"""See BzrDirFormat.get_format_description()."""
1954
return "All-in-one format 5"
1956
def get_converter(self, format=None):
1957
"""See BzrDirFormat.get_converter()."""
1958
# there is one and only one upgrade path here.
1959
return ConvertBzrDir5To6()
1961
def _initialize_for_clone(self, url):
1962
return self.initialize_on_transport(get_transport(url), _cloning=True)
1964
def initialize_on_transport(self, transport, _cloning=False):
1965
"""Format 5 dirs always have working tree, branch and repository.
1967
Except when they are being cloned.
1969
from bzrlib.branch import BzrBranchFormat4
1970
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1971
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1972
RepositoryFormat5().initialize(result, _internal=True)
1974
branch = BzrBranchFormat4().initialize(result)
1975
result._init_workingtree()
1978
def _open(self, transport):
1979
"""See BzrDirFormat._open."""
1980
return BzrDir5(transport, self)
1982
def __return_repository_format(self):
1983
"""Circular import protection."""
1984
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1985
return RepositoryFormat5()
1986
repository_format = property(__return_repository_format)
1989
class BzrDirFormat6(BzrDirFormat):
1990
"""Bzr control format 6.
1992
This format is a combined format for working tree, branch and repository.
1994
- Format 2 working trees [always]
1995
- Format 4 branches [always]
1996
- Format 6 repositories [always]
1999
_lock_class = lockable_files.TransportLock
2001
def get_format_string(self):
2002
"""See BzrDirFormat.get_format_string()."""
2003
return "Bazaar-NG branch, format 6\n"
2005
def get_format_description(self):
2006
"""See BzrDirFormat.get_format_description()."""
2007
return "All-in-one format 6"
2009
def get_branch_format(self):
2010
from bzrlib import branch
2011
return branch.BzrBranchFormat4()
2013
def get_converter(self, format=None):
2014
"""See BzrDirFormat.get_converter()."""
2015
# there is one and only one upgrade path here.
2016
return ConvertBzrDir6ToMeta()
2018
def _initialize_for_clone(self, url):
2019
return self.initialize_on_transport(get_transport(url), _cloning=True)
2021
def initialize_on_transport(self, transport, _cloning=False):
2022
"""Format 6 dirs always have working tree, branch and repository.
2024
Except when they are being cloned.
2026
from bzrlib.branch import BzrBranchFormat4
2027
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2028
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
2029
RepositoryFormat6().initialize(result, _internal=True)
2031
branch = BzrBranchFormat4().initialize(result)
2032
result._init_workingtree()
2035
def _open(self, transport):
2036
"""See BzrDirFormat._open."""
2037
return BzrDir6(transport, self)
2039
def __return_repository_format(self):
2040
"""Circular import protection."""
2041
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2042
return RepositoryFormat6()
2043
repository_format = property(__return_repository_format)
2046
class BzrDirMetaFormat1(BzrDirFormat):
2047
"""Bzr meta control format 1
2049
This is the first format with split out working tree, branch and repository
2052
- Format 3 working trees [optional]
2053
- Format 5 branches [optional]
2054
- Format 7 repositories [optional]
2057
_lock_class = lockdir.LockDir
2060
self._workingtree_format = None
2061
self._branch_format = None
2063
def __eq__(self, other):
2064
if other.__class__ is not self.__class__:
2066
if other.repository_format != self.repository_format:
2068
if other.workingtree_format != self.workingtree_format:
2072
def __ne__(self, other):
2073
return not self == other
2075
def get_branch_format(self):
2076
if self._branch_format is None:
2077
from bzrlib.branch import BranchFormat
2078
self._branch_format = BranchFormat.get_default_format()
2079
return self._branch_format
2081
def set_branch_format(self, format):
2082
self._branch_format = format
2084
def require_stacking(self):
2085
if not self.get_branch_format().supports_stacking():
2086
# We need to make a stacked branch, but the default format for the
2087
# target doesn't support stacking. So force a branch that *can*
2089
from bzrlib.branch import BzrBranchFormat7
2090
branch_format = BzrBranchFormat7()
2091
self.set_branch_format(branch_format)
2092
mutter("using %r for stacking" % (branch_format,))
2093
from bzrlib.repofmt import pack_repo
2094
if self.repository_format.rich_root_data:
2095
bzrdir_format_name = '1.6.1-rich-root'
2096
repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2098
bzrdir_format_name = '1.6'
2099
repo_format = pack_repo.RepositoryFormatKnitPack5()
2100
note('Source format does not support stacking, using format:'
2102
bzrdir_format_name, repo_format.get_format_description())
2103
self.repository_format = repo_format
2105
def get_converter(self, format=None):
2106
"""See BzrDirFormat.get_converter()."""
2108
format = BzrDirFormat.get_default_format()
2109
if not isinstance(self, format.__class__):
2110
# converting away from metadir is not implemented
2111
raise NotImplementedError(self.get_converter)
2112
return ConvertMetaToMeta(format)
2114
def get_format_string(self):
2115
"""See BzrDirFormat.get_format_string()."""
2116
return "Bazaar-NG meta directory, format 1\n"
2118
def get_format_description(self):
2119
"""See BzrDirFormat.get_format_description()."""
2120
return "Meta directory format 1"
2122
def _open(self, transport):
2123
"""See BzrDirFormat._open."""
2124
return BzrDirMeta1(transport, self)
2126
def __return_repository_format(self):
2127
"""Circular import protection."""
2128
if getattr(self, '_repository_format', None):
2129
return self._repository_format
2130
from bzrlib.repository import RepositoryFormat
2131
return RepositoryFormat.get_default_format()
2133
def _set_repository_format(self, value):
2134
"""Allow changing the repository format for metadir formats."""
2135
self._repository_format = value
2137
repository_format = property(__return_repository_format,
2138
_set_repository_format)
2140
def _supply_sub_formats_to(self, other_format):
2141
"""Give other_format the same values for sub formats as this has.
2143
This method is expected to be used when parameterising a
2144
RemoteBzrDirFormat instance with the parameters from a
2145
BzrDirMetaFormat1 instance.
2147
:param other_format: other_format is a format which should be
2148
compatible with whatever sub formats are supported by self.
2151
if getattr(self, '_repository_format', None) is not None:
2152
other_format.repository_format = self.repository_format
2153
if self._branch_format is not None:
2154
other_format._branch_format = self._branch_format
2155
if self._workingtree_format is not None:
2156
other_format.workingtree_format = self.workingtree_format
2158
def __get_workingtree_format(self):
2159
if self._workingtree_format is None:
2160
from bzrlib.workingtree import WorkingTreeFormat
2161
self._workingtree_format = WorkingTreeFormat.get_default_format()
2162
return self._workingtree_format
2164
def __set_workingtree_format(self, wt_format):
2165
self._workingtree_format = wt_format
2167
workingtree_format = property(__get_workingtree_format,
2168
__set_workingtree_format)
2171
# Register bzr control format
2172
BzrDirFormat.register_control_format(BzrDirFormat)
2174
# Register bzr formats
2175
BzrDirFormat.register_format(BzrDirFormat4())
2176
BzrDirFormat.register_format(BzrDirFormat5())
2177
BzrDirFormat.register_format(BzrDirFormat6())
2178
__default_format = BzrDirMetaFormat1()
2179
BzrDirFormat.register_format(__default_format)
2180
BzrDirFormat._default_format = __default_format
2183
class Converter(object):
2184
"""Converts a disk format object from one format to another."""
2186
def convert(self, to_convert, pb):
2187
"""Perform the conversion of to_convert, giving feedback via pb.
2189
:param to_convert: The disk object to convert.
2190
:param pb: a progress bar to use for progress information.
2193
def step(self, message):
2194
"""Update the pb by a step."""
2196
self.pb.update(message, self.count, self.total)
2199
class ConvertBzrDir4To5(Converter):
2200
"""Converts format 4 bzr dirs to format 5."""
2203
super(ConvertBzrDir4To5, self).__init__()
2204
self.converted_revs = set()
2205
self.absent_revisions = set()
2209
def convert(self, to_convert, pb):
2210
"""See Converter.convert()."""
2211
self.bzrdir = to_convert
2213
self.pb.note('starting upgrade from format 4 to 5')
2214
if isinstance(self.bzrdir.transport, local.LocalTransport):
2215
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2216
self._convert_to_weaves()
2217
return BzrDir.open(self.bzrdir.root_transport.base)
2219
def _convert_to_weaves(self):
2220
self.pb.note('note: upgrade may be faster if all store files are ungzipped first')
2223
stat = self.bzrdir.transport.stat('weaves')
2224
if not S_ISDIR(stat.st_mode):
2225
self.bzrdir.transport.delete('weaves')
2226
self.bzrdir.transport.mkdir('weaves')
2227
except errors.NoSuchFile:
2228
self.bzrdir.transport.mkdir('weaves')
2229
# deliberately not a WeaveFile as we want to build it up slowly.
2230
self.inv_weave = Weave('inventory')
2231
# holds in-memory weaves for all files
2232
self.text_weaves = {}
2233
self.bzrdir.transport.delete('branch-format')
2234
self.branch = self.bzrdir.open_branch()
2235
self._convert_working_inv()
2236
rev_history = self.branch.revision_history()
2237
# to_read is a stack holding the revisions we still need to process;
2238
# appending to it adds new highest-priority revisions
2239
self.known_revisions = set(rev_history)
2240
self.to_read = rev_history[-1:]
2242
rev_id = self.to_read.pop()
2243
if (rev_id not in self.revisions
2244
and rev_id not in self.absent_revisions):
2245
self._load_one_rev(rev_id)
2247
to_import = self._make_order()
2248
for i, rev_id in enumerate(to_import):
2249
self.pb.update('converting revision', i, len(to_import))
2250
self._convert_one_rev(rev_id)
2252
self._write_all_weaves()
2253
self._write_all_revs()
2254
self.pb.note('upgraded to weaves:')
2255
self.pb.note(' %6d revisions and inventories', len(self.revisions))
2256
self.pb.note(' %6d revisions not present', len(self.absent_revisions))
2257
self.pb.note(' %6d texts', self.text_count)
2258
self._cleanup_spare_files_after_format4()
2259
self.branch._transport.put_bytes(
2261
BzrDirFormat5().get_format_string(),
2262
mode=self.bzrdir._get_file_mode())
2264
def _cleanup_spare_files_after_format4(self):
2265
# FIXME working tree upgrade foo.
2266
for n in 'merged-patches', 'pending-merged-patches':
2268
## assert os.path.getsize(p) == 0
2269
self.bzrdir.transport.delete(n)
2270
except errors.NoSuchFile:
2272
self.bzrdir.transport.delete_tree('inventory-store')
2273
self.bzrdir.transport.delete_tree('text-store')
2275
def _convert_working_inv(self):
2276
inv = xml4.serializer_v4.read_inventory(
2277
self.branch._transport.get('inventory'))
2278
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2279
self.branch._transport.put_bytes('inventory', new_inv_xml,
2280
mode=self.bzrdir._get_file_mode())
2282
def _write_all_weaves(self):
2283
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2284
weave_transport = self.bzrdir.transport.clone('weaves')
2285
weaves = WeaveStore(weave_transport, prefixed=False)
2286
transaction = WriteTransaction()
2290
for file_id, file_weave in self.text_weaves.items():
2291
self.pb.update('writing weave', i, len(self.text_weaves))
2292
weaves._put_weave(file_id, file_weave, transaction)
2294
self.pb.update('inventory', 0, 1)
2295
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2296
self.pb.update('inventory', 1, 1)
2300
def _write_all_revs(self):
2301
"""Write all revisions out in new form."""
2302
self.bzrdir.transport.delete_tree('revision-store')
2303
self.bzrdir.transport.mkdir('revision-store')
2304
revision_transport = self.bzrdir.transport.clone('revision-store')
2306
from bzrlib.xml5 import serializer_v5
2307
from bzrlib.repofmt.weaverepo import RevisionTextStore
2308
revision_store = RevisionTextStore(revision_transport,
2309
serializer_v5, False, versionedfile.PrefixMapper(),
2310
lambda:True, lambda:True)
2312
for i, rev_id in enumerate(self.converted_revs):
2313
self.pb.update('write revision', i, len(self.converted_revs))
2314
text = serializer_v5.write_revision_to_string(
2315
self.revisions[rev_id])
2317
revision_store.add_lines(key, None, osutils.split_lines(text))
2321
def _load_one_rev(self, rev_id):
2322
"""Load a revision object into memory.
2324
Any parents not either loaded or abandoned get queued to be
2326
self.pb.update('loading revision',
2327
len(self.revisions),
2328
len(self.known_revisions))
2329
if not self.branch.repository.has_revision(rev_id):
2331
self.pb.note('revision {%s} not present in branch; '
2332
'will be converted as a ghost',
2334
self.absent_revisions.add(rev_id)
2336
rev = self.branch.repository.get_revision(rev_id)
2337
for parent_id in rev.parent_ids:
2338
self.known_revisions.add(parent_id)
2339
self.to_read.append(parent_id)
2340
self.revisions[rev_id] = rev
2342
def _load_old_inventory(self, rev_id):
2343
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2344
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2345
inv.revision_id = rev_id
2346
rev = self.revisions[rev_id]
2349
def _load_updated_inventory(self, rev_id):
2350
inv_xml = self.inv_weave.get_text(rev_id)
2351
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2354
def _convert_one_rev(self, rev_id):
2355
"""Convert revision and all referenced objects to new format."""
2356
rev = self.revisions[rev_id]
2357
inv = self._load_old_inventory(rev_id)
2358
present_parents = [p for p in rev.parent_ids
2359
if p not in self.absent_revisions]
2360
self._convert_revision_contents(rev, inv, present_parents)
2361
self._store_new_inv(rev, inv, present_parents)
2362
self.converted_revs.add(rev_id)
2364
def _store_new_inv(self, rev, inv, present_parents):
2365
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2366
new_inv_sha1 = sha_string(new_inv_xml)
2367
self.inv_weave.add_lines(rev.revision_id,
2369
new_inv_xml.splitlines(True))
2370
rev.inventory_sha1 = new_inv_sha1
2372
def _convert_revision_contents(self, rev, inv, present_parents):
2373
"""Convert all the files within a revision.
2375
Also upgrade the inventory to refer to the text revision ids."""
2376
rev_id = rev.revision_id
2377
mutter('converting texts of revision {%s}',
2379
parent_invs = map(self._load_updated_inventory, present_parents)
2380
entries = inv.iter_entries()
2382
for path, ie in entries:
2383
self._convert_file_version(rev, ie, parent_invs)
2385
def _convert_file_version(self, rev, ie, parent_invs):
2386
"""Convert one version of one file.
2388
The file needs to be added into the weave if it is a merge
2389
of >=2 parents or if it's changed from its parent.
2391
file_id = ie.file_id
2392
rev_id = rev.revision_id
2393
w = self.text_weaves.get(file_id)
2396
self.text_weaves[file_id] = w
2397
text_changed = False
2398
parent_candiate_entries = ie.parent_candidates(parent_invs)
2399
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2400
# XXX: Note that this is unordered - and this is tolerable because
2401
# the previous code was also unordered.
2402
previous_entries = dict((head, parent_candiate_entries[head]) for head
2404
self.snapshot_ie(previous_entries, ie, w, rev_id)
2407
@symbol_versioning.deprecated_method(symbol_versioning.one_one)
2408
def get_parents(self, revision_ids):
2409
for revision_id in revision_ids:
2410
yield self.revisions[revision_id].parent_ids
2412
def get_parent_map(self, revision_ids):
2413
"""See graph._StackedParentsProvider.get_parent_map"""
2414
return dict((revision_id, self.revisions[revision_id])
2415
for revision_id in revision_ids
2416
if revision_id in self.revisions)
2418
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2419
# TODO: convert this logic, which is ~= snapshot to
2420
# a call to:. This needs the path figured out. rather than a work_tree
2421
# a v4 revision_tree can be given, or something that looks enough like
2422
# one to give the file content to the entry if it needs it.
2423
# and we need something that looks like a weave store for snapshot to
2425
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2426
if len(previous_revisions) == 1:
2427
previous_ie = previous_revisions.values()[0]
2428
if ie._unchanged(previous_ie):
2429
ie.revision = previous_ie.revision
2432
text = self.branch.repository._text_store.get(ie.text_id)
2433
file_lines = text.readlines()
2434
w.add_lines(rev_id, previous_revisions, file_lines)
2435
self.text_count += 1
2437
w.add_lines(rev_id, previous_revisions, [])
2438
ie.revision = rev_id
2440
def _make_order(self):
2441
"""Return a suitable order for importing revisions.
2443
The order must be such that an revision is imported after all
2444
its (present) parents.
2446
todo = set(self.revisions.keys())
2447
done = self.absent_revisions.copy()
2450
# scan through looking for a revision whose parents
2452
for rev_id in sorted(list(todo)):
2453
rev = self.revisions[rev_id]
2454
parent_ids = set(rev.parent_ids)
2455
if parent_ids.issubset(done):
2456
# can take this one now
2457
order.append(rev_id)
2463
class ConvertBzrDir5To6(Converter):
2464
"""Converts format 5 bzr dirs to format 6."""
2466
def convert(self, to_convert, pb):
2467
"""See Converter.convert()."""
2468
self.bzrdir = to_convert
2470
self.pb.note('starting upgrade from format 5 to 6')
2471
self._convert_to_prefixed()
2472
return BzrDir.open(self.bzrdir.root_transport.base)
2474
def _convert_to_prefixed(self):
2475
from bzrlib.store import TransportStore
2476
self.bzrdir.transport.delete('branch-format')
2477
for store_name in ["weaves", "revision-store"]:
2478
self.pb.note("adding prefixes to %s" % store_name)
2479
store_transport = self.bzrdir.transport.clone(store_name)
2480
store = TransportStore(store_transport, prefixed=True)
2481
for urlfilename in store_transport.list_dir('.'):
2482
filename = urlutils.unescape(urlfilename)
2483
if (filename.endswith(".weave") or
2484
filename.endswith(".gz") or
2485
filename.endswith(".sig")):
2486
file_id, suffix = os.path.splitext(filename)
2490
new_name = store._mapper.map((file_id,)) + suffix
2491
# FIXME keep track of the dirs made RBC 20060121
2493
store_transport.move(filename, new_name)
2494
except errors.NoSuchFile: # catches missing dirs strangely enough
2495
store_transport.mkdir(osutils.dirname(new_name))
2496
store_transport.move(filename, new_name)
2497
self.bzrdir.transport.put_bytes(
2499
BzrDirFormat6().get_format_string(),
2500
mode=self.bzrdir._get_file_mode())
2503
class ConvertBzrDir6ToMeta(Converter):
2504
"""Converts format 6 bzr dirs to metadirs."""
2506
def convert(self, to_convert, pb):
2507
"""See Converter.convert()."""
2508
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2509
from bzrlib.branch import BzrBranchFormat5
2510
self.bzrdir = to_convert
2513
self.total = 20 # the steps we know about
2514
self.garbage_inventories = []
2515
self.dir_mode = self.bzrdir._get_dir_mode()
2516
self.file_mode = self.bzrdir._get_file_mode()
2518
self.pb.note('starting upgrade from format 6 to metadir')
2519
self.bzrdir.transport.put_bytes(
2521
"Converting to format 6",
2522
mode=self.file_mode)
2523
# its faster to move specific files around than to open and use the apis...
2524
# first off, nuke ancestry.weave, it was never used.
2526
self.step('Removing ancestry.weave')
2527
self.bzrdir.transport.delete('ancestry.weave')
2528
except errors.NoSuchFile:
2530
# find out whats there
2531
self.step('Finding branch files')
2532
last_revision = self.bzrdir.open_branch().last_revision()
2533
bzrcontents = self.bzrdir.transport.list_dir('.')
2534
for name in bzrcontents:
2535
if name.startswith('basis-inventory.'):
2536
self.garbage_inventories.append(name)
2537
# create new directories for repository, working tree and branch
2538
repository_names = [('inventory.weave', True),
2539
('revision-store', True),
2541
self.step('Upgrading repository ')
2542
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2543
self.make_lock('repository')
2544
# we hard code the formats here because we are converting into
2545
# the meta format. The meta format upgrader can take this to a
2546
# future format within each component.
2547
self.put_format('repository', RepositoryFormat7())
2548
for entry in repository_names:
2549
self.move_entry('repository', entry)
2551
self.step('Upgrading branch ')
2552
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2553
self.make_lock('branch')
2554
self.put_format('branch', BzrBranchFormat5())
2555
branch_files = [('revision-history', True),
2556
('branch-name', True),
2558
for entry in branch_files:
2559
self.move_entry('branch', entry)
2561
checkout_files = [('pending-merges', True),
2562
('inventory', True),
2563
('stat-cache', False)]
2564
# If a mandatory checkout file is not present, the branch does not have
2565
# a functional checkout. Do not create a checkout in the converted
2567
for name, mandatory in checkout_files:
2568
if mandatory and name not in bzrcontents:
2569
has_checkout = False
2573
if not has_checkout:
2574
self.pb.note('No working tree.')
2575
# If some checkout files are there, we may as well get rid of them.
2576
for name, mandatory in checkout_files:
2577
if name in bzrcontents:
2578
self.bzrdir.transport.delete(name)
2580
from bzrlib.workingtree import WorkingTreeFormat3
2581
self.step('Upgrading working tree')
2582
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2583
self.make_lock('checkout')
2585
'checkout', WorkingTreeFormat3())
2586
self.bzrdir.transport.delete_multi(
2587
self.garbage_inventories, self.pb)
2588
for entry in checkout_files:
2589
self.move_entry('checkout', entry)
2590
if last_revision is not None:
2591
self.bzrdir.transport.put_bytes(
2592
'checkout/last-revision', last_revision)
2593
self.bzrdir.transport.put_bytes(
2595
BzrDirMetaFormat1().get_format_string(),
2596
mode=self.file_mode)
2597
return BzrDir.open(self.bzrdir.root_transport.base)
2599
def make_lock(self, name):
2600
"""Make a lock for the new control dir name."""
2601
self.step('Make %s lock' % name)
2602
ld = lockdir.LockDir(self.bzrdir.transport,
2604
file_modebits=self.file_mode,
2605
dir_modebits=self.dir_mode)
2608
def move_entry(self, new_dir, entry):
2609
"""Move then entry name into new_dir."""
2611
mandatory = entry[1]
2612
self.step('Moving %s' % name)
2614
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2615
except errors.NoSuchFile:
2619
def put_format(self, dirname, format):
2620
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2621
format.get_format_string(),
2625
class ConvertMetaToMeta(Converter):
2626
"""Converts the components of metadirs."""
2628
def __init__(self, target_format):
2629
"""Create a metadir to metadir converter.
2631
:param target_format: The final metadir format that is desired.
2633
self.target_format = target_format
2635
def convert(self, to_convert, pb):
2636
"""See Converter.convert()."""
2637
self.bzrdir = to_convert
2641
self.step('checking repository format')
2643
repo = self.bzrdir.open_repository()
2644
except errors.NoRepositoryPresent:
2647
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2648
from bzrlib.repository import CopyConverter
2649
self.pb.note('starting repository conversion')
2650
converter = CopyConverter(self.target_format.repository_format)
2651
converter.convert(repo, pb)
2653
branch = self.bzrdir.open_branch()
2654
except errors.NotBranchError:
2657
# TODO: conversions of Branch and Tree should be done by
2658
# InterXFormat lookups/some sort of registry.
2659
# Avoid circular imports
2660
from bzrlib import branch as _mod_branch
2661
old = branch._format.__class__
2662
new = self.target_format.get_branch_format().__class__
2664
if (old == _mod_branch.BzrBranchFormat5 and
2665
new in (_mod_branch.BzrBranchFormat6,
2666
_mod_branch.BzrBranchFormat7)):
2667
branch_converter = _mod_branch.Converter5to6()
2668
elif (old == _mod_branch.BzrBranchFormat6 and
2669
new == _mod_branch.BzrBranchFormat7):
2670
branch_converter = _mod_branch.Converter6to7()
2672
raise errors.BadConversionTarget("No converter", new)
2673
branch_converter.convert(branch)
2674
branch = self.bzrdir.open_branch()
2675
old = branch._format.__class__
2677
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2678
except (errors.NoWorkingTree, errors.NotLocalUrl):
2681
# TODO: conversions of Branch and Tree should be done by
2682
# InterXFormat lookups
2683
if (isinstance(tree, workingtree.WorkingTree3) and
2684
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2685
isinstance(self.target_format.workingtree_format,
2686
workingtree_4.DirStateWorkingTreeFormat)):
2687
workingtree_4.Converter3to4().convert(tree)
2688
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2689
not isinstance(tree, workingtree_4.WorkingTree5) and
2690
isinstance(self.target_format.workingtree_format,
2691
workingtree_4.WorkingTreeFormat5)):
2692
workingtree_4.Converter4to5().convert(tree)
2696
# This is not in remote.py because it's small, and needs to be registered.
2697
# Putting it in remote.py creates a circular import problem.
2698
# we can make it a lazy object if the control formats is turned into something
2700
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2701
"""Format representing bzrdirs accessed via a smart server"""
2703
def get_format_description(self):
2704
return 'bzr remote bzrdir'
2706
def get_format_string(self):
2707
raise NotImplementedError(self.get_format_string)
2710
def probe_transport(klass, transport):
2711
"""Return a RemoteBzrDirFormat object if it looks possible."""
2713
medium = transport.get_smart_medium()
2714
except (NotImplementedError, AttributeError,
2715
errors.TransportNotPossible, errors.NoSmartMedium,
2716
errors.SmartProtocolError):
2717
# no smart server, so not a branch for this format type.
2718
raise errors.NotBranchError(path=transport.base)
2720
# Decline to open it if the server doesn't support our required
2721
# version (3) so that the VFS-based transport will do it.
2722
if medium.should_probe():
2724
server_version = medium.protocol_version()
2725
except errors.SmartProtocolError:
2726
# Apparently there's no usable smart server there, even though
2727
# the medium supports the smart protocol.
2728
raise errors.NotBranchError(path=transport.base)
2729
if server_version != '2':
2730
raise errors.NotBranchError(path=transport.base)
2733
def initialize_on_transport(self, transport):
2735
# hand off the request to the smart server
2736
client_medium = transport.get_smart_medium()
2737
except errors.NoSmartMedium:
2738
# TODO: lookup the local format from a server hint.
2739
local_dir_format = BzrDirMetaFormat1()
2740
return local_dir_format.initialize_on_transport(transport)
2741
client = _SmartClient(client_medium)
2742
path = client.remote_path_from_transport(transport)
2743
response = client.call('BzrDirFormat.initialize', path)
2744
if response[0] != 'ok':
2745
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2746
format = RemoteBzrDirFormat()
2747
self._supply_sub_formats_to(format)
2748
return remote.RemoteBzrDir(transport, format)
2750
def _open(self, transport):
2751
return remote.RemoteBzrDir(transport, self)
2753
def __eq__(self, other):
2754
if not isinstance(other, RemoteBzrDirFormat):
2756
return self.get_format_description() == other.get_format_description()
2758
def __return_repository_format(self):
2759
# Always return a RemoteRepositoryFormat object, but if a specific bzr
2760
# repository format has been asked for, tell the RemoteRepositoryFormat
2761
# that it should use that for init() etc.
2762
result = remote.RemoteRepositoryFormat()
2763
custom_format = getattr(self, '_repository_format', None)
2765
# We will use the custom format to create repositories over the
2766
# wire; expose its details like rich_root_data for code to query
2767
if isinstance(custom_format, remote.RemoteRepositoryFormat):
2768
result._custom_format = custom_format._custom_format
2770
result._custom_format = custom_format
2771
result.rich_root_data = custom_format.rich_root_data
2774
def get_branch_format(self):
2775
result = BzrDirMetaFormat1.get_branch_format(self)
2776
if not isinstance(result, remote.RemoteBranchFormat):
2777
new_result = remote.RemoteBranchFormat()
2778
new_result._custom_format = result
2780
self.set_branch_format(new_result)
2784
repository_format = property(__return_repository_format,
2785
BzrDirMetaFormat1._set_repository_format) #.im_func)
2788
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
2791
class BzrDirFormatInfo(object):
2793
def __init__(self, native, deprecated, hidden, experimental):
2794
self.deprecated = deprecated
2795
self.native = native
2796
self.hidden = hidden
2797
self.experimental = experimental
2800
class BzrDirFormatRegistry(registry.Registry):
2801
"""Registry of user-selectable BzrDir subformats.
2803
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
2804
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
2808
"""Create a BzrDirFormatRegistry."""
2809
self._aliases = set()
2810
self._registration_order = list()
2811
super(BzrDirFormatRegistry, self).__init__()
2814
"""Return a set of the format names which are aliases."""
2815
return frozenset(self._aliases)
2817
def register_metadir(self, key,
2818
repository_format, help, native=True, deprecated=False,
2824
"""Register a metadir subformat.
2826
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
2827
by the Repository format.
2829
:param repository_format: The fully-qualified repository format class
2831
:param branch_format: Fully-qualified branch format class name as
2833
:param tree_format: Fully-qualified tree format class name as
2836
# This should be expanded to support setting WorkingTree and Branch
2837
# formats, once BzrDirMetaFormat1 supports that.
2838
def _load(full_name):
2839
mod_name, factory_name = full_name.rsplit('.', 1)
2841
mod = __import__(mod_name, globals(), locals(),
2843
except ImportError, e:
2844
raise ImportError('failed to load %s: %s' % (full_name, e))
2846
factory = getattr(mod, factory_name)
2847
except AttributeError:
2848
raise AttributeError('no factory %s in module %r'
2853
bd = BzrDirMetaFormat1()
2854
if branch_format is not None:
2855
bd.set_branch_format(_load(branch_format))
2856
if tree_format is not None:
2857
bd.workingtree_format = _load(tree_format)
2858
if repository_format is not None:
2859
bd.repository_format = _load(repository_format)
2861
self.register(key, helper, help, native, deprecated, hidden,
2862
experimental, alias)
2864
def register(self, key, factory, help, native=True, deprecated=False,
2865
hidden=False, experimental=False, alias=False):
2866
"""Register a BzrDirFormat factory.
2868
The factory must be a callable that takes one parameter: the key.
2869
It must produce an instance of the BzrDirFormat when called.
2871
This function mainly exists to prevent the info object from being
2874
registry.Registry.register(self, key, factory, help,
2875
BzrDirFormatInfo(native, deprecated, hidden, experimental))
2877
self._aliases.add(key)
2878
self._registration_order.append(key)
2880
def register_lazy(self, key, module_name, member_name, help, native=True,
2881
deprecated=False, hidden=False, experimental=False, alias=False):
2882
registry.Registry.register_lazy(self, key, module_name, member_name,
2883
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
2885
self._aliases.add(key)
2886
self._registration_order.append(key)
2888
def set_default(self, key):
2889
"""Set the 'default' key to be a clone of the supplied key.
2891
This method must be called once and only once.
2893
registry.Registry.register(self, 'default', self.get(key),
2894
self.get_help(key), info=self.get_info(key))
2895
self._aliases.add('default')
2897
def set_default_repository(self, key):
2898
"""Set the FormatRegistry default and Repository default.
2900
This is a transitional method while Repository.set_default_format
2903
if 'default' in self:
2904
self.remove('default')
2905
self.set_default(key)
2906
format = self.get('default')()
2908
def make_bzrdir(self, key):
2909
return self.get(key)()
2911
def help_topic(self, topic):
2913
default_realkey = None
2914
default_help = self.get_help('default')
2916
for key in self._registration_order:
2917
if key == 'default':
2919
help = self.get_help(key)
2920
if help == default_help:
2921
default_realkey = key
2923
help_pairs.append((key, help))
2925
def wrapped(key, help, info):
2927
help = '(native) ' + help
2928
return ':%s:\n%s\n\n' % (key,
2929
textwrap.fill(help, initial_indent=' ',
2930
subsequent_indent=' '))
2931
if default_realkey is not None:
2932
output += wrapped(default_realkey, '(default) %s' % default_help,
2933
self.get_info('default'))
2934
deprecated_pairs = []
2935
experimental_pairs = []
2936
for key, help in help_pairs:
2937
info = self.get_info(key)
2940
elif info.deprecated:
2941
deprecated_pairs.append((key, help))
2942
elif info.experimental:
2943
experimental_pairs.append((key, help))
2945
output += wrapped(key, help, info)
2946
output += "\nSee ``bzr help formats`` for more about storage formats."
2948
if len(experimental_pairs) > 0:
2949
other_output += "Experimental formats are shown below.\n\n"
2950
for key, help in experimental_pairs:
2951
info = self.get_info(key)
2952
other_output += wrapped(key, help, info)
2955
"No experimental formats are available.\n\n"
2956
if len(deprecated_pairs) > 0:
2957
other_output += "\nDeprecated formats are shown below.\n\n"
2958
for key, help in deprecated_pairs:
2959
info = self.get_info(key)
2960
other_output += wrapped(key, help, info)
2963
"\nNo deprecated formats are available.\n\n"
2965
"\nSee ``bzr help formats`` for more about storage formats."
2967
if topic == 'other-formats':
2973
class RepositoryAcquisitionPolicy(object):
2974
"""Abstract base class for repository acquisition policies.
2976
A repository acquisition policy decides how a BzrDir acquires a repository
2977
for a branch that is being created. The most basic policy decision is
2978
whether to create a new repository or use an existing one.
2980
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2983
:param stack_on: A location to stack on
2984
:param stack_on_pwd: If stack_on is relative, the location it is
2986
:param require_stacking: If True, it is a failure to not stack.
2988
self._stack_on = stack_on
2989
self._stack_on_pwd = stack_on_pwd
2990
self._require_stacking = require_stacking
2992
def configure_branch(self, branch):
2993
"""Apply any configuration data from this policy to the branch.
2995
Default implementation sets repository stacking.
2997
if self._stack_on is None:
2999
if self._stack_on_pwd is None:
3000
stack_on = self._stack_on
3003
stack_on = urlutils.rebase_url(self._stack_on,
3005
branch.bzrdir.root_transport.base)
3006
except errors.InvalidRebaseURLs:
3007
stack_on = self._get_full_stack_on()
3009
branch.set_stacked_on_url(stack_on)
3010
except errors.UnstackableBranchFormat:
3011
if self._require_stacking:
3014
def _get_full_stack_on(self):
3015
"""Get a fully-qualified URL for the stack_on location."""
3016
if self._stack_on is None:
3018
if self._stack_on_pwd is None:
3019
return self._stack_on
3021
return urlutils.join(self._stack_on_pwd, self._stack_on)
3023
def _add_fallback(self, repository, possible_transports=None):
3024
"""Add a fallback to the supplied repository, if stacking is set."""
3025
stack_on = self._get_full_stack_on()
3026
if stack_on is None:
3028
stacked_dir = BzrDir.open(stack_on,
3029
possible_transports=possible_transports)
3031
stacked_repo = stacked_dir.open_branch().repository
3032
except errors.NotBranchError:
3033
stacked_repo = stacked_dir.open_repository()
3035
repository.add_fallback_repository(stacked_repo)
3036
except errors.UnstackableRepositoryFormat:
3037
if self._require_stacking:
3040
self._require_stacking = True
3042
def acquire_repository(self, make_working_trees=None, shared=False):
3043
"""Acquire a repository for this bzrdir.
3045
Implementations may create a new repository or use a pre-exising
3047
:param make_working_trees: If creating a repository, set
3048
make_working_trees to this value (if non-None)
3049
:param shared: If creating a repository, make it shared if True
3050
:return: A repository
3052
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3055
class CreateRepository(RepositoryAcquisitionPolicy):
3056
"""A policy of creating a new repository"""
3058
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3059
require_stacking=False):
3062
:param bzrdir: The bzrdir to create the repository on.
3063
:param stack_on: A location to stack on
3064
:param stack_on_pwd: If stack_on is relative, the location it is
3067
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3069
self._bzrdir = bzrdir
3071
def acquire_repository(self, make_working_trees=None, shared=False):
3072
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3074
Creates the desired repository in the bzrdir we already have.
3076
repository = self._bzrdir.create_repository(shared=shared)
3077
self._add_fallback(repository,
3078
possible_transports=[self._bzrdir.transport])
3079
if make_working_trees is not None:
3080
repository.set_make_working_trees(make_working_trees)
3084
class UseExistingRepository(RepositoryAcquisitionPolicy):
3085
"""A policy of reusing an existing repository"""
3087
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3088
require_stacking=False):
3091
:param repository: The repository to use.
3092
:param stack_on: A location to stack on
3093
:param stack_on_pwd: If stack_on is relative, the location it is
3096
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3098
self._repository = repository
3100
def acquire_repository(self, make_working_trees=None, shared=False):
3101
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3103
Returns an existing repository to use
3105
self._add_fallback(self._repository,
3106
possible_transports=[self._repository.bzrdir.transport])
3107
return self._repository
3110
# Please register new formats after old formats so that formats
3111
# appear in chronological order and format descriptions can build
3113
format_registry = BzrDirFormatRegistry()
3114
# The pre-0.8 formats have their repository format network name registered in
3115
# repository.py. MetaDir formats have their repository format network name
3116
# inferred from their disk format string.
3117
format_registry.register('weave', BzrDirFormat6,
3118
'Pre-0.8 format. Slower than knit and does not'
3119
' support checkouts or shared repositories.',
3121
format_registry.register_metadir('metaweave',
3122
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3123
'Transitional format in 0.8. Slower than knit.',
3124
branch_format='bzrlib.branch.BzrBranchFormat5',
3125
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3127
format_registry.register_metadir('knit',
3128
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3129
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3130
branch_format='bzrlib.branch.BzrBranchFormat5',
3131
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3133
format_registry.register_metadir('dirstate',
3134
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3135
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3136
'above when accessed over the network.',
3137
branch_format='bzrlib.branch.BzrBranchFormat5',
3138
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3139
# directly from workingtree_4 triggers a circular import.
3140
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3142
format_registry.register_metadir('dirstate-tags',
3143
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3144
help='New in 0.15: Fast local operations and improved scaling for '
3145
'network operations. Additionally adds support for tags.'
3146
' Incompatible with bzr < 0.15.',
3147
branch_format='bzrlib.branch.BzrBranchFormat6',
3148
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3150
format_registry.register_metadir('rich-root',
3151
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3152
help='New in 1.0. Better handling of tree roots. Incompatible with'
3154
branch_format='bzrlib.branch.BzrBranchFormat6',
3155
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3157
format_registry.register_metadir('dirstate-with-subtree',
3158
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3159
help='New in 0.15: Fast local operations and improved scaling for '
3160
'network operations. Additionally adds support for versioning nested '
3161
'bzr branches. Incompatible with bzr < 0.15.',
3162
branch_format='bzrlib.branch.BzrBranchFormat6',
3163
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3167
format_registry.register_metadir('pack-0.92',
3168
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3169
help='New in 0.92: Pack-based format with data compatible with '
3170
'dirstate-tags format repositories. Interoperates with '
3171
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3172
'Previously called knitpack-experimental. '
3173
'For more information, see '
3174
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3175
branch_format='bzrlib.branch.BzrBranchFormat6',
3176
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3178
format_registry.register_metadir('pack-0.92-subtree',
3179
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3180
help='New in 0.92: Pack-based format with data compatible with '
3181
'dirstate-with-subtree format repositories. Interoperates with '
3182
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3183
'Previously called knitpack-experimental. '
3184
'For more information, see '
3185
'http://doc.bazaar-vcs.org/latest/developers/packrepo.html.',
3186
branch_format='bzrlib.branch.BzrBranchFormat6',
3187
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3191
format_registry.register_metadir('rich-root-pack',
3192
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3193
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3194
'(needed for bzr-svn).',
3195
branch_format='bzrlib.branch.BzrBranchFormat6',
3196
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3198
format_registry.register_metadir('1.6',
3199
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3200
help='A format that allows a branch to indicate that there is another '
3201
'(stacked) repository that should be used to access data that is '
3202
'not present locally.',
3203
branch_format='bzrlib.branch.BzrBranchFormat7',
3204
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3206
format_registry.register_metadir('1.6.1-rich-root',
3207
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3208
help='A variant of 1.6 that supports rich-root data '
3209
'(needed for bzr-svn).',
3210
branch_format='bzrlib.branch.BzrBranchFormat7',
3211
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3213
format_registry.register_metadir('1.9',
3214
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3215
help='A repository format using B+tree indexes. These indexes '
3216
'are smaller in size, have smarter caching and provide faster '
3217
'performance for most operations.',
3218
branch_format='bzrlib.branch.BzrBranchFormat7',
3219
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3221
format_registry.register_metadir('1.9-rich-root',
3222
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3223
help='A variant of 1.9 that supports rich-root data '
3224
'(needed for bzr-svn).',
3225
branch_format='bzrlib.branch.BzrBranchFormat7',
3226
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3228
format_registry.register_metadir('development-wt5',
3229
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3230
help='A working-tree format that supports views and content filtering.',
3231
branch_format='bzrlib.branch.BzrBranchFormat7',
3232
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3235
format_registry.register_metadir('development-wt5-rich-root',
3236
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3237
help='A variant of development-wt5 that supports rich-root data '
3238
'(needed for bzr-svn).',
3239
branch_format='bzrlib.branch.BzrBranchFormat7',
3240
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3243
# The following two formats should always just be aliases.
3244
format_registry.register_metadir('development',
3245
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3246
help='Current development format. Can convert data to and from pack-0.92 '
3247
'(and anything compatible with pack-0.92) format repositories. '
3248
'Repositories and branches in this format can only be read by bzr.dev. '
3250
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3252
branch_format='bzrlib.branch.BzrBranchFormat7',
3253
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3257
format_registry.register_metadir('development-subtree',
3258
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3259
help='Current development format, subtree variant. Can convert data to and '
3260
'from pack-0.92-subtree (and anything compatible with '
3261
'pack-0.92-subtree) format repositories. Repositories and branches in '
3262
'this format can only be read by bzr.dev. Please read '
3263
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3265
branch_format='bzrlib.branch.BzrBranchFormat7',
3266
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3270
# And the development formats above will have aliased one of the following:
3271
format_registry.register_metadir('development2',
3272
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2',
3273
help='1.6.1 with B+Tree based index. '
3275
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3277
branch_format='bzrlib.branch.BzrBranchFormat7',
3278
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3282
format_registry.register_metadir('development2-subtree',
3283
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3284
help='1.6.1-subtree with B+Tree based index. '
3286
'http://doc.bazaar-vcs.org/latest/developers/development-repo.html '
3288
branch_format='bzrlib.branch.BzrBranchFormat7',
3289
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3293
# The current format that is made on 'bzr init'.
3294
format_registry.set_default('pack-0.92')