704
701
# we're still spending ~1/4 of the method in isinstance though.
705
702
# so lets hard code the acceptable string classes we expect:
706
703
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
707
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
704
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
709
706
# yay, down to ~1/4 the initial extract time, and our inline time
710
707
# has shrunk again, with isinstance no longer dominating.
711
708
# tweaking the stack inclusion test to use a set gives:
712
709
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
713
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
710
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
715
712
# - a 5% win, or possibly just noise. However with large istacks that
716
713
# 'in' test could dominate, so I'm leaving this change in place -
717
714
# when its fast enough to consider profiling big datasets we can review.
722
719
for l in self._weave:
723
720
if l.__class__ == tuple:
973
970
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)
977
981
def _reweave(wa, wb, pb=None, msg=None):
978
982
"""Combine two weaves and return the result.
980
This works even if a revision R has different parents in
984
This works even if a revision R has different parents in
981
985
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
987
This is done by just building up a new weave, maintaining ordering
984
988
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
989
might be possible but it should only be necessary to do
990
this operation rarely, when a new previously ghost version is
989
993
:param pb: An optional progress bar, indicating how far done we are
1034
1037
p = combined.setdefault(name, set())
1035
1038
p.update(map(weave._idx_to_name, weave._parents[idx]))
1036
1039
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))