44
45
from bzrlib.config import BranchConfig, TransportConfig
46
from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5RichRoot
45
47
from bzrlib.tag import (
54
from bzrlib.decorators import (
59
from bzrlib.hooks import Hooks
53
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
54
from bzrlib.hooks import HookPoint, Hooks
60
55
from bzrlib.inter import InterObject
61
56
from bzrlib.lock import _RelockDebugMixin, LogicalLockResult
62
57
from bzrlib import registry
669
662
raise errors.UnsupportedOperation(self.get_reference_info, self)
671
664
@needs_write_lock
672
def fetch(self, from_branch, last_revision=None, fetch_spec=None):
665
def fetch(self, from_branch, last_revision=None, pb=None, fetch_spec=None):
673
666
"""Copy revisions from from_branch into this branch.
675
668
:param from_branch: Where to copy from.
676
669
:param last_revision: What revision to stop at (None for at the end
671
:param pb: An optional progress bar to use.
678
672
:param fetch_spec: If specified, a SearchResult or
679
673
PendingAncestryResult that describes which revisions to copy. This
680
674
allows copying multiple heads at once. Mutually exclusive with
684
return InterBranch.get(from_branch, self).fetch(last_revision,
678
if fetch_spec is not None and last_revision is not None:
679
raise AssertionError(
680
"fetch_spec and last_revision are mutually exclusive.")
681
if self.base == from_branch.base:
684
symbol_versioning.warn(
685
symbol_versioning.deprecated_in((1, 14, 0))
686
% "pb parameter to fetch()")
687
from_branch.lock_read()
689
if last_revision is None and fetch_spec is None:
690
last_revision = from_branch.last_revision()
691
last_revision = _mod_revision.ensure_null(last_revision)
692
return self.repository.fetch(from_branch.repository,
693
revision_id=last_revision,
694
pb=pb, fetch_spec=fetch_spec)
687
698
def get_bound_location(self):
688
699
"""Return the URL of the branch we are bound to.
997
1007
return (0, _mod_revision.NULL_REVISION)
1009
@deprecated_method(deprecated_in((1, 6, 0)))
1010
def missing_revisions(self, other, stop_revision=None):
1011
"""Return a list of new revisions that would perfectly fit.
1013
If self and other have not diverged, return a list of the revisions
1014
present in other, but missing from self.
1016
self_history = self.revision_history()
1017
self_len = len(self_history)
1018
other_history = other.revision_history()
1019
other_len = len(other_history)
1020
common_index = min(self_len, other_len) -1
1021
if common_index >= 0 and \
1022
self_history[common_index] != other_history[common_index]:
1023
raise errors.DivergedBranches(self, other)
1025
if stop_revision is None:
1026
stop_revision = other_len
1028
if stop_revision > other_len:
1029
raise errors.NoSuchRevision(self, stop_revision)
1030
return other_history[self_len:stop_revision]
999
1032
def update_revisions(self, other, stop_revision=None, overwrite=False,
1000
1033
graph=None, fetch_tags=True):
1001
1034
"""Pull in new perfect-fit revisions.
1527
1560
raise AssertionError("invalid heads: %r" % (heads,))
1529
def heads_to_fetch(self):
1530
"""Return the heads that must and that should be fetched to copy this
1531
branch into another repo.
1533
:returns: a 2-tuple of (must_fetch, if_present_fetch). must_fetch is a
1534
set of heads that must be fetched. if_present_fetch is a set of
1535
heads that must be fetched if present, but no error is necessary if
1536
they are not present.
1538
# For bzr native formats must_fetch is just the tip, and if_present_fetch
1540
must_fetch = set([self.last_revision()])
1542
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1543
except errors.TagsNotSupported:
1544
if_present_fetch = set()
1545
must_fetch.discard(_mod_revision.NULL_REVISION)
1546
if_present_fetch.discard(_mod_revision.NULL_REVISION)
1547
return must_fetch, if_present_fetch
1550
class BranchFormat(controldir.ControlComponentFormat):
1563
class BranchFormat(object):
1551
1564
"""An encapsulation of the initialization and open routines for a format.
1553
1566
Formats provide three things:
1580
1602
transport = a_bzrdir.get_branch_transport(None, name=name)
1581
1603
format_string = transport.get_bytes("format")
1582
return format_registry.get(format_string)
1604
format = klass._formats[format_string]
1605
if isinstance(format, MetaDirBranchFormatFactory):
1583
1608
except errors.NoSuchFile:
1584
1609
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1585
1610
except KeyError:
1586
1611
raise errors.UnknownFormatError(format=format_string, kind='branch')
1589
@deprecated_method(deprecated_in((2, 4, 0)))
1590
1614
def get_default_format(klass):
1591
1615
"""Return the current default format."""
1592
return format_registry.get_default()
1616
return klass._default_format
1595
@deprecated_method(deprecated_in((2, 4, 0)))
1596
1619
def get_formats(klass):
1597
1620
"""Get all the known formats.
1599
1622
Warning: This triggers a load of all lazy registered formats: do not
1600
1623
use except when that is desireed.
1602
return format_registry._get_all()
1626
for fmt in klass._formats.values():
1627
if isinstance(fmt, MetaDirBranchFormatFactory):
1630
return result + klass._extra_formats
1604
1632
def get_reference(self, a_bzrdir, name=None):
1605
1633
"""Get the target reference of the branch in a_bzrdir.
1644
1672
for hook in hooks:
1675
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1676
repository=None, lock_type='metadir',
1678
"""Initialize a branch in a bzrdir, with specified files
1680
:param a_bzrdir: The bzrdir to initialize the branch in
1681
:param utf8_files: The files to create as a list of
1682
(filename, content) tuples
1683
:param name: Name of colocated branch to create, if any
1684
:param set_format: If True, set the format with
1685
self.get_format_string. (BzrBranch4 has its format set
1687
:return: a branch in this format
1689
mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1690
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1692
'metadir': ('lock', lockdir.LockDir),
1693
'branch4': ('branch-lock', lockable_files.TransportLock),
1695
lock_name, lock_class = lock_map[lock_type]
1696
control_files = lockable_files.LockableFiles(branch_transport,
1697
lock_name, lock_class)
1698
control_files.create_lock()
1700
control_files.lock_write()
1701
except errors.LockContention:
1702
if lock_type != 'branch4':
1708
utf8_files += [('format', self.get_format_string())]
1710
for (filename, content) in utf8_files:
1711
branch_transport.put_bytes(
1713
mode=a_bzrdir._get_file_mode())
1716
control_files.unlock()
1717
branch = self.open(a_bzrdir, name, _found=True,
1718
found_repository=repository)
1719
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
1647
1722
def initialize(self, a_bzrdir, name=None, repository=None):
1648
1723
"""Create a branch of this format in a_bzrdir.
1698
1773
raise NotImplementedError(self.open)
1701
@deprecated_method(deprecated_in((2, 4, 0)))
1776
def register_extra_format(klass, format):
1777
"""Register a branch format that can not be part of a metadir.
1779
This is mainly useful to allow custom branch formats, such as
1780
older Bazaar formats and foreign formats, to be tested
1782
klass._extra_formats.append(format)
1783
network_format_registry.register(
1784
format.network_name(), format.__class__)
1702
1787
def register_format(klass, format):
1703
1788
"""Register a metadir format.
1705
1790
See MetaDirBranchFormatFactory for the ability to register a format
1706
1791
without loading the code the format needs until it is actually used.
1708
format_registry.register(format)
1793
klass._formats[format.get_format_string()] = format
1794
# Metadir formats have a network name of their format string, and get
1795
# registered as factories.
1796
if isinstance(format, MetaDirBranchFormatFactory):
1797
network_format_registry.register(format.get_format_string(), format)
1799
network_format_registry.register(format.get_format_string(),
1711
@deprecated_method(deprecated_in((2, 4, 0)))
1712
1803
def set_default_format(klass, format):
1713
format_registry.set_default(format)
1804
klass._default_format = format
1715
1806
def supports_set_append_revisions_only(self):
1716
1807
"""True if this format supports set_append_revisions_only."""
1720
1811
"""True if this format records a stacked-on branch."""
1723
def supports_leaving_lock(self):
1724
"""True if this format supports leaving locks in place."""
1725
return False # by default
1728
@deprecated_method(deprecated_in((2, 4, 0)))
1729
1815
def unregister_format(klass, format):
1730
format_registry.remove(format)
1816
del klass._formats[format.get_format_string()]
1819
def unregister_extra_format(klass, format):
1820
klass._extra_formats.remove(format)
1732
1822
def __str__(self):
1733
1823
return self.get_format_description().rstrip()
1778
1868
These are all empty initially, because by default nothing should get
1781
Hooks.__init__(self, "bzrlib.branch", "Branch.hooks")
1782
self.add_hook('set_rh',
1871
Hooks.__init__(self)
1872
self.create_hook(HookPoint('set_rh',
1783
1873
"Invoked whenever the revision history has been set via "
1784
1874
"set_revision_history. The api signature is (branch, "
1785
1875
"revision_history), and the branch will be write-locked. "
1786
1876
"The set_rh hook can be expensive for bzr to trigger, a better "
1787
"hook to use is Branch.post_change_branch_tip.", (0, 15))
1788
self.add_hook('open',
1877
"hook to use is Branch.post_change_branch_tip.", (0, 15), None))
1878
self.create_hook(HookPoint('open',
1789
1879
"Called with the Branch object that has been opened after a "
1790
"branch is opened.", (1, 8))
1791
self.add_hook('post_push',
1880
"branch is opened.", (1, 8), None))
1881
self.create_hook(HookPoint('post_push',
1792
1882
"Called after a push operation completes. post_push is called "
1793
1883
"with a bzrlib.branch.BranchPushResult object and only runs in the "
1794
"bzr client.", (0, 15))
1795
self.add_hook('post_pull',
1884
"bzr client.", (0, 15), None))
1885
self.create_hook(HookPoint('post_pull',
1796
1886
"Called after a pull operation completes. post_pull is called "
1797
1887
"with a bzrlib.branch.PullResult object and only runs in the "
1798
"bzr client.", (0, 15))
1799
self.add_hook('pre_commit',
1888
"bzr client.", (0, 15), None))
1889
self.create_hook(HookPoint('pre_commit',
1800
1890
"Called after a commit is calculated but before it is "
1801
1891
"completed. pre_commit is called with (local, master, old_revno, "
1802
1892
"old_revid, future_revno, future_revid, tree_delta, future_tree"
1805
1895
"basis revision. hooks MUST NOT modify this delta. "
1806
1896
" future_tree is an in-memory tree obtained from "
1807
1897
"CommitBuilder.revision_tree() and hooks MUST NOT modify this "
1809
self.add_hook('post_commit',
1898
"tree.", (0,91), None))
1899
self.create_hook(HookPoint('post_commit',
1810
1900
"Called in the bzr client after a commit has completed. "
1811
1901
"post_commit is called with (local, master, old_revno, old_revid, "
1812
1902
"new_revno, new_revid). old_revid is NULL_REVISION for the first "
1813
"commit to a branch.", (0, 15))
1814
self.add_hook('post_uncommit',
1903
"commit to a branch.", (0, 15), None))
1904
self.create_hook(HookPoint('post_uncommit',
1815
1905
"Called in the bzr client after an uncommit completes. "
1816
1906
"post_uncommit is called with (local, master, old_revno, "
1817
1907
"old_revid, new_revno, new_revid) where local is the local branch "
1818
1908
"or None, master is the target branch, and an empty branch "
1819
"receives new_revno of 0, new_revid of None.", (0, 15))
1820
self.add_hook('pre_change_branch_tip',
1909
"receives new_revno of 0, new_revid of None.", (0, 15), None))
1910
self.create_hook(HookPoint('pre_change_branch_tip',
1821
1911
"Called in bzr client and server before a change to the tip of a "
1822
1912
"branch is made. pre_change_branch_tip is called with a "
1823
1913
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1824
"commit, uncommit will all trigger this hook.", (1, 6))
1825
self.add_hook('post_change_branch_tip',
1914
"commit, uncommit will all trigger this hook.", (1, 6), None))
1915
self.create_hook(HookPoint('post_change_branch_tip',
1826
1916
"Called in bzr client and server after a change to the tip of a "
1827
1917
"branch is made. post_change_branch_tip is called with a "
1828
1918
"bzrlib.branch.ChangeBranchTipParams. Note that push, pull, "
1829
"commit, uncommit will all trigger this hook.", (1, 4))
1830
self.add_hook('transform_fallback_location',
1919
"commit, uncommit will all trigger this hook.", (1, 4), None))
1920
self.create_hook(HookPoint('transform_fallback_location',
1831
1921
"Called when a stacked branch is activating its fallback "
1832
1922
"locations. transform_fallback_location is called with (branch, "
1833
1923
"url), and should return a new url. Returning the same url "
1838
1928
"fallback locations have not been activated. When there are "
1839
1929
"multiple hooks installed for transform_fallback_location, "
1840
1930
"all are called with the url returned from the previous hook."
1841
"The order is however undefined.", (1, 9))
1842
self.add_hook('automatic_tag_name',
1931
"The order is however undefined.", (1, 9), None))
1932
self.create_hook(HookPoint('automatic_tag_name',
1843
1933
"Called to determine an automatic tag name for a revision. "
1844
1934
"automatic_tag_name is called with (branch, revision_id) and "
1845
1935
"should return a tag name or None if no tag name could be "
1846
1936
"determined. The first non-None tag name returned will be used.",
1848
self.add_hook('post_branch_init',
1938
self.create_hook(HookPoint('post_branch_init',
1849
1939
"Called after new branch initialization completes. "
1850
1940
"post_branch_init is called with a "
1851
1941
"bzrlib.branch.BranchInitHookParams. "
1852
1942
"Note that init, branch and checkout (both heavyweight and "
1853
"lightweight) will all trigger this hook.", (2, 2))
1854
self.add_hook('post_switch',
1943
"lightweight) will all trigger this hook.", (2, 2), None))
1944
self.create_hook(HookPoint('post_switch',
1855
1945
"Called after a checkout switches branch. "
1856
1946
"post_switch is called with a "
1857
"bzrlib.branch.SwitchHookParams.", (2, 2))
1947
"bzrlib.branch.SwitchHookParams.", (2, 2), None))
1973
2063
self.revision_id)
2066
class BzrBranchFormat4(BranchFormat):
2067
"""Bzr branch format 4.
2070
- a revision-history file.
2071
- a branch-lock lock file [ to be shared with the bzrdir ]
2074
def get_format_description(self):
2075
"""See BranchFormat.get_format_description()."""
2076
return "Branch format 4"
2078
def initialize(self, a_bzrdir, name=None, repository=None):
2079
"""Create a branch of this format in a_bzrdir."""
2080
if repository is not None:
2081
raise NotImplementedError(
2082
"initialize(repository=<not None>) on %r" % (self,))
2083
utf8_files = [('revision-history', ''),
2084
('branch-name', ''),
2086
return self._initialize_helper(a_bzrdir, utf8_files, name=name,
2087
lock_type='branch4', set_format=False)
2090
super(BzrBranchFormat4, self).__init__()
2091
self._matchingbzrdir = bzrdir.BzrDirFormat6()
2093
def network_name(self):
2094
"""The network name for this format is the control dirs disk label."""
2095
return self._matchingbzrdir.get_format_string()
2097
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2098
found_repository=None):
2099
"""See BranchFormat.open()."""
2101
# we are being called directly and must probe.
2102
raise NotImplementedError
2103
if found_repository is None:
2104
found_repository = a_bzrdir.open_repository()
2105
return BzrBranchPreSplitOut(_format=self,
2106
_control_files=a_bzrdir._control_files,
2109
_repository=found_repository)
2112
return "Bazaar-NG branch format 4"
1976
2115
class BranchFormatMetadir(BranchFormat):
1977
2116
"""Common logic for meta-dir based branch formats."""
1980
2119
"""What class to instantiate on open calls."""
1981
2120
raise NotImplementedError(self._branch_class)
1983
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1985
"""Initialize a branch in a bzrdir, with specified files
1987
:param a_bzrdir: The bzrdir to initialize the branch in
1988
:param utf8_files: The files to create as a list of
1989
(filename, content) tuples
1990
:param name: Name of colocated branch to create, if any
1991
:return: a branch in this format
1993
mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1994
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1995
control_files = lockable_files.LockableFiles(branch_transport,
1996
'lock', lockdir.LockDir)
1997
control_files.create_lock()
1998
control_files.lock_write()
2000
utf8_files += [('format', self.get_format_string())]
2001
for (filename, content) in utf8_files:
2002
branch_transport.put_bytes(
2004
mode=a_bzrdir._get_file_mode())
2006
control_files.unlock()
2007
branch = self.open(a_bzrdir, name, _found=True,
2008
found_repository=repository)
2009
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2012
2122
def network_name(self):
2013
2123
"""A simple byte string uniquely identifying this format for RPC calls.
2306
class BranchFormatRegistry(controldir.ControlComponentFormatRegistry):
2307
"""Branch format registry."""
2309
def __init__(self, other_registry=None):
2310
super(BranchFormatRegistry, self).__init__(other_registry)
2311
self._default_format = None
2313
def set_default(self, format):
2314
self._default_format = format
2316
def get_default(self):
2317
return self._default_format
2320
2411
network_format_registry = registry.FormatRegistry()
2321
2412
"""Registry of formats indexed by their network name.
2334
2423
__format6 = BzrBranchFormat6()
2335
2424
__format7 = BzrBranchFormat7()
2336
2425
__format8 = BzrBranchFormat8()
2337
format_registry.register(__format5)
2338
format_registry.register(BranchReferenceFormat())
2339
format_registry.register(__format6)
2340
format_registry.register(__format7)
2341
format_registry.register(__format8)
2342
format_registry.set_default(__format7)
2426
BranchFormat.register_format(__format5)
2427
BranchFormat.register_format(BranchReferenceFormat())
2428
BranchFormat.register_format(__format6)
2429
BranchFormat.register_format(__format7)
2430
BranchFormat.register_format(__format8)
2431
BranchFormat.set_default_format(__format7)
2432
BranchFormat.register_extra_format(BzrBranchFormat4())
2345
2435
class BranchWriteLockResult(LogicalLockResult):
2649
2740
mode=self.bzrdir._get_file_mode())
2743
class BzrBranchPreSplitOut(BzrBranch):
2745
def _get_checkout_format(self):
2746
"""Return the most suitable metadir for a checkout of this branch.
2747
Weaves are used if this branch's repository uses weaves.
2749
from bzrlib.repofmt.weaverepo import RepositoryFormat7
2750
from bzrlib.bzrdir import BzrDirMetaFormat1
2751
format = BzrDirMetaFormat1()
2752
format.repository_format = RepositoryFormat7()
2652
2756
class BzrBranch5(BzrBranch):
2653
2757
"""A format 5 branch. This supports new features over plain branches.
2666
2770
"""Return the branch we are bound to.
2668
2772
:return: Either a Branch, or None
2774
This could memoise the branch, but if thats done
2775
it must be revalidated on each new lock.
2776
So for now we just don't memoise it.
2777
# RBC 20060304 review this decision.
2670
if self._master_branch_cache is None:
2671
self._master_branch_cache = self._get_master_branch(
2672
possible_transports)
2673
return self._master_branch_cache
2675
def _get_master_branch(self, possible_transports):
2676
2779
bound_loc = self.get_bound_location()
2677
2780
if not bound_loc:
3031
3132
index = self._partial_revision_history_cache.index(revision_id)
3032
3133
except ValueError:
3034
self._extend_partial_history(stop_revision=revision_id)
3035
except errors.RevisionNotPresent, e:
3036
raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
3134
self._extend_partial_history(stop_revision=revision_id)
3037
3135
index = len(self._partial_revision_history_cache) - 1
3038
3136
if self._partial_revision_history_cache[index] != revision_id:
3039
3137
raise errors.NoSuchRevision(self, revision_id)
3368
3457
self.source.tags.merge_to(self.target.tags)
3370
3459
@needs_write_lock
3371
def fetch(self, stop_revision=None, fetch_spec=None):
3372
if fetch_spec is not None and stop_revision is not None:
3373
raise AssertionError(
3374
"fetch_spec and last_revision are mutually exclusive.")
3375
if self.target.base == self.source.base:
3377
self.source.lock_read()
3379
if stop_revision is None and fetch_spec is None:
3380
stop_revision = self.source.last_revision()
3381
stop_revision = _mod_revision.ensure_null(stop_revision)
3382
return self.target.repository.fetch(self.source.repository,
3383
revision_id=stop_revision, fetch_spec=fetch_spec)
3385
self.source.unlock()
3388
3460
def update_revisions(self, stop_revision=None, overwrite=False,
3389
3461
graph=None, fetch_tags=True):
3390
3462
"""See InterBranch.update_revisions()."""
3548
3620
:param run_hooks: Private parameter - if false, this branch
3549
3621
is being called because it's the master of the primary branch,
3550
3622
so it should not run its hooks.
3551
is being called because it's the master of the primary branch,
3552
so it should not run its hooks.
3553
3623
:param _override_hook_target: Private parameter - set the branch to be
3554
3624
supplied as the target_branch to pull hooks.
3555
3625
:param local: Only update the local branch, and not the bound branch.