/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/weavefile.py

  • Committer: Martin Pool
  • Date: 2005-09-06 02:26:28 UTC
  • Revision ID: mbp@sourcefrog.net-20050906022628-66d65f0feb4a9e80
- implement version 5 xml storage, and tests

  This stores files identified by the version that introduced the 
  text, and the version that introduced the name.  Entry kinds are
  given by the xml tag not an explicit kind field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
# Copyright (C) 2005 Canonical Ltd
 
4
 
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
 
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
 
 
15
# You should have received a copy of the GNU General Public License
 
16
# 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
 
 
19
# Author: Martin Pool <mbp@canonical.com>
 
20
 
 
21
 
 
22
 
 
23
 
 
24
"""Store and retrieve weaves in files.
 
25
 
 
26
There is one format marker followed by a blank line, followed by a
 
27
series of version headers, followed by the weave itself.
 
28
 
 
29
Each version marker has
 
30
 
 
31
 'i'   parent version indexes
 
32
 '1'   SHA-1 of text
 
33
 'n'   name
 
34
 
 
35
The inclusions do not need to list versions included by a parent.
 
36
 
 
37
The weave is bracketed by 'w' and 'W' lines, and includes the '{}[]'
 
38
processing instructions.  Lines of text are prefixed by '.' if the
 
39
line contains a newline, or ',' if not.
 
40
"""
 
41
 
 
42
# TODO: When extracting a single version it'd be enough to just pass
 
43
# an iterator returning the weave lines...  We don't really need to
 
44
# deserialize it into memory.
 
45
 
 
46
FORMAT_1 = '# bzr weave file v5\n'
 
47
 
 
48
 
 
49
def write_weave(weave, f, format=None):
 
50
    if format == None or format == 1:
 
51
        return write_weave_v5(weave, f)
 
52
    else:
 
53
        raise ValueError("unknown weave format %r" % format)
 
54
 
 
55
 
 
56
def write_weave_v5(weave, f):
 
57
    """Write weave to file f."""
 
58
    print >>f, FORMAT_1,
 
59
 
 
60
    for version, included in enumerate(weave._parents):
 
61
        if included:
 
62
            # mininc = weave.minimal_parents(version)
 
63
            mininc = included
 
64
            print >>f, 'i',
 
65
            for i in mininc:
 
66
                print >>f, i,
 
67
            print >>f
 
68
        else:
 
69
            print >>f, 'i'
 
70
        print >>f, '1', weave._sha1s[version]
 
71
        print >>f, 'n', weave._names[version]
 
72
        print >>f
 
73
 
 
74
    print >>f, 'w'
 
75
 
 
76
    for l in weave._weave:
 
77
        if isinstance(l, tuple):
 
78
            assert l[0] in '{}[]'
 
79
            if l[0] == '}':
 
80
                print >>f, '}'
 
81
            else:
 
82
                print >>f, '%s %d' % l
 
83
        else: # text line
 
84
            if not l:
 
85
                print >>f, ', '
 
86
            elif l[-1] == '\n':
 
87
                assert l.find('\n', 0, -1) == -1
 
88
                print >>f, '.', l,
 
89
            else:
 
90
                assert l.find('\n') == -1
 
91
                print >>f, ',', l
 
92
 
 
93
    print >>f, 'W'
 
94
 
 
95
 
 
96
 
 
97
def read_weave(f):
 
98
    return read_weave_v5(f)
 
99
 
 
100
 
 
101
def read_weave_v5(f):
 
102
    from weave import Weave, WeaveFormatError
 
103
    w = Weave()
 
104
 
 
105
    l = f.readline()
 
106
    if l != FORMAT_1:
 
107
        raise WeaveFormatError('invalid weave file header: %r' % l)
 
108
 
 
109
    ver = 0
 
110
    while True:
 
111
        l = f.readline()
 
112
        if l[0] == 'i':
 
113
            if len(l) > 2:
 
114
                w._parents.append(map(int, l[2:].split(' ')))
 
115
            else:
 
116
                w._parents.append([])
 
117
 
 
118
            l = f.readline()[:-1]
 
119
            assert l.startswith('1 ')
 
120
            w._sha1s.append(l[2:])
 
121
                
 
122
            l = f.readline()
 
123
            assert l.startswith('n ')
 
124
            name = l[2:-1]
 
125
            assert name not in w._name_map
 
126
            w._names.append(name)
 
127
            w._name_map[name] = ver
 
128
                
 
129
            l = f.readline()
 
130
            assert l == '\n'
 
131
 
 
132
            ver += 1
 
133
        elif l == 'w\n':
 
134
            break
 
135
        else:
 
136
            raise WeaveFormatError('unexpected line %r' % l)
 
137
 
 
138
    while True:
 
139
        l = f.readline()
 
140
        if l == 'W\n':
 
141
            break
 
142
        elif l.startswith('. '):
 
143
            w._weave.append(l[2:])  # include newline
 
144
        elif l.startswith(', '):
 
145
            w._weave.append(l[2:-1])        # exclude newline
 
146
        elif l == '}\n':
 
147
            w._weave.append(('}', None))
 
148
        else:
 
149
            assert l[0] in '{[]', l
 
150
            assert l[1] == ' ', l
 
151
            w._weave.append((intern(l[0]), int(l[2:])))
 
152
 
 
153
    return w
 
154