701
704
# we're still spending ~1/4 of the method in isinstance though.
702
705
# so lets hard code the acceptable string classes we expect:
703
706
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
704
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
707
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
706
709
# yay, down to ~1/4 the initial extract time, and our inline time
707
710
# has shrunk again, with isinstance no longer dominating.
708
711
# tweaking the stack inclusion test to use a set gives:
709
712
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
710
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
713
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
712
715
# - a 5% win, or possibly just noise. However with large istacks that
713
716
# 'in' test could dominate, so I'm leaving this change in place -
714
717
# when its fast enough to consider profiling big datasets we can review.
719
722
for l in self._weave:
720
723
if l.__class__ == tuple:
970
973
super(WeaveFile, self).insert_record_stream(stream)
973
@deprecated_method(one_five)
974
def join(self, other, pb=None, msg=None, version_ids=None,
975
ignore_missing=False):
976
"""Join other into self and save."""
977
super(WeaveFile, self).join(other, pb, msg, version_ids, ignore_missing)
981
977
def _reweave(wa, wb, pb=None, msg=None):
982
978
"""Combine two weaves and return the result.
984
This works even if a revision R has different parents in
980
This works even if a revision R has different parents in
985
981
wa and wb. In the resulting weave all the parents are given.
987
This is done by just building up a new weave, maintaining ordering
983
This is done by just building up a new weave, maintaining ordering
988
984
of the versions in the two inputs. More efficient approaches
989
might be possible but it should only be necessary to do
990
this operation rarely, when a new previously ghost version is
985
might be possible but it should only be necessary to do
986
this operation rarely, when a new previously ghost version is
993
989
:param pb: An optional progress bar, indicating how far done we are
1037
1034
p = combined.setdefault(name, set())
1038
1035
p.update(map(weave._idx_to_name, weave._parents[idx]))
1039
1036
return combined
1043
"""Show the weave's table-of-contents"""
1044
print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
1045
for i in (6, 50, 10, 10):
1048
for i in range(w.num_versions()):
1051
parent_str = ' '.join(map(str, w._parents[i]))
1052
print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
1056
def weave_stats(weave_file, pb):
1057
from bzrlib.weavefile import read_weave
1059
wf = file(weave_file, 'rb')
1061
# FIXME: doesn't work on pipes
1062
weave_size = wf.tell()
1066
for i in range(vers):
1067
pb.update('checking sizes', i, vers)
1068
for origin, lineno, line in w._extract([i]):
1073
print 'versions %9d' % vers
1074
print 'weave file %9d bytes' % weave_size
1075
print 'total contents %9d bytes' % total
1076
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
1079
print 'average size %9d bytes' % avg
1080
print 'relative size %9.2fx' % (float(weave_size) / float(avg))
1084
print """bzr weave tool
1086
Experimental tool for weave algorithm.
1089
weave init WEAVEFILE
1090
Create an empty weave file
1091
weave get WEAVEFILE VERSION
1092
Write out specified version.
1093
weave check WEAVEFILE
1094
Check consistency of all versions.
1096
Display table of contents.
1097
weave add WEAVEFILE NAME [BASE...] < NEWTEXT
1098
Add NEWTEXT, with specified parent versions.
1099
weave annotate WEAVEFILE VERSION
1100
Display origin of each line.
1101
weave merge WEAVEFILE VERSION1 VERSION2 > OUT
1102
Auto-merge two versions and display conflicts.
1103
weave diff WEAVEFILE VERSION1 VERSION2
1104
Show differences between two versions.
1108
% weave init foo.weave
1110
% weave add foo.weave ver0 < foo.txt
1113
(create updated version)
1115
% weave get foo.weave 0 | diff -u - foo.txt
1116
% weave add foo.weave ver1 0 < foo.txt
1119
% weave get foo.weave 0 > foo.txt (create forked version)
1121
% weave add foo.weave ver2 0 < foo.txt
1124
% weave merge foo.weave 1 2 > foo.txt (merge them)
1125
% vi foo.txt (resolve conflicts)
1126
% weave add foo.weave merged 1 2 < foo.txt (commit merged version)
1138
# in case we're run directly from the subdirectory
1139
sys.path.append('..')
1141
from bzrlib.weavefile import write_weave, read_weave
1142
from bzrlib.progress import ProgressBar
1157
return read_weave(file(argv[2], 'rb'))
1163
# at the moment, based on everything in the file
1165
parents = map(int, argv[4:])
1166
lines = sys.stdin.readlines()
1167
ver = w.add(name, parents, lines)
1168
write_weave(w, file(argv[2], 'wb'))
1169
print 'added version %r %d' % (name, ver)
1172
if os.path.exists(fn):
1173
raise IOError("file exists")
1175
write_weave(w, file(fn, 'wb'))
1176
elif cmd == 'get': # get one version
1178
sys.stdout.writelines(w.get_iter(int(argv[3])))
1183
v1, v2 = map(int, argv[3:5])
1186
diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
1187
'%s version %d' % (fn, v1),
1188
'%s version %d' % (fn, v2))
1189
sys.stdout.writelines(diff_gen)
1191
elif cmd == 'annotate':
1193
# newline is added to all lines regardless; too hard to get
1194
# reasonable formatting otherwise
1196
for origin, text in w.annotate(int(argv[3])):
1197
text = text.rstrip('\r\n')
1199
print ' | %s' % (text)
1201
print '%5d | %s' % (origin, text)
1207
elif cmd == 'stats':
1208
weave_stats(argv[2], ProgressBar())
1210
elif cmd == 'check':
1215
print '%d versions ok' % w.num_versions()
1217
elif cmd == 'inclusions':
1219
print ' '.join(map(str, w.inclusions([int(argv[3])])))
1221
elif cmd == 'parents':
1223
print ' '.join(map(str, w._parents[int(argv[3])]))
1225
elif cmd == 'plan-merge':
1226
# replaced by 'bzr weave-plan-merge'
1228
for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
1230
print '%14s | %s' % (state, line),
1231
elif cmd == 'merge':
1232
# replaced by 'bzr weave-merge-text'
1234
p = w.plan_merge(int(argv[3]), int(argv[4]))
1235
sys.stdout.writelines(w.weave_merge(p))
1237
raise ValueError('unknown command %r' % cmd)
1240
if __name__ == '__main__':
1242
sys.exit(main(sys.argv))