462
472
raise NotImplementedError(self.get_parent)
474
def _set_config_location(self, name, url, config=None,
475
make_relative=False):
477
config = self.get_config()
481
url = urlutils.relative_url(self.base, url)
482
config.set_user_option(name, url)
484
def _get_config_location(self, name, config=None):
486
config = self.get_config()
487
location = config.get_user_option(name)
464
492
def get_submit_branch(self):
465
493
"""Return the submit location of the branch.
480
508
self.get_config().set_user_option('submit_branch', location)
510
def get_public_branch(self):
511
"""Return the public location of the branch.
513
This is is used by merge directives.
515
return self._get_config_location('public_branch')
517
def set_public_branch(self, location):
518
"""Return the submit location of the branch.
520
This is the default location for bundle. The usual
521
pattern is that the user can override it by specifying a
524
self._set_config_location('public_branch', location)
482
526
def get_push_location(self):
483
527
"""Return the None or the location to push this branch to."""
484
528
push_loc = self.get_config().get_user_option('push_location')
695
740
# pull up to the specified revision_id to set the initial
696
741
# branch tip correctly, and seed it with history.
697
742
checkout_branch.pull(self, stop_revision=revision_id)
698
return checkout.create_workingtree(revision_id)
743
tree = checkout.create_workingtree(revision_id)
744
basis_tree = tree.basis_tree()
745
basis_tree.lock_read()
747
for path, file_id in basis_tree.iter_references():
748
reference_parent = self.reference_parent(file_id, path)
749
reference_parent.create_checkout(tree.abspath(path),
750
basis_tree.get_reference_revision(file_id, path),
756
def reference_parent(self, file_id, path):
757
"""Return the parent branch for a tree-reference file_id
758
:param file_id: The file_id of the tree reference
759
:param path: The path of the file_id in the tree
760
:return: A branch associated with the file_id
762
# FIXME should provide multiple branches, based on config
763
return Branch.open(self.bzrdir.root_transport.clone(path).base)
765
def supports_tags(self):
766
return self._format.supports_tags()
701
769
class BranchFormat(object):
828
896
def __str__(self):
829
897
return self.get_format_string().rstrip()
899
def supports_tags(self):
900
"""True if this format supports tags stored in the branch"""
901
return False # by default
903
# XXX: Probably doesn't really belong here -- mbp 20070212
904
def _initialize_control_files(self, a_bzrdir, utf8_files, lock_filename,
906
branch_transport = a_bzrdir.get_branch_transport(self)
907
control_files = lockable_files.LockableFiles(branch_transport,
908
lock_filename, lock_class)
909
control_files.create_lock()
910
control_files.lock_write()
912
for filename, content in utf8_files:
913
control_files.put_utf8(filename, content)
915
control_files.unlock()
832
918
class BranchHooks(dict):
833
919
"""A dictionary mapping hook name to a list of callables for branch hooks.
1148
1239
upgrade/recovery type use; it's not guaranteed that
1149
1240
all operations will work on old format branches.
1242
Branch.__init__(self)
1151
1243
if a_bzrdir is None:
1152
1244
self.bzrdir = bzrdir.BzrDir.open(transport.base)
1154
1246
self.bzrdir = a_bzrdir
1155
self._transport = self.bzrdir.transport.clone('..')
1156
self._base = self._transport.base
1247
# self._transport used to point to the directory containing the
1248
# control directory, but was not used - now it's just the transport
1249
# for the branch control files. mbp 20070212
1250
self._base = self.bzrdir.transport.clone('..').base
1157
1251
self._format = _format
1158
1252
if _control_files is None:
1159
1253
raise ValueError('BzrBranch _control_files is None')
1160
1254
self.control_files = _control_files
1255
self._transport = _control_files._transport
1161
1256
if deprecated_passed(init):
1162
1257
warn("BzrBranch.__init__(..., init=XXX): The init parameter is "
1163
1258
"deprecated as of bzr 0.8. Please use Branch.create().",
1452
1549
:param _run_hooks: Private parameter - allow disabling of
1453
1550
hooks, used when pushing to a master branch.
1552
result = PullResult()
1553
result.source_branch = source
1554
result.target_branch = self
1455
1555
source.lock_read()
1457
old_count, old_tip = self.last_revision_info()
1557
result.old_revno, result.old_revid = self.last_revision_info()
1459
1559
self.update_revisions(source, stop_revision)
1460
1560
except DivergedBranches:
1461
1561
if not overwrite:
1464
self.set_revision_history(source.revision_history())
1465
new_count, new_tip = self.last_revision_info()
1564
if stop_revision is None:
1565
stop_revision = source.last_revision()
1566
self.generate_revision_history(stop_revision)
1567
result.tag_conflicts = source.tags.merge_to(self.tags)
1568
result.new_revno, result.new_revid = self.last_revision_info()
1570
result.master_branch = _hook_master
1571
result.local_branch = self
1573
result.master_branch = self
1574
result.local_branch = None
1472
1576
for hook in Branch.hooks['post_pull']:
1473
hook(source, _hook_local, _hook_master, old_count, old_tip,
1475
return new_count - old_count
1477
1579
source.unlock()
1479
1582
def _get_parent_location(self):
1480
1583
_locs = ['parent', 'pull', 'x-pull']
1495
1598
:param _run_hooks: Private parameter - allow disabling of
1496
1599
hooks, used when pushing to a master branch.
1601
result = PushResult()
1602
result.source_branch = self
1603
result.target_branch = target
1498
1604
target.lock_write()
1500
old_count, old_tip = target.last_revision_info()
1606
result.old_revno, result.old_revid = target.last_revision_info()
1502
1608
target.update_revisions(self, stop_revision)
1503
1609
except DivergedBranches:
1507
1613
target.set_revision_history(self.revision_history())
1508
new_count, new_tip = target.last_revision_info()
1614
result.tag_conflicts = self.tags.merge_to(target.tags)
1615
result.new_revno, result.new_revid = target.last_revision_info()
1617
result.master_branch = _hook_master
1618
result.local_branch = target
1620
result.master_branch = target
1621
result.local_branch = None
1511
_hook_local = target
1513
_hook_master = target
1515
1623
for hook in Branch.hooks['post_push']:
1516
hook(self, _hook_local, _hook_master, old_count, old_tip,
1518
return new_count - old_count
1520
1626
target.unlock()
1522
1629
def get_parent(self):
1523
1630
"""See Branch.get_parent."""
1854
class BzrBranchExperimental(BzrBranch5):
1855
"""Bzr experimental branch format
1858
- a revision-history file.
1860
- a lock dir guarding the branch itself
1861
- all of this stored in a branch/ subdirectory
1862
- works with shared repositories.
1863
- a tag dictionary in the branch
1865
This format is new in bzr 0.15, but shouldn't be used for real data,
1868
This class acts as it's own BranchFormat.
1871
_matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1874
def get_format_string(cls):
1875
"""See BranchFormat.get_format_string()."""
1876
return "Bazaar-NG branch format experimental\n"
1879
def get_format_description(cls):
1880
"""See BranchFormat.get_format_description()."""
1881
return "Experimental branch format"
1884
def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1886
branch_transport = a_bzrdir.get_branch_transport(cls)
1887
control_files = lockable_files.LockableFiles(branch_transport,
1888
lock_filename, lock_class)
1889
control_files.create_lock()
1890
control_files.lock_write()
1892
for filename, content in utf8_files:
1893
control_files.put_utf8(filename, content)
1895
control_files.unlock()
1898
def initialize(cls, a_bzrdir):
1899
"""Create a branch of this format in a_bzrdir."""
1900
utf8_files = [('format', cls.get_format_string()),
1901
('revision-history', ''),
1902
('branch-name', ''),
1905
cls._initialize_control_files(a_bzrdir, utf8_files,
1906
'lock', lockdir.LockDir)
1907
return cls.open(a_bzrdir, _found=True)
1910
def open(cls, a_bzrdir, _found=False):
1911
"""Return the branch object for a_bzrdir
1913
_found is a private parameter, do not use it. It is used to indicate
1914
if format probing has already be done.
1917
format = BranchFormat.find_format(a_bzrdir)
1918
assert format.__class__ == cls
1919
transport = a_bzrdir.get_branch_transport(None)
1920
control_files = lockable_files.LockableFiles(transport, 'lock',
1922
return cls(_format=cls,
1923
_control_files=control_files,
1925
_repository=a_bzrdir.find_repository())
1928
def is_supported(cls):
1931
def _make_tags(self):
1932
return BasicTags(self)
1935
def supports_tags(cls):
1939
BranchFormat.register_format(BzrBranchExperimental)
1747
1942
class BzrBranch6(BzrBranch5):
1749
1944
@needs_read_lock
1836
2031
self.set_last_revision_info(prev_revno + len(revision_ids),
1837
2032
revision_ids[-1])
1839
def _set_config_location(self, name, url, config=None,
1840
make_relative=False):
1842
config = self.get_config()
1846
url = urlutils.relative_url(self.base, url)
1847
config.set_user_option(name, url)
1850
def _get_config_location(self, name, config=None):
1852
config = self.get_config()
1853
location = config.get_user_option(name)
1858
2034
@needs_write_lock
1859
2035
def _set_parent_location(self, url):
1860
2036
"""Set the parent branch"""
1960
2139
new_test.bzrdir_format = bzrdir_format
1961
2140
new_test.branch_format = branch_format
1962
2141
def make_new_test_id():
1963
new_id = "%s(%s)" % (new_test.id(), branch_format.__class__.__name__)
2142
# the format can be either a class or an instance
2143
name = getattr(branch_format, '__name__',
2144
branch_format.__class__.__name__)
2145
new_id = "%s(%s)" % (new_test.id(), name)
1964
2146
return lambda: new_id
1965
2147
new_test.id = make_new_test_id()
1966
2148
result.addTest(new_test)
2152
######################################################################
2153
# results of operations
2156
class _Result(object):
2158
def _show_tag_conficts(self, to_file):
2159
if not getattr(self, 'tag_conflicts', None):
2161
to_file.write('Conflicting tags:\n')
2162
for name, value1, value2 in self.tag_conflicts:
2163
to_file.write(' %s\n' % (name, ))
2166
class PullResult(_Result):
2167
"""Result of a Branch.pull operation.
2169
:ivar old_revno: Revision number before pull.
2170
:ivar new_revno: Revision number after pull.
2171
:ivar old_revid: Tip revision id before pull.
2172
:ivar new_revid: Tip revision id after pull.
2173
:ivar source_branch: Source (local) branch object.
2174
:ivar master_branch: Master branch of the target, or None.
2175
:ivar target_branch: Target/destination branch object.
2179
# DEPRECATED: pull used to return the change in revno
2180
return self.new_revno - self.old_revno
2182
def report(self, to_file):
2183
if self.old_revid == self.new_revid:
2184
to_file.write('No revisions to pull.\n')
2186
to_file.write('Now on revision %d.\n' % self.new_revno)
2187
self._show_tag_conficts(to_file)
2190
class PushResult(_Result):
2191
"""Result of a Branch.push operation.
2193
:ivar old_revno: Revision number before push.
2194
:ivar new_revno: Revision number after push.
2195
:ivar old_revid: Tip revision id before push.
2196
:ivar new_revid: Tip revision id after push.
2197
:ivar source_branch: Source branch object.
2198
:ivar master_branch: Master branch of the target, or None.
2199
:ivar target_branch: Target/destination branch object.
2203
# DEPRECATED: push used to return the change in revno
2204
return self.new_revno - self.old_revno
2206
def report(self, to_file):
2207
"""Write a human-readable description of the result."""
2208
if self.old_revid == self.new_revid:
2209
to_file.write('No new revisions to push.\n')
2211
to_file.write('Pushed up to revision %d.\n' % self.new_revno)
2212
self._show_tag_conficts(to_file)
1970
2215
class BranchCheckResult(object):
1971
2216
"""Results of checking branch consistency.
1987
2232
self.branch._format)
1990
######################################################################
1994
@deprecated_function(zero_eight)
1995
def is_control_file(*args, **kwargs):
1996
"""See bzrlib.workingtree.is_control_file."""
1997
from bzrlib import workingtree
1998
return workingtree.is_control_file(*args, **kwargs)
2001
2235
class Converter5to6(object):
2002
2236
"""Perform an in-place upgrade of format 5 to format 6"""