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,
1367
stacked_on=None, create_prefix=False, use_existing_dir=False,
1375
stacked_on=None, create_prefix=False, use_existing_dir=False):
1369
1376
"""Create a clone of this branch and its bzrdir.
1371
1378
:param to_transport: The transport to clone onto.
1384
1391
revision_id = self.last_revision()
1385
1392
dir_to = self.bzrdir.clone_on_transport(to_transport,
1386
1393
revision_id=revision_id, stacked_on=stacked_on,
1387
create_prefix=create_prefix, use_existing_dir=use_existing_dir,
1394
create_prefix=create_prefix, use_existing_dir=use_existing_dir)
1389
1395
return dir_to.open_branch()
1391
1397
def create_checkout(self, to_location, revision_id=None,
1507
1513
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):
1516
class BranchFormat(object):
1531
1517
"""An encapsulation of the initialization and open routines for a format.
1533
1519
Formats provide three things:
1560
1552
transport = a_bzrdir.get_branch_transport(None, name=name)
1561
1553
format_string = transport.get_bytes("format")
1562
return format_registry.get(format_string)
1554
format = klass._formats[format_string]
1555
if isinstance(format, MetaDirBranchFormatFactory):
1563
1558
except errors.NoSuchFile:
1564
1559
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1565
1560
except KeyError:
1566
1561
raise errors.UnknownFormatError(format=format_string, kind='branch')
1569
@deprecated_method(deprecated_in((2, 4, 0)))
1570
1564
def get_default_format(klass):
1571
1565
"""Return the current default format."""
1572
return format_registry.get_default()
1566
return klass._default_format
1575
@deprecated_method(deprecated_in((2, 4, 0)))
1576
1569
def get_formats(klass):
1577
1570
"""Get all the known formats.
1579
1572
Warning: This triggers a load of all lazy registered formats: do not
1580
1573
use except when that is desireed.
1582
return format_registry._get_all()
1576
for fmt in klass._formats.values():
1577
if isinstance(fmt, MetaDirBranchFormatFactory):
1584
1582
def get_reference(self, a_bzrdir, name=None):
1585
1583
"""Get the target reference of the branch in a_bzrdir.
1624
1622
for hook in hooks:
1627
def initialize(self, a_bzrdir, name=None, repository=None):
1625
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1626
lock_type='metadir', set_format=True):
1627
"""Initialize a branch in a bzrdir, with specified files
1629
:param a_bzrdir: The bzrdir to initialize the branch in
1630
:param utf8_files: The files to create as a list of
1631
(filename, content) tuples
1632
:param name: Name of colocated branch to create, if any
1633
:param set_format: If True, set the format with
1634
self.get_format_string. (BzrBranch4 has its format set
1636
:return: a branch in this format
1638
mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1639
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1641
'metadir': ('lock', lockdir.LockDir),
1642
'branch4': ('branch-lock', lockable_files.TransportLock),
1644
lock_name, lock_class = lock_map[lock_type]
1645
control_files = lockable_files.LockableFiles(branch_transport,
1646
lock_name, lock_class)
1647
control_files.create_lock()
1649
control_files.lock_write()
1650
except errors.LockContention:
1651
if lock_type != 'branch4':
1657
utf8_files += [('format', self.get_format_string())]
1659
for (filename, content) in utf8_files:
1660
branch_transport.put_bytes(
1662
mode=a_bzrdir._get_file_mode())
1665
control_files.unlock()
1666
branch = self.open(a_bzrdir, name, _found=True)
1667
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1670
def initialize(self, a_bzrdir, name=None):
1628
1671
"""Create a branch of this format in a_bzrdir.
1630
1673
:param name: Name of the colocated branch to create.
1665
1708
raise NotImplementedError(self.network_name)
1667
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1668
found_repository=None):
1710
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
1669
1711
"""Return the branch object for a_bzrdir
1671
1713
:param a_bzrdir: A BzrDir that contains a branch.
1678
1720
raise NotImplementedError(self.open)
1681
@deprecated_method(deprecated_in((2, 4, 0)))
1682
1723
def register_format(klass, format):
1683
1724
"""Register a metadir format.
1685
1726
See MetaDirBranchFormatFactory for the ability to register a format
1686
1727
without loading the code the format needs until it is actually used.
1688
format_registry.register(format)
1729
klass._formats[format.get_format_string()] = format
1730
# Metadir formats have a network name of their format string, and get
1731
# registered as factories.
1732
if isinstance(format, MetaDirBranchFormatFactory):
1733
network_format_registry.register(format.get_format_string(), format)
1735
network_format_registry.register(format.get_format_string(),
1691
@deprecated_method(deprecated_in((2, 4, 0)))
1692
1739
def set_default_format(klass, format):
1693
format_registry.set_default(format)
1740
klass._default_format = format
1695
1742
def supports_set_append_revisions_only(self):
1696
1743
"""True if this format supports set_append_revisions_only."""
1700
1747
"""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
1751
def unregister_format(klass, format):
1710
format_registry.remove(format)
1752
del klass._formats[format.get_format_string()]
1712
1754
def __str__(self):
1713
1755
return self.get_format_description().rstrip()
1758
1800
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',
1803
Hooks.__init__(self)
1804
self.create_hook(HookPoint('set_rh',
1763
1805
"Invoked whenever the revision history has been set via "
1764
1806
"set_revision_history. The api signature is (branch, "
1765
1807
"revision_history), and the branch will be write-locked. "
1766
1808
"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',
1809
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1810
self.create_hook(HookPoint('open',
1769
1811
"Called with the Branch object that has been opened after a "
1770
"branch is opened.", (1, 8))
1771
self.add_hook('post_push',
1812
"branch is opened.", (1, 8), None))
1813
self.create_hook(HookPoint('post_push',
1772
1814
"Called after a push operation completes. post_push is called "
1773
1815
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1774
"bzr client.", (0, 15))
1775
self.add_hook('post_pull',
1816
"bzr client.", (0, 15), None))
1817
self.create_hook(HookPoint('post_pull',
1776
1818
"Called after a pull operation completes. post_pull is called "
1777
1819
"with a bzrlib.branch.PullResult object and only runs in the "
1778
"bzr client.", (0, 15))
1779
self.add_hook('pre_commit',
1820
"bzr client.", (0, 15), None))
1821
self.create_hook(HookPoint('pre_commit',
1780
1822
"Called after a commit is calculated but before it is "
1781
1823
"completed. pre_commit is called with (local, master, old_revno, "
1782
1824
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1785
1827
"basis revision. hooks MUST NOT modify this delta. "
1786
1828
" future_tree is an in-memory tree obtained from "
1787
1829
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1789
self.add_hook('post_commit',
1830
"tree.", (0,91), None))
1831
self.create_hook(HookPoint('post_commit',
1790
1832
"Called in the bzr client after a commit has completed. "
1791
1833
"post_commit is called with (local, master, old_revno, old_revid, "
1792
1834
"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',
1835
"commit to a branch.", (0, 15), None))
1836
self.create_hook(HookPoint('post_uncommit',
1795
1837
"Called in the bzr client after an uncommit completes. "
1796
1838
"post_uncommit is called with (local, master, old_revno, "
1797
1839
"old_revid, new_revno, new_revid) where local is the local branch "
1798
1840
"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',
1841
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1842
self.create_hook(HookPoint('pre_change_branch_tip',
1801
1843
"Called in bzr client and server before a change to the tip of a "
1802
1844
"branch is made. pre_change_branch_tip is called with a "
1803
1845
"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',
1846
"commit, uncommit will all trigger this hook.", (1, 6), None))
1847
self.create_hook(HookPoint('post_change_branch_tip',
1806
1848
"Called in bzr client and server after a change to the tip of a "
1807
1849
"branch is made. post_change_branch_tip is called with a "
1808
1850
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1809
"commit, uncommit will all trigger this hook.", (1, 4))
1810
self.add_hook('transform_fallback_location',
1851
"commit, uncommit will all trigger this hook.", (1, 4), None))
1852
self.create_hook(HookPoint('transform_fallback_location',
1811
1853
"Called when a stacked branch is activating its fallback "
1812
1854
"locations. transform_fallback_location is called with (branch, "
1813
1855
"url), and should return a new url. Returning the same url "
1818
1860
"fallback locations have not been activated. When there are "
1819
1861
"multiple hooks installed for transform_fallback_location, "
1820
1862
"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',
1863
"The order is however undefined.", (1, 9), None))
1864
self.create_hook(HookPoint('automatic_tag_name',
1823
1865
"Called to determine an automatic tag name for a revision. "
1824
1866
"automatic_tag_name is called with (branch, revision_id) and "
1825
1867
"should return a tag name or None if no tag name could be "
1826
1868
"determined. The first non-None tag name returned will be used.",
1828
self.add_hook('post_branch_init',
1870
self.create_hook(HookPoint('post_branch_init',
1829
1871
"Called after new branch initialization completes. "
1830
1872
"post_branch_init is called with a "
1831
1873
"bzrlib.branch.BranchInitHookParams. "
1832
1874
"Note that init, branch and checkout (both heavyweight and "
1833
"lightweight) will all trigger this hook.", (2, 2))
1834
self.add_hook('post_switch',
1875
"lightweight) will all trigger this hook.", (2, 2), None))
1876
self.create_hook(HookPoint('post_switch',
1835
1877
"Called after a checkout switches branch. "
1836
1878
"post_switch is called with a "
1837
"bzrlib.branch.SwitchHookParams.", (2, 2))
1879
"bzrlib.branch.SwitchHookParams.", (2, 2), None))
1953
1995
self.revision_id)
1998
class BzrBranchFormat4(BranchFormat):
1999
"""Bzr branch format 4.
2002
- a revision-history file.
2003
- a branch-lock lock file [ to be shared with the bzrdir ]
2006
def get_format_description(self):
2007
"""See BranchFormat.get_format_description()."""
2008
return "Branch format 4"
2010
def initialize(self, a_bzrdir, name=None):
2011
"""Create a branch of this format in a_bzrdir."""
2012
utf8_files = [('revision-history', ''),
2013
('branch-name', ''),
2015
return self._initialize_helper(a_bzrdir, utf8_files, name=name,
2016
lock_type='branch4', set_format=False)
2019
super(BzrBranchFormat4, self).__init__()
2020
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2022
def network_name(self):
2023
"""The network name for this format is the control dirs disk label."""
2024
return self._matchingbzrdir.get_format_string()
2026
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2027
"""See BranchFormat.open()."""
2029
# we are being called directly and must probe.
2030
raise NotImplementedError
2031
return BzrBranch(_format=self,
2032
_control_files=a_bzrdir._control_files,
2035
_repository=a_bzrdir.open_repository())
2038
return "Bazaar-NG branch format 4"
1956
2041
class BranchFormatMetadir(BranchFormat):
1957
2042
"""Common logic for meta-dir based branch formats."""
1960
2045
"""What class to instantiate on open calls."""
1961
2046
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
2048
def network_name(self):
1993
2049
"""A simple byte string uniquely identifying this format for RPC calls.
1997
2053
return self.get_format_string()
1999
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2000
found_repository=None):
2055
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
2001
2056
"""See BranchFormat.open()."""
2003
2058
format = BranchFormat.find_format(a_bzrdir, name=name)
2009
2064
control_files = lockable_files.LockableFiles(transport, 'lock',
2010
2065
lockdir.LockDir)
2011
if found_repository is None:
2012
found_repository = a_bzrdir.find_repository()
2013
2066
return self._branch_class()(_format=self,
2014
2067
_control_files=control_files,
2016
2069
a_bzrdir=a_bzrdir,
2017
_repository=found_repository,
2070
_repository=a_bzrdir.find_repository(),
2018
2071
ignore_fallbacks=ignore_fallbacks)
2019
2072
except errors.NoSuchFile:
2020
2073
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2055
2105
"""See BranchFormat.get_format_description()."""
2056
2106
return "Branch format 5"
2058
def initialize(self, a_bzrdir, name=None, repository=None):
2108
def initialize(self, a_bzrdir, name=None):
2059
2109
"""Create a branch of this format in a_bzrdir."""
2060
2110
utf8_files = [('revision-history', ''),
2061
2111
('branch-name', ''),
2063
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2113
return self._initialize_helper(a_bzrdir, utf8_files, name)
2065
2115
def supports_tags(self):
2088
2138
"""See BranchFormat.get_format_description()."""
2089
2139
return "Branch format 6"
2091
def initialize(self, a_bzrdir, name=None, repository=None):
2141
def initialize(self, a_bzrdir, name=None):
2092
2142
"""Create a branch of this format in a_bzrdir."""
2093
2143
utf8_files = [('last-revision', '0 null:\n'),
2094
2144
('branch.conf', ''),
2097
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2147
return self._initialize_helper(a_bzrdir, utf8_files, name)
2099
2149
def make_tags(self, branch):
2100
2150
"""See bzrlib.branch.BranchFormat.make_tags()."""
2118
2168
"""See BranchFormat.get_format_description()."""
2119
2169
return "Branch format 8"
2121
def initialize(self, a_bzrdir, name=None, repository=None):
2171
def initialize(self, a_bzrdir, name=None):
2122
2172
"""Create a branch of this format in a_bzrdir."""
2123
2173
utf8_files = [('last-revision', '0 null:\n'),
2124
2174
('branch.conf', ''),
2126
2176
('references', '')
2128
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2178
return self._initialize_helper(a_bzrdir, utf8_files, name)
2181
super(BzrBranchFormat8, self).__init__()
2182
self._matchingbzrdir.repository_format = \
2183
RepositoryFormatKnitPack5RichRoot()
2130
2185
def make_tags(self, branch):
2131
2186
"""See bzrlib.branch.BranchFormat.make_tags()."""
2149
2204
This format was introduced in bzr 1.6.
2152
def initialize(self, a_bzrdir, name=None, repository=None):
2207
def initialize(self, a_bzrdir, name=None):
2153
2208
"""Create a branch of this format in a_bzrdir."""
2154
2209
utf8_files = [('last-revision', '0 null:\n'),
2155
2210
('branch.conf', ''),
2158
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2213
return self._initialize_helper(a_bzrdir, utf8_files, name)
2160
2215
def _branch_class(self):
2161
2216
return BzrBranch7
2210
2258
transport = a_bzrdir.get_branch_transport(None, name=name)
2211
2259
location = transport.put_bytes('location', to_branch.base)
2213
def initialize(self, a_bzrdir, name=None, target_branch=None,
2261
def initialize(self, a_bzrdir, name=None, target_branch=None):
2215
2262
"""Create a branch of this format in a_bzrdir."""
2216
2263
if target_branch is None:
2217
2264
# 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
2332
network_format_registry = registry.FormatRegistry()
2301
2333
"""Registry of formats indexed by their network name.
2314
2344
__format6 = BzrBranchFormat6()
2315
2345
__format7 = BzrBranchFormat7()
2316
2346
__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)
2347
BranchFormat.register_format(__format5)
2348
BranchFormat.register_format(BranchReferenceFormat())
2349
BranchFormat.register_format(__format6)
2350
BranchFormat.register_format(__format7)
2351
BranchFormat.register_format(__format8)
2352
BranchFormat.set_default_format(__format7)
2353
_legacy_formats = [BzrBranchFormat4(),
2355
network_format_registry.register(
2356
_legacy_formats[0].network_name(), _legacy_formats[0].__class__)
2325
2359
class BranchWriteLockResult(LogicalLockResult):
2482
2516
'revision-history', '\n'.join(history),
2483
2517
mode=self.bzrdir._get_file_mode())
2485
@deprecated_method(deprecated_in((2, 4, 0)))
2486
2520
def set_revision_history(self, rev_history):
2487
2521
"""See Branch.set_revision_history."""
2488
self._set_revision_history(rev_history)
2491
def _set_revision_history(self, rev_history):
2492
2522
if 'evil' in debug.debug_flags:
2493
2523
mutter_callsite(3, "set_revision_history scales with history.")
2494
2524
check_not_reserved_id = _mod_revision.check_not_reserved_id
2552
2582
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)
2585
revision_id = _mod_revision.ensure_null(revision_id)
2557
2586
# this old format stores the full history, but this api doesn't
2558
2587
# provide it, so we must generate, and might as well check it's
2560
2589
history = self._lefthand_history(revision_id)
2561
2590
if len(history) != revno:
2562
2591
raise AssertionError('%d != %d' % (len(history), revno))
2563
self._set_revision_history(history)
2592
self.set_revision_history(history)
2565
2594
def _gen_revision_history(self):
2566
2595
history = self._transport.get_bytes('revision-history').split('\n')
2628
def _basic_push(self, target, overwrite, stop_revision):
2629
"""Basic implementation of push without bound branches or hooks.
2631
Must be called with source read locked and target write locked.
2633
result = BranchPushResult()
2634
result.source_branch = self
2635
result.target_branch = target
2636
result.old_revno, result.old_revid = target.last_revision_info()
2637
self.update_references(target)
2638
if result.old_revid != self.last_revision():
2639
# We assume that during 'push' this repository is closer than
2641
graph = self.repository.get_graph(target.repository)
2642
target.update_revisions(self, stop_revision,
2643
overwrite=overwrite, graph=graph)
2644
if self._push_should_merge_tags():
2645
result.tag_conflicts = self.tags.merge_to(target.tags,
2647
result.new_revno, result.new_revid = target.last_revision_info()
2599
2650
def get_stacked_on_url(self):
2600
2651
raise errors.UnstackableBranchFormat(self._format, self.user_url)
2630
2681
"""Return the branch we are bound to.
2632
2683
:return: Either a Branch, or None
2685
This could memoise the branch, but if thats done
2686
it must be revalidated on each new lock.
2687
So for now we just don't memoise it.
2688
# 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
2690
bound_loc = self.get_bound_location()
2641
2691
if not bound_loc:
2769
2818
@needs_write_lock
2770
2819
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)
2820
revision_id = _mod_revision.ensure_null(revision_id)
2773
2821
old_revno, old_revid = self.last_revision_info()
2774
2822
if self._get_append_revisions_only():
2775
2823
self._check_history_violation(revision_id)
2996
3043
index = self._partial_revision_history_cache.index(revision_id)
2997
3044
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)
3045
self._extend_partial_history(stop_revision=revision_id)
3002
3046
index = len(self._partial_revision_history_cache) - 1
3003
3047
if self._partial_revision_history_cache[index] != revision_id:
3004
3048
raise errors.NoSuchRevision(self, revision_id)
3251
3295
raise NotImplementedError(self.pull)
3253
3297
@needs_write_lock
3298
def update_revisions(self, stop_revision=None, overwrite=False,
3300
"""Pull in new perfect-fit revisions.
3302
:param stop_revision: Updated until the given revision
3303
:param overwrite: Always set the branch pointer, rather than checking
3304
to see if it is a proper descendant.
3305
:param graph: A Graph object that can be used to query history
3306
information. This can be None.
3309
raise NotImplementedError(self.update_revisions)
3254
3312
def push(self, overwrite=False, stop_revision=None,
3255
3313
_override_hook_source_branch=None):
3256
3314
"""Mirror the source branch into the target branch.
3289
3339
def _get_branch_formats_to_test(klass):
3290
return [(format_registry.get_default(), format_registry.get_default())]
3340
return [(BranchFormat._default_format, BranchFormat._default_format)]
3293
3343
def unwrap_format(klass, format):
3294
3344
if isinstance(format, remote.RemoteBranchFormat):
3295
3345
format._ensure_real()
3296
3346
return format._custom_format
3299
3349
@needs_write_lock
3300
3350
def copy_content_into(self, revision_id=None):
3316
3366
self.source.tags.merge_to(self.target.tags)
3318
3368
@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,
3369
def update_revisions(self, stop_revision=None, overwrite=False,
3371
"""See InterBranch.update_revisions()."""
3339
3372
other_revno, other_last_revision = self.source.last_revision_info()
3340
3373
stop_revno = None # unknown
3341
3374
if stop_revision is None:
3428
3459
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
3461
def _push_with_bound_branches(self, overwrite, stop_revision,
3453
3462
_override_hook_source_branch=None):
3454
3463
"""Push from source into target, and into target's master if any.
3469
3478
master_branch.lock_write()
3471
3480
# 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)
3481
self.source._basic_push(master_branch, overwrite, stop_revision)
3482
# and push into the target branch from the source. Note that we
3483
# push from the source branch again, because it's considered the
3484
# highest bandwidth repository.
3485
result = self.source._basic_push(self.target, overwrite,
3478
3487
result.master_branch = master_branch
3479
3488
result.local_branch = self.target
3495
3505
def _pull(self, overwrite=False, stop_revision=None,
3496
3506
possible_transports=None, _hook_master=None, run_hooks=True,
3497
_override_hook_target=None, local=False,
3498
merge_tags_to_master=True):
3507
_override_hook_target=None, local=False):
3499
3508
"""See Branch.pull.
3501
3510
This function is the core worker, used by GenericInterBranch.pull to
3506
3515
:param run_hooks: Private parameter - if false, this branch
3507
3516
is being called because it's the master of the primary branch,
3508
3517
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
3518
:param _override_hook_target: Private parameter - set the branch to be
3512
3519
supplied as the target_branch to pull hooks.
3513
3520
:param local: Only update the local branch, and not the bound branch.
3532
3539
# -- JRV20090506
3533
3540
result.old_revno, result.old_revid = \
3534
3541
self.target.last_revision_info()
3535
self._update_revisions(stop_revision, overwrite=overwrite,
3542
self.target.update_revisions(self.source, stop_revision,
3543
overwrite=overwrite, graph=graph)
3537
3544
# TODO: The old revid should be specified when merging tags,
3538
3545
# so a tags implementation that versions tags can only
3539
3546
# pull in the most recent changes. -- JRV20090506
3540
3547
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3541
overwrite, ignore_master=not merge_tags_to_master)
3542
3549
result.new_revno, result.new_revid = self.target.last_revision_info()
3543
3550
if _hook_master:
3544
3551
result.master_branch = _hook_master