699
700
# we're still spending ~1/4 of the method in isinstance though.
700
701
# so lets hard code the acceptable string classes we expect:
701
702
# 449 0 1202.9420 786.2930 bzrlib.weave:556(_extract)
702
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
703
# +71352 0 377.5560 377.5560 +<method 'append' of 'list'
704
705
# yay, down to ~1/4 the initial extract time, and our inline time
705
706
# has shrunk again, with isinstance no longer dominating.
706
707
# tweaking the stack inclusion test to use a set gives:
707
708
# 449 0 1122.8030 713.0080 bzrlib.weave:556(_extract)
708
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
709
# +71352 0 354.9980 354.9980 +<method 'append' of 'list'
710
711
# - a 5% win, or possibly just noise. However with large istacks that
711
712
# 'in' test could dominate, so I'm leaving this change in place -
712
713
# when its fast enough to consider profiling big datasets we can review.
717
718
for l in self._weave:
718
719
if l.__class__ == tuple:
968
969
super(WeaveFile, self).insert_record_stream(stream)
972
@deprecated_method(one_five)
973
def join(self, other, pb=None, msg=None, version_ids=None,
974
ignore_missing=False):
975
"""Join other into self and save."""
976
super(WeaveFile, self).join(other, pb, msg, version_ids, ignore_missing)
972
980
def _reweave(wa, wb, pb=None, msg=None):
973
981
"""Combine two weaves and return the result.
975
This works even if a revision R has different parents in
983
This works even if a revision R has different parents in
976
984
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
986
This is done by just building up a new weave, maintaining ordering
979
987
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
988
might be possible but it should only be necessary to do
989
this operation rarely, when a new previously ghost version is
984
992
:param pb: An optional progress bar, indicating how far done we are
1029
1036
p = combined.setdefault(name, set())
1030
1037
p.update(map(weave._idx_to_name, weave._parents[idx]))
1031
1038
return combined
1042
"""Show the weave's table-of-contents"""
1043
print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
1044
for i in (6, 50, 10, 10):
1047
for i in range(w.num_versions()):
1050
parent_str = ' '.join(map(str, w._parents[i]))
1051
print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
1055
def weave_stats(weave_file, pb):
1056
from bzrlib.weavefile import read_weave
1058
wf = file(weave_file, 'rb')
1060
# FIXME: doesn't work on pipes
1061
weave_size = wf.tell()
1065
for i in range(vers):
1066
pb.update('checking sizes', i, vers)
1067
for origin, lineno, line in w._extract([i]):
1072
print 'versions %9d' % vers
1073
print 'weave file %9d bytes' % weave_size
1074
print 'total contents %9d bytes' % total
1075
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
1078
print 'average size %9d bytes' % avg
1079
print 'relative size %9.2fx' % (float(weave_size) / float(avg))
1083
print """bzr weave tool
1085
Experimental tool for weave algorithm.
1088
weave init WEAVEFILE
1089
Create an empty weave file
1090
weave get WEAVEFILE VERSION
1091
Write out specified version.
1092
weave check WEAVEFILE
1093
Check consistency of all versions.
1095
Display table of contents.
1096
weave add WEAVEFILE NAME [BASE...] < NEWTEXT
1097
Add NEWTEXT, with specified parent versions.
1098
weave annotate WEAVEFILE VERSION
1099
Display origin of each line.
1100
weave merge WEAVEFILE VERSION1 VERSION2 > OUT
1101
Auto-merge two versions and display conflicts.
1102
weave diff WEAVEFILE VERSION1 VERSION2
1103
Show differences between two versions.
1107
% weave init foo.weave
1109
% weave add foo.weave ver0 < foo.txt
1112
(create updated version)
1114
% weave get foo.weave 0 | diff -u - foo.txt
1115
% weave add foo.weave ver1 0 < foo.txt
1118
% weave get foo.weave 0 > foo.txt (create forked version)
1120
% weave add foo.weave ver2 0 < foo.txt
1123
% weave merge foo.weave 1 2 > foo.txt (merge them)
1124
% vi foo.txt (resolve conflicts)
1125
% weave add foo.weave merged 1 2 < foo.txt (commit merged version)
1137
# in case we're run directly from the subdirectory
1138
sys.path.append('..')
1140
from bzrlib.weavefile import write_weave, read_weave
1141
from bzrlib.progress import ProgressBar
1156
return read_weave(file(argv[2], 'rb'))
1162
# at the moment, based on everything in the file
1164
parents = map(int, argv[4:])
1165
lines = sys.stdin.readlines()
1166
ver = w.add(name, parents, lines)
1167
write_weave(w, file(argv[2], 'wb'))
1168
print 'added version %r %d' % (name, ver)
1171
if os.path.exists(fn):
1172
raise IOError("file exists")
1174
write_weave(w, file(fn, 'wb'))
1175
elif cmd == 'get': # get one version
1177
sys.stdout.writelines(w.get_iter(int(argv[3])))
1182
v1, v2 = map(int, argv[3:5])
1185
diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
1186
'%s version %d' % (fn, v1),
1187
'%s version %d' % (fn, v2))
1188
sys.stdout.writelines(diff_gen)
1190
elif cmd == 'annotate':
1192
# newline is added to all lines regardless; too hard to get
1193
# reasonable formatting otherwise
1195
for origin, text in w.annotate(int(argv[3])):
1196
text = text.rstrip('\r\n')
1198
print ' | %s' % (text)
1200
print '%5d | %s' % (origin, text)
1206
elif cmd == 'stats':
1207
weave_stats(argv[2], ProgressBar())
1209
elif cmd == 'check':
1214
print '%d versions ok' % w.num_versions()
1216
elif cmd == 'inclusions':
1218
print ' '.join(map(str, w.inclusions([int(argv[3])])))
1220
elif cmd == 'parents':
1222
print ' '.join(map(str, w._parents[int(argv[3])]))
1224
elif cmd == 'plan-merge':
1225
# replaced by 'bzr weave-plan-merge'
1227
for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
1229
print '%14s | %s' % (state, line),
1230
elif cmd == 'merge':
1231
# replaced by 'bzr weave-merge-text'
1233
p = w.plan_merge(int(argv[3]), int(argv[4]))
1234
sys.stdout.writelines(w.weave_merge(p))
1236
raise ValueError('unknown command %r' % cmd)
1239
if __name__ == '__main__':
1241
sys.exit(main(sys.argv))