~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Move FetchSpecFactory and TargetRepoKinds to bzrlib.fetch (from bzrlib.controldir).

Show diffs side-by-side

added added

removed removed

Lines of Context:
337
337
            selected_ids.append(parent_id)
338
338
    parent_keys = [(root_id, parent_id) for parent_id in selected_ids]
339
339
    return parent_keys
 
340
 
 
341
 
 
342
class TargetRepoKinds(object):
 
343
    """An enum-like set of constants.
 
344
    
 
345
    They are the possible values of FetchSpecFactory.target_repo_kinds.
 
346
    """
 
347
    
 
348
    PREEXISTING = 'preexisting'
 
349
    STACKED = 'stacked'
 
350
    EMPTY = 'empty'
 
351
 
 
352
 
 
353
class FetchSpecFactory(object):
 
354
    """A helper for building the best fetch spec for a sprout call.
 
355
 
 
356
    Factors that go into determining the sort of fetch to perform:
 
357
     * did the caller specify any revision IDs?
 
358
     * did the caller specify a source branch (need to fetch the tip + tags)
 
359
     * is there an existing target repo (don't need to refetch revs it
 
360
       already has)
 
361
     * target is stacked?  (similar to pre-existing target repo: even if
 
362
       the target itself is new don't want to refetch existing revs)
 
363
 
 
364
    :ivar source_branch: the source branch if one specified, else None.
 
365
    :ivar source_branch_stop_revision_id: fetch up to this revision of
 
366
        source_branch, rather than its tip.
 
367
    :ivar source_repo: the source repository if one found, else None.
 
368
    :ivar target_repo: the target repository acquired by sprout.
 
369
    :ivar target_repo_kind: one of the TargetRepoKinds constants.
 
370
    """
 
371
 
 
372
    def __init__(self):
 
373
        self._explicit_rev_ids = set()
 
374
        self.source_branch = None
 
375
        self.source_branch_stop_revision_id = None
 
376
        self.source_repo = None
 
377
        self.target_repo = None
 
378
        self.target_repo_kind = None
 
379
 
 
380
    def add_revision_ids(self, revision_ids):
 
381
        """Add revision_ids to the set of revision_ids to be fetched."""
 
382
        self._explicit_rev_ids.update(revision_ids)
 
383
        
 
384
    def make_fetch_spec(self):
 
385
        """Build a SearchResult or PendingAncestryResult or etc."""
 
386
        if self.target_repo_kind is None or self.source_repo is None:
 
387
            raise AssertionError(
 
388
                'Incomplete FetchSpecFactory: %r' % (self.__dict__,))
 
389
        if len(self._explicit_rev_ids) == 0 and self.source_branch is None:
 
390
            # Caller hasn't specified any revisions or source branch
 
391
            if self.target_repo_kind == TargetRepoKinds.EMPTY:
 
392
                return graph.EverythingResult(self.source_repo)
 
393
            else:
 
394
                # We want everything not already in the target (or target's
 
395
                # fallbacks).
 
396
                return graph.EverythingNotInOther(
 
397
                    self.target_repo, self.source_repo)
 
398
        heads_to_fetch = set(self._explicit_rev_ids)
 
399
        tags_to_fetch = set()
 
400
        if self.source_branch is not None:
 
401
            try:
 
402
                tags_to_fetch.update(
 
403
                    self.source_branch.tags.get_reverse_tag_dict())
 
404
            except errors.TagsNotSupported:
 
405
                pass
 
406
            if self.source_branch_stop_revision_id is not None:
 
407
                heads_to_fetch.add(self.source_branch_stop_revision_id)
 
408
            else:
 
409
                heads_to_fetch.add(self.source_branch.last_revision())
 
410
        if self.target_repo_kind == TargetRepoKinds.EMPTY:
 
411
            # PendingAncestryResult does not raise errors if a requested head
 
412
            # is absent.  Ideally it would support the
 
413
            # required_ids/if_present_ids distinction, but in practice
 
414
            # heads_to_fetch will almost certainly be present so this doesn't
 
415
            # matter much.
 
416
            all_heads = heads_to_fetch.union(tags_to_fetch)
 
417
            return graph.PendingAncestryResult(all_heads, self.source_repo)
 
418
        return graph.NotInOtherForRevs(self.target_repo, self.source_repo,
 
419
            required_ids=heads_to_fetch, if_present_ids=tags_to_fetch)
 
420
 
 
421