~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Don't add a new verb; instead just teach the client to fallback if it gets a BadSearch error.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
from bzrlib.lazy_import import lazy_import
29
29
lazy_import(globals(), """
30
30
from bzrlib import (
 
31
    graph,
31
32
    tsort,
32
33
    versionedfile,
33
34
    )
93
94
        try:
94
95
            pb.update("Finding revisions", 0, 2)
95
96
            search = self._revids_to_fetch()
96
 
            if search is None:
 
97
            mutter('fetching: %s', search)
 
98
            if search.is_empty():
97
99
                return
98
100
            pb.update("Fetching revisions", 1, 2)
99
101
            self._fetch_everything_for_search(search)
126
128
            resume_tokens, missing_keys = self.sink.insert_stream(
127
129
                stream, from_format, [])
128
130
            if self.to_repository._fallback_repositories:
129
 
                missing_keys.update(
130
 
                    self._parent_inventories(search.get_keys()))
 
131
                if not isinstance(search, graph.EverythingResult):
 
132
                    # If search is EverythingResult this is be unnecessary,
 
133
                    # so we can skip this step.  The source will send us
 
134
                    # every revision it has, and their parent inventories.
 
135
                    # (Unless the source is damaged!  but not really worth
 
136
                    # optimising for that case.  The pack code will reject bad
 
137
                    # streams anyway.)
 
138
                    missing_keys.update(
 
139
                        self._parent_inventories(search.get_keys()))
131
140
            if missing_keys:
132
141
                pb.update("Missing keys")
133
142
                stream = source.get_stream_for_missing_keys(missing_keys)
151
160
        """Determines the exact revisions needed from self.from_repository to
152
161
        install self._last_revision in self.to_repository.
153
162
 
154
 
        If no revisions need to be fetched, then this just returns None.
 
163
        :returns: A SearchResult of some sort.  (Possibly a
 
164
        PendingAncestryResult, EmptySearchResult, etc.)
155
165
        """
156
 
        if self._fetch_spec is not None:
 
166
        mutter("self._fetch_spec, self._last_revision: %r, %r",
 
167
                self._fetch_spec, self._last_revision)
 
168
        get_search = getattr(self._fetch_spec, 'get_search', None)
 
169
        if get_search is not None:
 
170
            # This is EverythingNotInOther or a similar kind of fetch_spec.
 
171
            # Turn it into a search result.
 
172
            return get_search()
 
173
        elif self._fetch_spec is not None:
 
174
            # The fetch spec is already a concrete search result.
157
175
            return self._fetch_spec
158
 
        mutter('fetch up to rev {%s}', self._last_revision)
159
 
        if self._last_revision is NULL_REVISION:
 
176
        elif self._last_revision == NULL_REVISION:
 
177
            # fetch_spec is None + last_revision is null => empty fetch.
160
178
            # explicit limit of no revisions needed
161
 
            return None
162
 
        return self.to_repository.search_missing_revision_ids(
163
 
            self.from_repository, self._last_revision,
164
 
            find_ghosts=self.find_ghosts)
 
179
            return graph.EmptySearchResult()
 
180
        elif self._last_revision is not None:
 
181
            return graph.NotInOtherForRevs(self.to_repository,
 
182
                self.from_repository, [self._last_revision],
 
183
                find_ghosts=self.find_ghosts).get_search()
 
184
        else: # self._last_revision is None:
 
185
            return graph.EverythingNotInOther(self.to_repository,
 
186
                self.from_repository, find_ghosts=self.find_ghosts).get_search()
165
187
 
166
188
    def _parent_inventories(self, revision_ids):
167
189
        # Find all the parent revisions referenced by the stream, but
182
204
    This is for use by fetchers and converters.
183
205
    """
184
206
 
 
207
    # This is a class variable so that the test suite can override it.
 
208
    known_graph_threshold = 100
 
209
 
185
210
    def __init__(self, source):
186
211
        """Constructor.
187
212
 
243
268
        # yet, and are unlikely to in non-rich-root environments anyway.
244
269
        root_id_order.sort(key=operator.itemgetter(0))
245
270
        # Create a record stream containing the roots to create.
246
 
        if len(revs) > 100:
247
 
            # XXX: not covered by tests, should have a flag to always run
248
 
            # this. -- mbp 20100129
249
 
            graph = self.source_repo.get_known_graph_ancestry(revs)
 
271
        if len(revs) > self.known_graph_threshold:
 
272
            graph = self.source.get_known_graph_ancestry(revs)
250
273
        new_roots_stream = _new_root_data_stream(
251
274
            root_id_order, rev_id_to_root_id, parent_map, self.source, graph)
252
275
        return [('texts', new_roots_stream)]
253
276
 
254
277
 
255
 
def _get_rich_root_heads_graph(source_repo, revision_ids):
256
 
    """Get a Graph object suitable for asking heads() for new rich roots."""
257
 
    return 
258
 
 
259
 
 
260
278
def _new_root_data_stream(
261
279
    root_keys_to_create, rev_id_to_root_id_map, parent_map, repo, graph=None):
262
280
    """Generate a texts substream of synthesised root entries.