91
class ControlComponent(object):
92
"""Abstract base class for control directory components.
94
This provides interfaces that are common across bzrdirs,
95
repositories, branches, and workingtree control directories.
97
They all expose two urls and transports: the *user* URL is the
98
one that stops above the control directory (eg .bzr) and that
99
should normally be used in messages, and the *control* URL is
100
under that in eg .bzr/checkout and is used to read the control
103
This can be used as a mixin and is intended to fit with
108
def control_transport(self):
109
raise NotImplementedError
112
def control_url(self):
113
return self.control_transport.base
116
def user_transport(self):
117
raise NotImplementedError
121
return self.user_transport.base
124
class BzrDir(ControlComponent):
125
92
"""A .bzr control diretory.
127
94
BzrDir instances let you create or open any of the things that can be
294
261
# copied, and finally if we are copying up to a specific
295
262
# revision_id then we can use the pending-ancestry-result which
296
263
# does not require traversing all of history to describe it.
297
if (result_repo.user_url == result.user_url
298
and not require_stacking and
264
if (result_repo.bzrdir.root_transport.base ==
265
result.root_transport.base and not require_stacking and
299
266
revision_id is not None):
300
267
fetch_spec = graph.PendingAncestryResult(
301
268
[revision_id], local_repo)
429
396
"""Destroy the repository in this BzrDir"""
430
397
raise NotImplementedError(self.destroy_repository)
432
def create_branch(self, name=None):
399
def create_branch(self):
433
400
"""Create a branch in this BzrDir.
435
:param name: Name of the colocated branch to create, None for
438
402
The bzrdir's format will control what branch format is created.
439
403
For more control see BranchFormatXX.create(a_bzrdir).
441
405
raise NotImplementedError(self.create_branch)
443
def destroy_branch(self, name=None):
444
"""Destroy a branch in this BzrDir.
446
:param name: Name of the branch to destroy, None for the default
407
def destroy_branch(self):
408
"""Destroy the branch in this BzrDir"""
449
409
raise NotImplementedError(self.destroy_branch)
499
459
except errors.NoRepositoryPresent:
500
460
repository = None
502
if (found_bzrdir.user_url != self.user_url
503
and not repository.is_shared()):
462
if ((found_bzrdir.root_transport.base !=
463
self.root_transport.base) and not repository.is_shared()):
504
464
# Don't look higher, can't use a higher shared repo.
505
465
repository = None
621
581
:return: Tuple with old path name and new path name
623
def name_gen(base='backup.bzr'):
625
name = "%s.~%d~" % (base, counter)
626
while self.root_transport.has(name):
628
name = "%s.~%d~" % (base, counter)
631
backup_dir=name_gen()
632
583
pb = ui.ui_factory.nested_progress_bar()
634
585
# FIXME: bug 300001 -- the backup fails if the backup directory
635
586
# already exists, but it should instead either remove it or make
636
587
# a new backup directory.
589
# FIXME: bug 262450 -- the backup directory should have the same
590
# permissions as the .bzr directory (probably a bug in copy_tree)
638
591
old_path = self.root_transport.abspath('.bzr')
639
new_path = self.root_transport.abspath(backup_dir)
592
new_path = self.root_transport.abspath('backup.bzr')
640
593
ui.ui_factory.note('making backup of %s\n to %s' % (old_path, new_path,))
641
self.root_transport.copy_tree('.bzr', backup_dir)
594
self.root_transport.copy_tree('.bzr', 'backup.bzr')
642
595
return (old_path, new_path)
704
657
next_transport = found_bzrdir.root_transport.clone('..')
705
if (found_bzrdir.user_url == next_transport.base):
658
if (found_bzrdir.root_transport.base == next_transport.base):
706
659
# top of the file system
708
661
# find the next containing bzrdir
725
678
repository = found_bzrdir.open_repository()
726
679
except errors.NoRepositoryPresent:
727
680
return None, False
728
if found_bzrdir.user_url == self.user_url:
681
if found_bzrdir.root_transport.base == self.root_transport.base:
729
682
return repository, True
730
683
elif repository.is_shared():
731
684
return repository, True
737
690
raise errors.NoRepositoryPresent(self)
738
691
return found_repo
740
def get_branch_reference(self, name=None):
693
def get_branch_reference(self):
741
694
"""Return the referenced URL for the branch in this bzrdir.
743
:param name: Optional colocated branch name
744
696
:raises NotBranchError: If there is no Branch.
745
:raises NoColocatedBranchSupport: If a branch name was specified
746
but colocated branches are not supported.
747
697
:return: The URL the branch in this bzrdir references if it is a
748
698
reference branch, or None for regular branches.
751
raise errors.NoColocatedBranchSupport(self)
754
def get_branch_transport(self, branch_format, name=None):
702
def get_branch_transport(self, branch_format):
755
703
"""Get the transport for use by branch format in this BzrDir.
757
705
Note that bzr dirs that do not support format strings will raise
852
800
:param _transport: the transport this dir is based at.
854
802
self._format = _format
855
# these are also under the more standard names of
856
# control_transport and user_transport
857
803
self.transport = _transport.clone('.bzr')
858
804
self.root_transport = _transport
859
805
self._mode_check_done = False
862
def user_transport(self):
863
return self.root_transport
866
def control_transport(self):
867
return self.transport
869
807
def is_control_filename(self, filename):
870
808
"""True if filename is the name of a path which is reserved for bzrdir's.
945
883
BzrDir._check_supported(format, _unsupported)
946
884
return format.open(transport, _found=True)
948
def open_branch(self, name=None, unsupported=False,
949
ignore_fallbacks=False):
886
def open_branch(self, unsupported=False, ignore_fallbacks=False):
950
887
"""Open the branch object at this BzrDir if one is present.
952
889
If unsupported is True, then no longer supported branch formats can
999
936
raise errors.NotBranchError(path=url)
1000
937
a_transport = new_t
1002
def _get_tree_branch(self, name=None):
939
def _get_tree_branch(self):
1003
940
"""Return the branch and tree, if any, for this bzrdir.
1005
:param name: Name of colocated branch to open.
1007
942
Return None for tree if not present or inaccessible.
1008
943
Raise NotBranchError if no branch is present.
1009
944
:return: (tree, branch)
1012
947
tree = self.open_workingtree()
1013
948
except (errors.NoWorkingTree, errors.NotLocalUrl):
1015
branch = self.open_branch(name=name)
950
branch = self.open_branch()
1017
if name is not None:
1018
branch = self.open_branch(name=name)
1020
branch = tree.branch
1021
953
return tree, branch
1096
1028
raise NotImplementedError(self.open_workingtree)
1098
def has_branch(self, name=None):
1030
def has_branch(self):
1099
1031
"""Tell if this bzrdir contains a branch.
1101
1033
Note: if you're going to open the branch, you should just go ahead
1383
1315
self.create_hook(hooks.HookPoint('pre_open',
1384
1316
"Invoked before attempting to open a BzrDir with the transport "
1385
1317
"that the open will use.", (1, 14), None))
1386
self.create_hook(hooks.HookPoint('post_repo_init',
1387
"Invoked after a repository has been initialized. "
1388
"post_repo_init is called with a "
1389
"bzrlib.bzrdir.RepoInitHookParams.",
1392
1319
# install the default hooks
1393
1320
BzrDir.hooks = BzrDirHooks()
1396
class RepoInitHookParams(object):
1397
"""Object holding parameters passed to *_repo_init hooks.
1399
There are 4 fields that hooks may wish to access:
1401
:ivar repository: Repository created
1402
:ivar format: Repository format
1403
:ivar bzrdir: The bzrdir for the repository
1404
:ivar shared: The repository is shared
1407
def __init__(self, repository, format, a_bzrdir, shared):
1408
"""Create a group of RepoInitHook parameters.
1410
:param repository: Repository created
1411
:param format: Repository format
1412
:param bzrdir: The bzrdir for the repository
1413
:param shared: The repository is shared
1415
self.repository = repository
1416
self.format = format
1417
self.bzrdir = a_bzrdir
1418
self.shared = shared
1420
def __eq__(self, other):
1421
return self.__dict__ == other.__dict__
1425
return "<%s for %s>" % (self.__class__.__name__,
1428
return "<%s for %s>" % (self.__class__.__name__,
1432
1323
class BzrDirPreSplitOut(BzrDir):
1433
1324
"""A common class for the all-in-one formats."""
1473
1364
tree.clone(result)
1476
def create_branch(self, name=None):
1367
def create_branch(self):
1477
1368
"""See BzrDir.create_branch."""
1478
return self._format.get_branch_format().initialize(self, name=name)
1369
return self._format.get_branch_format().initialize(self)
1480
def destroy_branch(self, name=None):
1371
def destroy_branch(self):
1481
1372
"""See BzrDir.destroy_branch."""
1482
1373
raise errors.UnsupportedOperation(self.destroy_branch, self)
1539
1430
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1542
def get_branch_transport(self, branch_format, name=None):
1433
def get_branch_transport(self, branch_format):
1543
1434
"""See BzrDir.get_branch_transport()."""
1544
if name is not None:
1545
raise errors.NoColocatedBranchSupport(self)
1546
1435
if branch_format is None:
1547
1436
return self.transport
1581
1470
format = BzrDirFormat.get_default_format()
1582
1471
return not isinstance(self._format, format.__class__)
1584
def open_branch(self, name=None, unsupported=False,
1585
ignore_fallbacks=False):
1473
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1586
1474
"""See BzrDir.open_branch."""
1587
1475
from bzrlib.branch import BzrBranchFormat4
1588
1476
format = BzrBranchFormat4()
1589
1477
self._check_supported(format, unsupported)
1590
return format.open(self, name, _found=True)
1478
return format.open(self, _found=True)
1592
1480
def sprout(self, url, revision_id=None, force_new_repo=False,
1593
1481
possible_transports=None, accelerator_tree=None,
1710
1598
"""See BzrDir.can_convert_format()."""
1713
def create_branch(self, name=None):
1601
def create_branch(self):
1714
1602
"""See BzrDir.create_branch."""
1715
return self._format.get_branch_format().initialize(self, name=name)
1603
return self._format.get_branch_format().initialize(self)
1717
def destroy_branch(self, name=None):
1605
def destroy_branch(self):
1718
1606
"""See BzrDir.create_branch."""
1719
if name is not None:
1720
raise errors.NoColocatedBranchSupport(self)
1721
1607
self.transport.delete_tree('branch')
1723
1609
def create_repository(self, shared=False):
1746
1632
def destroy_workingtree_metadata(self):
1747
1633
self.transport.delete_tree('checkout')
1749
def find_branch_format(self, name=None):
1635
def find_branch_format(self):
1750
1636
"""Find the branch 'format' for this bzrdir.
1752
1638
This might be a synthetic object for e.g. RemoteBranch and SVN.
1754
1640
from bzrlib.branch import BranchFormat
1755
return BranchFormat.find_format(self, name=name)
1641
return BranchFormat.find_format(self)
1757
1643
def _get_mkdir_mode(self):
1758
1644
"""Figure out the mode to use when creating a bzrdir subdir."""
1760
1646
lockable_files.TransportLock)
1761
1647
return temp_control._dir_mode
1763
def get_branch_reference(self, name=None):
1649
def get_branch_reference(self):
1764
1650
"""See BzrDir.get_branch_reference()."""
1765
1651
from bzrlib.branch import BranchFormat
1766
format = BranchFormat.find_format(self, name=name)
1767
return format.get_reference(self, name=name)
1652
format = BranchFormat.find_format(self)
1653
return format.get_reference(self)
1769
def get_branch_transport(self, branch_format, name=None):
1655
def get_branch_transport(self, branch_format):
1770
1656
"""See BzrDir.get_branch_transport()."""
1771
if name is not None:
1772
raise errors.NoColocatedBranchSupport(self)
1773
1657
# XXX: this shouldn't implicitly create the directory if it's just
1774
1658
# promising to get a transport -- mbp 20090727
1775
1659
if branch_format is None:
1847
1731
except errors.NoRepositoryPresent:
1849
for branch in self.list_branches():
1850
if not isinstance(branch._format,
1734
if not isinstance(self.open_branch()._format,
1851
1735
format.get_branch_format().__class__):
1852
1736
# the branch needs an upgrade.
1738
except errors.NotBranchError:
1855
1741
my_wt = self.open_workingtree(recommend_upgrade=False)
1856
1742
if not isinstance(my_wt._format,
1864
def open_branch(self, name=None, unsupported=False,
1865
ignore_fallbacks=False):
1750
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1866
1751
"""See BzrDir.open_branch."""
1867
format = self.find_branch_format(name=name)
1752
format = self.find_branch_format()
1868
1753
self._check_supported(format, unsupported)
1869
return format.open(self, name=name,
1870
_found=True, ignore_fallbacks=ignore_fallbacks)
1754
return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1872
1756
def open_repository(self, unsupported=False):
1873
1757
"""See BzrDir.open_repository."""
1905
1789
Once a format is deprecated, just deprecate the initialize and open
1906
1790
methods on the format class. Do not deprecate the object, as the
1907
1791
object will be created every system load.
1909
:cvar colocated_branches: Whether this formats supports colocated branches.
1912
1794
_default_format = None
1930
1812
_lock_file_name = 'branch-lock'
1932
colocated_branches = False
1933
"""Whether co-located branches are supported for this control dir format.
1936
1814
# _lock_class must be set in subclasses to the lock type, typ.
1937
1815
# TransportLock or LockDir
2745
2623
if isinstance(self.bzrdir.transport, local.LocalTransport):
2746
2624
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2747
2625
self._convert_to_weaves()
2748
return BzrDir.open(self.bzrdir.user_url)
2626
return BzrDir.open(self.bzrdir.root_transport.base)
2750
2628
self.pb.finished()
3126
3004
BzrDirMetaFormat1().get_format_string(),
3127
3005
mode=self.file_mode)
3128
3006
self.pb.finished()
3129
return BzrDir.open(self.bzrdir.user_url)
3007
return BzrDir.open(self.bzrdir.root_transport.base)
3131
3009
def make_lock(self, name):
3132
3010
"""Make a lock for the new control dir name."""
3714
3592
stack_on = urlutils.rebase_url(self._stack_on,
3715
3593
self._stack_on_pwd,
3594
branch.bzrdir.root_transport.base)
3717
3595
except errors.InvalidRebaseURLs:
3718
3596
stack_on = self._get_full_stack_on()