~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weavefile.py

(vila) Fix bzrlib.tests.test_gpg.TestVerify.test_verify_revoked_signature
 with recent versions of gpg. (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/python
2
 
 
3
 
# Copyright (C) 2005 Canonical Ltd
4
 
 
 
1
# Copyright (C) 2005-2010 Canonical Ltd
 
2
#
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.
9
 
 
 
7
#
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.
14
 
 
 
12
#
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
18
 
 
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
#
19
17
# Author: Martin Pool <mbp@canonical.com>
20
18
 
21
 
 
22
 
 
23
 
 
24
19
"""Store and retrieve weaves in files.
25
20
 
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.
28
23
 
29
 
Each version marker has 'v' and the version, then 'i' and the included
30
 
previous versions.
 
24
Each version marker has
 
25
 
 
26
 'i'   parent version indexes
 
27
 '1'   SHA-1 of text
 
28
 'n'   name
 
29
 
 
30
The inclusions do not need to list versions included by a parent.
31
31
 
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.
35
35
"""
36
36
 
 
37
from __future__ import absolute_import
 
38
 
37
39
# TODO: When extracting a single version it'd be enough to just pass
38
 
# an iterator returning the weave lines...
39
 
 
40
 
FORMAT_1 = '# bzr weave file v1\n'
41
 
 
 
40
# an iterator returning the weave lines...  We don't really need to
 
41
# deserialize it into memory.
 
42
 
 
43
FORMAT_1 = '# bzr weave file v5\n'
42
44
 
43
45
 
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)
47
49
    else:
48
50
        raise ValueError("unknown weave format %r" % format)
49
51
 
50
52
 
51
 
def write_weave_v1(weave, f):
 
53
def write_weave_v5(weave, f):
52
54
    """Write weave to file f."""
53
 
    print >>f, FORMAT_1,
 
55
    f.write(FORMAT_1)
54
56
 
55
 
    for version, included in enumerate(weave._v):
56
 
        print >>f, 'v', version
 
57
    for version, included in enumerate(weave._parents):
57
58
        if included:
58
 
            included = list(included)
59
 
            included.sort()
60
 
            assert included[0] >= 0
61
 
            assert included[-1] < version
62
 
            print >>f, 'i',
63
 
            for i in included:
64
 
                print >>f, i,
65
 
            print >>f
 
59
            # mininc = weave.minimal_parents(version)
 
60
            mininc = included
 
61
            f.write('i ')
 
62
            f.write(' '.join(str(i) for i in mininc))
 
63
            f.write('\n')
66
64
        else:
67
 
            print >>f, 'i'
68
 
        print >>f
69
 
 
70
 
    print >>f, 'w'
71
 
 
72
 
    for l in weave._l:
 
65
            f.write('i\n')
 
66
        f.write('1 ' + weave._sha1s[version] + '\n')
 
67
        f.write('n ' + weave._names[version] + '\n')
 
68
        f.write('\n')
 
69
 
 
70
    f.write('w\n')
 
71
 
 
72
    for l in weave._weave:
73
73
        if isinstance(l, tuple):
74
 
            assert l[0] in '{}[]'
75
 
            print >>f, '%s %d' % l
 
74
            if l[0] == '}':
 
75
                f.write('}\n')
 
76
            else:
 
77
                f.write('%s %d\n' % l)
76
78
        else: # text line
77
79
            if not l:
78
 
                print >>f, ', '
 
80
                f.write(', \n')
79
81
            elif l[-1] == '\n':
80
 
                assert l.find('\n', 0, -1) == -1
81
 
                print >>f, '.', l,
 
82
                f.write('. ' + l)
82
83
            else:
83
 
                assert l.find('\n') == -1
84
 
                print >>f, ',', l
 
84
                f.write(', ' + l + '\n')
85
85
 
86
 
    print >>f, 'W'
 
86
    f.write('W\n')
87
87
 
88
88
 
89
89
 
90
90
def read_weave(f):
91
 
    return read_weave_v1(f)
92
 
 
93
 
 
94
 
def read_weave_v1(f):
95
 
    from weave import Weave, WeaveFormatError
96
 
    w = Weave()
97
 
 
98
 
    wfe = WeaveFormatError
99
 
    l = f.readline()
 
91
    # FIXME: detect the weave type and dispatch
 
92
    from bzrlib.weave import Weave
 
93
    w = Weave(getattr(f, 'name', None))
 
94
    _read_weave_v5(f, w)
 
95
    return w
 
96
 
 
97
 
 
98
def _read_weave_v5(f, w):
 
99
    """Private helper routine to read a weave format 5 file into memory.
 
100
 
 
101
    This is only to be used by read_weave and WeaveFile.__init__.
 
102
    """
 
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>
 
116
 
 
117
    from bzrlib.weave import WeaveFormatError
 
118
 
 
119
    try:
 
120
        lines = iter(f.readlines())
 
121
    finally:
 
122
        f.close()
 
123
 
 
124
    try:
 
125
        l = lines.next()
 
126
    except StopIteration:
 
127
        raise WeaveFormatError('invalid weave file: no header')
 
128
 
100
129
    if l != FORMAT_1:
101
130
        raise WeaveFormatError('invalid weave file header: %r' % l)
102
131
 
103
 
    v_cnt = 0
 
132
    ver = 0
 
133
    # read weave header.
104
134
    while True:
105
 
        l = f.readline()
106
 
        if l.startswith('v '):
107
 
            ver = int(l[2:])
108
 
            if ver != v_cnt:
109
 
                raise WeaveFormatError('version %d!=%d out of order'
110
 
                                       % (ver, v_cnt))
111
 
            v_cnt += 1
112
 
            
113
 
            l = f.readline()[:-1]
114
 
            if l[0] != 'i':
115
 
                raise WeaveFormatError('unexpected line %r' % l)
 
135
        l = lines.next()
 
136
        if l[0] == 'i':
116
137
            if len(l) > 2:
117
 
                included = map(int, l[2:].split(' '))
118
 
                w._addversion(included)
 
138
                w._parents.append(map(int, l[2:].split(' ')))
119
139
            else:
120
 
                w._addversion(None)
121
 
            assert f.readline() == '\n'
 
140
                w._parents.append([])
 
141
            l = lines.next()[:-1]
 
142
            w._sha1s.append(l[2:])
 
143
            l = lines.next()
 
144
            name = l[2:-1]
 
145
            w._names.append(name)
 
146
            w._name_map[name] = ver
 
147
            l = lines.next()
 
148
            ver += 1
122
149
        elif l == 'w\n':
123
150
            break
124
151
        else:
125
152
            raise WeaveFormatError('unexpected line %r' % l)
126
153
 
 
154
    # read weave body
127
155
    while True:
128
 
        l = f.readline()
 
156
        l = lines.next()
129
157
        if l == 'W\n':
130
158
            break
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
 
159
        elif '. ' == l[0:2]:
 
160
            w._weave.append(l[2:])  # include newline
 
161
        elif ', ' == l[0:2]:
 
162
            w._weave.append(l[2:-1])        # exclude newline
 
163
        elif l == '}\n':
 
164
            w._weave.append(('}', None))
135
165
        else:
136
 
            assert l[0] in '{}[]', l
137
 
            assert l[1] == ' ', l
138
 
            w._l.append((l[0], int(l[2:])))
139
 
 
 
166
            w._weave.append((intern(l[0]), int(l[2:])))
140
167
    return w
141