1
# Copyright (C) 2006-2010 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""BzrDir logic. The BzrDir is the basic control directory used by bzr.
19
At format 7 this was split out into Branch, Repository and Checkout control
22
Note: This module has a lot of ``open`` functions/methods that return
23
references to in-memory objects. As a rule, there are no matching ``close``
24
methods. To free any associated resources, simply stop referencing the
28
# TODO: Move old formats into a plugin to make this file smaller.
34
from bzrlib.lazy_import import lazy_import
35
lazy_import(globals(), """
36
from stat import S_ISDIR
50
revision as _mod_revision,
60
from bzrlib.osutils import (
63
from bzrlib.push import (
66
from bzrlib.repofmt import pack_repo
67
from bzrlib.smart.client import _SmartClient
68
from bzrlib.store.versioned import WeaveStore
69
from bzrlib.transactions import WriteTransaction
70
from bzrlib.transport import (
71
do_catching_redirections,
75
from bzrlib.weave import Weave
78
from bzrlib.trace import (
91
class ControlComponent(object):
92
"""Abstract base class for control directory components.
94
This provides interfaces that are common across bzrdirs,
95
repositories, branches, and workingtree control directories.
97
They all expose two urls and transports: the *user* URL is the
98
one that stops above the control directory (eg .bzr) and that
99
should normally be used in messages, and the *control* URL is
100
under that in eg .bzr/checkout and is used to read the control
103
This can be used as a mixin and is intended to fit with
108
def control_transport(self):
109
raise NotImplementedError
112
def control_url(self):
113
return self.control_transport.base
116
def user_transport(self):
117
raise NotImplementedError
121
return self.user_transport.base
124
class BzrDir(ControlComponent):
125
"""A .bzr control diretory.
127
BzrDir instances let you create or open any of the things that can be
128
found within .bzr - checkouts, branches and repositories.
131
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
132
:ivar root_transport:
133
a transport connected to the directory this bzr was opened from
134
(i.e. the parent directory holding the .bzr directory).
136
Everything in the bzrdir should have the same file permissions.
138
:cvar hooks: An instance of BzrDirHooks.
141
def break_lock(self):
142
"""Invoke break_lock on the first object in the bzrdir.
144
If there is a tree, the tree is opened and break_lock() called.
145
Otherwise, branch is tried, and finally repository.
147
# XXX: This seems more like a UI function than something that really
148
# belongs in this class.
150
thing_to_unlock = self.open_workingtree()
151
except (errors.NotLocalUrl, errors.NoWorkingTree):
153
thing_to_unlock = self.open_branch()
154
except errors.NotBranchError:
156
thing_to_unlock = self.open_repository()
157
except errors.NoRepositoryPresent:
159
thing_to_unlock.break_lock()
161
def can_convert_format(self):
162
"""Return true if this bzrdir is one whose format we can convert from."""
165
def check_conversion_target(self, target_format):
166
"""Check that a bzrdir as a whole can be converted to a new format."""
167
# The only current restriction is that the repository content can be
168
# fetched compatibly with the target.
169
target_repo_format = target_format.repository_format
171
self.open_repository()._format.check_conversion_target(
173
except errors.NoRepositoryPresent:
174
# No repo, no problem.
178
def _check_supported(format, allow_unsupported,
179
recommend_upgrade=True,
181
"""Give an error or warning on old formats.
183
:param format: may be any kind of format - workingtree, branch,
186
:param allow_unsupported: If true, allow opening
187
formats that are strongly deprecated, and which may
188
have limited functionality.
190
:param recommend_upgrade: If true (default), warn
191
the user through the ui object that they may wish
192
to upgrade the object.
194
# TODO: perhaps move this into a base Format class; it's not BzrDir
195
# specific. mbp 20070323
196
if not allow_unsupported and not format.is_supported():
197
# see open_downlevel to open legacy branches.
198
raise errors.UnsupportedFormatError(format=format)
199
if recommend_upgrade \
200
and getattr(format, 'upgrade_recommended', False):
201
ui.ui_factory.recommend_upgrade(
202
format.get_format_description(),
205
def clone(self, url, revision_id=None, force_new_repo=False,
206
preserve_stacking=False):
207
"""Clone this bzrdir and its contents to url verbatim.
209
:param url: The url create the clone at. If url's last component does
210
not exist, it will be created.
211
:param revision_id: The tip revision-id to use for any branch or
212
working tree. If not None, then the clone operation may tune
213
itself to download less data.
214
:param force_new_repo: Do not use a shared repository for the target
215
even if one is available.
216
:param preserve_stacking: When cloning a stacked branch, stack the
217
new branch on top of the other branch's stacked-on branch.
219
return self.clone_on_transport(get_transport(url),
220
revision_id=revision_id,
221
force_new_repo=force_new_repo,
222
preserve_stacking=preserve_stacking)
224
def clone_on_transport(self, transport, revision_id=None,
225
force_new_repo=False, preserve_stacking=False, stacked_on=None,
226
create_prefix=False, use_existing_dir=True):
227
"""Clone this bzrdir and its contents to transport verbatim.
229
:param transport: The transport for the location to produce the clone
230
at. If the target directory does not exist, it will be created.
231
:param revision_id: The tip revision-id to use for any branch or
232
working tree. If not None, then the clone operation may tune
233
itself to download less data.
234
:param force_new_repo: Do not use a shared repository for the target,
235
even if one is available.
236
:param preserve_stacking: When cloning a stacked branch, stack the
237
new branch on top of the other branch's stacked-on branch.
238
:param create_prefix: Create any missing directories leading up to
240
:param use_existing_dir: Use an existing directory if one exists.
242
# Overview: put together a broad description of what we want to end up
243
# with; then make as few api calls as possible to do it.
245
# We may want to create a repo/branch/tree, if we do so what format
246
# would we want for each:
247
require_stacking = (stacked_on is not None)
248
format = self.cloning_metadir(require_stacking)
250
# Figure out what objects we want:
252
local_repo = self.find_repository()
253
except errors.NoRepositoryPresent:
256
local_branch = self.open_branch()
257
except errors.NotBranchError:
260
# enable fallbacks when branch is not a branch reference
261
if local_branch.repository.has_same_location(local_repo):
262
local_repo = local_branch.repository
263
if preserve_stacking:
265
stacked_on = local_branch.get_stacked_on_url()
266
except (errors.UnstackableBranchFormat,
267
errors.UnstackableRepositoryFormat,
270
# Bug: We create a metadir without knowing if it can support stacking,
271
# we should look up the policy needs first, or just use it as a hint,
274
make_working_trees = local_repo.make_working_trees()
275
want_shared = local_repo.is_shared()
276
repo_format_name = format.repository_format.network_name()
278
make_working_trees = False
280
repo_format_name = None
282
result_repo, result, require_stacking, repository_policy = \
283
format.initialize_on_transport_ex(transport,
284
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
285
force_new_repo=force_new_repo, stacked_on=stacked_on,
286
stack_on_pwd=self.root_transport.base,
287
repo_format_name=repo_format_name,
288
make_working_trees=make_working_trees, shared_repo=want_shared)
291
# If the result repository is in the same place as the
292
# resulting bzr dir, it will have no content, further if the
293
# result is not stacked then we know all content should be
294
# copied, and finally if we are copying up to a specific
295
# revision_id then we can use the pending-ancestry-result which
296
# does not require traversing all of history to describe it.
297
if (result_repo.bzrdir.root_transport.base ==
298
result.root_transport.base and not require_stacking and
299
revision_id is not None):
300
fetch_spec = graph.PendingAncestryResult(
301
[revision_id], local_repo)
302
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
304
result_repo.fetch(local_repo, revision_id=revision_id)
308
if result_repo is not None:
309
raise AssertionError('result_repo not None(%r)' % result_repo)
310
# 1 if there is a branch present
311
# make sure its content is available in the target repository
313
if local_branch is not None:
314
result_branch = local_branch.clone(result, revision_id=revision_id,
315
repository_policy=repository_policy)
317
# Cheaper to check if the target is not local, than to try making
319
result.root_transport.local_abspath('.')
320
if result_repo is None or result_repo.make_working_trees():
321
self.open_workingtree().clone(result)
322
except (errors.NoWorkingTree, errors.NotLocalUrl):
326
# TODO: This should be given a Transport, and should chdir up; otherwise
327
# this will open a new connection.
328
def _make_tail(self, url):
329
t = get_transport(url)
333
def create(cls, base, format=None, possible_transports=None):
334
"""Create a new BzrDir at the url 'base'.
336
:param format: If supplied, the format of branch to create. If not
337
supplied, the default is used.
338
:param possible_transports: If supplied, a list of transports that
339
can be reused to share a remote connection.
341
if cls is not BzrDir:
342
raise AssertionError("BzrDir.create always creates the default"
343
" format, not one of %r" % cls)
344
t = get_transport(base, possible_transports)
347
format = BzrDirFormat.get_default_format()
348
return format.initialize_on_transport(t)
351
def find_bzrdirs(transport, evaluate=None, list_current=None):
352
"""Find bzrdirs recursively from current location.
354
This is intended primarily as a building block for more sophisticated
355
functionality, like finding trees under a directory, or finding
356
branches that use a given repository.
357
:param evaluate: An optional callable that yields recurse, value,
358
where recurse controls whether this bzrdir is recursed into
359
and value is the value to yield. By default, all bzrdirs
360
are recursed into, and the return value is the bzrdir.
361
:param list_current: if supplied, use this function to list the current
362
directory, instead of Transport.list_dir
363
:return: a generator of found bzrdirs, or whatever evaluate returns.
365
if list_current is None:
366
def list_current(transport):
367
return transport.list_dir('')
369
def evaluate(bzrdir):
372
pending = [transport]
373
while len(pending) > 0:
374
current_transport = pending.pop()
377
bzrdir = BzrDir.open_from_transport(current_transport)
378
except errors.NotBranchError:
381
recurse, value = evaluate(bzrdir)
384
subdirs = list_current(current_transport)
385
except errors.NoSuchFile:
388
for subdir in sorted(subdirs, reverse=True):
389
pending.append(current_transport.clone(subdir))
391
def list_branches(self):
392
"""Return a sequence of all branches local to this control directory.
396
return [self.open_branch()]
397
except errors.NotBranchError:
401
def find_branches(transport):
402
"""Find all branches under a transport.
404
This will find all branches below the transport, including branches
405
inside other branches. Where possible, it will use
406
Repository.find_branches.
408
To list all the branches that use a particular Repository, see
409
Repository.find_branches
411
def evaluate(bzrdir):
413
repository = bzrdir.open_repository()
414
except errors.NoRepositoryPresent:
417
return False, ([], repository)
418
return True, (bzrdir.list_branches(), None)
420
for branches, repo in BzrDir.find_bzrdirs(transport,
423
ret.extend(repo.find_branches())
424
if branches is not None:
428
def destroy_repository(self):
429
"""Destroy the repository in this BzrDir"""
430
raise NotImplementedError(self.destroy_repository)
432
def create_branch(self, name=None):
433
"""Create a branch in this BzrDir.
435
:param name: Name of the colocated branch to create, None for
438
The bzrdir's format will control what branch format is created.
439
For more control see BranchFormatXX.create(a_bzrdir).
441
raise NotImplementedError(self.create_branch)
443
def destroy_branch(self, name=None):
444
"""Destroy a branch in this BzrDir.
446
:param name: Name of the branch to destroy, None for the default
449
raise NotImplementedError(self.destroy_branch)
452
def create_branch_and_repo(base, force_new_repo=False, format=None):
453
"""Create a new BzrDir, Branch and Repository at the url 'base'.
455
This will use the current default BzrDirFormat unless one is
456
specified, and use whatever
457
repository format that that uses via bzrdir.create_branch and
458
create_repository. If a shared repository is available that is used
461
The created Branch object is returned.
463
:param base: The URL to create the branch at.
464
:param force_new_repo: If True a new repository is always created.
465
:param format: If supplied, the format of branch to create. If not
466
supplied, the default is used.
468
bzrdir = BzrDir.create(base, format)
469
bzrdir._find_or_create_repository(force_new_repo)
470
return bzrdir.create_branch()
472
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
473
stack_on_pwd=None, require_stacking=False):
474
"""Return an object representing a policy to use.
476
This controls whether a new repository is created, and the format of
477
that repository, or some existing shared repository used instead.
479
If stack_on is supplied, will not seek a containing shared repo.
481
:param force_new_repo: If True, require a new repository to be created.
482
:param stack_on: If supplied, the location to stack on. If not
483
supplied, a default_stack_on location may be used.
484
:param stack_on_pwd: If stack_on is relative, the location it is
487
def repository_policy(found_bzrdir):
490
config = found_bzrdir.get_config()
492
stack_on = config.get_default_stack_on()
493
if stack_on is not None:
494
stack_on_pwd = found_bzrdir.root_transport.base
496
# does it have a repository ?
498
repository = found_bzrdir.open_repository()
499
except errors.NoRepositoryPresent:
502
if ((found_bzrdir.root_transport.base !=
503
self.root_transport.base) and not repository.is_shared()):
504
# Don't look higher, can't use a higher shared repo.
512
return UseExistingRepository(repository, stack_on,
513
stack_on_pwd, require_stacking=require_stacking), True
515
return CreateRepository(self, stack_on, stack_on_pwd,
516
require_stacking=require_stacking), True
518
if not force_new_repo:
520
policy = self._find_containing(repository_policy)
521
if policy is not None:
525
return UseExistingRepository(self.open_repository(),
526
stack_on, stack_on_pwd,
527
require_stacking=require_stacking)
528
except errors.NoRepositoryPresent:
530
return CreateRepository(self, stack_on, stack_on_pwd,
531
require_stacking=require_stacking)
533
def _find_or_create_repository(self, force_new_repo):
534
"""Create a new repository if needed, returning the repository."""
535
policy = self.determine_repository_policy(force_new_repo)
536
return policy.acquire_repository()[0]
539
def create_branch_convenience(base, force_new_repo=False,
540
force_new_tree=None, format=None,
541
possible_transports=None):
542
"""Create a new BzrDir, Branch and Repository at the url 'base'.
544
This is a convenience function - it will use an existing repository
545
if possible, can be told explicitly whether to create a working tree or
548
This will use the current default BzrDirFormat unless one is
549
specified, and use whatever
550
repository format that that uses via bzrdir.create_branch and
551
create_repository. If a shared repository is available that is used
552
preferentially. Whatever repository is used, its tree creation policy
555
The created Branch object is returned.
556
If a working tree cannot be made due to base not being a file:// url,
557
no error is raised unless force_new_tree is True, in which case no
558
data is created on disk and NotLocalUrl is raised.
560
:param base: The URL to create the branch at.
561
:param force_new_repo: If True a new repository is always created.
562
:param force_new_tree: If True or False force creation of a tree or
563
prevent such creation respectively.
564
:param format: Override for the bzrdir format to create.
565
:param possible_transports: An optional reusable transports list.
568
# check for non local urls
569
t = get_transport(base, possible_transports)
570
if not isinstance(t, local.LocalTransport):
571
raise errors.NotLocalUrl(base)
572
bzrdir = BzrDir.create(base, format, possible_transports)
573
repo = bzrdir._find_or_create_repository(force_new_repo)
574
result = bzrdir.create_branch()
575
if force_new_tree or (repo.make_working_trees() and
576
force_new_tree is None):
578
bzrdir.create_workingtree()
579
except errors.NotLocalUrl:
584
def create_standalone_workingtree(base, format=None):
585
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
587
'base' must be a local path or a file:// url.
589
This will use the current default BzrDirFormat unless one is
590
specified, and use whatever
591
repository format that that uses for bzrdirformat.create_workingtree,
592
create_branch and create_repository.
594
:param format: Override for the bzrdir format to create.
595
:return: The WorkingTree object.
597
t = get_transport(base)
598
if not isinstance(t, local.LocalTransport):
599
raise errors.NotLocalUrl(base)
600
bzrdir = BzrDir.create_branch_and_repo(base,
602
format=format).bzrdir
603
return bzrdir.create_workingtree()
605
def create_workingtree(self, revision_id=None, from_branch=None,
606
accelerator_tree=None, hardlink=False):
607
"""Create a working tree at this BzrDir.
609
:param revision_id: create it as of this revision id.
610
:param from_branch: override bzrdir branch (for lightweight checkouts)
611
:param accelerator_tree: A tree which can be used for retrieving file
612
contents more quickly than the revision tree, i.e. a workingtree.
613
The revision tree will be used for cases where accelerator_tree's
614
content is different.
616
raise NotImplementedError(self.create_workingtree)
618
def backup_bzrdir(self):
619
"""Backup this bzr control directory.
621
:return: Tuple with old path name and new path name
623
def name_gen(base='backup.bzr'):
625
name = "%s.~%d~" % (base, counter)
626
while self.root_transport.has(name):
628
name = "%s.~%d~" % (base, counter)
631
backup_dir=name_gen()
632
pb = ui.ui_factory.nested_progress_bar()
634
# FIXME: bug 300001 -- the backup fails if the backup directory
635
# already exists, but it should instead either remove it or make
636
# a new backup directory.
638
old_path = self.root_transport.abspath('.bzr')
639
new_path = self.root_transport.abspath(backup_dir)
640
ui.ui_factory.note('making backup of %s\n to %s' % (old_path, new_path,))
641
self.root_transport.copy_tree('.bzr', backup_dir)
642
return (old_path, new_path)
646
def retire_bzrdir(self, limit=10000):
647
"""Permanently disable the bzrdir.
649
This is done by renaming it to give the user some ability to recover
650
if there was a problem.
652
This will have horrible consequences if anyone has anything locked or
654
:param limit: number of times to retry
659
to_path = '.bzr.retired.%d' % i
660
self.root_transport.rename('.bzr', to_path)
661
note("renamed %s to %s"
662
% (self.root_transport.abspath('.bzr'), to_path))
664
except (errors.TransportError, IOError, errors.PathError):
671
def destroy_workingtree(self):
672
"""Destroy the working tree at this BzrDir.
674
Formats that do not support this may raise UnsupportedOperation.
676
raise NotImplementedError(self.destroy_workingtree)
678
def destroy_workingtree_metadata(self):
679
"""Destroy the control files for the working tree at this BzrDir.
681
The contents of working tree files are not affected.
682
Formats that do not support this may raise UnsupportedOperation.
684
raise NotImplementedError(self.destroy_workingtree_metadata)
686
def _find_containing(self, evaluate):
687
"""Find something in a containing control directory.
689
This method will scan containing control dirs, until it finds what
690
it is looking for, decides that it will never find it, or runs out
691
of containing control directories to check.
693
It is used to implement find_repository and
694
determine_repository_policy.
696
:param evaluate: A function returning (value, stop). If stop is True,
697
the value will be returned.
701
result, stop = evaluate(found_bzrdir)
704
next_transport = found_bzrdir.root_transport.clone('..')
705
if (found_bzrdir.root_transport.base == next_transport.base):
706
# top of the file system
708
# find the next containing bzrdir
710
found_bzrdir = BzrDir.open_containing_from_transport(
712
except errors.NotBranchError:
715
def find_repository(self):
716
"""Find the repository that should be used.
718
This does not require a branch as we use it to find the repo for
719
new branches as well as to hook existing branches up to their
722
def usable_repository(found_bzrdir):
723
# does it have a repository ?
725
repository = found_bzrdir.open_repository()
726
except errors.NoRepositoryPresent:
728
if found_bzrdir.root_transport.base == self.root_transport.base:
729
return repository, True
730
elif repository.is_shared():
731
return repository, True
735
found_repo = self._find_containing(usable_repository)
736
if found_repo is None:
737
raise errors.NoRepositoryPresent(self)
740
def get_branch_reference(self):
741
"""Return the referenced URL for the branch in this bzrdir.
743
:raises NotBranchError: If there is no Branch.
744
:return: The URL the branch in this bzrdir references if it is a
745
reference branch, or None for regular branches.
749
def get_branch_transport(self, branch_format, name=None):
750
"""Get the transport for use by branch format in this BzrDir.
752
Note that bzr dirs that do not support format strings will raise
753
IncompatibleFormat if the branch format they are given has
754
a format string, and vice versa.
756
If branch_format is None, the transport is returned with no
757
checking. If it is not None, then the returned transport is
758
guaranteed to point to an existing directory ready for use.
760
raise NotImplementedError(self.get_branch_transport)
762
def _find_creation_modes(self):
763
"""Determine the appropriate modes for files and directories.
765
They're always set to be consistent with the base directory,
766
assuming that this transport allows setting modes.
768
# TODO: Do we need or want an option (maybe a config setting) to turn
769
# this off or override it for particular locations? -- mbp 20080512
770
if self._mode_check_done:
772
self._mode_check_done = True
774
st = self.transport.stat('.')
775
except errors.TransportNotPossible:
776
self._dir_mode = None
777
self._file_mode = None
779
# Check the directory mode, but also make sure the created
780
# directories and files are read-write for this user. This is
781
# mostly a workaround for filesystems which lie about being able to
782
# write to a directory (cygwin & win32)
783
if (st.st_mode & 07777 == 00000):
784
# FTP allows stat but does not return dir/file modes
785
self._dir_mode = None
786
self._file_mode = None
788
self._dir_mode = (st.st_mode & 07777) | 00700
789
# Remove the sticky and execute bits for files
790
self._file_mode = self._dir_mode & ~07111
792
def _get_file_mode(self):
793
"""Return Unix mode for newly created files, or None.
795
if not self._mode_check_done:
796
self._find_creation_modes()
797
return self._file_mode
799
def _get_dir_mode(self):
800
"""Return Unix mode for newly created directories, or None.
802
if not self._mode_check_done:
803
self._find_creation_modes()
804
return self._dir_mode
806
def get_repository_transport(self, repository_format):
807
"""Get the transport for use by repository format in this BzrDir.
809
Note that bzr dirs that do not support format strings will raise
810
IncompatibleFormat if the repository format they are given has
811
a format string, and vice versa.
813
If repository_format is None, the transport is returned with no
814
checking. If it is not None, then the returned transport is
815
guaranteed to point to an existing directory ready for use.
817
raise NotImplementedError(self.get_repository_transport)
819
def get_workingtree_transport(self, tree_format):
820
"""Get the transport for use by workingtree format in this BzrDir.
822
Note that bzr dirs that do not support format strings will raise
823
IncompatibleFormat if the workingtree format they are given has a
824
format string, and vice versa.
826
If workingtree_format is None, the transport is returned with no
827
checking. If it is not None, then the returned transport is
828
guaranteed to point to an existing directory ready for use.
830
raise NotImplementedError(self.get_workingtree_transport)
832
def get_config(self):
833
"""Get configuration for this BzrDir."""
834
return config.BzrDirConfig(self)
836
def _get_config(self):
837
"""By default, no configuration is available."""
840
def __init__(self, _transport, _format):
841
"""Initialize a Bzr control dir object.
843
Only really common logic should reside here, concrete classes should be
844
made with varying behaviours.
846
:param _format: the format that is creating this BzrDir instance.
847
:param _transport: the transport this dir is based at.
849
self._format = _format
850
# these are also under the more standard names of
851
# control_transport and user_transport
852
self.transport = _transport.clone('.bzr')
853
self.root_transport = _transport
854
self._mode_check_done = False
857
def user_transport(self):
858
return self.root_transport
861
def control_transport(self):
862
return self.transport
864
def is_control_filename(self, filename):
865
"""True if filename is the name of a path which is reserved for bzrdir's.
867
:param filename: A filename within the root transport of this bzrdir.
869
This is true IF and ONLY IF the filename is part of the namespace reserved
870
for bzr control dirs. Currently this is the '.bzr' directory in the root
871
of the root_transport. it is expected that plugins will need to extend
872
this in the future - for instance to make bzr talk with svn working
875
# this might be better on the BzrDirFormat class because it refers to
876
# all the possible bzrdir disk formats.
877
# This method is tested via the workingtree is_control_filename tests-
878
# it was extracted from WorkingTree.is_control_filename. If the method's
879
# contract is extended beyond the current trivial implementation, please
880
# add new tests for it to the appropriate place.
881
return filename == '.bzr' or filename.startswith('.bzr/')
883
def needs_format_conversion(self, format=None):
884
"""Return true if this bzrdir needs convert_format run on it.
886
For instance, if the repository format is out of date but the
887
branch and working tree are not, this should return True.
889
:param format: Optional parameter indicating a specific desired
890
format we plan to arrive at.
892
raise NotImplementedError(self.needs_format_conversion)
895
def open_unsupported(base):
896
"""Open a branch which is not supported."""
897
return BzrDir.open(base, _unsupported=True)
900
def open(base, _unsupported=False, possible_transports=None):
901
"""Open an existing bzrdir, rooted at 'base' (url).
903
:param _unsupported: a private parameter to the BzrDir class.
905
t = get_transport(base, possible_transports=possible_transports)
906
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
909
def open_from_transport(transport, _unsupported=False,
910
_server_formats=True):
911
"""Open a bzrdir within a particular directory.
913
:param transport: Transport containing the bzrdir.
914
:param _unsupported: private.
916
for hook in BzrDir.hooks['pre_open']:
918
# Keep initial base since 'transport' may be modified while following
920
base = transport.base
921
def find_format(transport):
922
return transport, BzrDirFormat.find_format(
923
transport, _server_formats=_server_formats)
925
def redirected(transport, e, redirection_notice):
926
redirected_transport = transport._redirected_to(e.source, e.target)
927
if redirected_transport is None:
928
raise errors.NotBranchError(base)
929
note('%s is%s redirected to %s',
930
transport.base, e.permanently, redirected_transport.base)
931
return redirected_transport
934
transport, format = do_catching_redirections(find_format,
937
except errors.TooManyRedirections:
938
raise errors.NotBranchError(base)
940
BzrDir._check_supported(format, _unsupported)
941
return format.open(transport, _found=True)
943
def open_branch(self, name=None, unsupported=False,
944
ignore_fallbacks=False):
945
"""Open the branch object at this BzrDir if one is present.
947
If unsupported is True, then no longer supported branch formats can
950
TODO: static convenience version of this?
952
raise NotImplementedError(self.open_branch)
955
def open_containing(url, possible_transports=None):
956
"""Open an existing branch which contains url.
958
:param url: url to search from.
959
See open_containing_from_transport for more detail.
961
transport = get_transport(url, possible_transports)
962
return BzrDir.open_containing_from_transport(transport)
965
def open_containing_from_transport(a_transport):
966
"""Open an existing branch which contains a_transport.base.
968
This probes for a branch at a_transport, and searches upwards from there.
970
Basically we keep looking up until we find the control directory or
971
run into the root. If there isn't one, raises NotBranchError.
972
If there is one and it is either an unrecognised format or an unsupported
973
format, UnknownFormatError or UnsupportedFormatError are raised.
974
If there is one, it is returned, along with the unused portion of url.
976
:return: The BzrDir that contains the path, and a Unicode path
977
for the rest of the URL.
979
# this gets the normalised url back. I.e. '.' -> the full path.
980
url = a_transport.base
983
result = BzrDir.open_from_transport(a_transport)
984
return result, urlutils.unescape(a_transport.relpath(url))
985
except errors.NotBranchError, e:
988
new_t = a_transport.clone('..')
989
except errors.InvalidURLJoin:
990
# reached the root, whatever that may be
991
raise errors.NotBranchError(path=url)
992
if new_t.base == a_transport.base:
993
# reached the root, whatever that may be
994
raise errors.NotBranchError(path=url)
997
def _get_tree_branch(self):
998
"""Return the branch and tree, if any, for this bzrdir.
1000
Return None for tree if not present or inaccessible.
1001
Raise NotBranchError if no branch is present.
1002
:return: (tree, branch)
1005
tree = self.open_workingtree()
1006
except (errors.NoWorkingTree, errors.NotLocalUrl):
1008
branch = self.open_branch()
1010
branch = tree.branch
1014
def open_tree_or_branch(klass, location):
1015
"""Return the branch and working tree at a location.
1017
If there is no tree at the location, tree will be None.
1018
If there is no branch at the location, an exception will be
1020
:return: (tree, branch)
1022
bzrdir = klass.open(location)
1023
return bzrdir._get_tree_branch()
1026
def open_containing_tree_or_branch(klass, location):
1027
"""Return the branch and working tree contained by a location.
1029
Returns (tree, branch, relpath).
1030
If there is no tree at containing the location, tree will be None.
1031
If there is no branch containing the location, an exception will be
1033
relpath is the portion of the path that is contained by the branch.
1035
bzrdir, relpath = klass.open_containing(location)
1036
tree, branch = bzrdir._get_tree_branch()
1037
return tree, branch, relpath
1040
def open_containing_tree_branch_or_repository(klass, location):
1041
"""Return the working tree, branch and repo contained by a location.
1043
Returns (tree, branch, repository, relpath).
1044
If there is no tree containing the location, tree will be None.
1045
If there is no branch containing the location, branch will be None.
1046
If there is no repository containing the location, repository will be
1048
relpath is the portion of the path that is contained by the innermost
1051
If no tree, branch or repository is found, a NotBranchError is raised.
1053
bzrdir, relpath = klass.open_containing(location)
1055
tree, branch = bzrdir._get_tree_branch()
1056
except errors.NotBranchError:
1058
repo = bzrdir.find_repository()
1059
return None, None, repo, relpath
1060
except (errors.NoRepositoryPresent):
1061
raise errors.NotBranchError(location)
1062
return tree, branch, branch.repository, relpath
1064
def open_repository(self, _unsupported=False):
1065
"""Open the repository object at this BzrDir if one is present.
1067
This will not follow the Branch object pointer - it's strictly a direct
1068
open facility. Most client code should use open_branch().repository to
1069
get at a repository.
1071
:param _unsupported: a private parameter, not part of the api.
1072
TODO: static convenience version of this?
1074
raise NotImplementedError(self.open_repository)
1076
def open_workingtree(self, _unsupported=False,
1077
recommend_upgrade=True, from_branch=None):
1078
"""Open the workingtree object at this BzrDir if one is present.
1080
:param recommend_upgrade: Optional keyword parameter, when True (the
1081
default), emit through the ui module a recommendation that the user
1082
upgrade the working tree when the workingtree being opened is old
1083
(but still fully supported).
1084
:param from_branch: override bzrdir branch (for lightweight checkouts)
1086
raise NotImplementedError(self.open_workingtree)
1088
def has_branch(self, name=None):
1089
"""Tell if this bzrdir contains a branch.
1091
Note: if you're going to open the branch, you should just go ahead
1092
and try, and not ask permission first. (This method just opens the
1093
branch and discards it, and that's somewhat expensive.)
1096
self.open_branch(name)
1098
except errors.NotBranchError:
1101
def has_workingtree(self):
1102
"""Tell if this bzrdir contains a working tree.
1104
This will still raise an exception if the bzrdir has a workingtree that
1105
is remote & inaccessible.
1107
Note: if you're going to open the working tree, you should just go ahead
1108
and try, and not ask permission first. (This method just opens the
1109
workingtree and discards it, and that's somewhat expensive.)
1112
self.open_workingtree(recommend_upgrade=False)
1114
except errors.NoWorkingTree:
1117
def _cloning_metadir(self):
1118
"""Produce a metadir suitable for cloning with.
1120
:returns: (destination_bzrdir_format, source_repository)
1122
result_format = self._format.__class__()
1125
branch = self.open_branch(ignore_fallbacks=True)
1126
source_repository = branch.repository
1127
result_format._branch_format = branch._format
1128
except errors.NotBranchError:
1129
source_branch = None
1130
source_repository = self.open_repository()
1131
except errors.NoRepositoryPresent:
1132
source_repository = None
1134
# XXX TODO: This isinstance is here because we have not implemented
1135
# the fix recommended in bug # 103195 - to delegate this choice the
1136
# repository itself.
1137
repo_format = source_repository._format
1138
if isinstance(repo_format, remote.RemoteRepositoryFormat):
1139
source_repository._ensure_real()
1140
repo_format = source_repository._real_repository._format
1141
result_format.repository_format = repo_format
1143
# TODO: Couldn't we just probe for the format in these cases,
1144
# rather than opening the whole tree? It would be a little
1145
# faster. mbp 20070401
1146
tree = self.open_workingtree(recommend_upgrade=False)
1147
except (errors.NoWorkingTree, errors.NotLocalUrl):
1148
result_format.workingtree_format = None
1150
result_format.workingtree_format = tree._format.__class__()
1151
return result_format, source_repository
1153
def cloning_metadir(self, require_stacking=False):
1154
"""Produce a metadir suitable for cloning or sprouting with.
1156
These operations may produce workingtrees (yes, even though they're
1157
"cloning" something that doesn't have a tree), so a viable workingtree
1158
format must be selected.
1160
:require_stacking: If True, non-stackable formats will be upgraded
1161
to similar stackable formats.
1162
:returns: a BzrDirFormat with all component formats either set
1163
appropriately or set to None if that component should not be
1166
format, repository = self._cloning_metadir()
1167
if format._workingtree_format is None:
1169
if repository is None:
1170
# No repository either
1172
# We have a repository, so set a working tree? (Why? This seems to
1173
# contradict the stated return value in the docstring).
1174
tree_format = repository._format._matchingbzrdir.workingtree_format
1175
format.workingtree_format = tree_format.__class__()
1176
if require_stacking:
1177
format.require_stacking()
1180
def checkout_metadir(self):
1181
return self.cloning_metadir()
1183
def sprout(self, url, revision_id=None, force_new_repo=False,
1184
recurse='down', possible_transports=None,
1185
accelerator_tree=None, hardlink=False, stacked=False,
1186
source_branch=None, create_tree_if_local=True):
1187
"""Create a copy of this bzrdir prepared for use as a new line of
1190
If url's last component does not exist, it will be created.
1192
Attributes related to the identity of the source branch like
1193
branch nickname will be cleaned, a working tree is created
1194
whether one existed before or not; and a local branch is always
1197
if revision_id is not None, then the clone operation may tune
1198
itself to download less data.
1199
:param accelerator_tree: A tree which can be used for retrieving file
1200
contents more quickly than the revision tree, i.e. a workingtree.
1201
The revision tree will be used for cases where accelerator_tree's
1202
content is different.
1203
:param hardlink: If true, hard-link files from accelerator_tree,
1205
:param stacked: If true, create a stacked branch referring to the
1206
location of this control directory.
1207
:param create_tree_if_local: If true, a working-tree will be created
1208
when working locally.
1210
target_transport = get_transport(url, possible_transports)
1211
target_transport.ensure_base()
1212
cloning_format = self.cloning_metadir(stacked)
1213
# Create/update the result branch
1214
result = cloning_format.initialize_on_transport(target_transport)
1215
# if a stacked branch wasn't requested, we don't create one
1216
# even if the origin was stacked
1217
stacked_branch_url = None
1218
if source_branch is not None:
1220
stacked_branch_url = self.root_transport.base
1221
source_repository = source_branch.repository
1224
source_branch = self.open_branch()
1225
source_repository = source_branch.repository
1227
stacked_branch_url = self.root_transport.base
1228
except errors.NotBranchError:
1229
source_branch = None
1231
source_repository = self.open_repository()
1232
except errors.NoRepositoryPresent:
1233
source_repository = None
1234
repository_policy = result.determine_repository_policy(
1235
force_new_repo, stacked_branch_url, require_stacking=stacked)
1236
result_repo, is_new_repo = repository_policy.acquire_repository()
1237
if is_new_repo and revision_id is not None and not stacked:
1238
fetch_spec = graph.PendingAncestryResult(
1239
[revision_id], source_repository)
1242
if source_repository is not None:
1243
# Fetch while stacked to prevent unstacked fetch from
1245
if fetch_spec is None:
1246
result_repo.fetch(source_repository, revision_id=revision_id)
1248
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
1250
if source_branch is None:
1251
# this is for sprouting a bzrdir without a branch; is that
1253
# Not especially, but it's part of the contract.
1254
result_branch = result.create_branch()
1256
result_branch = source_branch.sprout(result,
1257
revision_id=revision_id, repository_policy=repository_policy)
1258
mutter("created new branch %r" % (result_branch,))
1260
# Create/update the result working tree
1261
if (create_tree_if_local and
1262
isinstance(target_transport, local.LocalTransport) and
1263
(result_repo is None or result_repo.make_working_trees())):
1264
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
1268
if wt.path2id('') is None:
1270
wt.set_root_id(self.open_workingtree.get_root_id())
1271
except errors.NoWorkingTree:
1277
if recurse == 'down':
1279
basis = wt.basis_tree()
1281
subtrees = basis.iter_references()
1282
elif result_branch is not None:
1283
basis = result_branch.basis_tree()
1285
subtrees = basis.iter_references()
1286
elif source_branch is not None:
1287
basis = source_branch.basis_tree()
1289
subtrees = basis.iter_references()
1294
for path, file_id in subtrees:
1295
target = urlutils.join(url, urlutils.escape(path))
1296
sublocation = source_branch.reference_parent(file_id, path)
1297
sublocation.bzrdir.sprout(target,
1298
basis.get_reference_revision(file_id, path),
1299
force_new_repo=force_new_repo, recurse=recurse,
1302
if basis is not None:
1306
def push_branch(self, source, revision_id=None, overwrite=False,
1307
remember=False, create_prefix=False):
1308
"""Push the source branch into this BzrDir."""
1310
# If we can open a branch, use its direct repository, otherwise see
1311
# if there is a repository without a branch.
1313
br_to = self.open_branch()
1314
except errors.NotBranchError:
1315
# Didn't find a branch, can we find a repository?
1316
repository_to = self.find_repository()
1318
# Found a branch, so we must have found a repository
1319
repository_to = br_to.repository
1321
push_result = PushResult()
1322
push_result.source_branch = source
1324
# We have a repository but no branch, copy the revisions, and then
1326
repository_to.fetch(source.repository, revision_id=revision_id)
1327
br_to = source.clone(self, revision_id=revision_id)
1328
if source.get_push_location() is None or remember:
1329
source.set_push_location(br_to.base)
1330
push_result.stacked_on = None
1331
push_result.branch_push_result = None
1332
push_result.old_revno = None
1333
push_result.old_revid = _mod_revision.NULL_REVISION
1334
push_result.target_branch = br_to
1335
push_result.master_branch = None
1336
push_result.workingtree_updated = False
1338
# We have successfully opened the branch, remember if necessary:
1339
if source.get_push_location() is None or remember:
1340
source.set_push_location(br_to.base)
1342
tree_to = self.open_workingtree()
1343
except errors.NotLocalUrl:
1344
push_result.branch_push_result = source.push(br_to,
1345
overwrite, stop_revision=revision_id)
1346
push_result.workingtree_updated = False
1347
except errors.NoWorkingTree:
1348
push_result.branch_push_result = source.push(br_to,
1349
overwrite, stop_revision=revision_id)
1350
push_result.workingtree_updated = None # Not applicable
1352
tree_to.lock_write()
1354
push_result.branch_push_result = source.push(
1355
tree_to.branch, overwrite, stop_revision=revision_id)
1359
push_result.workingtree_updated = True
1360
push_result.old_revno = push_result.branch_push_result.old_revno
1361
push_result.old_revid = push_result.branch_push_result.old_revid
1362
push_result.target_branch = \
1363
push_result.branch_push_result.target_branch
1367
class BzrDirHooks(hooks.Hooks):
1368
"""Hooks for BzrDir operations."""
1371
"""Create the default hooks."""
1372
hooks.Hooks.__init__(self)
1373
self.create_hook(hooks.HookPoint('pre_open',
1374
"Invoked before attempting to open a BzrDir with the transport "
1375
"that the open will use.", (1, 14), None))
1377
# install the default hooks
1378
BzrDir.hooks = BzrDirHooks()
1381
class BzrDirPreSplitOut(BzrDir):
1382
"""A common class for the all-in-one formats."""
1384
def __init__(self, _transport, _format):
1385
"""See BzrDir.__init__."""
1386
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
1387
self._control_files = lockable_files.LockableFiles(
1388
self.get_branch_transport(None),
1389
self._format._lock_file_name,
1390
self._format._lock_class)
1392
def break_lock(self):
1393
"""Pre-splitout bzrdirs do not suffer from stale locks."""
1394
raise NotImplementedError(self.break_lock)
1396
def cloning_metadir(self, require_stacking=False):
1397
"""Produce a metadir suitable for cloning with."""
1398
if require_stacking:
1399
return format_registry.make_bzrdir('1.6')
1400
return self._format.__class__()
1402
def clone(self, url, revision_id=None, force_new_repo=False,
1403
preserve_stacking=False):
1404
"""See BzrDir.clone().
1406
force_new_repo has no effect, since this family of formats always
1407
require a new repository.
1408
preserve_stacking has no effect, since no source branch using this
1409
family of formats can be stacked, so there is no stacking to preserve.
1411
self._make_tail(url)
1412
result = self._format._initialize_for_clone(url)
1413
self.open_repository().clone(result, revision_id=revision_id)
1414
from_branch = self.open_branch()
1415
from_branch.clone(result, revision_id=revision_id)
1417
tree = self.open_workingtree()
1418
except errors.NotLocalUrl:
1419
# make a new one, this format always has to have one.
1420
result._init_workingtree()
1425
def create_branch(self, name=None):
1426
"""See BzrDir.create_branch."""
1427
return self._format.get_branch_format().initialize(self, name=name)
1429
def destroy_branch(self, name=None):
1430
"""See BzrDir.destroy_branch."""
1431
raise errors.UnsupportedOperation(self.destroy_branch, self)
1433
def create_repository(self, shared=False):
1434
"""See BzrDir.create_repository."""
1436
raise errors.IncompatibleFormat('shared repository', self._format)
1437
return self.open_repository()
1439
def destroy_repository(self):
1440
"""See BzrDir.destroy_repository."""
1441
raise errors.UnsupportedOperation(self.destroy_repository, self)
1443
def create_workingtree(self, revision_id=None, from_branch=None,
1444
accelerator_tree=None, hardlink=False):
1445
"""See BzrDir.create_workingtree."""
1446
# The workingtree is sometimes created when the bzrdir is created,
1447
# but not when cloning.
1449
# this looks buggy but is not -really-
1450
# because this format creates the workingtree when the bzrdir is
1452
# clone and sprout will have set the revision_id
1453
# and that will have set it for us, its only
1454
# specific uses of create_workingtree in isolation
1455
# that can do wonky stuff here, and that only
1456
# happens for creating checkouts, which cannot be
1457
# done on this format anyway. So - acceptable wart.
1459
warning("can't support hardlinked working trees in %r"
1462
result = self.open_workingtree(recommend_upgrade=False)
1463
except errors.NoSuchFile:
1464
result = self._init_workingtree()
1465
if revision_id is not None:
1466
if revision_id == _mod_revision.NULL_REVISION:
1467
result.set_parent_ids([])
1469
result.set_parent_ids([revision_id])
1472
def _init_workingtree(self):
1473
from bzrlib.workingtree import WorkingTreeFormat2
1475
return WorkingTreeFormat2().initialize(self)
1476
except errors.NotLocalUrl:
1477
# Even though we can't access the working tree, we need to
1478
# create its control files.
1479
return WorkingTreeFormat2()._stub_initialize_on_transport(
1480
self.transport, self._control_files._file_mode)
1482
def destroy_workingtree(self):
1483
"""See BzrDir.destroy_workingtree."""
1484
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1486
def destroy_workingtree_metadata(self):
1487
"""See BzrDir.destroy_workingtree_metadata."""
1488
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1491
def get_branch_transport(self, branch_format, name=None):
1492
"""See BzrDir.get_branch_transport()."""
1493
if name is not None:
1494
raise errors.NoColocatedBranchSupport(self)
1495
if branch_format is None:
1496
return self.transport
1498
branch_format.get_format_string()
1499
except NotImplementedError:
1500
return self.transport
1501
raise errors.IncompatibleFormat(branch_format, self._format)
1503
def get_repository_transport(self, repository_format):
1504
"""See BzrDir.get_repository_transport()."""
1505
if repository_format is None:
1506
return self.transport
1508
repository_format.get_format_string()
1509
except NotImplementedError:
1510
return self.transport
1511
raise errors.IncompatibleFormat(repository_format, self._format)
1513
def get_workingtree_transport(self, workingtree_format):
1514
"""See BzrDir.get_workingtree_transport()."""
1515
if workingtree_format is None:
1516
return self.transport
1518
workingtree_format.get_format_string()
1519
except NotImplementedError:
1520
return self.transport
1521
raise errors.IncompatibleFormat(workingtree_format, self._format)
1523
def needs_format_conversion(self, format=None):
1524
"""See BzrDir.needs_format_conversion()."""
1525
# if the format is not the same as the system default,
1526
# an upgrade is needed.
1528
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1529
% 'needs_format_conversion(format=None)')
1530
format = BzrDirFormat.get_default_format()
1531
return not isinstance(self._format, format.__class__)
1533
def open_branch(self, name=None, unsupported=False,
1534
ignore_fallbacks=False):
1535
"""See BzrDir.open_branch."""
1536
from bzrlib.branch import BzrBranchFormat4
1537
format = BzrBranchFormat4()
1538
self._check_supported(format, unsupported)
1539
return format.open(self, name, _found=True)
1541
def sprout(self, url, revision_id=None, force_new_repo=False,
1542
possible_transports=None, accelerator_tree=None,
1543
hardlink=False, stacked=False, create_tree_if_local=True,
1544
source_branch=None):
1545
"""See BzrDir.sprout()."""
1546
if source_branch is not None:
1547
my_branch = self.open_branch()
1548
if source_branch.base != my_branch.base:
1549
raise AssertionError(
1550
"source branch %r is not within %r with branch %r" %
1551
(source_branch, self, my_branch))
1553
raise errors.UnstackableBranchFormat(
1554
self._format, self.root_transport.base)
1555
if not create_tree_if_local:
1556
raise errors.MustHaveWorkingTree(
1557
self._format, self.root_transport.base)
1558
from bzrlib.workingtree import WorkingTreeFormat2
1559
self._make_tail(url)
1560
result = self._format._initialize_for_clone(url)
1562
self.open_repository().clone(result, revision_id=revision_id)
1563
except errors.NoRepositoryPresent:
1566
self.open_branch().sprout(result, revision_id=revision_id)
1567
except errors.NotBranchError:
1570
# we always want a working tree
1571
WorkingTreeFormat2().initialize(result,
1572
accelerator_tree=accelerator_tree,
1577
class BzrDir4(BzrDirPreSplitOut):
1578
"""A .bzr version 4 control object.
1580
This is a deprecated format and may be removed after sept 2006.
1583
def create_repository(self, shared=False):
1584
"""See BzrDir.create_repository."""
1585
return self._format.repository_format.initialize(self, shared)
1587
def needs_format_conversion(self, format=None):
1588
"""Format 4 dirs are always in need of conversion."""
1590
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1591
% 'needs_format_conversion(format=None)')
1594
def open_repository(self):
1595
"""See BzrDir.open_repository."""
1596
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1597
return RepositoryFormat4().open(self, _found=True)
1600
class BzrDir5(BzrDirPreSplitOut):
1601
"""A .bzr version 5 control object.
1603
This is a deprecated format and may be removed after sept 2006.
1606
def has_workingtree(self):
1607
"""See BzrDir.has_workingtree."""
1610
def open_repository(self):
1611
"""See BzrDir.open_repository."""
1612
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1613
return RepositoryFormat5().open(self, _found=True)
1615
def open_workingtree(self, _unsupported=False,
1616
recommend_upgrade=True):
1617
"""See BzrDir.create_workingtree."""
1618
from bzrlib.workingtree import WorkingTreeFormat2
1619
wt_format = WorkingTreeFormat2()
1620
# we don't warn here about upgrades; that ought to be handled for the
1622
return wt_format.open(self, _found=True)
1625
class BzrDir6(BzrDirPreSplitOut):
1626
"""A .bzr version 6 control object.
1628
This is a deprecated format and may be removed after sept 2006.
1631
def has_workingtree(self):
1632
"""See BzrDir.has_workingtree."""
1635
def open_repository(self):
1636
"""See BzrDir.open_repository."""
1637
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1638
return RepositoryFormat6().open(self, _found=True)
1640
def open_workingtree(self, _unsupported=False,
1641
recommend_upgrade=True):
1642
"""See BzrDir.create_workingtree."""
1643
# we don't warn here about upgrades; that ought to be handled for the
1645
from bzrlib.workingtree import WorkingTreeFormat2
1646
return WorkingTreeFormat2().open(self, _found=True)
1649
class BzrDirMeta1(BzrDir):
1650
"""A .bzr meta version 1 control object.
1652
This is the first control object where the
1653
individual aspects are really split out: there are separate repository,
1654
workingtree and branch subdirectories and any subset of the three can be
1655
present within a BzrDir.
1658
def can_convert_format(self):
1659
"""See BzrDir.can_convert_format()."""
1662
def create_branch(self, name=None):
1663
"""See BzrDir.create_branch."""
1664
return self._format.get_branch_format().initialize(self, name=name)
1666
def destroy_branch(self, name=None):
1667
"""See BzrDir.create_branch."""
1668
if name is not None:
1669
raise errors.NoColocatedBranchSupport(self)
1670
self.transport.delete_tree('branch')
1672
def create_repository(self, shared=False):
1673
"""See BzrDir.create_repository."""
1674
return self._format.repository_format.initialize(self, shared)
1676
def destroy_repository(self):
1677
"""See BzrDir.destroy_repository."""
1678
self.transport.delete_tree('repository')
1680
def create_workingtree(self, revision_id=None, from_branch=None,
1681
accelerator_tree=None, hardlink=False):
1682
"""See BzrDir.create_workingtree."""
1683
return self._format.workingtree_format.initialize(
1684
self, revision_id, from_branch=from_branch,
1685
accelerator_tree=accelerator_tree, hardlink=hardlink)
1687
def destroy_workingtree(self):
1688
"""See BzrDir.destroy_workingtree."""
1689
wt = self.open_workingtree(recommend_upgrade=False)
1690
repository = wt.branch.repository
1691
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1692
wt.revert(old_tree=empty)
1693
self.destroy_workingtree_metadata()
1695
def destroy_workingtree_metadata(self):
1696
self.transport.delete_tree('checkout')
1698
def find_branch_format(self):
1699
"""Find the branch 'format' for this bzrdir.
1701
This might be a synthetic object for e.g. RemoteBranch and SVN.
1703
from bzrlib.branch import BranchFormat
1704
return BranchFormat.find_format(self)
1706
def _get_mkdir_mode(self):
1707
"""Figure out the mode to use when creating a bzrdir subdir."""
1708
temp_control = lockable_files.LockableFiles(self.transport, '',
1709
lockable_files.TransportLock)
1710
return temp_control._dir_mode
1712
def get_branch_reference(self):
1713
"""See BzrDir.get_branch_reference()."""
1714
from bzrlib.branch import BranchFormat
1715
format = BranchFormat.find_format(self)
1716
return format.get_reference(self)
1718
def get_branch_transport(self, branch_format, name=None):
1719
"""See BzrDir.get_branch_transport()."""
1720
if name is not None:
1721
raise errors.NoColocatedBranchSupport(self)
1722
# XXX: this shouldn't implicitly create the directory if it's just
1723
# promising to get a transport -- mbp 20090727
1724
if branch_format is None:
1725
return self.transport.clone('branch')
1727
branch_format.get_format_string()
1728
except NotImplementedError:
1729
raise errors.IncompatibleFormat(branch_format, self._format)
1731
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1732
except errors.FileExists:
1734
return self.transport.clone('branch')
1736
def get_repository_transport(self, repository_format):
1737
"""See BzrDir.get_repository_transport()."""
1738
if repository_format is None:
1739
return self.transport.clone('repository')
1741
repository_format.get_format_string()
1742
except NotImplementedError:
1743
raise errors.IncompatibleFormat(repository_format, self._format)
1745
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1746
except errors.FileExists:
1748
return self.transport.clone('repository')
1750
def get_workingtree_transport(self, workingtree_format):
1751
"""See BzrDir.get_workingtree_transport()."""
1752
if workingtree_format is None:
1753
return self.transport.clone('checkout')
1755
workingtree_format.get_format_string()
1756
except NotImplementedError:
1757
raise errors.IncompatibleFormat(workingtree_format, self._format)
1759
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1760
except errors.FileExists:
1762
return self.transport.clone('checkout')
1764
def has_workingtree(self):
1765
"""Tell if this bzrdir contains a working tree.
1767
This will still raise an exception if the bzrdir has a workingtree that
1768
is remote & inaccessible.
1770
Note: if you're going to open the working tree, you should just go
1771
ahead and try, and not ask permission first.
1773
from bzrlib.workingtree import WorkingTreeFormat
1775
WorkingTreeFormat.find_format(self)
1776
except errors.NoWorkingTree:
1780
def needs_format_conversion(self, format=None):
1781
"""See BzrDir.needs_format_conversion()."""
1783
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1784
% 'needs_format_conversion(format=None)')
1786
format = BzrDirFormat.get_default_format()
1787
if not isinstance(self._format, format.__class__):
1788
# it is not a meta dir format, conversion is needed.
1790
# we might want to push this down to the repository?
1792
if not isinstance(self.open_repository()._format,
1793
format.repository_format.__class__):
1794
# the repository needs an upgrade.
1796
except errors.NoRepositoryPresent:
1798
for branch in self.list_branches():
1799
if not isinstance(branch._format,
1800
format.get_branch_format().__class__):
1801
# the branch needs an upgrade.
1804
my_wt = self.open_workingtree(recommend_upgrade=False)
1805
if not isinstance(my_wt._format,
1806
format.workingtree_format.__class__):
1807
# the workingtree needs an upgrade.
1809
except (errors.NoWorkingTree, errors.NotLocalUrl):
1813
def open_branch(self, name=None, unsupported=False,
1814
ignore_fallbacks=False):
1815
"""See BzrDir.open_branch."""
1816
format = self.find_branch_format()
1817
self._check_supported(format, unsupported)
1818
return format.open(self, name=name,
1819
_found=True, ignore_fallbacks=ignore_fallbacks)
1821
def open_repository(self, unsupported=False):
1822
"""See BzrDir.open_repository."""
1823
from bzrlib.repository import RepositoryFormat
1824
format = RepositoryFormat.find_format(self)
1825
self._check_supported(format, unsupported)
1826
return format.open(self, _found=True)
1828
def open_workingtree(self, unsupported=False,
1829
recommend_upgrade=True):
1830
"""See BzrDir.open_workingtree."""
1831
from bzrlib.workingtree import WorkingTreeFormat
1832
format = WorkingTreeFormat.find_format(self)
1833
self._check_supported(format, unsupported,
1835
basedir=self.root_transport.base)
1836
return format.open(self, _found=True)
1838
def _get_config(self):
1839
return config.TransportConfig(self.transport, 'control.conf')
1842
class BzrDirFormat(object):
1843
"""An encapsulation of the initialization and open routines for a format.
1845
Formats provide three things:
1846
* An initialization routine,
1850
Formats are placed in a dict by their format string for reference
1851
during bzrdir opening. These should be subclasses of BzrDirFormat
1854
Once a format is deprecated, just deprecate the initialize and open
1855
methods on the format class. Do not deprecate the object, as the
1856
object will be created every system load.
1858
:cvar colocated_branches: Whether this formats supports colocated branches.
1861
_default_format = None
1862
"""The default format used for new .bzr dirs."""
1865
"""The known formats."""
1867
_control_formats = []
1868
"""The registered control formats - .bzr, ....
1870
This is a list of BzrDirFormat objects.
1873
_control_server_formats = []
1874
"""The registered control server formats, e.g. RemoteBzrDirs.
1876
This is a list of BzrDirFormat objects.
1879
_lock_file_name = 'branch-lock'
1881
colocated_branches = False
1882
"""Whether co-located branches are supported for this control dir format.
1885
# _lock_class must be set in subclasses to the lock type, typ.
1886
# TransportLock or LockDir
1889
def find_format(klass, transport, _server_formats=True):
1890
"""Return the format present at transport."""
1892
formats = klass._control_server_formats + klass._control_formats
1894
formats = klass._control_formats
1895
for format in formats:
1897
return format.probe_transport(transport)
1898
except errors.NotBranchError:
1899
# this format does not find a control dir here.
1901
raise errors.NotBranchError(path=transport.base)
1904
def probe_transport(klass, transport):
1905
"""Return the .bzrdir style format present in a directory."""
1907
format_string = transport.get_bytes(".bzr/branch-format")
1908
except errors.NoSuchFile:
1909
raise errors.NotBranchError(path=transport.base)
1912
return klass._formats[format_string]
1914
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1917
def get_default_format(klass):
1918
"""Return the current default format."""
1919
return klass._default_format
1921
def get_format_string(self):
1922
"""Return the ASCII format string that identifies this format."""
1923
raise NotImplementedError(self.get_format_string)
1925
def get_format_description(self):
1926
"""Return the short description for this format."""
1927
raise NotImplementedError(self.get_format_description)
1929
def get_converter(self, format=None):
1930
"""Return the converter to use to convert bzrdirs needing converts.
1932
This returns a bzrlib.bzrdir.Converter object.
1934
This should return the best upgrader to step this format towards the
1935
current default format. In the case of plugins we can/should provide
1936
some means for them to extend the range of returnable converters.
1938
:param format: Optional format to override the default format of the
1941
raise NotImplementedError(self.get_converter)
1943
def initialize(self, url, possible_transports=None):
1944
"""Create a bzr control dir at this url and return an opened copy.
1946
While not deprecated, this method is very specific and its use will
1947
lead to many round trips to setup a working environment. See
1948
initialize_on_transport_ex for a [nearly] all-in-one method.
1950
Subclasses should typically override initialize_on_transport
1951
instead of this method.
1953
return self.initialize_on_transport(get_transport(url,
1954
possible_transports))
1956
def initialize_on_transport(self, transport):
1957
"""Initialize a new bzrdir in the base directory of a Transport."""
1959
# can we hand off the request to the smart server rather than using
1961
client_medium = transport.get_smart_medium()
1962
except errors.NoSmartMedium:
1963
return self._initialize_on_transport_vfs(transport)
1965
# Current RPC's only know how to create bzr metadir1 instances, so
1966
# we still delegate to vfs methods if the requested format is not a
1968
if type(self) != BzrDirMetaFormat1:
1969
return self._initialize_on_transport_vfs(transport)
1970
remote_format = RemoteBzrDirFormat()
1971
self._supply_sub_formats_to(remote_format)
1972
return remote_format.initialize_on_transport(transport)
1974
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1975
create_prefix=False, force_new_repo=False, stacked_on=None,
1976
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1977
shared_repo=False, vfs_only=False):
1978
"""Create this format on transport.
1980
The directory to initialize will be created.
1982
:param force_new_repo: Do not use a shared repository for the target,
1983
even if one is available.
1984
:param create_prefix: Create any missing directories leading up to
1986
:param use_existing_dir: Use an existing directory if one exists.
1987
:param stacked_on: A url to stack any created branch on, None to follow
1988
any target stacking policy.
1989
:param stack_on_pwd: If stack_on is relative, the location it is
1991
:param repo_format_name: If non-None, a repository will be
1992
made-or-found. Should none be found, or if force_new_repo is True
1993
the repo_format_name is used to select the format of repository to
1995
:param make_working_trees: Control the setting of make_working_trees
1996
for a new shared repository when one is made. None to use whatever
1997
default the format has.
1998
:param shared_repo: Control whether made repositories are shared or
2000
:param vfs_only: If True do not attempt to use a smart server
2001
:return: repo, bzrdir, require_stacking, repository_policy. repo is
2002
None if none was created or found, bzrdir is always valid.
2003
require_stacking is the result of examining the stacked_on
2004
parameter and any stacking policy found for the target.
2007
# Try to hand off to a smart server
2009
client_medium = transport.get_smart_medium()
2010
except errors.NoSmartMedium:
2013
# TODO: lookup the local format from a server hint.
2014
remote_dir_format = RemoteBzrDirFormat()
2015
remote_dir_format._network_name = self.network_name()
2016
self._supply_sub_formats_to(remote_dir_format)
2017
return remote_dir_format.initialize_on_transport_ex(transport,
2018
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2019
force_new_repo=force_new_repo, stacked_on=stacked_on,
2020
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2021
make_working_trees=make_working_trees, shared_repo=shared_repo)
2022
# XXX: Refactor the create_prefix/no_create_prefix code into a
2023
# common helper function
2024
# The destination may not exist - if so make it according to policy.
2025
def make_directory(transport):
2026
transport.mkdir('.')
2028
def redirected(transport, e, redirection_notice):
2029
note(redirection_notice)
2030
return transport._redirected_to(e.source, e.target)
2032
transport = do_catching_redirections(make_directory, transport,
2034
except errors.FileExists:
2035
if not use_existing_dir:
2037
except errors.NoSuchFile:
2038
if not create_prefix:
2040
transport.create_prefix()
2042
require_stacking = (stacked_on is not None)
2043
# Now the target directory exists, but doesn't have a .bzr
2044
# directory. So we need to create it, along with any work to create
2045
# all of the dependent branches, etc.
2047
result = self.initialize_on_transport(transport)
2048
if repo_format_name:
2050
# use a custom format
2051
result._format.repository_format = \
2052
repository.network_format_registry.get(repo_format_name)
2053
except AttributeError:
2054
# The format didn't permit it to be set.
2056
# A repository is desired, either in-place or shared.
2057
repository_policy = result.determine_repository_policy(
2058
force_new_repo, stacked_on, stack_on_pwd,
2059
require_stacking=require_stacking)
2060
result_repo, is_new_repo = repository_policy.acquire_repository(
2061
make_working_trees, shared_repo)
2062
if not require_stacking and repository_policy._require_stacking:
2063
require_stacking = True
2064
result._format.require_stacking()
2065
result_repo.lock_write()
2068
repository_policy = None
2069
return result_repo, result, require_stacking, repository_policy
2071
def _initialize_on_transport_vfs(self, transport):
2072
"""Initialize a new bzrdir using VFS calls.
2074
:param transport: The transport to create the .bzr directory in.
2077
# Since we are creating a .bzr directory, inherit the
2078
# mode from the root directory
2079
temp_control = lockable_files.LockableFiles(transport,
2080
'', lockable_files.TransportLock)
2081
temp_control._transport.mkdir('.bzr',
2082
# FIXME: RBC 20060121 don't peek under
2084
mode=temp_control._dir_mode)
2085
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
2086
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
2087
file_mode = temp_control._file_mode
2089
bzrdir_transport = transport.clone('.bzr')
2090
utf8_files = [('README',
2091
"This is a Bazaar control directory.\n"
2092
"Do not change any files in this directory.\n"
2093
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
2094
('branch-format', self.get_format_string()),
2096
# NB: no need to escape relative paths that are url safe.
2097
control_files = lockable_files.LockableFiles(bzrdir_transport,
2098
self._lock_file_name, self._lock_class)
2099
control_files.create_lock()
2100
control_files.lock_write()
2102
for (filename, content) in utf8_files:
2103
bzrdir_transport.put_bytes(filename, content,
2106
control_files.unlock()
2107
return self.open(transport, _found=True)
2109
def is_supported(self):
2110
"""Is this format supported?
2112
Supported formats must be initializable and openable.
2113
Unsupported formats may not support initialization or committing or
2114
some other features depending on the reason for not being supported.
2118
def network_name(self):
2119
"""A simple byte string uniquely identifying this format for RPC calls.
2121
Bzr control formats use thir disk format string to identify the format
2122
over the wire. Its possible that other control formats have more
2123
complex detection requirements, so we permit them to use any unique and
2124
immutable string they desire.
2126
raise NotImplementedError(self.network_name)
2128
def same_model(self, target_format):
2129
return (self.repository_format.rich_root_data ==
2130
target_format.rich_root_data)
2133
def known_formats(klass):
2134
"""Return all the known formats.
2136
Concrete formats should override _known_formats.
2138
# There is double indirection here to make sure that control
2139
# formats used by more than one dir format will only be probed
2140
# once. This can otherwise be quite expensive for remote connections.
2142
for format in klass._control_formats:
2143
result.update(format._known_formats())
2147
def _known_formats(klass):
2148
"""Return the known format instances for this control format."""
2149
return set(klass._formats.values())
2151
def open(self, transport, _found=False):
2152
"""Return an instance of this format for the dir transport points at.
2154
_found is a private parameter, do not use it.
2157
found_format = BzrDirFormat.find_format(transport)
2158
if not isinstance(found_format, self.__class__):
2159
raise AssertionError("%s was asked to open %s, but it seems to need "
2161
% (self, transport, found_format))
2162
# Allow subclasses - use the found format.
2163
self._supply_sub_formats_to(found_format)
2164
return found_format._open(transport)
2165
return self._open(transport)
2167
def _open(self, transport):
2168
"""Template method helper for opening BzrDirectories.
2170
This performs the actual open and any additional logic or parameter
2173
raise NotImplementedError(self._open)
2176
def register_format(klass, format):
2177
klass._formats[format.get_format_string()] = format
2178
# bzr native formats have a network name of their format string.
2179
network_format_registry.register(format.get_format_string(), format.__class__)
2182
def register_control_format(klass, format):
2183
"""Register a format that does not use '.bzr' for its control dir.
2185
TODO: This should be pulled up into a 'ControlDirFormat' base class
2186
which BzrDirFormat can inherit from, and renamed to register_format
2187
there. It has been done without that for now for simplicity of
2190
klass._control_formats.append(format)
2193
def register_control_server_format(klass, format):
2194
"""Register a control format for client-server environments.
2196
These formats will be tried before ones registered with
2197
register_control_format. This gives implementations that decide to the
2198
chance to grab it before anything looks at the contents of the format
2201
klass._control_server_formats.append(format)
2204
def _set_default_format(klass, format):
2205
"""Set default format (for testing behavior of defaults only)"""
2206
klass._default_format = format
2210
return self.get_format_description().rstrip()
2212
def _supply_sub_formats_to(self, other_format):
2213
"""Give other_format the same values for sub formats as this has.
2215
This method is expected to be used when parameterising a
2216
RemoteBzrDirFormat instance with the parameters from a
2217
BzrDirMetaFormat1 instance.
2219
:param other_format: other_format is a format which should be
2220
compatible with whatever sub formats are supported by self.
2225
def unregister_format(klass, format):
2226
del klass._formats[format.get_format_string()]
2229
def unregister_control_format(klass, format):
2230
klass._control_formats.remove(format)
2233
class BzrDirFormat4(BzrDirFormat):
2234
"""Bzr dir format 4.
2236
This format is a combined format for working tree, branch and repository.
2238
- Format 1 working trees [always]
2239
- Format 4 branches [always]
2240
- Format 4 repositories [always]
2242
This format is deprecated: it indexes texts using a text it which is
2243
removed in format 5; write support for this format has been removed.
2246
_lock_class = lockable_files.TransportLock
2248
def get_format_string(self):
2249
"""See BzrDirFormat.get_format_string()."""
2250
return "Bazaar-NG branch, format 0.0.4\n"
2252
def get_format_description(self):
2253
"""See BzrDirFormat.get_format_description()."""
2254
return "All-in-one format 4"
2256
def get_converter(self, format=None):
2257
"""See BzrDirFormat.get_converter()."""
2258
# there is one and only one upgrade path here.
2259
return ConvertBzrDir4To5()
2261
def initialize_on_transport(self, transport):
2262
"""Format 4 branches cannot be created."""
2263
raise errors.UninitializableFormat(self)
2265
def is_supported(self):
2266
"""Format 4 is not supported.
2268
It is not supported because the model changed from 4 to 5 and the
2269
conversion logic is expensive - so doing it on the fly was not
2274
def network_name(self):
2275
return self.get_format_string()
2277
def _open(self, transport):
2278
"""See BzrDirFormat._open."""
2279
return BzrDir4(transport, self)
2281
def __return_repository_format(self):
2282
"""Circular import protection."""
2283
from bzrlib.repofmt.weaverepo import RepositoryFormat4
2284
return RepositoryFormat4()
2285
repository_format = property(__return_repository_format)
2288
class BzrDirFormatAllInOne(BzrDirFormat):
2289
"""Common class for formats before meta-dirs."""
2291
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
2292
create_prefix=False, force_new_repo=False, stacked_on=None,
2293
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
2295
"""See BzrDirFormat.initialize_on_transport_ex."""
2296
require_stacking = (stacked_on is not None)
2297
# Format 5 cannot stack, but we've been asked to - actually init
2299
if require_stacking:
2300
format = BzrDirMetaFormat1()
2301
return format.initialize_on_transport_ex(transport,
2302
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2303
force_new_repo=force_new_repo, stacked_on=stacked_on,
2304
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2305
make_working_trees=make_working_trees, shared_repo=shared_repo)
2306
return BzrDirFormat.initialize_on_transport_ex(self, transport,
2307
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2308
force_new_repo=force_new_repo, stacked_on=stacked_on,
2309
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2310
make_working_trees=make_working_trees, shared_repo=shared_repo)
2313
class BzrDirFormat5(BzrDirFormatAllInOne):
2314
"""Bzr control format 5.
2316
This format is a combined format for working tree, branch and repository.
2318
- Format 2 working trees [always]
2319
- Format 4 branches [always]
2320
- Format 5 repositories [always]
2321
Unhashed stores in the repository.
2324
_lock_class = lockable_files.TransportLock
2326
def get_format_string(self):
2327
"""See BzrDirFormat.get_format_string()."""
2328
return "Bazaar-NG branch, format 5\n"
2330
def get_branch_format(self):
2331
from bzrlib import branch
2332
return branch.BzrBranchFormat4()
2334
def get_format_description(self):
2335
"""See BzrDirFormat.get_format_description()."""
2336
return "All-in-one format 5"
2338
def get_converter(self, format=None):
2339
"""See BzrDirFormat.get_converter()."""
2340
# there is one and only one upgrade path here.
2341
return ConvertBzrDir5To6()
2343
def _initialize_for_clone(self, url):
2344
return self.initialize_on_transport(get_transport(url), _cloning=True)
2346
def initialize_on_transport(self, transport, _cloning=False):
2347
"""Format 5 dirs always have working tree, branch and repository.
2349
Except when they are being cloned.
2351
from bzrlib.branch import BzrBranchFormat4
2352
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2353
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
2354
RepositoryFormat5().initialize(result, _internal=True)
2356
branch = BzrBranchFormat4().initialize(result)
2357
result._init_workingtree()
2360
def network_name(self):
2361
return self.get_format_string()
2363
def _open(self, transport):
2364
"""See BzrDirFormat._open."""
2365
return BzrDir5(transport, self)
2367
def __return_repository_format(self):
2368
"""Circular import protection."""
2369
from bzrlib.repofmt.weaverepo import RepositoryFormat5
2370
return RepositoryFormat5()
2371
repository_format = property(__return_repository_format)
2374
class BzrDirFormat6(BzrDirFormatAllInOne):
2375
"""Bzr control format 6.
2377
This format is a combined format for working tree, branch and repository.
2379
- Format 2 working trees [always]
2380
- Format 4 branches [always]
2381
- Format 6 repositories [always]
2384
_lock_class = lockable_files.TransportLock
2386
def get_format_string(self):
2387
"""See BzrDirFormat.get_format_string()."""
2388
return "Bazaar-NG branch, format 6\n"
2390
def get_format_description(self):
2391
"""See BzrDirFormat.get_format_description()."""
2392
return "All-in-one format 6"
2394
def get_branch_format(self):
2395
from bzrlib import branch
2396
return branch.BzrBranchFormat4()
2398
def get_converter(self, format=None):
2399
"""See BzrDirFormat.get_converter()."""
2400
# there is one and only one upgrade path here.
2401
return ConvertBzrDir6ToMeta()
2403
def _initialize_for_clone(self, url):
2404
return self.initialize_on_transport(get_transport(url), _cloning=True)
2406
def initialize_on_transport(self, transport, _cloning=False):
2407
"""Format 6 dirs always have working tree, branch and repository.
2409
Except when they are being cloned.
2411
from bzrlib.branch import BzrBranchFormat4
2412
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2413
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
2414
RepositoryFormat6().initialize(result, _internal=True)
2416
branch = BzrBranchFormat4().initialize(result)
2417
result._init_workingtree()
2420
def network_name(self):
2421
return self.get_format_string()
2423
def _open(self, transport):
2424
"""See BzrDirFormat._open."""
2425
return BzrDir6(transport, self)
2427
def __return_repository_format(self):
2428
"""Circular import protection."""
2429
from bzrlib.repofmt.weaverepo import RepositoryFormat6
2430
return RepositoryFormat6()
2431
repository_format = property(__return_repository_format)
2434
class BzrDirMetaFormat1(BzrDirFormat):
2435
"""Bzr meta control format 1
2437
This is the first format with split out working tree, branch and repository
2440
- Format 3 working trees [optional]
2441
- Format 5 branches [optional]
2442
- Format 7 repositories [optional]
2445
_lock_class = lockdir.LockDir
2448
self._workingtree_format = None
2449
self._branch_format = None
2450
self._repository_format = None
2452
def __eq__(self, other):
2453
if other.__class__ is not self.__class__:
2455
if other.repository_format != self.repository_format:
2457
if other.workingtree_format != self.workingtree_format:
2461
def __ne__(self, other):
2462
return not self == other
2464
def get_branch_format(self):
2465
if self._branch_format is None:
2466
from bzrlib.branch import BranchFormat
2467
self._branch_format = BranchFormat.get_default_format()
2468
return self._branch_format
2470
def set_branch_format(self, format):
2471
self._branch_format = format
2473
def require_stacking(self, stack_on=None, possible_transports=None,
2475
"""We have a request to stack, try to ensure the formats support it.
2477
:param stack_on: If supplied, it is the URL to a branch that we want to
2478
stack on. Check to see if that format supports stacking before
2481
# Stacking is desired. requested by the target, but does the place it
2482
# points at support stacking? If it doesn't then we should
2483
# not implicitly upgrade. We check this here.
2484
new_repo_format = None
2485
new_branch_format = None
2487
# a bit of state for get_target_branch so that we don't try to open it
2488
# 2 times, for both repo *and* branch
2489
target = [None, False, None] # target_branch, checked, upgrade anyway
2490
def get_target_branch():
2492
# We've checked, don't check again
2494
if stack_on is None:
2495
# No target format, that means we want to force upgrading
2496
target[:] = [None, True, True]
2499
target_dir = BzrDir.open(stack_on,
2500
possible_transports=possible_transports)
2501
except errors.NotBranchError:
2502
# Nothing there, don't change formats
2503
target[:] = [None, True, False]
2505
except errors.JailBreak:
2506
# JailBreak, JFDI and upgrade anyway
2507
target[:] = [None, True, True]
2510
target_branch = target_dir.open_branch()
2511
except errors.NotBranchError:
2512
# No branch, don't upgrade formats
2513
target[:] = [None, True, False]
2515
target[:] = [target_branch, True, False]
2518
if (not _skip_repo and
2519
not self.repository_format.supports_external_lookups):
2520
# We need to upgrade the Repository.
2521
target_branch, _, do_upgrade = get_target_branch()
2522
if target_branch is None:
2523
# We don't have a target branch, should we upgrade anyway?
2525
# stack_on is inaccessible, JFDI.
2526
# TODO: bad monkey, hard-coded formats...
2527
if self.repository_format.rich_root_data:
2528
new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2530
new_repo_format = pack_repo.RepositoryFormatKnitPack5()
2532
# If the target already supports stacking, then we know the
2533
# project is already able to use stacking, so auto-upgrade
2535
new_repo_format = target_branch.repository._format
2536
if not new_repo_format.supports_external_lookups:
2537
# target doesn't, source doesn't, so don't auto upgrade
2539
new_repo_format = None
2540
if new_repo_format is not None:
2541
self.repository_format = new_repo_format
2542
note('Source repository format does not support stacking,'
2543
' using format:\n %s',
2544
new_repo_format.get_format_description())
2546
if not self.get_branch_format().supports_stacking():
2547
# We just checked the repo, now lets check if we need to
2548
# upgrade the branch format
2549
target_branch, _, do_upgrade = get_target_branch()
2550
if target_branch is None:
2552
# TODO: bad monkey, hard-coded formats...
2553
new_branch_format = branch.BzrBranchFormat7()
2555
new_branch_format = target_branch._format
2556
if not new_branch_format.supports_stacking():
2557
new_branch_format = None
2558
if new_branch_format is not None:
2559
# Does support stacking, use its format.
2560
self.set_branch_format(new_branch_format)
2561
note('Source branch format does not support stacking,'
2562
' using format:\n %s',
2563
new_branch_format.get_format_description())
2565
def get_converter(self, format=None):
2566
"""See BzrDirFormat.get_converter()."""
2568
format = BzrDirFormat.get_default_format()
2569
if not isinstance(self, format.__class__):
2570
# converting away from metadir is not implemented
2571
raise NotImplementedError(self.get_converter)
2572
return ConvertMetaToMeta(format)
2574
def get_format_string(self):
2575
"""See BzrDirFormat.get_format_string()."""
2576
return "Bazaar-NG meta directory, format 1\n"
2578
def get_format_description(self):
2579
"""See BzrDirFormat.get_format_description()."""
2580
return "Meta directory format 1"
2582
def network_name(self):
2583
return self.get_format_string()
2585
def _open(self, transport):
2586
"""See BzrDirFormat._open."""
2587
# Create a new format instance because otherwise initialisation of new
2588
# metadirs share the global default format object leading to alias
2590
format = BzrDirMetaFormat1()
2591
self._supply_sub_formats_to(format)
2592
return BzrDirMeta1(transport, format)
2594
def __return_repository_format(self):
2595
"""Circular import protection."""
2596
if self._repository_format:
2597
return self._repository_format
2598
from bzrlib.repository import RepositoryFormat
2599
return RepositoryFormat.get_default_format()
2601
def _set_repository_format(self, value):
2602
"""Allow changing the repository format for metadir formats."""
2603
self._repository_format = value
2605
repository_format = property(__return_repository_format,
2606
_set_repository_format)
2608
def _supply_sub_formats_to(self, other_format):
2609
"""Give other_format the same values for sub formats as this has.
2611
This method is expected to be used when parameterising a
2612
RemoteBzrDirFormat instance with the parameters from a
2613
BzrDirMetaFormat1 instance.
2615
:param other_format: other_format is a format which should be
2616
compatible with whatever sub formats are supported by self.
2619
if getattr(self, '_repository_format', None) is not None:
2620
other_format.repository_format = self.repository_format
2621
if self._branch_format is not None:
2622
other_format._branch_format = self._branch_format
2623
if self._workingtree_format is not None:
2624
other_format.workingtree_format = self.workingtree_format
2626
def __get_workingtree_format(self):
2627
if self._workingtree_format is None:
2628
from bzrlib.workingtree import WorkingTreeFormat
2629
self._workingtree_format = WorkingTreeFormat.get_default_format()
2630
return self._workingtree_format
2632
def __set_workingtree_format(self, wt_format):
2633
self._workingtree_format = wt_format
2635
workingtree_format = property(__get_workingtree_format,
2636
__set_workingtree_format)
2639
network_format_registry = registry.FormatRegistry()
2640
"""Registry of formats indexed by their network name.
2642
The network name for a BzrDirFormat is an identifier that can be used when
2643
referring to formats with smart server operations. See
2644
BzrDirFormat.network_name() for more detail.
2648
# Register bzr control format
2649
BzrDirFormat.register_control_format(BzrDirFormat)
2651
# Register bzr formats
2652
BzrDirFormat.register_format(BzrDirFormat4())
2653
BzrDirFormat.register_format(BzrDirFormat5())
2654
BzrDirFormat.register_format(BzrDirFormat6())
2655
__default_format = BzrDirMetaFormat1()
2656
BzrDirFormat.register_format(__default_format)
2657
BzrDirFormat._default_format = __default_format
2660
class Converter(object):
2661
"""Converts a disk format object from one format to another."""
2663
def convert(self, to_convert, pb):
2664
"""Perform the conversion of to_convert, giving feedback via pb.
2666
:param to_convert: The disk object to convert.
2667
:param pb: a progress bar to use for progress information.
2670
def step(self, message):
2671
"""Update the pb by a step."""
2673
self.pb.update(message, self.count, self.total)
2676
class ConvertBzrDir4To5(Converter):
2677
"""Converts format 4 bzr dirs to format 5."""
2680
super(ConvertBzrDir4To5, self).__init__()
2681
self.converted_revs = set()
2682
self.absent_revisions = set()
2686
def convert(self, to_convert, pb):
2687
"""See Converter.convert()."""
2688
self.bzrdir = to_convert
2690
warnings.warn("pb parameter to convert() is deprecated")
2691
self.pb = ui.ui_factory.nested_progress_bar()
2693
ui.ui_factory.note('starting upgrade from format 4 to 5')
2694
if isinstance(self.bzrdir.transport, local.LocalTransport):
2695
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2696
self._convert_to_weaves()
2697
return BzrDir.open(self.bzrdir.root_transport.base)
2701
def _convert_to_weaves(self):
2702
ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
2705
stat = self.bzrdir.transport.stat('weaves')
2706
if not S_ISDIR(stat.st_mode):
2707
self.bzrdir.transport.delete('weaves')
2708
self.bzrdir.transport.mkdir('weaves')
2709
except errors.NoSuchFile:
2710
self.bzrdir.transport.mkdir('weaves')
2711
# deliberately not a WeaveFile as we want to build it up slowly.
2712
self.inv_weave = Weave('inventory')
2713
# holds in-memory weaves for all files
2714
self.text_weaves = {}
2715
self.bzrdir.transport.delete('branch-format')
2716
self.branch = self.bzrdir.open_branch()
2717
self._convert_working_inv()
2718
rev_history = self.branch.revision_history()
2719
# to_read is a stack holding the revisions we still need to process;
2720
# appending to it adds new highest-priority revisions
2721
self.known_revisions = set(rev_history)
2722
self.to_read = rev_history[-1:]
2724
rev_id = self.to_read.pop()
2725
if (rev_id not in self.revisions
2726
and rev_id not in self.absent_revisions):
2727
self._load_one_rev(rev_id)
2729
to_import = self._make_order()
2730
for i, rev_id in enumerate(to_import):
2731
self.pb.update('converting revision', i, len(to_import))
2732
self._convert_one_rev(rev_id)
2734
self._write_all_weaves()
2735
self._write_all_revs()
2736
ui.ui_factory.note('upgraded to weaves:')
2737
ui.ui_factory.note(' %6d revisions and inventories' % len(self.revisions))
2738
ui.ui_factory.note(' %6d revisions not present' % len(self.absent_revisions))
2739
ui.ui_factory.note(' %6d texts' % self.text_count)
2740
self._cleanup_spare_files_after_format4()
2741
self.branch._transport.put_bytes(
2743
BzrDirFormat5().get_format_string(),
2744
mode=self.bzrdir._get_file_mode())
2746
def _cleanup_spare_files_after_format4(self):
2747
# FIXME working tree upgrade foo.
2748
for n in 'merged-patches', 'pending-merged-patches':
2750
## assert os.path.getsize(p) == 0
2751
self.bzrdir.transport.delete(n)
2752
except errors.NoSuchFile:
2754
self.bzrdir.transport.delete_tree('inventory-store')
2755
self.bzrdir.transport.delete_tree('text-store')
2757
def _convert_working_inv(self):
2758
inv = xml4.serializer_v4.read_inventory(
2759
self.branch._transport.get('inventory'))
2760
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2761
self.branch._transport.put_bytes('inventory', new_inv_xml,
2762
mode=self.bzrdir._get_file_mode())
2764
def _write_all_weaves(self):
2765
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2766
weave_transport = self.bzrdir.transport.clone('weaves')
2767
weaves = WeaveStore(weave_transport, prefixed=False)
2768
transaction = WriteTransaction()
2772
for file_id, file_weave in self.text_weaves.items():
2773
self.pb.update('writing weave', i, len(self.text_weaves))
2774
weaves._put_weave(file_id, file_weave, transaction)
2776
self.pb.update('inventory', 0, 1)
2777
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2778
self.pb.update('inventory', 1, 1)
2782
def _write_all_revs(self):
2783
"""Write all revisions out in new form."""
2784
self.bzrdir.transport.delete_tree('revision-store')
2785
self.bzrdir.transport.mkdir('revision-store')
2786
revision_transport = self.bzrdir.transport.clone('revision-store')
2788
from bzrlib.xml5 import serializer_v5
2789
from bzrlib.repofmt.weaverepo import RevisionTextStore
2790
revision_store = RevisionTextStore(revision_transport,
2791
serializer_v5, False, versionedfile.PrefixMapper(),
2792
lambda:True, lambda:True)
2794
for i, rev_id in enumerate(self.converted_revs):
2795
self.pb.update('write revision', i, len(self.converted_revs))
2796
text = serializer_v5.write_revision_to_string(
2797
self.revisions[rev_id])
2799
revision_store.add_lines(key, None, osutils.split_lines(text))
2803
def _load_one_rev(self, rev_id):
2804
"""Load a revision object into memory.
2806
Any parents not either loaded or abandoned get queued to be
2808
self.pb.update('loading revision',
2809
len(self.revisions),
2810
len(self.known_revisions))
2811
if not self.branch.repository.has_revision(rev_id):
2813
ui.ui_factory.note('revision {%s} not present in branch; '
2814
'will be converted as a ghost' %
2816
self.absent_revisions.add(rev_id)
2818
rev = self.branch.repository.get_revision(rev_id)
2819
for parent_id in rev.parent_ids:
2820
self.known_revisions.add(parent_id)
2821
self.to_read.append(parent_id)
2822
self.revisions[rev_id] = rev
2824
def _load_old_inventory(self, rev_id):
2825
old_inv_xml = self.branch.repository.inventory_store.get(rev_id).read()
2826
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2827
inv.revision_id = rev_id
2828
rev = self.revisions[rev_id]
2831
def _load_updated_inventory(self, rev_id):
2832
inv_xml = self.inv_weave.get_text(rev_id)
2833
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2836
def _convert_one_rev(self, rev_id):
2837
"""Convert revision and all referenced objects to new format."""
2838
rev = self.revisions[rev_id]
2839
inv = self._load_old_inventory(rev_id)
2840
present_parents = [p for p in rev.parent_ids
2841
if p not in self.absent_revisions]
2842
self._convert_revision_contents(rev, inv, present_parents)
2843
self._store_new_inv(rev, inv, present_parents)
2844
self.converted_revs.add(rev_id)
2846
def _store_new_inv(self, rev, inv, present_parents):
2847
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2848
new_inv_sha1 = sha_string(new_inv_xml)
2849
self.inv_weave.add_lines(rev.revision_id,
2851
new_inv_xml.splitlines(True))
2852
rev.inventory_sha1 = new_inv_sha1
2854
def _convert_revision_contents(self, rev, inv, present_parents):
2855
"""Convert all the files within a revision.
2857
Also upgrade the inventory to refer to the text revision ids."""
2858
rev_id = rev.revision_id
2859
mutter('converting texts of revision {%s}',
2861
parent_invs = map(self._load_updated_inventory, present_parents)
2862
entries = inv.iter_entries()
2864
for path, ie in entries:
2865
self._convert_file_version(rev, ie, parent_invs)
2867
def _convert_file_version(self, rev, ie, parent_invs):
2868
"""Convert one version of one file.
2870
The file needs to be added into the weave if it is a merge
2871
of >=2 parents or if it's changed from its parent.
2873
file_id = ie.file_id
2874
rev_id = rev.revision_id
2875
w = self.text_weaves.get(file_id)
2878
self.text_weaves[file_id] = w
2879
text_changed = False
2880
parent_candiate_entries = ie.parent_candidates(parent_invs)
2881
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2882
# XXX: Note that this is unordered - and this is tolerable because
2883
# the previous code was also unordered.
2884
previous_entries = dict((head, parent_candiate_entries[head]) for head
2886
self.snapshot_ie(previous_entries, ie, w, rev_id)
2889
def get_parent_map(self, revision_ids):
2890
"""See graph.StackedParentsProvider.get_parent_map"""
2891
return dict((revision_id, self.revisions[revision_id])
2892
for revision_id in revision_ids
2893
if revision_id in self.revisions)
2895
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2896
# TODO: convert this logic, which is ~= snapshot to
2897
# a call to:. This needs the path figured out. rather than a work_tree
2898
# a v4 revision_tree can be given, or something that looks enough like
2899
# one to give the file content to the entry if it needs it.
2900
# and we need something that looks like a weave store for snapshot to
2902
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2903
if len(previous_revisions) == 1:
2904
previous_ie = previous_revisions.values()[0]
2905
if ie._unchanged(previous_ie):
2906
ie.revision = previous_ie.revision
2909
text = self.branch.repository._text_store.get(ie.text_id)
2910
file_lines = text.readlines()
2911
w.add_lines(rev_id, previous_revisions, file_lines)
2912
self.text_count += 1
2914
w.add_lines(rev_id, previous_revisions, [])
2915
ie.revision = rev_id
2917
def _make_order(self):
2918
"""Return a suitable order for importing revisions.
2920
The order must be such that an revision is imported after all
2921
its (present) parents.
2923
todo = set(self.revisions.keys())
2924
done = self.absent_revisions.copy()
2927
# scan through looking for a revision whose parents
2929
for rev_id in sorted(list(todo)):
2930
rev = self.revisions[rev_id]
2931
parent_ids = set(rev.parent_ids)
2932
if parent_ids.issubset(done):
2933
# can take this one now
2934
order.append(rev_id)
2940
class ConvertBzrDir5To6(Converter):
2941
"""Converts format 5 bzr dirs to format 6."""
2943
def convert(self, to_convert, pb):
2944
"""See Converter.convert()."""
2945
self.bzrdir = to_convert
2946
pb = ui.ui_factory.nested_progress_bar()
2948
ui.ui_factory.note('starting upgrade from format 5 to 6')
2949
self._convert_to_prefixed()
2950
return BzrDir.open(self.bzrdir.root_transport.base)
2954
def _convert_to_prefixed(self):
2955
from bzrlib.store import TransportStore
2956
self.bzrdir.transport.delete('branch-format')
2957
for store_name in ["weaves", "revision-store"]:
2958
ui.ui_factory.note("adding prefixes to %s" % store_name)
2959
store_transport = self.bzrdir.transport.clone(store_name)
2960
store = TransportStore(store_transport, prefixed=True)
2961
for urlfilename in store_transport.list_dir('.'):
2962
filename = urlutils.unescape(urlfilename)
2963
if (filename.endswith(".weave") or
2964
filename.endswith(".gz") or
2965
filename.endswith(".sig")):
2966
file_id, suffix = os.path.splitext(filename)
2970
new_name = store._mapper.map((file_id,)) + suffix
2971
# FIXME keep track of the dirs made RBC 20060121
2973
store_transport.move(filename, new_name)
2974
except errors.NoSuchFile: # catches missing dirs strangely enough
2975
store_transport.mkdir(osutils.dirname(new_name))
2976
store_transport.move(filename, new_name)
2977
self.bzrdir.transport.put_bytes(
2979
BzrDirFormat6().get_format_string(),
2980
mode=self.bzrdir._get_file_mode())
2983
class ConvertBzrDir6ToMeta(Converter):
2984
"""Converts format 6 bzr dirs to metadirs."""
2986
def convert(self, to_convert, pb):
2987
"""See Converter.convert()."""
2988
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2989
from bzrlib.branch import BzrBranchFormat5
2990
self.bzrdir = to_convert
2991
self.pb = ui.ui_factory.nested_progress_bar()
2993
self.total = 20 # the steps we know about
2994
self.garbage_inventories = []
2995
self.dir_mode = self.bzrdir._get_dir_mode()
2996
self.file_mode = self.bzrdir._get_file_mode()
2998
ui.ui_factory.note('starting upgrade from format 6 to metadir')
2999
self.bzrdir.transport.put_bytes(
3001
"Converting to format 6",
3002
mode=self.file_mode)
3003
# its faster to move specific files around than to open and use the apis...
3004
# first off, nuke ancestry.weave, it was never used.
3006
self.step('Removing ancestry.weave')
3007
self.bzrdir.transport.delete('ancestry.weave')
3008
except errors.NoSuchFile:
3010
# find out whats there
3011
self.step('Finding branch files')
3012
last_revision = self.bzrdir.open_branch().last_revision()
3013
bzrcontents = self.bzrdir.transport.list_dir('.')
3014
for name in bzrcontents:
3015
if name.startswith('basis-inventory.'):
3016
self.garbage_inventories.append(name)
3017
# create new directories for repository, working tree and branch
3018
repository_names = [('inventory.weave', True),
3019
('revision-store', True),
3021
self.step('Upgrading repository ')
3022
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
3023
self.make_lock('repository')
3024
# we hard code the formats here because we are converting into
3025
# the meta format. The meta format upgrader can take this to a
3026
# future format within each component.
3027
self.put_format('repository', RepositoryFormat7())
3028
for entry in repository_names:
3029
self.move_entry('repository', entry)
3031
self.step('Upgrading branch ')
3032
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
3033
self.make_lock('branch')
3034
self.put_format('branch', BzrBranchFormat5())
3035
branch_files = [('revision-history', True),
3036
('branch-name', True),
3038
for entry in branch_files:
3039
self.move_entry('branch', entry)
3041
checkout_files = [('pending-merges', True),
3042
('inventory', True),
3043
('stat-cache', False)]
3044
# If a mandatory checkout file is not present, the branch does not have
3045
# a functional checkout. Do not create a checkout in the converted
3047
for name, mandatory in checkout_files:
3048
if mandatory and name not in bzrcontents:
3049
has_checkout = False
3053
if not has_checkout:
3054
ui.ui_factory.note('No working tree.')
3055
# If some checkout files are there, we may as well get rid of them.
3056
for name, mandatory in checkout_files:
3057
if name in bzrcontents:
3058
self.bzrdir.transport.delete(name)
3060
from bzrlib.workingtree import WorkingTreeFormat3
3061
self.step('Upgrading working tree')
3062
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
3063
self.make_lock('checkout')
3065
'checkout', WorkingTreeFormat3())
3066
self.bzrdir.transport.delete_multi(
3067
self.garbage_inventories, self.pb)
3068
for entry in checkout_files:
3069
self.move_entry('checkout', entry)
3070
if last_revision is not None:
3071
self.bzrdir.transport.put_bytes(
3072
'checkout/last-revision', last_revision)
3073
self.bzrdir.transport.put_bytes(
3075
BzrDirMetaFormat1().get_format_string(),
3076
mode=self.file_mode)
3078
return BzrDir.open(self.bzrdir.root_transport.base)
3080
def make_lock(self, name):
3081
"""Make a lock for the new control dir name."""
3082
self.step('Make %s lock' % name)
3083
ld = lockdir.LockDir(self.bzrdir.transport,
3085
file_modebits=self.file_mode,
3086
dir_modebits=self.dir_mode)
3089
def move_entry(self, new_dir, entry):
3090
"""Move then entry name into new_dir."""
3092
mandatory = entry[1]
3093
self.step('Moving %s' % name)
3095
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
3096
except errors.NoSuchFile:
3100
def put_format(self, dirname, format):
3101
self.bzrdir.transport.put_bytes('%s/format' % dirname,
3102
format.get_format_string(),
3106
class ConvertMetaToMeta(Converter):
3107
"""Converts the components of metadirs."""
3109
def __init__(self, target_format):
3110
"""Create a metadir to metadir converter.
3112
:param target_format: The final metadir format that is desired.
3114
self.target_format = target_format
3116
def convert(self, to_convert, pb):
3117
"""See Converter.convert()."""
3118
self.bzrdir = to_convert
3119
self.pb = ui.ui_factory.nested_progress_bar()
3122
self.step('checking repository format')
3124
repo = self.bzrdir.open_repository()
3125
except errors.NoRepositoryPresent:
3128
if not isinstance(repo._format, self.target_format.repository_format.__class__):
3129
from bzrlib.repository import CopyConverter
3130
ui.ui_factory.note('starting repository conversion')
3131
converter = CopyConverter(self.target_format.repository_format)
3132
converter.convert(repo, pb)
3133
for branch in self.bzrdir.list_branches():
3134
# TODO: conversions of Branch and Tree should be done by
3135
# InterXFormat lookups/some sort of registry.
3136
# Avoid circular imports
3137
from bzrlib import branch as _mod_branch
3138
old = branch._format.__class__
3139
new = self.target_format.get_branch_format().__class__
3141
if (old == _mod_branch.BzrBranchFormat5 and
3142
new in (_mod_branch.BzrBranchFormat6,
3143
_mod_branch.BzrBranchFormat7,
3144
_mod_branch.BzrBranchFormat8)):
3145
branch_converter = _mod_branch.Converter5to6()
3146
elif (old == _mod_branch.BzrBranchFormat6 and
3147
new in (_mod_branch.BzrBranchFormat7,
3148
_mod_branch.BzrBranchFormat8)):
3149
branch_converter = _mod_branch.Converter6to7()
3150
elif (old == _mod_branch.BzrBranchFormat7 and
3151
new is _mod_branch.BzrBranchFormat8):
3152
branch_converter = _mod_branch.Converter7to8()
3154
raise errors.BadConversionTarget("No converter", new,
3156
branch_converter.convert(branch)
3157
branch = self.bzrdir.open_branch()
3158
old = branch._format.__class__
3160
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
3161
except (errors.NoWorkingTree, errors.NotLocalUrl):
3164
# TODO: conversions of Branch and Tree should be done by
3165
# InterXFormat lookups
3166
if (isinstance(tree, workingtree.WorkingTree3) and
3167
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
3168
isinstance(self.target_format.workingtree_format,
3169
workingtree_4.DirStateWorkingTreeFormat)):
3170
workingtree_4.Converter3to4().convert(tree)
3171
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
3172
not isinstance(tree, workingtree_4.WorkingTree5) and
3173
isinstance(self.target_format.workingtree_format,
3174
workingtree_4.WorkingTreeFormat5)):
3175
workingtree_4.Converter4to5().convert(tree)
3176
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
3177
not isinstance(tree, workingtree_4.WorkingTree6) and
3178
isinstance(self.target_format.workingtree_format,
3179
workingtree_4.WorkingTreeFormat6)):
3180
workingtree_4.Converter4or5to6().convert(tree)
3185
# This is not in remote.py because it's relatively small, and needs to be
3186
# registered. Putting it in remote.py creates a circular import problem.
3187
# we can make it a lazy object if the control formats is turned into something
3189
class RemoteBzrDirFormat(BzrDirMetaFormat1):
3190
"""Format representing bzrdirs accessed via a smart server"""
3193
BzrDirMetaFormat1.__init__(self)
3194
# XXX: It's a bit ugly that the network name is here, because we'd
3195
# like to believe that format objects are stateless or at least
3196
# immutable, However, we do at least avoid mutating the name after
3197
# it's returned. See <https://bugs.edge.launchpad.net/bzr/+bug/504102>
3198
self._network_name = None
3201
return "%s(_network_name=%r)" % (self.__class__.__name__,
3204
def get_format_description(self):
3205
if self._network_name:
3206
real_format = network_format_registry.get(self._network_name)
3207
return 'Remote: ' + real_format.get_format_description()
3208
return 'bzr remote bzrdir'
3210
def get_format_string(self):
3211
raise NotImplementedError(self.get_format_string)
3213
def network_name(self):
3214
if self._network_name:
3215
return self._network_name
3217
raise AssertionError("No network name set.")
3220
def probe_transport(klass, transport):
3221
"""Return a RemoteBzrDirFormat object if it looks possible."""
3223
medium = transport.get_smart_medium()
3224
except (NotImplementedError, AttributeError,
3225
errors.TransportNotPossible, errors.NoSmartMedium,
3226
errors.SmartProtocolError):
3227
# no smart server, so not a branch for this format type.
3228
raise errors.NotBranchError(path=transport.base)
3230
# Decline to open it if the server doesn't support our required
3231
# version (3) so that the VFS-based transport will do it.
3232
if medium.should_probe():
3234
server_version = medium.protocol_version()
3235
except errors.SmartProtocolError:
3236
# Apparently there's no usable smart server there, even though
3237
# the medium supports the smart protocol.
3238
raise errors.NotBranchError(path=transport.base)
3239
if server_version != '2':
3240
raise errors.NotBranchError(path=transport.base)
3243
def initialize_on_transport(self, transport):
3245
# hand off the request to the smart server
3246
client_medium = transport.get_smart_medium()
3247
except errors.NoSmartMedium:
3248
# TODO: lookup the local format from a server hint.
3249
local_dir_format = BzrDirMetaFormat1()
3250
return local_dir_format.initialize_on_transport(transport)
3251
client = _SmartClient(client_medium)
3252
path = client.remote_path_from_transport(transport)
3254
response = client.call('BzrDirFormat.initialize', path)
3255
except errors.ErrorFromSmartServer, err:
3256
remote._translate_error(err, path=path)
3257
if response[0] != 'ok':
3258
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
3259
format = RemoteBzrDirFormat()
3260
self._supply_sub_formats_to(format)
3261
return remote.RemoteBzrDir(transport, format)
3263
def parse_NoneTrueFalse(self, arg):
3270
raise AssertionError("invalid arg %r" % arg)
3272
def _serialize_NoneTrueFalse(self, arg):
3279
def _serialize_NoneString(self, arg):
3282
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
3283
create_prefix=False, force_new_repo=False, stacked_on=None,
3284
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
3287
# hand off the request to the smart server
3288
client_medium = transport.get_smart_medium()
3289
except errors.NoSmartMedium:
3292
# Decline to open it if the server doesn't support our required
3293
# version (3) so that the VFS-based transport will do it.
3294
if client_medium.should_probe():
3296
server_version = client_medium.protocol_version()
3297
if server_version != '2':
3301
except errors.SmartProtocolError:
3302
# Apparently there's no usable smart server there, even though
3303
# the medium supports the smart protocol.
3308
client = _SmartClient(client_medium)
3309
path = client.remote_path_from_transport(transport)
3310
if client_medium._is_remote_before((1, 16)):
3313
# TODO: lookup the local format from a server hint.
3314
local_dir_format = BzrDirMetaFormat1()
3315
self._supply_sub_formats_to(local_dir_format)
3316
return local_dir_format.initialize_on_transport_ex(transport,
3317
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3318
force_new_repo=force_new_repo, stacked_on=stacked_on,
3319
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3320
make_working_trees=make_working_trees, shared_repo=shared_repo,
3322
return self._initialize_on_transport_ex_rpc(client, path, transport,
3323
use_existing_dir, create_prefix, force_new_repo, stacked_on,
3324
stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
3326
def _initialize_on_transport_ex_rpc(self, client, path, transport,
3327
use_existing_dir, create_prefix, force_new_repo, stacked_on,
3328
stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
3330
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
3331
args.append(self._serialize_NoneTrueFalse(create_prefix))
3332
args.append(self._serialize_NoneTrueFalse(force_new_repo))
3333
args.append(self._serialize_NoneString(stacked_on))
3334
# stack_on_pwd is often/usually our transport
3337
stack_on_pwd = transport.relpath(stack_on_pwd)
3338
if not stack_on_pwd:
3340
except errors.PathNotChild:
3342
args.append(self._serialize_NoneString(stack_on_pwd))
3343
args.append(self._serialize_NoneString(repo_format_name))
3344
args.append(self._serialize_NoneTrueFalse(make_working_trees))
3345
args.append(self._serialize_NoneTrueFalse(shared_repo))
3346
request_network_name = self._network_name or \
3347
BzrDirFormat.get_default_format().network_name()
3349
response = client.call('BzrDirFormat.initialize_ex_1.16',
3350
request_network_name, path, *args)
3351
except errors.UnknownSmartMethod:
3352
client._medium._remember_remote_is_before((1,16))
3353
local_dir_format = BzrDirMetaFormat1()
3354
self._supply_sub_formats_to(local_dir_format)
3355
return local_dir_format.initialize_on_transport_ex(transport,
3356
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
3357
force_new_repo=force_new_repo, stacked_on=stacked_on,
3358
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
3359
make_working_trees=make_working_trees, shared_repo=shared_repo,
3361
except errors.ErrorFromSmartServer, err:
3362
remote._translate_error(err, path=path)
3363
repo_path = response[0]
3364
bzrdir_name = response[6]
3365
require_stacking = response[7]
3366
require_stacking = self.parse_NoneTrueFalse(require_stacking)
3367
format = RemoteBzrDirFormat()
3368
format._network_name = bzrdir_name
3369
self._supply_sub_formats_to(format)
3370
bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
3372
repo_format = remote.response_tuple_to_repo_format(response[1:])
3373
if repo_path == '.':
3376
repo_bzrdir_format = RemoteBzrDirFormat()
3377
repo_bzrdir_format._network_name = response[5]
3378
repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
3382
final_stack = response[8] or None
3383
final_stack_pwd = response[9] or None
3385
final_stack_pwd = urlutils.join(
3386
transport.base, final_stack_pwd)
3387
remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
3388
if len(response) > 10:
3389
# Updated server verb that locks remotely.
3390
repo_lock_token = response[10] or None
3391
remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
3393
remote_repo.dont_leave_lock_in_place()
3395
remote_repo.lock_write()
3396
policy = UseExistingRepository(remote_repo, final_stack,
3397
final_stack_pwd, require_stacking)
3398
policy.acquire_repository()
3402
bzrdir._format.set_branch_format(self.get_branch_format())
3403
if require_stacking:
3404
# The repo has already been created, but we need to make sure that
3405
# we'll make a stackable branch.
3406
bzrdir._format.require_stacking(_skip_repo=True)
3407
return remote_repo, bzrdir, require_stacking, policy
3409
def _open(self, transport):
3410
return remote.RemoteBzrDir(transport, self)
3412
def __eq__(self, other):
3413
if not isinstance(other, RemoteBzrDirFormat):
3415
return self.get_format_description() == other.get_format_description()
3417
def __return_repository_format(self):
3418
# Always return a RemoteRepositoryFormat object, but if a specific bzr
3419
# repository format has been asked for, tell the RemoteRepositoryFormat
3420
# that it should use that for init() etc.
3421
result = remote.RemoteRepositoryFormat()
3422
custom_format = getattr(self, '_repository_format', None)
3424
if isinstance(custom_format, remote.RemoteRepositoryFormat):
3425
return custom_format
3427
# We will use the custom format to create repositories over the
3428
# wire; expose its details like rich_root_data for code to
3430
result._custom_format = custom_format
3433
def get_branch_format(self):
3434
result = BzrDirMetaFormat1.get_branch_format(self)
3435
if not isinstance(result, remote.RemoteBranchFormat):
3436
new_result = remote.RemoteBranchFormat()
3437
new_result._custom_format = result
3439
self.set_branch_format(new_result)
3443
repository_format = property(__return_repository_format,
3444
BzrDirMetaFormat1._set_repository_format) #.im_func)
3447
BzrDirFormat.register_control_server_format(RemoteBzrDirFormat)
3450
class BzrDirFormatInfo(object):
3452
def __init__(self, native, deprecated, hidden, experimental):
3453
self.deprecated = deprecated
3454
self.native = native
3455
self.hidden = hidden
3456
self.experimental = experimental
3459
class BzrDirFormatRegistry(registry.Registry):
3460
"""Registry of user-selectable BzrDir subformats.
3462
Differs from BzrDirFormat._control_formats in that it provides sub-formats,
3463
e.g. BzrDirMeta1 with weave repository. Also, it's more user-oriented.
3467
"""Create a BzrDirFormatRegistry."""
3468
self._aliases = set()
3469
self._registration_order = list()
3470
super(BzrDirFormatRegistry, self).__init__()
3473
"""Return a set of the format names which are aliases."""
3474
return frozenset(self._aliases)
3476
def register_metadir(self, key,
3477
repository_format, help, native=True, deprecated=False,
3483
"""Register a metadir subformat.
3485
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3486
by the Repository/Branch/WorkingTreeformats.
3488
:param repository_format: The fully-qualified repository format class
3490
:param branch_format: Fully-qualified branch format class name as
3492
:param tree_format: Fully-qualified tree format class name as
3495
# This should be expanded to support setting WorkingTree and Branch
3496
# formats, once BzrDirMetaFormat1 supports that.
3497
def _load(full_name):
3498
mod_name, factory_name = full_name.rsplit('.', 1)
3500
mod = __import__(mod_name, globals(), locals(),
3502
except ImportError, e:
3503
raise ImportError('failed to load %s: %s' % (full_name, e))
3505
factory = getattr(mod, factory_name)
3506
except AttributeError:
3507
raise AttributeError('no factory %s in module %r'
3512
bd = BzrDirMetaFormat1()
3513
if branch_format is not None:
3514
bd.set_branch_format(_load(branch_format))
3515
if tree_format is not None:
3516
bd.workingtree_format = _load(tree_format)
3517
if repository_format is not None:
3518
bd.repository_format = _load(repository_format)
3520
self.register(key, helper, help, native, deprecated, hidden,
3521
experimental, alias)
3523
def register(self, key, factory, help, native=True, deprecated=False,
3524
hidden=False, experimental=False, alias=False):
3525
"""Register a BzrDirFormat factory.
3527
The factory must be a callable that takes one parameter: the key.
3528
It must produce an instance of the BzrDirFormat when called.
3530
This function mainly exists to prevent the info object from being
3533
registry.Registry.register(self, key, factory, help,
3534
BzrDirFormatInfo(native, deprecated, hidden, experimental))
3536
self._aliases.add(key)
3537
self._registration_order.append(key)
3539
def register_lazy(self, key, module_name, member_name, help, native=True,
3540
deprecated=False, hidden=False, experimental=False, alias=False):
3541
registry.Registry.register_lazy(self, key, module_name, member_name,
3542
help, BzrDirFormatInfo(native, deprecated, hidden, experimental))
3544
self._aliases.add(key)
3545
self._registration_order.append(key)
3547
def set_default(self, key):
3548
"""Set the 'default' key to be a clone of the supplied key.
3550
This method must be called once and only once.
3552
registry.Registry.register(self, 'default', self.get(key),
3553
self.get_help(key), info=self.get_info(key))
3554
self._aliases.add('default')
3556
def set_default_repository(self, key):
3557
"""Set the FormatRegistry default and Repository default.
3559
This is a transitional method while Repository.set_default_format
3562
if 'default' in self:
3563
self.remove('default')
3564
self.set_default(key)
3565
format = self.get('default')()
3567
def make_bzrdir(self, key):
3568
return self.get(key)()
3570
def help_topic(self, topic):
3572
default_realkey = None
3573
default_help = self.get_help('default')
3575
for key in self._registration_order:
3576
if key == 'default':
3578
help = self.get_help(key)
3579
if help == default_help:
3580
default_realkey = key
3582
help_pairs.append((key, help))
3584
def wrapped(key, help, info):
3586
help = '(native) ' + help
3587
return ':%s:\n%s\n\n' % (key,
3588
textwrap.fill(help, initial_indent=' ',
3589
subsequent_indent=' ',
3590
break_long_words=False))
3591
if default_realkey is not None:
3592
output += wrapped(default_realkey, '(default) %s' % default_help,
3593
self.get_info('default'))
3594
deprecated_pairs = []
3595
experimental_pairs = []
3596
for key, help in help_pairs:
3597
info = self.get_info(key)
3600
elif info.deprecated:
3601
deprecated_pairs.append((key, help))
3602
elif info.experimental:
3603
experimental_pairs.append((key, help))
3605
output += wrapped(key, help, info)
3606
output += "\nSee :doc:`formats-help` for more about storage formats."
3608
if len(experimental_pairs) > 0:
3609
other_output += "Experimental formats are shown below.\n\n"
3610
for key, help in experimental_pairs:
3611
info = self.get_info(key)
3612
other_output += wrapped(key, help, info)
3615
"No experimental formats are available.\n\n"
3616
if len(deprecated_pairs) > 0:
3617
other_output += "\nDeprecated formats are shown below.\n\n"
3618
for key, help in deprecated_pairs:
3619
info = self.get_info(key)
3620
other_output += wrapped(key, help, info)
3623
"\nNo deprecated formats are available.\n\n"
3625
"\nSee :doc:`formats-help` for more about storage formats."
3627
if topic == 'other-formats':
3633
class RepositoryAcquisitionPolicy(object):
3634
"""Abstract base class for repository acquisition policies.
3636
A repository acquisition policy decides how a BzrDir acquires a repository
3637
for a branch that is being created. The most basic policy decision is
3638
whether to create a new repository or use an existing one.
3640
def __init__(self, stack_on, stack_on_pwd, require_stacking):
3643
:param stack_on: A location to stack on
3644
:param stack_on_pwd: If stack_on is relative, the location it is
3646
:param require_stacking: If True, it is a failure to not stack.
3648
self._stack_on = stack_on
3649
self._stack_on_pwd = stack_on_pwd
3650
self._require_stacking = require_stacking
3652
def configure_branch(self, branch):
3653
"""Apply any configuration data from this policy to the branch.
3655
Default implementation sets repository stacking.
3657
if self._stack_on is None:
3659
if self._stack_on_pwd is None:
3660
stack_on = self._stack_on
3663
stack_on = urlutils.rebase_url(self._stack_on,
3665
branch.bzrdir.root_transport.base)
3666
except errors.InvalidRebaseURLs:
3667
stack_on = self._get_full_stack_on()
3669
branch.set_stacked_on_url(stack_on)
3670
except (errors.UnstackableBranchFormat,
3671
errors.UnstackableRepositoryFormat):
3672
if self._require_stacking:
3675
def requires_stacking(self):
3676
"""Return True if this policy requires stacking."""
3677
return self._stack_on is not None and self._require_stacking
3679
def _get_full_stack_on(self):
3680
"""Get a fully-qualified URL for the stack_on location."""
3681
if self._stack_on is None:
3683
if self._stack_on_pwd is None:
3684
return self._stack_on
3686
return urlutils.join(self._stack_on_pwd, self._stack_on)
3688
def _add_fallback(self, repository, possible_transports=None):
3689
"""Add a fallback to the supplied repository, if stacking is set."""
3690
stack_on = self._get_full_stack_on()
3691
if stack_on is None:
3694
stacked_dir = BzrDir.open(stack_on,
3695
possible_transports=possible_transports)
3696
except errors.JailBreak:
3697
# We keep the stacking details, but we are in the server code so
3698
# actually stacking is not needed.
3701
stacked_repo = stacked_dir.open_branch().repository
3702
except errors.NotBranchError:
3703
stacked_repo = stacked_dir.open_repository()
3705
repository.add_fallback_repository(stacked_repo)
3706
except errors.UnstackableRepositoryFormat:
3707
if self._require_stacking:
3710
self._require_stacking = True
3712
def acquire_repository(self, make_working_trees=None, shared=False):
3713
"""Acquire a repository for this bzrdir.
3715
Implementations may create a new repository or use a pre-exising
3717
:param make_working_trees: If creating a repository, set
3718
make_working_trees to this value (if non-None)
3719
:param shared: If creating a repository, make it shared if True
3720
:return: A repository, is_new_flag (True if the repository was
3723
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3726
class CreateRepository(RepositoryAcquisitionPolicy):
3727
"""A policy of creating a new repository"""
3729
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3730
require_stacking=False):
3733
:param bzrdir: The bzrdir to create the repository on.
3734
:param stack_on: A location to stack on
3735
:param stack_on_pwd: If stack_on is relative, the location it is
3738
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3740
self._bzrdir = bzrdir
3742
def acquire_repository(self, make_working_trees=None, shared=False):
3743
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3745
Creates the desired repository in the bzrdir we already have.
3747
stack_on = self._get_full_stack_on()
3749
format = self._bzrdir._format
3750
format.require_stacking(stack_on=stack_on,
3751
possible_transports=[self._bzrdir.root_transport])
3752
if not self._require_stacking:
3753
# We have picked up automatic stacking somewhere.
3754
note('Using default stacking branch %s at %s', self._stack_on,
3756
repository = self._bzrdir.create_repository(shared=shared)
3757
self._add_fallback(repository,
3758
possible_transports=[self._bzrdir.transport])
3759
if make_working_trees is not None:
3760
repository.set_make_working_trees(make_working_trees)
3761
return repository, True
3764
class UseExistingRepository(RepositoryAcquisitionPolicy):
3765
"""A policy of reusing an existing repository"""
3767
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3768
require_stacking=False):
3771
:param repository: The repository to use.
3772
:param stack_on: A location to stack on
3773
:param stack_on_pwd: If stack_on is relative, the location it is
3776
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3778
self._repository = repository
3780
def acquire_repository(self, make_working_trees=None, shared=False):
3781
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3783
Returns an existing repository to use.
3785
self._add_fallback(self._repository,
3786
possible_transports=[self._repository.bzrdir.transport])
3787
return self._repository, False
3790
# Please register new formats after old formats so that formats
3791
# appear in chronological order and format descriptions can build
3793
format_registry = BzrDirFormatRegistry()
3794
# The pre-0.8 formats have their repository format network name registered in
3795
# repository.py. MetaDir formats have their repository format network name
3796
# inferred from their disk format string.
3797
format_registry.register('weave', BzrDirFormat6,
3798
'Pre-0.8 format. Slower than knit and does not'
3799
' support checkouts or shared repositories.',
3802
format_registry.register_metadir('metaweave',
3803
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3804
'Transitional format in 0.8. Slower than knit.',
3805
branch_format='bzrlib.branch.BzrBranchFormat5',
3806
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3809
format_registry.register_metadir('knit',
3810
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3811
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3812
branch_format='bzrlib.branch.BzrBranchFormat5',
3813
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3816
format_registry.register_metadir('dirstate',
3817
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3818
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3819
'above when accessed over the network.',
3820
branch_format='bzrlib.branch.BzrBranchFormat5',
3821
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3822
# directly from workingtree_4 triggers a circular import.
3823
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3826
format_registry.register_metadir('dirstate-tags',
3827
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3828
help='New in 0.15: Fast local operations and improved scaling for '
3829
'network operations. Additionally adds support for tags.'
3830
' Incompatible with bzr < 0.15.',
3831
branch_format='bzrlib.branch.BzrBranchFormat6',
3832
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3835
format_registry.register_metadir('rich-root',
3836
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3837
help='New in 1.0. Better handling of tree roots. Incompatible with'
3839
branch_format='bzrlib.branch.BzrBranchFormat6',
3840
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3843
format_registry.register_metadir('dirstate-with-subtree',
3844
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3845
help='New in 0.15: Fast local operations and improved scaling for '
3846
'network operations. Additionally adds support for versioning nested '
3847
'bzr branches. Incompatible with bzr < 0.15.',
3848
branch_format='bzrlib.branch.BzrBranchFormat6',
3849
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3853
format_registry.register_metadir('pack-0.92',
3854
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3855
help='New in 0.92: Pack-based format with data compatible with '
3856
'dirstate-tags format repositories. Interoperates with '
3857
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3859
branch_format='bzrlib.branch.BzrBranchFormat6',
3860
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3862
format_registry.register_metadir('pack-0.92-subtree',
3863
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3864
help='New in 0.92: Pack-based format with data compatible with '
3865
'dirstate-with-subtree format repositories. Interoperates with '
3866
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3868
branch_format='bzrlib.branch.BzrBranchFormat6',
3869
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3873
format_registry.register_metadir('rich-root-pack',
3874
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3875
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3876
'(needed for bzr-svn and bzr-git).',
3877
branch_format='bzrlib.branch.BzrBranchFormat6',
3878
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3881
format_registry.register_metadir('1.6',
3882
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3883
help='A format that allows a branch to indicate that there is another '
3884
'(stacked) repository that should be used to access data that is '
3885
'not present locally.',
3886
branch_format='bzrlib.branch.BzrBranchFormat7',
3887
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3890
format_registry.register_metadir('1.6.1-rich-root',
3891
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3892
help='A variant of 1.6 that supports rich-root data '
3893
'(needed for bzr-svn and bzr-git).',
3894
branch_format='bzrlib.branch.BzrBranchFormat7',
3895
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3898
format_registry.register_metadir('1.9',
3899
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3900
help='A repository format using B+tree indexes. These indexes '
3901
'are smaller in size, have smarter caching and provide faster '
3902
'performance for most operations.',
3903
branch_format='bzrlib.branch.BzrBranchFormat7',
3904
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3907
format_registry.register_metadir('1.9-rich-root',
3908
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3909
help='A variant of 1.9 that supports rich-root data '
3910
'(needed for bzr-svn and bzr-git).',
3911
branch_format='bzrlib.branch.BzrBranchFormat7',
3912
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3915
format_registry.register_metadir('1.14',
3916
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3917
help='A working-tree format that supports content filtering.',
3918
branch_format='bzrlib.branch.BzrBranchFormat7',
3919
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3921
format_registry.register_metadir('1.14-rich-root',
3922
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3923
help='A variant of 1.14 that supports rich-root data '
3924
'(needed for bzr-svn and bzr-git).',
3925
branch_format='bzrlib.branch.BzrBranchFormat7',
3926
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3928
# The following un-numbered 'development' formats should always just be aliases.
3929
format_registry.register_metadir('development-rich-root',
3930
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3931
help='Current development format. Supports rich roots. Can convert data '
3932
'to and from rich-root-pack (and anything compatible with '
3933
'rich-root-pack) format repositories. Repositories and branches in '
3934
'this format can only be read by bzr.dev. Please read '
3935
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3937
branch_format='bzrlib.branch.BzrBranchFormat7',
3938
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3943
format_registry.register_metadir('development-subtree',
3944
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3945
help='Current development format, subtree variant. Can convert data to and '
3946
'from pack-0.92-subtree (and anything compatible with '
3947
'pack-0.92-subtree) format repositories. Repositories and branches in '
3948
'this format can only be read by bzr.dev. Please read '
3949
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3951
branch_format='bzrlib.branch.BzrBranchFormat7',
3952
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3955
alias=False, # Restore to being an alias when an actual development subtree format is added
3956
# This current non-alias status is simply because we did not introduce a
3957
# chk based subtree format.
3960
# And the development formats above will have aliased one of the following:
3961
format_registry.register_metadir('development6-rich-root',
3962
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3963
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3965
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3967
branch_format='bzrlib.branch.BzrBranchFormat7',
3968
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3973
format_registry.register_metadir('development7-rich-root',
3974
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3975
help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3976
'rich roots. Please read '
3977
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3979
branch_format='bzrlib.branch.BzrBranchFormat7',
3980
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3985
format_registry.register_metadir('2a',
3986
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3987
help='First format for bzr 2.0 series.\n'
3988
'Uses group-compress storage.\n'
3989
'Provides rich roots which are a one-way transition.\n',
3990
# 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
3991
# 'rich roots. Supported by bzr 1.16 and later.',
3992
branch_format='bzrlib.branch.BzrBranchFormat7',
3993
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3997
# The following format should be an alias for the rich root equivalent
3998
# of the default format
3999
format_registry.register_metadir('default-rich-root',
4000
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
4001
branch_format='bzrlib.branch.BzrBranchFormat7',
4002
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
4007
# The current format that is made on 'bzr init'.
4008
format_registry.set_default('2a')