/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/views.py

  • Committer: Andrew Bennetts
  • Date: 2011-06-09 07:38:32 UTC
  • mto: This revision was merged to the branch mainline in revision 5964.
  • Revision ID: andrew.bennetts@canonical.com-20110609073832-dt6oww033iexli4l
Fix thinko in wording regarding stacking invariants and revisions with multiple parents.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
  tree.views.lookup_view()
23
23
"""
24
24
 
 
25
 
25
26
import re
26
27
 
27
 
from . import (
 
28
from bzrlib import (
28
29
    errors,
29
30
    osutils,
30
31
    )
31
32
 
32
33
 
33
 
_VIEWS_FORMAT_MARKER_RE = re.compile(b'Bazaar views format (\\d+)')
34
 
_VIEWS_FORMAT1_MARKER = b"Bazaar views format 1\n"
35
 
 
36
 
 
37
 
class NoSuchView(errors.BzrError):
38
 
    """A view does not exist.
39
 
    """
40
 
 
41
 
    _fmt = u"No such view: %(view_name)s."
42
 
 
43
 
    def __init__(self, view_name):
44
 
        self.view_name = view_name
45
 
 
46
 
 
47
 
class ViewsNotSupported(errors.BzrError):
48
 
    """Views are not supported by a tree format.
49
 
    """
50
 
 
51
 
    _fmt = ("Views are not supported by %(tree)s;"
52
 
            " use 'brz upgrade' to change your tree to a later format.")
53
 
 
54
 
    def __init__(self, tree):
55
 
        self.tree = tree
56
 
 
57
 
 
58
 
class FileOutsideView(errors.BzrError):
59
 
 
60
 
    _fmt = ('Specified file "%(file_name)s" is outside the current view: '
61
 
            '%(view_str)s')
62
 
 
63
 
    def __init__(self, file_name, view_files):
64
 
        self.file_name = file_name
65
 
        self.view_str = ", ".join(view_files)
 
34
_VIEWS_FORMAT_MARKER_RE = re.compile(r'Bazaar views format (\d+)')
 
35
_VIEWS_FORMAT1_MARKER = "Bazaar views format 1\n"
66
36
 
67
37
 
68
38
class _Views(object):
124
94
        :param views: a map from view name to list of files/directories
125
95
        """
126
96
        if current is not None and current not in views:
127
 
            raise NoSuchView(current)
128
 
        with self.tree.lock_write():
 
97
            raise errors.NoSuchView(current)
 
98
        self.tree.lock_write()
 
99
        try:
129
100
            self._current = current
130
101
            self._views = views
131
102
            self._save_view_info()
 
103
        finally:
 
104
            self.tree.unlock()
132
105
 
133
106
    def lookup_view(self, view_name=None):
134
107
        """Return the contents of a view.
145
118
                    return []
146
119
            return self._views[view_name]
147
120
        except KeyError:
148
 
            raise NoSuchView(view_name)
 
121
            raise errors.NoSuchView(view_name)
149
122
 
150
123
    def set_view(self, view_name, view_files, make_current=True):
151
124
        """Add or update a view definition.
154
127
        :param view_files: the list of files/directories in the view
155
128
        :param make_current: make this view the current one or not
156
129
        """
157
 
        with self.tree.lock_write():
 
130
        self.tree.lock_write()
 
131
        try:
158
132
            self._load_view_info()
159
133
            self._views[view_name] = view_files
160
134
            if make_current:
161
135
                self._current = view_name
162
136
            self._save_view_info()
 
137
        finally:
 
138
            self.tree.unlock()
163
139
 
164
140
    def delete_view(self, view_name):
165
141
        """Delete a view definition.
166
142
 
167
143
        If the view deleted is the current one, the current view is reset.
168
144
        """
169
 
        with self.tree.lock_write():
 
145
        self.tree.lock_write()
 
146
        try:
170
147
            self._load_view_info()
171
148
            try:
172
149
                del self._views[view_name]
173
150
            except KeyError:
174
 
                raise NoSuchView(view_name)
 
151
                raise errors.NoSuchView(view_name)
175
152
            if view_name == self._current:
176
153
                self._current = None
177
154
            self._save_view_info()
 
155
        finally:
 
156
            self.tree.unlock()
178
157
 
179
158
    def _save_view_info(self):
180
159
        """Save the current view and all view definitions.
182
161
        Be sure to have initialised self._current and self._views before
183
162
        calling this method.
184
163
        """
185
 
        with self.tree.lock_write():
 
164
        self.tree.lock_write()
 
165
        try:
186
166
            if self._current is None:
187
167
                keywords = {}
188
168
            else:
189
169
                keywords = {'current': self._current}
190
 
            self.tree._transport.put_bytes(
191
 
                'views', self._serialize_view_content(keywords, self._views))
 
170
            self.tree._transport.put_bytes('views',
 
171
                self._serialize_view_content(keywords, self._views))
 
172
        finally:
 
173
            self.tree.unlock()
192
174
 
193
175
    def _load_view_info(self):
194
176
        """Load the current view and dictionary of view definitions."""
195
177
        if not self._loaded:
196
 
            with self.tree.lock_read():
 
178
            self.tree.lock_read()
 
179
            try:
197
180
                try:
198
181
                    view_content = self.tree._transport.get_bytes('views')
199
 
                except errors.NoSuchFile:
 
182
                except errors.NoSuchFile, e:
200
183
                    self._current, self._views = None, {}
201
184
                else:
202
185
                    keywords, self._views = \
203
186
                        self._deserialize_view_content(view_content)
204
187
                    self._current = keywords.get('current')
 
188
            finally:
 
189
                self.tree.unlock()
205
190
            self._loaded = True
206
191
 
207
192
    def _serialize_view_content(self, keywords, view_dict):
208
193
        """Convert view keywords and a view dictionary into a stream."""
209
194
        lines = [_VIEWS_FORMAT1_MARKER]
210
195
        for key in keywords:
211
 
            line = "%s=%s\n" % (key, keywords[key])
 
196
            line = "%s=%s\n" % (key,keywords[key])
212
197
            lines.append(line.encode('utf-8'))
213
198
        if view_dict:
214
199
            lines.append("views:\n".encode('utf-8'))
215
200
            for view in sorted(view_dict):
216
201
                view_data = "%s\0%s\n" % (view, "\0".join(view_dict[view]))
217
202
                lines.append(view_data.encode('utf-8'))
218
 
        return b"".join(lines)
 
203
        return "".join(lines)
219
204
 
220
205
    def _deserialize_view_content(self, view_content):
221
206
        """Convert a stream into view keywords and a dictionary of views."""
222
207
        # as a special case to make initialization easy, an empty definition
223
208
        # maps to no current view and an empty view dictionary
224
 
        if view_content == b'':
 
209
        if view_content == '':
225
210
            return {}, {}
226
211
        lines = view_content.splitlines()
227
212
        match = _VIEWS_FORMAT_MARKER_RE.match(lines[0])
228
213
        if not match:
229
214
            raise ValueError(
230
215
                "format marker missing from top of views file")
231
 
        elif match.group(1) != b'1':
 
216
        elif match.group(1) != '1':
232
217
            raise ValueError(
233
218
                "cannot decode views format %s" % match.group(1))
234
219
        try:
250
235
                    keywords[keyword] = value
251
236
                else:
252
237
                    raise ValueError("failed to deserialize views line %s",
253
 
                                     text)
 
238
                        text)
254
239
            return keywords, views
255
 
        except ValueError as e:
 
240
        except ValueError, e:
256
241
            raise ValueError("failed to deserialize views content %r: %s"
257
 
                             % (view_content, e))
 
242
                % (view_content, e))
258
243
 
259
244
 
260
245
class DisabledViews(_Views):
270
255
        return False
271
256
 
272
257
    def _not_supported(self, *a, **k):
273
 
        raise ViewsNotSupported(self.tree)
 
258
        raise errors.ViewsNotSupported(self.tree)
274
259
 
275
260
    get_view_info = _not_supported
276
261
    set_view_info = _not_supported
295
280
    """If a working tree has a view enabled, check the path is within it."""
296
281
    if tree.supports_views():
297
282
        view_files = tree.views.lookup_view()
298
 
        if view_files and not osutils.is_inside_any(view_files, relpath):
299
 
            raise FileOutsideView(relpath, view_files)
 
283
        if  view_files and not osutils.is_inside_any(view_files, relpath):
 
284
            raise errors.FileOutsideView(relpath, view_files)