1
# Copyright (C) 2006-2011 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
30
from bzrlib.lazy_import import lazy_import
31
lazy_import(globals(), """
34
branch as _mod_branch,
45
revision as _mod_revision,
46
transport as _mod_transport,
53
from bzrlib.repofmt import knitpack_repo
54
from bzrlib.transport import (
55
do_catching_redirections,
58
from bzrlib.i18n import gettext
61
from bzrlib.trace import (
71
from bzrlib.symbol_versioning import (
77
class BzrDir(controldir.ControlDir):
78
"""A .bzr control diretory.
80
BzrDir instances let you create or open any of the things that can be
81
found within .bzr - checkouts, branches and repositories.
84
the transport which this bzr dir is rooted at (i.e. file:///.../.bzr/)
86
a transport connected to the directory this bzr was opened from
87
(i.e. the parent directory holding the .bzr directory).
89
Everything in the bzrdir should have the same file permissions.
91
:cvar hooks: An instance of BzrDirHooks.
95
"""Invoke break_lock on the first object in the bzrdir.
97
If there is a tree, the tree is opened and break_lock() called.
98
Otherwise, branch is tried, and finally repository.
100
# XXX: This seems more like a UI function than something that really
101
# belongs in this class.
103
thing_to_unlock = self.open_workingtree()
104
except (errors.NotLocalUrl, errors.NoWorkingTree):
106
thing_to_unlock = self.open_branch()
107
except errors.NotBranchError:
109
thing_to_unlock = self.open_repository()
110
except errors.NoRepositoryPresent:
112
thing_to_unlock.break_lock()
114
def check_conversion_target(self, target_format):
115
"""Check that a bzrdir as a whole can be converted to a new format."""
116
# The only current restriction is that the repository content can be
117
# fetched compatibly with the target.
118
target_repo_format = target_format.repository_format
120
self.open_repository()._format.check_conversion_target(
122
except errors.NoRepositoryPresent:
123
# No repo, no problem.
126
def clone_on_transport(self, transport, revision_id=None,
127
force_new_repo=False, preserve_stacking=False, stacked_on=None,
128
create_prefix=False, use_existing_dir=True, no_tree=False):
129
"""Clone this bzrdir and its contents to transport verbatim.
131
:param transport: The transport for the location to produce the clone
132
at. If the target directory does not exist, it will be created.
133
:param revision_id: The tip revision-id to use for any branch or
134
working tree. If not None, then the clone operation may tune
135
itself to download less data.
136
:param force_new_repo: Do not use a shared repository for the target,
137
even if one is available.
138
:param preserve_stacking: When cloning a stacked branch, stack the
139
new branch on top of the other branch's stacked-on branch.
140
:param create_prefix: Create any missing directories leading up to
142
:param use_existing_dir: Use an existing directory if one exists.
143
:param no_tree: If set to true prevents creation of a working tree.
145
# Overview: put together a broad description of what we want to end up
146
# with; then make as few api calls as possible to do it.
148
# We may want to create a repo/branch/tree, if we do so what format
149
# would we want for each:
150
require_stacking = (stacked_on is not None)
151
format = self.cloning_metadir(require_stacking)
153
# Figure out what objects we want:
155
local_repo = self.find_repository()
156
except errors.NoRepositoryPresent:
159
local_branch = self.open_branch()
160
except errors.NotBranchError:
163
# enable fallbacks when branch is not a branch reference
164
if local_branch.repository.has_same_location(local_repo):
165
local_repo = local_branch.repository
166
if preserve_stacking:
168
stacked_on = local_branch.get_stacked_on_url()
169
except (errors.UnstackableBranchFormat,
170
errors.UnstackableRepositoryFormat,
173
# Bug: We create a metadir without knowing if it can support stacking,
174
# we should look up the policy needs first, or just use it as a hint,
177
make_working_trees = local_repo.make_working_trees() and not no_tree
178
want_shared = local_repo.is_shared()
179
repo_format_name = format.repository_format.network_name()
181
make_working_trees = False
183
repo_format_name = None
185
result_repo, result, require_stacking, repository_policy = \
186
format.initialize_on_transport_ex(transport,
187
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
188
force_new_repo=force_new_repo, stacked_on=stacked_on,
189
stack_on_pwd=self.root_transport.base,
190
repo_format_name=repo_format_name,
191
make_working_trees=make_working_trees, shared_repo=want_shared)
194
# If the result repository is in the same place as the
195
# resulting bzr dir, it will have no content, further if the
196
# result is not stacked then we know all content should be
197
# copied, and finally if we are copying up to a specific
198
# revision_id then we can use the pending-ancestry-result which
199
# does not require traversing all of history to describe it.
200
if (result_repo.user_url == result.user_url
201
and not require_stacking and
202
revision_id is not None):
203
fetch_spec = graph.PendingAncestryResult(
204
[revision_id], local_repo)
205
result_repo.fetch(local_repo, fetch_spec=fetch_spec)
207
result_repo.fetch(local_repo, revision_id=revision_id)
211
if result_repo is not None:
212
raise AssertionError('result_repo not None(%r)' % result_repo)
213
# 1 if there is a branch present
214
# make sure its content is available in the target repository
216
if local_branch is not None:
217
result_branch = local_branch.clone(result, revision_id=revision_id,
218
repository_policy=repository_policy)
220
# Cheaper to check if the target is not local, than to try making
222
result.root_transport.local_abspath('.')
223
if result_repo is None or result_repo.make_working_trees():
224
self.open_workingtree().clone(result, revision_id=revision_id)
225
except (errors.NoWorkingTree, errors.NotLocalUrl):
229
# TODO: This should be given a Transport, and should chdir up; otherwise
230
# this will open a new connection.
231
def _make_tail(self, url):
232
t = _mod_transport.get_transport(url)
235
def determine_repository_policy(self, force_new_repo=False, stack_on=None,
236
stack_on_pwd=None, require_stacking=False):
237
"""Return an object representing a policy to use.
239
This controls whether a new repository is created, and the format of
240
that repository, or some existing shared repository used instead.
242
If stack_on is supplied, will not seek a containing shared repo.
244
:param force_new_repo: If True, require a new repository to be created.
245
:param stack_on: If supplied, the location to stack on. If not
246
supplied, a default_stack_on location may be used.
247
:param stack_on_pwd: If stack_on is relative, the location it is
250
def repository_policy(found_bzrdir):
253
config = found_bzrdir.get_config()
255
stack_on = config.get_default_stack_on()
256
if stack_on is not None:
257
stack_on_pwd = found_bzrdir.user_url
259
# does it have a repository ?
261
repository = found_bzrdir.open_repository()
262
except errors.NoRepositoryPresent:
265
if (found_bzrdir.user_url != self.user_url
266
and not repository.is_shared()):
267
# Don't look higher, can't use a higher shared repo.
275
return UseExistingRepository(repository, stack_on,
276
stack_on_pwd, require_stacking=require_stacking), True
278
return CreateRepository(self, stack_on, stack_on_pwd,
279
require_stacking=require_stacking), True
281
if not force_new_repo:
283
policy = self._find_containing(repository_policy)
284
if policy is not None:
288
return UseExistingRepository(self.open_repository(),
289
stack_on, stack_on_pwd,
290
require_stacking=require_stacking)
291
except errors.NoRepositoryPresent:
293
return CreateRepository(self, stack_on, stack_on_pwd,
294
require_stacking=require_stacking)
296
def _find_or_create_repository(self, force_new_repo):
297
"""Create a new repository if needed, returning the repository."""
298
policy = self.determine_repository_policy(force_new_repo)
299
return policy.acquire_repository()[0]
301
def _find_source_repo(self, add_cleanup, source_branch):
302
"""Find the source branch and repo for a sprout operation.
304
This is helper intended for use by _sprout.
306
:returns: (source_branch, source_repository). Either or both may be
307
None. If not None, they will be read-locked (and their unlock(s)
308
scheduled via the add_cleanup param).
310
if source_branch is not None:
311
add_cleanup(source_branch.lock_read().unlock)
312
return source_branch, source_branch.repository
314
source_branch = self.open_branch()
315
source_repository = source_branch.repository
316
except errors.NotBranchError:
319
source_repository = self.open_repository()
320
except errors.NoRepositoryPresent:
321
source_repository = None
323
add_cleanup(source_repository.lock_read().unlock)
325
add_cleanup(source_branch.lock_read().unlock)
326
return source_branch, source_repository
328
def sprout(self, url, revision_id=None, force_new_repo=False,
329
recurse='down', possible_transports=None,
330
accelerator_tree=None, hardlink=False, stacked=False,
331
source_branch=None, create_tree_if_local=True):
332
"""Create a copy of this controldir prepared for use as a new line of
335
If url's last component does not exist, it will be created.
337
Attributes related to the identity of the source branch like
338
branch nickname will be cleaned, a working tree is created
339
whether one existed before or not; and a local branch is always
342
if revision_id is not None, then the clone operation may tune
343
itself to download less data.
345
:param accelerator_tree: A tree which can be used for retrieving file
346
contents more quickly than the revision tree, i.e. a workingtree.
347
The revision tree will be used for cases where accelerator_tree's
348
content is different.
349
:param hardlink: If true, hard-link files from accelerator_tree,
351
:param stacked: If true, create a stacked branch referring to the
352
location of this control directory.
353
:param create_tree_if_local: If true, a working-tree will be created
354
when working locally.
356
operation = cleanup.OperationWithCleanups(self._sprout)
357
return operation.run(url, revision_id=revision_id,
358
force_new_repo=force_new_repo, recurse=recurse,
359
possible_transports=possible_transports,
360
accelerator_tree=accelerator_tree, hardlink=hardlink,
361
stacked=stacked, source_branch=source_branch,
362
create_tree_if_local=create_tree_if_local)
364
def _sprout(self, op, url, revision_id=None, force_new_repo=False,
365
recurse='down', possible_transports=None,
366
accelerator_tree=None, hardlink=False, stacked=False,
367
source_branch=None, create_tree_if_local=True):
368
add_cleanup = op.add_cleanup
369
fetch_spec_factory = fetch.FetchSpecFactory()
370
if revision_id is not None:
371
fetch_spec_factory.add_revision_ids([revision_id])
372
fetch_spec_factory.source_branch_stop_revision_id = revision_id
373
target_transport = _mod_transport.get_transport(url,
375
target_transport.ensure_base()
376
cloning_format = self.cloning_metadir(stacked)
377
# Create/update the result branch
378
result = cloning_format.initialize_on_transport(target_transport)
379
source_branch, source_repository = self._find_source_repo(
380
add_cleanup, source_branch)
381
fetch_spec_factory.source_branch = source_branch
382
# if a stacked branch wasn't requested, we don't create one
383
# even if the origin was stacked
384
if stacked and source_branch is not None:
385
stacked_branch_url = self.root_transport.base
387
stacked_branch_url = None
388
repository_policy = result.determine_repository_policy(
389
force_new_repo, stacked_branch_url, require_stacking=stacked)
390
result_repo, is_new_repo = repository_policy.acquire_repository()
391
add_cleanup(result_repo.lock_write().unlock)
392
fetch_spec_factory.source_repo = source_repository
393
fetch_spec_factory.target_repo = result_repo
394
if stacked or (len(result_repo._fallback_repositories) != 0):
395
target_repo_kind = fetch.TargetRepoKinds.STACKED
397
target_repo_kind = fetch.TargetRepoKinds.EMPTY
399
target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
400
fetch_spec_factory.target_repo_kind = target_repo_kind
401
if source_repository is not None:
402
fetch_spec = fetch_spec_factory.make_fetch_spec()
403
result_repo.fetch(source_repository, fetch_spec=fetch_spec)
405
if source_branch is None:
406
# this is for sprouting a controldir without a branch; is that
408
# Not especially, but it's part of the contract.
409
result_branch = result.create_branch()
411
result_branch = source_branch.sprout(result,
412
revision_id=revision_id, repository_policy=repository_policy,
413
repository=result_repo)
414
mutter("created new branch %r" % (result_branch,))
416
# Create/update the result working tree
417
if (create_tree_if_local and
418
isinstance(target_transport, local.LocalTransport) and
419
(result_repo is None or result_repo.make_working_trees())):
420
wt = result.create_workingtree(accelerator_tree=accelerator_tree,
421
hardlink=hardlink, from_branch=result_branch)
424
if wt.path2id('') is None:
426
wt.set_root_id(self.open_workingtree.get_root_id())
427
except errors.NoWorkingTree:
433
if recurse == 'down':
436
basis = wt.basis_tree()
437
elif result_branch is not None:
438
basis = result_branch.basis_tree()
439
elif source_branch is not None:
440
basis = source_branch.basis_tree()
441
if basis is not None:
442
add_cleanup(basis.lock_read().unlock)
443
subtrees = basis.iter_references()
446
for path, file_id in subtrees:
447
target = urlutils.join(url, urlutils.escape(path))
448
sublocation = source_branch.reference_parent(file_id, path)
449
sublocation.bzrdir.sprout(target,
450
basis.get_reference_revision(file_id, path),
451
force_new_repo=force_new_repo, recurse=recurse,
455
@deprecated_method(deprecated_in((2, 3, 0)))
456
def generate_backup_name(self, base):
457
return self._available_backup_name(base)
459
def _available_backup_name(self, base):
460
"""Find a non-existing backup file name based on base.
462
See bzrlib.osutils.available_backup_name about race conditions.
464
return osutils.available_backup_name(base, self.root_transport.has)
466
def backup_bzrdir(self):
467
"""Backup this bzr control directory.
469
:return: Tuple with old path name and new path name
472
pb = ui.ui_factory.nested_progress_bar()
474
old_path = self.root_transport.abspath('.bzr')
475
backup_dir = self._available_backup_name('backup.bzr')
476
new_path = self.root_transport.abspath(backup_dir)
477
ui.ui_factory.note(gettext('making backup of {0}\n to {1}').format(
478
urlutils.unescape_for_display(old_path, 'utf-8'),
479
urlutils.unescape_for_display(new_path, 'utf-8')))
480
self.root_transport.copy_tree('.bzr', backup_dir)
481
return (old_path, new_path)
485
def retire_bzrdir(self, limit=10000):
486
"""Permanently disable the bzrdir.
488
This is done by renaming it to give the user some ability to recover
489
if there was a problem.
491
This will have horrible consequences if anyone has anything locked or
493
:param limit: number of times to retry
498
to_path = '.bzr.retired.%d' % i
499
self.root_transport.rename('.bzr', to_path)
500
note(gettext("renamed {0} to {1}").format(
501
self.root_transport.abspath('.bzr'), to_path))
503
except (errors.TransportError, IOError, errors.PathError):
510
def _find_containing(self, evaluate):
511
"""Find something in a containing control directory.
513
This method will scan containing control dirs, until it finds what
514
it is looking for, decides that it will never find it, or runs out
515
of containing control directories to check.
517
It is used to implement find_repository and
518
determine_repository_policy.
520
:param evaluate: A function returning (value, stop). If stop is True,
521
the value will be returned.
525
result, stop = evaluate(found_bzrdir)
528
next_transport = found_bzrdir.root_transport.clone('..')
529
if (found_bzrdir.user_url == next_transport.base):
530
# top of the file system
532
# find the next containing bzrdir
534
found_bzrdir = self.open_containing_from_transport(
536
except errors.NotBranchError:
539
def find_repository(self):
540
"""Find the repository that should be used.
542
This does not require a branch as we use it to find the repo for
543
new branches as well as to hook existing branches up to their
546
def usable_repository(found_bzrdir):
547
# does it have a repository ?
549
repository = found_bzrdir.open_repository()
550
except errors.NoRepositoryPresent:
552
if found_bzrdir.user_url == self.user_url:
553
return repository, True
554
elif repository.is_shared():
555
return repository, True
559
found_repo = self._find_containing(usable_repository)
560
if found_repo is None:
561
raise errors.NoRepositoryPresent(self)
564
def _find_creation_modes(self):
565
"""Determine the appropriate modes for files and directories.
567
They're always set to be consistent with the base directory,
568
assuming that this transport allows setting modes.
570
# TODO: Do we need or want an option (maybe a config setting) to turn
571
# this off or override it for particular locations? -- mbp 20080512
572
if self._mode_check_done:
574
self._mode_check_done = True
576
st = self.transport.stat('.')
577
except errors.TransportNotPossible:
578
self._dir_mode = None
579
self._file_mode = None
581
# Check the directory mode, but also make sure the created
582
# directories and files are read-write for this user. This is
583
# mostly a workaround for filesystems which lie about being able to
584
# write to a directory (cygwin & win32)
585
if (st.st_mode & 07777 == 00000):
586
# FTP allows stat but does not return dir/file modes
587
self._dir_mode = None
588
self._file_mode = None
590
self._dir_mode = (st.st_mode & 07777) | 00700
591
# Remove the sticky and execute bits for files
592
self._file_mode = self._dir_mode & ~07111
594
def _get_file_mode(self):
595
"""Return Unix mode for newly created files, or None.
597
if not self._mode_check_done:
598
self._find_creation_modes()
599
return self._file_mode
601
def _get_dir_mode(self):
602
"""Return Unix mode for newly created directories, or None.
604
if not self._mode_check_done:
605
self._find_creation_modes()
606
return self._dir_mode
608
def get_config(self):
609
"""Get configuration for this BzrDir."""
610
return config.BzrDirConfig(self)
612
def _get_config(self):
613
"""By default, no configuration is available."""
616
def __init__(self, _transport, _format):
617
"""Initialize a Bzr control dir object.
619
Only really common logic should reside here, concrete classes should be
620
made with varying behaviours.
622
:param _format: the format that is creating this BzrDir instance.
623
:param _transport: the transport this dir is based at.
625
self._format = _format
626
# these are also under the more standard names of
627
# control_transport and user_transport
628
self.transport = _transport.clone('.bzr')
629
self.root_transport = _transport
630
self._mode_check_done = False
633
def user_transport(self):
634
return self.root_transport
637
def control_transport(self):
638
return self.transport
640
def is_control_filename(self, filename):
641
"""True if filename is the name of a path which is reserved for bzrdir's.
643
:param filename: A filename within the root transport of this bzrdir.
645
This is true IF and ONLY IF the filename is part of the namespace reserved
646
for bzr control dirs. Currently this is the '.bzr' directory in the root
647
of the root_transport.
649
# this might be better on the BzrDirFormat class because it refers to
650
# all the possible bzrdir disk formats.
651
# This method is tested via the workingtree is_control_filename tests-
652
# it was extracted from WorkingTree.is_control_filename. If the method's
653
# contract is extended beyond the current trivial implementation, please
654
# add new tests for it to the appropriate place.
655
return filename == '.bzr' or filename.startswith('.bzr/')
657
def _cloning_metadir(self):
658
"""Produce a metadir suitable for cloning with.
660
:returns: (destination_bzrdir_format, source_repository)
662
result_format = self._format.__class__()
665
branch = self.open_branch(ignore_fallbacks=True)
666
source_repository = branch.repository
667
result_format._branch_format = branch._format
668
except errors.NotBranchError:
670
source_repository = self.open_repository()
671
except errors.NoRepositoryPresent:
672
source_repository = None
674
# XXX TODO: This isinstance is here because we have not implemented
675
# the fix recommended in bug # 103195 - to delegate this choice the
677
repo_format = source_repository._format
678
if isinstance(repo_format, remote.RemoteRepositoryFormat):
679
source_repository._ensure_real()
680
repo_format = source_repository._real_repository._format
681
result_format.repository_format = repo_format
683
# TODO: Couldn't we just probe for the format in these cases,
684
# rather than opening the whole tree? It would be a little
685
# faster. mbp 20070401
686
tree = self.open_workingtree(recommend_upgrade=False)
687
except (errors.NoWorkingTree, errors.NotLocalUrl):
688
result_format.workingtree_format = None
690
result_format.workingtree_format = tree._format.__class__()
691
return result_format, source_repository
693
def cloning_metadir(self, require_stacking=False):
694
"""Produce a metadir suitable for cloning or sprouting with.
696
These operations may produce workingtrees (yes, even though they're
697
"cloning" something that doesn't have a tree), so a viable workingtree
698
format must be selected.
700
:require_stacking: If True, non-stackable formats will be upgraded
701
to similar stackable formats.
702
:returns: a ControlDirFormat with all component formats either set
703
appropriately or set to None if that component should not be
706
format, repository = self._cloning_metadir()
707
if format._workingtree_format is None:
709
if repository is None:
710
# No repository either
712
# We have a repository, so set a working tree? (Why? This seems to
713
# contradict the stated return value in the docstring).
714
tree_format = repository._format._matchingbzrdir.workingtree_format
715
format.workingtree_format = tree_format.__class__()
717
format.require_stacking()
720
def get_branch_transport(self, branch_format, name=None):
721
"""Get the transport for use by branch format in this BzrDir.
723
Note that bzr dirs that do not support format strings will raise
724
IncompatibleFormat if the branch format they are given has
725
a format string, and vice versa.
727
If branch_format is None, the transport is returned with no
728
checking. If it is not None, then the returned transport is
729
guaranteed to point to an existing directory ready for use.
731
raise NotImplementedError(self.get_branch_transport)
733
def get_repository_transport(self, repository_format):
734
"""Get the transport for use by repository format in this BzrDir.
736
Note that bzr dirs that do not support format strings will raise
737
IncompatibleFormat if the repository format they are given has
738
a format string, and vice versa.
740
If repository_format is None, the transport is returned with no
741
checking. If it is not None, then the returned transport is
742
guaranteed to point to an existing directory ready for use.
744
raise NotImplementedError(self.get_repository_transport)
746
def get_workingtree_transport(self, tree_format):
747
"""Get the transport for use by workingtree format in this BzrDir.
749
Note that bzr dirs that do not support format strings will raise
750
IncompatibleFormat if the workingtree format they are given has a
751
format string, and vice versa.
753
If workingtree_format is None, the transport is returned with no
754
checking. If it is not None, then the returned transport is
755
guaranteed to point to an existing directory ready for use.
757
raise NotImplementedError(self.get_workingtree_transport)
760
def create(cls, base, format=None, possible_transports=None):
761
"""Create a new BzrDir at the url 'base'.
763
:param format: If supplied, the format of branch to create. If not
764
supplied, the default is used.
765
:param possible_transports: If supplied, a list of transports that
766
can be reused to share a remote connection.
768
if cls is not BzrDir:
769
raise AssertionError("BzrDir.create always creates the "
770
"default format, not one of %r" % cls)
771
return controldir.ControlDir.create(base, format=format,
772
possible_transports=possible_transports)
775
class BzrDirMeta1(BzrDir):
776
"""A .bzr meta version 1 control object.
778
This is the first control object where the
779
individual aspects are really split out: there are separate repository,
780
workingtree and branch subdirectories and any subset of the three can be
781
present within a BzrDir.
784
def can_convert_format(self):
785
"""See BzrDir.can_convert_format()."""
788
def create_branch(self, name=None, repository=None,
789
append_revisions_only=None):
790
"""See BzrDir.create_branch."""
791
return self._format.get_branch_format().initialize(self, name=name,
792
repository=repository,
793
append_revisions_only=append_revisions_only)
795
def destroy_branch(self, name=None):
796
"""See BzrDir.create_branch."""
798
raise errors.NoColocatedBranchSupport(self)
799
self.transport.delete_tree('branch')
801
def create_repository(self, shared=False):
802
"""See BzrDir.create_repository."""
803
return self._format.repository_format.initialize(self, shared)
805
def destroy_repository(self):
806
"""See BzrDir.destroy_repository."""
807
self.transport.delete_tree('repository')
809
def create_workingtree(self, revision_id=None, from_branch=None,
810
accelerator_tree=None, hardlink=False):
811
"""See BzrDir.create_workingtree."""
812
return self._format.workingtree_format.initialize(
813
self, revision_id, from_branch=from_branch,
814
accelerator_tree=accelerator_tree, hardlink=hardlink)
816
def destroy_workingtree(self):
817
"""See BzrDir.destroy_workingtree."""
818
wt = self.open_workingtree(recommend_upgrade=False)
819
repository = wt.branch.repository
820
empty = repository.revision_tree(_mod_revision.NULL_REVISION)
821
# We ignore the conflicts returned by wt.revert since we're about to
822
# delete the wt metadata anyway, all that should be left here are
823
# detritus. But see bug #634470 about subtree .bzr dirs.
824
conflicts = wt.revert(old_tree=empty)
825
self.destroy_workingtree_metadata()
827
def destroy_workingtree_metadata(self):
828
self.transport.delete_tree('checkout')
830
def find_branch_format(self, name=None):
831
"""Find the branch 'format' for this bzrdir.
833
This might be a synthetic object for e.g. RemoteBranch and SVN.
835
from bzrlib.branch import BranchFormat
836
return BranchFormat.find_format(self, name=name)
838
def _get_mkdir_mode(self):
839
"""Figure out the mode to use when creating a bzrdir subdir."""
840
temp_control = lockable_files.LockableFiles(self.transport, '',
841
lockable_files.TransportLock)
842
return temp_control._dir_mode
844
def get_branch_reference(self, name=None):
845
"""See BzrDir.get_branch_reference()."""
846
from bzrlib.branch import BranchFormat
847
format = BranchFormat.find_format(self, name=name)
848
return format.get_reference(self, name=name)
850
def get_branch_transport(self, branch_format, name=None):
851
"""See BzrDir.get_branch_transport()."""
853
raise errors.NoColocatedBranchSupport(self)
854
# XXX: this shouldn't implicitly create the directory if it's just
855
# promising to get a transport -- mbp 20090727
856
if branch_format is None:
857
return self.transport.clone('branch')
859
branch_format.get_format_string()
860
except NotImplementedError:
861
raise errors.IncompatibleFormat(branch_format, self._format)
863
self.transport.mkdir('branch', mode=self._get_mkdir_mode())
864
except errors.FileExists:
866
return self.transport.clone('branch')
868
def get_repository_transport(self, repository_format):
869
"""See BzrDir.get_repository_transport()."""
870
if repository_format is None:
871
return self.transport.clone('repository')
873
repository_format.get_format_string()
874
except NotImplementedError:
875
raise errors.IncompatibleFormat(repository_format, self._format)
877
self.transport.mkdir('repository', mode=self._get_mkdir_mode())
878
except errors.FileExists:
880
return self.transport.clone('repository')
882
def get_workingtree_transport(self, workingtree_format):
883
"""See BzrDir.get_workingtree_transport()."""
884
if workingtree_format is None:
885
return self.transport.clone('checkout')
887
workingtree_format.get_format_string()
888
except NotImplementedError:
889
raise errors.IncompatibleFormat(workingtree_format, self._format)
891
self.transport.mkdir('checkout', mode=self._get_mkdir_mode())
892
except errors.FileExists:
894
return self.transport.clone('checkout')
896
def has_workingtree(self):
897
"""Tell if this bzrdir contains a working tree.
899
Note: if you're going to open the working tree, you should just go
900
ahead and try, and not ask permission first.
902
from bzrlib.workingtree import WorkingTreeFormat
904
WorkingTreeFormat.find_format_string(self)
905
except errors.NoWorkingTree:
909
def needs_format_conversion(self, format):
910
"""See BzrDir.needs_format_conversion()."""
911
if (not isinstance(self._format, format.__class__) or
912
self._format.get_format_string() != format.get_format_string()):
913
# it is not a meta dir format, conversion is needed.
915
# we might want to push this down to the repository?
917
if not isinstance(self.open_repository()._format,
918
format.repository_format.__class__):
919
# the repository needs an upgrade.
921
except errors.NoRepositoryPresent:
923
for branch in self.list_branches():
924
if not isinstance(branch._format,
925
format.get_branch_format().__class__):
926
# the branch needs an upgrade.
929
my_wt = self.open_workingtree(recommend_upgrade=False)
930
if not isinstance(my_wt._format,
931
format.workingtree_format.__class__):
932
# the workingtree needs an upgrade.
934
except (errors.NoWorkingTree, errors.NotLocalUrl):
938
def open_branch(self, name=None, unsupported=False,
939
ignore_fallbacks=False):
940
"""See BzrDir.open_branch."""
941
format = self.find_branch_format(name=name)
942
format.check_support_status(unsupported)
943
return format.open(self, name=name,
944
_found=True, ignore_fallbacks=ignore_fallbacks)
946
def open_repository(self, unsupported=False):
947
"""See BzrDir.open_repository."""
948
from bzrlib.repository import RepositoryFormat
949
format = RepositoryFormat.find_format(self)
950
format.check_support_status(unsupported)
951
return format.open(self, _found=True)
953
def open_workingtree(self, unsupported=False,
954
recommend_upgrade=True):
955
"""See BzrDir.open_workingtree."""
956
from bzrlib.workingtree import WorkingTreeFormat
957
format = WorkingTreeFormat.find_format(self)
958
format.check_support_status(unsupported, recommend_upgrade,
959
basedir=self.root_transport.base)
960
return format.open(self, _found=True)
962
def _get_config(self):
963
return config.TransportConfig(self.transport, 'control.conf')
966
class BzrDirMeta1Colo(BzrDirMeta1):
967
"""BzrDirMeta1 with support for colocated branches.
969
This format is experimental, and will eventually be merged back into
973
def __init__(self, _transport, _format):
974
super(BzrDirMeta1Colo, self).__init__(_transport, _format)
975
self.control_files = lockable_files.LockableFiles(self.control_transport,
976
self._format._lock_file_name, self._format._lock_class)
978
def _get_branch_path(self, name):
979
"""Obtain the branch path to use.
981
This uses the API specified branch name first, and then falls back to
982
the branch name specified in the URL. If neither of those is specified,
983
it uses the default branch.
985
:param name: Optional branch name to use
986
:return: Relative path to branch, branch name
989
name = self._get_selected_branch()
991
return 'branch', None
992
return urlutils.join('branches', name), name
994
def _read_branch_list(self):
995
"""Read the branch list.
997
:return: List of utf-8 encoded branch names.
1000
f = self.control_transport.get('branch-list')
1001
except errors.NoSuchFile:
1007
ret.append(name.rstrip("\n"))
1012
def _write_branch_list(self, branches):
1013
"""Write out the branch list.
1015
:param branches: List of utf-8 branch names to write
1017
self.transport.put_bytes('branch-list',
1018
"".join([name+"\n" for name in branches]))
1020
def destroy_branch(self, name=None):
1021
"""See BzrDir.create_branch."""
1022
path, name = self._get_branch_path(name)
1023
if name is not None:
1024
self.control_files.lock_write()
1026
branches = self._read_branch_list()
1028
branches.remove(name)
1030
raise errors.NotBranchError(name)
1031
self._write_branch_list(name)
1033
self.control_files.unlock()
1034
self.transport.delete_tree(path)
1036
def list_branches(self):
1037
"""See ControlDir.list_branches."""
1041
ret.append(self.open_branch())
1042
except (errors.NotBranchError, errors.NoRepositoryPresent):
1045
# colocated branches
1046
ret.extend([self.open_branch(name) for name in
1047
self._read_branch_list()])
1051
def get_branch_transport(self, branch_format, name=None):
1052
"""See BzrDir.get_branch_transport()."""
1053
path, name = self._get_branch_path(name)
1054
# XXX: this shouldn't implicitly create the directory if it's just
1055
# promising to get a transport -- mbp 20090727
1056
if branch_format is None:
1057
return self.transport.clone(path)
1059
branch_format.get_format_string()
1060
except NotImplementedError:
1061
raise errors.IncompatibleFormat(branch_format, self._format)
1062
if name is not None:
1064
self.transport.mkdir('branches', mode=self._get_mkdir_mode())
1065
except errors.FileExists:
1067
branches = self._read_branch_list()
1068
if not name in branches:
1069
self.control_files.lock_write()
1071
branches = self._read_branch_list()
1072
branches.append(name)
1073
self._write_branch_list(branches)
1075
self.control_files.unlock()
1077
self.transport.mkdir(path, mode=self._get_mkdir_mode())
1078
except errors.FileExists:
1080
return self.transport.clone(path)
1083
class BzrProber(controldir.Prober):
1084
"""Prober for formats that use a .bzr/ control directory."""
1086
formats = registry.FormatRegistry(controldir.network_format_registry)
1087
"""The known .bzr formats."""
1090
@deprecated_method(deprecated_in((2, 4, 0)))
1091
def register_bzrdir_format(klass, format):
1092
klass.formats.register(format.get_format_string(), format)
1095
@deprecated_method(deprecated_in((2, 4, 0)))
1096
def unregister_bzrdir_format(klass, format):
1097
klass.formats.remove(format.get_format_string())
1100
def probe_transport(klass, transport):
1101
"""Return the .bzrdir style format present in a directory."""
1103
format_string = transport.get_bytes(".bzr/branch-format")
1104
except errors.NoSuchFile:
1105
raise errors.NotBranchError(path=transport.base)
1107
return klass.formats.get(format_string)
1109
raise errors.UnknownFormatError(format=format_string, kind='bzrdir')
1112
def known_formats(cls):
1114
for name, format in cls.formats.iteritems():
1115
if callable(format):
1121
controldir.ControlDirFormat.register_prober(BzrProber)
1124
class RemoteBzrProber(controldir.Prober):
1125
"""Prober for remote servers that provide a Bazaar smart server."""
1128
def probe_transport(klass, transport):
1129
"""Return a RemoteBzrDirFormat object if it looks possible."""
1131
medium = transport.get_smart_medium()
1132
except (NotImplementedError, AttributeError,
1133
errors.TransportNotPossible, errors.NoSmartMedium,
1134
errors.SmartProtocolError):
1135
# no smart server, so not a branch for this format type.
1136
raise errors.NotBranchError(path=transport.base)
1138
# Decline to open it if the server doesn't support our required
1139
# version (3) so that the VFS-based transport will do it.
1140
if medium.should_probe():
1142
server_version = medium.protocol_version()
1143
except errors.SmartProtocolError:
1144
# Apparently there's no usable smart server there, even though
1145
# the medium supports the smart protocol.
1146
raise errors.NotBranchError(path=transport.base)
1147
if server_version != '2':
1148
raise errors.NotBranchError(path=transport.base)
1149
from bzrlib.remote import RemoteBzrDirFormat
1150
return RemoteBzrDirFormat()
1153
def known_formats(cls):
1154
from bzrlib.remote import RemoteBzrDirFormat
1155
return set([RemoteBzrDirFormat()])
1158
class BzrDirFormat(controldir.ControlDirFormat):
1159
"""ControlDirFormat base class for .bzr/ directories.
1161
Formats are placed in a dict by their format string for reference
1162
during bzrdir opening. These should be subclasses of BzrDirFormat
1165
Once a format is deprecated, just deprecate the initialize and open
1166
methods on the format class. Do not deprecate the object, as the
1167
object will be created every system load.
1170
_lock_file_name = 'branch-lock'
1172
# _lock_class must be set in subclasses to the lock type, typ.
1173
# TransportLock or LockDir
1176
def get_format_string(cls):
1177
"""Return the ASCII format string that identifies this format."""
1178
raise NotImplementedError(cls.get_format_string)
1180
def initialize_on_transport(self, transport):
1181
"""Initialize a new bzrdir in the base directory of a Transport."""
1183
# can we hand off the request to the smart server rather than using
1185
client_medium = transport.get_smart_medium()
1186
except errors.NoSmartMedium:
1187
return self._initialize_on_transport_vfs(transport)
1189
# Current RPC's only know how to create bzr metadir1 instances, so
1190
# we still delegate to vfs methods if the requested format is not a
1192
if type(self) != BzrDirMetaFormat1:
1193
return self._initialize_on_transport_vfs(transport)
1194
from bzrlib.remote import RemoteBzrDirFormat
1195
remote_format = RemoteBzrDirFormat()
1196
self._supply_sub_formats_to(remote_format)
1197
return remote_format.initialize_on_transport(transport)
1199
def initialize_on_transport_ex(self, transport, use_existing_dir=False,
1200
create_prefix=False, force_new_repo=False, stacked_on=None,
1201
stack_on_pwd=None, repo_format_name=None, make_working_trees=None,
1202
shared_repo=False, vfs_only=False):
1203
"""Create this format on transport.
1205
The directory to initialize will be created.
1207
:param force_new_repo: Do not use a shared repository for the target,
1208
even if one is available.
1209
:param create_prefix: Create any missing directories leading up to
1211
:param use_existing_dir: Use an existing directory if one exists.
1212
:param stacked_on: A url to stack any created branch on, None to follow
1213
any target stacking policy.
1214
:param stack_on_pwd: If stack_on is relative, the location it is
1216
:param repo_format_name: If non-None, a repository will be
1217
made-or-found. Should none be found, or if force_new_repo is True
1218
the repo_format_name is used to select the format of repository to
1220
:param make_working_trees: Control the setting of make_working_trees
1221
for a new shared repository when one is made. None to use whatever
1222
default the format has.
1223
:param shared_repo: Control whether made repositories are shared or
1225
:param vfs_only: If True do not attempt to use a smart server
1226
:return: repo, bzrdir, require_stacking, repository_policy. repo is
1227
None if none was created or found, bzrdir is always valid.
1228
require_stacking is the result of examining the stacked_on
1229
parameter and any stacking policy found for the target.
1232
# Try to hand off to a smart server
1234
client_medium = transport.get_smart_medium()
1235
except errors.NoSmartMedium:
1238
from bzrlib.remote import RemoteBzrDirFormat
1239
# TODO: lookup the local format from a server hint.
1240
remote_dir_format = RemoteBzrDirFormat()
1241
remote_dir_format._network_name = self.network_name()
1242
self._supply_sub_formats_to(remote_dir_format)
1243
return remote_dir_format.initialize_on_transport_ex(transport,
1244
use_existing_dir=use_existing_dir, create_prefix=create_prefix,
1245
force_new_repo=force_new_repo, stacked_on=stacked_on,
1246
stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
1247
make_working_trees=make_working_trees, shared_repo=shared_repo)
1248
# XXX: Refactor the create_prefix/no_create_prefix code into a
1249
# common helper function
1250
# The destination may not exist - if so make it according to policy.
1251
def make_directory(transport):
1252
transport.mkdir('.')
1254
def redirected(transport, e, redirection_notice):
1255
note(redirection_notice)
1256
return transport._redirected_to(e.source, e.target)
1258
transport = do_catching_redirections(make_directory, transport,
1260
except errors.FileExists:
1261
if not use_existing_dir:
1263
except errors.NoSuchFile:
1264
if not create_prefix:
1266
transport.create_prefix()
1268
require_stacking = (stacked_on is not None)
1269
# Now the target directory exists, but doesn't have a .bzr
1270
# directory. So we need to create it, along with any work to create
1271
# all of the dependent branches, etc.
1273
result = self.initialize_on_transport(transport)
1274
if repo_format_name:
1276
# use a custom format
1277
result._format.repository_format = \
1278
repository.network_format_registry.get(repo_format_name)
1279
except AttributeError:
1280
# The format didn't permit it to be set.
1282
# A repository is desired, either in-place or shared.
1283
repository_policy = result.determine_repository_policy(
1284
force_new_repo, stacked_on, stack_on_pwd,
1285
require_stacking=require_stacking)
1286
result_repo, is_new_repo = repository_policy.acquire_repository(
1287
make_working_trees, shared_repo)
1288
if not require_stacking and repository_policy._require_stacking:
1289
require_stacking = True
1290
result._format.require_stacking()
1291
result_repo.lock_write()
1294
repository_policy = None
1295
return result_repo, result, require_stacking, repository_policy
1297
def _initialize_on_transport_vfs(self, transport):
1298
"""Initialize a new bzrdir using VFS calls.
1300
:param transport: The transport to create the .bzr directory in.
1303
# Since we are creating a .bzr directory, inherit the
1304
# mode from the root directory
1305
temp_control = lockable_files.LockableFiles(transport,
1306
'', lockable_files.TransportLock)
1307
temp_control._transport.mkdir('.bzr',
1308
# FIXME: RBC 20060121 don't peek under
1310
mode=temp_control._dir_mode)
1311
if sys.platform == 'win32' and isinstance(transport, local.LocalTransport):
1312
win32utils.set_file_attr_hidden(transport._abspath('.bzr'))
1313
file_mode = temp_control._file_mode
1315
bzrdir_transport = transport.clone('.bzr')
1316
utf8_files = [('README',
1317
"This is a Bazaar control directory.\n"
1318
"Do not change any files in this directory.\n"
1319
"See http://bazaar.canonical.com/ for more information about Bazaar.\n"),
1320
('branch-format', self.get_format_string()),
1322
# NB: no need to escape relative paths that are url safe.
1323
control_files = lockable_files.LockableFiles(bzrdir_transport,
1324
self._lock_file_name, self._lock_class)
1325
control_files.create_lock()
1326
control_files.lock_write()
1328
for (filename, content) in utf8_files:
1329
bzrdir_transport.put_bytes(filename, content,
1332
control_files.unlock()
1333
return self.open(transport, _found=True)
1335
def open(self, transport, _found=False):
1336
"""Return an instance of this format for the dir transport points at.
1338
_found is a private parameter, do not use it.
1341
found_format = controldir.ControlDirFormat.find_format(transport)
1342
if not isinstance(found_format, self.__class__):
1343
raise AssertionError("%s was asked to open %s, but it seems to need "
1345
% (self, transport, found_format))
1346
# Allow subclasses - use the found format.
1347
self._supply_sub_formats_to(found_format)
1348
return found_format._open(transport)
1349
return self._open(transport)
1351
def _open(self, transport):
1352
"""Template method helper for opening BzrDirectories.
1354
This performs the actual open and any additional logic or parameter
1357
raise NotImplementedError(self._open)
1359
def _supply_sub_formats_to(self, other_format):
1360
"""Give other_format the same values for sub formats as this has.
1362
This method is expected to be used when parameterising a
1363
RemoteBzrDirFormat instance with the parameters from a
1364
BzrDirMetaFormat1 instance.
1366
:param other_format: other_format is a format which should be
1367
compatible with whatever sub formats are supported by self.
1371
def supports_transport(self, transport):
1372
# bzr formats can be opened over all known transports
1376
class BzrDirMetaFormat1(BzrDirFormat):
1377
"""Bzr meta control format 1
1379
This is the first format with split out working tree, branch and repository
1384
- Format 3 working trees [optional]
1385
- Format 5 branches [optional]
1386
- Format 7 repositories [optional]
1389
_lock_class = lockdir.LockDir
1391
fixed_components = False
1393
colocated_branches = False
1396
self._workingtree_format = None
1397
self._branch_format = None
1398
self._repository_format = None
1400
def __eq__(self, other):
1401
if other.__class__ is not self.__class__:
1403
if other.repository_format != self.repository_format:
1405
if other.workingtree_format != self.workingtree_format:
1409
def __ne__(self, other):
1410
return not self == other
1412
def get_branch_format(self):
1413
if self._branch_format is None:
1414
from bzrlib.branch import format_registry as branch_format_registry
1415
self._branch_format = branch_format_registry.get_default()
1416
return self._branch_format
1418
def set_branch_format(self, format):
1419
self._branch_format = format
1421
def require_stacking(self, stack_on=None, possible_transports=None,
1423
"""We have a request to stack, try to ensure the formats support it.
1425
:param stack_on: If supplied, it is the URL to a branch that we want to
1426
stack on. Check to see if that format supports stacking before
1429
# Stacking is desired. requested by the target, but does the place it
1430
# points at support stacking? If it doesn't then we should
1431
# not implicitly upgrade. We check this here.
1432
new_repo_format = None
1433
new_branch_format = None
1435
# a bit of state for get_target_branch so that we don't try to open it
1436
# 2 times, for both repo *and* branch
1437
target = [None, False, None] # target_branch, checked, upgrade anyway
1438
def get_target_branch():
1440
# We've checked, don't check again
1442
if stack_on is None:
1443
# No target format, that means we want to force upgrading
1444
target[:] = [None, True, True]
1447
target_dir = BzrDir.open(stack_on,
1448
possible_transports=possible_transports)
1449
except errors.NotBranchError:
1450
# Nothing there, don't change formats
1451
target[:] = [None, True, False]
1453
except errors.JailBreak:
1454
# JailBreak, JFDI and upgrade anyway
1455
target[:] = [None, True, True]
1458
target_branch = target_dir.open_branch()
1459
except errors.NotBranchError:
1460
# No branch, don't upgrade formats
1461
target[:] = [None, True, False]
1463
target[:] = [target_branch, True, False]
1466
if (not _skip_repo and
1467
not self.repository_format.supports_external_lookups):
1468
# We need to upgrade the Repository.
1469
target_branch, _, do_upgrade = get_target_branch()
1470
if target_branch is None:
1471
# We don't have a target branch, should we upgrade anyway?
1473
# stack_on is inaccessible, JFDI.
1474
# TODO: bad monkey, hard-coded formats...
1475
if self.repository_format.rich_root_data:
1476
new_repo_format = knitpack_repo.RepositoryFormatKnitPack5RichRoot()
1478
new_repo_format = knitpack_repo.RepositoryFormatKnitPack5()
1480
# If the target already supports stacking, then we know the
1481
# project is already able to use stacking, so auto-upgrade
1483
new_repo_format = target_branch.repository._format
1484
if not new_repo_format.supports_external_lookups:
1485
# target doesn't, source doesn't, so don't auto upgrade
1487
new_repo_format = None
1488
if new_repo_format is not None:
1489
self.repository_format = new_repo_format
1490
note(gettext('Source repository format does not support stacking,'
1491
' using format:\n %s'),
1492
new_repo_format.get_format_description())
1494
if not self.get_branch_format().supports_stacking():
1495
# We just checked the repo, now lets check if we need to
1496
# upgrade the branch format
1497
target_branch, _, do_upgrade = get_target_branch()
1498
if target_branch is None:
1500
# TODO: bad monkey, hard-coded formats...
1501
from bzrlib.branch import BzrBranchFormat7
1502
new_branch_format = BzrBranchFormat7()
1504
new_branch_format = target_branch._format
1505
if not new_branch_format.supports_stacking():
1506
new_branch_format = None
1507
if new_branch_format is not None:
1508
# Does support stacking, use its format.
1509
self.set_branch_format(new_branch_format)
1510
note(gettext('Source branch format does not support stacking,'
1511
' using format:\n %s'),
1512
new_branch_format.get_format_description())
1514
def get_converter(self, format=None):
1515
"""See BzrDirFormat.get_converter()."""
1517
format = BzrDirFormat.get_default_format()
1518
if (type(self) is BzrDirMetaFormat1 and
1519
type(format) is BzrDirMetaFormat1Colo):
1520
return ConvertMetaToColo(format)
1521
if (type(self) is BzrDirMetaFormat1Colo and
1522
type(format) is BzrDirMetaFormat1):
1523
return ConvertMetaRemoveColo(format)
1524
if not isinstance(self, format.__class__):
1525
# converting away from metadir is not implemented
1526
raise NotImplementedError(self.get_converter)
1527
return ConvertMetaToMeta(format)
1530
def get_format_string(cls):
1531
"""See BzrDirFormat.get_format_string()."""
1532
return "Bazaar-NG meta directory, format 1\n"
1534
def get_format_description(self):
1535
"""See BzrDirFormat.get_format_description()."""
1536
return "Meta directory format 1"
1538
def network_name(self):
1539
return self.get_format_string()
1541
def _open(self, transport):
1542
"""See BzrDirFormat._open."""
1543
# Create a new format instance because otherwise initialisation of new
1544
# metadirs share the global default format object leading to alias
1546
format = BzrDirMetaFormat1()
1547
self._supply_sub_formats_to(format)
1548
return BzrDirMeta1(transport, format)
1550
def __return_repository_format(self):
1551
"""Circular import protection."""
1552
if self._repository_format:
1553
return self._repository_format
1554
from bzrlib.repository import format_registry
1555
return format_registry.get_default()
1557
def _set_repository_format(self, value):
1558
"""Allow changing the repository format for metadir formats."""
1559
self._repository_format = value
1561
repository_format = property(__return_repository_format,
1562
_set_repository_format)
1564
def _supply_sub_formats_to(self, other_format):
1565
"""Give other_format the same values for sub formats as this has.
1567
This method is expected to be used when parameterising a
1568
RemoteBzrDirFormat instance with the parameters from a
1569
BzrDirMetaFormat1 instance.
1571
:param other_format: other_format is a format which should be
1572
compatible with whatever sub formats are supported by self.
1575
if getattr(self, '_repository_format', None) is not None:
1576
other_format.repository_format = self.repository_format
1577
if self._branch_format is not None:
1578
other_format._branch_format = self._branch_format
1579
if self._workingtree_format is not None:
1580
other_format.workingtree_format = self.workingtree_format
1582
def __get_workingtree_format(self):
1583
if self._workingtree_format is None:
1584
from bzrlib.workingtree import (
1585
format_registry as wt_format_registry,
1587
self._workingtree_format = wt_format_registry.get_default()
1588
return self._workingtree_format
1590
def __set_workingtree_format(self, wt_format):
1591
self._workingtree_format = wt_format
1593
workingtree_format = property(__get_workingtree_format,
1594
__set_workingtree_format)
1597
# Register bzr formats
1598
BzrProber.formats.register(BzrDirMetaFormat1.get_format_string(),
1600
controldir.ControlDirFormat._default_format = BzrDirMetaFormat1()
1603
class BzrDirMetaFormat1Colo(BzrDirMetaFormat1):
1604
"""BzrDirMeta1 format with support for colocated branches."""
1606
colocated_branches = True
1609
def get_format_string(cls):
1610
"""See BzrDirFormat.get_format_string()."""
1611
return "Bazaar meta directory, format 1 (with colocated branches)\n"
1613
def get_format_description(self):
1614
"""See BzrDirFormat.get_format_description()."""
1615
return "Meta directory format 1 with support for colocated branches"
1617
def _open(self, transport):
1618
"""See BzrDirFormat._open."""
1619
# Create a new format instance because otherwise initialisation of new
1620
# metadirs share the global default format object leading to alias
1622
format = BzrDirMetaFormat1Colo()
1623
self._supply_sub_formats_to(format)
1624
return BzrDirMeta1Colo(transport, format)
1627
BzrProber.formats.register(BzrDirMetaFormat1Colo.get_format_string(),
1628
BzrDirMetaFormat1Colo)
1631
class ConvertMetaToMeta(controldir.Converter):
1632
"""Converts the components of metadirs."""
1634
def __init__(self, target_format):
1635
"""Create a metadir to metadir converter.
1637
:param target_format: The final metadir format that is desired.
1639
self.target_format = target_format
1641
def convert(self, to_convert, pb):
1642
"""See Converter.convert()."""
1643
self.bzrdir = to_convert
1644
self.pb = ui.ui_factory.nested_progress_bar()
1647
self.step('checking repository format')
1649
repo = self.bzrdir.open_repository()
1650
except errors.NoRepositoryPresent:
1653
if not isinstance(repo._format, self.target_format.repository_format.__class__):
1654
from bzrlib.repository import CopyConverter
1655
ui.ui_factory.note(gettext('starting repository conversion'))
1656
converter = CopyConverter(self.target_format.repository_format)
1657
converter.convert(repo, pb)
1658
for branch in self.bzrdir.list_branches():
1659
# TODO: conversions of Branch and Tree should be done by
1660
# InterXFormat lookups/some sort of registry.
1661
# Avoid circular imports
1662
old = branch._format.__class__
1663
new = self.target_format.get_branch_format().__class__
1665
if (old == _mod_branch.BzrBranchFormat5 and
1666
new in (_mod_branch.BzrBranchFormat6,
1667
_mod_branch.BzrBranchFormat7,
1668
_mod_branch.BzrBranchFormat8)):
1669
branch_converter = _mod_branch.Converter5to6()
1670
elif (old == _mod_branch.BzrBranchFormat6 and
1671
new in (_mod_branch.BzrBranchFormat7,
1672
_mod_branch.BzrBranchFormat8)):
1673
branch_converter = _mod_branch.Converter6to7()
1674
elif (old == _mod_branch.BzrBranchFormat7 and
1675
new is _mod_branch.BzrBranchFormat8):
1676
branch_converter = _mod_branch.Converter7to8()
1678
raise errors.BadConversionTarget("No converter", new,
1680
branch_converter.convert(branch)
1681
branch = self.bzrdir.open_branch()
1682
old = branch._format.__class__
1684
tree = self.bzrdir.open_workingtree(recommend_upgrade=False)
1685
except (errors.NoWorkingTree, errors.NotLocalUrl):
1688
# TODO: conversions of Branch and Tree should be done by
1689
# InterXFormat lookups
1690
if (isinstance(tree, workingtree_3.WorkingTree3) and
1691
not isinstance(tree, workingtree_4.DirStateWorkingTree) and
1692
isinstance(self.target_format.workingtree_format,
1693
workingtree_4.DirStateWorkingTreeFormat)):
1694
workingtree_4.Converter3to4().convert(tree)
1695
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
1696
not isinstance(tree, workingtree_4.WorkingTree5) and
1697
isinstance(self.target_format.workingtree_format,
1698
workingtree_4.WorkingTreeFormat5)):
1699
workingtree_4.Converter4to5().convert(tree)
1700
if (isinstance(tree, workingtree_4.DirStateWorkingTree) and
1701
not isinstance(tree, workingtree_4.WorkingTree6) and
1702
isinstance(self.target_format.workingtree_format,
1703
workingtree_4.WorkingTreeFormat6)):
1704
workingtree_4.Converter4or5to6().convert(tree)
1709
class ConvertMetaToColo(controldir.Converter):
1710
"""Add colocated branch support."""
1712
def __init__(self, target_format):
1713
"""Create a converter.that upgrades a metadir to the colo format.
1715
:param target_format: The final metadir format that is desired.
1717
self.target_format = target_format
1719
def convert(self, to_convert, pb):
1720
"""See Converter.convert()."""
1721
to_convert.transport.put_bytes('branch-format',
1722
self.target_format.get_format_string())
1723
return BzrDir.open_from_transport(to_convert.root_transport)
1726
class ConvertMetaRemoveColo(controldir.Converter):
1727
"""Remove colocated branch support from a bzrdir."""
1729
def __init__(self, target_format):
1730
"""Create a converter.that downgrades a colocated branch metadir
1731
to a regular metadir.
1733
:param target_format: The final metadir format that is desired.
1735
self.target_format = target_format
1737
def convert(self, to_convert, pb):
1738
"""See Converter.convert()."""
1739
to_convert.control_files.lock_write()
1741
branches = to_convert.list_branches()
1742
if len(branches) > 1:
1743
raise errors.BzrError("remove all but a single "
1744
"colocated branch when downgrading")
1746
to_convert.control_files.unlock()
1747
to_convert.transport.put_bytes('branch-format',
1748
self.target_format.get_format_string())
1749
return BzrDir.open_from_transport(to_convert.root_transport)
1752
controldir.ControlDirFormat.register_server_prober(RemoteBzrProber)
1755
class RepositoryAcquisitionPolicy(object):
1756
"""Abstract base class for repository acquisition policies.
1758
A repository acquisition policy decides how a BzrDir acquires a repository
1759
for a branch that is being created. The most basic policy decision is
1760
whether to create a new repository or use an existing one.
1762
def __init__(self, stack_on, stack_on_pwd, require_stacking):
1765
:param stack_on: A location to stack on
1766
:param stack_on_pwd: If stack_on is relative, the location it is
1768
:param require_stacking: If True, it is a failure to not stack.
1770
self._stack_on = stack_on
1771
self._stack_on_pwd = stack_on_pwd
1772
self._require_stacking = require_stacking
1774
def configure_branch(self, branch):
1775
"""Apply any configuration data from this policy to the branch.
1777
Default implementation sets repository stacking.
1779
if self._stack_on is None:
1781
if self._stack_on_pwd is None:
1782
stack_on = self._stack_on
1785
stack_on = urlutils.rebase_url(self._stack_on,
1788
except errors.InvalidRebaseURLs:
1789
stack_on = self._get_full_stack_on()
1791
branch.set_stacked_on_url(stack_on)
1792
except (errors.UnstackableBranchFormat,
1793
errors.UnstackableRepositoryFormat):
1794
if self._require_stacking:
1797
def requires_stacking(self):
1798
"""Return True if this policy requires stacking."""
1799
return self._stack_on is not None and self._require_stacking
1801
def _get_full_stack_on(self):
1802
"""Get a fully-qualified URL for the stack_on location."""
1803
if self._stack_on is None:
1805
if self._stack_on_pwd is None:
1806
return self._stack_on
1808
return urlutils.join(self._stack_on_pwd, self._stack_on)
1810
def _add_fallback(self, repository, possible_transports=None):
1811
"""Add a fallback to the supplied repository, if stacking is set."""
1812
stack_on = self._get_full_stack_on()
1813
if stack_on is None:
1816
stacked_dir = BzrDir.open(stack_on,
1817
possible_transports=possible_transports)
1818
except errors.JailBreak:
1819
# We keep the stacking details, but we are in the server code so
1820
# actually stacking is not needed.
1823
stacked_repo = stacked_dir.open_branch().repository
1824
except errors.NotBranchError:
1825
stacked_repo = stacked_dir.open_repository()
1827
repository.add_fallback_repository(stacked_repo)
1828
except errors.UnstackableRepositoryFormat:
1829
if self._require_stacking:
1832
self._require_stacking = True
1834
def acquire_repository(self, make_working_trees=None, shared=False):
1835
"""Acquire a repository for this bzrdir.
1837
Implementations may create a new repository or use a pre-exising
1840
:param make_working_trees: If creating a repository, set
1841
make_working_trees to this value (if non-None)
1842
:param shared: If creating a repository, make it shared if True
1843
:return: A repository, is_new_flag (True if the repository was
1846
raise NotImplemented(RepositoryAcquisitionPolicy.acquire_repository)
1849
class CreateRepository(RepositoryAcquisitionPolicy):
1850
"""A policy of creating a new repository"""
1852
def __init__(self, bzrdir, stack_on=None, stack_on_pwd=None,
1853
require_stacking=False):
1856
:param bzrdir: The bzrdir to create the repository on.
1857
:param stack_on: A location to stack on
1858
:param stack_on_pwd: If stack_on is relative, the location it is
1861
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
1863
self._bzrdir = bzrdir
1865
def acquire_repository(self, make_working_trees=None, shared=False):
1866
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
1868
Creates the desired repository in the bzrdir we already have.
1870
stack_on = self._get_full_stack_on()
1872
format = self._bzrdir._format
1873
format.require_stacking(stack_on=stack_on,
1874
possible_transports=[self._bzrdir.root_transport])
1875
if not self._require_stacking:
1876
# We have picked up automatic stacking somewhere.
1877
note(gettext('Using default stacking branch {0} at {1}').format(
1878
self._stack_on, self._stack_on_pwd))
1879
repository = self._bzrdir.create_repository(shared=shared)
1880
self._add_fallback(repository,
1881
possible_transports=[self._bzrdir.transport])
1882
if make_working_trees is not None:
1883
repository.set_make_working_trees(make_working_trees)
1884
return repository, True
1887
class UseExistingRepository(RepositoryAcquisitionPolicy):
1888
"""A policy of reusing an existing repository"""
1890
def __init__(self, repository, stack_on=None, stack_on_pwd=None,
1891
require_stacking=False):
1894
:param repository: The repository to use.
1895
:param stack_on: A location to stack on
1896
:param stack_on_pwd: If stack_on is relative, the location it is
1899
RepositoryAcquisitionPolicy.__init__(self, stack_on, stack_on_pwd,
1901
self._repository = repository
1903
def acquire_repository(self, make_working_trees=None, shared=False):
1904
"""Implementation of RepositoryAcquisitionPolicy.acquire_repository
1906
Returns an existing repository to use.
1908
self._add_fallback(self._repository,
1909
possible_transports=[self._repository.bzrdir.transport])
1910
return self._repository, False
1913
def register_metadir(registry, key,
1914
repository_format, help, native=True, deprecated=False,
1919
alias=False, bzrdir_format=None):
1920
"""Register a metadir subformat.
1922
These all use a meta bzrdir, but can be parameterized by the
1923
Repository/Branch/WorkingTreeformats.
1925
:param repository_format: The fully-qualified repository format class
1927
:param branch_format: Fully-qualified branch format class name as
1929
:param tree_format: Fully-qualified tree format class name as
1932
if bzrdir_format is None:
1933
bzrdir_format = BzrDirMetaFormat1
1934
# This should be expanded to support setting WorkingTree and Branch
1935
# formats, once the API supports that.
1936
def _load(full_name):
1937
mod_name, factory_name = full_name.rsplit('.', 1)
1939
factory = pyutils.get_named_object(mod_name, factory_name)
1940
except ImportError, e:
1941
raise ImportError('failed to load %s: %s' % (full_name, e))
1942
except AttributeError:
1943
raise AttributeError('no factory %s in module %r'
1944
% (full_name, sys.modules[mod_name]))
1948
bd = bzrdir_format()
1949
if branch_format is not None:
1950
bd.set_branch_format(_load(branch_format))
1951
if tree_format is not None:
1952
bd.workingtree_format = _load(tree_format)
1953
if repository_format is not None:
1954
bd.repository_format = _load(repository_format)
1956
registry.register(key, helper, help, native, deprecated, hidden,
1957
experimental, alias)
1959
register_metadir(controldir.format_registry, 'knit',
1960
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1961
'Format using knits. Recommended for interoperation with bzr <= 0.14.',
1962
branch_format='bzrlib.branch.BzrBranchFormat5',
1963
tree_format='bzrlib.workingtree_3.WorkingTreeFormat3',
1966
register_metadir(controldir.format_registry, 'dirstate',
1967
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1968
help='New in 0.15: Fast local operations. Compatible with bzr 0.8 and '
1969
'above when accessed over the network.',
1970
branch_format='bzrlib.branch.BzrBranchFormat5',
1971
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1974
register_metadir(controldir.format_registry, 'dirstate-tags',
1975
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
1976
help='New in 0.15: Fast local operations and improved scaling for '
1977
'network operations. Additionally adds support for tags.'
1978
' Incompatible with bzr < 0.15.',
1979
branch_format='bzrlib.branch.BzrBranchFormat6',
1980
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1983
register_metadir(controldir.format_registry, 'rich-root',
1984
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit4',
1985
help='New in 1.0. Better handling of tree roots. Incompatible with'
1987
branch_format='bzrlib.branch.BzrBranchFormat6',
1988
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
1991
register_metadir(controldir.format_registry, 'dirstate-with-subtree',
1992
'bzrlib.repofmt.knitrepo.RepositoryFormatKnit3',
1993
help='New in 0.15: Fast local operations and improved scaling for '
1994
'network operations. Additionally adds support for versioning nested '
1995
'bzr branches. Incompatible with bzr < 0.15.',
1996
branch_format='bzrlib.branch.BzrBranchFormat6',
1997
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2001
register_metadir(controldir.format_registry, 'pack-0.92',
2002
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack1',
2003
help='New in 0.92: Pack-based format with data compatible with '
2004
'dirstate-tags format repositories. Interoperates with '
2005
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
2007
branch_format='bzrlib.branch.BzrBranchFormat6',
2008
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2010
register_metadir(controldir.format_registry, 'pack-0.92-subtree',
2011
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack3',
2012
help='New in 0.92: Pack-based format with data compatible with '
2013
'dirstate-with-subtree format repositories. Interoperates with '
2014
'bzr repositories before 0.92 but cannot be read by bzr < 0.92. '
2016
branch_format='bzrlib.branch.BzrBranchFormat6',
2017
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2021
register_metadir(controldir.format_registry, 'rich-root-pack',
2022
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack4',
2023
help='New in 1.0: A variant of pack-0.92 that supports rich-root data '
2024
'(needed for bzr-svn and bzr-git).',
2025
branch_format='bzrlib.branch.BzrBranchFormat6',
2026
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2029
register_metadir(controldir.format_registry, '1.6',
2030
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5',
2031
help='A format that allows a branch to indicate that there is another '
2032
'(stacked) repository that should be used to access data that is '
2033
'not present locally.',
2034
branch_format='bzrlib.branch.BzrBranchFormat7',
2035
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2038
register_metadir(controldir.format_registry, '1.6.1-rich-root',
2039
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack5RichRoot',
2040
help='A variant of 1.6 that supports rich-root data '
2041
'(needed for bzr-svn and bzr-git).',
2042
branch_format='bzrlib.branch.BzrBranchFormat7',
2043
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2046
register_metadir(controldir.format_registry, '1.9',
2047
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
2048
help='A repository format using B+tree indexes. These indexes '
2049
'are smaller in size, have smarter caching and provide faster '
2050
'performance for most operations.',
2051
branch_format='bzrlib.branch.BzrBranchFormat7',
2052
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2055
register_metadir(controldir.format_registry, '1.9-rich-root',
2056
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
2057
help='A variant of 1.9 that supports rich-root data '
2058
'(needed for bzr-svn and bzr-git).',
2059
branch_format='bzrlib.branch.BzrBranchFormat7',
2060
tree_format='bzrlib.workingtree_4.WorkingTreeFormat4',
2063
register_metadir(controldir.format_registry, '1.14',
2064
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6',
2065
help='A working-tree format that supports content filtering.',
2066
branch_format='bzrlib.branch.BzrBranchFormat7',
2067
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
2069
register_metadir(controldir.format_registry, '1.14-rich-root',
2070
'bzrlib.repofmt.knitpack_repo.RepositoryFormatKnitPack6RichRoot',
2071
help='A variant of 1.14 that supports rich-root data '
2072
'(needed for bzr-svn and bzr-git).',
2073
branch_format='bzrlib.branch.BzrBranchFormat7',
2074
tree_format='bzrlib.workingtree_4.WorkingTreeFormat5',
2076
# The following un-numbered 'development' formats should always just be aliases.
2077
register_metadir(controldir.format_registry, 'development-subtree',
2078
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2aSubtree',
2079
help='Current development format, subtree variant. Can convert data to and '
2080
'from pack-0.92-subtree (and anything compatible with '
2081
'pack-0.92-subtree) format repositories. Repositories and branches in '
2082
'this format can only be read by bzr.dev. Please read '
2083
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
2085
branch_format='bzrlib.branch.BzrBranchFormat7',
2086
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2089
alias=False, # Restore to being an alias when an actual development subtree format is added
2090
# This current non-alias status is simply because we did not introduce a
2091
# chk based subtree format.
2093
register_metadir(controldir.format_registry, 'development5-subtree',
2094
'bzrlib.repofmt.knitpack_repo.RepositoryFormatPackDevelopment2Subtree',
2095
help='Development format, subtree variant. Can convert data to and '
2096
'from pack-0.92-subtree (and anything compatible with '
2097
'pack-0.92-subtree) format repositories. Repositories and branches in '
2098
'this format can only be read by bzr.dev. Please read '
2099
'http://doc.bazaar.canonical.com/latest/developers/development-repo.html '
2101
branch_format='bzrlib.branch.BzrBranchFormat7',
2102
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2108
register_metadir(controldir.format_registry, 'development-colo',
2109
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
2110
help='The 2a format with experimental support for colocated branches.\n',
2111
branch_format='bzrlib.branch.BzrBranchFormat7',
2112
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2114
bzrdir_format=BzrDirMetaFormat1Colo,
2118
# And the development formats above will have aliased one of the following:
2120
# Finally, the current format.
2121
register_metadir(controldir.format_registry, '2a',
2122
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
2123
help='First format for bzr 2.0 series.\n'
2124
'Uses group-compress storage.\n'
2125
'Provides rich roots which are a one-way transition.\n',
2126
# 'storage in packs, 255-way hashed CHK inventory, bencode revision, group compress, '
2127
# 'rich roots. Supported by bzr 1.16 and later.',
2128
branch_format='bzrlib.branch.BzrBranchFormat7',
2129
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2133
# The following format should be an alias for the rich root equivalent
2134
# of the default format
2135
register_metadir(controldir.format_registry, 'default-rich-root',
2136
'bzrlib.repofmt.groupcompress_repo.RepositoryFormat2a',
2137
branch_format='bzrlib.branch.BzrBranchFormat7',
2138
tree_format='bzrlib.workingtree_4.WorkingTreeFormat6',
2143
# The current format that is made on 'bzr init'.
2144
format_name = config.GlobalStack().get('default_format')
2145
controldir.format_registry.set_default(format_name)
2147
# XXX 2010-08-20 JRV: There is still a lot of code relying on
2148
# bzrlib.bzrdir.format_registry existing. When BzrDir.create/BzrDir.open/etc
2149
# get changed to ControlDir.create/ControlDir.open/etc this should be removed.
2150
format_registry = controldir.format_registry