562
574
result.set_parent(self.bzrdir.root_transport.base)
566
def copy_content_into(self, destination, revision_id=None):
567
"""Copy the content of self into destination.
569
revision_id: if not None, the revision history in the new branch will
570
be truncated to end with revision_id.
577
def _synchronize_history(self, destination, revision_id):
578
"""Synchronize last revision and revision history between branches.
580
This version is most efficient when the destination is also a
581
BzrBranch5, but works for BzrBranch6 as long as the revision
582
history is the true lefthand parent history, and all of the revisions
583
are in the destination's repository. If not, set_revision_history
586
:param destination: The branch to copy the history into
587
:param revision_id: The revision-id to truncate history at. May
588
be None to copy complete history.
572
590
new_history = self.revision_history()
573
591
if revision_id is not None:
592
revision_id = osutils.safe_revision_id(revision_id)
575
594
new_history = new_history[:new_history.index(revision_id) + 1]
576
595
except ValueError:
577
596
rev = self.repository.get_revision(revision_id)
578
597
new_history = rev.get_history(self.repository)[1:]
579
598
destination.set_revision_history(new_history)
601
def copy_content_into(self, destination, revision_id=None):
602
"""Copy the content of self into destination.
604
revision_id: if not None, the revision history in the new branch will
605
be truncated to end with revision_id.
607
self._synchronize_history(destination, revision_id)
581
609
parent = self.get_parent()
582
610
except errors.InaccessibleParent, e:
717
746
"""Return the short format description for this format."""
718
747
raise NotImplementedError(self.get_format_description)
749
def _initialize_helper(self, a_bzrdir, utf8_files, lock_type='metadir',
751
"""Initialize a branch in a bzrdir, with specified files
753
:param a_bzrdir: The bzrdir to initialize the branch in
754
:param utf8_files: The files to create as a list of
755
(filename, content) tuples
756
:param set_format: If True, set the format with
757
self.get_format_string. (BzrBranch4 has its format set
759
:return: a branch in this format
761
mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
762
branch_transport = a_bzrdir.get_branch_transport(self)
764
'metadir': ('lock', lockdir.LockDir),
765
'branch4': ('branch-lock', lockable_files.TransportLock),
767
lock_name, lock_class = lock_map[lock_type]
768
control_files = lockable_files.LockableFiles(branch_transport,
769
lock_name, lock_class)
770
control_files.create_lock()
771
control_files.lock_write()
773
control_files.put_utf8('format', self.get_format_string())
775
for file, content in utf8_files:
776
control_files.put_utf8(file, content)
778
control_files.unlock()
779
return self.open(a_bzrdir, _found=True)
720
781
def initialize(self, a_bzrdir):
721
782
"""Create a branch of this format in a_bzrdir."""
722
783
raise NotImplementedError(self.initialize)
945
993
_repository=a_bzrdir.find_repository())
996
class BzrBranchFormat6(BzrBranchFormat5):
997
"""Branch format with last-revision
999
Unlike previous formats, this has no explicit revision history. Instead,
1000
this just stores the last-revision, and the left-hand history leading
1001
up to there is the history.
1003
This format was introduced in bzr 0.15
1006
def get_format_string(self):
1007
"""See BranchFormat.get_format_string()."""
1008
return "Bazaar-NG branch format 6\n"
1010
def get_format_description(self):
1011
"""See BranchFormat.get_format_description()."""
1012
return "Branch format 6"
1014
def initialize(self, a_bzrdir):
1015
"""Create a branch of this format in a_bzrdir."""
1016
utf8_files = [('last-revision', '0 null:\n'),
1017
('branch-name', ''),
1020
return self._initialize_helper(a_bzrdir, utf8_files)
1022
def open(self, a_bzrdir, _found=False):
1023
"""Return the branch object for a_bzrdir
1025
_found is a private parameter, do not use it. It is used to indicate
1026
if format probing has already be done.
1029
format = BranchFormat.find_format(a_bzrdir)
1030
assert format.__class__ == self.__class__
1031
transport = a_bzrdir.get_branch_transport(None)
1032
control_files = lockable_files.LockableFiles(transport, 'lock',
1034
return BzrBranch6(_format=self,
1035
_control_files=control_files,
1037
_repository=a_bzrdir.find_repository())
948
1040
class BranchReferenceFormat(BranchFormat):
949
1041
"""Bzr branch reference format.
1229
1344
if history is not None:
1230
1345
# mutter("cache hit for revision-history in %s", self)
1231
1346
return list(history)
1232
decode_utf8 = cache_utf8.decode
1233
history = [decode_utf8(l.rstrip('\r\n')) for l in
1234
self.control_files.get('revision-history').readlines()]
1347
history = self._gen_revision_history()
1235
1348
transaction.map.add_revision_history(history)
1236
1349
# this call is disabled because revision_history is
1237
1350
# not really an object yet, and the transaction is for objects.
1238
1351
# transaction.register_clean(history, precious=True)
1239
1352
return list(history)
1242
def generate_revision_history(self, revision_id, last_rev=None,
1244
"""Create a new revision history that will finish with revision_id.
1246
:param revision_id: the new tip to use.
1247
:param last_rev: The previous last_revision. If not None, then this
1248
must be a ancestory of revision_id, or DivergedBranches is raised.
1249
:param other_branch: The other branch that DivergedBranches should
1250
raise with respect to.
1354
def _lefthand_history(self, revision_id, last_rev=None,
1252
1356
# stop_revision must be a descendant of last_revision
1253
1357
stop_graph = self.repository.get_revision_graph(revision_id)
1254
1358
if last_rev is not None and last_rev not in stop_graph:
1692
1822
BranchFormat.register_format(BzrBranchExperimental)
1825
class BzrBranch6(BzrBranch5):
1828
def last_revision_info(self):
1829
revision_string = self.control_files.get('last-revision').read()
1830
revno, revision_id = revision_string.rstrip('\n').split(' ', 1)
1831
revision_id = cache_utf8.get_cached_utf8(revision_id)
1833
return revno, revision_id
1835
def last_revision(self):
1836
"""Return last revision id, or None"""
1837
revision_id = self.last_revision_info()[1]
1838
if revision_id == _mod_revision.NULL_REVISION:
1842
def _write_last_revision_info(self, revno, revision_id):
1843
"""Simply write out the revision id, with no checks.
1845
Use set_last_revision_info to perform this safely.
1847
Does not update the revision_history cache.
1848
Intended to be called by set_last_revision_info and
1849
_write_revision_history.
1851
if revision_id is None:
1852
revision_id = 'null:'
1853
out_string = '%d %s\n' % (revno, revision_id)
1854
self.control_files.put_bytes('last-revision', out_string)
1857
def set_last_revision_info(self, revno, revision_id):
1858
revision_id = osutils.safe_revision_id(revision_id)
1859
if self._get_append_revisions_only():
1860
self._check_history_violation(revision_id)
1861
self._write_last_revision_info(revno, revision_id)
1862
transaction = self.get_transaction()
1863
cached_history = transaction.map.find_revision_history()
1864
if cached_history is not None:
1865
transaction.map.remove_object(cached_history)
1867
def _check_history_violation(self, revision_id):
1868
last_revision = self.last_revision()
1869
if last_revision is None:
1871
if last_revision not in self._lefthand_history(revision_id):
1872
raise errors.AppendRevisionsOnlyViolation(self.base)
1874
def _gen_revision_history(self):
1875
"""Generate the revision history from last revision
1877
history = list(self.repository.iter_reverse_revision_history(
1878
self.last_revision()))
1882
def _write_revision_history(self, history):
1883
"""Factored out of set_revision_history.
1885
This performs the actual writing to disk, with format-specific checks.
1886
It is intended to be called by BzrBranch5.set_revision_history.
1888
if len(history) == 0:
1889
last_revision = 'null:'
1891
if history != self._lefthand_history(history[-1]):
1892
raise errors.NotLefthandHistory(history)
1893
last_revision = history[-1]
1894
if self._get_append_revisions_only():
1895
self._check_history_violation(last_revision)
1896
self._write_last_revision_info(len(history), last_revision)
1899
def append_revision(self, *revision_ids):
1900
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
1901
if len(revision_ids) == 0:
1903
prev_revno, prev_revision = self.last_revision_info()
1904
for revision in self.repository.get_revisions(revision_ids):
1905
if prev_revision == _mod_revision.NULL_REVISION:
1906
if revision.parent_ids != []:
1907
raise errors.NotLeftParentDescendant(self, prev_revision,
1908
revision.revision_id)
1910
if revision.parent_ids[0] != prev_revision:
1911
raise errors.NotLeftParentDescendant(self, prev_revision,
1912
revision.revision_id)
1913
prev_revision = revision.revision_id
1914
self.set_last_revision_info(prev_revno + len(revision_ids),
1917
def _set_config_location(self, name, url, config=None,
1918
make_relative=False):
1920
config = self.get_config()
1924
url = urlutils.relative_url(self.base, url)
1925
config.set_user_option(name, url)
1928
def _get_config_location(self, name, config=None):
1930
config = self.get_config()
1931
location = config.get_user_option(name)
1937
def _set_parent_location(self, url):
1938
"""Set the parent branch"""
1939
self._set_config_location('parent_location', url, make_relative=True)
1942
def _get_parent_location(self):
1943
"""Set the parent branch"""
1944
return self._get_config_location('parent_location')
1946
def set_push_location(self, location):
1947
"""See Branch.set_push_location."""
1948
self._set_config_location('push_location', location)
1950
def set_bound_location(self, location):
1951
"""See Branch.set_push_location."""
1953
config = self.get_config()
1954
if location is None:
1955
if config.get_user_option('bound') != 'True':
1958
config.set_user_option('bound', 'False')
1961
self._set_config_location('bound_location', location,
1963
config.set_user_option('bound', 'True')
1966
def _get_bound_location(self, bound):
1967
"""Return the bound location in the config file.
1969
Return None if the bound parameter does not match"""
1970
config = self.get_config()
1971
config_bound = (config.get_user_option('bound') == 'True')
1972
if config_bound != bound:
1974
return self._get_config_location('bound_location', config=config)
1976
def get_bound_location(self):
1977
"""See Branch.set_push_location."""
1978
return self._get_bound_location(True)
1980
def get_old_bound_location(self):
1981
"""See Branch.get_old_bound_location"""
1982
return self._get_bound_location(False)
1984
def set_append_revisions_only(self, enabled):
1989
self.get_config().set_user_option('append_revisions_only', value)
1991
def _get_append_revisions_only(self):
1992
value = self.get_config().get_user_option('append_revisions_only')
1993
return value == 'True'
1995
def _synchronize_history(self, destination, revision_id):
1996
"""Synchronize last revision and revision history between branches.
1998
This version is most efficient when the destination is also a
1999
BzrBranch6, but works for BzrBranch5, as long as the destination's
2000
repository contains all the lefthand ancestors of the intended
2001
last_revision. If not, set_last_revision_info will fail.
2003
:param destination: The branch to copy the history into
2004
:param revision_id: The revision-id to truncate history at. May
2005
be None to copy complete history.
2007
if revision_id is None:
2008
revno, revision_id = self.last_revision_info()
2010
revno = self.revision_id_to_revno(revision_id)
2011
destination.set_last_revision_info(revno, revision_id)
1695
2014
class BranchTestProviderAdapter(object):
1696
2015
"""A tool to generate a suite testing multiple branch formats at once.