Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/context.py @ 17469:fb72eec7efd8
obsolete: introduce caches for all meaningful sets
This changeset introduces caches on the `obsstore` that keeps track of sets of
revisions meaningful for obsolescence related logics. For now they are:
- obsolete: changesets used as precursors (and not public),
- extinct: obsolete changesets with osbolete descendants only,
- unstable: non obsolete changesets with obsolete ancestors.
The cache is accessed using the `getobscache(repo, '<set-name>')` function which
builds the cache on demand. The `clearobscaches(repo)` function takes care of
clearing the caches if any.
Caches are cleared when one of these events happens:
- a new marker is added,
- a new changeset is added,
- some changesets are made public,
- some public changesets are demoted to draft or secret.
Declaration of more sets is made easy because we will have to handle at least
two other "troubles" (latecomer and conflicting).
Caches are now used by revset and changectx. It is usually not much more
expensive to compute the whole set than to check the property of a few elements.
The performance boost is welcome in case we apply obsolescence logic on a lot of
revisions. This makes the feature usable!
author | Pierre-Yves David <pierre-yves.david@logilab.fr> |
---|---|
date | Tue, 28 Aug 2012 20:52:04 +0200 |
parents | 57c6c24b9bc4 |
children | 3a524b647897 |
comparison
equal
deleted
inserted
replaced
17460:a306837f8c87 | 17469:fb72eec7efd8 |
---|---|
9 from i18n import _ | 9 from i18n import _ |
10 import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases | 10 import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases |
11 import copies | 11 import copies |
12 import match as matchmod | 12 import match as matchmod |
13 import os, errno, stat | 13 import os, errno, stat |
14 import obsolete as obsmod | |
14 | 15 |
15 propertycache = util.propertycache | 16 propertycache = util.propertycache |
16 | 17 |
17 class changectx(object): | 18 class changectx(object): |
18 """A changecontext object makes access to data related to a particular | 19 """A changecontext object makes access to data related to a particular |
230 for d in self._repo.changelog.descendants([self._rev]): | 231 for d in self._repo.changelog.descendants([self._rev]): |
231 yield changectx(self._repo, d) | 232 yield changectx(self._repo, d) |
232 | 233 |
233 def obsolete(self): | 234 def obsolete(self): |
234 """True if the changeset is obsolete""" | 235 """True if the changeset is obsolete""" |
235 return (self.node() in self._repo.obsstore.precursors | 236 return self.rev() in obsmod.getobscache(self._repo, 'obsolete') |
236 and self.phase() > phases.public) | |
237 | 237 |
238 def extinct(self): | 238 def extinct(self): |
239 """True if the changeset is extinct""" | 239 """True if the changeset is extinct""" |
240 # We should just compute a cache and check against it. | 240 return self.rev() in obsmod.getobscache(self._repo, 'extinct') |
241 # See revset implementation for details. | |
242 # | |
243 # But this naive implementation does not require cache | |
244 if self.phase() <= phases.public: | |
245 return False | |
246 if not self.obsolete(): | |
247 return False | |
248 for desc in self.descendants(): | |
249 if not desc.obsolete(): | |
250 return False | |
251 return True | |
252 | 241 |
253 def unstable(self): | 242 def unstable(self): |
254 """True if the changeset is not obsolete but it's ancestor are""" | 243 """True if the changeset is not obsolete but it's ancestor are""" |
255 # We should just compute /(obsolete()::) - obsolete()/ | 244 return self.rev() in obsmod.getobscache(self._repo, 'unstable') |
256 # and keep it in a cache. | |
257 # | |
258 # But this naive implementation does not require cache | |
259 if self.phase() <= phases.public: | |
260 return False | |
261 if self.obsolete(): | |
262 return False | |
263 for anc in self.ancestors(): | |
264 if anc.obsolete(): | |
265 return True | |
266 return False | |
267 | 245 |
268 def _fileinfo(self, path): | 246 def _fileinfo(self, path): |
269 if '_manifest' in self.__dict__: | 247 if '_manifest' in self.__dict__: |
270 try: | 248 try: |
271 return self._manifest[path], self._manifest.flags(path) | 249 return self._manifest[path], self._manifest.flags(path) |