/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 breezy/fetch.py

  • Committer: Jelmer Vernooij
  • Date: 2018-02-18 21:42:57 UTC
  • mto: This revision was merged to the branch mainline in revision 6859.
  • Revision ID: jelmer@jelmer.uk-20180218214257-jpevutp1wa30tz3v
Update TODO to reference Breezy, not Bazaar.

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