694
704
# we're still spending ~1/4 of the method in isinstance though.
695
705
# so lets hard code the acceptable string classes we expect:
696
706
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
697
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
707
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
699
709
# yay, down to ~1/4 the initial extract time, and our inline time
700
710
# has shrunk again, with isinstance no longer dominating.
701
711
# tweaking the stack inclusion test to use a set gives:
702
712
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
703
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
713
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
705
715
# - a 5% win, or possibly just noise. However with large istacks that
706
716
# 'in' test could dominate, so I'm leaving this change in place -
707
717
# when its fast enough to consider profiling big datasets we can review.
712
722
for l in self._weave:
713
723
if l.__class__ == tuple:
963
973
super(WeaveFile, self).insert_record_stream(stream)
966
@deprecated_method(one_five)
967
def join(self, other, pb=None, msg=None, version_ids=None,
968
ignore_missing=False):
969
"""Join other into self and save."""
970
super(WeaveFile, self).join(other, pb, msg, version_ids, ignore_missing)
974
977
def _reweave(wa, wb, pb=None, msg=None):
975
978
"""Combine two weaves and return the result.
977
This works even if a revision R has different parents in
980
This works even if a revision R has different parents in
978
981
wa and wb. In the resulting weave all the parents are given.
980
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
981
984
of the versions in the two inputs. More efficient approaches
982
might be possible but it should only be necessary to do
983
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
986
989
:param pb: An optional progress bar, indicating how far done we are
1030
1034
p = combined.setdefault(name, set())
1031
1035
p.update(map(weave._idx_to_name, weave._parents[idx]))
1032
1036
return combined
1036
"""Show the weave's table-of-contents"""
1037
print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
1038
for i in (6, 50, 10, 10):
1041
for i in range(w.num_versions()):
1044
parent_str = ' '.join(map(str, w._parents[i]))
1045
print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
1049
def weave_stats(weave_file, pb):
1050
from bzrlib.weavefile import read_weave
1052
wf = file(weave_file, 'rb')
1054
# FIXME: doesn't work on pipes
1055
weave_size = wf.tell()
1059
for i in range(vers):
1060
pb.update('checking sizes', i, vers)
1061
for origin, lineno, line in w._extract([i]):
1066
print 'versions %9d' % vers
1067
print 'weave file %9d bytes' % weave_size
1068
print 'total contents %9d bytes' % total
1069
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
1072
print 'average size %9d bytes' % avg
1073
print 'relative size %9.2fx' % (float(weave_size) / float(avg))
1077
print """bzr weave tool
1079
Experimental tool for weave algorithm.
1082
weave init WEAVEFILE
1083
Create an empty weave file
1084
weave get WEAVEFILE VERSION
1085
Write out specified version.
1086
weave check WEAVEFILE
1087
Check consistency of all versions.
1089
Display table of contents.
1090
weave add WEAVEFILE NAME [BASE...] < NEWTEXT
1091
Add NEWTEXT, with specified parent versions.
1092
weave annotate WEAVEFILE VERSION
1093
Display origin of each line.
1094
weave merge WEAVEFILE VERSION1 VERSION2 > OUT
1095
Auto-merge two versions and display conflicts.
1096
weave diff WEAVEFILE VERSION1 VERSION2
1097
Show differences between two versions.
1101
% weave init foo.weave
1103
% weave add foo.weave ver0 < foo.txt
1106
(create updated version)
1108
% weave get foo.weave 0 | diff -u - foo.txt
1109
% weave add foo.weave ver1 0 < foo.txt
1112
% weave get foo.weave 0 > foo.txt (create forked version)
1114
% weave add foo.weave ver2 0 < foo.txt
1117
% weave merge foo.weave 1 2 > foo.txt (merge them)
1118
% vi foo.txt (resolve conflicts)
1119
% weave add foo.weave merged 1 2 < foo.txt (commit merged version)
1131
# in case we're run directly from the subdirectory
1132
sys.path.append('..')
1134
from bzrlib.weavefile import write_weave, read_weave
1135
from bzrlib.progress import ProgressBar
1150
return read_weave(file(argv[2], 'rb'))
1156
# at the moment, based on everything in the file
1158
parents = map(int, argv[4:])
1159
lines = sys.stdin.readlines()
1160
ver = w.add(name, parents, lines)
1161
write_weave(w, file(argv[2], 'wb'))
1162
print 'added version %r %d' % (name, ver)
1165
if os.path.exists(fn):
1166
raise IOError("file exists")
1168
write_weave(w, file(fn, 'wb'))
1169
elif cmd == 'get': # get one version
1171
sys.stdout.writelines(w.get_iter(int(argv[3])))
1176
v1, v2 = map(int, argv[3:5])
1179
diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
1180
'%s version %d' % (fn, v1),
1181
'%s version %d' % (fn, v2))
1182
sys.stdout.writelines(diff_gen)
1184
elif cmd == 'annotate':
1186
# newline is added to all lines regardless; too hard to get
1187
# reasonable formatting otherwise
1189
for origin, text in w.annotate(int(argv[3])):
1190
text = text.rstrip('\r\n')
1192
print ' | %s' % (text)
1194
print '%5d | %s' % (origin, text)
1200
elif cmd == 'stats':
1201
weave_stats(argv[2], ProgressBar())
1203
elif cmd == 'check':
1208
print '%d versions ok' % w.num_versions()
1210
elif cmd == 'inclusions':
1212
print ' '.join(map(str, w.inclusions([int(argv[3])])))
1214
elif cmd == 'parents':
1216
print ' '.join(map(str, w._parents[int(argv[3])]))
1218
elif cmd == 'plan-merge':
1219
# replaced by 'bzr weave-plan-merge'
1221
for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
1223
print '%14s | %s' % (state, line),
1224
elif cmd == 'merge':
1225
# replaced by 'bzr weave-merge-text'
1227
p = w.plan_merge(int(argv[3]), int(argv[4]))
1228
sys.stdout.writelines(w.weave_merge(p))
1230
raise ValueError('unknown command %r' % cmd)
1233
if __name__ == '__main__':
1235
sys.exit(main(sys.argv))