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

  • Committer: John Arbash Meinel
  • Date: 2011-04-20 14:27:19 UTC
  • mto: This revision was merged to the branch mainline in revision 5837.
  • Revision ID: john@arbash-meinel.com-20110420142719-advs1k5vztqzbrgv
Fix bug #767177. Be more agressive with file.close() calls.

Our test suite gets a number of thread leaks and failures because it happens to get async
SFTPFile.close() calls. (if an SFTPFile closes due to __del__ it is done as an async request,
while if you call SFTPFile.close() it is done as a synchronous request.)
We have a couple other cases, probably. Namely SFTPTransport.get() also does an async
prefetch of the content, so if you don't .read() you'll also leak threads that think they
are doing work that you want.

The biggest change here, though, is using a try/finally in a generator, which is not 
python2.4 compatible.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
    File text can be retrieved from the text store.
32
32
    """
33
33
 
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
 
34
    def __init__(self, repository, revision_id):
 
35
        self._repository = repository
42
36
        self._revision_id = revision_id
43
37
        self._rules_searcher = None
44
38
 
62
56
        """Return the revision id associated with this tree."""
63
57
        return self._revision_id
64
58
 
 
59
    def get_file_revision(self, file_id, path=None):
 
60
        """Return the revision id in which a file was last changed."""
 
61
        raise NotImplementedError(self.get_file_revision)
 
62
 
65
63
    def get_file_text(self, file_id, path=None):
66
64
        _, content = list(self.iter_files_bytes([(file_id, None)]))[0]
67
65
        return ''.join(content)
69
67
    def get_file(self, file_id, path=None):
70
68
        return StringIO(self.get_file_text(file_id))
71
69
 
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]
 
70
    def is_locked(self):
 
71
        return self._repository.is_locked()
 
72
 
 
73
    def lock_read(self):
 
74
        self._repository.lock_read()
 
75
        return self
 
76
 
 
77
    def __repr__(self):
 
78
        return '<%s instance at %x, rev_id=%r>' % (
 
79
            self.__class__.__name__, id(self), self._revision_id)
 
80
 
 
81
    def unlock(self):
 
82
        self._repository.unlock()
 
83
 
 
84
    def _get_rules_searcher(self, default_searcher):
 
85
        """See Tree._get_rules_searcher."""
 
86
        if self._rules_searcher is None:
 
87
            self._rules_searcher = super(RevisionTree,
 
88
                self)._get_rules_searcher(default_searcher)
 
89
        return self._rules_searcher
 
90
 
 
91
 
 
92
class InventoryRevisionTree(RevisionTree,tree.InventoryTree):
 
93
 
 
94
    def __init__(self, repository, inv, revision_id):
 
95
        RevisionTree.__init__(self, repository, revision_id)
 
96
        self._inventory = inv
 
97
 
 
98
    def get_file_mtime(self, file_id, path=None):
 
99
        ie = self._inventory[file_id]
78
100
        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]
 
101
            revision = self._repository.get_revision(ie.revision)
 
102
        except errors.NoSuchRevision:
 
103
            raise errors.FileTimestampUnavailable(self.id2path(file_id))
 
104
        return revision.timestamp
91
105
 
92
106
    def get_file_size(self, file_id):
93
 
        """See Tree.get_file_size"""
94
107
        return self._inventory[file_id].text_size
95
108
 
96
109
    def get_file_sha1(self, file_id, path=None, stat_value=None):
99
112
            return ie.text_sha1
100
113
        return None
101
114
 
102
 
    def get_file_mtime(self, file_id, path=None):
 
115
    def get_file_revision(self, file_id, path=None):
103
116
        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
 
117
        return ie.revision
109
118
 
110
119
    def is_executable(self, file_id, path=None):
111
120
        ie = self._inventory[file_id]
112
121
        if ie.kind != "file":
113
 
            return None
 
122
            return False
114
123
        return ie.executable
115
124
 
116
125
    def has_filename(self, filename):
174
183
        return set(self._repository.get_ancestry(self._revision_id,
175
184
                                                 topo_sorted=False))
176
185
 
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
186
    def walkdirs(self, prefix=""):
188
187
        _directory = 'directory'
189
188
        inv = self.inventory
213
212
                if dir[2] == _directory:
214
213
                    pending.append(dir)
215
214
 
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
 
215
    def iter_files_bytes(self, desired_files):
 
216
        """See Tree.iter_files_bytes.
 
217
 
 
218
        This version is implemented on top of Repository.extract_files_bytes"""
 
219
        repo_desired_files = [(f, self.get_file_revision(f), i)
 
220
                              for f, i in desired_files]
 
221
        try:
 
222
            for result in self._repository.iter_files_bytes(repo_desired_files):
 
223
                yield result
 
224
        except errors.RevisionNotPresent, e:
 
225
            raise errors.NoSuchFile(e.revision_id)
 
226
 
 
227
    def annotate_iter(self, file_id,
 
228
                      default_revision=revision.CURRENT_REVISION):
 
229
        """See Tree.annotate_iter"""
 
230
        text_key = (file_id, self.get_file_revision(file_id))
 
231
        annotator = self._repository.texts.get_annotator()
 
232
        annotations = annotator.annotate_flat(text_key)
 
233
        return [(key[-1], line) for key, line in annotations]
222
234
 
223
235
 
224
236
class InterCHKRevisionTree(tree.InterTree):