/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 bzrlib/versionedfile.py

  • Committer: Robert Collins
  • Date: 2008-02-06 04:06:42 UTC
  • mfrom: (3216 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3217.
  • Revision ID: robertc@robertcollins.net-20080206040642-2efx3l4iv5f95lxp
Merge up with bzr.dev.

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, base=None):
 
521
        """See VersionedFile.plan_merge"""
 
522
        from bzrlib.merge import _PlanMerge
 
523
        if base is None:
 
524
            return _PlanMerge(ver_a, ver_b, self).plan_merge()
 
525
        old_plan = list(_PlanMerge(ver_a, base, self).plan_merge())
 
526
        new_plan = list(_PlanMerge(ver_a, ver_b, self).plan_merge())
 
527
        return _PlanMerge._subtract_plans(old_plan, new_plan)
 
528
 
 
529
    def plan_lca_merge(self, ver_a, ver_b, base=None):
 
530
        from bzrlib.merge import _PlanLCAMerge
 
531
        graph = self._get_graph()
 
532
        new_plan = _PlanLCAMerge(ver_a, ver_b, self, graph).plan_merge()
 
533
        if base is None:
 
534
            return new_plan
 
535
        old_plan = _PlanLCAMerge(ver_a, base, self, graph).plan_merge()
 
536
        return _PlanLCAMerge._subtract_plans(list(old_plan), list(new_plan))
 
537
 
 
538
    def add_lines(self, version_id, parents, lines):
 
539
        """See VersionedFile.add_lines
 
540
 
 
541
        Lines are added locally, not fallback versionedfiles.  Also, ghosts are
 
542
        permitted.  Only reserved ids are permitted.
 
543
        """
 
544
        if not revision.is_reserved_id(version_id):
 
545
            raise ValueError('Only reserved ids may be used')
 
546
        if parents is None:
 
547
            raise ValueError('Parents may not be None')
 
548
        if lines is None:
 
549
            raise ValueError('Lines may not be None')
 
550
        self._parents[version_id] = parents
 
551
        self._lines[version_id] = lines
 
552
 
 
553
    def get_lines(self, version_id):
 
554
        """See VersionedFile.get_ancestry"""
 
555
        lines = self._lines.get(version_id)
 
556
        if lines is not None:
 
557
            return lines
 
558
        for versionedfile in self.fallback_versionedfiles:
 
559
            try:
 
560
                return versionedfile.get_lines(version_id)
 
561
            except errors.RevisionNotPresent:
 
562
                continue
 
563
        else:
 
564
            raise errors.RevisionNotPresent(version_id, self._file_id)
 
565
 
 
566
    def get_ancestry(self, version_id, topo_sorted=False):
 
567
        """See VersionedFile.get_ancestry.
 
568
 
 
569
        Note that this implementation assumes that if a VersionedFile can
 
570
        answer get_ancestry at all, it can give an authoritative answer.  In
 
571
        fact, ghosts can invalidate this assumption.  But it's good enough
 
572
        99% of the time, and far cheaper/simpler.
 
573
 
 
574
        Also note that the results of this version are never topologically
 
575
        sorted, and are a set.
 
576
        """
 
577
        if topo_sorted:
 
578
            raise ValueError('This implementation does not provide sorting')
 
579
        parents = self._parents.get(version_id)
 
580
        if parents is None:
 
581
            for vf in self.fallback_versionedfiles:
 
582
                try:
 
583
                    return vf.get_ancestry(version_id, topo_sorted=False)
 
584
                except errors.RevisionNotPresent:
 
585
                    continue
 
586
            else:
 
587
                raise errors.RevisionNotPresent(version_id, self._file_id)
 
588
        ancestry = set([version_id])
 
589
        for parent in parents:
 
590
            ancestry.update(self.get_ancestry(parent, topo_sorted=False))
 
591
        return ancestry
 
592
 
 
593
    def get_parents(self, version_id):
 
594
        """See VersionedFile.get_parents"""
 
595
        parents = self._parents.get(version_id)
 
596
        if parents is not None:
 
597
            return parents
 
598
        for versionedfile in self.fallback_versionedfiles:
 
599
            try:
 
600
                return versionedfile.get_parents(version_id)
 
601
            except errors.RevisionNotPresent:
 
602
                continue
 
603
        else:
 
604
            raise errors.RevisionNotPresent(version_id, self._file_id)
 
605
 
 
606
    def _get_graph(self):
 
607
        from bzrlib.graph import (
 
608
            DictParentsProvider,
 
609
            Graph,
 
610
            _StackedParentsProvider,
 
611
            )
 
612
        from bzrlib.repofmt.knitrepo import _KnitParentsProvider
 
613
        parent_providers = [DictParentsProvider(self._parents)]
 
614
        for vf in self.fallback_versionedfiles:
 
615
            parent_providers.append(_KnitParentsProvider(vf))
 
616
        return Graph(_StackedParentsProvider(parent_providers))
 
617
 
 
618
 
495
619
class PlanWeaveMerge(TextMerge):
496
620
    """Weave merge that takes a plan as its input.
497
621
    
549
673
            elif state == 'new-b':
550
674
                ch_b = True
551
675
                lines_b.append(line)
 
676
            elif state == 'conflicted-a':
 
677
                ch_b = ch_a = True
 
678
                lines_a.append(line)
 
679
            elif state == 'conflicted-b':
 
680
                ch_b = ch_a = True
 
681
                lines_b.append(line)
552
682
            else:
553
683
                assert state in ('irrelevant', 'ghost-a', 'ghost-b', 
554
684
                                 'killed-base', 'killed-both'), state