3
# Copyright (C) 2005 Canonical Ltd
1
# Copyright (C) 2005-2010 Canonical Ltd
5
3
# This program is free software; you can redistribute it and/or modify
6
4
# it under the terms of the GNU General Public License as published by
7
5
# the Free Software Foundation; either version 2 of the License, or
8
6
# (at your option) any later version.
10
8
# This program is distributed in the hope that it will be useful,
11
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
11
# GNU General Public License for more details.
15
13
# You should have received a copy of the GNU General Public License
16
14
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
17
# Author: Martin Pool <mbp@canonical.com>
24
19
"""Store and retrieve weaves in files.
26
21
There is one format marker followed by a blank line, followed by a
27
22
series of version headers, followed by the weave itself.
29
Each version marker has 'v' and the version, then 'i' and the included
24
Each version marker has
26
'i' parent version indexes
30
The inclusions do not need to list versions included by a parent.
32
32
The weave is bracketed by 'w' and 'W' lines, and includes the '{}[]'
33
33
processing instructions. Lines of text are prefixed by '.' if the
34
34
line contains a newline, or ',' if not.
37
from __future__ import absolute_import
37
39
# TODO: When extracting a single version it'd be enough to just pass
38
# an iterator returning the weave lines...
40
FORMAT_1 = '# bzr weave file v1\n'
40
# an iterator returning the weave lines... We don't really need to
41
# deserialize it into memory.
43
FORMAT_1 = '# bzr weave file v5\n'
44
46
def write_weave(weave, f, format=None):
45
if format == None or format == 1:
46
return write_weave_v1(weave, f)
47
if format is None or format == 1:
48
return write_weave_v5(weave, f)
48
50
raise ValueError("unknown weave format %r" % format)
51
def write_weave_v1(weave, f):
53
def write_weave_v5(weave, f):
52
54
"""Write weave to file f."""
55
for version, included in enumerate(weave._v):
56
print >>f, 'v', version
57
for version, included in enumerate(weave._parents):
58
included = list(included)
60
assert included[0] >= 0
61
assert included[-1] < version
59
# mininc = weave.minimal_parents(version)
62
f.write(' '.join(str(i) for i in mininc))
66
f.write('1 ' + weave._sha1s[version] + '\n')
67
f.write('n ' + weave._names[version] + '\n')
72
for l in weave._weave:
73
73
if isinstance(l, tuple):
75
print >>f, '%s %d' % l
77
f.write('%s %d\n' % l)
79
81
elif l[-1] == '\n':
80
assert l.find('\n', 0, -1) == -1
83
assert l.find('\n') == -1
84
f.write(', ' + l + '\n')
91
return read_weave_v1(f)
95
from weave import Weave, WeaveFormatError
98
wfe = WeaveFormatError
91
# FIXME: detect the weave type and dispatch
92
from bzrlib.weave import Weave
93
w = Weave(getattr(f, 'name', None))
98
def _read_weave_v5(f, w):
99
"""Private helper routine to read a weave format 5 file into memory.
101
This is only to be used by read_weave and WeaveFile.__init__.
103
# 200 0 2075.5080 1084.0360 bzrlib.weavefile:104(_read_weave_v5)
104
# +60412 0 366.5900 366.5900 +<method 'readline' of 'file' objects>
105
# +59982 0 320.5280 320.5280 +<method 'startswith' of 'str' objects>
106
# +59363 0 297.8080 297.8080 +<method 'append' of 'list' objects>
107
# replace readline call with iter over all lines ->
108
# safe because we already suck on memory.
109
# 200 0 1492.7170 802.6220 bzrlib.weavefile:104(_read_weave_v5)
110
# +59982 0 329.9100 329.9100 +<method 'startswith' of 'str' objects>
111
# +59363 0 320.2980 320.2980 +<method 'append' of 'list' objects>
112
# replaced startswith with slice lookups:
113
# 200 0 851.7250 501.1120 bzrlib.weavefile:104(_read_weave_v5)
114
# +59363 0 311.8780 311.8780 +<method 'append' of 'list' objects>
115
# +200 0 30.2500 30.2500 +<method 'readlines' of 'file' objects>
117
from bzrlib.weave import WeaveFormatError
120
lines = iter(f.readlines())
126
except StopIteration:
127
raise WeaveFormatError('invalid weave file: no header')
100
129
if l != FORMAT_1:
101
130
raise WeaveFormatError('invalid weave file header: %r' % l)
106
if l.startswith('v '):
109
raise WeaveFormatError('version %d!=%d out of order'
113
l = f.readline()[:-1]
115
raise WeaveFormatError('unexpected line %r' % l)
117
included = map(int, l[2:].split(' '))
118
w._addversion(included)
138
w._parents.append(map(int, l[2:].split(' ')))
121
assert f.readline() == '\n'
140
w._parents.append([])
141
l = lines.next()[:-1]
142
w._sha1s.append(l[2:])
145
w._names.append(name)
146
w._name_map[name] = ver
125
152
raise WeaveFormatError('unexpected line %r' % l)
131
elif l.startswith('. '):
132
w._l.append(l[2:]) # include newline
133
elif l.startswith(', '):
134
w._l.append(l[2:-1]) # exclude newline
160
w._weave.append(l[2:]) # include newline
162
w._weave.append(l[2:-1]) # exclude newline
164
w._weave.append(('}', None))
136
assert l[0] in '{}[]', l
137
assert l[1] == ' ', l
138
w._l.append((l[0], int(l[2:])))
166
w._weave.append((intern(l[0]), int(l[2:])))