699
697
# we're still spending ~1/4 of the method in isinstance though.
700
698
# so lets hard code the acceptable string classes we expect:
701
699
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
702
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
700
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
704
702
# yay, down to ~1/4 the initial extract time, and our inline time
705
703
# has shrunk again, with isinstance no longer dominating.
706
704
# tweaking the stack inclusion test to use a set gives:
707
705
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
708
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
706
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
710
708
# - a 5% win, or possibly just noise. However with large istacks that
711
709
# 'in' test could dominate, so I'm leaving this change in place -
712
710
# when its fast enough to consider profiling big datasets we can review.
717
715
for l in self._weave:
718
716
if l.__class__ == tuple:
968
966
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)
972
977
def _reweave(wa, wb, pb=None, msg=None):
973
978
"""Combine two weaves and return the result.
975
This works even if a revision R has different parents in
980
This works even if a revision R has different parents in
976
981
wa and wb. In the resulting weave all the parents are given.
978
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
979
984
of the versions in the two inputs. More efficient approaches
980
might be possible but it should only be necessary to do
981
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
984
989
:param pb: An optional progress bar, indicating how far done we are
1029
1033
p = combined.setdefault(name, set())
1030
1034
p.update(map(weave._idx_to_name, weave._parents[idx]))
1031
1035
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))