697
699
# we're still spending ~1/4 of the method in isinstance though.
698
700
# so lets hard code the acceptable string classes we expect:
699
701
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
700
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
702
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
702
704
# yay, down to ~1/4 the initial extract time, and our inline time
703
705
# has shrunk again, with isinstance no longer dominating.
704
706
# tweaking the stack inclusion test to use a set gives:
705
707
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
706
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
708
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
708
710
# - a 5% win, or possibly just noise. However with large istacks that
709
711
# 'in' test could dominate, so I'm leaving this change in place -
710
712
# when its fast enough to consider profiling big datasets we can review.
715
717
for l in self._weave:
716
718
if l.__class__ == tuple:
966
969
super(WeaveFile, self).insert_record_stream(stream)
969
@deprecated_method(one_five)
970
def join(self, other, pb=None, msg=None, version_ids=None,
971
ignore_missing=False):
972
"""Join other into self and save."""
973
super(WeaveFile, self).join(other, pb, msg, version_ids, ignore_missing)
977
973
def _reweave(wa, wb, pb=None, msg=None):
978
974
"""Combine two weaves and return the result.
980
This works even if a revision R has different parents in
976
This works even if a revision R has different parents in
981
977
wa and wb. In the resulting weave all the parents are given.
983
This is done by just building up a new weave, maintaining ordering
979
This is done by just building up a new weave, maintaining ordering
984
980
of the versions in the two inputs. More efficient approaches
985
might be possible but it should only be necessary to do
986
this operation rarely, when a new previously ghost version is
981
might be possible but it should only be necessary to do
982
this operation rarely, when a new previously ghost version is
989
985
:param pb: An optional progress bar, indicating how far done we are
1033
1030
p = combined.setdefault(name, set())
1034
1031
p.update(map(weave._idx_to_name, weave._parents[idx]))
1035
1032
return combined
1039
"""Show the weave's table-of-contents"""
1040
print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
1041
for i in (6, 50, 10, 10):
1044
for i in range(w.num_versions()):
1047
parent_str = ' '.join(map(str, w._parents[i]))
1048
print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
1052
def weave_stats(weave_file, pb):
1053
from bzrlib.weavefile import read_weave
1055
wf = file(weave_file, 'rb')
1057
# FIXME: doesn't work on pipes
1058
weave_size = wf.tell()
1062
for i in range(vers):
1063
pb.update('checking sizes', i, vers)
1064
for origin, lineno, line in w._extract([i]):
1069
print 'versions %9d' % vers
1070
print 'weave file %9d bytes' % weave_size
1071
print 'total contents %9d bytes' % total
1072
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
1075
print 'average size %9d bytes' % avg
1076
print 'relative size %9.2fx' % (float(weave_size) / float(avg))
1080
print """bzr weave tool
1082
Experimental tool for weave algorithm.
1085
weave init WEAVEFILE
1086
Create an empty weave file
1087
weave get WEAVEFILE VERSION
1088
Write out specified version.
1089
weave check WEAVEFILE
1090
Check consistency of all versions.
1092
Display table of contents.
1093
weave add WEAVEFILE NAME [BASE...] < NEWTEXT
1094
Add NEWTEXT, with specified parent versions.
1095
weave annotate WEAVEFILE VERSION
1096
Display origin of each line.
1097
weave merge WEAVEFILE VERSION1 VERSION2 > OUT
1098
Auto-merge two versions and display conflicts.
1099
weave diff WEAVEFILE VERSION1 VERSION2
1100
Show differences between two versions.
1104
% weave init foo.weave
1106
% weave add foo.weave ver0 < foo.txt
1109
(create updated version)
1111
% weave get foo.weave 0 | diff -u - foo.txt
1112
% weave add foo.weave ver1 0 < foo.txt
1115
% weave get foo.weave 0 > foo.txt (create forked version)
1117
% weave add foo.weave ver2 0 < foo.txt
1120
% weave merge foo.weave 1 2 > foo.txt (merge them)
1121
% vi foo.txt (resolve conflicts)
1122
% weave add foo.weave merged 1 2 < foo.txt (commit merged version)
1134
# in case we're run directly from the subdirectory
1135
sys.path.append('..')
1137
from bzrlib.weavefile import write_weave, read_weave
1138
from bzrlib.progress import ProgressBar
1153
return read_weave(file(argv[2], 'rb'))
1159
# at the moment, based on everything in the file
1161
parents = map(int, argv[4:])
1162
lines = sys.stdin.readlines()
1163
ver = w.add(name, parents, lines)
1164
write_weave(w, file(argv[2], 'wb'))
1165
print 'added version %r %d' % (name, ver)
1168
if os.path.exists(fn):
1169
raise IOError("file exists")
1171
write_weave(w, file(fn, 'wb'))
1172
elif cmd == 'get': # get one version
1174
sys.stdout.writelines(w.get_iter(int(argv[3])))
1179
v1, v2 = map(int, argv[3:5])
1182
diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
1183
'%s version %d' % (fn, v1),
1184
'%s version %d' % (fn, v2))
1185
sys.stdout.writelines(diff_gen)
1187
elif cmd == 'annotate':
1189
# newline is added to all lines regardless; too hard to get
1190
# reasonable formatting otherwise
1192
for origin, text in w.annotate(int(argv[3])):
1193
text = text.rstrip('\r\n')
1195
print ' | %s' % (text)
1197
print '%5d | %s' % (origin, text)
1203
elif cmd == 'stats':
1204
weave_stats(argv[2], ProgressBar())
1206
elif cmd == 'check':
1211
print '%d versions ok' % w.num_versions()
1213
elif cmd == 'inclusions':
1215
print ' '.join(map(str, w.inclusions([int(argv[3])])))
1217
elif cmd == 'parents':
1219
print ' '.join(map(str, w._parents[int(argv[3])]))
1221
elif cmd == 'plan-merge':
1222
# replaced by 'bzr weave-plan-merge'
1224
for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
1226
print '%14s | %s' % (state, line),
1227
elif cmd == 'merge':
1228
# replaced by 'bzr weave-merge-text'
1230
p = w.plan_merge(int(argv[3]), int(argv[4]))
1231
sys.stdout.writelines(w.weave_merge(p))
1233
raise ValueError('unknown command %r' % cmd)
1236
if __name__ == '__main__':
1238
sys.exit(main(sys.argv))