/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to brzlib/fetch.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
branch.
23
23
"""
24
24
 
 
25
from __future__ import absolute_import
 
26
 
25
27
import operator
26
28
 
27
 
from ..lazy_import import lazy_import
 
29
from brzlib.lazy_import import lazy_import
28
30
lazy_import(globals(), """
29
 
from breezy import (
 
31
from brzlib import (
30
32
    tsort,
31
 
    )
32
 
from breezy.bzr import (
33
33
    versionedfile,
34
34
    vf_search,
35
35
    )
36
36
""")
37
 
from .. import (
 
37
from brzlib import (
38
38
    errors,
39
39
    ui,
40
40
    )
41
 
from ..i18n import gettext
42
 
from ..revision import NULL_REVISION
43
 
from ..trace import mutter
 
41
from brzlib.i18n import gettext
 
42
from brzlib.revision import NULL_REVISION
 
43
from brzlib.trace import mutter
44
44
 
45
45
 
46
46
class RepoFetcher(object):
51
51
    """
52
52
 
53
53
    def __init__(self, to_repository, from_repository, last_revision=None,
54
 
                 find_ghosts=True, fetch_spec=None):
 
54
        find_ghosts=True, fetch_spec=None):
55
55
        """Create a repo fetcher.
56
56
 
57
57
        :param last_revision: If set, try to limit to the data this revision
69
69
        self._last_revision = last_revision
70
70
        self._fetch_spec = fetch_spec
71
71
        self.find_ghosts = find_ghosts
72
 
        with self.from_repository.lock_read():
73
 
            mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
74
 
                   str(self.from_repository), str(self.from_repository._format),
75
 
                   str(self.to_repository), str(self.to_repository._format))
 
72
        self.from_repository.lock_read()
 
73
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
 
74
               self.from_repository, self.from_repository._format,
 
75
               self.to_repository, self.to_repository._format)
 
76
        try:
76
77
            self.__fetch()
 
78
        finally:
 
79
            self.from_repository.unlock()
77
80
 
78
81
    def __fetch(self):
79
82
        """Primary worker function.
89
92
        # assert not missing
90
93
        self.count_total = 0
91
94
        self.file_ids_names = {}
92
 
        with ui.ui_factory.nested_progress_bar() as pb:
93
 
            pb.show_pct = pb.show_count = False
 
95
        pb = ui.ui_factory.nested_progress_bar()
 
96
        pb.show_pct = pb.show_count = False
 
97
        try:
94
98
            pb.update(gettext("Finding revisions"), 0, 2)
95
99
            search_result = self._revids_to_fetch()
96
 
            mutter('fetching: %s', str(search_result))
 
100
            mutter('fetching: %s', search_result)
97
101
            if search_result.is_empty():
98
102
                return
99
103
            pb.update(gettext("Fetching revisions"), 1, 2)
100
104
            self._fetch_everything_for_search(search_result)
 
105
        finally:
 
106
            pb.finished()
101
107
 
102
108
    def _fetch_everything_for_search(self, search):
103
109
        """Fetch all data for the given set of revisions."""
110
116
        # moment, so that it can feed the progress information back to this
111
117
        # function?
112
118
        if (self.from_repository._format.rich_root_data and
113
 
                not self.to_repository._format.rich_root_data):
 
119
            not self.to_repository._format.rich_root_data):
114
120
            raise errors.IncompatibleRepositories(
115
121
                self.from_repository, self.to_repository,
116
122
                "different rich-root support")
117
 
        with ui.ui_factory.nested_progress_bar() as pb:
 
123
        pb = ui.ui_factory.nested_progress_bar()
 
124
        try:
118
125
            pb.update("Get stream source")
119
126
            source = self.from_repository._get_source(
120
127
                self.to_repository._format)
139
146
                        resume_tokens,))
140
147
            pb.update("Finishing stream")
141
148
            self.sink.finished()
 
149
        finally:
 
150
            pb.finished()
142
151
 
143
152
    def _revids_to_fetch(self):
144
153
        """Determines the exact revisions needed from self.from_repository to
156
165
            return vf_search.EmptySearchResult()
157
166
        elif self._last_revision is not None:
158
167
            return vf_search.NotInOtherForRevs(self.to_repository,
159
 
                                               self.from_repository, [
160
 
                                                   self._last_revision],
161
 
                                               find_ghosts=self.find_ghosts).execute()
162
 
        else:  # self._last_revision is None:
 
168
                self.from_repository, [self._last_revision],
 
169
                find_ghosts=self.find_ghosts).execute()
 
170
        else: # self._last_revision is None:
163
171
            return vf_search.EverythingNotInOther(self.to_repository,
164
 
                                                  self.from_repository,
165
 
                                                  find_ghosts=self.find_ghosts).execute()
 
172
                self.from_repository,
 
173
                find_ghosts=self.find_ghosts).execute()
166
174
 
167
175
 
168
176
class Inter1and2Helper(object):
203
211
    def _find_root_ids(self, revs, parent_map, graph):
204
212
        revision_root = {}
205
213
        for tree in self.iter_rev_trees(revs):
206
 
            root_id = tree.path2id('')
207
 
            revision_id = tree.get_file_revision(u'')
 
214
            root_id = tree.get_root_id()
 
215
            revision_id = tree.get_file_revision(root_id, u"")
208
216
            revision_root[revision_id] = root_id
209
217
        # Find out which parents we don't already know root ids for
210
 
        parents = set(parent_map.values())
211
 
        parents.difference_update(revision_root)
212
 
        parents.discard(NULL_REVISION)
 
218
        parents = set()
 
219
        for revision_parents in parent_map.itervalues():
 
220
            parents.update(revision_parents)
 
221
        parents.difference_update(revision_root.keys() + [NULL_REVISION])
213
222
        # Limit to revisions present in the versionedfile
214
 
        parents = graph.get_parent_map(parents)
 
223
        parents = graph.get_parent_map(parents).keys()
215
224
        for tree in self.iter_rev_trees(parents):
216
 
            root_id = tree.path2id('')
 
225
            root_id = tree.get_root_id()
217
226
            revision_root[tree.get_revision_id()] = root_id
218
227
        return revision_root
219
228
 
227
236
        rev_order = tsort.topo_sort(parent_map)
228
237
        rev_id_to_root_id = self._find_root_ids(revs, parent_map, graph)
229
238
        root_id_order = [(rev_id_to_root_id[rev_id], rev_id) for rev_id in
230
 
                         rev_order]
 
239
            rev_order]
231
240
        # Guaranteed stable, this groups all the file id operations together
232
241
        # retaining topological order within the revisions of a file id.
233
242
        # File id splits and joins would invalidate this, but they don't exist
242
251
 
243
252
 
244
253
def _new_root_data_stream(
245
 
        root_keys_to_create, rev_id_to_root_id_map, parent_map, repo, graph=None):
 
254
    root_keys_to_create, rev_id_to_root_id_map, parent_map, repo, graph=None):
246
255
    """Generate a texts substream of synthesised root entries.
247
256
 
248
257
    Used in fetches that do rich-root upgrades.
249
 
 
 
258
    
250
259
    :param root_keys_to_create: iterable of (root_id, rev_id) pairs describing
251
260
        the root entries to create.
252
261
    :param rev_id_to_root_id_map: dict of known rev_id -> root_id mappings for
260
269
        root_id, rev_id = root_key
261
270
        parent_keys = _parent_keys_for_root_version(
262
271
            root_id, rev_id, rev_id_to_root_id_map, parent_map, repo, graph)
263
 
        yield versionedfile.ChunkedContentFactory(
264
 
            root_key, parent_keys, None, [])
 
272
        yield versionedfile.FulltextContentFactory(
 
273
            root_key, parent_keys, None, '')
265
274
 
266
275
 
267
276
def _parent_keys_for_root_version(
268
 
        root_id, rev_id, rev_id_to_root_id_map, parent_map, repo, graph=None):
 
277
    root_id, rev_id, rev_id_to_root_id_map, parent_map, repo, graph=None):
269
278
    """Get the parent keys for a given root id.
270
 
 
 
279
    
271
280
    A helper function for _new_root_data_stream.
272
281
    """
273
282
    # Include direct parents of the revision, but only if they used the same
288
297
                # But set parent_root_id to None since we don't really know
289
298
                parent_root_id = None
290
299
            else:
291
 
                parent_root_id = tree.path2id('')
 
300
                parent_root_id = tree.get_root_id()
292
301
            rev_id_to_root_id_map[parent_id] = None
293
302
            # XXX: why not:
294
303
            #   rev_id_to_root_id_map[parent_id] = parent_root_id
310
319
                pass
311
320
            else:
312
321
                try:
313
 
                    parent_ids.append(
314
 
                        tree.get_file_revision(
315
 
                            tree.id2path(root_id, recurse='none')))
 
322
                    parent_ids.append(tree.get_file_revision(root_id))
316
323
                except errors.NoSuchId:
317
324
                    # not in the tree
318
325
                    pass
330
337
 
331
338
class TargetRepoKinds(object):
332
339
    """An enum-like set of constants.
333
 
 
 
340
    
334
341
    They are the possible values of FetchSpecFactory.target_repo_kinds.
335
342
    """
336
 
 
 
343
    
337
344
    PREEXISTING = 'preexisting'
338
345
    STACKED = 'stacked'
339
346
    EMPTY = 'empty'
415
422
                graph = self.source_repo.get_graph()
416
423
                topo_order = list(graph.iter_topo_order(ret.get_keys()))
417
424
                result_set = topo_order[:self.limit]
418
 
                ret = self.source_repo.revision_ids_to_search_result(
419
 
                    result_set)
 
425
                ret = self.source_repo.revision_ids_to_search_result(result_set)
420
426
            return ret
421
427
        else:
422
428
            return vf_search.NotInOtherForRevs(self.target_repo, self.source_repo,
423
 
                                               required_ids=heads_to_fetch, if_present_ids=if_present_fetch,
424
 
                                               limit=self.limit).execute()
 
429
                required_ids=heads_to_fetch, if_present_ids=if_present_fetch,
 
430
                limit=self.limit).execute()