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):
521
"""See VersionedFile.plan_merge"""
522
from merge import _PlanMerge
523
return _PlanMerge(ver_a, ver_b, self).plan_merge()
525
def add_lines(self, version_id, parents, lines):
526
"""See VersionedFile.add_lines
528
Lines are added locally, not fallback versionedfiles. Also, ghosts are
529
permitted. Only reserved ids are permitted.
531
if not revision.is_reserved_id(version_id):
532
raise ValueError('Only reserved ids may be used')
534
raise ValueError('Parents may not be None')
536
raise ValueError('Lines may not be None')
537
self._parents[version_id] = parents
538
self._lines[version_id] = lines
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:
545
for versionedfile in self.fallback_versionedfiles:
547
return versionedfile.get_lines(version_id)
548
except errors.RevisionNotPresent:
551
raise errors.RevisionNotPresent(version_id, self._file_id)
553
def get_ancestry(self, version_id, topo_sorted=False):
554
"""See VersionedFile.get_ancestry.
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.
561
Also note that the results of this version are never topologically
562
sorted, and are a set.
565
raise ValueError('This implementation does not provide sorting')
566
parents = self._parents.get(version_id)
568
for vf in self.fallback_versionedfiles:
570
return vf.get_ancestry(version_id, topo_sorted=False)
571
except errors.RevisionNotPresent:
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))
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:
585
for versionedfile in self.fallback_versionedfiles:
587
return versionedfile.get_parents(version_id)
588
except errors.RevisionNotPresent:
591
raise errors.RevisionNotPresent(version_id, self._file_id)
495
594
class PlanWeaveMerge(TextMerge):
496
595
"""Weave merge that takes a plan as its input.