/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

Implement _bisect_recursive, which uses multiple bisect calls to
handle renames and finding entries in subdirs.
As is, this could be hooked into paths2ids() if the dirstate has not been loaded yet.
However, it doesn't quite provide enough, since the parsed entries would probably not
be saved. Further, the multiple bisect calls are less efficient then they could be,
because they do not remember the last bisect call.
We should explore switching to a caching structure, which maintains all records that
have been processed, in a structure that can be in-memory searched before going back
to disk.

Show diffs side-by-side

added added

removed removed

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