17
17
# Author: Martin Pool <mbp@canonical.com>
20
19
"""Weave - storage of related text file versions"""
21
from __future__ import absolute_import
23
23
# XXX: If we do weaves this way, will a merge still behave the same
24
24
# way if it's done in a different order? That's a pretty desirable
67
67
# FIXME: the conflict markers should be *7* characters
69
69
from copy import copy
70
from cStringIO import StringIO
73
from bzrlib.lazy_import import lazy_import
72
from .lazy_import import lazy_import
74
73
lazy_import(globals(), """
75
from bzrlib import tsort
74
from breezy import tsort
81
from bzrlib.errors import (WeaveError, WeaveFormatError, WeaveParentMismatch,
80
from .errors import (WeaveError, WeaveFormatError, WeaveParentMismatch,
82
81
RevisionAlreadyPresent,
83
82
RevisionNotPresent,
84
83
UnavailableRepresentation,
86
from bzrlib.osutils import dirname, sha, sha_strings, split_lines
87
import bzrlib.patiencediff
88
from bzrlib.revision import NULL_REVISION
89
from bzrlib.symbol_versioning import *
90
from bzrlib.trace import mutter
91
from bzrlib.versionedfile import (
85
from .osutils import dirname, sha, sha_strings, split_lines
86
from . import patiencediff
87
from .revision import NULL_REVISION
91
from .trace import mutter
92
from .versionedfile import (
92
93
AbsentContentFactory,
95
96
sort_groupcompress,
98
from bzrlib.weavefile import _read_weave_v5, write_weave_v5
99
from .weavefile import _read_weave_v5, write_weave_v5
101
102
class WeaveContentFactory(ContentFactory):
391
392
def _add_lines(self, version_id, parents, lines, parent_texts,
392
393
left_matching_blocks, nostore_sha, random_id, check_content):
393
394
"""See VersionedFile.add_lines."""
394
idx = self._add(version_id, lines, map(self._lookup, parents),
395
idx = self._add(version_id, lines, list(map(self._lookup, parents)),
395
396
nostore_sha=nostore_sha)
396
397
return sha_strings(lines), sum(map(len, lines)), idx
688
689
WFE = WeaveFormatError
691
# 449 0 4474.6820 2356.5590 bzrlib.weave:556(_extract)
692
# 449 0 4474.6820 2356.5590 breezy.weave:556(_extract)
692
693
# +285282 0 1676.8040 1676.8040 +<isinstance>
693
694
# 1.6 seconds in 'isinstance'.
694
695
# changing the first isinstance:
695
# 449 0 2814.2660 1577.1760 bzrlib.weave:556(_extract)
696
# 449 0 2814.2660 1577.1760 breezy.weave:556(_extract)
696
697
# +140414 0 762.8050 762.8050 +<isinstance>
697
698
# note that the inline time actually dropped (less function calls)
698
699
# and total processing time was halved.
699
700
# we're still spending ~1/4 of the method in isinstance though.
700
701
# so lets hard code the acceptable string classes we expect:
701
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
702
# 449 0 1202.9420 786.2930 breezy.weave:556(_extract)
702
703
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
704
705
# yay, down to ~1/4 the initial extract time, and our inline time
705
706
# has shrunk again, with isinstance no longer dominating.
706
707
# tweaking the stack inclusion test to use a set gives:
707
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
708
# 449 0 1122.8030 713.0080 breezy.weave:556(_extract)
708
709
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
710
711
# - a 5% win, or possibly just noise. However with large istacks that
751
752
NOT FOR PUBLIC USE.
753
if isinstance(name_or_index, (int, long)):
754
# GZ 2017-04-01: This used to check for long as well, but I don't think
755
# there are python implementations with sys.maxsize > sys.maxint
756
if isinstance(name_or_index, int):
754
757
return name_or_index
756
759
return self._lookup(name_or_index)
878
881
raise errors.WeaveTextDiffers(name, self, other)
879
882
self_parents = self._parents[this_idx]
880
883
other_parents = other._parents[other_idx]
881
n1 = set([self._names[i] for i in self_parents])
882
n2 = set([other._names[i] for i in other_parents])
884
n1 = {self._names[i] for i in self_parents}
885
n2 = {other._names[i] for i in other_parents}
883
886
if not self._compatible_parents(n1, n2):
884
887
raise WeaveParentMismatch("inconsistent parents "
885
888
"for version {%s}: %s vs %s" % (name, n1, n2))
920
923
self._transport = transport
921
924
self._filemode = filemode
923
_read_weave_v5(self._transport.get(name + WeaveFile.WEAVE_SUFFIX), self)
926
f = self._transport.get(name + WeaveFile.WEAVE_SUFFIX)
927
_read_weave_v5(BytesIO(f.read()), self)
924
928
except errors.NoSuchFile:
940
944
def copy_to(self, name, transport):
941
945
"""See VersionedFile.copy_to()."""
942
946
# as we are all in memory always, just serialise to the new place.
944
948
write_weave_v5(self, sio)
946
950
transport.put_file(name + WeaveFile.WEAVE_SUFFIX, sio, self._filemode)