794
809
def __str__(self):
795
810
return self.get_format_string().rstrip()
812
def supports_tags(self):
813
"""True if this format supports tags stored in the branch"""
814
return False # by default
816
# XXX: Probably doesn't really belong here -- mbp 20070212
817
def _initialize_control_files(self, a_bzrdir, utf8_files, lock_filename,
819
branch_transport = a_bzrdir.get_branch_transport(self)
820
control_files = lockable_files.LockableFiles(branch_transport,
821
lock_filename, lock_class)
822
control_files.create_lock()
823
control_files.lock_write()
825
for filename, content in utf8_files:
826
control_files.put_utf8(filename, content)
828
control_files.unlock()
798
831
class BranchHooks(dict):
799
832
"""A dictionary mapping hook name to a list of callables for branch hooks.
1105
1143
upgrade/recovery type use; it's not guaranteed that
1106
1144
all operations will work on old format branches.
1146
Branch.__init__(self)
1108
1147
if a_bzrdir is None:
1109
1148
self.bzrdir = bzrdir.BzrDir.open(transport.base)
1111
1150
self.bzrdir = a_bzrdir
1112
self._transport = self.bzrdir.transport.clone('..')
1113
self._base = self._transport.base
1151
# self._transport used to point to the directory containing the
1152
# control directory, but was not used - now it's just the transport
1153
# for the branch control files. mbp 20070212
1154
self._base = self.bzrdir.transport.clone('..').base
1114
1155
self._format = _format
1115
1156
if _control_files is None:
1116
1157
raise ValueError('BzrBranch _control_files is None')
1117
1158
self.control_files = _control_files
1159
self._transport = _control_files._transport
1118
1160
if deprecated_passed(init):
1119
1161
warn("BzrBranch.__init__(..., init=XXX): The init parameter is "
1120
1162
"deprecated as of bzr 0.8. Please use Branch.create().",
1258
1302
This performs the actual writing to disk.
1259
1303
It is intended to be called by BzrBranch5.set_revision_history."""
1260
self.control_files.put_utf8(
1304
self.control_files.put_bytes(
1261
1305
'revision-history', '\n'.join(history))
1263
1307
@needs_write_lock
1264
1308
def set_revision_history(self, rev_history):
1265
1309
"""See Branch.set_revision_history."""
1310
rev_history = [osutils.safe_revision_id(r) for r in rev_history]
1266
1311
self._write_revision_history(rev_history)
1267
1312
transaction = self.get_transaction()
1268
1313
history = transaction.map.find_revision_history()
1283
1328
@needs_write_lock
1284
1329
def set_last_revision_info(self, revno, revision_id):
1330
revision_id = osutils.safe_revision_id(revision_id)
1285
1331
history = self._lefthand_history(revision_id)
1286
1332
assert len(history) == revno, '%d != %d' % (len(history), revno)
1287
1333
self.set_revision_history(history)
1289
1335
def _gen_revision_history(self):
1290
decode_utf8 = cache_utf8.decode
1291
history = [decode_utf8(l.rstrip('\r\n')) for l in
1336
get_cached_utf8 = cache_utf8.get_cached_utf8
1337
history = [get_cached_utf8(l.rstrip('\r\n')) for l in
1292
1338
self.control_files.get('revision-history').readlines()]
1390
1439
:param _run_hooks: Private parameter - allow disabling of
1391
1440
hooks, used when pushing to a master branch.
1442
result = PullResult()
1443
result.source_branch = source
1444
result.target_branch = self
1393
1445
source.lock_read()
1395
old_count, old_tip = self.last_revision_info()
1447
result.old_revno, result.old_revid = self.last_revision_info()
1397
1449
self.update_revisions(source, stop_revision)
1398
1450
except DivergedBranches:
1399
1451
if not overwrite:
1402
self.set_revision_history(source.revision_history())
1403
new_count, new_tip = self.last_revision_info()
1454
if stop_revision is None:
1455
stop_revision = source.last_revision()
1456
self.generate_revision_history(stop_revision)
1457
result.tag_conflicts = source.tags.merge_to(self.tags)
1458
result.new_revno, result.new_revid = self.last_revision_info()
1460
result.master_branch = _hook_master
1461
result.local_branch = self
1463
result.master_branch = self
1464
result.local_branch = None
1410
1466
for hook in Branch.hooks['post_pull']:
1411
hook(source, _hook_local, _hook_master, old_count, old_tip,
1413
return new_count - old_count
1415
1469
source.unlock()
1417
1472
def _get_parent_location(self):
1418
1473
_locs = ['parent', 'pull', 'x-pull']
1433
1488
:param _run_hooks: Private parameter - allow disabling of
1434
1489
hooks, used when pushing to a master branch.
1491
result = PushResult()
1492
result.source_branch = self
1493
result.target_branch = target
1436
1494
target.lock_write()
1438
old_count, old_tip = target.last_revision_info()
1496
result.old_revno, result.old_revid = target.last_revision_info()
1440
1498
target.update_revisions(self, stop_revision)
1441
1499
except DivergedBranches:
1445
1503
target.set_revision_history(self.revision_history())
1446
new_count, new_tip = target.last_revision_info()
1504
result.tag_conflicts = self.tags.merge_to(target.tags)
1505
result.new_revno, result.new_revid = target.last_revision_info()
1507
result.master_branch = _hook_master
1508
result.local_branch = target
1510
result.master_branch = target
1511
result.local_branch = None
1449
_hook_local = target
1451
_hook_master = target
1453
1513
for hook in Branch.hooks['post_push']:
1454
hook(self, _hook_local, _hook_master, old_count, old_tip,
1456
return new_count - old_count
1458
1516
target.unlock()
1460
1519
def get_parent(self):
1461
1520
"""See Branch.get_parent."""
1749
class BzrBranchExperimental(BzrBranch5):
1750
"""Bzr experimental branch format
1753
- a revision-history file.
1755
- a lock dir guarding the branch itself
1756
- all of this stored in a branch/ subdirectory
1757
- works with shared repositories.
1758
- a tag dictionary in the branch
1760
This format is new in bzr 0.15, but shouldn't be used for real data,
1763
This class acts as it's own BranchFormat.
1766
_matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1769
def get_format_string(cls):
1770
"""See BranchFormat.get_format_string()."""
1771
return "Bazaar-NG branch format experimental\n"
1774
def get_format_description(cls):
1775
"""See BranchFormat.get_format_description()."""
1776
return "Experimental branch format"
1779
def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1781
branch_transport = a_bzrdir.get_branch_transport(cls)
1782
control_files = lockable_files.LockableFiles(branch_transport,
1783
lock_filename, lock_class)
1784
control_files.create_lock()
1785
control_files.lock_write()
1787
for filename, content in utf8_files:
1788
control_files.put_utf8(filename, content)
1790
control_files.unlock()
1793
def initialize(cls, a_bzrdir):
1794
"""Create a branch of this format in a_bzrdir."""
1795
utf8_files = [('format', cls.get_format_string()),
1796
('revision-history', ''),
1797
('branch-name', ''),
1800
cls._initialize_control_files(a_bzrdir, utf8_files,
1801
'lock', lockdir.LockDir)
1802
return cls.open(a_bzrdir, _found=True)
1805
def open(cls, a_bzrdir, _found=False):
1806
"""Return the branch object for a_bzrdir
1808
_found is a private parameter, do not use it. It is used to indicate
1809
if format probing has already be done.
1812
format = BranchFormat.find_format(a_bzrdir)
1813
assert format.__class__ == cls
1814
transport = a_bzrdir.get_branch_transport(None)
1815
control_files = lockable_files.LockableFiles(transport, 'lock',
1817
return cls(_format=cls,
1818
_control_files=control_files,
1820
_repository=a_bzrdir.find_repository())
1823
def is_supported(cls):
1826
def _make_tags(self):
1827
return BasicTags(self)
1830
def supports_tags(cls):
1834
BranchFormat.register_format(BzrBranchExperimental)
1691
1837
class BzrBranch6(BzrBranch5):
1693
1839
@needs_read_lock
1694
1840
def last_revision_info(self):
1695
revision_string = self.control_files.get_utf8('last-revision').read()
1841
revision_string = self.control_files.get('last-revision').read()
1696
1842
revno, revision_id = revision_string.rstrip('\n').split(' ', 1)
1843
revision_id = cache_utf8.get_cached_utf8(revision_id)
1697
1844
revno = int(revno)
1698
1845
return revno, revision_id
1716
1863
if revision_id is None:
1717
1864
revision_id = 'null:'
1718
1865
out_string = '%d %s\n' % (revno, revision_id)
1719
self.control_files.put_utf8('last-revision', out_string)
1866
self.control_files.put_bytes('last-revision', out_string)
1721
1868
@needs_write_lock
1722
1869
def set_last_revision_info(self, revno, revision_id):
1870
revision_id = osutils.safe_revision_id(revision_id)
1723
1871
if self._get_append_revisions_only():
1724
1872
self._check_history_violation(revision_id)
1725
1873
self._write_last_revision_info(revno, revision_id)
1897
2049
new_test.bzrdir_format = bzrdir_format
1898
2050
new_test.branch_format = branch_format
1899
2051
def make_new_test_id():
1900
new_id = "%s(%s)" % (new_test.id(), branch_format.__class__.__name__)
2052
# the format can be either a class or an instance
2053
name = getattr(branch_format, '__name__',
2054
branch_format.__class__.__name__)
2055
new_id = "%s(%s)" % (new_test.id(), name)
1901
2056
return lambda: new_id
1902
2057
new_test.id = make_new_test_id()
1903
2058
result.addTest(new_test)
2062
######################################################################
2063
# results of operations
2066
class _Result(object):
2068
def _show_tag_conficts(self, to_file):
2069
if not getattr(self, 'tag_conflicts', None):
2071
to_file.write('Conflicting tags:\n')
2072
for name, value1, value2 in self.tag_conflicts:
2073
to_file.write(' %s\n' % (name, ))
2076
class PullResult(_Result):
2077
"""Result of a Branch.pull operation.
2079
:ivar old_revno: Revision number before pull.
2080
:ivar new_revno: Revision number after pull.
2081
:ivar old_revid: Tip revision id before pull.
2082
:ivar new_revid: Tip revision id after pull.
2083
:ivar source_branch: Source (local) branch object.
2084
:ivar master_branch: Master branch of the target, or None.
2085
:ivar target_branch: Target/destination branch object.
2089
# DEPRECATED: pull used to return the change in revno
2090
return self.new_revno - self.old_revno
2092
def report(self, to_file):
2093
if self.old_revid == self.new_revid:
2094
to_file.write('No revisions to pull.\n')
2096
to_file.write('Now on revision %d.\n' % self.new_revno)
2097
self._show_tag_conficts(to_file)
2100
class PushResult(_Result):
2101
"""Result of a Branch.push operation.
2103
:ivar old_revno: Revision number before push.
2104
:ivar new_revno: Revision number after push.
2105
:ivar old_revid: Tip revision id before push.
2106
:ivar new_revid: Tip revision id after push.
2107
:ivar source_branch: Source branch object.
2108
:ivar master_branch: Master branch of the target, or None.
2109
:ivar target_branch: Target/destination branch object.
2113
# DEPRECATED: push used to return the change in revno
2114
return self.new_revno - self.old_revno
2116
def report(self, to_file):
2117
"""Write a human-readable description of the result."""
2118
if self.old_revid == self.new_revid:
2119
to_file.write('No new revisions to push.\n')
2121
to_file.write('Pushed up to revision %d.\n' % self.new_revno)
2122
self._show_tag_conficts(to_file)
1907
2125
class BranchCheckResult(object):
1908
2126
"""Results of checking branch consistency.
1924
2142
self.branch._format)
1927
######################################################################
1931
@deprecated_function(zero_eight)
1932
def is_control_file(*args, **kwargs):
1933
"""See bzrlib.workingtree.is_control_file."""
1934
from bzrlib import workingtree
1935
return workingtree.is_control_file(*args, **kwargs)
1938
2145
class Converter5to6(object):
1939
2146
"""Perform an in-place upgrade of format 5 to format 6"""