~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to weavefile.py

  • Committer: Martin Pool
  • Date: 2005-06-30 07:49:50 UTC
  • mto: This revision was merged to the branch mainline in revision 852.
  • Revision ID: mbp@sourcefrog.net-20050630074950-bafafe0eb0a5eb15
Add format-hidden readwrite methods

Show diffs side-by-side

added added

removed removed

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