~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

(vila) '\n' cannot be part of a valid config option reference. (Vincent
 Ladeuil)

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
import bz2
 
18
import zlib
18
19
 
19
20
from bzrlib import (
20
21
    bencode,
28
29
    graph,
29
30
    lock,
30
31
    lockdir,
 
32
    osutils,
31
33
    registry,
32
34
    repository as _mod_repository,
33
35
    revision as _mod_revision,
36
38
    testament as _mod_testament,
37
39
    urlutils,
38
40
    vf_repository,
 
41
    vf_search,
39
42
    )
40
43
from bzrlib.branch import BranchReferenceFormat, BranchWriteLockResult
41
44
from bzrlib.decorators import needs_read_lock, needs_write_lock, only_raises
51
54
from bzrlib.revision import NULL_REVISION
52
55
from bzrlib.revisiontree import InventoryRevisionTree
53
56
from bzrlib.repository import RepositoryWriteLockResult, _LazyListJoin
 
57
from bzrlib.serializer import format_registry as serializer_format_registry
54
58
from bzrlib.trace import mutter, note, warning, log_exception_quietly
55
59
 
56
60
 
119
123
 
120
124
    def get_format_description(self):
121
125
        if self._network_name:
122
 
            real_format = controldir.network_format_registry.get(self._network_name)
123
 
            return 'Remote: ' + real_format.get_format_description()
 
126
            try:
 
127
                real_format = controldir.network_format_registry.get(
 
128
                        self._network_name)
 
129
            except KeyError:
 
130
                pass
 
131
            else:
 
132
                return 'Remote: ' + real_format.get_format_description()
124
133
        return 'bzr remote bzrdir'
125
134
 
126
135
    def get_format_string(self):
516
525
        if len(branch_info) != 2:
517
526
            raise errors.UnexpectedSmartServerResponse(response)
518
527
        branch_ref, branch_name = branch_info
519
 
        format = controldir.network_format_registry.get(control_name)
 
528
        try:
 
529
            format = controldir.network_format_registry.get(control_name)
 
530
        except KeyError:
 
531
            raise errors.UnknownFormatError(kind='control', format=control_name)
 
532
 
520
533
        if repo_name:
521
 
            format.repository_format = _mod_repository.network_format_registry.get(
522
 
                repo_name)
 
534
            try:
 
535
                format.repository_format = _mod_repository.network_format_registry.get(
 
536
                    repo_name)
 
537
            except KeyError:
 
538
                raise errors.UnknownFormatError(kind='repository',
 
539
                    format=repo_name)
523
540
        if branch_ref == 'ref':
524
541
            # XXX: we need possible_transports here to avoid reopening the
525
542
            # connection to the referenced location
528
545
            format.set_branch_format(branch_format)
529
546
        elif branch_ref == 'branch':
530
547
            if branch_name:
531
 
                format.set_branch_format(
532
 
                    branch.network_format_registry.get(branch_name))
 
548
                try:
 
549
                    branch_format = branch.network_format_registry.get(
 
550
                        branch_name)
 
551
                except KeyError:
 
552
                    raise errors.UnknownFormatError(kind='branch',
 
553
                        format=branch_name)
 
554
                format.set_branch_format(branch_format)
533
555
        else:
534
556
            raise errors.UnexpectedSmartServerResponse(response)
535
557
        return format
655
677
        return None, self.open_branch(name=name)
656
678
 
657
679
    def open_branch(self, name=None, unsupported=False,
658
 
                    ignore_fallbacks=False):
 
680
                    ignore_fallbacks=False, possible_transports=None):
659
681
        if unsupported:
660
682
            raise NotImplementedError('unsupported flag support not implemented yet.')
661
683
        if self._next_open_branch_result is not None:
668
690
            # a branch reference, use the existing BranchReference logic.
669
691
            format = BranchReferenceFormat()
670
692
            return format.open(self, name=name, _found=True,
671
 
                location=response[1], ignore_fallbacks=ignore_fallbacks)
 
693
                location=response[1], ignore_fallbacks=ignore_fallbacks,
 
694
                possible_transports=possible_transports)
672
695
        branch_format_name = response[1]
673
696
        if not branch_format_name:
674
697
            branch_format_name = None
675
698
        format = RemoteBranchFormat(network_name=branch_format_name)
676
699
        return RemoteBranch(self, self.find_repository(), format=format,
677
 
            setup_stacking=not ignore_fallbacks, name=name)
 
700
            setup_stacking=not ignore_fallbacks, name=name,
 
701
            possible_transports=possible_transports)
678
702
 
679
703
    def _open_repo_v1(self, path):
680
704
        verb = 'BzrDir.find_repository'
965
989
 
966
990
    def _ensure_real(self):
967
991
        if self._custom_format is None:
968
 
            self._custom_format = _mod_repository.network_format_registry.get(
969
 
                self._network_name)
 
992
            try:
 
993
                self._custom_format = _mod_repository.network_format_registry.get(
 
994
                    self._network_name)
 
995
            except KeyError:
 
996
                raise errors.UnknownFormatError(kind='repository',
 
997
                    format=self._network_name)
970
998
 
971
999
    @property
972
1000
    def _fetch_order(self):
1758
1786
 
1759
1787
    @needs_read_lock
1760
1788
    def get_inventory(self, revision_id):
1761
 
        self._ensure_real()
1762
 
        return self._real_repository.get_inventory(revision_id)
 
1789
        return list(self.iter_inventories([revision_id]))[0]
1763
1790
 
1764
1791
    def iter_inventories(self, revision_ids, ordering=None):
1765
1792
        self._ensure_real()
1815
1842
        included_keys = result_set.intersection(result_parents)
1816
1843
        start_keys = result_set.difference(included_keys)
1817
1844
        exclude_keys = result_parents.difference(result_set)
1818
 
        result = graph.SearchResult(start_keys, exclude_keys,
 
1845
        result = vf_search.SearchResult(start_keys, exclude_keys,
1819
1846
            len(result_set), result_set)
1820
1847
        return result
1821
1848
 
1869
1896
        # the InterRepository base class, which raises an
1870
1897
        # IncompatibleRepositories when asked to fetch.
1871
1898
        inter = _mod_repository.InterRepository.get(source, self)
 
1899
        if (fetch_spec is not None and
 
1900
            not getattr(inter, "supports_fetch_spec", False)):
 
1901
            raise errors.UnsupportedOperation(
 
1902
                "fetch_spec not supported for %r" % inter)
1872
1903
        return inter.fetch(revision_id=revision_id,
1873
1904
            find_ghosts=find_ghosts, fetch_spec=fetch_spec)
1874
1905
 
1892
1923
        return self._real_repository._get_versioned_file_checker(
1893
1924
            revisions, revision_versions_cache)
1894
1925
 
 
1926
    def _iter_files_bytes_rpc(self, desired_files, absent):
 
1927
        path = self.bzrdir._path_for_remote_call(self._client)
 
1928
        lines = []
 
1929
        identifiers = []
 
1930
        for (file_id, revid, identifier) in desired_files:
 
1931
            lines.append("%s\0%s" % (
 
1932
                osutils.safe_file_id(file_id),
 
1933
                osutils.safe_revision_id(revid)))
 
1934
            identifiers.append(identifier)
 
1935
        (response_tuple, response_handler) = (
 
1936
            self._call_with_body_bytes_expecting_body(
 
1937
            "Repository.iter_files_bytes", (path, ), "\n".join(lines)))
 
1938
        if response_tuple != ('ok', ):
 
1939
            response_handler.cancel_read_body()
 
1940
            raise errors.UnexpectedSmartServerResponse(response_tuple)
 
1941
        byte_stream = response_handler.read_streamed_body()
 
1942
        def decompress_stream(start, byte_stream, unused):
 
1943
            decompressor = zlib.decompressobj()
 
1944
            yield decompressor.decompress(start)
 
1945
            while decompressor.unused_data == "":
 
1946
                try:
 
1947
                    data = byte_stream.next()
 
1948
                except StopIteration:
 
1949
                    break
 
1950
                yield decompressor.decompress(data)
 
1951
            yield decompressor.flush()
 
1952
            unused.append(decompressor.unused_data)
 
1953
        unused = ""
 
1954
        while True:
 
1955
            while not "\n" in unused:
 
1956
                unused += byte_stream.next()
 
1957
            header, rest = unused.split("\n", 1)
 
1958
            args = header.split("\0")
 
1959
            if args[0] == "absent":
 
1960
                absent[identifiers[int(args[3])]] = (args[1], args[2])
 
1961
                unused = rest
 
1962
                continue
 
1963
            elif args[0] == "ok":
 
1964
                idx = int(args[1])
 
1965
            else:
 
1966
                raise errors.UnexpectedSmartServerResponse(args)
 
1967
            unused_chunks = []
 
1968
            yield (identifiers[idx],
 
1969
                decompress_stream(rest, byte_stream, unused_chunks))
 
1970
            unused = "".join(unused_chunks)
 
1971
 
1895
1972
    def iter_files_bytes(self, desired_files):
1896
1973
        """See Repository.iter_file_bytes.
1897
1974
        """
1898
 
        self._ensure_real()
1899
 
        return self._real_repository.iter_files_bytes(desired_files)
 
1975
        try:
 
1976
            absent = {}
 
1977
            for (identifier, bytes_iterator) in self._iter_files_bytes_rpc(
 
1978
                    desired_files, absent):
 
1979
                yield identifier, bytes_iterator
 
1980
            for fallback in self._fallback_repositories:
 
1981
                if not absent:
 
1982
                    break
 
1983
                desired_files = [(key[0], key[1], identifier) for
 
1984
                    (identifier, key) in absent.iteritems()]
 
1985
                for (identifier, bytes_iterator) in fallback.iter_files_bytes(desired_files):
 
1986
                    del absent[identifier]
 
1987
                    yield identifier, bytes_iterator
 
1988
            if absent:
 
1989
                # There may be more missing items, but raise an exception
 
1990
                # for just one.
 
1991
                missing_identifier = absent.keys()[0]
 
1992
                missing_key = absent[missing_identifier]
 
1993
                raise errors.RevisionNotPresent(revision_id=missing_key[1],
 
1994
                    file_id=missing_key[0])
 
1995
        except errors.UnknownSmartMethod:
 
1996
            self._ensure_real()
 
1997
            for (identifier, bytes_iterator) in (
 
1998
                self._real_repository.iter_files_bytes(desired_files)):
 
1999
                yield identifier, bytes_iterator
1900
2000
 
1901
2001
    def get_cached_parent_map(self, revision_ids):
1902
2002
        """See bzrlib.CachingParentsProvider.get_cached_parent_map"""
1967
2067
            parents_map = {}
1968
2068
        if _DEFAULT_SEARCH_DEPTH <= 0:
1969
2069
            (start_set, stop_keys,
1970
 
             key_count) = graph.search_result_from_parent_map(
 
2070
             key_count) = vf_search.search_result_from_parent_map(
1971
2071
                parents_map, self._unstacked_provider.missing_keys)
1972
2072
        else:
1973
2073
            (start_set, stop_keys,
1974
 
             key_count) = graph.limited_search_result_from_parent_map(
 
2074
             key_count) = vf_search.limited_search_result_from_parent_map(
1975
2075
                parents_map, self._unstacked_provider.missing_keys,
1976
2076
                keys, depth=_DEFAULT_SEARCH_DEPTH)
1977
2077
        recipe = ('manual', start_set, stop_keys, key_count)
2028
2128
 
2029
2129
    @needs_read_lock
2030
2130
    def get_signature_text(self, revision_id):
2031
 
        self._ensure_real()
2032
 
        return self._real_repository.get_signature_text(revision_id)
 
2131
        path = self.bzrdir._path_for_remote_call(self._client)
 
2132
        try:
 
2133
            response_tuple, response_handler = self._call_expecting_body(
 
2134
                'Repository.get_revision_signature_text', path, revision_id)
 
2135
        except errors.UnknownSmartMethod:
 
2136
            self._ensure_real()
 
2137
            return self._real_repository.get_signature_text(revision_id)
 
2138
        except errors.NoSuchRevision, err:
 
2139
            for fallback in self._fallback_repositories:
 
2140
                try:
 
2141
                    return fallback.get_signature_text(revision_id)
 
2142
                except errors.NoSuchRevision:
 
2143
                    pass
 
2144
            raise err
 
2145
        else:
 
2146
            if response_tuple[0] != 'ok':
 
2147
                raise errors.UnexpectedSmartServerResponse(response_tuple)
 
2148
            return response_handler.read_body_bytes()
2033
2149
 
2034
2150
    @needs_read_lock
2035
2151
    def _get_inventory_xml(self, revision_id):
2069
2185
 
2070
2186
    @needs_read_lock
2071
2187
    def revision_trees(self, revision_ids):
2072
 
        self._ensure_real()
2073
 
        return self._real_repository.revision_trees(revision_ids)
 
2188
        inventories = self.iter_inventories(revision_ids)
 
2189
        for inv in inventories:
 
2190
            yield InventoryRevisionTree(self, inv, inv.revision_id)
2074
2191
 
2075
2192
    @needs_read_lock
2076
2193
    def get_revision_reconcile(self, revision_id):
2095
2212
    def _copy_repository_tarball(self, to_bzrdir, revision_id=None):
2096
2213
        # get a tarball of the remote repository, and copy from that into the
2097
2214
        # destination
2098
 
        from bzrlib import osutils
2099
2215
        import tarfile
2100
2216
        # TODO: Maybe a progress bar while streaming the tarball?
2101
2217
        note(gettext("Copying repository content as tarball..."))
2133
2249
    @needs_write_lock
2134
2250
    def pack(self, hint=None, clean_obsolete_packs=False):
2135
2251
        """Compress the data within the repository.
2136
 
 
2137
 
        This is not currently implemented within the smart server.
2138
2252
        """
2139
 
        self._ensure_real()
2140
 
        return self._real_repository.pack(hint=hint, clean_obsolete_packs=clean_obsolete_packs)
 
2253
        if hint is None:
 
2254
            body = ""
 
2255
        else:
 
2256
            body = "".join([l+"\n" for l in hint])
 
2257
        path = self.bzrdir._path_for_remote_call(self._client)
 
2258
        try:
 
2259
            response, handler = self._call_with_body_bytes_expecting_body(
 
2260
                'Repository.pack', (path, self._lock_token,
 
2261
                    str(clean_obsolete_packs)), body)
 
2262
        except errors.UnknownSmartMethod:
 
2263
            self._ensure_real()
 
2264
            return self._real_repository.pack(hint=hint,
 
2265
                clean_obsolete_packs=clean_obsolete_packs)
 
2266
        handler.cancel_read_body()
 
2267
        if response != ('ok', ):
 
2268
            raise errors.UnexpectedSmartServerResponse(response)
2141
2269
 
2142
2270
    @property
2143
2271
    def revisions(self):
2144
2272
        """Decorate the real repository for now.
2145
2273
 
2146
 
        In the short term this should become a real object to intercept graph
2147
 
        lookups.
2148
 
 
2149
2274
        In the long term a full blown network facility is needed.
2150
2275
        """
2151
2276
        self._ensure_real()
2193
2318
        self._ensure_real()
2194
2319
        return self._real_repository.texts
2195
2320
 
 
2321
    def _iter_revisions_rpc(self, revision_ids):
 
2322
        body = "\n".join(revision_ids)
 
2323
        path = self.bzrdir._path_for_remote_call(self._client)
 
2324
        response_tuple, response_handler = (
 
2325
            self._call_with_body_bytes_expecting_body(
 
2326
            "Repository.iter_revisions", (path, ), body))
 
2327
        if response_tuple[0] != "ok":
 
2328
            raise errors.UnexpectedSmartServerResponse(response_tuple)
 
2329
        serializer_format = response_tuple[1]
 
2330
        serializer = serializer_format_registry.get(serializer_format)
 
2331
        byte_stream = response_handler.read_streamed_body()
 
2332
        decompressor = zlib.decompressobj()
 
2333
        chunks = []
 
2334
        for bytes in byte_stream:
 
2335
            chunks.append(decompressor.decompress(bytes))
 
2336
            if decompressor.unused_data != "":
 
2337
                chunks.append(decompressor.flush())
 
2338
                yield serializer.read_revision_from_string("".join(chunks))
 
2339
                unused = decompressor.unused_data
 
2340
                decompressor = zlib.decompressobj()
 
2341
                chunks = [decompressor.decompress(unused)]
 
2342
        chunks.append(decompressor.flush())
 
2343
        text = "".join(chunks)
 
2344
        if text != "":
 
2345
            yield serializer.read_revision_from_string("".join(chunks))
 
2346
 
2196
2347
    @needs_read_lock
2197
2348
    def get_revisions(self, revision_ids):
2198
 
        self._ensure_real()
2199
 
        return self._real_repository.get_revisions(revision_ids)
 
2349
        if revision_ids is None:
 
2350
            revision_ids = self.all_revision_ids()
 
2351
        else:
 
2352
            for rev_id in revision_ids:
 
2353
                if not rev_id or not isinstance(rev_id, basestring):
 
2354
                    raise errors.InvalidRevisionId(
 
2355
                        revision_id=rev_id, branch=self)
 
2356
        try:
 
2357
            missing = set(revision_ids)
 
2358
            revs = {}
 
2359
            for rev in self._iter_revisions_rpc(revision_ids):
 
2360
                missing.remove(rev.revision_id)
 
2361
                revs[rev.revision_id] = rev
 
2362
        except errors.UnknownSmartMethod:
 
2363
            self._ensure_real()
 
2364
            return self._real_repository.get_revisions(revision_ids)
 
2365
        for fallback in self._fallback_repositories:
 
2366
            if not missing:
 
2367
                break
 
2368
            for revid in list(missing):
 
2369
                # XXX JRV 2011-11-20: It would be nice if there was a
 
2370
                # public method on Repository that could be used to query
 
2371
                # for revision objects *without* failing completely if one
 
2372
                # was missing. There is VersionedFileRepository._iter_revisions,
 
2373
                # but unfortunately that's private and not provided by
 
2374
                # all repository implementations.
 
2375
                try:
 
2376
                    revs[revid] = fallback.get_revision(revid)
 
2377
                except errors.NoSuchRevision:
 
2378
                    pass
 
2379
                else:
 
2380
                    missing.remove(revid)
 
2381
        if missing:
 
2382
            raise errors.NoSuchRevision(self, list(missing)[0])
 
2383
        return [revs[revid] for revid in revision_ids]
2200
2384
 
2201
2385
    def supports_rich_root(self):
2202
2386
        return self._format.rich_root_data
2223
2407
            return self._real_repository.add_signature_text(
2224
2408
                revision_id, signature)
2225
2409
        path = self.bzrdir._path_for_remote_call(self._client)
2226
 
        response, response_handler = self._call_with_body_bytes(
2227
 
            'Repository.add_signature_text', (path, revision_id),
2228
 
            signature)
 
2410
        response, handler = self._call_with_body_bytes_expecting_body(
 
2411
            'Repository.add_signature_text', (path, self._lock_token,
 
2412
                revision_id) + tuple(self._write_group_tokens), signature)
 
2413
        handler.cancel_read_body()
2229
2414
        self.refresh_data()
2230
2415
        if response[0] != 'ok':
2231
2416
            raise errors.UnexpectedSmartServerResponse(response)
 
2417
        self._write_group_tokens = response[1:]
2232
2418
 
2233
2419
    def has_signature_for_revision_id(self, revision_id):
2234
2420
        path = self.bzrdir._path_for_remote_call(self._client)
2241
2427
                revision_id)
2242
2428
        if response[0] not in ('yes', 'no'):
2243
2429
            raise SmartProtocolError('unexpected response code %s' % (response,))
2244
 
        return (response[0] == 'yes')
 
2430
        if response[0] == 'yes':
 
2431
            return True
 
2432
        for fallback in self._fallback_repositories:
 
2433
            if fallback.has_signature_for_revision_id(revision_id):
 
2434
                return True
 
2435
        return False
2245
2436
 
2246
2437
    @needs_read_lock
2247
2438
    def verify_revision_signature(self, revision_id, gpg_strategy):
2448
2639
 
2449
2640
    def _real_stream(self, repo, search):
2450
2641
        """Get a stream for search from repo.
2451
 
        
2452
 
        This never called RemoteStreamSource.get_stream, and is a heler
2453
 
        for RemoteStreamSource._get_stream to allow getting a stream 
 
2642
 
 
2643
        This never called RemoteStreamSource.get_stream, and is a helper
 
2644
        for RemoteStreamSource._get_stream to allow getting a stream
2454
2645
        reliably whether fallback back because of old servers or trying
2455
2646
        to stream from a non-RemoteRepository (which the stacked support
2456
2647
        code will do).
2498
2689
            except errors.UnknownSmartMethod:
2499
2690
                medium._remember_remote_is_before(version)
2500
2691
            except errors.UnknownErrorFromSmartServer, e:
2501
 
                if isinstance(search, graph.EverythingResult):
 
2692
                if isinstance(search, vf_search.EverythingResult):
2502
2693
                    error_verb = e.error_from_smart_server.error_verb
2503
2694
                    if error_verb == 'BadSearch':
2504
2695
                        # Pre-2.4 servers don't support this sort of search.
2596
2787
 
2597
2788
    def _ensure_real(self):
2598
2789
        if self._custom_format is None:
2599
 
            self._custom_format = branch.network_format_registry.get(
2600
 
                self._network_name)
 
2790
            try:
 
2791
                self._custom_format = branch.network_format_registry.get(
 
2792
                    self._network_name)
 
2793
            except KeyError:
 
2794
                raise errors.UnknownFormatError(kind='branch',
 
2795
                    format=self._network_name)
2601
2796
 
2602
2797
    def get_format_description(self):
2603
2798
        self._ensure_real()
2797
2992
    """
2798
2993
 
2799
2994
    def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
2800
 
        _client=None, format=None, setup_stacking=True, name=None):
 
2995
        _client=None, format=None, setup_stacking=True, name=None,
 
2996
        possible_transports=None):
2801
2997
        """Create a RemoteBranch instance.
2802
2998
 
2803
2999
        :param real_branch: An optional local implementation of the branch
2868
3064
            hook(self)
2869
3065
        self._is_stacked = False
2870
3066
        if setup_stacking:
2871
 
            self._setup_stacking()
 
3067
            self._setup_stacking(possible_transports)
2872
3068
 
2873
 
    def _setup_stacking(self):
 
3069
    def _setup_stacking(self, possible_transports):
2874
3070
        # configure stacking into the remote repository, by reading it from
2875
3071
        # the vfs branch.
2876
3072
        try:
2879
3075
            errors.UnstackableRepositoryFormat), e:
2880
3076
            return
2881
3077
        self._is_stacked = True
2882
 
        self._activate_fallback_location(fallback_url)
 
3078
        if possible_transports is None:
 
3079
            possible_transports = []
 
3080
        else:
 
3081
            possible_transports = list(possible_transports)
 
3082
        possible_transports.append(self.bzrdir.root_transport)
 
3083
        self._activate_fallback_location(fallback_url,
 
3084
            possible_transports=possible_transports)
2883
3085
 
2884
3086
    def _get_config(self):
2885
3087
        return RemoteBranchConfig(self)
3621
3823
        return self._bzrdir._real_bzrdir
3622
3824
 
3623
3825
 
3624
 
 
3625
3826
def _extract_tar(tar, to_dir):
3626
3827
    """Extract all the contents of a tarfile object.
3627
3828
 
3727
3928
    lambda err, find, get_path: errors.ReadError(get_path()))
3728
3929
error_translators.register('NoSuchFile',
3729
3930
    lambda err, find, get_path: errors.NoSuchFile(get_path()))
 
3931
error_translators.register('UnsuspendableWriteGroup',
 
3932
    lambda err, find, get_path: errors.UnsuspendableWriteGroup(
 
3933
        repository=find('repository')))
 
3934
error_translators.register('UnresumableWriteGroup',
 
3935
    lambda err, find, get_path: errors.UnresumableWriteGroup(
 
3936
        repository=find('repository'), write_groups=err.error_args[0],
 
3937
        reason=err.error_args[1]))
3730
3938
no_context_error_translators.register('IncompatibleRepositories',
3731
3939
    lambda err: errors.IncompatibleRepositories(
3732
3940
        err.error_args[0], err.error_args[1], err.error_args[2]))
3777
3985
no_context_error_translators.register('MemoryError',
3778
3986
    lambda err: errors.BzrError("remote server out of memory\n"
3779
3987
        "Retry non-remotely, or contact the server admin for details."))
 
3988
no_context_error_translators.register('RevisionNotPresent',
 
3989
    lambda err: errors.RevisionNotPresent(err.error_args[0], err.error_args[1]))
3780
3990
 
3781
3991
no_context_error_translators.register('BzrCheckError',
3782
3992
    lambda err: errors.BzrCheckError(msg=err.error_args[0]))
3783
3993
 
3784
 
error_translators.register('UnsuspendableWriteGroup',
3785
 
    lambda err, find, get_path: errors.UnsuspendableWriteGroup(
3786
 
        repository=find('repository')))
3787
 
error_translators.register('UnresumableWriteGroup',
3788
 
    lambda err, find, get_path: errors.UnresumableWriteGroup(
3789
 
        repository=find('repository'), write_groups=err.error_args[0],
3790
 
        reason=err.error_args[1]))