/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: Robert Collins
  • Date: 2010-05-06 23:41:35 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506234135-yivbzczw1sejxnxc
Lock methods on ``Tree``, ``Branch`` and ``Repository`` are now
expected to return an object which can be used to unlock them. This reduces
duplicate code when using cleanups. The previous 'tokens's returned by
``Branch.lock_write`` and ``Repository.lock_write`` are now attributes
on the result of the lock_write. ``repository.RepositoryWriteLockResult``
and ``branch.BranchWriteLockResult`` document this. (Robert Collins)

``log._get_info_for_log_files`` now takes an add_cleanup callable.
(Robert Collins)

Show diffs side-by-side

added added

removed removed

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