~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
18
17
"""Copying of history from one branch to another.
19
18
 
20
19
The basic plan is that every branch knows the history of everything
23
22
branch.
24
23
"""
25
24
 
 
25
from __future__ import absolute_import
 
26
 
26
27
import operator
27
28
 
28
29
from bzrlib.lazy_import import lazy_import
29
30
lazy_import(globals(), """
30
31
from bzrlib import (
31
 
    graph,
32
32
    tsort,
33
33
    versionedfile,
 
34
    vf_search,
34
35
    )
35
36
""")
36
 
import bzrlib
37
37
from bzrlib import (
38
38
    errors,
39
39
    ui,
40
40
    )
 
41
from bzrlib.i18n import gettext
41
42
from bzrlib.revision import NULL_REVISION
42
43
from bzrlib.trace import mutter
43
44
 
94
95
        pb = ui.ui_factory.nested_progress_bar()
95
96
        pb.show_pct = pb.show_count = False
96
97
        try:
97
 
            pb.update("Finding revisions", 0, 2)
 
98
            pb.update(gettext("Finding revisions"), 0, 2)
98
99
            search_result = self._revids_to_fetch()
99
100
            mutter('fetching: %s', search_result)
100
101
            if search_result.is_empty():
101
102
                return
102
 
            pb.update("Fetching revisions", 1, 2)
 
103
            pb.update(gettext("Fetching revisions"), 1, 2)
103
104
            self._fetch_everything_for_search(search_result)
104
105
        finally:
105
106
            pb.finished()
161
162
        elif self._last_revision == NULL_REVISION:
162
163
            # fetch_spec is None + last_revision is null => empty fetch.
163
164
            # explicit limit of no revisions needed
164
 
            return graph.EmptySearchResult()
 
165
            return vf_search.EmptySearchResult()
165
166
        elif self._last_revision is not None:
166
 
            return graph.NotInOtherForRevs(self.to_repository,
 
167
            return vf_search.NotInOtherForRevs(self.to_repository,
167
168
                self.from_repository, [self._last_revision],
168
169
                find_ghosts=self.find_ghosts).execute()
169
170
        else: # self._last_revision is None:
170
 
            return graph.EverythingNotInOther(self.to_repository,
 
171
            return vf_search.EverythingNotInOther(self.to_repository,
171
172
                self.from_repository,
172
173
                find_ghosts=self.find_ghosts).execute()
173
174
 
202
203
        revs = list(revs)
203
204
        while revs:
204
205
            for tree in self.source.revision_trees(revs[:100]):
205
 
                if tree.inventory.revision_id is None:
206
 
                    tree.inventory.revision_id = tree.get_revision_id()
 
206
                if tree.root_inventory.revision_id is None:
 
207
                    tree.root_inventory.revision_id = tree.get_revision_id()
207
208
                yield tree
208
209
            revs = revs[100:]
209
210
 
210
211
    def _find_root_ids(self, revs, parent_map, graph):
211
212
        revision_root = {}
212
213
        for tree in self.iter_rev_trees(revs):
213
 
            revision_id = tree.inventory.root.revision
214
214
            root_id = tree.get_root_id()
 
215
            revision_id = tree.get_file_revision(root_id, u"")
215
216
            revision_root[revision_id] = root_id
216
217
        # Find out which parents we don't already know root ids for
217
218
        parents = set()
318
319
                pass
319
320
            else:
320
321
                try:
321
 
                    parent_ids.append(tree.inventory[root_id].revision)
 
322
                    parent_ids.append(tree.get_file_revision(root_id))
322
323
                except errors.NoSuchId:
323
324
                    # not in the tree
324
325
                    pass
350
351
 
351
352
    Factors that go into determining the sort of fetch to perform:
352
353
     * did the caller specify any revision IDs?
353
 
     * did the caller specify a source branch (need to fetch the tip + tags)
 
354
     * did the caller specify a source branch (need to fetch its
 
355
       heads_to_fetch(), usually the tip + tags)
354
356
     * is there an existing target repo (don't need to refetch revs it
355
357
       already has)
356
358
     * target is stacked?  (similar to pre-existing target repo: even if
371
373
        self.source_repo = None
372
374
        self.target_repo = None
373
375
        self.target_repo_kind = None
 
376
        self.limit = None
374
377
 
375
378
    def add_revision_ids(self, revision_ids):
376
379
        """Add revision_ids to the set of revision_ids to be fetched."""
377
380
        self._explicit_rev_ids.update(revision_ids)
378
 
        
 
381
 
379
382
    def make_fetch_spec(self):
380
383
        """Build a SearchResult or PendingAncestryResult or etc."""
381
384
        if self.target_repo_kind is None or self.source_repo is None:
382
385
            raise AssertionError(
383
386
                'Incomplete FetchSpecFactory: %r' % (self.__dict__,))
384
387
        if len(self._explicit_rev_ids) == 0 and self.source_branch is None:
 
388
            if self.limit is not None:
 
389
                raise NotImplementedError(
 
390
                    "limit is only supported with a source branch set")
385
391
            # Caller hasn't specified any revisions or source branch
386
392
            if self.target_repo_kind == TargetRepoKinds.EMPTY:
387
 
                return graph.EverythingResult(self.source_repo)
 
393
                return vf_search.EverythingResult(self.source_repo)
388
394
            else:
389
395
                # We want everything not already in the target (or target's
390
396
                # fallbacks).
391
 
                return graph.EverythingNotInOther(
 
397
                return vf_search.EverythingNotInOther(
392
398
                    self.target_repo, self.source_repo).execute()
393
399
        heads_to_fetch = set(self._explicit_rev_ids)
394
 
        tags_to_fetch = set()
395
400
        if self.source_branch is not None:
396
 
            try:
397
 
                tags_to_fetch.update(
398
 
                    self.source_branch.tags.get_reverse_tag_dict())
399
 
            except errors.TagsNotSupported:
400
 
                pass
 
401
            must_fetch, if_present_fetch = self.source_branch.heads_to_fetch()
401
402
            if self.source_branch_stop_revision_id is not None:
402
 
                heads_to_fetch.add(self.source_branch_stop_revision_id)
403
 
            else:
404
 
                heads_to_fetch.add(self.source_branch.last_revision())
 
403
                # Replace the tip rev from must_fetch with the stop revision
 
404
                # XXX: this might be wrong if the tip rev is also in the
 
405
                # must_fetch set for other reasons (e.g. it's the tip of
 
406
                # multiple loom threads?), but then it's pretty unclear what it
 
407
                # should mean to specify a stop_revision in that case anyway.
 
408
                must_fetch.discard(self.source_branch.last_revision())
 
409
                must_fetch.add(self.source_branch_stop_revision_id)
 
410
            heads_to_fetch.update(must_fetch)
 
411
        else:
 
412
            if_present_fetch = set()
405
413
        if self.target_repo_kind == TargetRepoKinds.EMPTY:
406
414
            # PendingAncestryResult does not raise errors if a requested head
407
415
            # is absent.  Ideally it would support the
408
416
            # required_ids/if_present_ids distinction, but in practice
409
417
            # heads_to_fetch will almost certainly be present so this doesn't
410
418
            # matter much.
411
 
            all_heads = heads_to_fetch.union(tags_to_fetch)
412
 
            return graph.PendingAncestryResult(all_heads, self.source_repo)
413
 
        return graph.NotInOtherForRevs(self.target_repo, self.source_repo,
414
 
            required_ids=heads_to_fetch, if_present_ids=tags_to_fetch
415
 
            ).execute()
416
 
 
417
 
 
 
419
            all_heads = heads_to_fetch.union(if_present_fetch)
 
420
            ret = vf_search.PendingAncestryResult(all_heads, self.source_repo)
 
421
            if self.limit is not None:
 
422
                graph = self.source_repo.get_graph()
 
423
                topo_order = list(graph.iter_topo_order(ret.get_keys()))
 
424
                result_set = topo_order[:self.limit]
 
425
                ret = self.source_repo.revision_ids_to_search_result(result_set)
 
426
            return ret
 
427
        else:
 
428
            return vf_search.NotInOtherForRevs(self.target_repo, self.source_repo,
 
429
                required_ids=heads_to_fetch, if_present_ids=if_present_fetch,
 
430
                limit=self.limit).execute()