~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisiontree.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""RevisionTree - a Tree implementation backed by repository data for a revision."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
from cStringIO import StringIO
20
22
 
21
23
from bzrlib import (
31
33
    File text can be retrieved from the text store.
32
34
    """
33
35
 
34
 
    def __init__(self, branch, inv, revision_id):
35
 
        # for compatability the 'branch' parameter has not been renamed to
36
 
        # repository at this point. However, we should change RevisionTree's
37
 
        # construction to always be via Repository and not via direct
38
 
        # construction - this will mean that we can change the constructor
39
 
        # with much less chance of breaking client code.
40
 
        self._repository = branch
41
 
        self._inventory = inv
 
36
    def __init__(self, repository, revision_id):
 
37
        self._repository = repository
42
38
        self._revision_id = revision_id
43
39
        self._rules_searcher = None
44
40
 
 
41
    def has_versioned_directories(self):
 
42
        """See `Tree.has_versioned_directories`."""
 
43
        return self._repository._format.supports_versioned_directories
 
44
 
45
45
    def supports_tree_reference(self):
46
46
        return getattr(self._repository._format, "supports_tree_reference",
47
47
            False)
62
62
        """Return the revision id associated with this tree."""
63
63
        return self._revision_id
64
64
 
 
65
    def get_file_revision(self, file_id, path=None):
 
66
        """Return the revision id in which a file was last changed."""
 
67
        raise NotImplementedError(self.get_file_revision)
 
68
 
65
69
    def get_file_text(self, file_id, path=None):
66
 
        _, content = list(self.iter_files_bytes([(file_id, None)]))[0]
67
 
        return ''.join(content)
 
70
        for (identifier, content) in self.iter_files_bytes([(file_id, None)]):
 
71
            ret = "".join(content)
 
72
        return ret
68
73
 
69
74
    def get_file(self, file_id, path=None):
70
75
        return StringIO(self.get_file_text(file_id))
71
76
 
72
 
    def iter_files_bytes(self, desired_files):
73
 
        """See Tree.iter_files_bytes.
74
 
 
75
 
        This version is implemented on top of Repository.extract_files_bytes"""
76
 
        repo_desired_files = [(f, self.inventory[f].revision, i)
77
 
                              for f, i in desired_files]
 
77
    def is_locked(self):
 
78
        return self._repository.is_locked()
 
79
 
 
80
    def lock_read(self):
 
81
        self._repository.lock_read()
 
82
        return self
 
83
 
 
84
    def __repr__(self):
 
85
        return '<%s instance at %x, rev_id=%r>' % (
 
86
            self.__class__.__name__, id(self), self._revision_id)
 
87
 
 
88
    def unlock(self):
 
89
        self._repository.unlock()
 
90
 
 
91
    def _get_rules_searcher(self, default_searcher):
 
92
        """See Tree._get_rules_searcher."""
 
93
        if self._rules_searcher is None:
 
94
            self._rules_searcher = super(RevisionTree,
 
95
                self)._get_rules_searcher(default_searcher)
 
96
        return self._rules_searcher
 
97
 
 
98
 
 
99
class InventoryRevisionTree(RevisionTree,tree.InventoryTree):
 
100
 
 
101
    def __init__(self, repository, inv, revision_id):
 
102
        RevisionTree.__init__(self, repository, revision_id)
 
103
        self._inventory = inv
 
104
 
 
105
    def get_file_mtime(self, file_id, path=None):
 
106
        ie = self._inventory[file_id]
78
107
        try:
79
 
            for result in self._repository.iter_files_bytes(repo_desired_files):
80
 
                yield result
81
 
        except errors.RevisionNotPresent, e:
82
 
            raise errors.NoSuchFile(e.revision_id)
83
 
 
84
 
    def annotate_iter(self, file_id,
85
 
                      default_revision=revision.CURRENT_REVISION):
86
 
        """See Tree.annotate_iter"""
87
 
        text_key = (file_id, self.inventory[file_id].revision)
88
 
        annotator = self._repository.texts.get_annotator()
89
 
        annotations = annotator.annotate_flat(text_key)
90
 
        return [(key[-1], line) for key, line in annotations]
 
108
            revision = self._repository.get_revision(ie.revision)
 
109
        except errors.NoSuchRevision:
 
110
            raise errors.FileTimestampUnavailable(self.id2path(file_id))
 
111
        return revision.timestamp
91
112
 
92
113
    def get_file_size(self, file_id):
93
 
        """See Tree.get_file_size"""
94
114
        return self._inventory[file_id].text_size
95
115
 
96
116
    def get_file_sha1(self, file_id, path=None, stat_value=None):
99
119
            return ie.text_sha1
100
120
        return None
101
121
 
102
 
    def get_file_mtime(self, file_id, path=None):
 
122
    def get_file_revision(self, file_id, path=None):
103
123
        ie = self._inventory[file_id]
104
 
        try:
105
 
            revision = self._repository.get_revision(ie.revision)
106
 
        except errors.NoSuchRevision:
107
 
            raise errors.FileTimestampUnavailable(self.id2path(file_id))
108
 
        return revision.timestamp
 
124
        return ie.revision
109
125
 
110
126
    def is_executable(self, file_id, path=None):
111
127
        ie = self._inventory[file_id]
112
128
        if ie.kind != "file":
113
 
            return None
 
129
            return False
114
130
        return ie.executable
115
131
 
116
132
    def has_filename(self, filename):
133
149
        for path, entry in entries:
134
150
            yield path, 'V', entry.kind, entry.file_id, entry
135
151
 
136
 
    def get_symlink_target(self, file_id):
 
152
    def get_symlink_target(self, file_id, path=None):
137
153
        ie = self._inventory[file_id]
138
154
        # Inventories store symlink targets in unicode
139
155
        return ie.symlink_target
170
186
    def _file_size(self, entry, stat_value):
171
187
        return entry.text_size
172
188
 
173
 
    def _get_ancestors(self, default_revision):
174
 
        return set(self._repository.get_ancestry(self._revision_id,
175
 
                                                 topo_sorted=False))
176
 
 
177
 
    def lock_read(self):
178
 
        self._repository.lock_read()
179
 
 
180
 
    def __repr__(self):
181
 
        return '<%s instance at %x, rev_id=%r>' % (
182
 
            self.__class__.__name__, id(self), self._revision_id)
183
 
 
184
 
    def unlock(self):
185
 
        self._repository.unlock()
186
 
 
187
189
    def walkdirs(self, prefix=""):
188
190
        _directory = 'directory'
189
191
        inv = self.inventory
213
215
                if dir[2] == _directory:
214
216
                    pending.append(dir)
215
217
 
216
 
    def _get_rules_searcher(self, default_searcher):
217
 
        """See Tree._get_rules_searcher."""
218
 
        if self._rules_searcher is None:
219
 
            self._rules_searcher = super(RevisionTree,
220
 
                self)._get_rules_searcher(default_searcher)
221
 
        return self._rules_searcher
 
218
    def iter_files_bytes(self, desired_files):
 
219
        """See Tree.iter_files_bytes.
 
220
 
 
221
        This version is implemented on top of Repository.iter_files_bytes"""
 
222
        repo_desired_files = [(f, self.get_file_revision(f), i)
 
223
                              for f, i in desired_files]
 
224
        try:
 
225
            for result in self._repository.iter_files_bytes(repo_desired_files):
 
226
                yield result
 
227
        except errors.RevisionNotPresent, e:
 
228
            raise errors.NoSuchFile(e.file_id)
 
229
 
 
230
    def annotate_iter(self, file_id,
 
231
                      default_revision=revision.CURRENT_REVISION):
 
232
        """See Tree.annotate_iter"""
 
233
        text_key = (file_id, self.get_file_revision(file_id))
 
234
        annotator = self._repository.texts.get_annotator()
 
235
        annotations = annotator.annotate_flat(text_key)
 
236
        return [(key[-1], line) for key, line in annotations]
222
237
 
223
238
 
224
239
class InterCHKRevisionTree(tree.InterTree):