216
220
__slots__ = ['_weave', '_parents', '_sha1s', '_names', '_name_map',
217
'_weave_name', '_matcher']
219
def __init__(self, weave_name=None, access_mode='w', matcher=None, get_scope=None):
221
'_weave_name', '_matcher', '_allow_reserved']
223
def __init__(self, weave_name=None, access_mode='w', matcher=None,
224
get_scope=None, allow_reserved=False):
220
225
"""Create a weave.
222
227
:param get_scope: A callable that returns an opaque object to be used
223
228
for detecting when this weave goes out of scope (should stop
224
229
answering requests or allowing mutation).
226
super(Weave, self).__init__(access_mode)
231
super(Weave, self).__init__()
228
233
self._parents = []
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:
962
973
super(WeaveFile, self).insert_record_stream(stream)
965
@deprecated_method(one_five)
966
def join(self, other, pb=None, msg=None, version_ids=None,
967
ignore_missing=False):
968
"""Join other into self and save."""
969
super(WeaveFile, self).join(other, pb, msg, version_ids, ignore_missing)
973
977
def _reweave(wa, wb, pb=None, msg=None):
974
978
"""Combine two weaves and return the result.
976
This works even if a revision R has different parents in
980
This works even if a revision R has different parents in
977
981
wa and wb. In the resulting weave all the parents are given.
979
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
980
984
of the versions in the two inputs. More efficient approaches
981
might be possible but it should only be necessary to do
982
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
985
989
:param pb: An optional progress bar, indicating how far done we are
1029
1034
p = combined.setdefault(name, set())
1030
1035
p.update(map(weave._idx_to_name, weave._parents[idx]))
1031
1036
return combined
1035
"""Show the weave's table-of-contents"""
1036
print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
1037
for i in (6, 50, 10, 10):
1040
for i in range(w.num_versions()):
1043
parent_str = ' '.join(map(str, w._parents[i]))
1044
print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
1048
def weave_stats(weave_file, pb):
1049
from bzrlib.weavefile import read_weave
1051
wf = file(weave_file, 'rb')
1053
# FIXME: doesn't work on pipes
1054
weave_size = wf.tell()
1058
for i in range(vers):
1059
pb.update('checking sizes', i, vers)
1060
for origin, lineno, line in w._extract([i]):
1065
print 'versions %9d' % vers
1066
print 'weave file %9d bytes' % weave_size
1067
print 'total contents %9d bytes' % total
1068
print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
1071
print 'average size %9d bytes' % avg
1072
print 'relative size %9.2fx' % (float(weave_size) / float(avg))
1076
print """bzr weave tool
1078
Experimental tool for weave algorithm.
1081
weave init WEAVEFILE
1082
Create an empty weave file
1083
weave get WEAVEFILE VERSION
1084
Write out specified version.
1085
weave check WEAVEFILE
1086
Check consistency of all versions.
1088
Display table of contents.
1089
weave add WEAVEFILE NAME [BASE...] < NEWTEXT
1090
Add NEWTEXT, with specified parent versions.
1091
weave annotate WEAVEFILE VERSION
1092
Display origin of each line.
1093
weave merge WEAVEFILE VERSION1 VERSION2 > OUT
1094
Auto-merge two versions and display conflicts.
1095
weave diff WEAVEFILE VERSION1 VERSION2
1096
Show differences between two versions.
1100
% weave init foo.weave
1102
% weave add foo.weave ver0 < foo.txt
1105
(create updated version)
1107
% weave get foo.weave 0 | diff -u - foo.txt
1108
% weave add foo.weave ver1 0 < foo.txt
1111
% weave get foo.weave 0 > foo.txt (create forked version)
1113
% weave add foo.weave ver2 0 < foo.txt
1116
% weave merge foo.weave 1 2 > foo.txt (merge them)
1117
% vi foo.txt (resolve conflicts)
1118
% weave add foo.weave merged 1 2 < foo.txt (commit merged version)
1130
# in case we're run directly from the subdirectory
1131
sys.path.append('..')
1133
from bzrlib.weavefile import write_weave, read_weave
1134
from bzrlib.progress import ProgressBar
1149
return read_weave(file(argv[2], 'rb'))
1155
# at the moment, based on everything in the file
1157
parents = map(int, argv[4:])
1158
lines = sys.stdin.readlines()
1159
ver = w.add(name, parents, lines)
1160
write_weave(w, file(argv[2], 'wb'))
1161
print 'added version %r %d' % (name, ver)
1164
if os.path.exists(fn):
1165
raise IOError("file exists")
1167
write_weave(w, file(fn, 'wb'))
1168
elif cmd == 'get': # get one version
1170
sys.stdout.writelines(w.get_iter(int(argv[3])))
1175
v1, v2 = map(int, argv[3:5])
1178
diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
1179
'%s version %d' % (fn, v1),
1180
'%s version %d' % (fn, v2))
1181
sys.stdout.writelines(diff_gen)
1183
elif cmd == 'annotate':
1185
# newline is added to all lines regardless; too hard to get
1186
# reasonable formatting otherwise
1188
for origin, text in w.annotate(int(argv[3])):
1189
text = text.rstrip('\r\n')
1191
print ' | %s' % (text)
1193
print '%5d | %s' % (origin, text)
1199
elif cmd == 'stats':
1200
weave_stats(argv[2], ProgressBar())
1202
elif cmd == 'check':
1207
print '%d versions ok' % w.num_versions()
1209
elif cmd == 'inclusions':
1211
print ' '.join(map(str, w.inclusions([int(argv[3])])))
1213
elif cmd == 'parents':
1215
print ' '.join(map(str, w._parents[int(argv[3])]))
1217
elif cmd == 'plan-merge':
1218
# replaced by 'bzr weave-plan-merge'
1220
for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
1222
print '%14s | %s' % (state, line),
1223
elif cmd == 'merge':
1224
# replaced by 'bzr weave-merge-text'
1226
p = w.plan_merge(int(argv[3]), int(argv[4]))
1227
sys.stdout.writelines(w.weave_merge(p))
1229
raise ValueError('unknown command %r' % cmd)
1232
if __name__ == '__main__':
1234
sys.exit(main(sys.argv))