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

  • Committer: Jelmer Vernooij
  • Date: 2017-09-06 04:15:55 UTC
  • mfrom: (6754.8.21 lock-context-2)
  • Revision ID: jelmer@jelmer.uk-20170906041555-jtr5qxli38167gc6
Merge lp:~jelmer/brz/lock-context-2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
from __future__ import absolute_import
23
23
 
24
 
import operator
25
 
import os
26
24
from . import (
27
25
    errors,
28
26
    hooks,
31
29
    tree,
32
30
    )
33
31
 
34
 
from .decorators import needs_read_lock, needs_write_lock
35
32
from .sixish import (
36
33
    text_type,
37
34
    viewvalues,
38
35
    )
39
36
 
40
37
 
41
 
def needs_tree_write_lock(unbound):
42
 
    """Decorate unbound to take out and release a tree_write lock."""
43
 
    def tree_write_locked(self, *args, **kwargs):
44
 
        with self.lock_tree_write():
45
 
            return unbound(self, *args, **kwargs)
46
 
    tree_write_locked.__doc__ = unbound.__doc__
47
 
    tree_write_locked.__name__ = unbound.__name__
48
 
    return tree_write_locked
49
 
 
50
 
 
51
38
class MutableTree(tree.Tree):
52
39
    """A MutableTree is a specialisation of Tree which is able to be mutated.
53
40
 
85
72
        """
86
73
        raise NotImplementedError(self.is_control_filename)
87
74
 
88
 
    @needs_tree_write_lock
89
75
    def add(self, files, ids=None, kinds=None):
90
76
        """Add paths to the set of versioned paths.
91
77
 
128
114
            kinds = [None] * len(files)
129
115
        elif not len(kinds) == len(files):
130
116
            raise AssertionError()
131
 
        for f in files:
132
 
            # generic constraint checks:
133
 
            if self.is_control_filename(f):
134
 
                raise errors.ForbiddenControlFileError(filename=f)
135
 
            fp = osutils.splitpath(f)
136
 
        # fill out file kinds for all files [not needed when we stop
137
 
        # caring about the instantaneous file kind within a uncommmitted tree
138
 
        #
139
 
        self._gather_kinds(files, kinds)
140
 
        self._add(files, ids, kinds)
 
117
        with self.lock_tree_write():
 
118
            for f in files:
 
119
                # generic constraint checks:
 
120
                if self.is_control_filename(f):
 
121
                    raise errors.ForbiddenControlFileError(filename=f)
 
122
                fp = osutils.splitpath(f)
 
123
            # fill out file kinds for all files [not needed when we stop
 
124
            # caring about the instantaneous file kind within a uncommmitted tree
 
125
            #
 
126
            self._gather_kinds(files, kinds)
 
127
            self._add(files, ids, kinds)
141
128
 
142
129
    def add_reference(self, sub_tree):
143
130
        """Add a TreeReference to the tree, pointing at sub_tree"""
179
166
        """
180
167
        raise NotImplementedError(self.apply_inventory_delta)
181
168
 
182
 
    @needs_write_lock
183
169
    def commit(self, message=None, revprops=None, *args, **kwargs):
184
170
        # avoid circular imports
185
171
        from breezy import commit
186
172
        possible_master_transports=[]
187
 
        revprops = commit.Commit.update_revprops(
188
 
                revprops,
189
 
                self.branch,
190
 
                kwargs.pop('authors', None),
191
 
                kwargs.get('local', False),
192
 
                possible_master_transports)
193
 
        # args for wt.commit start at message from the Commit.commit method,
194
 
        args = (message, ) + args
195
 
        for hook in MutableTree.hooks['start_commit']:
196
 
            hook(self)
197
 
        committed_id = commit.Commit().commit(working_tree=self,
198
 
            revprops=revprops,
199
 
            possible_master_transports=possible_master_transports,
200
 
            *args, **kwargs)
201
 
        post_hook_params = PostCommitHookParams(self)
202
 
        for hook in MutableTree.hooks['post_commit']:
203
 
            hook(post_hook_params)
204
 
        return committed_id
 
173
        with self.lock_write():
 
174
            revprops = commit.Commit.update_revprops(
 
175
                    revprops,
 
176
                    self.branch,
 
177
                    kwargs.pop('authors', None),
 
178
                    kwargs.get('local', False),
 
179
                    possible_master_transports)
 
180
            # args for wt.commit start at message from the Commit.commit method,
 
181
            args = (message, ) + args
 
182
            for hook in MutableTree.hooks['start_commit']:
 
183
                hook(self)
 
184
            committed_id = commit.Commit().commit(working_tree=self,
 
185
                revprops=revprops,
 
186
                possible_master_transports=possible_master_transports,
 
187
                *args, **kwargs)
 
188
            post_hook_params = PostCommitHookParams(self)
 
189
            for hook in MutableTree.hooks['post_commit']:
 
190
                hook(post_hook_params)
 
191
            return committed_id
205
192
 
206
193
    def _gather_kinds(self, files, kinds):
207
194
        """Helper function for add - sets the entries of kinds."""
208
195
        raise NotImplementedError(self._gather_kinds)
209
196
 
210
 
    @needs_read_lock
211
197
    def has_changes(self, _from_tree=None):
212
198
        """Quickly check that the tree contains at least one commitable change.
213
199
 
216
202
 
217
203
        :return: True if a change is found. False otherwise
218
204
        """
219
 
        # Check pending merges
220
 
        if len(self.get_parent_ids()) > 1:
221
 
            return True
222
 
        if _from_tree is None:
223
 
            _from_tree = self.basis_tree()
224
 
        changes = self.iter_changes(_from_tree)
225
 
        try:
226
 
            change = next(changes)
227
 
            # Exclude root (talk about black magic... --vila 20090629)
228
 
            if change[4] == (None, None):
 
205
        with self.lock_read():
 
206
            # Check pending merges
 
207
            if len(self.get_parent_ids()) > 1:
 
208
                return True
 
209
            if _from_tree is None:
 
210
                _from_tree = self.basis_tree()
 
211
            changes = self.iter_changes(_from_tree)
 
212
            try:
229
213
                change = next(changes)
230
 
            return True
231
 
        except StopIteration:
232
 
            # No changes
233
 
            return False
 
214
                # Exclude root (talk about black magic... --vila 20090629)
 
215
                if change[4] == (None, None):
 
216
                    change = next(changes)
 
217
                return True
 
218
            except StopIteration:
 
219
                # No changes
 
220
                return False
234
221
 
235
 
    @needs_read_lock
236
222
    def check_changed_or_out_of_date(self, strict, opt_name,
237
223
                                     more_error, more_warning):
238
224
        """Check the tree for uncommitted changes and branch synchronization.
249
235
 
250
236
        :param more_warning: Details about what is happening.
251
237
        """
252
 
        if strict is None:
253
 
            strict = self.branch.get_config_stack().get(opt_name)
254
 
        if strict is not False:
255
 
            err_class = None
256
 
            if (self.has_changes()):
257
 
                err_class = errors.UncommittedChanges
258
 
            elif self.last_revision() != self.branch.last_revision():
259
 
                # The tree has lost sync with its branch, there is little
260
 
                # chance that the user is aware of it but he can still force
261
 
                # the action with --no-strict
262
 
                err_class = errors.OutOfDateTree
263
 
            if err_class is not None:
264
 
                if strict is None:
265
 
                    err = err_class(self, more=more_warning)
266
 
                    # We don't want to interrupt the user if he expressed no
267
 
                    # preference about strict.
268
 
                    trace.warning('%s', err._format())
269
 
                else:
270
 
                    err = err_class(self, more=more_error)
271
 
                    raise err
 
238
        with self.lock_read():
 
239
            if strict is None:
 
240
                strict = self.branch.get_config_stack().get(opt_name)
 
241
            if strict is not False:
 
242
                err_class = None
 
243
                if (self.has_changes()):
 
244
                    err_class = errors.UncommittedChanges
 
245
                elif self.last_revision() != self.branch.last_revision():
 
246
                    # The tree has lost sync with its branch, there is little
 
247
                    # chance that the user is aware of it but he can still
 
248
                    # force the action with --no-strict
 
249
                    err_class = errors.OutOfDateTree
 
250
                if err_class is not None:
 
251
                    if strict is None:
 
252
                        err = err_class(self, more=more_warning)
 
253
                        # We don't want to interrupt the user if he expressed
 
254
                        # no preference about strict.
 
255
                        trace.warning('%s', err._format())
 
256
                    else:
 
257
                        err = err_class(self, more=more_error)
 
258
                        raise err
272
259
 
273
 
    @needs_read_lock
274
260
    def last_revision(self):
275
261
        """Return the revision id of the last commit performed in this tree.
276
262
 
306
292
        """
307
293
        raise NotImplementedError(self.lock_write)
308
294
 
309
 
    @needs_write_lock
310
295
    def mkdir(self, path, file_id=None):
311
296
        """Create a directory in the tree. if file_id is None, one is assigned.
312
297
 
332
317
        :return: None
333
318
        """
334
319
 
335
 
    @needs_write_lock
336
320
    def put_file_bytes_non_atomic(self, file_id, bytes):
337
321
        """Update the content of a file in the tree.
338
322