492
492
return PlanWeaveMerge(plan, a_marker, b_marker).merge_lines()[0]
495
class _PlanMergeVersionedFile(object):
496
"""A VersionedFile for uncommitted and committed texts.
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.
504
def __init__(self, file_id, fallback_versionedfiles=None):
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.
512
self._file_id = file_id
513
if fallback_versionedfiles is None:
514
self.fallback_versionedfiles = []
516
self.fallback_versionedfiles = fallback_versionedfiles
520
def plan_merge(self, ver_a, ver_b, base=None):
521
"""See VersionedFile.plan_merge"""
522
from bzrlib.merge import _PlanMerge
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)
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()
535
old_plan = _PlanLCAMerge(ver_a, base, self, graph).plan_merge()
536
return _PlanLCAMerge._subtract_plans(list(old_plan), list(new_plan))
538
def add_lines(self, version_id, parents, lines):
539
"""See VersionedFile.add_lines
541
Lines are added locally, not fallback versionedfiles. Also, ghosts are
542
permitted. Only reserved ids are permitted.
544
if not revision.is_reserved_id(version_id):
545
raise ValueError('Only reserved ids may be used')
547
raise ValueError('Parents may not be None')
549
raise ValueError('Lines may not be None')
550
self._parents[version_id] = parents
551
self._lines[version_id] = lines
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:
558
for versionedfile in self.fallback_versionedfiles:
560
return versionedfile.get_lines(version_id)
561
except errors.RevisionNotPresent:
564
raise errors.RevisionNotPresent(version_id, self._file_id)
566
def get_ancestry(self, version_id, topo_sorted=False):
567
"""See VersionedFile.get_ancestry.
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.
574
Also note that the results of this version are never topologically
575
sorted, and are a set.
578
raise ValueError('This implementation does not provide sorting')
579
parents = self._parents.get(version_id)
581
for vf in self.fallback_versionedfiles:
583
return vf.get_ancestry(version_id, topo_sorted=False)
584
except errors.RevisionNotPresent:
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))
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:
598
for versionedfile in self.fallback_versionedfiles:
600
return versionedfile.get_parents(version_id)
601
except errors.RevisionNotPresent:
604
raise errors.RevisionNotPresent(version_id, self._file_id)
606
def _get_graph(self):
607
from bzrlib.graph import (
610
_StackedParentsProvider,
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))
495
619
class PlanWeaveMerge(TextMerge):
496
620
"""Weave merge that takes a plan as its input.