496
496
b_marker=TextMerge.B_MARKER):
497
497
return PlanWeaveMerge(plan, a_marker, b_marker).merge_lines()[0]
499
def find_bad_ancestors(self, revision_ids, get_text_version, file_id,
501
"""Search this versionedfile for ancestors that are not referenced.
503
One possible deviation is if a text's parents are not a subset of its
504
revision's parents' last-modified revisions. This deviation prevents
505
fileids_altered_by_revision_ids from correctly determining which
506
revisions of each text need to be fetched.
508
This method detects this case.
510
:param revision_ids: The revisions to scan for deviations
511
:param file_id: The file-id of the versionedfile to scan
512
:param get_text_version: a callable that takes two arguments,
513
file_id and a revision_id, and returns the id of text version of
514
that file in that revision.
516
:returns: a dict mapping bad parents to a set of revisions they occur
520
from bzrlib.trace import mutter
521
for num, revision_id in enumerate(revision_ids):
523
#if revision_id == 'broken-revision-1-2': import pdb; pdb.set_trace()
524
#if revision_id == 'broken-revision-1-2':
525
# result.setdefault('parent-1',set()).add('broken-revision-1-2')
526
# result.setdefault('parent-2',set()).add('broken-revision-1-2')
527
text_revision = get_text_version(file_id, revision_id)
528
if text_revision is None:
531
file_parents = repo_graph.get_parents([text_revision])[0]
532
revision_parents = set()
533
for parent_id in file_parents:
535
revision_parents.add(get_text_version(file_id, parent_id))
536
# Skip ghosts (this means they can't provide texts...)
537
except errors.RevisionNotPresent:
540
knit_parents = set(self.get_parents(text_revision))
541
unreferenced = knit_parents.difference(revision_parents)
542
for unreferenced_id in unreferenced:
543
result.setdefault(unreferenced_id, set()).add(text_revision)
545
correct_parents = tuple(repo_graph.heads(knit_parents))
546
spurious_parents = knit_parents.difference(correct_parents)
547
for spurious_parent in spurious_parents:
548
result.setdefault(spurious_parent, set()).add(text_revision)
549
# XXX: false positives
550
#text_parents = self.get_parents(text_revision)
551
#if text_parents != file_parents:
552
# for text_parent in text_parents:
553
# result.setdefault(text_parent, set()).add(text_revision)
554
mutter('find_bad_ancestors: %r', result)
558
500
class PlanWeaveMerge(TextMerge):
559
501
"""Weave merge that takes a plan as its input.