909
909
# indexes can't directly store that, so we give them
910
910
# an empty tuple instead.
912
line_bytes = ''.join(lines)
912
913
return self._add(key, lines, parents,
913
parent_texts, left_matching_blocks, nostore_sha, random_id)
914
parent_texts, left_matching_blocks, nostore_sha, random_id,
915
line_bytes=line_bytes)
917
def _add_text(self, key, parents, text, nostore_sha=None, random_id=False):
918
"""See VersionedFiles._add_text()."""
919
self._index._check_write_ok()
920
self._check_add(key, None, random_id, check_content=False)
921
if text.__class__ is not str:
922
raise errors.BzrBadParameterUnicode("text")
924
# The caller might pass None if there is no graph data, but kndx
925
# indexes can't directly store that, so we give them
926
# an empty tuple instead.
928
return self._add(key, None, parents,
929
None, None, nostore_sha, random_id,
915
932
def _add(self, key, lines, parents, parent_texts,
916
left_matching_blocks, nostore_sha, random_id):
933
left_matching_blocks, nostore_sha, random_id,
917
935
"""Add a set of lines on top of version specified by parents.
919
937
Any versions not present will be converted into ghosts.
939
:param lines: A list of strings where each one is a single line (has a
940
single newline at the end of the string) This is now optional
941
(callers can pass None). It is left in its location for backwards
942
compatibility. It should ''.join(lines) must == line_bytes
943
:param line_bytes: A single string containing the content
945
We pass both lines and line_bytes because different routes bring the
946
values to this function. And for memory efficiency, we don't want to
947
have to split/join on-demand.
921
949
# first thing, if the content is something we don't need to store, find
923
line_bytes = ''.join(lines)
924
951
digest = sha_string(line_bytes)
925
952
if nostore_sha == digest:
926
953
raise errors.ExistingContent
948
975
text_length = len(line_bytes)
951
if lines[-1][-1] != '\n':
952
# copy the contents of lines.
978
# Note: line_bytes is not modified to add a newline, that is tracked
979
# via the no_eol flag. 'lines' *is* modified, because that is the
980
# general values needed by the Content code.
981
if line_bytes and line_bytes[-1] != '\n':
982
options.append('no-eol')
984
# Copy the existing list, or create a new one
986
lines = osutils.split_lines(line_bytes)
954
options.append('no-eol')
955
lines[-1] = lines[-1] + '\n'
989
# Replace the last line with one that ends in a final newline
990
lines[-1] = lines[-1] + '\n'
992
lines = osutils.split_lines(line_bytes)
958
994
for element in key[:-1]:
959
if type(element) != str:
995
if type(element) is not str:
960
996
raise TypeError("key contains non-strings: %r" % (key,))
961
997
if key[-1] is None:
962
998
key = key[:-1] + ('sha1:' + digest,)
963
elif type(key[-1]) != str:
999
elif type(key[-1]) is not str:
964
1000
raise TypeError("key contains non-strings: %r" % (key,))
965
1001
# Knit hunks are still last-element only
966
1002
version_id = key[-1]
967
1003
content = self._factory.make(lines, version_id)
968
if 'no-eol' in options:
969
1005
# Hint to the content object that its text() call should strip the
971
1007
content._should_strip_eol = True
1920
1959
function spends less time resizing the final string.
1921
1960
:return: (len, a StringIO instance with the raw data ready to read.)
1923
# Note: using a string copy here increases memory pressure with e.g.
1924
# ISO's, but it is about 3 seconds faster on a 1.2Ghz intel machine
1925
# when doing the initial commit of a mozilla tree. RBC 20070921
1926
bytes = ''.join(chain(
1927
["version %s %d %s\n" % (key[-1],
1930
dense_lines or lines,
1931
["end %s\n" % key[-1]]))
1932
if type(bytes) != str:
1933
raise AssertionError(
1934
'data must be plain bytes was %s' % type(bytes))
1962
chunks = ["version %s %d %s\n" % (key[-1], len(lines), digest)]
1963
chunks.extend(dense_lines or lines)
1964
chunks.append("end %s\n" % key[-1])
1965
for chunk in chunks:
1966
if type(chunk) is not str:
1967
raise AssertionError(
1968
'data must be plain bytes was %s' % type(chunk))
1935
1969
if lines and lines[-1][-1] != '\n':
1936
1970
raise ValueError('corrupt lines value %r' % lines)
1937
compressed_bytes = tuned_gzip.bytes_to_gzip(bytes)
1971
compressed_bytes = tuned_gzip.chunks_to_gzip(chunks)
1938
1972
return len(compressed_bytes), compressed_bytes
1940
1974
def _split_header(self, line):
2883
2917
def get_missing_parents(self):
2884
2918
"""Return the keys of missing parents."""
2919
# If updating this, you should also update
2920
# groupcompress._GCGraphIndex.get_missing_parents
2885
2921
# We may have false positives, so filter those out.
2886
2922
self._key_dependencies.add_keys(
2887
2923
self.get_parent_map(self._key_dependencies.get_unsatisfied_refs()))
3550
3586
"""Create a heads provider for resolving ancestry issues."""
3551
3587
if self._heads_provider is not None:
3552
3588
return self._heads_provider
3553
parent_provider = _mod_graph.DictParentsProvider(
3554
self._revision_id_graph)
3555
graph_obj = _mod_graph.Graph(parent_provider)
3556
head_cache = _mod_graph.FrozenHeadsCache(graph_obj)
3557
self._heads_provider = head_cache
3589
self._heads_provider = _mod_graph.KnownGraph(self._revision_id_graph)
3590
return self._heads_provider
3560
3592
def annotate(self, key):
3561
3593
"""Return the annotated fulltext at the given key.
3584
3616
being able to produce line deltas.
3586
3618
# TODO: this code generates a parent maps of present ancestors; it
3587
# could be split out into a separate method, and probably should use
3588
# iter_ancestry instead. -- mbp and robertc 20080704
3619
# could be split out into a separate method
3620
# -- mbp and robertc 20080704
3589
3621
graph = _mod_graph.Graph(self._knit)
3590
head_cache = _mod_graph.FrozenHeadsCache(graph)
3591
search = graph._make_breadth_first_searcher([key])
3595
present, ghosts = search.next_with_ghosts()
3596
except StopIteration:
3598
keys.update(present)
3599
parent_map = self._knit.get_parent_map(keys)
3622
parent_map = dict((k, v) for k, v in graph.iter_ancestry([key])
3625
raise errors.RevisionNotPresent(key, self)
3626
keys = parent_map.keys()
3627
heads_provider = _mod_graph.KnownGraph(parent_map)
3600
3628
parent_cache = {}
3601
3629
reannotate = annotate.reannotate
3602
3630
for record in self._knit.get_record_stream(keys, 'topological', True):