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 BzrDir(controldir.ControlDir):
92
"""A .bzr control diretory.
94
BzrDir instances let you create or open any of the things that can be
95
found within .bzr - checkouts, branches and repositories.
98
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
100
a transport connected to the directory this bzr was opened from
101
(i.e. the parent directory holding the .bzr directory).
103
Everything in the bzrdir should have the same file permissions.
105
:cvar hooks: An instance of BzrDirHooks.
108
def break_lock(self):
109
"""Invoke break_lock on the first object in the bzrdir.
111
If there is a tree, the tree is opened and break_lock() called.
112
Otherwise, branch is tried, and finally repository.
114
# XXX: This seems more like a UI function than something that really
115
# belongs in this class.
117
thing_to_unlock = self.open_workingtree()
118
except (errors.NotLocalUrl, errors.NoWorkingTree):
120
thing_to_unlock = self.open_branch()
121
except errors.NotBranchError:
123
thing_to_unlock = self.open_repository()
124
except errors.NoRepositoryPresent:
126
thing_to_unlock.break_lock()
128
def check_conversion_target(self, target_format):
129
"""Check that a bzrdir as a whole can be converted to a new format."""
130
# The only current restriction is that the repository content can be
131
# fetched compatibly with the target.
132
target_repo_format = target_format.repository_format
134
self.open_repository()._format.check_conversion_target(
136
except errors.NoRepositoryPresent:
137
# No repo, no problem.
141
def _check_supported(format, allow_unsupported,
142
recommend_upgrade=True,
144
"""Give an error or warning on old formats.
146
:param format: may be any kind of format - workingtree, branch,
149
:param allow_unsupported: If true, allow opening
150
formats that are strongly deprecated, and which may
151
have limited functionality.
153
:param recommend_upgrade: If true (default), warn
154
the user through the ui object that they may wish
155
to upgrade the object.
157
# TODO: perhaps move this into a base Format class; it's not BzrDir
158
# specific. mbp 20070323
159
if not allow_unsupported and not format.is_supported():
160
# see open_downlevel to open legacy branches.
161
raise errors.UnsupportedFormatError(format=format)
162
if recommend_upgrade \
163
and getattr(format, 'upgrade_recommended', False):
164
ui.ui_factory.recommend_upgrade(
165
format.get_format_description(),
168
def clone_on_transport(self, transport, revision_id=None,
169
force_new_repo=False, preserve_stacking=False, stacked_on=None,
170
create_prefix=False, use_existing_dir=True):
171
"""Clone this bzrdir and its contents to transport verbatim.
173
:param transport: The transport for the location to produce the clone
174
at. If the target directory does not exist, it will be created.
175
:param revision_id: The tip revision-id to use for any branch or
176
working tree. If not None, then the clone operation may tune
177
itself to download less data.
178
:param force_new_repo: Do not use a shared repository for the target,
179
even if one is available.
180
:param preserve_stacking: When cloning a stacked branch, stack the
181
new branch on top of the other branch's stacked-on branch.
182
:param create_prefix: Create any missing directories leading up to
184
:param use_existing_dir: Use an existing directory if one exists.
186
# Overview: put together a broad description of what we want to end up
187
# with; then make as few api calls as possible to do it.
189
# We may want to create a repo/branch/tree, if we do so what format
190
# would we want for each:
191
require_stacking = (stacked_on is not None)
192
format = self.cloning_metadir(require_stacking)
194
# Figure out what objects we want:
196
local_repo = self.find_repository()
197
except errors.NoRepositoryPresent:
200
local_branch = self.open_branch()
201
except errors.NotBranchError:
204
# enable fallbacks when branch is not a branch reference
205
if local_branch.repository.has_same_location(local_repo):
206
local_repo = local_branch.repository
207
if preserve_stacking:
209
stacked_on = local_branch.get_stacked_on_url()
210
except (errors.UnstackableBranchFormat,
211
errors.UnstackableRepositoryFormat,
214
# Bug: We create a metadir without knowing if it can support stacking,
215
# we should look up the policy needs first, or just use it as a hint,
218
make_working_trees = local_repo.make_working_trees()
219
want_shared = local_repo.is_shared()
220
repo_format_name = format.repository_format.network_name()
222
make_working_trees = False
224
repo_format_name = None
226
result_repo, result, require_stacking, repository_policy = \
227
format.initialize_on_transport_ex(transport,
228
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
229
force_new_repo=force_new_repo, stacked_on=stacked_on,
230
stack_on_pwd=self.root_transport.base,
231
repo_format_name=repo_format_name,
232
make_working_trees=make_working_trees, shared_repo=want_shared)
235
# If the result repository is in the same place as the
236
# resulting bzr dir, it will have no content, further if the
237
# result is not stacked then we know all content should be
238
# copied, and finally if we are copying up to a specific
239
# revision_id then we can use the pending-ancestry-result which
240
# does not require traversing all of history to describe it.
241
if (result_repo.user_url == result.user_url
242
and not require_stacking and
243
revision_id is not None):
244
fetch_spec = graph.PendingAncestryResult(
245
[revision_id], local_repo)
246
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
248
result_repo.fetch(local_repo, revision_id=revision_id)
252
if result_repo is not None:
253
raise AssertionError('result_repo not None(%r)' % result_repo)
254
# 1 if there is a branch present
255
# make sure its content is available in the target repository
257
if local_branch is not None:
258
result_branch = local_branch.clone(result, revision_id=revision_id,
259
repository_policy=repository_policy)
261
# Cheaper to check if the target is not local, than to try making
263
result.root_transport.local_abspath('.')
264
if result_repo is None or result_repo.make_working_trees():
265
self.open_workingtree().clone(result)
266
except (errors.NoWorkingTree, errors.NotLocalUrl):
270
# TODO: This should be given a Transport, and should chdir up; otherwise
271
# this will open a new connection.
272
def _make_tail(self, url):
273
t = get_transport(url)
277
def find_bzrdirs(transport, evaluate=None, list_current=None):
278
"""Find bzrdirs recursively from current location.
280
This is intended primarily as a building block for more sophisticated
281
functionality, like finding trees under a directory, or finding
282
branches that use a given repository.
283
:param evaluate: An optional callable that yields recurse, value,
284
where recurse controls whether this bzrdir is recursed into
285
and value is the value to yield. By default, all bzrdirs
286
are recursed into, and the return value is the bzrdir.
287
:param list_current: if supplied, use this function to list the current
288
directory, instead of Transport.list_dir
289
:return: a generator of found bzrdirs, or whatever evaluate returns.
291
if list_current is None:
292
def list_current(transport):
293
return transport.list_dir('')
295
def evaluate(bzrdir):
298
pending = [transport]
299
while len(pending) > 0:
300
current_transport = pending.pop()
303
bzrdir = BzrDir.open_from_transport(current_transport)
304
except (errors.NotBranchError, errors.PermissionDenied):
307
recurse, value = evaluate(bzrdir)
310
subdirs = list_current(current_transport)
311
except (errors.NoSuchFile, errors.PermissionDenied):
314
for subdir in sorted(subdirs, reverse=True):
315
pending.append(current_transport.clone(subdir))
318
def find_branches(transport):
319
"""Find all branches under a transport.
321
This will find all branches below the transport, including branches
322
inside other branches. Where possible, it will use
323
Repository.find_branches.
325
To list all the branches that use a particular Repository, see
326
Repository.find_branches
328
def evaluate(bzrdir):
330
repository = bzrdir.open_repository()
331
except errors.NoRepositoryPresent:
334
return False, ([], repository)
335
return True, (bzrdir.list_branches(), None)
337
for branches, repo in BzrDir.find_bzrdirs(transport,
340
ret.extend(repo.find_branches())
341
if branches is not None:
346
def create_branch_and_repo(base, force_new_repo=False, format=None):
347
"""Create a new BzrDir, Branch and Repository at the url 'base'.
349
This will use the current default BzrDirFormat unless one is
350
specified, and use whatever
351
repository format that that uses via bzrdir.create_branch and
352
create_repository. If a shared repository is available that is used
355
The created Branch object is returned.
357
:param base: The URL to create the branch at.
358
:param force_new_repo: If True a new repository is always created.
359
:param format: If supplied, the format of branch to create. If not
360
supplied, the default is used.
362
bzrdir = BzrDir.create(base, format)
363
bzrdir._find_or_create_repository(force_new_repo)
364
return bzrdir.create_branch()
366
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
367
stack_on_pwd=None, require_stacking=False):
368
"""Return an object representing a policy to use.
370
This controls whether a new repository is created, and the format of
371
that repository, or some existing shared repository used instead.
373
If stack_on is supplied, will not seek a containing shared repo.
375
:param force_new_repo: If True, require a new repository to be created.
376
:param stack_on: If supplied, the location to stack on. If not
377
supplied, a default_stack_on location may be used.
378
:param stack_on_pwd: If stack_on is relative, the location it is
381
def repository_policy(found_bzrdir):
384
config = found_bzrdir.get_config()
386
stack_on = config.get_default_stack_on()
387
if stack_on is not None:
388
stack_on_pwd = found_bzrdir.user_url
390
# does it have a repository ?
392
repository = found_bzrdir.open_repository()
393
except errors.NoRepositoryPresent:
396
if (found_bzrdir.user_url != self.user_url
397
and not repository.is_shared()):
398
# Don't look higher, can't use a higher shared repo.
406
return UseExistingRepository(repository, stack_on,
407
stack_on_pwd, require_stacking=require_stacking), True
409
return CreateRepository(self, stack_on, stack_on_pwd,
410
require_stacking=require_stacking), True
412
if not force_new_repo:
414
policy = self._find_containing(repository_policy)
415
if policy is not None:
419
return UseExistingRepository(self.open_repository(),
420
stack_on, stack_on_pwd,
421
require_stacking=require_stacking)
422
except errors.NoRepositoryPresent:
424
return CreateRepository(self, stack_on, stack_on_pwd,
425
require_stacking=require_stacking)
427
def _find_or_create_repository(self, force_new_repo):
428
"""Create a new repository if needed, returning the repository."""
429
policy = self.determine_repository_policy(force_new_repo)
430
return policy.acquire_repository()[0]
433
def create_branch_convenience(base, force_new_repo=False,
434
force_new_tree=None, format=None,
435
possible_transports=None):
436
"""Create a new BzrDir, Branch and Repository at the url 'base'.
438
This is a convenience function - it will use an existing repository
439
if possible, can be told explicitly whether to create a working tree or
442
This will use the current default BzrDirFormat unless one is
443
specified, and use whatever
444
repository format that that uses via bzrdir.create_branch and
445
create_repository. If a shared repository is available that is used
446
preferentially. Whatever repository is used, its tree creation policy
449
The created Branch object is returned.
450
If a working tree cannot be made due to base not being a file:// url,
451
no error is raised unless force_new_tree is True, in which case no
452
data is created on disk and NotLocalUrl is raised.
454
:param base: The URL to create the branch at.
455
:param force_new_repo: If True a new repository is always created.
456
:param force_new_tree: If True or False force creation of a tree or
457
prevent such creation respectively.
458
:param format: Override for the bzrdir format to create.
459
:param possible_transports: An optional reusable transports list.
462
# check for non local urls
463
t = get_transport(base, possible_transports)
464
if not isinstance(t, local.LocalTransport):
465
raise errors.NotLocalUrl(base)
466
bzrdir = BzrDir.create(base, format, possible_transports)
467
repo = bzrdir._find_or_create_repository(force_new_repo)
468
result = bzrdir.create_branch()
469
if force_new_tree or (repo.make_working_trees() and
470
force_new_tree is None):
472
bzrdir.create_workingtree()
473
except errors.NotLocalUrl:
478
def create_standalone_workingtree(base, format=None):
479
"""Create a new BzrDir, WorkingTree, Branch and Repository at 'base'.
481
'base' must be a local path or a file:// url.
483
This will use the current default BzrDirFormat unless one is
484
specified, and use whatever
485
repository format that that uses for bzrdirformat.create_workingtree,
486
create_branch and create_repository.
488
:param format: Override for the bzrdir format to create.
489
:return: The WorkingTree object.
491
t = get_transport(base)
492
if not isinstance(t, local.LocalTransport):
493
raise errors.NotLocalUrl(base)
494
bzrdir = BzrDir.create_branch_and_repo(base,
496
format=format).bzrdir
497
return bzrdir.create_workingtree()
499
def generate_backup_name(self, base):
500
"""Generate a non-existing backup file name based on base."""
502
name = "%s.~%d~" % (base, counter)
503
while self.root_transport.has(name):
505
name = "%s.~%d~" % (base, counter)
508
def backup_bzrdir(self):
509
"""Backup this bzr control directory.
511
:return: Tuple with old path name and new path name
514
backup_dir=self.generate_backup_name('backup.bzr')
515
pb = ui.ui_factory.nested_progress_bar()
517
# FIXME: bug 300001 -- the backup fails if the backup directory
518
# already exists, but it should instead either remove it or make
519
# a new backup directory.
521
old_path = self.root_transport.abspath('.bzr')
522
new_path = self.root_transport.abspath(backup_dir)
523
ui.ui_factory.note('making backup of %s\n to %s' % (old_path, new_path,))
524
self.root_transport.copy_tree('.bzr', backup_dir)
525
return (old_path, new_path)
529
def retire_bzrdir(self, limit=10000):
530
"""Permanently disable the bzrdir.
532
This is done by renaming it to give the user some ability to recover
533
if there was a problem.
535
This will have horrible consequences if anyone has anything locked or
537
:param limit: number of times to retry
542
to_path = '.bzr.retired.%d' % i
543
self.root_transport.rename('.bzr', to_path)
544
note("renamed %s to %s"
545
% (self.root_transport.abspath('.bzr'), to_path))
547
except (errors.TransportError, IOError, errors.PathError):
554
def _find_containing(self, evaluate):
555
"""Find something in a containing control directory.
557
This method will scan containing control dirs, until it finds what
558
it is looking for, decides that it will never find it, or runs out
559
of containing control directories to check.
561
It is used to implement find_repository and
562
determine_repository_policy.
564
:param evaluate: A function returning (value, stop). If stop is True,
565
the value will be returned.
569
result, stop = evaluate(found_bzrdir)
572
next_transport = found_bzrdir.root_transport.clone('..')
573
if (found_bzrdir.user_url == next_transport.base):
574
# top of the file system
576
# find the next containing bzrdir
578
found_bzrdir = BzrDir.open_containing_from_transport(
580
except errors.NotBranchError:
583
def find_repository(self):
584
"""Find the repository that should be used.
586
This does not require a branch as we use it to find the repo for
587
new branches as well as to hook existing branches up to their
590
def usable_repository(found_bzrdir):
591
# does it have a repository ?
593
repository = found_bzrdir.open_repository()
594
except errors.NoRepositoryPresent:
596
if found_bzrdir.user_url == self.user_url:
597
return repository, True
598
elif repository.is_shared():
599
return repository, True
603
found_repo = self._find_containing(usable_repository)
604
if found_repo is None:
605
raise errors.NoRepositoryPresent(self)
608
def _find_creation_modes(self):
609
"""Determine the appropriate modes for files and directories.
611
They're always set to be consistent with the base directory,
612
assuming that this transport allows setting modes.
614
# TODO: Do we need or want an option (maybe a config setting) to turn
615
# this off or override it for particular locations? -- mbp 20080512
616
if self._mode_check_done:
618
self._mode_check_done = True
620
st = self.transport.stat('.')
621
except errors.TransportNotPossible:
622
self._dir_mode = None
623
self._file_mode = None
625
# Check the directory mode, but also make sure the created
626
# directories and files are read-write for this user. This is
627
# mostly a workaround for filesystems which lie about being able to
628
# write to a directory (cygwin & win32)
629
if (st.st_mode & 07777 == 00000):
630
# FTP allows stat but does not return dir/file modes
631
self._dir_mode = None
632
self._file_mode = None
634
self._dir_mode = (st.st_mode & 07777) | 00700
635
# Remove the sticky and execute bits for files
636
self._file_mode = self._dir_mode & ~07111
638
def _get_file_mode(self):
639
"""Return Unix mode for newly created files, or None.
641
if not self._mode_check_done:
642
self._find_creation_modes()
643
return self._file_mode
645
def _get_dir_mode(self):
646
"""Return Unix mode for newly created directories, or None.
648
if not self._mode_check_done:
649
self._find_creation_modes()
650
return self._dir_mode
652
def get_config(self):
653
"""Get configuration for this BzrDir."""
654
return config.BzrDirConfig(self)
656
def _get_config(self):
657
"""By default, no configuration is available."""
660
def __init__(self, _transport, _format):
661
"""Initialize a Bzr control dir object.
663
Only really common logic should reside here, concrete classes should be
664
made with varying behaviours.
666
:param _format: the format that is creating this BzrDir instance.
667
:param _transport: the transport this dir is based at.
669
self._format = _format
670
# these are also under the more standard names of
671
# control_transport and user_transport
672
self.transport = _transport.clone('.bzr')
673
self.root_transport = _transport
674
self._mode_check_done = False
677
def user_transport(self):
678
return self.root_transport
681
def control_transport(self):
682
return self.transport
684
def is_control_filename(self, filename):
685
"""True if filename is the name of a path which is reserved for bzrdir's.
687
:param filename: A filename within the root transport of this bzrdir.
689
This is true IF and ONLY IF the filename is part of the namespace reserved
690
for bzr control dirs. Currently this is the '.bzr' directory in the root
691
of the root_transport.
693
# this might be better on the BzrDirFormat class because it refers to
694
# all the possible bzrdir disk formats.
695
# This method is tested via the workingtree is_control_filename tests-
696
# it was extracted from WorkingTree.is_control_filename. If the method's
697
# contract is extended beyond the current trivial implementation, please
698
# add new tests for it to the appropriate place.
699
return filename == '.bzr' or filename.startswith('.bzr/')
702
def open_unsupported(base):
703
"""Open a branch which is not supported."""
704
return BzrDir.open(base, _unsupported=True)
707
def open(base, _unsupported=False, possible_transports=None):
708
"""Open an existing bzrdir, rooted at 'base' (url).
710
:param _unsupported: a private parameter to the BzrDir class.
712
t = get_transport(base, possible_transports=possible_transports)
713
return BzrDir.open_from_transport(t, _unsupported=_unsupported)
716
def open_from_transport(transport, _unsupported=False,
717
_server_formats=True):
718
"""Open a bzrdir within a particular directory.
720
:param transport: Transport containing the bzrdir.
721
:param _unsupported: private.
723
for hook in BzrDir.hooks['pre_open']:
725
# Keep initial base since 'transport' may be modified while following
727
base = transport.base
728
def find_format(transport):
729
return transport, controldir.ControlDirFormat.find_format(
730
transport, _server_formats=_server_formats)
732
def redirected(transport, e, redirection_notice):
733
redirected_transport = transport._redirected_to(e.source, e.target)
734
if redirected_transport is None:
735
raise errors.NotBranchError(base)
736
note('%s is%s redirected to %s',
737
transport.base, e.permanently, redirected_transport.base)
738
return redirected_transport
741
transport, format = do_catching_redirections(find_format,
744
except errors.TooManyRedirections:
745
raise errors.NotBranchError(base)
747
BzrDir._check_supported(format, _unsupported)
748
return format.open(transport, _found=True)
751
def open_containing(url, possible_transports=None):
752
"""Open an existing branch which contains url.
754
:param url: url to search from.
755
See open_containing_from_transport for more detail.
757
transport = get_transport(url, possible_transports)
758
return BzrDir.open_containing_from_transport(transport)
761
def open_containing_from_transport(a_transport):
762
"""Open an existing branch which contains a_transport.base.
764
This probes for a branch at a_transport, and searches upwards from there.
766
Basically we keep looking up until we find the control directory or
767
run into the root. If there isn't one, raises NotBranchError.
768
If there is one and it is either an unrecognised format or an unsupported
769
format, UnknownFormatError or UnsupportedFormatError are raised.
770
If there is one, it is returned, along with the unused portion of url.
772
:return: The BzrDir that contains the path, and a Unicode path
773
for the rest of the URL.
775
# this gets the normalised url back. I.e. '.' -> the full path.
776
url = a_transport.base
779
result = BzrDir.open_from_transport(a_transport)
780
return result, urlutils.unescape(a_transport.relpath(url))
781
except errors.NotBranchError, e:
784
new_t = a_transport.clone('..')
785
except errors.InvalidURLJoin:
786
# reached the root, whatever that may be
787
raise errors.NotBranchError(path=url)
788
if new_t.base == a_transport.base:
789
# reached the root, whatever that may be
790
raise errors.NotBranchError(path=url)
794
def open_tree_or_branch(klass, location):
795
"""Return the branch and working tree at a location.
797
If there is no tree at the location, tree will be None.
798
If there is no branch at the location, an exception will be
800
:return: (tree, branch)
802
bzrdir = klass.open(location)
803
return bzrdir._get_tree_branch()
806
def open_containing_tree_or_branch(klass, location):
807
"""Return the branch and working tree contained by a location.
809
Returns (tree, branch, relpath).
810
If there is no tree at containing the location, tree will be None.
811
If there is no branch containing the location, an exception will be
813
relpath is the portion of the path that is contained by the branch.
815
bzrdir, relpath = klass.open_containing(location)
816
tree, branch = bzrdir._get_tree_branch()
817
return tree, branch, relpath
820
def open_containing_tree_branch_or_repository(klass, location):
821
"""Return the working tree, branch and repo contained by a location.
823
Returns (tree, branch, repository, relpath).
824
If there is no tree containing the location, tree will be None.
825
If there is no branch containing the location, branch will be None.
826
If there is no repository containing the location, repository will be
828
relpath is the portion of the path that is contained by the innermost
831
If no tree, branch or repository is found, a NotBranchError is raised.
833
bzrdir, relpath = klass.open_containing(location)
835
tree, branch = bzrdir._get_tree_branch()
836
except errors.NotBranchError:
838
repo = bzrdir.find_repository()
839
return None, None, repo, relpath
840
except (errors.NoRepositoryPresent):
841
raise errors.NotBranchError(location)
842
return tree, branch, branch.repository, relpath
844
def _cloning_metadir(self):
845
"""Produce a metadir suitable for cloning with.
847
:returns: (destination_bzrdir_format, source_repository)
849
result_format = self._format.__class__()
852
branch = self.open_branch(ignore_fallbacks=True)
853
source_repository = branch.repository
854
result_format._branch_format = branch._format
855
except errors.NotBranchError:
857
source_repository = self.open_repository()
858
except errors.NoRepositoryPresent:
859
source_repository = None
861
# XXX TODO: This isinstance is here because we have not implemented
862
# the fix recommended in bug # 103195 - to delegate this choice the
864
repo_format = source_repository._format
865
if isinstance(repo_format, remote.RemoteRepositoryFormat):
866
source_repository._ensure_real()
867
repo_format = source_repository._real_repository._format
868
result_format.repository_format = repo_format
870
# TODO: Couldn't we just probe for the format in these cases,
871
# rather than opening the whole tree? It would be a little
872
# faster. mbp 20070401
873
tree = self.open_workingtree(recommend_upgrade=False)
874
except (errors.NoWorkingTree, errors.NotLocalUrl):
875
result_format.workingtree_format = None
877
result_format.workingtree_format = tree._format.__class__()
878
return result_format, source_repository
880
def cloning_metadir(self, require_stacking=False):
881
"""Produce a metadir suitable for cloning or sprouting with.
883
These operations may produce workingtrees (yes, even though they're
884
"cloning" something that doesn't have a tree), so a viable workingtree
885
format must be selected.
887
:require_stacking: If True, non-stackable formats will be upgraded
888
to similar stackable formats.
889
:returns: a BzrDirFormat with all component formats either set
890
appropriately or set to None if that component should not be
893
format, repository = self._cloning_metadir()
894
if format._workingtree_format is None:
896
if repository is None:
897
# No repository either
899
# We have a repository, so set a working tree? (Why? This seems to
900
# contradict the stated return value in the docstring).
901
tree_format = repository._format._matchingbzrdir.workingtree_format
902
format.workingtree_format = tree_format.__class__()
904
format.require_stacking()
908
def create(cls, base, format=None, possible_transports=None):
909
"""Create a new BzrDir at the url 'base'.
911
:param format: If supplied, the format of branch to create. If not
912
supplied, the default is used.
913
:param possible_transports: If supplied, a list of transports that
914
can be reused to share a remote connection.
916
if cls is not BzrDir:
917
raise AssertionError("BzrDir.create always creates the"
918
"default format, not one of %r" % cls)
919
t = get_transport(base, possible_transports)
922
format = controldir.ControlDirFormat.get_default_format()
923
return format.initialize_on_transport(t)
927
class BzrDirHooks(hooks.Hooks):
928
"""Hooks for BzrDir operations."""
931
"""Create the default hooks."""
932
hooks.Hooks.__init__(self)
933
self.create_hook(hooks.HookPoint('pre_open',
934
"Invoked before attempting to open a BzrDir with the transport "
935
"that the open will use.", (1, 14), None))
936
self.create_hook(hooks.HookPoint('post_repo_init',
937
"Invoked after a repository has been initialized. "
938
"post_repo_init is called with a "
939
"bzrlib.bzrdir.RepoInitHookParams.",
942
# install the default hooks
943
BzrDir.hooks = BzrDirHooks()
946
class RepoInitHookParams(object):
947
"""Object holding parameters passed to *_repo_init hooks.
949
There are 4 fields that hooks may wish to access:
951
:ivar repository: Repository created
952
:ivar format: Repository format
953
:ivar bzrdir: The bzrdir for the repository
954
:ivar shared: The repository is shared
957
def __init__(self, repository, format, a_bzrdir, shared):
958
"""Create a group of RepoInitHook parameters.
960
:param repository: Repository created
961
:param format: Repository format
962
:param bzrdir: The bzrdir for the repository
963
:param shared: The repository is shared
965
self.repository = repository
967
self.bzrdir = a_bzrdir
970
def __eq__(self, other):
971
return self.__dict__ == other.__dict__
975
return "<%s for %s>" % (self.__class__.__name__,
978
return "<%s for %s>" % (self.__class__.__name__,
982
class BzrDirPreSplitOut(BzrDir):
983
"""A common class for the all-in-one formats."""
985
def __init__(self, _transport, _format):
986
"""See BzrDir.__init__."""
987
super(BzrDirPreSplitOut, self).__init__(_transport, _format)
988
self._control_files = lockable_files.LockableFiles(
989
self.get_branch_transport(None),
990
self._format._lock_file_name,
991
self._format._lock_class)
993
def break_lock(self):
994
"""Pre-splitout bzrdirs do not suffer from stale locks."""
995
raise NotImplementedError(self.break_lock)
997
def cloning_metadir(self, require_stacking=False):
998
"""Produce a metadir suitable for cloning with."""
1000
return controldir.format_registry.make_bzrdir('1.6')
1001
return self._format.__class__()
1003
def clone(self, url, revision_id=None, force_new_repo=False,
1004
preserve_stacking=False):
1005
"""See BzrDir.clone().
1007
force_new_repo has no effect, since this family of formats always
1008
require a new repository.
1009
preserve_stacking has no effect, since no source branch using this
1010
family of formats can be stacked, so there is no stacking to preserve.
1012
self._make_tail(url)
1013
result = self._format._initialize_for_clone(url)
1014
self.open_repository().clone(result, revision_id=revision_id)
1015
from_branch = self.open_branch()
1016
from_branch.clone(result, revision_id=revision_id)
1018
tree = self.open_workingtree()
1019
except errors.NotLocalUrl:
1020
# make a new one, this format always has to have one.
1021
result._init_workingtree()
1026
def create_branch(self, name=None):
1027
"""See BzrDir.create_branch."""
1028
return self._format.get_branch_format().initialize(self, name=name)
1030
def destroy_branch(self, name=None):
1031
"""See BzrDir.destroy_branch."""
1032
raise errors.UnsupportedOperation(self.destroy_branch, self)
1034
def create_repository(self, shared=False):
1035
"""See BzrDir.create_repository."""
1037
raise errors.IncompatibleFormat('shared repository', self._format)
1038
return self.open_repository()
1040
def destroy_repository(self):
1041
"""See BzrDir.destroy_repository."""
1042
raise errors.UnsupportedOperation(self.destroy_repository, self)
1044
def create_workingtree(self, revision_id=None, from_branch=None,
1045
accelerator_tree=None, hardlink=False):
1046
"""See BzrDir.create_workingtree."""
1047
# The workingtree is sometimes created when the bzrdir is created,
1048
# but not when cloning.
1050
# this looks buggy but is not -really-
1051
# because this format creates the workingtree when the bzrdir is
1053
# clone and sprout will have set the revision_id
1054
# and that will have set it for us, its only
1055
# specific uses of create_workingtree in isolation
1056
# that can do wonky stuff here, and that only
1057
# happens for creating checkouts, which cannot be
1058
# done on this format anyway. So - acceptable wart.
1060
warning("can't support hardlinked working trees in %r"
1063
result = self.open_workingtree(recommend_upgrade=False)
1064
except errors.NoSuchFile:
1065
result = self._init_workingtree()
1066
if revision_id is not None:
1067
if revision_id == _mod_revision.NULL_REVISION:
1068
result.set_parent_ids([])
1070
result.set_parent_ids([revision_id])
1073
def _init_workingtree(self):
1074
from bzrlib.workingtree import WorkingTreeFormat2
1076
return WorkingTreeFormat2().initialize(self)
1077
except errors.NotLocalUrl:
1078
# Even though we can't access the working tree, we need to
1079
# create its control files.
1080
return WorkingTreeFormat2()._stub_initialize_on_transport(
1081
self.transport, self._control_files._file_mode)
1083
def destroy_workingtree(self):
1084
"""See BzrDir.destroy_workingtree."""
1085
raise errors.UnsupportedOperation(self.destroy_workingtree, self)
1087
def destroy_workingtree_metadata(self):
1088
"""See BzrDir.destroy_workingtree_metadata."""
1089
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1092
def get_branch_transport(self, branch_format, name=None):
1093
"""See BzrDir.get_branch_transport()."""
1094
if name is not None:
1095
raise errors.NoColocatedBranchSupport(self)
1096
if branch_format is None:
1097
return self.transport
1099
branch_format.get_format_string()
1100
except NotImplementedError:
1101
return self.transport
1102
raise errors.IncompatibleFormat(branch_format, self._format)
1104
def get_repository_transport(self, repository_format):
1105
"""See BzrDir.get_repository_transport()."""
1106
if repository_format is None:
1107
return self.transport
1109
repository_format.get_format_string()
1110
except NotImplementedError:
1111
return self.transport
1112
raise errors.IncompatibleFormat(repository_format, self._format)
1114
def get_workingtree_transport(self, workingtree_format):
1115
"""See BzrDir.get_workingtree_transport()."""
1116
if workingtree_format is None:
1117
return self.transport
1119
workingtree_format.get_format_string()
1120
except NotImplementedError:
1121
return self.transport
1122
raise errors.IncompatibleFormat(workingtree_format, self._format)
1124
def needs_format_conversion(self, format=None):
1125
"""See BzrDir.needs_format_conversion()."""
1126
# if the format is not the same as the system default,
1127
# an upgrade is needed.
1129
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1130
% 'needs_format_conversion(format=None)')
1131
format = BzrDirFormat.get_default_format()
1132
return not isinstance(self._format, format.__class__)
1134
def open_branch(self, name=None, unsupported=False,
1135
ignore_fallbacks=False):
1136
"""See BzrDir.open_branch."""
1137
from bzrlib.branch import BzrBranchFormat4
1138
format = BzrBranchFormat4()
1139
self._check_supported(format, unsupported)
1140
return format.open(self, name, _found=True)
1142
def sprout(self, url, revision_id=None, force_new_repo=False,
1143
possible_transports=None, accelerator_tree=None,
1144
hardlink=False, stacked=False, create_tree_if_local=True,
1145
source_branch=None):
1146
"""See BzrDir.sprout()."""
1147
if source_branch is not None:
1148
my_branch = self.open_branch()
1149
if source_branch.base != my_branch.base:
1150
raise AssertionError(
1151
"source branch %r is not within %r with branch %r" %
1152
(source_branch, self, my_branch))
1154
raise errors.UnstackableBranchFormat(
1155
self._format, self.root_transport.base)
1156
if not create_tree_if_local:
1157
raise errors.MustHaveWorkingTree(
1158
self._format, self.root_transport.base)
1159
from bzrlib.workingtree import WorkingTreeFormat2
1160
self._make_tail(url)
1161
result = self._format._initialize_for_clone(url)
1163
self.open_repository().clone(result, revision_id=revision_id)
1164
except errors.NoRepositoryPresent:
1167
self.open_branch().sprout(result, revision_id=revision_id)
1168
except errors.NotBranchError:
1171
# we always want a working tree
1172
WorkingTreeFormat2().initialize(result,
1173
accelerator_tree=accelerator_tree,
1178
class BzrDir4(BzrDirPreSplitOut):
1179
"""A .bzr version 4 control object.
1181
This is a deprecated format and may be removed after sept 2006.
1184
def create_repository(self, shared=False):
1185
"""See BzrDir.create_repository."""
1186
return self._format.repository_format.initialize(self, shared)
1188
def needs_format_conversion(self, format=None):
1189
"""Format 4 dirs are always in need of conversion."""
1191
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1192
% 'needs_format_conversion(format=None)')
1195
def open_repository(self):
1196
"""See BzrDir.open_repository."""
1197
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1198
return RepositoryFormat4().open(self, _found=True)
1201
class BzrDir5(BzrDirPreSplitOut):
1202
"""A .bzr version 5 control object.
1204
This is a deprecated format and may be removed after sept 2006.
1207
def has_workingtree(self):
1208
"""See BzrDir.has_workingtree."""
1211
def open_repository(self):
1212
"""See BzrDir.open_repository."""
1213
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1214
return RepositoryFormat5().open(self, _found=True)
1216
def open_workingtree(self, _unsupported=False,
1217
recommend_upgrade=True):
1218
"""See BzrDir.create_workingtree."""
1219
from bzrlib.workingtree import WorkingTreeFormat2
1220
wt_format = WorkingTreeFormat2()
1221
# we don't warn here about upgrades; that ought to be handled for the
1223
return wt_format.open(self, _found=True)
1226
class BzrDir6(BzrDirPreSplitOut):
1227
"""A .bzr version 6 control object.
1229
This is a deprecated format and may be removed after sept 2006.
1232
def has_workingtree(self):
1233
"""See BzrDir.has_workingtree."""
1236
def open_repository(self):
1237
"""See BzrDir.open_repository."""
1238
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1239
return RepositoryFormat6().open(self, _found=True)
1241
def open_workingtree(self, _unsupported=False,
1242
recommend_upgrade=True):
1243
"""See BzrDir.create_workingtree."""
1244
# we don't warn here about upgrades; that ought to be handled for the
1246
from bzrlib.workingtree import WorkingTreeFormat2
1247
return WorkingTreeFormat2().open(self, _found=True)
1250
class BzrDirMeta1(BzrDir):
1251
"""A .bzr meta version 1 control object.
1253
This is the first control object where the
1254
individual aspects are really split out: there are separate repository,
1255
workingtree and branch subdirectories and any subset of the three can be
1256
present within a BzrDir.
1259
def can_convert_format(self):
1260
"""See BzrDir.can_convert_format()."""
1263
def create_branch(self, name=None):
1264
"""See BzrDir.create_branch."""
1265
return self._format.get_branch_format().initialize(self, name=name)
1267
def destroy_branch(self, name=None):
1268
"""See BzrDir.create_branch."""
1269
if name is not None:
1270
raise errors.NoColocatedBranchSupport(self)
1271
self.transport.delete_tree('branch')
1273
def create_repository(self, shared=False):
1274
"""See BzrDir.create_repository."""
1275
return self._format.repository_format.initialize(self, shared)
1277
def destroy_repository(self):
1278
"""See BzrDir.destroy_repository."""
1279
self.transport.delete_tree('repository')
1281
def create_workingtree(self, revision_id=None, from_branch=None,
1282
accelerator_tree=None, hardlink=False):
1283
"""See BzrDir.create_workingtree."""
1284
return self._format.workingtree_format.initialize(
1285
self, revision_id, from_branch=from_branch,
1286
accelerator_tree=accelerator_tree, hardlink=hardlink)
1288
def destroy_workingtree(self):
1289
"""See BzrDir.destroy_workingtree."""
1290
wt = self.open_workingtree(recommend_upgrade=False)
1291
repository = wt.branch.repository
1292
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1293
wt.revert(old_tree=empty)
1294
self.destroy_workingtree_metadata()
1296
def destroy_workingtree_metadata(self):
1297
self.transport.delete_tree('checkout')
1299
def find_branch_format(self, name=None):
1300
"""Find the branch 'format' for this bzrdir.
1302
This might be a synthetic object for e.g. RemoteBranch and SVN.
1304
from bzrlib.branch import BranchFormat
1305
return BranchFormat.find_format(self, name=name)
1307
def _get_mkdir_mode(self):
1308
"""Figure out the mode to use when creating a bzrdir subdir."""
1309
temp_control = lockable_files.LockableFiles(self.transport, '',
1310
lockable_files.TransportLock)
1311
return temp_control._dir_mode
1313
def get_branch_reference(self, name=None):
1314
"""See BzrDir.get_branch_reference()."""
1315
from bzrlib.branch import BranchFormat
1316
format = BranchFormat.find_format(self, name=name)
1317
return format.get_reference(self, name=name)
1319
def get_branch_transport(self, branch_format, name=None):
1320
"""See BzrDir.get_branch_transport()."""
1321
if name is not None:
1322
raise errors.NoColocatedBranchSupport(self)
1323
# XXX: this shouldn't implicitly create the directory if it's just
1324
# promising to get a transport -- mbp 20090727
1325
if branch_format is None:
1326
return self.transport.clone('branch')
1328
branch_format.get_format_string()
1329
except NotImplementedError:
1330
raise errors.IncompatibleFormat(branch_format, self._format)
1332
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
1333
except errors.FileExists:
1335
return self.transport.clone('branch')
1337
def get_repository_transport(self, repository_format):
1338
"""See BzrDir.get_repository_transport()."""
1339
if repository_format is None:
1340
return self.transport.clone('repository')
1342
repository_format.get_format_string()
1343
except NotImplementedError:
1344
raise errors.IncompatibleFormat(repository_format, self._format)
1346
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
1347
except errors.FileExists:
1349
return self.transport.clone('repository')
1351
def get_workingtree_transport(self, workingtree_format):
1352
"""See BzrDir.get_workingtree_transport()."""
1353
if workingtree_format is None:
1354
return self.transport.clone('checkout')
1356
workingtree_format.get_format_string()
1357
except NotImplementedError:
1358
raise errors.IncompatibleFormat(workingtree_format, self._format)
1360
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
1361
except errors.FileExists:
1363
return self.transport.clone('checkout')
1365
def has_workingtree(self):
1366
"""Tell if this bzrdir contains a working tree.
1368
This will still raise an exception if the bzrdir has a workingtree that
1369
is remote & inaccessible.
1371
Note: if you're going to open the working tree, you should just go
1372
ahead and try, and not ask permission first.
1374
from bzrlib.workingtree import WorkingTreeFormat
1376
WorkingTreeFormat.find_format(self)
1377
except errors.NoWorkingTree:
1381
def needs_format_conversion(self, format=None):
1382
"""See BzrDir.needs_format_conversion()."""
1384
symbol_versioning.warn(symbol_versioning.deprecated_in((1, 13, 0))
1385
% 'needs_format_conversion(format=None)')
1387
format = BzrDirFormat.get_default_format()
1388
if not isinstance(self._format, format.__class__):
1389
# it is not a meta dir format, conversion is needed.
1391
# we might want to push this down to the repository?
1393
if not isinstance(self.open_repository()._format,
1394
format.repository_format.__class__):
1395
# the repository needs an upgrade.
1397
except errors.NoRepositoryPresent:
1399
for branch in self.list_branches():
1400
if not isinstance(branch._format,
1401
format.get_branch_format().__class__):
1402
# the branch needs an upgrade.
1405
my_wt = self.open_workingtree(recommend_upgrade=False)
1406
if not isinstance(my_wt._format,
1407
format.workingtree_format.__class__):
1408
# the workingtree needs an upgrade.
1410
except (errors.NoWorkingTree, errors.NotLocalUrl):
1414
def open_branch(self, name=None, unsupported=False,
1415
ignore_fallbacks=False):
1416
"""See BzrDir.open_branch."""
1417
format = self.find_branch_format(name=name)
1418
self._check_supported(format, unsupported)
1419
return format.open(self, name=name,
1420
_found=True, ignore_fallbacks=ignore_fallbacks)
1422
def open_repository(self, unsupported=False):
1423
"""See BzrDir.open_repository."""
1424
from bzrlib.repository import RepositoryFormat
1425
format = RepositoryFormat.find_format(self)
1426
self._check_supported(format, unsupported)
1427
return format.open(self, _found=True)
1429
def open_workingtree(self, unsupported=False,
1430
recommend_upgrade=True):
1431
"""See BzrDir.open_workingtree."""
1432
from bzrlib.workingtree import WorkingTreeFormat
1433
format = WorkingTreeFormat.find_format(self)
1434
self._check_supported(format, unsupported,
1436
basedir=self.root_transport.base)
1437
return format.open(self, _found=True)
1439
def _get_config(self):
1440
return config.TransportConfig(self.transport, 'control.conf')
1443
class BzrProber(controldir.Prober):
1444
"""Prober for formats that use a .bzr/ control directory."""
1447
"""The known .bzr formats."""
1450
def register_bzrdir_format(klass, format):
1451
klass._formats[format.get_format_string()] = format
1454
def unregister_bzrdir_format(klass, format):
1455
del klass._formats[format.get_format_string()]
1458
def probe_transport(klass, transport):
1459
"""Return the .bzrdir style format present in a directory."""
1461
format_string = transport.get_bytes(".bzr/branch-format")
1462
except errors.NoSuchFile:
1463
raise errors.NotBranchError(path=transport.base)
1465
return klass._formats[format_string]
1467
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1470
controldir.ControlDirFormat.register_prober(BzrProber)
1473
class RemoteBzrProber(controldir.Prober):
1474
"""Prober for remote servers that provide a Bazaar smart server."""
1477
def probe_transport(klass, transport):
1478
"""Return a RemoteBzrDirFormat object if it looks possible."""
1480
medium = transport.get_smart_medium()
1481
except (NotImplementedError, AttributeError,
1482
errors.TransportNotPossible, errors.NoSmartMedium,
1483
errors.SmartProtocolError):
1484
# no smart server, so not a branch for this format type.
1485
raise errors.NotBranchError(path=transport.base)
1487
# Decline to open it if the server doesn't support our required
1488
# version (3) so that the VFS-based transport will do it.
1489
if medium.should_probe():
1491
server_version = medium.protocol_version()
1492
except errors.SmartProtocolError:
1493
# Apparently there's no usable smart server there, even though
1494
# the medium supports the smart protocol.
1495
raise errors.NotBranchError(path=transport.base)
1496
if server_version != '2':
1497
raise errors.NotBranchError(path=transport.base)
1498
return RemoteBzrDirFormat()
1501
class BzrDirFormat(controldir.ControlDirFormat):
1502
"""ControlDirFormat base class for .bzr/ directories.
1504
Formats are placed in a dict by their format string for reference
1505
during bzrdir opening. These should be subclasses of BzrDirFormat
1508
Once a format is deprecated, just deprecate the initialize and open
1509
methods on the format class. Do not deprecate the object, as the
1510
object will be created every system load.
1513
_lock_file_name = 'branch-lock'
1515
# _lock_class must be set in subclasses to the lock type, typ.
1516
# TransportLock or LockDir
1518
def get_format_string(self):
1519
"""Return the ASCII format string that identifies this format."""
1520
raise NotImplementedError(self.get_format_string)
1522
def initialize_on_transport(self, transport):
1523
"""Initialize a new bzrdir in the base directory of a Transport."""
1525
# can we hand off the request to the smart server rather than using
1527
client_medium = transport.get_smart_medium()
1528
except errors.NoSmartMedium:
1529
return self._initialize_on_transport_vfs(transport)
1531
# Current RPC's only know how to create bzr metadir1 instances, so
1532
# we still delegate to vfs methods if the requested format is not a
1534
if type(self) != BzrDirMetaFormat1:
1535
return self._initialize_on_transport_vfs(transport)
1536
remote_format = RemoteBzrDirFormat()
1537
self._supply_sub_formats_to(remote_format)
1538
return remote_format.initialize_on_transport(transport)
1540
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1541
create_prefix=False, force_new_repo=False, stacked_on=None,
1542
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1543
shared_repo=False, vfs_only=False):
1544
"""Create this format on transport.
1546
The directory to initialize will be created.
1548
:param force_new_repo: Do not use a shared repository for the target,
1549
even if one is available.
1550
:param create_prefix: Create any missing directories leading up to
1552
:param use_existing_dir: Use an existing directory if one exists.
1553
:param stacked_on: A url to stack any created branch on, None to follow
1554
any target stacking policy.
1555
:param stack_on_pwd: If stack_on is relative, the location it is
1557
:param repo_format_name: If non-None, a repository will be
1558
made-or-found. Should none be found, or if force_new_repo is True
1559
the repo_format_name is used to select the format of repository to
1561
:param make_working_trees: Control the setting of make_working_trees
1562
for a new shared repository when one is made. None to use whatever
1563
default the format has.
1564
:param shared_repo: Control whether made repositories are shared or
1566
:param vfs_only: If True do not attempt to use a smart server
1567
:return: repo, bzrdir, require_stacking, repository_policy. repo is
1568
None if none was created or found, bzrdir is always valid.
1569
require_stacking is the result of examining the stacked_on
1570
parameter and any stacking policy found for the target.
1573
# Try to hand off to a smart server
1575
client_medium = transport.get_smart_medium()
1576
except errors.NoSmartMedium:
1579
# TODO: lookup the local format from a server hint.
1580
remote_dir_format = RemoteBzrDirFormat()
1581
remote_dir_format._network_name = self.network_name()
1582
self._supply_sub_formats_to(remote_dir_format)
1583
return remote_dir_format.initialize_on_transport_ex(transport,
1584
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1585
force_new_repo=force_new_repo, stacked_on=stacked_on,
1586
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1587
make_working_trees=make_working_trees, shared_repo=shared_repo)
1588
# XXX: Refactor the create_prefix/no_create_prefix code into a
1589
# common helper function
1590
# The destination may not exist - if so make it according to policy.
1591
def make_directory(transport):
1592
transport.mkdir('.')
1594
def redirected(transport, e, redirection_notice):
1595
note(redirection_notice)
1596
return transport._redirected_to(e.source, e.target)
1598
transport = do_catching_redirections(make_directory, transport,
1600
except errors.FileExists:
1601
if not use_existing_dir:
1603
except errors.NoSuchFile:
1604
if not create_prefix:
1606
transport.create_prefix()
1608
require_stacking = (stacked_on is not None)
1609
# Now the target directory exists, but doesn't have a .bzr
1610
# directory. So we need to create it, along with any work to create
1611
# all of the dependent branches, etc.
1613
result = self.initialize_on_transport(transport)
1614
if repo_format_name:
1616
# use a custom format
1617
result._format.repository_format = \
1618
repository.network_format_registry.get(repo_format_name)
1619
except AttributeError:
1620
# The format didn't permit it to be set.
1622
# A repository is desired, either in-place or shared.
1623
repository_policy = result.determine_repository_policy(
1624
force_new_repo, stacked_on, stack_on_pwd,
1625
require_stacking=require_stacking)
1626
result_repo, is_new_repo = repository_policy.acquire_repository(
1627
make_working_trees, shared_repo)
1628
if not require_stacking and repository_policy._require_stacking:
1629
require_stacking = True
1630
result._format.require_stacking()
1631
result_repo.lock_write()
1634
repository_policy = None
1635
return result_repo, result, require_stacking, repository_policy
1637
def _initialize_on_transport_vfs(self, transport):
1638
"""Initialize a new bzrdir using VFS calls.
1640
:param transport: The transport to create the .bzr directory in.
1643
# Since we are creating a .bzr directory, inherit the
1644
# mode from the root directory
1645
temp_control = lockable_files.LockableFiles(transport,
1646
'', lockable_files.TransportLock)
1647
temp_control._transport.mkdir('.bzr',
1648
# FIXME: RBC 20060121 don't peek under
1650
mode=temp_control._dir_mode)
1651
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1652
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1653
file_mode = temp_control._file_mode
1655
bzrdir_transport = transport.clone('.bzr')
1656
utf8_files = [('README',
1657
"This is a Bazaar control directory.\n"
1658
"Do not change any files in this directory.\n"
1659
"See http://bazaar-vcs.org/ for more information about Bazaar.\n"),
1660
('branch-format', self.get_format_string()),
1662
# NB: no need to escape relative paths that are url safe.
1663
control_files = lockable_files.LockableFiles(bzrdir_transport,
1664
self._lock_file_name, self._lock_class)
1665
control_files.create_lock()
1666
control_files.lock_write()
1668
for (filename, content) in utf8_files:
1669
bzrdir_transport.put_bytes(filename, content,
1672
control_files.unlock()
1673
return self.open(transport, _found=True)
1675
def open(self, transport, _found=False):
1676
"""Return an instance of this format for the dir transport points at.
1678
_found is a private parameter, do not use it.
1681
found_format = controldir.ControlDirFormat.find_format(transport)
1682
if not isinstance(found_format, self.__class__):
1683
raise AssertionError("%s was asked to open %s, but it seems to need "
1685
% (self, transport, found_format))
1686
# Allow subclasses - use the found format.
1687
self._supply_sub_formats_to(found_format)
1688
return found_format._open(transport)
1689
return self._open(transport)
1691
def _open(self, transport):
1692
"""Template method helper for opening BzrDirectories.
1694
This performs the actual open and any additional logic or parameter
1697
raise NotImplementedError(self._open)
1700
def register_format(klass, format):
1701
BzrProber.register_bzrdir_format(format)
1702
# bzr native formats have a network name of their format string.
1703
controldir.network_format_registry.register(format.get_format_string(), format.__class__)
1704
controldir.ControlDirFormat.register_format(format)
1706
def _supply_sub_formats_to(self, other_format):
1707
"""Give other_format the same values for sub formats as this has.
1709
This method is expected to be used when parameterising a
1710
RemoteBzrDirFormat instance with the parameters from a
1711
BzrDirMetaFormat1 instance.
1713
:param other_format: other_format is a format which should be
1714
compatible with whatever sub formats are supported by self.
1719
def unregister_format(klass, format):
1720
BzrProber.unregister_bzrdir_format(format)
1721
controldir.ControlDirFormat.unregister_format(format)
1722
controldir.network_format_registry.remove(format.get_format_string())
1725
class BzrDirFormat4(BzrDirFormat):
1726
"""Bzr dir format 4.
1728
This format is a combined format for working tree, branch and repository.
1730
- Format 1 working trees [always]
1731
- Format 4 branches [always]
1732
- Format 4 repositories [always]
1734
This format is deprecated: it indexes texts using a text it which is
1735
removed in format 5; write support for this format has been removed.
1738
_lock_class = lockable_files.TransportLock
1740
def get_format_string(self):
1741
"""See BzrDirFormat.get_format_string()."""
1742
return "Bazaar-NG branch, format 0.0.4\n"
1744
def get_format_description(self):
1745
"""See BzrDirFormat.get_format_description()."""
1746
return "All-in-one format 4"
1748
def get_converter(self, format=None):
1749
"""See BzrDirFormat.get_converter()."""
1750
# there is one and only one upgrade path here.
1751
return ConvertBzrDir4To5()
1753
def initialize_on_transport(self, transport):
1754
"""Format 4 branches cannot be created."""
1755
raise errors.UninitializableFormat(self)
1757
def is_supported(self):
1758
"""Format 4 is not supported.
1760
It is not supported because the model changed from 4 to 5 and the
1761
conversion logic is expensive - so doing it on the fly was not
1766
def network_name(self):
1767
return self.get_format_string()
1769
def _open(self, transport):
1770
"""See BzrDirFormat._open."""
1771
return BzrDir4(transport, self)
1773
def __return_repository_format(self):
1774
"""Circular import protection."""
1775
from bzrlib.repofmt.weaverepo import RepositoryFormat4
1776
return RepositoryFormat4()
1777
repository_format = property(__return_repository_format)
1780
class BzrDirFormatAllInOne(BzrDirFormat):
1781
"""Common class for formats before meta-dirs."""
1783
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1784
create_prefix=False, force_new_repo=False, stacked_on=None,
1785
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1787
"""See BzrDirFormat.initialize_on_transport_ex."""
1788
require_stacking = (stacked_on is not None)
1789
# Format 5 cannot stack, but we've been asked to - actually init
1791
if require_stacking:
1792
format = BzrDirMetaFormat1()
1793
return format.initialize_on_transport_ex(transport,
1794
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1795
force_new_repo=force_new_repo, stacked_on=stacked_on,
1796
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1797
make_working_trees=make_working_trees, shared_repo=shared_repo)
1798
return BzrDirFormat.initialize_on_transport_ex(self, transport,
1799
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1800
force_new_repo=force_new_repo, stacked_on=stacked_on,
1801
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1802
make_working_trees=make_working_trees, shared_repo=shared_repo)
1805
class BzrDirFormat5(BzrDirFormatAllInOne):
1806
"""Bzr control format 5.
1808
This format is a combined format for working tree, branch and repository.
1810
- Format 2 working trees [always]
1811
- Format 4 branches [always]
1812
- Format 5 repositories [always]
1813
Unhashed stores in the repository.
1816
_lock_class = lockable_files.TransportLock
1818
def get_format_string(self):
1819
"""See BzrDirFormat.get_format_string()."""
1820
return "Bazaar-NG branch, format 5\n"
1822
def get_branch_format(self):
1823
from bzrlib import branch
1824
return branch.BzrBranchFormat4()
1826
def get_format_description(self):
1827
"""See BzrDirFormat.get_format_description()."""
1828
return "All-in-one format 5"
1830
def get_converter(self, format=None):
1831
"""See BzrDirFormat.get_converter()."""
1832
# there is one and only one upgrade path here.
1833
return ConvertBzrDir5To6()
1835
def _initialize_for_clone(self, url):
1836
return self.initialize_on_transport(get_transport(url), _cloning=True)
1838
def initialize_on_transport(self, transport, _cloning=False):
1839
"""Format 5 dirs always have working tree, branch and repository.
1841
Except when they are being cloned.
1843
from bzrlib.branch import BzrBranchFormat4
1844
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1845
result = (super(BzrDirFormat5, self).initialize_on_transport(transport))
1846
RepositoryFormat5().initialize(result, _internal=True)
1848
branch = BzrBranchFormat4().initialize(result)
1849
result._init_workingtree()
1852
def network_name(self):
1853
return self.get_format_string()
1855
def _open(self, transport):
1856
"""See BzrDirFormat._open."""
1857
return BzrDir5(transport, self)
1859
def __return_repository_format(self):
1860
"""Circular import protection."""
1861
from bzrlib.repofmt.weaverepo import RepositoryFormat5
1862
return RepositoryFormat5()
1863
repository_format = property(__return_repository_format)
1866
class BzrDirFormat6(BzrDirFormatAllInOne):
1867
"""Bzr control format 6.
1869
This format is a combined format for working tree, branch and repository.
1871
- Format 2 working trees [always]
1872
- Format 4 branches [always]
1873
- Format 6 repositories [always]
1876
_lock_class = lockable_files.TransportLock
1878
def get_format_string(self):
1879
"""See BzrDirFormat.get_format_string()."""
1880
return "Bazaar-NG branch, format 6\n"
1882
def get_format_description(self):
1883
"""See BzrDirFormat.get_format_description()."""
1884
return "All-in-one format 6"
1886
def get_branch_format(self):
1887
from bzrlib import branch
1888
return branch.BzrBranchFormat4()
1890
def get_converter(self, format=None):
1891
"""See BzrDirFormat.get_converter()."""
1892
# there is one and only one upgrade path here.
1893
return ConvertBzrDir6ToMeta()
1895
def _initialize_for_clone(self, url):
1896
return self.initialize_on_transport(get_transport(url), _cloning=True)
1898
def initialize_on_transport(self, transport, _cloning=False):
1899
"""Format 6 dirs always have working tree, branch and repository.
1901
Except when they are being cloned.
1903
from bzrlib.branch import BzrBranchFormat4
1904
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1905
result = super(BzrDirFormat6, self).initialize_on_transport(transport)
1906
RepositoryFormat6().initialize(result, _internal=True)
1908
branch = BzrBranchFormat4().initialize(result)
1909
result._init_workingtree()
1912
def network_name(self):
1913
return self.get_format_string()
1915
def _open(self, transport):
1916
"""See BzrDirFormat._open."""
1917
return BzrDir6(transport, self)
1919
def __return_repository_format(self):
1920
"""Circular import protection."""
1921
from bzrlib.repofmt.weaverepo import RepositoryFormat6
1922
return RepositoryFormat6()
1923
repository_format = property(__return_repository_format)
1926
class BzrDirMetaFormat1(BzrDirFormat):
1927
"""Bzr meta control format 1
1929
This is the first format with split out working tree, branch and repository
1932
- Format 3 working trees [optional]
1933
- Format 5 branches [optional]
1934
- Format 7 repositories [optional]
1937
_lock_class = lockdir.LockDir
1940
self._workingtree_format = None
1941
self._branch_format = None
1942
self._repository_format = None
1944
def __eq__(self, other):
1945
if other.__class__ is not self.__class__:
1947
if other.repository_format != self.repository_format:
1949
if other.workingtree_format != self.workingtree_format:
1953
def __ne__(self, other):
1954
return not self == other
1956
def get_branch_format(self):
1957
if self._branch_format is None:
1958
from bzrlib.branch import BranchFormat
1959
self._branch_format = BranchFormat.get_default_format()
1960
return self._branch_format
1962
def set_branch_format(self, format):
1963
self._branch_format = format
1965
def require_stacking(self, stack_on=None, possible_transports=None,
1967
"""We have a request to stack, try to ensure the formats support it.
1969
:param stack_on: If supplied, it is the URL to a branch that we want to
1970
stack on. Check to see if that format supports stacking before
1973
# Stacking is desired. requested by the target, but does the place it
1974
# points at support stacking? If it doesn't then we should
1975
# not implicitly upgrade. We check this here.
1976
new_repo_format = None
1977
new_branch_format = None
1979
# a bit of state for get_target_branch so that we don't try to open it
1980
# 2 times, for both repo *and* branch
1981
target = [None, False, None] # target_branch, checked, upgrade anyway
1982
def get_target_branch():
1984
# We've checked, don't check again
1986
if stack_on is None:
1987
# No target format, that means we want to force upgrading
1988
target[:] = [None, True, True]
1991
target_dir = BzrDir.open(stack_on,
1992
possible_transports=possible_transports)
1993
except errors.NotBranchError:
1994
# Nothing there, don't change formats
1995
target[:] = [None, True, False]
1997
except errors.JailBreak:
1998
# JailBreak, JFDI and upgrade anyway
1999
target[:] = [None, True, True]
2002
target_branch = target_dir.open_branch()
2003
except errors.NotBranchError:
2004
# No branch, don't upgrade formats
2005
target[:] = [None, True, False]
2007
target[:] = [target_branch, True, False]
2010
if (not _skip_repo and
2011
not self.repository_format.supports_external_lookups):
2012
# We need to upgrade the Repository.
2013
target_branch, _, do_upgrade = get_target_branch()
2014
if target_branch is None:
2015
# We don't have a target branch, should we upgrade anyway?
2017
# stack_on is inaccessible, JFDI.
2018
# TODO: bad monkey, hard-coded formats...
2019
if self.repository_format.rich_root_data:
2020
new_repo_format = pack_repo.RepositoryFormatKnitPack5RichRoot()
2022
new_repo_format = pack_repo.RepositoryFormatKnitPack5()
2024
# If the target already supports stacking, then we know the
2025
# project is already able to use stacking, so auto-upgrade
2027
new_repo_format = target_branch.repository._format
2028
if not new_repo_format.supports_external_lookups:
2029
# target doesn't, source doesn't, so don't auto upgrade
2031
new_repo_format = None
2032
if new_repo_format is not None:
2033
self.repository_format = new_repo_format
2034
note('Source repository format does not support stacking,'
2035
' using format:\n %s',
2036
new_repo_format.get_format_description())
2038
if not self.get_branch_format().supports_stacking():
2039
# We just checked the repo, now lets check if we need to
2040
# upgrade the branch format
2041
target_branch, _, do_upgrade = get_target_branch()
2042
if target_branch is None:
2044
# TODO: bad monkey, hard-coded formats...
2045
new_branch_format = branch.BzrBranchFormat7()
2047
new_branch_format = target_branch._format
2048
if not new_branch_format.supports_stacking():
2049
new_branch_format = None
2050
if new_branch_format is not None:
2051
# Does support stacking, use its format.
2052
self.set_branch_format(new_branch_format)
2053
note('Source branch format does not support stacking,'
2054
' using format:\n %s',
2055
new_branch_format.get_format_description())
2057
def get_converter(self, format=None):
2058
"""See BzrDirFormat.get_converter()."""
2060
format = BzrDirFormat.get_default_format()
2061
if not isinstance(self, format.__class__):
2062
# converting away from metadir is not implemented
2063
raise NotImplementedError(self.get_converter)
2064
return ConvertMetaToMeta(format)
2066
def get_format_string(self):
2067
"""See BzrDirFormat.get_format_string()."""
2068
return "Bazaar-NG meta directory, format 1\n"
2070
def get_format_description(self):
2071
"""See BzrDirFormat.get_format_description()."""
2072
return "Meta directory format 1"
2074
def network_name(self):
2075
return self.get_format_string()
2077
def _open(self, transport):
2078
"""See BzrDirFormat._open."""
2079
# Create a new format instance because otherwise initialisation of new
2080
# metadirs share the global default format object leading to alias
2082
format = BzrDirMetaFormat1()
2083
self._supply_sub_formats_to(format)
2084
return BzrDirMeta1(transport, format)
2086
def __return_repository_format(self):
2087
"""Circular import protection."""
2088
if self._repository_format:
2089
return self._repository_format
2090
from bzrlib.repository import RepositoryFormat
2091
return RepositoryFormat.get_default_format()
2093
def _set_repository_format(self, value):
2094
"""Allow changing the repository format for metadir formats."""
2095
self._repository_format = value
2097
repository_format = property(__return_repository_format,
2098
_set_repository_format)
2100
def _supply_sub_formats_to(self, other_format):
2101
"""Give other_format the same values for sub formats as this has.
2103
This method is expected to be used when parameterising a
2104
RemoteBzrDirFormat instance with the parameters from a
2105
BzrDirMetaFormat1 instance.
2107
:param other_format: other_format is a format which should be
2108
compatible with whatever sub formats are supported by self.
2111
if getattr(self, '_repository_format', None) is not None:
2112
other_format.repository_format = self.repository_format
2113
if self._branch_format is not None:
2114
other_format._branch_format = self._branch_format
2115
if self._workingtree_format is not None:
2116
other_format.workingtree_format = self.workingtree_format
2118
def __get_workingtree_format(self):
2119
if self._workingtree_format is None:
2120
from bzrlib.workingtree import WorkingTreeFormat
2121
self._workingtree_format = WorkingTreeFormat.get_default_format()
2122
return self._workingtree_format
2124
def __set_workingtree_format(self, wt_format):
2125
self._workingtree_format = wt_format
2127
workingtree_format = property(__get_workingtree_format,
2128
__set_workingtree_format)
2131
# Register bzr formats
2132
BzrDirFormat.register_format(BzrDirFormat4())
2133
BzrDirFormat.register_format(BzrDirFormat5())
2134
BzrDirFormat.register_format(BzrDirFormat6())
2135
__default_format = BzrDirMetaFormat1()
2136
BzrDirFormat.register_format(__default_format)
2137
controldir.ControlDirFormat._default_format = __default_format
2140
class Converter(object):
2141
"""Converts a disk format object from one format to another."""
2143
def convert(self, to_convert, pb):
2144
"""Perform the conversion of to_convert, giving feedback via pb.
2146
:param to_convert: The disk object to convert.
2147
:param pb: a progress bar to use for progress information.
2150
def step(self, message):
2151
"""Update the pb by a step."""
2153
self.pb.update(message, self.count, self.total)
2156
class ConvertBzrDir4To5(Converter):
2157
"""Converts format 4 bzr dirs to format 5."""
2160
super(ConvertBzrDir4To5, self).__init__()
2161
self.converted_revs = set()
2162
self.absent_revisions = set()
2166
def convert(self, to_convert, pb):
2167
"""See Converter.convert()."""
2168
self.bzrdir = to_convert
2170
warnings.warn("pb parameter to convert() is deprecated")
2171
self.pb = ui.ui_factory.nested_progress_bar()
2173
ui.ui_factory.note('starting upgrade from format 4 to 5')
2174
if isinstance(self.bzrdir.transport, local.LocalTransport):
2175
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2176
self._convert_to_weaves()
2177
return BzrDir.open(self.bzrdir.user_url)
2181
def _convert_to_weaves(self):
2182
ui.ui_factory.note('note: upgrade may be faster if all store files are ungzipped first')
2185
stat = self.bzrdir.transport.stat('weaves')
2186
if not S_ISDIR(stat.st_mode):
2187
self.bzrdir.transport.delete('weaves')
2188
self.bzrdir.transport.mkdir('weaves')
2189
except errors.NoSuchFile:
2190
self.bzrdir.transport.mkdir('weaves')
2191
# deliberately not a WeaveFile as we want to build it up slowly.
2192
self.inv_weave = Weave('inventory')
2193
# holds in-memory weaves for all files
2194
self.text_weaves = {}
2195
self.bzrdir.transport.delete('branch-format')
2196
self.branch = self.bzrdir.open_branch()
2197
self._convert_working_inv()
2198
rev_history = self.branch.revision_history()
2199
# to_read is a stack holding the revisions we still need to process;
2200
# appending to it adds new highest-priority revisions
2201
self.known_revisions = set(rev_history)
2202
self.to_read = rev_history[-1:]
2204
rev_id = self.to_read.pop()
2205
if (rev_id not in self.revisions
2206
and rev_id not in self.absent_revisions):
2207
self._load_one_rev(rev_id)
2209
to_import = self._make_order()
2210
for i, rev_id in enumerate(to_import):
2211
self.pb.update('converting revision', i, len(to_import))
2212
self._convert_one_rev(rev_id)
2214
self._write_all_weaves()
2215
self._write_all_revs()
2216
ui.ui_factory.note('upgraded to weaves:')
2217
ui.ui_factory.note(' %6d revisions and inventories' % len(self.revisions))
2218
ui.ui_factory.note(' %6d revisions not present' % len(self.absent_revisions))
2219
ui.ui_factory.note(' %6d texts' % self.text_count)
2220
self._cleanup_spare_files_after_format4()
2221
self.branch._transport.put_bytes(
2223
BzrDirFormat5().get_format_string(),
2224
mode=self.bzrdir._get_file_mode())
2226
def _cleanup_spare_files_after_format4(self):
2227
# FIXME working tree upgrade foo.
2228
for n in 'merged-patches', 'pending-merged-patches':
2230
## assert os.path.getsize(p) == 0
2231
self.bzrdir.transport.delete(n)
2232
except errors.NoSuchFile:
2234
self.bzrdir.transport.delete_tree('inventory-store')
2235
self.bzrdir.transport.delete_tree('text-store')
2237
def _convert_working_inv(self):
2238
inv = xml4.serializer_v4.read_inventory(
2239
self.branch._transport.get('inventory'))
2240
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
2241
self.branch._transport.put_bytes('inventory', new_inv_xml,
2242
mode=self.bzrdir._get_file_mode())
2244
def _write_all_weaves(self):
2245
controlweaves = WeaveStore(self.bzrdir.transport, prefixed=False)
2246
weave_transport = self.bzrdir.transport.clone('weaves')
2247
weaves = WeaveStore(weave_transport, prefixed=False)
2248
transaction = WriteTransaction()
2252
for file_id, file_weave in self.text_weaves.items():
2253
self.pb.update('writing weave', i, len(self.text_weaves))
2254
weaves._put_weave(file_id, file_weave, transaction)
2256
self.pb.update('inventory', 0, 1)
2257
controlweaves._put_weave('inventory', self.inv_weave, transaction)
2258
self.pb.update('inventory', 1, 1)
2262
def _write_all_revs(self):
2263
"""Write all revisions out in new form."""
2264
self.bzrdir.transport.delete_tree('revision-store')
2265
self.bzrdir.transport.mkdir('revision-store')
2266
revision_transport = self.bzrdir.transport.clone('revision-store')
2268
from bzrlib.xml5 import serializer_v5
2269
from bzrlib.repofmt.weaverepo import RevisionTextStore
2270
revision_store = RevisionTextStore(revision_transport,
2271
serializer_v5, False, versionedfile.PrefixMapper(),
2272
lambda:True, lambda:True)
2274
for i, rev_id in enumerate(self.converted_revs):
2275
self.pb.update('write revision', i, len(self.converted_revs))
2276
text = serializer_v5.write_revision_to_string(
2277
self.revisions[rev_id])
2279
revision_store.add_lines(key, None, osutils.split_lines(text))
2283
def _load_one_rev(self, rev_id):
2284
"""Load a revision object into memory.
2286
Any parents not either loaded or abandoned get queued to be
2288
self.pb.update('loading revision',
2289
len(self.revisions),
2290
len(self.known_revisions))
2291
if not self.branch.repository.has_revision(rev_id):
2293
ui.ui_factory.note('revision {%s} not present in branch; '
2294
'will be converted as a ghost' %
2296
self.absent_revisions.add(rev_id)
2298
rev = self.branch.repository.get_revision(rev_id)
2299
for parent_id in rev.parent_ids:
2300
self.known_revisions.add(parent_id)
2301
self.to_read.append(parent_id)
2302
self.revisions[rev_id] = rev
2304
def _load_old_inventory(self, rev_id):
2305
f = self.branch.repository.inventory_store.get(rev_id)
2307
old_inv_xml = f.read()
2310
inv = xml4.serializer_v4.read_inventory_from_string(old_inv_xml)
2311
inv.revision_id = rev_id
2312
rev = self.revisions[rev_id]
2315
def _load_updated_inventory(self, rev_id):
2316
inv_xml = self.inv_weave.get_text(rev_id)
2317
inv = xml5.serializer_v5.read_inventory_from_string(inv_xml, rev_id)
2320
def _convert_one_rev(self, rev_id):
2321
"""Convert revision and all referenced objects to new format."""
2322
rev = self.revisions[rev_id]
2323
inv = self._load_old_inventory(rev_id)
2324
present_parents = [p for p in rev.parent_ids
2325
if p not in self.absent_revisions]
2326
self._convert_revision_contents(rev, inv, present_parents)
2327
self._store_new_inv(rev, inv, present_parents)
2328
self.converted_revs.add(rev_id)
2330
def _store_new_inv(self, rev, inv, present_parents):
2331
new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
2332
new_inv_sha1 = sha_string(new_inv_xml)
2333
self.inv_weave.add_lines(rev.revision_id,
2335
new_inv_xml.splitlines(True))
2336
rev.inventory_sha1 = new_inv_sha1
2338
def _convert_revision_contents(self, rev, inv, present_parents):
2339
"""Convert all the files within a revision.
2341
Also upgrade the inventory to refer to the text revision ids."""
2342
rev_id = rev.revision_id
2343
mutter('converting texts of revision {%s}',
2345
parent_invs = map(self._load_updated_inventory, present_parents)
2346
entries = inv.iter_entries()
2348
for path, ie in entries:
2349
self._convert_file_version(rev, ie, parent_invs)
2351
def _convert_file_version(self, rev, ie, parent_invs):
2352
"""Convert one version of one file.
2354
The file needs to be added into the weave if it is a merge
2355
of >=2 parents or if it's changed from its parent.
2357
file_id = ie.file_id
2358
rev_id = rev.revision_id
2359
w = self.text_weaves.get(file_id)
2362
self.text_weaves[file_id] = w
2363
text_changed = False
2364
parent_candiate_entries = ie.parent_candidates(parent_invs)
2365
heads = graph.Graph(self).heads(parent_candiate_entries.keys())
2366
# XXX: Note that this is unordered - and this is tolerable because
2367
# the previous code was also unordered.
2368
previous_entries = dict((head, parent_candiate_entries[head]) for head
2370
self.snapshot_ie(previous_entries, ie, w, rev_id)
2372
def get_parent_map(self, revision_ids):
2373
"""See graph.StackedParentsProvider.get_parent_map"""
2374
return dict((revision_id, self.revisions[revision_id])
2375
for revision_id in revision_ids
2376
if revision_id in self.revisions)
2378
def snapshot_ie(self, previous_revisions, ie, w, rev_id):
2379
# TODO: convert this logic, which is ~= snapshot to
2380
# a call to:. This needs the path figured out. rather than a work_tree
2381
# a v4 revision_tree can be given, or something that looks enough like
2382
# one to give the file content to the entry if it needs it.
2383
# and we need something that looks like a weave store for snapshot to
2385
#ie.snapshot(rev, PATH, previous_revisions, REVISION_TREE, InMemoryWeaveStore(self.text_weaves))
2386
if len(previous_revisions) == 1:
2387
previous_ie = previous_revisions.values()[0]
2388
if ie._unchanged(previous_ie):
2389
ie.revision = previous_ie.revision
2392
f = self.branch.repository._text_store.get(ie.text_id)
2394
file_lines = f.readlines()
2397
w.add_lines(rev_id, previous_revisions, file_lines)
2398
self.text_count += 1
2400
w.add_lines(rev_id, previous_revisions, [])
2401
ie.revision = rev_id
2403
def _make_order(self):
2404
"""Return a suitable order for importing revisions.
2406
The order must be such that an revision is imported after all
2407
its (present) parents.
2409
todo = set(self.revisions.keys())
2410
done = self.absent_revisions.copy()
2413
# scan through looking for a revision whose parents
2415
for rev_id in sorted(list(todo)):
2416
rev = self.revisions[rev_id]
2417
parent_ids = set(rev.parent_ids)
2418
if parent_ids.issubset(done):
2419
# can take this one now
2420
order.append(rev_id)
2426
class ConvertBzrDir5To6(Converter):
2427
"""Converts format 5 bzr dirs to format 6."""
2429
def convert(self, to_convert, pb):
2430
"""See Converter.convert()."""
2431
self.bzrdir = to_convert
2432
pb = ui.ui_factory.nested_progress_bar()
2434
ui.ui_factory.note('starting upgrade from format 5 to 6')
2435
self._convert_to_prefixed()
2436
return BzrDir.open(self.bzrdir.user_url)
2440
def _convert_to_prefixed(self):
2441
from bzrlib.store import TransportStore
2442
self.bzrdir.transport.delete('branch-format')
2443
for store_name in ["weaves", "revision-store"]:
2444
ui.ui_factory.note("adding prefixes to %s" % store_name)
2445
store_transport = self.bzrdir.transport.clone(store_name)
2446
store = TransportStore(store_transport, prefixed=True)
2447
for urlfilename in store_transport.list_dir('.'):
2448
filename = urlutils.unescape(urlfilename)
2449
if (filename.endswith(".weave") or
2450
filename.endswith(".gz") or
2451
filename.endswith(".sig")):
2452
file_id, suffix = os.path.splitext(filename)
2456
new_name = store._mapper.map((file_id,)) + suffix
2457
# FIXME keep track of the dirs made RBC 20060121
2459
store_transport.move(filename, new_name)
2460
except errors.NoSuchFile: # catches missing dirs strangely enough
2461
store_transport.mkdir(osutils.dirname(new_name))
2462
store_transport.move(filename, new_name)
2463
self.bzrdir.transport.put_bytes(
2465
BzrDirFormat6().get_format_string(),
2466
mode=self.bzrdir._get_file_mode())
2469
class ConvertBzrDir6ToMeta(Converter):
2470
"""Converts format 6 bzr dirs to metadirs."""
2472
def convert(self, to_convert, pb):
2473
"""See Converter.convert()."""
2474
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2475
from bzrlib.branch import BzrBranchFormat5
2476
self.bzrdir = to_convert
2477
self.pb = ui.ui_factory.nested_progress_bar()
2479
self.total = 20 # the steps we know about
2480
self.garbage_inventories = []
2481
self.dir_mode = self.bzrdir._get_dir_mode()
2482
self.file_mode = self.bzrdir._get_file_mode()
2484
ui.ui_factory.note('starting upgrade from format 6 to metadir')
2485
self.bzrdir.transport.put_bytes(
2487
"Converting to format 6",
2488
mode=self.file_mode)
2489
# its faster to move specific files around than to open and use the apis...
2490
# first off, nuke ancestry.weave, it was never used.
2492
self.step('Removing ancestry.weave')
2493
self.bzrdir.transport.delete('ancestry.weave')
2494
except errors.NoSuchFile:
2496
# find out whats there
2497
self.step('Finding branch files')
2498
last_revision = self.bzrdir.open_branch().last_revision()
2499
bzrcontents = self.bzrdir.transport.list_dir('.')
2500
for name in bzrcontents:
2501
if name.startswith('basis-inventory.'):
2502
self.garbage_inventories.append(name)
2503
# create new directories for repository, working tree and branch
2504
repository_names = [('inventory.weave', True),
2505
('revision-store', True),
2507
self.step('Upgrading repository ')
2508
self.bzrdir.transport.mkdir('repository', mode=self.dir_mode)
2509
self.make_lock('repository')
2510
# we hard code the formats here because we are converting into
2511
# the meta format. The meta format upgrader can take this to a
2512
# future format within each component.
2513
self.put_format('repository', RepositoryFormat7())
2514
for entry in repository_names:
2515
self.move_entry('repository', entry)
2517
self.step('Upgrading branch ')
2518
self.bzrdir.transport.mkdir('branch', mode=self.dir_mode)
2519
self.make_lock('branch')
2520
self.put_format('branch', BzrBranchFormat5())
2521
branch_files = [('revision-history', True),
2522
('branch-name', True),
2524
for entry in branch_files:
2525
self.move_entry('branch', entry)
2527
checkout_files = [('pending-merges', True),
2528
('inventory', True),
2529
('stat-cache', False)]
2530
# If a mandatory checkout file is not present, the branch does not have
2531
# a functional checkout. Do not create a checkout in the converted
2533
for name, mandatory in checkout_files:
2534
if mandatory and name not in bzrcontents:
2535
has_checkout = False
2539
if not has_checkout:
2540
ui.ui_factory.note('No working tree.')
2541
# If some checkout files are there, we may as well get rid of them.
2542
for name, mandatory in checkout_files:
2543
if name in bzrcontents:
2544
self.bzrdir.transport.delete(name)
2546
from bzrlib.workingtree import WorkingTreeFormat3
2547
self.step('Upgrading working tree')
2548
self.bzrdir.transport.mkdir('checkout', mode=self.dir_mode)
2549
self.make_lock('checkout')
2551
'checkout', WorkingTreeFormat3())
2552
self.bzrdir.transport.delete_multi(
2553
self.garbage_inventories, self.pb)
2554
for entry in checkout_files:
2555
self.move_entry('checkout', entry)
2556
if last_revision is not None:
2557
self.bzrdir.transport.put_bytes(
2558
'checkout/last-revision', last_revision)
2559
self.bzrdir.transport.put_bytes(
2561
BzrDirMetaFormat1().get_format_string(),
2562
mode=self.file_mode)
2564
return BzrDir.open(self.bzrdir.user_url)
2566
def make_lock(self, name):
2567
"""Make a lock for the new control dir name."""
2568
self.step('Make %s lock' % name)
2569
ld = lockdir.LockDir(self.bzrdir.transport,
2571
file_modebits=self.file_mode,
2572
dir_modebits=self.dir_mode)
2575
def move_entry(self, new_dir, entry):
2576
"""Move then entry name into new_dir."""
2578
mandatory = entry[1]
2579
self.step('Moving %s' % name)
2581
self.bzrdir.transport.move(name, '%s/%s' % (new_dir, name))
2582
except errors.NoSuchFile:
2586
def put_format(self, dirname, format):
2587
self.bzrdir.transport.put_bytes('%s/format' % dirname,
2588
format.get_format_string(),
2592
class ConvertMetaToMeta(Converter):
2593
"""Converts the components of metadirs."""
2595
def __init__(self, target_format):
2596
"""Create a metadir to metadir converter.
2598
:param target_format: The final metadir format that is desired.
2600
self.target_format = target_format
2602
def convert(self, to_convert, pb):
2603
"""See Converter.convert()."""
2604
self.bzrdir = to_convert
2605
self.pb = ui.ui_factory.nested_progress_bar()
2608
self.step('checking repository format')
2610
repo = self.bzrdir.open_repository()
2611
except errors.NoRepositoryPresent:
2614
if not isinstance(repo._format, self.target_format.repository_format.__class__):
2615
from bzrlib.repository import CopyConverter
2616
ui.ui_factory.note('starting repository conversion')
2617
converter = CopyConverter(self.target_format.repository_format)
2618
converter.convert(repo, pb)
2619
for branch in self.bzrdir.list_branches():
2620
# TODO: conversions of Branch and Tree should be done by
2621
# InterXFormat lookups/some sort of registry.
2622
# Avoid circular imports
2623
from bzrlib import branch as _mod_branch
2624
old = branch._format.__class__
2625
new = self.target_format.get_branch_format().__class__
2627
if (old == _mod_branch.BzrBranchFormat5 and
2628
new in (_mod_branch.BzrBranchFormat6,
2629
_mod_branch.BzrBranchFormat7,
2630
_mod_branch.BzrBranchFormat8)):
2631
branch_converter = _mod_branch.Converter5to6()
2632
elif (old == _mod_branch.BzrBranchFormat6 and
2633
new in (_mod_branch.BzrBranchFormat7,
2634
_mod_branch.BzrBranchFormat8)):
2635
branch_converter = _mod_branch.Converter6to7()
2636
elif (old == _mod_branch.BzrBranchFormat7 and
2637
new is _mod_branch.BzrBranchFormat8):
2638
branch_converter = _mod_branch.Converter7to8()
2640
raise errors.BadConversionTarget("No converter", new,
2642
branch_converter.convert(branch)
2643
branch = self.bzrdir.open_branch()
2644
old = branch._format.__class__
2646
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
2647
except (errors.NoWorkingTree, errors.NotLocalUrl):
2650
# TODO: conversions of Branch and Tree should be done by
2651
# InterXFormat lookups
2652
if (isinstance(tree, workingtree.WorkingTree3) and
2653
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
2654
isinstance(self.target_format.workingtree_format,
2655
workingtree_4.DirStateWorkingTreeFormat)):
2656
workingtree_4.Converter3to4().convert(tree)
2657
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2658
not isinstance(tree, workingtree_4.WorkingTree5) and
2659
isinstance(self.target_format.workingtree_format,
2660
workingtree_4.WorkingTreeFormat5)):
2661
workingtree_4.Converter4to5().convert(tree)
2662
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
2663
not isinstance(tree, workingtree_4.WorkingTree6) and
2664
isinstance(self.target_format.workingtree_format,
2665
workingtree_4.WorkingTreeFormat6)):
2666
workingtree_4.Converter4or5to6().convert(tree)
2671
# This is not in remote.py because it's relatively small, and needs to be
2672
# registered. Putting it in remote.py creates a circular import problem.
2673
# we can make it a lazy object if the control formats is turned into something
2675
class RemoteBzrDirFormat(BzrDirMetaFormat1):
2676
"""Format representing bzrdirs accessed via a smart server"""
2678
supports_workingtrees = False
2681
BzrDirMetaFormat1.__init__(self)
2682
# XXX: It's a bit ugly that the network name is here, because we'd
2683
# like to believe that format objects are stateless or at least
2684
# immutable, However, we do at least avoid mutating the name after
2685
# it's returned. See <https://bugs.launchpad.net/bzr/+bug/504102>
2686
self._network_name = None
2689
return "%s(_network_name=%r)" % (self.__class__.__name__,
2692
def get_format_description(self):
2693
if self._network_name:
2694
real_format = controldir.network_format_registry.get(self._network_name)
2695
return 'Remote: ' + real_format.get_format_description()
2696
return 'bzr remote bzrdir'
2698
def get_format_string(self):
2699
raise NotImplementedError(self.get_format_string)
2701
def network_name(self):
2702
if self._network_name:
2703
return self._network_name
2705
raise AssertionError("No network name set.")
2707
def initialize_on_transport(self, transport):
2709
# hand off the request to the smart server
2710
client_medium = transport.get_smart_medium()
2711
except errors.NoSmartMedium:
2712
# TODO: lookup the local format from a server hint.
2713
local_dir_format = BzrDirMetaFormat1()
2714
return local_dir_format.initialize_on_transport(transport)
2715
client = _SmartClient(client_medium)
2716
path = client.remote_path_from_transport(transport)
2718
response = client.call('BzrDirFormat.initialize', path)
2719
except errors.ErrorFromSmartServer, err:
2720
remote._translate_error(err, path=path)
2721
if response[0] != 'ok':
2722
raise errors.SmartProtocolError('unexpected response code %s' % (response,))
2723
format = RemoteBzrDirFormat()
2724
self._supply_sub_formats_to(format)
2725
return remote.RemoteBzrDir(transport, format)
2727
def parse_NoneTrueFalse(self, arg):
2734
raise AssertionError("invalid arg %r" % arg)
2736
def _serialize_NoneTrueFalse(self, arg):
2743
def _serialize_NoneString(self, arg):
2746
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
2747
create_prefix=False, force_new_repo=False, stacked_on=None,
2748
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
2751
# hand off the request to the smart server
2752
client_medium = transport.get_smart_medium()
2753
except errors.NoSmartMedium:
2756
# Decline to open it if the server doesn't support our required
2757
# version (3) so that the VFS-based transport will do it.
2758
if client_medium.should_probe():
2760
server_version = client_medium.protocol_version()
2761
if server_version != '2':
2765
except errors.SmartProtocolError:
2766
# Apparently there's no usable smart server there, even though
2767
# the medium supports the smart protocol.
2772
client = _SmartClient(client_medium)
2773
path = client.remote_path_from_transport(transport)
2774
if client_medium._is_remote_before((1, 16)):
2777
# TODO: lookup the local format from a server hint.
2778
local_dir_format = BzrDirMetaFormat1()
2779
self._supply_sub_formats_to(local_dir_format)
2780
return local_dir_format.initialize_on_transport_ex(transport,
2781
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2782
force_new_repo=force_new_repo, stacked_on=stacked_on,
2783
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2784
make_working_trees=make_working_trees, shared_repo=shared_repo,
2786
return self._initialize_on_transport_ex_rpc(client, path, transport,
2787
use_existing_dir, create_prefix, force_new_repo, stacked_on,
2788
stack_on_pwd, repo_format_name, make_working_trees, shared_repo)
2790
def _initialize_on_transport_ex_rpc(self, client, path, transport,
2791
use_existing_dir, create_prefix, force_new_repo, stacked_on,
2792
stack_on_pwd, repo_format_name, make_working_trees, shared_repo):
2794
args.append(self._serialize_NoneTrueFalse(use_existing_dir))
2795
args.append(self._serialize_NoneTrueFalse(create_prefix))
2796
args.append(self._serialize_NoneTrueFalse(force_new_repo))
2797
args.append(self._serialize_NoneString(stacked_on))
2798
# stack_on_pwd is often/usually our transport
2801
stack_on_pwd = transport.relpath(stack_on_pwd)
2802
if not stack_on_pwd:
2804
except errors.PathNotChild:
2806
args.append(self._serialize_NoneString(stack_on_pwd))
2807
args.append(self._serialize_NoneString(repo_format_name))
2808
args.append(self._serialize_NoneTrueFalse(make_working_trees))
2809
args.append(self._serialize_NoneTrueFalse(shared_repo))
2810
request_network_name = self._network_name or \
2811
BzrDirFormat.get_default_format().network_name()
2813
response = client.call('BzrDirFormat.initialize_ex_1.16',
2814
request_network_name, path, *args)
2815
except errors.UnknownSmartMethod:
2816
client._medium._remember_remote_is_before((1,16))
2817
local_dir_format = BzrDirMetaFormat1()
2818
self._supply_sub_formats_to(local_dir_format)
2819
return local_dir_format.initialize_on_transport_ex(transport,
2820
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
2821
force_new_repo=force_new_repo, stacked_on=stacked_on,
2822
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
2823
make_working_trees=make_working_trees, shared_repo=shared_repo,
2825
except errors.ErrorFromSmartServer, err:
2826
remote._translate_error(err, path=path)
2827
repo_path = response[0]
2828
bzrdir_name = response[6]
2829
require_stacking = response[7]
2830
require_stacking = self.parse_NoneTrueFalse(require_stacking)
2831
format = RemoteBzrDirFormat()
2832
format._network_name = bzrdir_name
2833
self._supply_sub_formats_to(format)
2834
bzrdir = remote.RemoteBzrDir(transport, format, _client=client)
2836
repo_format = remote.response_tuple_to_repo_format(response[1:])
2837
if repo_path == '.':
2840
repo_bzrdir_format = RemoteBzrDirFormat()
2841
repo_bzrdir_format._network_name = response[5]
2842
repo_bzr = remote.RemoteBzrDir(transport.clone(repo_path),
2846
final_stack = response[8] or None
2847
final_stack_pwd = response[9] or None
2849
final_stack_pwd = urlutils.join(
2850
transport.base, final_stack_pwd)
2851
remote_repo = remote.RemoteRepository(repo_bzr, repo_format)
2852
if len(response) > 10:
2853
# Updated server verb that locks remotely.
2854
repo_lock_token = response[10] or None
2855
remote_repo.lock_write(repo_lock_token, _skip_rpc=True)
2857
remote_repo.dont_leave_lock_in_place()
2859
remote_repo.lock_write()
2860
policy = UseExistingRepository(remote_repo, final_stack,
2861
final_stack_pwd, require_stacking)
2862
policy.acquire_repository()
2866
bzrdir._format.set_branch_format(self.get_branch_format())
2867
if require_stacking:
2868
# The repo has already been created, but we need to make sure that
2869
# we'll make a stackable branch.
2870
bzrdir._format.require_stacking(_skip_repo=True)
2871
return remote_repo, bzrdir, require_stacking, policy
2873
def _open(self, transport):
2874
return remote.RemoteBzrDir(transport, self)
2876
def __eq__(self, other):
2877
if not isinstance(other, RemoteBzrDirFormat):
2879
return self.get_format_description() == other.get_format_description()
2881
def __return_repository_format(self):
2882
# Always return a RemoteRepositoryFormat object, but if a specific bzr
2883
# repository format has been asked for, tell the RemoteRepositoryFormat
2884
# that it should use that for init() etc.
2885
result = remote.RemoteRepositoryFormat()
2886
custom_format = getattr(self, '_repository_format', None)
2888
if isinstance(custom_format, remote.RemoteRepositoryFormat):
2889
return custom_format
2891
# We will use the custom format to create repositories over the
2892
# wire; expose its details like rich_root_data for code to
2894
result._custom_format = custom_format
2897
def get_branch_format(self):
2898
result = BzrDirMetaFormat1.get_branch_format(self)
2899
if not isinstance(result, remote.RemoteBranchFormat):
2900
new_result = remote.RemoteBranchFormat()
2901
new_result._custom_format = result
2903
self.set_branch_format(new_result)
2907
repository_format = property(__return_repository_format,
2908
BzrDirMetaFormat1._set_repository_format) #.im_func)
2911
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
2914
class RepositoryAcquisitionPolicy(object):
2915
"""Abstract base class for repository acquisition policies.
2917
A repository acquisition policy decides how a BzrDir acquires a repository
2918
for a branch that is being created. The most basic policy decision is
2919
whether to create a new repository or use an existing one.
2921
def __init__(self, stack_on, stack_on_pwd, require_stacking):
2924
:param stack_on: A location to stack on
2925
:param stack_on_pwd: If stack_on is relative, the location it is
2927
:param require_stacking: If True, it is a failure to not stack.
2929
self._stack_on = stack_on
2930
self._stack_on_pwd = stack_on_pwd
2931
self._require_stacking = require_stacking
2933
def configure_branch(self, branch):
2934
"""Apply any configuration data from this policy to the branch.
2936
Default implementation sets repository stacking.
2938
if self._stack_on is None:
2940
if self._stack_on_pwd is None:
2941
stack_on = self._stack_on
2944
stack_on = urlutils.rebase_url(self._stack_on,
2947
except errors.InvalidRebaseURLs:
2948
stack_on = self._get_full_stack_on()
2950
branch.set_stacked_on_url(stack_on)
2951
except (errors.UnstackableBranchFormat,
2952
errors.UnstackableRepositoryFormat):
2953
if self._require_stacking:
2956
def requires_stacking(self):
2957
"""Return True if this policy requires stacking."""
2958
return self._stack_on is not None and self._require_stacking
2960
def _get_full_stack_on(self):
2961
"""Get a fully-qualified URL for the stack_on location."""
2962
if self._stack_on is None:
2964
if self._stack_on_pwd is None:
2965
return self._stack_on
2967
return urlutils.join(self._stack_on_pwd, self._stack_on)
2969
def _add_fallback(self, repository, possible_transports=None):
2970
"""Add a fallback to the supplied repository, if stacking is set."""
2971
stack_on = self._get_full_stack_on()
2972
if stack_on is None:
2975
stacked_dir = BzrDir.open(stack_on,
2976
possible_transports=possible_transports)
2977
except errors.JailBreak:
2978
# We keep the stacking details, but we are in the server code so
2979
# actually stacking is not needed.
2982
stacked_repo = stacked_dir.open_branch().repository
2983
except errors.NotBranchError:
2984
stacked_repo = stacked_dir.open_repository()
2986
repository.add_fallback_repository(stacked_repo)
2987
except errors.UnstackableRepositoryFormat:
2988
if self._require_stacking:
2991
self._require_stacking = True
2993
def acquire_repository(self, make_working_trees=None, shared=False):
2994
"""Acquire a repository for this bzrdir.
2996
Implementations may create a new repository or use a pre-exising
2998
:param make_working_trees: If creating a repository, set
2999
make_working_trees to this value (if non-None)
3000
:param shared: If creating a repository, make it shared if True
3001
:return: A repository, is_new_flag (True if the repository was
3004
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
3007
class CreateRepository(RepositoryAcquisitionPolicy):
3008
"""A policy of creating a new repository"""
3010
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
3011
require_stacking=False):
3014
:param bzrdir: The bzrdir to create the repository on.
3015
:param stack_on: A location to stack on
3016
:param stack_on_pwd: If stack_on is relative, the location it is
3019
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3021
self._bzrdir = bzrdir
3023
def acquire_repository(self, make_working_trees=None, shared=False):
3024
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3026
Creates the desired repository in the bzrdir we already have.
3028
stack_on = self._get_full_stack_on()
3030
format = self._bzrdir._format
3031
format.require_stacking(stack_on=stack_on,
3032
possible_transports=[self._bzrdir.root_transport])
3033
if not self._require_stacking:
3034
# We have picked up automatic stacking somewhere.
3035
note('Using default stacking branch %s at %s', self._stack_on,
3037
repository = self._bzrdir.create_repository(shared=shared)
3038
self._add_fallback(repository,
3039
possible_transports=[self._bzrdir.transport])
3040
if make_working_trees is not None:
3041
repository.set_make_working_trees(make_working_trees)
3042
return repository, True
3045
class UseExistingRepository(RepositoryAcquisitionPolicy):
3046
"""A policy of reusing an existing repository"""
3048
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
3049
require_stacking=False):
3052
:param repository: The repository to use.
3053
:param stack_on: A location to stack on
3054
:param stack_on_pwd: If stack_on is relative, the location it is
3057
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
3059
self._repository = repository
3061
def acquire_repository(self, make_working_trees=None, shared=False):
3062
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
3064
Returns an existing repository to use.
3066
self._add_fallback(self._repository,
3067
possible_transports=[self._repository.bzrdir.transport])
3068
return self._repository, False
3071
def register_metadir(registry, key,
3072
repository_format, help, native=True, deprecated=False,
3078
"""Register a metadir subformat.
3080
These all use a BzrDirMetaFormat1 bzrdir, but can be parameterized
3081
by the Repository/Branch/WorkingTreeformats.
3083
:param repository_format: The fully-qualified repository format class
3085
:param branch_format: Fully-qualified branch format class name as
3087
:param tree_format: Fully-qualified tree format class name as
3090
# This should be expanded to support setting WorkingTree and Branch
3091
# formats, once BzrDirMetaFormat1 supports that.
3092
def _load(full_name):
3093
mod_name, factory_name = full_name.rsplit('.', 1)
3095
mod = __import__(mod_name, globals(), locals(),
3097
except ImportError, e:
3098
raise ImportError('failed to load %s: %s' % (full_name, e))
3100
factory = getattr(mod, factory_name)
3101
except AttributeError:
3102
raise AttributeError('no factory %s in module %r'
3107
bd = BzrDirMetaFormat1()
3108
if branch_format is not None:
3109
bd.set_branch_format(_load(branch_format))
3110
if tree_format is not None:
3111
bd.workingtree_format = _load(tree_format)
3112
if repository_format is not None:
3113
bd.repository_format = _load(repository_format)
3115
registry.register(key, helper, help, native, deprecated, hidden,
3116
experimental, alias)
3118
# The pre-0.8 formats have their repository format network name registered in
3119
# repository.py. MetaDir formats have their repository format network name
3120
# inferred from their disk format string.
3121
controldir.format_registry.register('weave', BzrDirFormat6,
3122
'Pre-0.8 format. Slower than knit and does not'
3123
' support checkouts or shared repositories.',
3126
register_metadir(controldir.format_registry, 'metaweave',
3127
'bzrlib.repofmt.weaverepo.RepositoryFormat7',
3128
'Transitional format in 0.8. Slower than knit.',
3129
branch_format='bzrlib.branch.BzrBranchFormat5',
3130
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3133
register_metadir(controldir.format_registry, 'knit',
3134
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3135
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
3136
branch_format='bzrlib.branch.BzrBranchFormat5',
3137
tree_format='bzrlib.workingtree.WorkingTreeFormat3',
3140
register_metadir(controldir.format_registry, 'dirstate',
3141
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3142
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
3143
'above when accessed over the network.',
3144
branch_format='bzrlib.branch.BzrBranchFormat5',
3145
# this uses bzrlib.workingtree.WorkingTreeFormat4 because importing
3146
# directly from workingtree_4 triggers a circular import.
3147
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3150
register_metadir(controldir.format_registry, 'dirstate-tags',
3151
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
3152
help='New in 0.15: Fast local operations and improved scaling for '
3153
'network operations. Additionally adds support for tags.'
3154
' Incompatible with bzr < 0.15.',
3155
branch_format='bzrlib.branch.BzrBranchFormat6',
3156
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3159
register_metadir(controldir.format_registry, 'rich-root',
3160
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
3161
help='New in 1.0. Better handling of tree roots. Incompatible with'
3163
branch_format='bzrlib.branch.BzrBranchFormat6',
3164
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3167
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
3168
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
3169
help='New in 0.15: Fast local operations and improved scaling for '
3170
'network operations. Additionally adds support for versioning nested '
3171
'bzr branches. Incompatible with bzr < 0.15.',
3172
branch_format='bzrlib.branch.BzrBranchFormat6',
3173
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3177
register_metadir(controldir.format_registry, 'pack-0.92',
3178
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack1',
3179
help='New in 0.92: Pack-based format with data compatible with '
3180
'dirstate-tags format repositories. Interoperates with '
3181
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3183
branch_format='bzrlib.branch.BzrBranchFormat6',
3184
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3186
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
3187
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack3',
3188
help='New in 0.92: Pack-based format with data compatible with '
3189
'dirstate-with-subtree format repositories. Interoperates with '
3190
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
3192
branch_format='bzrlib.branch.BzrBranchFormat6',
3193
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3197
register_metadir(controldir.format_registry, 'rich-root-pack',
3198
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack4',
3199
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
3200
'(needed for bzr-svn and bzr-git).',
3201
branch_format='bzrlib.branch.BzrBranchFormat6',
3202
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3205
register_metadir(controldir.format_registry, '1.6',
3206
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5',
3207
help='A format that allows a branch to indicate that there is another '
3208
'(stacked) repository that should be used to access data that is '
3209
'not present locally.',
3210
branch_format='bzrlib.branch.BzrBranchFormat7',
3211
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3214
register_metadir(controldir.format_registry, '1.6.1-rich-root',
3215
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack5RichRoot',
3216
help='A variant of 1.6 that supports rich-root data '
3217
'(needed for bzr-svn and bzr-git).',
3218
branch_format='bzrlib.branch.BzrBranchFormat7',
3219
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3222
register_metadir(controldir.format_registry, '1.9',
3223
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3224
help='A repository format using B+tree indexes. These indexes '
3225
'are smaller in size, have smarter caching and provide faster '
3226
'performance for most operations.',
3227
branch_format='bzrlib.branch.BzrBranchFormat7',
3228
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3231
register_metadir(controldir.format_registry, '1.9-rich-root',
3232
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3233
help='A variant of 1.9 that supports rich-root data '
3234
'(needed for bzr-svn and bzr-git).',
3235
branch_format='bzrlib.branch.BzrBranchFormat7',
3236
tree_format='bzrlib.workingtree.WorkingTreeFormat4',
3239
register_metadir(controldir.format_registry, '1.14',
3240
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6',
3241
help='A working-tree format that supports content filtering.',
3242
branch_format='bzrlib.branch.BzrBranchFormat7',
3243
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3245
register_metadir(controldir.format_registry, '1.14-rich-root',
3246
'bzrlib.repofmt.pack_repo.RepositoryFormatKnitPack6RichRoot',
3247
help='A variant of 1.14 that supports rich-root data '
3248
'(needed for bzr-svn and bzr-git).',
3249
branch_format='bzrlib.branch.BzrBranchFormat7',
3250
tree_format='bzrlib.workingtree.WorkingTreeFormat5',
3252
# The following un-numbered 'development' formats should always just be aliases.
3253
register_metadir(controldir.format_registry, 'development-rich-root',
3254
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3255
help='Current development format. Supports rich roots. Can convert data '
3256
'to and from rich-root-pack (and anything compatible with '
3257
'rich-root-pack) format repositories. Repositories and branches in '
3258
'this format can only be read by bzr.dev. Please read '
3259
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3261
branch_format='bzrlib.branch.BzrBranchFormat7',
3262
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3267
register_metadir(controldir.format_registry, 'development5-subtree',
3268
'bzrlib.repofmt.pack_repo.RepositoryFormatPackDevelopment2Subtree',
3269
help='Development format, subtree variant. Can convert data to and '
3270
'from pack-0.92-subtree (and anything compatible with '
3271
'pack-0.92-subtree) format repositories. Repositories and branches in '
3272
'this format can only be read by bzr.dev. Please read '
3273
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3275
branch_format='bzrlib.branch.BzrBranchFormat7',
3276
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3283
register_metadir(controldir.format_registry, 'development-subtree',
3284
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
3285
help='Current development format, subtree variant. Can convert data to and '
3286
'from pack-0.92-subtree (and anything compatible with '
3287
'pack-0.92-subtree) format repositories. Repositories and branches in '
3288
'this format can only be read by bzr.dev. Please read '
3289
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3291
branch_format='bzrlib.branch.BzrBranchFormat7',
3292
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3295
alias=False, # Restore to being an alias when an actual development subtree format is added
3296
# This current non-alias status is simply because we did not introduce a
3297
# chk based subtree format.
3300
# And the development formats above will have aliased one of the following:
3301
register_metadir(controldir.format_registry, 'development6-rich-root',
3302
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK1',
3303
help='pack-1.9 with 255-way hashed CHK inv, group compress, rich roots '
3305
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3307
branch_format='bzrlib.branch.BzrBranchFormat7',
3308
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3313
register_metadir(controldir.format_registry, 'development7-rich-root',
3314
'bzrlib.repofmt.groupcompress_repo.RepositoryFormatCHK2',
3315
help='pack-1.9 with 255-way hashed CHK inv, bencode revision, group compress, '
3316
'rich roots. Please read '
3317
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
3319
branch_format='bzrlib.branch.BzrBranchFormat7',
3320
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3325
register_metadir(controldir.format_registry, '2a',
3326
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3327
help='First format for bzr 2.0 series.\n'
3328
'Uses group-compress storage.\n'
3329
'Provides rich roots which are a one-way transition.\n',
3330
# 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
3331
# 'rich roots. Supported by bzr 1.16 and later.',
3332
branch_format='bzrlib.branch.BzrBranchFormat7',
3333
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3337
# The following format should be an alias for the rich root equivalent
3338
# of the default format
3339
register_metadir(controldir.format_registry, 'default-rich-root',
3340
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
3341
branch_format='bzrlib.branch.BzrBranchFormat7',
3342
tree_format='bzrlib.workingtree.WorkingTreeFormat6',
3347
# The current format that is made on 'bzr init'.
3348
controldir.format_registry.set_default('2a')
3350
# XXX 2010-08-20 JRV: There is still a lot of code relying on
3351
# bzrlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc
3352
# get changed to ControlDir.create/ControlDir.open/etc this should be removed.
3353
format_registry = controldir.format_registry