45
from bzrlib.graph import DictParentsProvider, Graph, StackedParentsProvider
42
from bzrlib.graph import DictParentsProvider, Graph, _StackedParentsProvider
46
43
from bzrlib.transport.memory import MemoryTransport
45
from bzrlib.inter import InterObject
48
46
from bzrlib.registry import Registry
49
47
from bzrlib.symbol_versioning import *
50
48
from bzrlib.textmerge import TextMerge
51
from bzrlib import bencode
49
from bzrlib.util import bencode
54
52
adapter_registry = Registry()
837
829
raise NotImplementedError(self.add_lines)
839
def _add_text(self, key, parents, text, nostore_sha=None, random_id=False):
840
"""Add a text to the store.
842
This is a private function for use by CommitBuilder.
844
:param key: The key tuple of the text to add. If the last element is
845
None, a CHK string will be generated during the addition.
846
:param parents: The parents key tuples of the text to add.
847
:param text: A string containing the text to be committed.
848
:param nostore_sha: Raise ExistingContent and do not add the lines to
849
the versioned file if the digest of the lines matches this.
850
:param random_id: If True a random id has been selected rather than
851
an id determined by some deterministic process such as a converter
852
from a foreign VCS. When True the backend may choose not to check
853
for uniqueness of the resulting key within the versioned file, so
854
this should only be done when the result is expected to be unique
856
:param check_content: If True, the lines supplied are verified to be
857
bytestrings that are correctly formed lines.
858
:return: The text sha1, the number of bytes in the text, and an opaque
859
representation of the inserted version which can be provided
860
back to future _add_text calls in the parent_texts dictionary.
862
# The default implementation just thunks over to .add_lines(),
863
# inefficient, but it works.
864
return self.add_lines(key, parents, osutils.split_lines(text),
865
nostore_sha=nostore_sha,
869
831
def add_mpdiffs(self, records):
870
832
"""Add mpdiffs to this VersionedFile.
913
875
raise NotImplementedError(self.annotate)
915
877
def check(self, progress_bar=None):
916
"""Check this object for integrity.
918
:param progress_bar: A progress bar to output as the check progresses.
919
:param keys: Specific keys within the VersionedFiles to check. When
920
this parameter is not None, check() becomes a generator as per
921
get_record_stream. The difference to get_record_stream is that
922
more or deeper checks will be performed.
923
:return: None, or if keys was supplied a generator as per
878
"""Check this object for integrity."""
926
879
raise NotImplementedError(self.check)
929
882
def check_not_reserved_id(version_id):
930
883
revision.check_not_reserved_id(version_id)
932
def clear_cache(self):
933
"""Clear whatever caches this VersionedFile holds.
935
This is generally called after an operation has been performed, when we
936
don't expect to be using this versioned file again soon.
939
885
def _check_lines_not_unicode(self, lines):
940
886
"""Check that lines being added to a versioned file are not unicode."""
941
887
for line in lines:
948
894
if '\n' in line[:-1]:
949
895
raise errors.BzrBadParameterContainsNewline("lines")
951
def get_known_graph_ancestry(self, keys):
952
"""Get a KnownGraph instance with the ancestry of keys."""
953
# most basic implementation is a loop around get_parent_map
957
this_parent_map = self.get_parent_map(pending)
958
parent_map.update(this_parent_map)
960
map(pending.update, this_parent_map.itervalues())
961
pending = pending.difference(parent_map)
962
kg = _mod_graph.KnownGraph(parent_map)
965
897
def get_parent_map(self, keys):
966
898
"""Get a map of the parents of keys.
1159
1091
result.append((prefix + (origin,), line))
1162
def get_annotator(self):
1163
return annotate.Annotator(self)
1165
def check(self, progress_bar=None, keys=None):
1094
def check(self, progress_bar=None):
1166
1095
"""See VersionedFiles.check()."""
1167
# XXX: This is over-enthusiastic but as we only thunk for Weaves today
1168
# this is tolerable. Ideally we'd pass keys down to check() and
1169
# have the older VersiondFile interface updated too.
1170
1096
for prefix, vf in self._iter_all_components():
1172
if keys is not None:
1173
return self.get_record_stream(keys, 'unordered', True)
1175
1099
def get_parent_map(self, keys):
1176
1100
"""Get a map of the parents of keys.
1478
1402
elif state == 'conflicted-b':
1479
1403
ch_b = ch_a = True
1480
1404
lines_b.append(line)
1481
elif state == 'killed-both':
1482
# This counts as a change, even though there is no associated
1486
1406
if state not in ('irrelevant', 'ghost-a', 'ghost-b',
1407
'killed-base', 'killed-both'):
1488
1408
raise AssertionError(state)
1489
1409
for struct in outstanding_struct():
1492
def base_from_plan(self):
1493
"""Construct a BASE file from the plan text."""
1495
for state, line in self.plan:
1496
if state in ('killed-a', 'killed-b', 'killed-both', 'unchanged'):
1497
# If unchanged, then this line is straight from base. If a or b
1498
# or both killed the line, then it *used* to be in base.
1499
base_lines.append(line)
1501
if state not in ('killed-base', 'irrelevant',
1502
'ghost-a', 'ghost-b',
1504
'conflicted-a', 'conflicted-b'):
1505
# killed-base, irrelevant means it doesn't apply
1506
# ghost-a/ghost-b are harder to say for sure, but they
1507
# aren't in the 'inc_c' which means they aren't in the
1508
# shared base of a & b. So we don't include them. And
1509
# obviously if the line is newly inserted, it isn't in base
1511
# If 'conflicted-a' or b, then it is new vs one base, but
1512
# old versus another base. However, if we make it present
1513
# in the base, it will be deleted from the target, and it
1514
# seems better to get a line doubled in the merge result,
1515
# rather than have it deleted entirely.
1516
# Example, each node is the 'text' at that point:
1524
# There was a criss-cross conflict merge. Both sides
1525
# include the other, but put themselves first.
1526
# Weave marks this as a 'clean' merge, picking OTHER over
1527
# THIS. (Though the details depend on order inserted into
1529
# LCA generates a plan:
1530
# [('unchanged', M),
1531
# ('conflicted-b', b),
1533
# ('conflicted-a', b),
1535
# If you mark 'conflicted-*' as part of BASE, then a 3-way
1536
# merge tool will cleanly generate "MaN" (as BASE vs THIS
1537
# removes one 'b', and BASE vs OTHER removes the other)
1538
# If you include neither, 3-way creates a clean "MbabN" as
1539
# THIS adds one 'b', and OTHER does too.
1540
# It seems that having the line 2 times is better than
1541
# having it omitted. (Easier to manually delete than notice
1542
# it needs to be added.)
1543
raise AssertionError('Unknown state: %s' % (state,))
1547
1413
class WeaveMerge(PlanWeaveMerge):
1548
1414
"""Weave merge that takes a VersionedFile and two versions as its input."""
1646
1512
record.get_bytes_as(record.storage_kind) call.
1648
1514
self._bytes_iterator = bytes_iterator
1649
self._kind_factory = {
1650
'fulltext': fulltext_network_to_record,
1651
'groupcompress-block': groupcompress.network_block_to_records,
1652
'knit-ft-gz': knit.knit_network_to_record,
1653
'knit-delta-gz': knit.knit_network_to_record,
1654
'knit-annotated-ft-gz': knit.knit_network_to_record,
1655
'knit-annotated-delta-gz': knit.knit_network_to_record,
1656
'knit-delta-closure': knit.knit_delta_closure_to_records,
1515
self._kind_factory = {'knit-ft-gz':knit.knit_network_to_record,
1516
'knit-delta-gz':knit.knit_network_to_record,
1517
'knit-annotated-ft-gz':knit.knit_network_to_record,
1518
'knit-annotated-delta-gz':knit.knit_network_to_record,
1519
'knit-delta-closure':knit.knit_delta_closure_to_records,
1520
'fulltext':fulltext_network_to_record,
1659
1523
def read(self):