/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-08-29 21:29:35 UTC
  • mfrom: (6754.8.21 lock-context-2)
  • mto: This revision was merged to the branch mainline in revision 6784.
  • Revision ID: jelmer@jelmer.uk-20170829212935-lakl2jhq9sqckejp
Merge 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
 
        self.lock_tree_write()
45
 
        try:
46
 
            return unbound(self, *args, **kwargs)
47
 
        finally:
48
 
            self.unlock()
49
 
    tree_write_locked.__doc__ = unbound.__doc__
50
 
    tree_write_locked.__name__ = unbound.__name__
51
 
    return tree_write_locked
52
 
 
53
 
 
54
38
class MutableTree(tree.Tree):
55
39
    """A MutableTree is a specialisation of Tree which is able to be mutated.
56
40
 
88
72
        """
89
73
        raise NotImplementedError(self.is_control_filename)
90
74
 
91
 
    @needs_tree_write_lock
92
75
    def add(self, files, ids=None, kinds=None):
93
76
        """Add paths to the set of versioned paths.
94
77
 
131
114
            kinds = [None] * len(files)
132
115
        elif not len(kinds) == len(files):
133
116
            raise AssertionError()
134
 
        for f in files:
135
 
            # generic constraint checks:
136
 
            if self.is_control_filename(f):
137
 
                raise errors.ForbiddenControlFileError(filename=f)
138
 
            fp = osutils.splitpath(f)
139
 
        # fill out file kinds for all files [not needed when we stop
140
 
        # caring about the instantaneous file kind within a uncommmitted tree
141
 
        #
142
 
        self._gather_kinds(files, kinds)
143
 
        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)
144
128
 
145
129
    def add_reference(self, sub_tree):
146
130
        """Add a TreeReference to the tree, pointing at sub_tree"""
172
156
        """
173
157
        raise NotImplementedError(self._add)
174
158
 
175
 
    @needs_write_lock
176
159
    def commit(self, message=None, revprops=None, *args, **kwargs):
177
160
        # avoid circular imports
178
161
        from breezy import commit
179
162
        possible_master_transports=[]
180
 
        revprops = commit.Commit.update_revprops(
181
 
                revprops,
182
 
                self.branch,
183
 
                kwargs.pop('authors', None),
184
 
                kwargs.get('local', False),
185
 
                possible_master_transports)
186
 
        # args for wt.commit start at message from the Commit.commit method,
187
 
        args = (message, ) + args
188
 
        for hook in MutableTree.hooks['start_commit']:
189
 
            hook(self)
190
 
        committed_id = commit.Commit().commit(working_tree=self,
191
 
            revprops=revprops,
192
 
            possible_master_transports=possible_master_transports,
193
 
            *args, **kwargs)
194
 
        post_hook_params = PostCommitHookParams(self)
195
 
        for hook in MutableTree.hooks['post_commit']:
196
 
            hook(post_hook_params)
197
 
        return committed_id
 
163
        with self.lock_write():
 
164
            revprops = commit.Commit.update_revprops(
 
165
                    revprops,
 
166
                    self.branch,
 
167
                    kwargs.pop('authors', None),
 
168
                    kwargs.get('local', False),
 
169
                    possible_master_transports)
 
170
            # args for wt.commit start at message from the Commit.commit method,
 
171
            args = (message, ) + args
 
172
            for hook in MutableTree.hooks['start_commit']:
 
173
                hook(self)
 
174
            committed_id = commit.Commit().commit(working_tree=self,
 
175
                revprops=revprops,
 
176
                possible_master_transports=possible_master_transports,
 
177
                *args, **kwargs)
 
178
            post_hook_params = PostCommitHookParams(self)
 
179
            for hook in MutableTree.hooks['post_commit']:
 
180
                hook(post_hook_params)
 
181
            return committed_id
198
182
 
199
183
    def _gather_kinds(self, files, kinds):
200
184
        """Helper function for add - sets the entries of kinds."""
201
185
        raise NotImplementedError(self._gather_kinds)
202
186
 
203
 
    @needs_read_lock
204
187
    def has_changes(self, _from_tree=None):
205
188
        """Quickly check that the tree contains at least one commitable change.
206
189
 
209
192
 
210
193
        :return: True if a change is found. False otherwise
211
194
        """
212
 
        # Check pending merges
213
 
        if len(self.get_parent_ids()) > 1:
214
 
            return True
215
 
        if _from_tree is None:
216
 
            _from_tree = self.basis_tree()
217
 
        changes = self.iter_changes(_from_tree)
218
 
        try:
219
 
            change = next(changes)
220
 
            # Exclude root (talk about black magic... --vila 20090629)
221
 
            if change[4] == (None, None):
 
195
        with self.lock_read():
 
196
            # Check pending merges
 
197
            if len(self.get_parent_ids()) > 1:
 
198
                return True
 
199
            if _from_tree is None:
 
200
                _from_tree = self.basis_tree()
 
201
            changes = self.iter_changes(_from_tree)
 
202
            try:
222
203
                change = next(changes)
223
 
            return True
224
 
        except StopIteration:
225
 
            # No changes
226
 
            return False
 
204
                # Exclude root (talk about black magic... --vila 20090629)
 
205
                if change[4] == (None, None):
 
206
                    change = next(changes)
 
207
                return True
 
208
            except StopIteration:
 
209
                # No changes
 
210
                return False
227
211
 
228
 
    @needs_read_lock
229
212
    def check_changed_or_out_of_date(self, strict, opt_name,
230
213
                                     more_error, more_warning):
231
214
        """Check the tree for uncommitted changes and branch synchronization.
242
225
 
243
226
        :param more_warning: Details about what is happening.
244
227
        """
245
 
        if strict is None:
246
 
            strict = self.branch.get_config_stack().get(opt_name)
247
 
        if strict is not False:
248
 
            err_class = None
249
 
            if (self.has_changes()):
250
 
                err_class = errors.UncommittedChanges
251
 
            elif self.last_revision() != self.branch.last_revision():
252
 
                # The tree has lost sync with its branch, there is little
253
 
                # chance that the user is aware of it but he can still force
254
 
                # the action with --no-strict
255
 
                err_class = errors.OutOfDateTree
256
 
            if err_class is not None:
257
 
                if strict is None:
258
 
                    err = err_class(self, more=more_warning)
259
 
                    # We don't want to interrupt the user if he expressed no
260
 
                    # preference about strict.
261
 
                    trace.warning('%s', err._format())
262
 
                else:
263
 
                    err = err_class(self, more=more_error)
264
 
                    raise err
 
228
        with self.lock_read():
 
229
            if strict is None:
 
230
                strict = self.branch.get_config_stack().get(opt_name)
 
231
            if strict is not False:
 
232
                err_class = None
 
233
                if (self.has_changes()):
 
234
                    err_class = errors.UncommittedChanges
 
235
                elif self.last_revision() != self.branch.last_revision():
 
236
                    # The tree has lost sync with its branch, there is little
 
237
                    # chance that the user is aware of it but he can still
 
238
                    # force the action with --no-strict
 
239
                    err_class = errors.OutOfDateTree
 
240
                if err_class is not None:
 
241
                    if strict is None:
 
242
                        err = err_class(self, more=more_warning)
 
243
                        # We don't want to interrupt the user if he expressed
 
244
                        # no preference about strict.
 
245
                        trace.warning('%s', err._format())
 
246
                    else:
 
247
                        err = err_class(self, more=more_error)
 
248
                        raise err
265
249
 
266
 
    @needs_read_lock
267
250
    def last_revision(self):
268
251
        """Return the revision id of the last commit performed in this tree.
269
252
 
299
282
        """
300
283
        raise NotImplementedError(self.lock_write)
301
284
 
302
 
    @needs_write_lock
303
285
    def mkdir(self, path, file_id=None):
304
286
        """Create a directory in the tree. if file_id is None, one is assigned.
305
287
 
325
307
        :return: None
326
308
        """
327
309
 
328
 
    @needs_write_lock
329
310
    def put_file_bytes_non_atomic(self, file_id, bytes):
330
311
        """Update the content of a file in the tree.
331
312