~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/versionedfile.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-12-04 00:42:43 UTC
  • mfrom: (3062.1.14 fast-plan-merge)
  • Revision ID: pqm@pqm.ubuntu.com-20071204004243-cgss0sl9yf0ayepc
Speed up annotate on packs

Show diffs side-by-side

added added

removed removed

Lines of Context:
492
492
        return PlanWeaveMerge(plan, a_marker, b_marker).merge_lines()[0]
493
493
 
494
494
 
 
495
class _PlanMergeVersionedFile(object):
 
496
    """A VersionedFile for uncommitted and committed texts.
 
497
 
 
498
    It is intended to allow merges to be planned with working tree texts.
 
499
    It implements only the small part of the VersionedFile interface used by
 
500
    PlanMerge.  It falls back to multiple versionedfiles for data not stored in
 
501
    _PlanMergeVersionedFile itself.
 
502
    """
 
503
 
 
504
    def __init__(self, file_id, fallback_versionedfiles=None):
 
505
        """Constuctor
 
506
 
 
507
        :param file_id: Used when raising exceptions.
 
508
        :param fallback_versionedfiles: If supplied, the set of fallbacks to
 
509
            use.  Otherwise, _PlanMergeVersionedFile.fallback_versionedfiles
 
510
            can be appended to later.
 
511
        """
 
512
        self._file_id = file_id
 
513
        if fallback_versionedfiles is None:
 
514
            self.fallback_versionedfiles = []
 
515
        else:
 
516
            self.fallback_versionedfiles = fallback_versionedfiles
 
517
        self._parents = {}
 
518
        self._lines = {}
 
519
 
 
520
    def plan_merge(self, ver_a, ver_b):
 
521
        """See VersionedFile.plan_merge"""
 
522
        from merge import _PlanMerge
 
523
        return _PlanMerge(ver_a, ver_b, self).plan_merge()
 
524
 
 
525
    def add_lines(self, version_id, parents, lines):
 
526
        """See VersionedFile.add_lines
 
527
 
 
528
        Lines are added locally, not fallback versionedfiles.  Also, ghosts are
 
529
        permitted.  Only reserved ids are permitted.
 
530
        """
 
531
        if not revision.is_reserved_id(version_id):
 
532
            raise ValueError('Only reserved ids may be used')
 
533
        if parents is None:
 
534
            raise ValueError('Parents may not be None')
 
535
        if lines is None:
 
536
            raise ValueError('Lines may not be None')
 
537
        self._parents[version_id] = parents
 
538
        self._lines[version_id] = lines
 
539
 
 
540
    def get_lines(self, version_id):
 
541
        """See VersionedFile.get_ancestry"""
 
542
        lines = self._lines.get(version_id)
 
543
        if lines is not None:
 
544
            return lines
 
545
        for versionedfile in self.fallback_versionedfiles:
 
546
            try:
 
547
                return versionedfile.get_lines(version_id)
 
548
            except errors.RevisionNotPresent:
 
549
                continue
 
550
        else:
 
551
            raise errors.RevisionNotPresent(version_id, self._file_id)
 
552
 
 
553
    def get_ancestry(self, version_id, topo_sorted=False):
 
554
        """See VersionedFile.get_ancestry.
 
555
 
 
556
        Note that this implementation assumes that if a VersionedFile can
 
557
        answer get_ancestry at all, it can give an authoritative answer.  In
 
558
        fact, ghosts can invalidate this assumption.  But it's good enough
 
559
        99% of the time, and far cheaper/simpler.
 
560
 
 
561
        Also note that the results of this version are never topologically
 
562
        sorted, and are a set.
 
563
        """
 
564
        if topo_sorted:
 
565
            raise ValueError('This implementation does not provide sorting')
 
566
        parents = self._parents.get(version_id)
 
567
        if parents is None:
 
568
            for vf in self.fallback_versionedfiles:
 
569
                try:
 
570
                    return vf.get_ancestry(version_id, topo_sorted=False)
 
571
                except errors.RevisionNotPresent:
 
572
                    continue
 
573
            else:
 
574
                raise errors.RevisionNotPresent(version_id, self._file_id)
 
575
        ancestry = set([version_id])
 
576
        for parent in parents:
 
577
            ancestry.update(self.get_ancestry(parent, topo_sorted=False))
 
578
        return ancestry
 
579
 
 
580
    def get_parents(self, version_id):
 
581
        """See VersionedFile.get_parents"""
 
582
        parents = self._parents.get(version_id)
 
583
        if parents is not None:
 
584
            return parents
 
585
        for versionedfile in self.fallback_versionedfiles:
 
586
            try:
 
587
                return versionedfile.get_parents(version_id)
 
588
            except errors.RevisionNotPresent:
 
589
                continue
 
590
        else:
 
591
            raise errors.RevisionNotPresent(version_id, self._file_id)
 
592
 
 
593
 
495
594
class PlanWeaveMerge(TextMerge):
496
595
    """Weave merge that takes a plan as its input.
497
596