71
71
# properly nested, that there is no text outside of an insertion, that
72
72
# insertions or deletions are not repeated, etc.
74
# TODO: Make the info command just show info, not extract everything:
75
# it can be much faster.
77
# TODO: Perhaps use long integers as sets instead of set objects; may
74
80
# TODO: Parallel-extract that passes back each line along with a
75
81
# description of which revisions include it. Nice for checking all
76
82
# shas in parallel.
107
113
the version-id is used to reference it in the larger world.
109
115
The weave is represented as a list mixing edit instructions and
110
literal text. Each entry in _weave can be either a string (or
116
literal text. Each entry in _l can be either a string (or
111
117
unicode), or a tuple. If a string, it means that the given line
112
118
should be output in the currently active revisions.
151
157
should be no way to get an earlier version deleting a later
155
Text of the weave; list of control instruction tuples and strings.
158
164
List of parents, indexed by version number.
159
165
It is only necessary to store the minimal set of parents for
160
166
each version; the parent's parents are implied.
163
169
List of hex SHA-1 of each version, or None if not recorded.
166
__slots__ = ['_weave', '_parents', '_sha1s']
172
## __slots__ = ['_l', '_v', '_sha1s']
168
174
def __init__(self):
174
180
def __eq__(self, other):
175
181
if not isinstance(other, Weave):
177
return self._parents == other._parents \
178
and self._weave == other._weave
183
return self._v == other._v \
184
and self._l == other._l
181
187
def __ne__(self, other):
214
220
# even more specially, if we're adding an empty text we
215
221
# need do nothing at all.
217
self._weave.append(('{', new_version))
218
self._weave.extend(text)
219
self._weave.append(('}', new_version))
223
self._l.append(('{', new_version))
225
self._l.append(('}', new_version))
221
227
return new_version
243
249
return new_version
245
251
# add a sentinal, because we can also match against the final line
246
basis_lineno.append(len(self._weave))
252
basis_lineno.append(len(self._l))
248
254
# XXX: which line of the weave should we really consider
249
255
# matches the end of the file? the current code says it's the
277
283
# the deletion and insertion are handled separately.
278
284
# first delete the region.
280
self._weave.insert(i1+offset, ('[', new_version))
281
self._weave.insert(i2+offset+1, (']', new_version))
286
self._l.insert(i1+offset, ('[', new_version))
287
self._l.insert(i2+offset+1, (']', new_version))
286
292
# i2; we want to insert after this region to make sure
287
293
# we don't destroy ourselves
289
self._weave[i:i] = ([('{', new_version)]
295
self._l[i:i] = ([('{', new_version)]
291
297
+ [('}', new_version)])
292
298
offset += 2 + (j2 - j1)
312
318
def minimal_parents(self, version):
313
319
"""Find the minimal set of parents for the version."""
314
included = self._parents[version]
320
included = self._v[version]
480
486
def dump(self, to_file):
481
487
from pprint import pprint
482
print >>to_file, "Weave._weave = ",
483
pprint(self._weave, to_file)
484
print >>to_file, "Weave._parents = ",
485
pprint(self._parents, to_file)
488
print >>to_file, "Weave._l = ",
489
pprint(self._l, to_file)
490
print >>to_file, "Weave._v = ",
491
pprint(self._v, to_file)
489
495
def numversions(self):
490
l = len(self._parents)
491
497
assert l == len(self._sha1s)
496
return self.numversions()
499
501
def check(self, progress_bar=None):
500
502
# check no circular inclusions
501
503
for version in range(self.numversions()):
502
inclusions = list(self._parents[version])
504
inclusions = list(self._v[version])
504
506
inclusions.sort()
505
507
if inclusions[-1] >= version:
675
def weave_info(filename, out):
674
676
"""Show some text information about the weave."""
675
print '%6s %40s %20s' % ('ver', 'sha1', 'parents')
676
for i in (6, 40, 20):
679
for i in range(w.numversions()):
681
print '%6d %40s %s' % (i, sha1, ' '.join(map(str, w._parents[i])))
685
def weave_stats(weave_file):
686
from bzrlib.progress import ProgressBar
687
from bzrlib.weavefile import read_weave
691
wf = file(weave_file, 'rb')
677
from weavefile import read_weave
678
wf = file(filename, 'rb')
692
679
w = read_weave(wf)
693
680
# FIXME: doesn't work on pipes
694
681
weave_size = wf.tell()
682
print >>out, "weave file size %d bytes" % weave_size
683
print >>out, "weave contains %d versions" % len(w._v)
698
for i in range(vers):
699
pb.update('checking sizes', i, vers)
700
for line in w.get_iter(i):
705
print 'versions %9d' % vers
706
print 'weave file %9d bytes' % weave_size
707
print 'total contents %9d bytes' % total
708
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
686
print '%6s %6s %8s %40s %20s' % ('ver', 'lines', 'bytes', 'sha1', 'parents')
687
for i in (6, 6, 8, 40, 20):
690
for i in range(len(w._v)):
693
bytes = sum((len(a) for a in text))
695
print '%6d %6d %8d %40s' % (i, lines, bytes, sha1),
701
print >>out, "versions total %d bytes" % total
702
print >>out, "compression ratio %.3f" % (float(total)/float(weave_size))