~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-30 22:40:42 UTC
  • mfrom: (4323 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4324.
  • Revision ID: tanner@real-time.com-20090430224042-53v45axtue5bw45l
Merge 1.14.1 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()
1324
1397
        control_files = lockable_files.LockableFiles(branch_transport,
1325
1398
            lock_name, lock_class)
1326
1399
        control_files.create_lock()
1327
 
        control_files.lock_write()
 
1400
        try:
 
1401
            control_files.lock_write()
 
1402
        except errors.LockContention:
 
1403
            if lock_type != 'branch4':
 
1404
                raise
 
1405
            lock_taken = False
 
1406
        else:
 
1407
            lock_taken = True
1328
1408
        if set_format:
1329
1409
            utf8_files += [('format', self.get_format_string())]
1330
1410
        try:
1333
1413
                    filename, content,
1334
1414
                    mode=a_bzrdir._get_file_mode())
1335
1415
        finally:
1336
 
            control_files.unlock()
 
1416
            if lock_taken:
 
1417
                control_files.unlock()
1337
1418
        return self.open(a_bzrdir, _found=True)
1338
1419
 
1339
1420
    def initialize(self, a_bzrdir):
1685
1766
 
1686
1767
 
1687
1768
 
1688
 
class BzrBranchFormat7(BranchFormatMetadir):
 
1769
class BzrBranchFormat8(BranchFormatMetadir):
 
1770
    """Metadir format supporting storing locations of subtree branches."""
 
1771
 
 
1772
    def _branch_class(self):
 
1773
        return BzrBranch8
 
1774
 
 
1775
    def get_format_string(self):
 
1776
        """See BranchFormat.get_format_string()."""
 
1777
        return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
 
1778
 
 
1779
    def get_format_description(self):
 
1780
        """See BranchFormat.get_format_description()."""
 
1781
        return "Branch format 8"
 
1782
 
 
1783
    def initialize(self, a_bzrdir):
 
1784
        """Create a branch of this format in a_bzrdir."""
 
1785
        utf8_files = [('last-revision', '0 null:\n'),
 
1786
                      ('branch.conf', ''),
 
1787
                      ('tags', ''),
 
1788
                      ('references', '')
 
1789
                      ]
 
1790
        return self._initialize_helper(a_bzrdir, utf8_files)
 
1791
 
 
1792
    def __init__(self):
 
1793
        super(BzrBranchFormat8, self).__init__()
 
1794
        self._matchingbzrdir.repository_format = \
 
1795
            RepositoryFormatKnitPack5RichRoot()
 
1796
 
 
1797
    def make_tags(self, branch):
 
1798
        """See bzrlib.branch.BranchFormat.make_tags()."""
 
1799
        return BasicTags(branch)
 
1800
 
 
1801
    def supports_stacking(self):
 
1802
        return True
 
1803
 
 
1804
    supports_reference_locations = True
 
1805
 
 
1806
 
 
1807
class BzrBranchFormat7(BzrBranchFormat8):
1689
1808
    """Branch format with last-revision, tags, and a stacked location pointer.
1690
1809
 
1691
1810
    The stacked location pointer is passed down to the repository and requires
1694
1813
    This format was introduced in bzr 1.6.
1695
1814
    """
1696
1815
 
 
1816
    def initialize(self, a_bzrdir):
 
1817
        """Create a branch of this format in a_bzrdir."""
 
1818
        utf8_files = [('last-revision', '0 null:\n'),
 
1819
                      ('branch.conf', ''),
 
1820
                      ('tags', ''),
 
1821
                      ]
 
1822
        return self._initialize_helper(a_bzrdir, utf8_files)
 
1823
 
1697
1824
    def _branch_class(self):
1698
1825
        return BzrBranch7
1699
1826
 
1705
1832
        """See BranchFormat.get_format_description()."""
1706
1833
        return "Branch format 7"
1707
1834
 
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
 
1835
    supports_reference_locations = False
1727
1836
 
1728
1837
 
1729
1838
class BranchReferenceFormat(BranchFormat):
1836
1945
__format5 = BzrBranchFormat5()
1837
1946
__format6 = BzrBranchFormat6()
1838
1947
__format7 = BzrBranchFormat7()
 
1948
__format8 = BzrBranchFormat8()
1839
1949
BranchFormat.register_format(__format5)
1840
1950
BranchFormat.register_format(BranchReferenceFormat())
1841
1951
BranchFormat.register_format(__format6)
1842
1952
BranchFormat.register_format(__format7)
 
1953
BranchFormat.register_format(__format8)
1843
1954
BranchFormat.set_default_format(__format6)
1844
1955
_legacy_formats = [BzrBranchFormat4(),
1845
1956
    ]
1899
2010
        return self.control_files.is_locked()
1900
2011
 
1901
2012
    def lock_write(self, token=None):
1902
 
        repo_token = self.repository.lock_write()
 
2013
        # All-in-one needs to always unlock/lock.
 
2014
        repo_control = getattr(self.repository, 'control_files', None)
 
2015
        if self.control_files == repo_control or not self.is_locked():
 
2016
            self.repository.lock_write()
 
2017
            took_lock = True
 
2018
        else:
 
2019
            took_lock = False
1903
2020
        try:
1904
 
            token = self.control_files.lock_write(token=token)
 
2021
            return self.control_files.lock_write(token=token)
1905
2022
        except:
1906
 
            self.repository.unlock()
 
2023
            if took_lock:
 
2024
                self.repository.unlock()
1907
2025
            raise
1908
 
        return token
1909
2026
 
1910
2027
    def lock_read(self):
1911
 
        self.repository.lock_read()
 
2028
        # All-in-one needs to always unlock/lock.
 
2029
        repo_control = getattr(self.repository, 'control_files', None)
 
2030
        if self.control_files == repo_control or not self.is_locked():
 
2031
            self.repository.lock_read()
 
2032
            took_lock = True
 
2033
        else:
 
2034
            took_lock = False
1912
2035
        try:
1913
2036
            self.control_files.lock_read()
1914
2037
        except:
1915
 
            self.repository.unlock()
 
2038
            if took_lock:
 
2039
                self.repository.unlock()
1916
2040
            raise
1917
2041
 
1918
2042
    def unlock(self):
1919
 
        # TODO: test for failed two phase locks. This is known broken.
1920
2043
        try:
1921
2044
            self.control_files.unlock()
1922
2045
        finally:
1923
 
            self.repository.unlock()
1924
 
        if not self.control_files.is_locked():
1925
 
            # we just released the lock
1926
 
            self._clear_cached_state()
 
2046
            # All-in-one needs to always unlock/lock.
 
2047
            repo_control = getattr(self.repository, 'control_files', None)
 
2048
            if (self.control_files == repo_control or
 
2049
                not self.control_files.is_locked()):
 
2050
                self.repository.unlock()
 
2051
            if not self.control_files.is_locked():
 
2052
                # we just released the lock
 
2053
                self._clear_cached_state()
1927
2054
 
1928
2055
    def peek_lock_mode(self):
1929
2056
        if self.control_files._lock_count == 0:
2072
2199
        try:
2073
2200
            # We assume that during 'pull' the local repository is closer than
2074
2201
            # the remote one.
 
2202
            source.update_references(self)
2075
2203
            graph = self.repository.get_graph(source.repository)
2076
2204
            result.old_revno, result.old_revid = self.last_revision_info()
2077
2205
            self.update_revisions(source, stop_revision, overwrite=overwrite,
2174
2302
        result.source_branch = self
2175
2303
        result.target_branch = target
2176
2304
        result.old_revno, result.old_revid = target.last_revision_info()
 
2305
        self.update_references(target)
2177
2306
        if result.old_revid != self.last_revision():
2178
2307
            # We assume that during 'push' this repository is closer than
2179
2308
            # the target.
2194
2323
            'push_location', location,
2195
2324
            store=_mod_config.STORE_LOCATION_NORECURSE)
2196
2325
 
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
2326
    def _set_parent_location(self, url):
2216
2327
        if url is None:
2217
2328
            self._transport.delete('parent')
2347
2458
        return None
2348
2459
 
2349
2460
 
2350
 
class BzrBranch7(BzrBranch5):
2351
 
    """A branch with support for a fallback repository."""
 
2461
class BzrBranch8(BzrBranch5):
 
2462
    """A branch that stores tree-reference locations."""
2352
2463
 
2353
2464
    def _open_hook(self):
2354
2465
        if self._ignore_fallbacks:
2366
2477
                    raise AssertionError(
2367
2478
                        "'transform_fallback_location' hook %s returned "
2368
2479
                        "None, not a URL." % hook_name)
2369
 
            self._activate_fallback_location(url)
 
2480
            self._activate_fallback_location(url, None)
2370
2481
 
2371
2482
    def __init__(self, *args, **kwargs):
2372
2483
        self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2373
 
        super(BzrBranch7, self).__init__(*args, **kwargs)
 
2484
        super(BzrBranch8, self).__init__(*args, **kwargs)
2374
2485
        self._last_revision_info_cache = None
2375
2486
        self._partial_revision_history_cache = []
 
2487
        self._reference_info = None
2376
2488
 
2377
2489
    def _clear_cached_state(self):
2378
 
        super(BzrBranch7, self)._clear_cached_state()
 
2490
        super(BzrBranch8, self)._clear_cached_state()
2379
2491
        self._last_revision_info_cache = None
2380
2492
        self._partial_revision_history_cache = []
 
2493
        self._reference_info = None
2381
2494
 
2382
2495
    def _last_revision_info(self):
2383
2496
        revision_string = self._transport.get_bytes('last-revision')
2493
2606
        """Set the parent branch"""
2494
2607
        return self._get_config_location('parent_location')
2495
2608
 
 
2609
    @needs_write_lock
 
2610
    def _set_all_reference_info(self, info_dict):
 
2611
        """Replace all reference info stored in a branch.
 
2612
 
 
2613
        :param info_dict: A dict of {file_id: (tree_path, branch_location)}
 
2614
        """
 
2615
        s = StringIO()
 
2616
        writer = rio.RioWriter(s)
 
2617
        for key, (tree_path, branch_location) in info_dict.iteritems():
 
2618
            stanza = rio.Stanza(file_id=key, tree_path=tree_path,
 
2619
                                branch_location=branch_location)
 
2620
            writer.write_stanza(stanza)
 
2621
        self._transport.put_bytes('references', s.getvalue())
 
2622
        self._reference_info = info_dict
 
2623
 
 
2624
    @needs_read_lock
 
2625
    def _get_all_reference_info(self):
 
2626
        """Return all the reference info stored in a branch.
 
2627
 
 
2628
        :return: A dict of {file_id: (tree_path, branch_location)}
 
2629
        """
 
2630
        if self._reference_info is not None:
 
2631
            return self._reference_info
 
2632
        rio_file = self._transport.get('references')
 
2633
        try:
 
2634
            stanzas = rio.read_stanzas(rio_file)
 
2635
            info_dict = dict((s['file_id'], (s['tree_path'],
 
2636
                             s['branch_location'])) for s in stanzas)
 
2637
        finally:
 
2638
            rio_file.close()
 
2639
        self._reference_info = info_dict
 
2640
        return info_dict
 
2641
 
 
2642
    def set_reference_info(self, file_id, tree_path, branch_location):
 
2643
        """Set the branch location to use for a tree reference.
 
2644
 
 
2645
        :param file_id: The file-id of the tree reference.
 
2646
        :param tree_path: The path of the tree reference in the tree.
 
2647
        :param branch_location: The location of the branch to retrieve tree
 
2648
            references from.
 
2649
        """
 
2650
        info_dict = self._get_all_reference_info()
 
2651
        info_dict[file_id] = (tree_path, branch_location)
 
2652
        if None in (tree_path, branch_location):
 
2653
            if tree_path is not None:
 
2654
                raise ValueError('tree_path must be None when branch_location'
 
2655
                                 ' is None.')
 
2656
            if branch_location is not None:
 
2657
                raise ValueError('branch_location must be None when tree_path'
 
2658
                                 ' is None.')
 
2659
            del info_dict[file_id]
 
2660
        self._set_all_reference_info(info_dict)
 
2661
 
 
2662
    def get_reference_info(self, file_id):
 
2663
        """Get the tree_path and branch_location for a tree reference.
 
2664
 
 
2665
        :return: a tuple of (tree_path, branch_location)
 
2666
        """
 
2667
        return self._get_all_reference_info().get(file_id, (None, None))
 
2668
 
 
2669
    def reference_parent(self, file_id, path, possible_transports=None):
 
2670
        """Return the parent branch for a tree-reference file_id.
 
2671
 
 
2672
        :param file_id: The file_id of the tree reference
 
2673
        :param path: The path of the file_id in the tree
 
2674
        :return: A branch associated with the file_id
 
2675
        """
 
2676
        branch_location = self.get_reference_info(file_id)[1]
 
2677
        if branch_location is None:
 
2678
            return Branch.reference_parent(self, file_id, path,
 
2679
                                           possible_transports)
 
2680
        branch_location = urlutils.join(self.base, branch_location)
 
2681
        return Branch.open(branch_location,
 
2682
                           possible_transports=possible_transports)
 
2683
 
2496
2684
    def set_push_location(self, location):
2497
2685
        """See Branch.set_push_location."""
2498
2686
        self._set_config_location('push_location', location)
2596
2784
        return self.revno() - index
2597
2785
 
2598
2786
 
 
2787
class BzrBranch7(BzrBranch8):
 
2788
    """A branch with support for a fallback repository."""
 
2789
 
 
2790
    def set_reference_info(self, file_id, tree_path, branch_location):
 
2791
        Branch.set_reference_info(self, file_id, tree_path, branch_location)
 
2792
 
 
2793
    def get_reference_info(self, file_id):
 
2794
        Branch.get_reference_info(self, file_id)
 
2795
 
 
2796
    def reference_parent(self, file_id, path, possible_transports=None):
 
2797
        return Branch.reference_parent(self, file_id, path,
 
2798
                                       possible_transports)
 
2799
 
 
2800
 
2599
2801
class BzrBranch6(BzrBranch7):
2600
2802
    """See BzrBranchFormat6 for the capabilities of this branch.
2601
2803
 
2742
2944
        branch._transport.put_bytes('format', format.get_format_string())
2743
2945
 
2744
2946
 
 
2947
class Converter7to8(object):
 
2948
    """Perform an in-place upgrade of format 6 to format 7"""
 
2949
 
 
2950
    def convert(self, branch):
 
2951
        format = BzrBranchFormat8()
 
2952
        branch._transport.put_bytes('references', '')
 
2953
        # update target format
 
2954
        branch._transport.put_bytes('format', format.get_format_string())
 
2955
 
2745
2956
 
2746
2957
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2747
2958
    """Run ``callable(*args, **kwargs)``, write-locking target for the