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
749
def get_branch_transport(self, branch_format, name=None):
702
def get_branch_transport(self, branch_format):
750
703
"""Get the transport for use by branch format in this BzrDir.
752
705
Note that bzr dirs that do not support format strings will raise
847
800
:param _transport: the transport this dir is based at.
849
802
self._format = _format
850
# these are also under the more standard names of
851
# control_transport and user_transport
852
803
self.transport = _transport.clone('.bzr')
853
804
self.root_transport = _transport
854
805
self._mode_check_done = False
857
def user_transport(self):
858
return self.root_transport
861
def control_transport(self):
862
return self.transport
864
807
def is_control_filename(self, filename):
865
808
"""True if filename is the name of a path which is reserved for bzrdir's.
940
883
BzrDir._check_supported(format, _unsupported)
941
884
return format.open(transport, _found=True)
943
def open_branch(self, name=None, unsupported=False,
944
ignore_fallbacks=False):
886
def open_branch(self, unsupported=False, ignore_fallbacks=False):
945
887
"""Open the branch object at this BzrDir if one is present.
947
889
If unsupported is True, then no longer supported branch formats can
1086
1028
raise NotImplementedError(self.open_workingtree)
1088
def has_branch(self, name=None):
1030
def has_branch(self):
1089
1031
"""Tell if this bzrdir contains a branch.
1091
1033
Note: if you're going to open the branch, you should just go ahead
1373
1315
self.create_hook(hooks.HookPoint('pre_open',
1374
1316
"Invoked before attempting to open a BzrDir with the transport "
1375
1317
"that the open will use.", (1, 14), None))
1376
self.create_hook(hooks.HookPoint('post_repo_init',
1377
"Invoked after a repository has been initialized. "
1378
"post_repo_init is called with a "
1379
"bzrlib.bzrdir.RepoInitHookParams.",
1382
1319
# install the default hooks
1383
1320
BzrDir.hooks = BzrDirHooks()
1386
class RepoInitHookParams(object):
1387
"""Object holding parameters passed to *_repo_init hooks.
1389
There are 4 fields that hooks may wish to access:
1391
:ivar repository: Repository created
1392
:ivar format: Repository format
1393
:ivar bzrdir: The bzrdir for the repository
1394
:ivar shared: The repository is shared
1397
def __init__(self, repository, format, a_bzrdir, shared):
1398
"""Create a group of RepoInitHook parameters.
1400
:param repository: Repository created
1401
:param format: Repository format
1402
:param bzrdir: The bzrdir for the repository
1403
:param shared: The repository is shared
1405
self.repository = repository
1406
self.format = format
1407
self.bzrdir = a_bzrdir
1408
self.shared = shared
1410
def __eq__(self, other):
1411
return self.__dict__ == other.__dict__
1415
return "<%s for %s>" % (self.__class__.__name__,
1418
return "<%s for %s>" % (self.__class__.__name__,
1422
1323
class BzrDirPreSplitOut(BzrDir):
1423
1324
"""A common class for the all-in-one formats."""
1463
1364
tree.clone(result)
1466
def create_branch(self, name=None):
1367
def create_branch(self):
1467
1368
"""See BzrDir.create_branch."""
1468
return self._format.get_branch_format().initialize(self, name=name)
1369
return self._format.get_branch_format().initialize(self)
1470
def destroy_branch(self, name=None):
1371
def destroy_branch(self):
1471
1372
"""See BzrDir.destroy_branch."""
1472
1373
raise errors.UnsupportedOperation(self.destroy_branch, self)
1529
1430
raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1532
def get_branch_transport(self, branch_format, name=None):
1433
def get_branch_transport(self, branch_format):
1533
1434
"""See BzrDir.get_branch_transport()."""
1534
if name is not None:
1535
raise errors.NoColocatedBranchSupport(self)
1536
1435
if branch_format is None:
1537
1436
return self.transport
1571
1470
format = BzrDirFormat.get_default_format()
1572
1471
return not isinstance(self._format, format.__class__)
1574
def open_branch(self, name=None, unsupported=False,
1575
ignore_fallbacks=False):
1473
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1576
1474
"""See BzrDir.open_branch."""
1577
1475
from bzrlib.branch import BzrBranchFormat4
1578
1476
format = BzrBranchFormat4()
1579
1477
self._check_supported(format, unsupported)
1580
return format.open(self, name, _found=True)
1478
return format.open(self, _found=True)
1582
1480
def sprout(self, url, revision_id=None, force_new_repo=False,
1583
1481
possible_transports=None, accelerator_tree=None,
1700
1598
"""See BzrDir.can_convert_format()."""
1703
def create_branch(self, name=None):
1601
def create_branch(self):
1704
1602
"""See BzrDir.create_branch."""
1705
return self._format.get_branch_format().initialize(self, name=name)
1603
return self._format.get_branch_format().initialize(self)
1707
def destroy_branch(self, name=None):
1605
def destroy_branch(self):
1708
1606
"""See BzrDir.create_branch."""
1709
if name is not None:
1710
raise errors.NoColocatedBranchSupport(self)
1711
1607
self.transport.delete_tree('branch')
1713
1609
def create_repository(self, shared=False):
1756
1652
format = BranchFormat.find_format(self)
1757
1653
return format.get_reference(self)
1759
def get_branch_transport(self, branch_format, name=None):
1655
def get_branch_transport(self, branch_format):
1760
1656
"""See BzrDir.get_branch_transport()."""
1761
if name is not None:
1762
raise errors.NoColocatedBranchSupport(self)
1763
1657
# XXX: this shouldn't implicitly create the directory if it's just
1764
1658
# promising to get a transport -- mbp 20090727
1765
1659
if branch_format is None:
1837
1731
except errors.NoRepositoryPresent:
1839
for branch in self.list_branches():
1840
if not isinstance(branch._format,
1734
if not isinstance(self.open_branch()._format,
1841
1735
format.get_branch_format().__class__):
1842
1736
# the branch needs an upgrade.
1738
except errors.NotBranchError:
1845
1741
my_wt = self.open_workingtree(recommend_upgrade=False)
1846
1742
if not isinstance(my_wt._format,
1854
def open_branch(self, name=None, unsupported=False,
1855
ignore_fallbacks=False):
1750
def open_branch(self, unsupported=False, ignore_fallbacks=False):
1856
1751
"""See BzrDir.open_branch."""
1857
1752
format = self.find_branch_format()
1858
1753
self._check_supported(format, unsupported)
1859
return format.open(self, name=name,
1860
_found=True, ignore_fallbacks=ignore_fallbacks)
1754
return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1862
1756
def open_repository(self, unsupported=False):
1863
1757
"""See BzrDir.open_repository."""
1895
1789
Once a format is deprecated, just deprecate the initialize and open
1896
1790
methods on the format class. Do not deprecate the object, as the
1897
1791
object will be created every system load.
1899
:cvar colocated_branches: Whether this formats supports colocated branches.
1902
1794
_default_format = None
1920
1812
_lock_file_name = 'branch-lock'
1922
colocated_branches = False
1923
"""Whether co-located branches are supported for this control dir format.
1926
1814
# _lock_class must be set in subclasses to the lock type, typ.
1927
1815
# TransportLock or LockDir
2735
2623
if isinstance(self.bzrdir.transport, local.LocalTransport):
2736
2624
self.bzrdir.get_workingtree_transport(None).delete('stat-cache')
2737
2625
self._convert_to_weaves()
2738
return BzrDir.open(self.bzrdir.user_url)
2626
return BzrDir.open(self.bzrdir.root_transport.base)
2740
2628
self.pb.finished()
3116
3004
BzrDirMetaFormat1().get_format_string(),
3117
3005
mode=self.file_mode)
3118
3006
self.pb.finished()
3119
return BzrDir.open(self.bzrdir.user_url)
3007
return BzrDir.open(self.bzrdir.root_transport.base)
3121
3009
def make_lock(self, name):
3122
3010
"""Make a lock for the new control dir name."""
3704
3592
stack_on = urlutils.rebase_url(self._stack_on,
3705
3593
self._stack_on_pwd,
3594
branch.bzrdir.root_transport.base)
3707
3595
except errors.InvalidRebaseURLs:
3708
3596
stack_on = self._get_full_stack_on()