44
43
from bzrlib.config import BranchConfig, TransportConfig
44
from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5RichRoot
45
45
from bzrlib.tag import (
54
from bzrlib.decorators import (
59
from bzrlib.hooks import Hooks
51
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
52
from bzrlib.hooks import HookPoint, Hooks
60
53
from bzrlib.inter import InterObject
61
54
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
62
55
from bzrlib import registry
115
105
def _activate_fallback_location(self, url):
116
106
"""Activate the branch/repository from url as a fallback repository."""
117
for existing_fallback_repo in self.repository._fallback_repositories:
118
if existing_fallback_repo.user_url == url:
119
# This fallback is already configured. This probably only
120
# happens because BzrDir.sprout is a horrible mess. To avoid
121
# confusing _unstack we don't add this a second time.
122
mutter('duplicate activation of fallback %r on %r', url, self)
124
107
repo = self._get_fallback_repository(url)
125
108
if repo.has_same_location(self.repository):
126
109
raise errors.UnstackableLocationError(self.user_url, url)
669
649
raise errors.UnsupportedOperation(self.get_reference_info, self)
671
651
@needs_write_lock
672
def fetch(self, from_branch, last_revision=None):
652
def fetch(self, from_branch, last_revision=None, pb=None):
673
653
"""Copy revisions from from_branch into this branch.
675
655
:param from_branch: Where to copy from.
676
656
:param last_revision: What revision to stop at (None for at the end
658
:param pb: An optional progress bar to use.
680
return InterBranch.get(from_branch, self).fetch(last_revision)
661
if self.base == from_branch.base:
664
symbol_versioning.warn(
665
symbol_versioning.deprecated_in((1, 14, 0))
666
% "pb parameter to fetch()")
667
from_branch.lock_read()
669
if last_revision is None:
670
last_revision = from_branch.last_revision()
671
last_revision = _mod_revision.ensure_null(last_revision)
672
return self.repository.fetch(from_branch.repository,
673
revision_id=last_revision,
682
678
def get_bound_location(self):
683
679
"""Return the URL of the branch we are bound to.
704
700
:param committer: Optional committer to set for commit.
705
701
:param revprops: Optional dictionary of revision properties.
706
702
:param revision_id: Optional revision id.
707
:param lossy: Whether to discard data that can not be natively
708
represented, when pushing to a foreign VCS
711
705
if config is None:
712
706
config = self.get_config()
714
708
return self.repository.get_commit_builder(self, parents, config,
715
timestamp, timezone, committer, revprops, revision_id,
709
timestamp, timezone, committer, revprops, revision_id)
718
711
def get_master_branch(self, possible_transports=None):
719
712
"""Return the branch we are bound to.
812
805
old_repository = self.repository
813
806
if len(old_repository._fallback_repositories) != 1:
814
807
raise AssertionError("can't cope with fallback repositories "
815
"of %r (fallbacks: %r)" % (old_repository,
816
old_repository._fallback_repositories))
808
"of %r" % (self.repository,))
817
809
# Open the new repository object.
818
810
# Repositories don't offer an interface to remove fallback
819
811
# repositories today; take the conceptually simpler option and just
867
859
# XXX: If you unstack a branch while it has a working tree
868
860
# with a pending merge, the pending-merged revisions will no
869
861
# longer be present. You can (probably) revert and remerge.
871
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
872
except errors.TagsNotSupported:
873
tags_to_fetch = set()
874
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
875
old_repository, required_ids=[self.last_revision()],
876
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
877
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
863
# XXX: This only fetches up to the tip of the repository; it
864
# doesn't bring across any tags. That's fairly consistent
865
# with how branch works, but perhaps not ideal.
866
self.repository.fetch(old_repository,
867
revision_id=self.last_revision(),
879
870
old_repository.unlock()
886
877
:seealso: Branch._get_tags_bytes.
888
return _run_with_write_locked_target(self, self._set_tags_bytes_locked,
891
def _set_tags_bytes_locked(self, bytes):
892
self._tags_bytes = bytes
893
return self._transport.put_bytes('tags', bytes)
879
return _run_with_write_locked_target(self, self._transport.put_bytes,
895
882
def _cache_revision_history(self, rev_history):
896
883
"""Set the cached revision history to rev_history.
995
980
return (0, _mod_revision.NULL_REVISION)
997
@deprecated_method(deprecated_in((2, 4, 0)))
982
@deprecated_method(deprecated_in((1, 6, 0)))
983
def missing_revisions(self, other, stop_revision=None):
984
"""Return a list of new revisions that would perfectly fit.
986
If self and other have not diverged, return a list of the revisions
987
present in other, but missing from self.
989
self_history = self.revision_history()
990
self_len = len(self_history)
991
other_history = other.revision_history()
992
other_len = len(other_history)
993
common_index = min(self_len, other_len) -1
994
if common_index >= 0 and \
995
self_history[common_index] != other_history[common_index]:
996
raise errors.DivergedBranches(self, other)
998
if stop_revision is None:
999
stop_revision = other_len
1001
if stop_revision > other_len:
1002
raise errors.NoSuchRevision(self, stop_revision)
1003
return other_history[self_len:stop_revision]
1005
def update_revisions(self, other, stop_revision=None, overwrite=False,
1007
"""Pull in new perfect-fit revisions.
1009
:param other: Another Branch to pull from
1010
:param stop_revision: Updated until the given revision
1011
:param overwrite: Always set the branch pointer, rather than checking
1012
to see if it is a proper descendant.
1013
:param graph: A Graph object that can be used to query history
1014
information. This can be None.
1017
return InterBranch.get(other, self).update_revisions(stop_revision,
998
1020
def import_last_revision_info(self, source_repo, revno, revid):
999
1021
"""Set the last revision info, importing from another repo if necessary.
1023
This is used by the bound branch code to upload a revision to
1024
the master branch first before updating the tip of the local branch.
1001
1026
:param source_repo: Source repository to optionally fetch from
1002
1027
:param revno: Revision number of the new tip
1003
1028
:param revid: Revision id of the new tip
1006
1031
self.repository.fetch(source_repo, revision_id=revid)
1007
1032
self.set_last_revision_info(revno, revid)
1009
def import_last_revision_info_and_tags(self, source, revno, revid,
1011
"""Set the last revision info, importing from another repo if necessary.
1013
This is used by the bound branch code to upload a revision to
1014
the master branch first before updating the tip of the local branch.
1015
Revisions referenced by source's tags are also transferred.
1017
:param source: Source branch to optionally fetch from
1018
:param revno: Revision number of the new tip
1019
:param revid: Revision id of the new tip
1020
:param lossy: Whether to discard metadata that can not be
1021
natively represented
1022
:return: Tuple with the new revision number and revision id
1023
(should only be different from the arguments when lossy=True)
1025
if not self.repository.has_same_location(source.repository):
1026
self.fetch(source, revid)
1027
self.set_last_revision_info(revno, revid)
1028
return (revno, revid)
1030
1034
def revision_id_to_revno(self, revision_id):
1031
1035
"""Given a revision id, return its revno"""
1032
1036
if _mod_revision.is_null(revision_id):
1359
1362
"""Return the most suitable metadir for a checkout of this branch.
1360
1363
Weaves are used if this branch's repository uses weaves.
1362
format = self.repository.bzrdir.checkout_metadir()
1363
format.set_branch_format(self._format)
1365
if isinstance(self.bzrdir, bzrdir.BzrDirPreSplitOut):
1366
from bzrlib.repofmt import weaverepo
1367
format = bzrdir.BzrDirMetaFormat1()
1368
format.repository_format = weaverepo.RepositoryFormat7()
1370
format = self.repository.bzrdir.checkout_metadir()
1371
format.set_branch_format(self._format)
1366
1374
def create_clone_on_transport(self, to_transport, revision_id=None,
1507
1515
raise AssertionError("invalid heads: %r" % (heads,))
1509
def heads_to_fetch(self):
1510
"""Return the heads that must and that should be fetched to copy this
1511
branch into another repo.
1513
:returns: a 2-tuple of (must_fetch, if_present_fetch). must_fetch is a
1514
set of heads that must be fetched. if_present_fetch is a set of
1515
heads that must be fetched if present, but no error is necessary if
1516
they are not present.
1518
# For bzr native formats must_fetch is just the tip, and if_present_fetch
1520
must_fetch = set([self.last_revision()])
1522
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1523
except errors.TagsNotSupported:
1524
if_present_fetch = set()
1525
must_fetch.discard(_mod_revision.NULL_REVISION)
1526
if_present_fetch.discard(_mod_revision.NULL_REVISION)
1527
return must_fetch, if_present_fetch
1530
class BranchFormat(controldir.ControlComponentFormat):
1518
class BranchFormat(object):
1531
1519
"""An encapsulation of the initialization and open routines for a format.
1533
1521
Formats provide three things:
1560
1554
transport = a_bzrdir.get_branch_transport(None, name=name)
1561
1555
format_string = transport.get_bytes("format")
1562
return format_registry.get(format_string)
1556
format = klass._formats[format_string]
1557
if isinstance(format, MetaDirBranchFormatFactory):
1563
1560
except errors.NoSuchFile:
1564
1561
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1565
1562
except KeyError:
1566
1563
raise errors.UnknownFormatError(format=format_string, kind='branch')
1569
@deprecated_method(deprecated_in((2, 4, 0)))
1570
1566
def get_default_format(klass):
1571
1567
"""Return the current default format."""
1572
return format_registry.get_default()
1568
return klass._default_format
1575
@deprecated_method(deprecated_in((2, 4, 0)))
1576
1571
def get_formats(klass):
1577
1572
"""Get all the known formats.
1579
1574
Warning: This triggers a load of all lazy registered formats: do not
1580
1575
use except when that is desireed.
1582
return format_registry._get_all()
1578
for fmt in klass._formats.values():
1579
if isinstance(fmt, MetaDirBranchFormatFactory):
1584
1584
def get_reference(self, a_bzrdir, name=None):
1585
1585
"""Get the target reference of the branch in a_bzrdir.
1624
1624
for hook in hooks:
1627
def initialize(self, a_bzrdir, name=None, repository=None):
1627
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1628
lock_type='metadir', set_format=True):
1629
"""Initialize a branch in a bzrdir, with specified files
1631
:param a_bzrdir: The bzrdir to initialize the branch in
1632
:param utf8_files: The files to create as a list of
1633
(filename, content) tuples
1634
:param name: Name of colocated branch to create, if any
1635
:param set_format: If True, set the format with
1636
self.get_format_string. (BzrBranch4 has its format set
1638
:return: a branch in this format
1640
mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1641
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1643
'metadir': ('lock', lockdir.LockDir),
1644
'branch4': ('branch-lock', lockable_files.TransportLock),
1646
lock_name, lock_class = lock_map[lock_type]
1647
control_files = lockable_files.LockableFiles(branch_transport,
1648
lock_name, lock_class)
1649
control_files.create_lock()
1651
control_files.lock_write()
1652
except errors.LockContention:
1653
if lock_type != 'branch4':
1659
utf8_files += [('format', self.get_format_string())]
1661
for (filename, content) in utf8_files:
1662
branch_transport.put_bytes(
1664
mode=a_bzrdir._get_file_mode())
1667
control_files.unlock()
1668
branch = self.open(a_bzrdir, name, _found=True)
1669
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1672
def initialize(self, a_bzrdir, name=None):
1628
1673
"""Create a branch of this format in a_bzrdir.
1630
1675
:param name: Name of the colocated branch to create.
1665
1710
raise NotImplementedError(self.network_name)
1667
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1668
found_repository=None):
1712
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1669
1713
"""Return the branch object for a_bzrdir
1671
1715
:param a_bzrdir: A BzrDir that contains a branch.
1678
1722
raise NotImplementedError(self.open)
1681
@deprecated_method(deprecated_in((2, 4, 0)))
1682
1725
def register_format(klass, format):
1683
1726
"""Register a metadir format.
1685
1728
See MetaDirBranchFormatFactory for the ability to register a format
1686
1729
without loading the code the format needs until it is actually used.
1688
format_registry.register(format)
1731
klass._formats[format.get_format_string()] = format
1732
# Metadir formats have a network name of their format string, and get
1733
# registered as factories.
1734
if isinstance(format, MetaDirBranchFormatFactory):
1735
network_format_registry.register(format.get_format_string(), format)
1737
network_format_registry.register(format.get_format_string(),
1691
@deprecated_method(deprecated_in((2, 4, 0)))
1692
1741
def set_default_format(klass, format):
1693
format_registry.set_default(format)
1742
klass._default_format = format
1695
1744
def supports_set_append_revisions_only(self):
1696
1745
"""True if this format supports set_append_revisions_only."""
1700
1749
"""True if this format records a stacked-on branch."""
1703
def supports_leaving_lock(self):
1704
"""True if this format supports leaving locks in place."""
1705
return False # by default
1708
@deprecated_method(deprecated_in((2, 4, 0)))
1709
1753
def unregister_format(klass, format):
1710
format_registry.remove(format)
1754
del klass._formats[format.get_format_string()]
1712
1756
def __str__(self):
1713
1757
return self.get_format_description().rstrip()
1758
1802
These are all empty initially, because by default nothing should get
1761
Hooks.__init__(self, "bzrlib.branch", "Branch.hooks")
1762
self.add_hook('set_rh',
1805
Hooks.__init__(self)
1806
self.create_hook(HookPoint('set_rh',
1763
1807
"Invoked whenever the revision history has been set via "
1764
1808
"set_revision_history. The api signature is (branch, "
1765
1809
"revision_history), and the branch will be write-locked. "
1766
1810
"The set_rh hook can be expensive for bzr to trigger, a better "
1767
"hook to use is Branch.post_change_branch_tip.", (0, 15))
1768
self.add_hook('open',
1811
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1812
self.create_hook(HookPoint('open',
1769
1813
"Called with the Branch object that has been opened after a "
1770
"branch is opened.", (1, 8))
1771
self.add_hook('post_push',
1814
"branch is opened.", (1, 8), None))
1815
self.create_hook(HookPoint('post_push',
1772
1816
"Called after a push operation completes. post_push is called "
1773
1817
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1774
"bzr client.", (0, 15))
1775
self.add_hook('post_pull',
1818
"bzr client.", (0, 15), None))
1819
self.create_hook(HookPoint('post_pull',
1776
1820
"Called after a pull operation completes. post_pull is called "
1777
1821
"with a bzrlib.branch.PullResult object and only runs in the "
1778
"bzr client.", (0, 15))
1779
self.add_hook('pre_commit',
1822
"bzr client.", (0, 15), None))
1823
self.create_hook(HookPoint('pre_commit',
1780
1824
"Called after a commit is calculated but before it is "
1781
1825
"completed. pre_commit is called with (local, master, old_revno, "
1782
1826
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1785
1829
"basis revision. hooks MUST NOT modify this delta. "
1786
1830
" future_tree is an in-memory tree obtained from "
1787
1831
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1789
self.add_hook('post_commit',
1832
"tree.", (0,91), None))
1833
self.create_hook(HookPoint('post_commit',
1790
1834
"Called in the bzr client after a commit has completed. "
1791
1835
"post_commit is called with (local, master, old_revno, old_revid, "
1792
1836
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1793
"commit to a branch.", (0, 15))
1794
self.add_hook('post_uncommit',
1837
"commit to a branch.", (0, 15), None))
1838
self.create_hook(HookPoint('post_uncommit',
1795
1839
"Called in the bzr client after an uncommit completes. "
1796
1840
"post_uncommit is called with (local, master, old_revno, "
1797
1841
"old_revid, new_revno, new_revid) where local is the local branch "
1798
1842
"or None, master is the target branch, and an empty branch "
1799
"receives new_revno of 0, new_revid of None.", (0, 15))
1800
self.add_hook('pre_change_branch_tip',
1843
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1844
self.create_hook(HookPoint('pre_change_branch_tip',
1801
1845
"Called in bzr client and server before a change to the tip of a "
1802
1846
"branch is made. pre_change_branch_tip is called with a "
1803
1847
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1804
"commit, uncommit will all trigger this hook.", (1, 6))
1805
self.add_hook('post_change_branch_tip',
1848
"commit, uncommit will all trigger this hook.", (1, 6), None))
1849
self.create_hook(HookPoint('post_change_branch_tip',
1806
1850
"Called in bzr client and server after a change to the tip of a "
1807
1851
"branch is made. post_change_branch_tip is called with a "
1808
1852
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1809
"commit, uncommit will all trigger this hook.", (1, 4))
1810
self.add_hook('transform_fallback_location',
1853
"commit, uncommit will all trigger this hook.", (1, 4), None))
1854
self.create_hook(HookPoint('transform_fallback_location',
1811
1855
"Called when a stacked branch is activating its fallback "
1812
1856
"locations. transform_fallback_location is called with (branch, "
1813
1857
"url), and should return a new url. Returning the same url "
1818
1862
"fallback locations have not been activated. When there are "
1819
1863
"multiple hooks installed for transform_fallback_location, "
1820
1864
"all are called with the url returned from the previous hook."
1821
"The order is however undefined.", (1, 9))
1822
self.add_hook('automatic_tag_name',
1865
"The order is however undefined.", (1, 9), None))
1866
self.create_hook(HookPoint('automatic_tag_name',
1823
1867
"Called to determine an automatic tag name for a revision. "
1824
1868
"automatic_tag_name is called with (branch, revision_id) and "
1825
1869
"should return a tag name or None if no tag name could be "
1826
1870
"determined. The first non-None tag name returned will be used.",
1828
self.add_hook('post_branch_init',
1872
self.create_hook(HookPoint('post_branch_init',
1829
1873
"Called after new branch initialization completes. "
1830
1874
"post_branch_init is called with a "
1831
1875
"bzrlib.branch.BranchInitHookParams. "
1832
1876
"Note that init, branch and checkout (both heavyweight and "
1833
"lightweight) will all trigger this hook.", (2, 2))
1834
self.add_hook('post_switch',
1877
"lightweight) will all trigger this hook.", (2, 2), None))
1878
self.create_hook(HookPoint('post_switch',
1835
1879
"Called after a checkout switches branch. "
1836
1880
"post_switch is called with a "
1837
"bzrlib.branch.SwitchHookParams.", (2, 2))
1881
"bzrlib.branch.SwitchHookParams.", (2, 2), None))
1953
1997
self.revision_id)
2000
class BzrBranchFormat4(BranchFormat):
2001
"""Bzr branch format 4.
2004
- a revision-history file.
2005
- a branch-lock lock file [ to be shared with the bzrdir ]
2008
def get_format_description(self):
2009
"""See BranchFormat.get_format_description()."""
2010
return "Branch format 4"
2012
def initialize(self, a_bzrdir, name=None):
2013
"""Create a branch of this format in a_bzrdir."""
2014
utf8_files = [('revision-history', ''),
2015
('branch-name', ''),
2017
return self._initialize_helper(a_bzrdir, utf8_files, name=name,
2018
lock_type='branch4', set_format=False)
2021
super(BzrBranchFormat4, self).__init__()
2022
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2024
def network_name(self):
2025
"""The network name for this format is the control dirs disk label."""
2026
return self._matchingbzrdir.get_format_string()
2028
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2029
"""See BranchFormat.open()."""
2031
# we are being called directly and must probe.
2032
raise NotImplementedError
2033
return BzrBranch(_format=self,
2034
_control_files=a_bzrdir._control_files,
2037
_repository=a_bzrdir.open_repository())
2040
return "Bazaar-NG branch format 4"
1956
2043
class BranchFormatMetadir(BranchFormat):
1957
2044
"""Common logic for meta-dir based branch formats."""
1960
2047
"""What class to instantiate on open calls."""
1961
2048
raise NotImplementedError(self._branch_class)
1963
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1965
"""Initialize a branch in a bzrdir, with specified files
1967
:param a_bzrdir: The bzrdir to initialize the branch in
1968
:param utf8_files: The files to create as a list of
1969
(filename, content) tuples
1970
:param name: Name of colocated branch to create, if any
1971
:return: a branch in this format
1973
mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1974
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1975
control_files = lockable_files.LockableFiles(branch_transport,
1976
'lock', lockdir.LockDir)
1977
control_files.create_lock()
1978
control_files.lock_write()
1980
utf8_files += [('format', self.get_format_string())]
1981
for (filename, content) in utf8_files:
1982
branch_transport.put_bytes(
1984
mode=a_bzrdir._get_file_mode())
1986
control_files.unlock()
1987
branch = self.open(a_bzrdir, name, _found=True,
1988
found_repository=repository)
1989
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1992
2050
def network_name(self):
1993
2051
"""A simple byte string uniquely identifying this format for RPC calls.
1997
2055
return self.get_format_string()
1999
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2000
found_repository=None):
2057
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2001
2058
"""See BranchFormat.open()."""
2003
2060
format = BranchFormat.find_format(a_bzrdir, name=name)
2009
2066
control_files = lockable_files.LockableFiles(transport, 'lock',
2010
2067
lockdir.LockDir)
2011
if found_repository is None:
2012
found_repository = a_bzrdir.find_repository()
2013
2068
return self._branch_class()(_format=self,
2014
2069
_control_files=control_files,
2016
2071
a_bzrdir=a_bzrdir,
2017
_repository=found_repository,
2072
_repository=a_bzrdir.find_repository(),
2018
2073
ignore_fallbacks=ignore_fallbacks)
2019
2074
except errors.NoSuchFile:
2020
2075
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2055
2107
"""See BranchFormat.get_format_description()."""
2056
2108
return "Branch format 5"
2058
def initialize(self, a_bzrdir, name=None, repository=None):
2110
def initialize(self, a_bzrdir, name=None):
2059
2111
"""Create a branch of this format in a_bzrdir."""
2060
2112
utf8_files = [('revision-history', ''),
2061
2113
('branch-name', ''),
2063
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2115
return self._initialize_helper(a_bzrdir, utf8_files, name)
2065
2117
def supports_tags(self):
2088
2140
"""See BranchFormat.get_format_description()."""
2089
2141
return "Branch format 6"
2091
def initialize(self, a_bzrdir, name=None, repository=None):
2143
def initialize(self, a_bzrdir, name=None):
2092
2144
"""Create a branch of this format in a_bzrdir."""
2093
2145
utf8_files = [('last-revision', '0 null:\n'),
2094
2146
('branch.conf', ''),
2097
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2149
return self._initialize_helper(a_bzrdir, utf8_files, name)
2099
2151
def make_tags(self, branch):
2100
2152
"""See bzrlib.branch.BranchFormat.make_tags()."""
2118
2170
"""See BranchFormat.get_format_description()."""
2119
2171
return "Branch format 8"
2121
def initialize(self, a_bzrdir, name=None, repository=None):
2173
def initialize(self, a_bzrdir, name=None):
2122
2174
"""Create a branch of this format in a_bzrdir."""
2123
2175
utf8_files = [('last-revision', '0 null:\n'),
2124
2176
('branch.conf', ''),
2126
2178
('references', '')
2128
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2180
return self._initialize_helper(a_bzrdir, utf8_files, name)
2183
super(BzrBranchFormat8, self).__init__()
2184
self._matchingbzrdir.repository_format = \
2185
RepositoryFormatKnitPack5RichRoot()
2130
2187
def make_tags(self, branch):
2131
2188
"""See bzrlib.branch.BranchFormat.make_tags()."""
2149
2206
This format was introduced in bzr 1.6.
2152
def initialize(self, a_bzrdir, name=None, repository=None):
2209
def initialize(self, a_bzrdir, name=None):
2153
2210
"""Create a branch of this format in a_bzrdir."""
2154
2211
utf8_files = [('last-revision', '0 null:\n'),
2155
2212
('branch.conf', ''),
2158
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2215
return self._initialize_helper(a_bzrdir, utf8_files, name)
2160
2217
def _branch_class(self):
2161
2218
return BzrBranch7
2210
2260
transport = a_bzrdir.get_branch_transport(None, name=name)
2211
2261
location = transport.put_bytes('location', to_branch.base)
2213
def initialize(self, a_bzrdir, name=None, target_branch=None,
2263
def initialize(self, a_bzrdir, name=None, target_branch=None):
2215
2264
"""Create a branch of this format in a_bzrdir."""
2216
2265
if target_branch is None:
2217
2266
# this format does not implement branch itself, thus the implicit
2286
class BranchFormatRegistry(controldir.ControlComponentFormatRegistry):
2287
"""Branch format registry."""
2289
def __init__(self, other_registry=None):
2290
super(BranchFormatRegistry, self).__init__(other_registry)
2291
self._default_format = None
2293
def set_default(self, format):
2294
self._default_format = format
2296
def get_default(self):
2297
return self._default_format
2300
2334
network_format_registry = registry.FormatRegistry()
2301
2335
"""Registry of formats indexed by their network name.
2314
2346
__format6 = BzrBranchFormat6()
2315
2347
__format7 = BzrBranchFormat7()
2316
2348
__format8 = BzrBranchFormat8()
2317
format_registry.register(__format5)
2318
format_registry.register(BranchReferenceFormat())
2319
format_registry.register(__format6)
2320
format_registry.register(__format7)
2321
format_registry.register(__format8)
2322
format_registry.set_default(__format7)
2349
BranchFormat.register_format(__format5)
2350
BranchFormat.register_format(BranchReferenceFormat())
2351
BranchFormat.register_format(__format6)
2352
BranchFormat.register_format(__format7)
2353
BranchFormat.register_format(__format8)
2354
BranchFormat.set_default_format(__format7)
2355
_legacy_formats = [BzrBranchFormat4(),
2357
network_format_registry.register(
2358
_legacy_formats[0].network_name(), _legacy_formats[0].__class__)
2325
2361
class BranchWriteLockResult(LogicalLockResult):
2482
2518
'revision-history', '\n'.join(history),
2483
2519
mode=self.bzrdir._get_file_mode())
2485
@deprecated_method(deprecated_in((2, 4, 0)))
2486
2522
def set_revision_history(self, rev_history):
2487
2523
"""See Branch.set_revision_history."""
2488
self._set_revision_history(rev_history)
2491
def _set_revision_history(self, rev_history):
2492
2524
if 'evil' in debug.debug_flags:
2493
2525
mutter_callsite(3, "set_revision_history scales with history.")
2494
2526
check_not_reserved_id = _mod_revision.check_not_reserved_id
2552
2584
configured to check constraints on history, in which case this may not
2555
if not revision_id or not isinstance(revision_id, basestring):
2556
raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2587
revision_id = _mod_revision.ensure_null(revision_id)
2557
2588
# this old format stores the full history, but this api doesn't
2558
2589
# provide it, so we must generate, and might as well check it's
2560
2591
history = self._lefthand_history(revision_id)
2561
2592
if len(history) != revno:
2562
2593
raise AssertionError('%d != %d' % (len(history), revno))
2563
self._set_revision_history(history)
2594
self.set_revision_history(history)
2565
2596
def _gen_revision_history(self):
2566
2597
history = self._transport.get_bytes('revision-history').split('\n')
2630
def _basic_push(self, target, overwrite, stop_revision):
2631
"""Basic implementation of push without bound branches or hooks.
2633
Must be called with source read locked and target write locked.
2635
result = BranchPushResult()
2636
result.source_branch = self
2637
result.target_branch = target
2638
result.old_revno, result.old_revid = target.last_revision_info()
2639
self.update_references(target)
2640
if result.old_revid != self.last_revision():
2641
# We assume that during 'push' this repository is closer than
2643
graph = self.repository.get_graph(target.repository)
2644
target.update_revisions(self, stop_revision,
2645
overwrite=overwrite, graph=graph)
2646
if self._push_should_merge_tags():
2647
result.tag_conflicts = self.tags.merge_to(target.tags,
2649
result.new_revno, result.new_revid = target.last_revision_info()
2599
2652
def get_stacked_on_url(self):
2600
2653
raise errors.UnstackableBranchFormat(self._format, self.user_url)
2630
2683
"""Return the branch we are bound to.
2632
2685
:return: Either a Branch, or None
2687
This could memoise the branch, but if thats done
2688
it must be revalidated on each new lock.
2689
So for now we just don't memoise it.
2690
# RBC 20060304 review this decision.
2634
if self._master_branch_cache is None:
2635
self._master_branch_cache = self._get_master_branch(
2636
possible_transports)
2637
return self._master_branch_cache
2639
def _get_master_branch(self, possible_transports):
2640
2692
bound_loc = self.get_bound_location()
2641
2693
if not bound_loc:
2769
2820
@needs_write_lock
2770
2821
def set_last_revision_info(self, revno, revision_id):
2771
if not revision_id or not isinstance(revision_id, basestring):
2772
raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2822
revision_id = _mod_revision.ensure_null(revision_id)
2773
2823
old_revno, old_revid = self.last_revision_info()
2774
2824
if self._get_append_revisions_only():
2775
2825
self._check_history_violation(revision_id)
2996
3045
index = self._partial_revision_history_cache.index(revision_id)
2997
3046
except ValueError:
2999
self._extend_partial_history(stop_revision=revision_id)
3000
except errors.RevisionNotPresent, e:
3001
raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
3047
self._extend_partial_history(stop_revision=revision_id)
3002
3048
index = len(self._partial_revision_history_cache) - 1
3003
3049
if self._partial_revision_history_cache[index] != revision_id:
3004
3050
raise errors.NoSuchRevision(self, revision_id)
3251
3297
raise NotImplementedError(self.pull)
3253
3299
@needs_write_lock
3300
def update_revisions(self, stop_revision=None, overwrite=False,
3302
"""Pull in new perfect-fit revisions.
3304
:param stop_revision: Updated until the given revision
3305
:param overwrite: Always set the branch pointer, rather than checking
3306
to see if it is a proper descendant.
3307
:param graph: A Graph object that can be used to query history
3308
information. This can be None.
3311
raise NotImplementedError(self.update_revisions)
3254
3314
def push(self, overwrite=False, stop_revision=None,
3255
3315
_override_hook_source_branch=None):
3256
3316
"""Mirror the source branch into the target branch.
3289
3341
def _get_branch_formats_to_test(klass):
3290
return [(format_registry.get_default(), format_registry.get_default())]
3342
return [(BranchFormat._default_format, BranchFormat._default_format)]
3293
3345
def unwrap_format(klass, format):
3294
3346
if isinstance(format, remote.RemoteBranchFormat):
3295
3347
format._ensure_real()
3296
3348
return format._custom_format
3299
3351
@needs_write_lock
3300
3352
def copy_content_into(self, revision_id=None):
3316
3368
self.source.tags.merge_to(self.target.tags)
3318
3370
@needs_write_lock
3319
def fetch(self, stop_revision=None):
3320
if self.target.base == self.source.base:
3322
self.source.lock_read()
3324
fetch_spec_factory = fetch.FetchSpecFactory()
3325
fetch_spec_factory.source_branch = self.source
3326
fetch_spec_factory.source_branch_stop_revision_id = stop_revision
3327
fetch_spec_factory.source_repo = self.source.repository
3328
fetch_spec_factory.target_repo = self.target.repository
3329
fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
3330
fetch_spec = fetch_spec_factory.make_fetch_spec()
3331
return self.target.repository.fetch(self.source.repository,
3332
fetch_spec=fetch_spec)
3334
self.source.unlock()
3337
def _update_revisions(self, stop_revision=None, overwrite=False,
3371
def update_revisions(self, stop_revision=None, overwrite=False,
3373
"""See InterBranch.update_revisions()."""
3339
3374
other_revno, other_last_revision = self.source.last_revision_info()
3340
3375
stop_revno = None # unknown
3341
3376
if stop_revision is None:
3428
3461
self.source.unlock()
3430
def _basic_push(self, overwrite, stop_revision):
3431
"""Basic implementation of push without bound branches or hooks.
3433
Must be called with source read locked and target write locked.
3435
result = BranchPushResult()
3436
result.source_branch = self.source
3437
result.target_branch = self.target
3438
result.old_revno, result.old_revid = self.target.last_revision_info()
3439
self.source.update_references(self.target)
3440
if result.old_revid != stop_revision:
3441
# We assume that during 'push' this repository is closer than
3443
graph = self.source.repository.get_graph(self.target.repository)
3444
self._update_revisions(stop_revision, overwrite=overwrite,
3446
if self.source._push_should_merge_tags():
3447
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3449
result.new_revno, result.new_revid = self.target.last_revision_info()
3452
3463
def _push_with_bound_branches(self, overwrite, stop_revision,
3453
3464
_override_hook_source_branch=None):
3454
3465
"""Push from source into target, and into target's master if any.
3469
3480
master_branch.lock_write()
3471
3482
# push into the master from the source branch.
3472
master_inter = InterBranch.get(self.source, master_branch)
3473
master_inter._basic_push(overwrite, stop_revision)
3474
# and push into the target branch from the source. Note that
3475
# we push from the source branch again, because it's considered
3476
# the highest bandwidth repository.
3477
result = self._basic_push(overwrite, stop_revision)
3483
self.source._basic_push(master_branch, overwrite, stop_revision)
3484
# and push into the target branch from the source. Note that we
3485
# push from the source branch again, because it's considered the
3486
# highest bandwidth repository.
3487
result = self.source._basic_push(self.target, overwrite,
3478
3489
result.master_branch = master_branch
3479
3490
result.local_branch = self.target
3495
3507
def _pull(self, overwrite=False, stop_revision=None,
3496
3508
possible_transports=None, _hook_master=None, run_hooks=True,
3497
_override_hook_target=None, local=False,
3498
merge_tags_to_master=True):
3509
_override_hook_target=None, local=False):
3499
3510
"""See Branch.pull.
3501
3512
This function is the core worker, used by GenericInterBranch.pull to
3506
3517
:param run_hooks: Private parameter - if false, this branch
3507
3518
is being called because it's the master of the primary branch,
3508
3519
so it should not run its hooks.
3509
is being called because it's the master of the primary branch,
3510
so it should not run its hooks.
3511
3520
:param _override_hook_target: Private parameter - set the branch to be
3512
3521
supplied as the target_branch to pull hooks.
3513
3522
:param local: Only update the local branch, and not the bound branch.
3532
3541
# -- JRV20090506
3533
3542
result.old_revno, result.old_revid = \
3534
3543
self.target.last_revision_info()
3535
self._update_revisions(stop_revision, overwrite=overwrite,
3544
self.target.update_revisions(self.source, stop_revision,
3545
overwrite=overwrite, graph=graph)
3537
3546
# TODO: The old revid should be specified when merging tags,
3538
3547
# so a tags implementation that versions tags can only
3539
3548
# pull in the most recent changes. -- JRV20090506
3540
3549
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3541
overwrite, ignore_master=not merge_tags_to_master)
3542
3551
result.new_revno, result.new_revid = self.target.last_revision_info()
3543
3552
if _hook_master:
3544
3553
result.master_branch = _hook_master