168
168
control = bzrdir.BzrDir.open(base, _unsupported,
169
169
possible_transports=possible_transports)
170
return control.open_branch(_unsupported)
170
return control.open_branch(unsupported=_unsupported)
173
def open_from_transport(transport, _unsupported=False):
173
def open_from_transport(transport, name=None, _unsupported=False):
174
174
"""Open the branch rooted at transport"""
175
175
control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
176
return control.open_branch(_unsupported)
176
return control.open_branch(name=name, unsupported=_unsupported)
179
179
def open_containing(url, possible_transports=None):
217
217
def _get_fallback_repository(self, url):
218
218
"""Get the repository we fallback to at url."""
219
219
url = urlutils.join(self.base, url)
220
a_bzrdir = bzrdir.BzrDir.open(url,
220
a_branch = Branch.open(url,
221
221
possible_transports=[self.bzrdir.root_transport])
222
return a_bzrdir.open_branch().repository
222
return a_branch.repository
224
224
def _get_tags_bytes(self):
225
225
"""Get the bytes of a serialised tags dict.
455
455
filtered = self._filter_merge_sorted_revisions(
456
456
self._merge_sorted_revisions_cache, start_revision_id,
457
457
stop_revision_id, stop_rule)
458
# Make sure we don't return revisions that are not part of the
459
# start_revision_id ancestry.
460
filtered = self._filter_non_ancestors(filtered)
458
461
if direction == 'reverse':
460
463
if direction == 'forward':
526
529
raise ValueError('invalid stop_rule %r' % stop_rule)
531
def _filter_non_ancestors(self, rev_iter):
532
# If we started from a dotted revno, we want to consider it as a tip
533
# and don't want to yield revisions that are not part of its
534
# ancestry. Given the order guaranteed by the merge sort, we will see
535
# uninteresting descendants of the first parent of our tip before the
537
first = rev_iter.next()
538
(rev_id, merge_depth, revno, end_of_merge) = first
541
# We start at a mainline revision so by definition, all others
542
# revisions in rev_iter are ancestors
543
for node in rev_iter:
548
pmap = self.repository.get_parent_map([rev_id])
549
parents = pmap.get(rev_id, [])
551
whitelist.update(parents)
553
# If there is no parents, there is nothing of interest left
555
# FIXME: It's hard to test this scenario here as this code is never
556
# called in that case. -- vila 20100322
559
for (rev_id, merge_depth, revno, end_of_merge) in rev_iter:
561
if rev_id in whitelist:
562
pmap = self.repository.get_parent_map([rev_id])
563
parents = pmap.get(rev_id, [])
564
whitelist.remove(rev_id)
565
whitelist.update(parents)
567
# We've reached the mainline, there is nothing left to
571
# A revision that is not part of the ancestry of our
574
yield (rev_id, merge_depth, revno, end_of_merge)
528
576
def leave_lock_in_place(self):
529
577
"""Tell this branch object not to release the physical lock when this
530
578
object is unlocked.
1317
1365
if lightweight:
1318
1366
format = self._get_checkout_format()
1319
1367
checkout = format.initialize_on_transport(t)
1320
from_branch = BranchReferenceFormat().initialize(checkout, self)
1368
from_branch = BranchReferenceFormat().initialize(checkout,
1322
1371
format = self._get_checkout_format()
1323
1372
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1365
1414
def supports_tags(self):
1366
1415
return self._format.supports_tags()
1417
def automatic_tag_name(self, revision_id):
1418
"""Try to automatically find the tag name for a revision.
1420
:param revision_id: Revision id of the revision.
1421
:return: A tag name or None if no tag name could be determined.
1423
for hook in Branch.hooks['automatic_tag_name']:
1424
ret = hook(self, revision_id)
1368
1429
def _check_if_descendant_or_diverged(self, revision_a, revision_b, graph,
1370
1431
"""Ensure that revision_b is a descendant of revision_a.
1434
1495
return not (self == other)
1437
def find_format(klass, a_bzrdir):
1498
def find_format(klass, a_bzrdir, name=None):
1438
1499
"""Return the format for the branch object in a_bzrdir."""
1440
transport = a_bzrdir.get_branch_transport(None)
1501
transport = a_bzrdir.get_branch_transport(None, name=name)
1441
1502
format_string = transport.get_bytes("format")
1442
1503
return klass._formats[format_string]
1443
1504
except errors.NoSuchFile:
1483
1544
"""Return the short format description for this format."""
1484
1545
raise NotImplementedError(self.get_format_description)
1486
def _initialize_helper(self, a_bzrdir, utf8_files, lock_type='metadir',
1547
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1548
lock_type='metadir', set_format=True):
1488
1549
"""Initialize a branch in a bzrdir, with specified files
1490
1551
:param a_bzrdir: The bzrdir to initialize the branch in
1491
1552
:param utf8_files: The files to create as a list of
1492
1553
(filename, content) tuples
1554
:param name: Name of colocated branch to create, if any
1493
1555
:param set_format: If True, set the format with
1494
1556
self.get_format_string. (BzrBranch4 has its format set
1496
1558
:return: a branch in this format
1498
1560
mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
1499
branch_transport = a_bzrdir.get_branch_transport(self)
1561
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1501
1563
'metadir': ('lock', lockdir.LockDir),
1502
1564
'branch4': ('branch-lock', lockable_files.TransportLock),
1525
1587
control_files.unlock()
1526
return self.open(a_bzrdir, _found=True)
1588
return self.open(a_bzrdir, name, _found=True)
1528
def initialize(self, a_bzrdir):
1529
"""Create a branch of this format in a_bzrdir."""
1590
def initialize(self, a_bzrdir, name=None):
1591
"""Create a branch of this format in a_bzrdir.
1593
:param name: Name of the colocated branch to create.
1530
1595
raise NotImplementedError(self.initialize)
1532
1597
def is_supported(self):
1563
1628
raise NotImplementedError(self.network_name)
1565
def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
1630
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1566
1631
"""Return the branch object for a_bzrdir
1568
1633
:param a_bzrdir: A BzrDir that contains a branch.
1634
:param name: Name of colocated branch to open
1569
1635
:param _found: a private parameter, do not use it. It is used to
1570
1636
indicate if format probing has already be done.
1571
1637
:param ignore_fallbacks: when set, no fallback branches will be opened
1679
1745
"multiple hooks installed for transform_fallback_location, "
1680
1746
"all are called with the url returned from the previous hook."
1681
1747
"The order is however undefined.", (1, 9), None))
1748
self.create_hook(HookPoint('automatic_tag_name',
1749
"Called to determine an automatic tag name for a revision."
1750
"automatic_tag_name is called with (branch, revision_id) and "
1751
"should return a tag name or None if no tag name could be "
1752
"determined. The first non-None tag name returned will be used.",
1684
1757
# install the default hooks into the Branch class.
1735
1808
"""See BranchFormat.get_format_description()."""
1736
1809
return "Branch format 4"
1738
def initialize(self, a_bzrdir):
1811
def initialize(self, a_bzrdir, name=None):
1739
1812
"""Create a branch of this format in a_bzrdir."""
1740
1813
utf8_files = [('revision-history', ''),
1741
1814
('branch-name', ''),
1743
return self._initialize_helper(a_bzrdir, utf8_files,
1816
return self._initialize_helper(a_bzrdir, utf8_files, name=name,
1744
1817
lock_type='branch4', set_format=False)
1746
1819
def __init__(self):
1751
1824
"""The network name for this format is the control dirs disk label."""
1752
1825
return self._matchingbzrdir.get_format_string()
1754
def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
1827
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1755
1828
"""See BranchFormat.open()."""
1757
1830
# we are being called directly and must probe.
1780
1854
return self.get_format_string()
1782
def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
1856
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1783
1857
"""See BranchFormat.open()."""
1785
format = BranchFormat.find_format(a_bzrdir)
1859
format = BranchFormat.find_format(a_bzrdir, name=name)
1786
1860
if format.__class__ != self.__class__:
1787
1861
raise AssertionError("wrong format %r found for %r" %
1788
1862
(format, self))
1790
transport = a_bzrdir.get_branch_transport(None)
1864
transport = a_bzrdir.get_branch_transport(None, name=name)
1791
1865
control_files = lockable_files.LockableFiles(transport, 'lock',
1792
1866
lockdir.LockDir)
1793
1867
return self._branch_class()(_format=self,
1794
1868
_control_files=control_files,
1795
1870
a_bzrdir=a_bzrdir,
1796
1871
_repository=a_bzrdir.find_repository(),
1797
1872
ignore_fallbacks=ignore_fallbacks)
1831
1906
"""See BranchFormat.get_format_description()."""
1832
1907
return "Branch format 5"
1834
def initialize(self, a_bzrdir):
1909
def initialize(self, a_bzrdir, name=None):
1835
1910
"""Create a branch of this format in a_bzrdir."""
1836
1911
utf8_files = [('revision-history', ''),
1837
1912
('branch-name', ''),
1839
return self._initialize_helper(a_bzrdir, utf8_files)
1914
return self._initialize_helper(a_bzrdir, utf8_files, name)
1841
1916
def supports_tags(self):
1864
1939
"""See BranchFormat.get_format_description()."""
1865
1940
return "Branch format 6"
1867
def initialize(self, a_bzrdir):
1942
def initialize(self, a_bzrdir, name=None):
1868
1943
"""Create a branch of this format in a_bzrdir."""
1869
1944
utf8_files = [('last-revision', '0 null:\n'),
1870
1945
('branch.conf', ''),
1873
return self._initialize_helper(a_bzrdir, utf8_files)
1948
return self._initialize_helper(a_bzrdir, utf8_files, name)
1875
1950
def make_tags(self, branch):
1876
1951
"""See bzrlib.branch.BranchFormat.make_tags()."""
1894
1969
"""See BranchFormat.get_format_description()."""
1895
1970
return "Branch format 8"
1897
def initialize(self, a_bzrdir):
1972
def initialize(self, a_bzrdir, name=None):
1898
1973
"""Create a branch of this format in a_bzrdir."""
1899
1974
utf8_files = [('last-revision', '0 null:\n'),
1900
1975
('branch.conf', ''),
1902
1977
('references', '')
1904
return self._initialize_helper(a_bzrdir, utf8_files)
1979
return self._initialize_helper(a_bzrdir, utf8_files, name)
1906
1981
def __init__(self):
1907
1982
super(BzrBranchFormat8, self).__init__()
1930
2005
This format was introduced in bzr 1.6.
1933
def initialize(self, a_bzrdir):
2008
def initialize(self, a_bzrdir, name=None):
1934
2009
"""Create a branch of this format in a_bzrdir."""
1935
2010
utf8_files = [('last-revision', '0 null:\n'),
1936
2011
('branch.conf', ''),
1939
return self._initialize_helper(a_bzrdir, utf8_files)
2014
return self._initialize_helper(a_bzrdir, utf8_files, name)
1941
2016
def _branch_class(self):
1942
2017
return BzrBranch7
1984
2059
transport = a_bzrdir.get_branch_transport(None)
1985
2060
location = transport.put_bytes('location', to_branch.base)
1987
def initialize(self, a_bzrdir, target_branch=None):
2062
def initialize(self, a_bzrdir, name=None, target_branch=None):
1988
2063
"""Create a branch of this format in a_bzrdir."""
1989
2064
if target_branch is None:
1990
2065
# this format does not implement branch itself, thus the implicit
1991
2066
# creation contract must see it as uninitializable
1992
2067
raise errors.UninitializableFormat(self)
1993
2068
mutter('creating branch reference in %s', a_bzrdir.transport.base)
1994
branch_transport = a_bzrdir.get_branch_transport(self)
2069
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1995
2070
branch_transport.put_bytes('location',
1996
2071
target_branch.bzrdir.root_transport.base)
1997
2072
branch_transport.put_bytes('format', self.get_format_string())
1998
2073
return self.open(
1999
a_bzrdir, _found=True,
2074
a_bzrdir, name, _found=True,
2000
2075
possible_transports=[target_branch.bzrdir.root_transport])
2002
2077
def __init__(self):
2009
2084
def clone(to_bzrdir, revision_id=None,
2010
2085
repository_policy=None):
2011
2086
"""See Branch.clone()."""
2012
return format.initialize(to_bzrdir, a_branch)
2087
return format.initialize(to_bzrdir, target_branch=a_branch)
2013
2088
# cannot obey revision_id limits when cloning a reference ...
2014
2089
# FIXME RBC 20060210 either nuke revision_id for clone, or
2015
2090
# emit some sort of warning/error to the caller ?!
2018
def open(self, a_bzrdir, _found=False, location=None,
2093
def open(self, a_bzrdir, name=None, _found=False, location=None,
2019
2094
possible_transports=None, ignore_fallbacks=False):
2020
2095
"""Return the branch that the branch reference in a_bzrdir points at.
2022
2097
:param a_bzrdir: A BzrDir that contains a branch.
2098
:param name: Name of colocated branch to open, if any
2023
2099
:param _found: a private parameter, do not use it. It is used to
2024
2100
indicate if format probing has already be done.
2025
2101
:param ignore_fallbacks: when set, no fallback branches will be opened
2030
2106
:param possible_transports: An optional reusable transports list.
2033
format = BranchFormat.find_format(a_bzrdir)
2109
format = BranchFormat.find_format(a_bzrdir, name=name)
2034
2110
if format.__class__ != self.__class__:
2035
2111
raise AssertionError("wrong format %r found for %r" %
2036
2112
(format, self))
2038
2114
location = self.get_reference(a_bzrdir)
2039
2115
real_bzrdir = bzrdir.BzrDir.open(
2040
2116
location, possible_transports=possible_transports)
2041
result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2117
result = real_bzrdir.open_branch(name=name,
2118
ignore_fallbacks=ignore_fallbacks)
2042
2119
# this changes the behaviour of result.clone to create a new reference
2043
2120
# rather than a copy of the content of the branch.
2044
2121
# I did not use a proxy object because that needs much more extensive
2090
2167
:ivar repository: Repository for this branch.
2091
2168
:ivar base: The url of the base directory for this branch; the one
2092
2169
containing the .bzr directory.
2170
:ivar name: Optional colocated branch name as it exists in the control
2095
2174
def __init__(self, _format=None,
2096
_control_files=None, a_bzrdir=None, _repository=None,
2097
ignore_fallbacks=False):
2175
_control_files=None, a_bzrdir=None, name=None,
2176
_repository=None, ignore_fallbacks=False):
2098
2177
"""Create new branch object at a particular location."""
2099
2178
if a_bzrdir is None:
2100
2179
raise ValueError('a_bzrdir must be supplied')
2102
2181
self.bzrdir = a_bzrdir
2103
2182
self._base = self.bzrdir.transport.clone('..').base
2104
2184
# XXX: We should be able to just do
2105
2185
# self.base = self.bzrdir.root_transport.base
2106
2186
# but this does not quite work yet -- mbp 20080522
2113
2193
Branch.__init__(self)
2115
2195
def __str__(self):
2116
return '%s(%r)' % (self.__class__.__name__, self.base)
2196
if self.name is None:
2197
return '%s(%r)' % (self.__class__.__name__, self.base)
2199
return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name)
2118
2201
__repr__ = __str__