~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Robert J. Tanner
  • Date: 2009-04-29 05:53:21 UTC
  • mfrom: (4311 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4312.
  • Revision ID: tanner@real-time.com-20090429055321-v2s5l1mgki9f6cgn
[merge] 1.14 back to trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
 
18
from cStringIO import StringIO
18
19
import sys
19
20
 
20
21
from bzrlib.lazy_import import lazy_import
30
31
        lockable_files,
31
32
        repository,
32
33
        revision as _mod_revision,
 
34
        rio,
33
35
        symbol_versioning,
34
36
        transport,
35
37
        tsort,
99
101
    def _open_hook(self):
100
102
        """Called by init to allow simpler extension of the base class."""
101
103
 
102
 
    def _activate_fallback_location(self, url):
 
104
    def _activate_fallback_location(self, url, lock_style):
103
105
        """Activate the branch/repository from url as a fallback repository."""
104
 
        self.repository.add_fallback_repository(
105
 
            self._get_fallback_repository(url))
 
106
        repo = self._get_fallback_repository(url)
 
107
        if lock_style == 'write':
 
108
            repo.lock_write()
 
109
        elif lock_style == 'read':
 
110
            repo.lock_read()
 
111
        self.repository.add_fallback_repository(repo)
106
112
 
107
113
    def break_lock(self):
108
114
        """Break a lock if one is present from another instance.
496
502
        """
497
503
        raise errors.UpgradeRequired(self.base)
498
504
 
 
505
    def set_reference_info(self, file_id, tree_path, branch_location):
 
506
        """Set the branch location to use for a tree reference."""
 
507
        raise errors.UnsupportedOperation(self.set_reference_info, self)
 
508
 
 
509
    def get_reference_info(self, file_id):
 
510
        """Get the tree_path and branch_location for a tree reference."""
 
511
        raise errors.UnsupportedOperation(self.get_reference_info, self)
 
512
 
499
513
    @needs_write_lock
500
514
    def fetch(self, from_branch, last_revision=None, pb=None):
501
515
        """Copy revisions from from_branch into this branch.
590
604
    def set_revision_history(self, rev_history):
591
605
        raise NotImplementedError(self.set_revision_history)
592
606
 
 
607
    @needs_write_lock
 
608
    def set_parent(self, url):
 
609
        """See Branch.set_parent."""
 
610
        # TODO: Maybe delete old location files?
 
611
        # URLs should never be unicode, even on the local fs,
 
612
        # FIXUP this and get_parent in a future branch format bump:
 
613
        # read and rewrite the file. RBC 20060125
 
614
        if url is not None:
 
615
            if isinstance(url, unicode):
 
616
                try:
 
617
                    url = url.encode('ascii')
 
618
                except UnicodeEncodeError:
 
619
                    raise errors.InvalidURL(url,
 
620
                        "Urls must be 7-bit ascii, "
 
621
                        "use bzrlib.urlutils.escape")
 
622
            url = urlutils.relative_url(self.base, url)
 
623
        self._set_parent_location(url)
 
624
 
 
625
    @needs_write_lock
593
626
    def set_stacked_on_url(self, url):
594
627
        """Set the URL this branch is stacked against.
595
628
 
608
641
                errors.UnstackableRepositoryFormat):
609
642
                return
610
643
            url = ''
 
644
            # XXX: Lock correctness - should unlock our old repo if we were
 
645
            # locked.
611
646
            # repositories don't offer an interface to remove fallback
612
647
            # repositories today; take the conceptually simpler option and just
613
648
            # reopen it.
614
649
            self.repository = self.bzrdir.find_repository()
 
650
            self.repository.lock_write()
615
651
            # for every revision reference the branch has, ensure it is pulled
616
652
            # in.
617
653
            source_repository = self._get_fallback_repository(old_url)
620
656
                self.repository.fetch(source_repository, revision_id,
621
657
                    find_ghosts=True)
622
658
        else:
623
 
            self._activate_fallback_location(url)
 
659
            self._activate_fallback_location(url, 'write')
624
660
        # write this out after the repository is stacked to avoid setting a
625
661
        # stacked config that doesn't work.
626
662
        self._set_config_location('stacked_on_location', url)
944
980
                raise errors.HookFailed(
945
981
                    'pre_change_branch_tip', hook_name, exc_info)
946
982
 
947
 
    def set_parent(self, url):
948
 
        raise NotImplementedError(self.set_parent)
949
 
 
950
983
    @needs_write_lock
951
984
    def update(self):
952
985
        """Synchronise this branch with the master branch if any.
982
1015
                     be truncated to end with revision_id.
983
1016
        """
984
1017
        result = to_bzrdir.create_branch()
985
 
        if repository_policy is not None:
986
 
            repository_policy.configure_branch(result)
987
 
        self.copy_content_into(result, revision_id=revision_id)
988
 
        return  result
 
1018
        result.lock_write()
 
1019
        try:
 
1020
            if repository_policy is not None:
 
1021
                repository_policy.configure_branch(result)
 
1022
            self.copy_content_into(result, revision_id=revision_id)
 
1023
        finally:
 
1024
            result.unlock()
 
1025
        return result
989
1026
 
990
1027
    @needs_read_lock
991
1028
    def sprout(self, to_bzrdir, revision_id=None, repository_policy=None):
997
1034
                     be truncated to end with revision_id.
998
1035
        """
999
1036
        result = to_bzrdir.create_branch()
1000
 
        if repository_policy is not None:
1001
 
            repository_policy.configure_branch(result)
1002
 
        self.copy_content_into(result, revision_id=revision_id)
1003
 
        result.set_parent(self.bzrdir.root_transport.base)
 
1037
        result.lock_write()
 
1038
        try:
 
1039
            if repository_policy is not None:
 
1040
                repository_policy.configure_branch(result)
 
1041
            self.copy_content_into(result, revision_id=revision_id)
 
1042
            result.set_parent(self.bzrdir.root_transport.base)
 
1043
        finally:
 
1044
            result.unlock()
1004
1045
        return result
1005
1046
 
1006
1047
    def _synchronize_history(self, destination, revision_id):
1039
1080
        revision_id: if not None, the revision history in the new branch will
1040
1081
                     be truncated to end with revision_id.
1041
1082
        """
 
1083
        self.update_references(destination)
1042
1084
        self._synchronize_history(destination, revision_id)
1043
1085
        try:
1044
1086
            parent = self.get_parent()
1050
1092
        if self._push_should_merge_tags():
1051
1093
            self.tags.merge_to(destination.tags)
1052
1094
 
 
1095
    def update_references(self, target):
 
1096
        if not getattr(self._format, 'supports_reference_locations', False):
 
1097
            return
 
1098
        reference_dict = self._get_all_reference_info()
 
1099
        if len(reference_dict) == 0:
 
1100
            return
 
1101
        old_base = self.base
 
1102
        new_base = target.base
 
1103
        target_reference_dict = target._get_all_reference_info()
 
1104
        for file_id, (tree_path, branch_location) in (
 
1105
            reference_dict.items()):
 
1106
            branch_location = urlutils.rebase_url(branch_location,
 
1107
                                                  old_base, new_base)
 
1108
            target_reference_dict.setdefault(
 
1109
                file_id, (tree_path, branch_location))
 
1110
        target._set_all_reference_info(target_reference_dict)
 
1111
 
1053
1112
    @needs_read_lock
1054
1113
    def check(self):
1055
1114
        """Check consistency of the branch.
1103
1162
        return format
1104
1163
 
1105
1164
    def create_clone_on_transport(self, to_transport, revision_id=None,
1106
 
        stacked_on=None):
 
1165
        stacked_on=None, create_prefix=False, use_existing_dir=False):
1107
1166
        """Create a clone of this branch and its bzrdir.
1108
1167
 
1109
1168
        :param to_transport: The transport to clone onto.
1110
1169
        :param revision_id: The revision id to use as tip in the new branch.
1111
1170
            If None the tip is obtained from this branch.
1112
1171
        :param stacked_on: An optional URL to stack the clone on.
 
1172
        :param create_prefix: Create any missing directories leading up to
 
1173
            to_transport.
 
1174
        :param use_existing_dir: Use an existing directory if one exists.
1113
1175
        """
1114
1176
        # XXX: Fix the bzrdir API to allow getting the branch back from the
1115
1177
        # clone call. Or something. 20090224 RBC/spiv.
1116
 
        dir_to = self.bzrdir.clone_on_transport(to_transport,
1117
 
            revision_id=revision_id, stacked_on=stacked_on)
 
1178
        if revision_id is None:
 
1179
            revision_id = self.last_revision()
 
1180
        try:
 
1181
            dir_to = self.bzrdir.clone_on_transport(to_transport,
 
1182
                revision_id=revision_id, stacked_on=stacked_on,
 
1183
                create_prefix=create_prefix, use_existing_dir=use_existing_dir)
 
1184
        except errors.FileExists:
 
1185
            if not use_existing_dir:
 
1186
                raise
 
1187
        except errors.NoSuchFile:
 
1188
            if not create_prefix:
 
1189
                raise
1118
1190
        return dir_to.open_branch()
1119
1191
 
1120
1192
    def create_checkout(self, to_location, revision_id=None,
1174
1246
        reconciler.reconcile()
1175
1247
        return reconciler
1176
1248
 
1177
 
    def reference_parent(self, file_id, path):
 
1249
    def reference_parent(self, file_id, path, possible_transports=None):
1178
1250
        """Return the parent branch for a tree-reference file_id
1179
1251
        :param file_id: The file_id of the tree reference
1180
1252
        :param path: The path of the file_id in the tree
1181
1253
        :return: A branch associated with the file_id
1182
1254
        """
1183
1255
        # FIXME should provide multiple branches, based on config
1184
 
        return Branch.open(self.bzrdir.root_transport.clone(path).base)
 
1256
        return Branch.open(self.bzrdir.root_transport.clone(path).base,
 
1257
                           possible_transports=possible_transports)
1185
1258
 
1186
1259
    def supports_tags(self):
1187
1260
        return self._format.supports_tags()
1685
1758
 
1686
1759
 
1687
1760
 
1688
 
class BzrBranchFormat7(BranchFormatMetadir):
 
1761
class BzrBranchFormat8(BranchFormatMetadir):
 
1762
    """Metadir format supporting storing locations of subtree branches."""
 
1763
 
 
1764
    def _branch_class(self):
 
1765
        return BzrBranch8
 
1766
 
 
1767
    def get_format_string(self):
 
1768
        """See BranchFormat.get_format_string()."""
 
1769
        return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
 
1770
 
 
1771
    def get_format_description(self):
 
1772
        """See BranchFormat.get_format_description()."""
 
1773
        return "Branch format 8"
 
1774
 
 
1775
    def initialize(self, a_bzrdir):
 
1776
        """Create a branch of this format in a_bzrdir."""
 
1777
        utf8_files = [('last-revision', '0 null:\n'),
 
1778
                      ('branch.conf', ''),
 
1779
                      ('tags', ''),
 
1780
                      ('references', '')
 
1781
                      ]
 
1782
        return self._initialize_helper(a_bzrdir, utf8_files)
 
1783
 
 
1784
    def __init__(self):
 
1785
        super(BzrBranchFormat8, self).__init__()
 
1786
        self._matchingbzrdir.repository_format = \
 
1787
            RepositoryFormatKnitPack5RichRoot()
 
1788
 
 
1789
    def make_tags(self, branch):
 
1790
        """See bzrlib.branch.BranchFormat.make_tags()."""
 
1791
        return BasicTags(branch)
 
1792
 
 
1793
    def supports_stacking(self):
 
1794
        return True
 
1795
 
 
1796
    supports_reference_locations = True
 
1797
 
 
1798
 
 
1799
class BzrBranchFormat7(BzrBranchFormat8):
1689
1800
    """Branch format with last-revision, tags, and a stacked location pointer.
1690
1801
 
1691
1802
    The stacked location pointer is passed down to the repository and requires
1694
1805
    This format was introduced in bzr 1.6.
1695
1806
    """
1696
1807
 
 
1808
    def initialize(self, a_bzrdir):
 
1809
        """Create a branch of this format in a_bzrdir."""
 
1810
        utf8_files = [('last-revision', '0 null:\n'),
 
1811
                      ('branch.conf', ''),
 
1812
                      ('tags', ''),
 
1813
                      ]
 
1814
        return self._initialize_helper(a_bzrdir, utf8_files)
 
1815
 
1697
1816
    def _branch_class(self):
1698
1817
        return BzrBranch7
1699
1818
 
1705
1824
        """See BranchFormat.get_format_description()."""
1706
1825
        return "Branch format 7"
1707
1826
 
1708
 
    def initialize(self, a_bzrdir):
1709
 
        """Create a branch of this format in a_bzrdir."""
1710
 
        utf8_files = [('last-revision', '0 null:\n'),
1711
 
                      ('branch.conf', ''),
1712
 
                      ('tags', ''),
1713
 
                      ]
1714
 
        return self._initialize_helper(a_bzrdir, utf8_files)
1715
 
 
1716
 
    def __init__(self):
1717
 
        super(BzrBranchFormat7, self).__init__()
1718
 
        self._matchingbzrdir.repository_format = \
1719
 
            RepositoryFormatKnitPack5RichRoot()
1720
 
 
1721
 
    def make_tags(self, branch):
1722
 
        """See bzrlib.branch.BranchFormat.make_tags()."""
1723
 
        return BasicTags(branch)
1724
 
 
1725
 
    def supports_stacking(self):
1726
 
        return True
 
1827
    supports_reference_locations = False
1727
1828
 
1728
1829
 
1729
1830
class BranchReferenceFormat(BranchFormat):
1836
1937
__format5 = BzrBranchFormat5()
1837
1938
__format6 = BzrBranchFormat6()
1838
1939
__format7 = BzrBranchFormat7()
 
1940
__format8 = BzrBranchFormat8()
1839
1941
BranchFormat.register_format(__format5)
1840
1942
BranchFormat.register_format(BranchReferenceFormat())
1841
1943
BranchFormat.register_format(__format6)
1842
1944
BranchFormat.register_format(__format7)
 
1945
BranchFormat.register_format(__format8)
1843
1946
BranchFormat.set_default_format(__format6)
1844
1947
_legacy_formats = [BzrBranchFormat4(),
1845
1948
    ]
1899
2002
        return self.control_files.is_locked()
1900
2003
 
1901
2004
    def lock_write(self, token=None):
1902
 
        repo_token = self.repository.lock_write()
 
2005
        # All-in-one needs to always unlock/lock.
 
2006
        repo_control = getattr(self.repository, 'control_files', None)
 
2007
        if self.control_files == repo_control or not self.is_locked():
 
2008
            self.repository.lock_write()
 
2009
            took_lock = True
 
2010
        else:
 
2011
            took_lock = False
1903
2012
        try:
1904
 
            token = self.control_files.lock_write(token=token)
 
2013
            return self.control_files.lock_write(token=token)
1905
2014
        except:
1906
 
            self.repository.unlock()
 
2015
            if took_lock:
 
2016
                self.repository.unlock()
1907
2017
            raise
1908
 
        return token
1909
2018
 
1910
2019
    def lock_read(self):
1911
 
        self.repository.lock_read()
 
2020
        # All-in-one needs to always unlock/lock.
 
2021
        repo_control = getattr(self.repository, 'control_files', None)
 
2022
        if self.control_files == repo_control or not self.is_locked():
 
2023
            self.repository.lock_read()
 
2024
            took_lock = True
 
2025
        else:
 
2026
            took_lock = False
1912
2027
        try:
1913
2028
            self.control_files.lock_read()
1914
2029
        except:
1915
 
            self.repository.unlock()
 
2030
            if took_lock:
 
2031
                self.repository.unlock()
1916
2032
            raise
1917
2033
 
1918
2034
    def unlock(self):
1919
 
        # TODO: test for failed two phase locks. This is known broken.
1920
2035
        try:
1921
2036
            self.control_files.unlock()
1922
2037
        finally:
1923
 
            self.repository.unlock()
1924
 
        if not self.control_files.is_locked():
1925
 
            # we just released the lock
1926
 
            self._clear_cached_state()
 
2038
            # All-in-one needs to always unlock/lock.
 
2039
            repo_control = getattr(self.repository, 'control_files', None)
 
2040
            if (self.control_files == repo_control or
 
2041
                not self.control_files.is_locked()):
 
2042
                self.repository.unlock()
 
2043
            if not self.control_files.is_locked():
 
2044
                # we just released the lock
 
2045
                self._clear_cached_state()
1927
2046
 
1928
2047
    def peek_lock_mode(self):
1929
2048
        if self.control_files._lock_count == 0:
2072
2191
        try:
2073
2192
            # We assume that during 'pull' the local repository is closer than
2074
2193
            # the remote one.
 
2194
            source.update_references(self)
2075
2195
            graph = self.repository.get_graph(source.repository)
2076
2196
            result.old_revno, result.old_revid = self.last_revision_info()
2077
2197
            self.update_revisions(source, stop_revision, overwrite=overwrite,
2174
2294
        result.source_branch = self
2175
2295
        result.target_branch = target
2176
2296
        result.old_revno, result.old_revid = target.last_revision_info()
 
2297
        self.update_references(target)
2177
2298
        if result.old_revid != self.last_revision():
2178
2299
            # We assume that during 'push' this repository is closer than
2179
2300
            # the target.
2194
2315
            'push_location', location,
2195
2316
            store=_mod_config.STORE_LOCATION_NORECURSE)
2196
2317
 
2197
 
    @needs_write_lock
2198
 
    def set_parent(self, url):
2199
 
        """See Branch.set_parent."""
2200
 
        # TODO: Maybe delete old location files?
2201
 
        # URLs should never be unicode, even on the local fs,
2202
 
        # FIXUP this and get_parent in a future branch format bump:
2203
 
        # read and rewrite the file. RBC 20060125
2204
 
        if url is not None:
2205
 
            if isinstance(url, unicode):
2206
 
                try:
2207
 
                    url = url.encode('ascii')
2208
 
                except UnicodeEncodeError:
2209
 
                    raise errors.InvalidURL(url,
2210
 
                        "Urls must be 7-bit ascii, "
2211
 
                        "use bzrlib.urlutils.escape")
2212
 
            url = urlutils.relative_url(self.base, url)
2213
 
        self._set_parent_location(url)
2214
 
 
2215
2318
    def _set_parent_location(self, url):
2216
2319
        if url is None:
2217
2320
            self._transport.delete('parent')
2347
2450
        return None
2348
2451
 
2349
2452
 
2350
 
class BzrBranch7(BzrBranch5):
2351
 
    """A branch with support for a fallback repository."""
 
2453
class BzrBranch8(BzrBranch5):
 
2454
    """A branch that stores tree-reference locations."""
2352
2455
 
2353
2456
    def _open_hook(self):
2354
2457
        if self._ignore_fallbacks:
2366
2469
                    raise AssertionError(
2367
2470
                        "'transform_fallback_location' hook %s returned "
2368
2471
                        "None, not a URL." % hook_name)
2369
 
            self._activate_fallback_location(url)
 
2472
            self._activate_fallback_location(url, None)
2370
2473
 
2371
2474
    def __init__(self, *args, **kwargs):
2372
2475
        self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2373
 
        super(BzrBranch7, self).__init__(*args, **kwargs)
 
2476
        super(BzrBranch8, self).__init__(*args, **kwargs)
2374
2477
        self._last_revision_info_cache = None
2375
2478
        self._partial_revision_history_cache = []
 
2479
        self._reference_info = None
2376
2480
 
2377
2481
    def _clear_cached_state(self):
2378
 
        super(BzrBranch7, self)._clear_cached_state()
 
2482
        super(BzrBranch8, self)._clear_cached_state()
2379
2483
        self._last_revision_info_cache = None
2380
2484
        self._partial_revision_history_cache = []
 
2485
        self._reference_info = None
2381
2486
 
2382
2487
    def _last_revision_info(self):
2383
2488
        revision_string = self._transport.get_bytes('last-revision')
2493
2598
        """Set the parent branch"""
2494
2599
        return self._get_config_location('parent_location')
2495
2600
 
 
2601
    @needs_write_lock
 
2602
    def _set_all_reference_info(self, info_dict):
 
2603
        """Replace all reference info stored in a branch.
 
2604
 
 
2605
        :param info_dict: A dict of {file_id: (tree_path, branch_location)}
 
2606
        """
 
2607
        s = StringIO()
 
2608
        writer = rio.RioWriter(s)
 
2609
        for key, (tree_path, branch_location) in info_dict.iteritems():
 
2610
            stanza = rio.Stanza(file_id=key, tree_path=tree_path,
 
2611
                                branch_location=branch_location)
 
2612
            writer.write_stanza(stanza)
 
2613
        self._transport.put_bytes('references', s.getvalue())
 
2614
        self._reference_info = info_dict
 
2615
 
 
2616
    @needs_read_lock
 
2617
    def _get_all_reference_info(self):
 
2618
        """Return all the reference info stored in a branch.
 
2619
 
 
2620
        :return: A dict of {file_id: (tree_path, branch_location)}
 
2621
        """
 
2622
        if self._reference_info is not None:
 
2623
            return self._reference_info
 
2624
        rio_file = self._transport.get('references')
 
2625
        try:
 
2626
            stanzas = rio.read_stanzas(rio_file)
 
2627
            info_dict = dict((s['file_id'], (s['tree_path'],
 
2628
                             s['branch_location'])) for s in stanzas)
 
2629
        finally:
 
2630
            rio_file.close()
 
2631
        self._reference_info = info_dict
 
2632
        return info_dict
 
2633
 
 
2634
    def set_reference_info(self, file_id, tree_path, branch_location):
 
2635
        """Set the branch location to use for a tree reference.
 
2636
 
 
2637
        :param file_id: The file-id of the tree reference.
 
2638
        :param tree_path: The path of the tree reference in the tree.
 
2639
        :param branch_location: The location of the branch to retrieve tree
 
2640
            references from.
 
2641
        """
 
2642
        info_dict = self._get_all_reference_info()
 
2643
        info_dict[file_id] = (tree_path, branch_location)
 
2644
        if None in (tree_path, branch_location):
 
2645
            if tree_path is not None:
 
2646
                raise ValueError('tree_path must be None when branch_location'
 
2647
                                 ' is None.')
 
2648
            if branch_location is not None:
 
2649
                raise ValueError('branch_location must be None when tree_path'
 
2650
                                 ' is None.')
 
2651
            del info_dict[file_id]
 
2652
        self._set_all_reference_info(info_dict)
 
2653
 
 
2654
    def get_reference_info(self, file_id):
 
2655
        """Get the tree_path and branch_location for a tree reference.
 
2656
 
 
2657
        :return: a tuple of (tree_path, branch_location)
 
2658
        """
 
2659
        return self._get_all_reference_info().get(file_id, (None, None))
 
2660
 
 
2661
    def reference_parent(self, file_id, path, possible_transports=None):
 
2662
        """Return the parent branch for a tree-reference file_id.
 
2663
 
 
2664
        :param file_id: The file_id of the tree reference
 
2665
        :param path: The path of the file_id in the tree
 
2666
        :return: A branch associated with the file_id
 
2667
        """
 
2668
        branch_location = self.get_reference_info(file_id)[1]
 
2669
        if branch_location is None:
 
2670
            return Branch.reference_parent(self, file_id, path,
 
2671
                                           possible_transports)
 
2672
        branch_location = urlutils.join(self.base, branch_location)
 
2673
        return Branch.open(branch_location,
 
2674
                           possible_transports=possible_transports)
 
2675
 
2496
2676
    def set_push_location(self, location):
2497
2677
        """See Branch.set_push_location."""
2498
2678
        self._set_config_location('push_location', location)
2596
2776
        return self.revno() - index
2597
2777
 
2598
2778
 
 
2779
class BzrBranch7(BzrBranch8):
 
2780
    """A branch with support for a fallback repository."""
 
2781
 
 
2782
    def set_reference_info(self, file_id, tree_path, branch_location):
 
2783
        Branch.set_reference_info(self, file_id, tree_path, branch_location)
 
2784
 
 
2785
    def get_reference_info(self, file_id):
 
2786
        Branch.get_reference_info(self, file_id)
 
2787
 
 
2788
    def reference_parent(self, file_id, path, possible_transports=None):
 
2789
        return Branch.reference_parent(self, file_id, path,
 
2790
                                       possible_transports)
 
2791
 
 
2792
 
2599
2793
class BzrBranch6(BzrBranch7):
2600
2794
    """See BzrBranchFormat6 for the capabilities of this branch.
2601
2795
 
2742
2936
        branch._transport.put_bytes('format', format.get_format_string())
2743
2937
 
2744
2938
 
 
2939
class Converter7to8(object):
 
2940
    """Perform an in-place upgrade of format 6 to format 7"""
 
2941
 
 
2942
    def convert(self, branch):
 
2943
        format = BzrBranchFormat8()
 
2944
        branch._transport.put_bytes('references', '')
 
2945
        # update target format
 
2946
        branch._transport.put_bytes('format', format.get_format_string())
 
2947
 
2745
2948
 
2746
2949
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2747
2950
    """Run ``callable(*args, **kwargs)``, write-locking target for the