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

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

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