Show More
@@ -710,7 +710,7 b' void dirs_module_init(PyObject *mod);' | |||
|
710 | 710 | void manifest_module_init(PyObject *mod); |
|
711 | 711 | void revlog_module_init(PyObject *mod); |
|
712 | 712 | |
|
713 |
static const int version = |
|
|
713 | static const int version = 4; | |
|
714 | 714 | |
|
715 | 715 | static void module_init(PyObject *mod) |
|
716 | 716 | { |
@@ -628,7 +628,7 b' static PyObject *compute_phases_map_sets' | |||
|
628 | 628 | { |
|
629 | 629 | PyObject *roots = Py_None; |
|
630 | 630 | PyObject *ret = NULL; |
|
631 |
PyObject *phases |
|
|
631 | PyObject *phasessize = NULL; | |
|
632 | 632 | PyObject *phaseroots = NULL; |
|
633 | 633 | PyObject *phaseset = NULL; |
|
634 | 634 | PyObject *phasessetlist = NULL; |
@@ -685,12 +685,10 b' static PyObject *compute_phases_map_sets' | |||
|
685 | 685 | } |
|
686 | 686 | } |
|
687 | 687 | /* Transform phase list to a python list */ |
|
688 |
phases |
|
|
689 |
if (phases |
|
|
688 | phasessize = PyInt_FromLong(len); | |
|
689 | if (phasessize == NULL) | |
|
690 | 690 | goto release; |
|
691 | 691 | for (i = 0; i < len; i++) { |
|
692 | PyObject *phaseval; | |
|
693 | ||
|
694 | 692 | phase = phases[i]; |
|
695 | 693 | /* We only store the sets of phase for non public phase, the public phase |
|
696 | 694 | * is computed as a difference */ |
@@ -702,15 +700,11 b' static PyObject *compute_phases_map_sets' | |||
|
702 | 700 | PySet_Add(phaseset, rev); |
|
703 | 701 | Py_XDECREF(rev); |
|
704 | 702 | } |
|
705 | phaseval = PyInt_FromLong(phase); | |
|
706 | if (phaseval == NULL) | |
|
707 | goto release; | |
|
708 | PyList_SET_ITEM(phaseslist, i, phaseval); | |
|
709 | 703 | } |
|
710 |
ret = PyTuple_Pack(2, phases |
|
|
704 | ret = PyTuple_Pack(2, phasessize, phasessetlist); | |
|
711 | 705 | |
|
712 | 706 | release: |
|
713 |
Py_XDECREF(phases |
|
|
707 | Py_XDECREF(phasessize); | |
|
714 | 708 | Py_XDECREF(phasessetlist); |
|
715 | 709 | done: |
|
716 | 710 | free(phases); |
@@ -688,8 +688,8 b' class localrepository(object):' | |||
|
688 | 688 | def _activebookmark(self): |
|
689 | 689 | return self._bookmarks.active |
|
690 | 690 | |
|
691 |
# _phase |
|
|
692 |
# |
|
|
691 | # _phasesets depend on changelog. what we need is to call | |
|
692 | # _phasecache.invalidate() if '00changelog.i' was changed, but it | |
|
693 | 693 | # can't be easily expressed in filecache mechanism. |
|
694 | 694 | @storecache('phaseroots', '00changelog.i') |
|
695 | 695 | def _phasecache(self): |
@@ -115,6 +115,7 b' from .node import (' | |||
|
115 | 115 | ) |
|
116 | 116 | from . import ( |
|
117 | 117 | error, |
|
118 | pycompat, | |
|
118 | 119 | smartset, |
|
119 | 120 | txnutil, |
|
120 | 121 | util, |
@@ -202,7 +203,7 b' class phasecache(object):' | |||
|
202 | 203 | if _load: |
|
203 | 204 | # Cheap trick to allow shallow-copy without copy module |
|
204 | 205 | self.phaseroots, self.dirty = _readroots(repo, phasedefaults) |
|
205 |
self._phaserev |
|
|
206 | self._phasemaxrev = nullrev | |
|
206 | 207 | self._phasesets = None |
|
207 | 208 | self.filterunknown(repo) |
|
208 | 209 | self.opener = repo.svfs |
@@ -210,23 +211,30 b' class phasecache(object):' | |||
|
210 | 211 | def getrevset(self, repo, phases): |
|
211 | 212 | """return a smartset for the given phases""" |
|
212 | 213 | self.loadphaserevs(repo) # ensure phase's sets are loaded |
|
213 | ||
|
214 | if self._phasesets and all(self._phasesets[p] is not None | |
|
215 | for p in phases): | |
|
216 | # fast path - use _phasesets | |
|
217 | revs = self._phasesets[phases[0]] | |
|
218 |
|
|
|
219 | revs = revs.copy() # only copy when needed | |
|
220 | for p in phases[1:]: | |
|
221 |
|
|
|
214 | phases = set(phases) | |
|
215 | if public not in phases: | |
|
216 | # fast path: _phasesets contains the interesting sets, | |
|
217 | # might only need a union and post-filtering. | |
|
218 | if len(phases) == 1: | |
|
219 | [p] = phases | |
|
220 | revs = self._phasesets[p] | |
|
221 | else: | |
|
222 | revs = set.union(*[self._phasesets[p] for p in phases]) | |
|
222 | 223 | if repo.changelog.filteredrevs: |
|
223 | 224 | revs = revs - repo.changelog.filteredrevs |
|
224 | 225 | return smartset.baseset(revs) |
|
225 | 226 | else: |
|
226 | # slow path - enumerate all revisions | |
|
227 |
|
|
|
228 | revs = (r for r in repo if phase(repo, r) in phases) | |
|
229 | return smartset.generatorset(revs, iterasc=True) | |
|
227 | phases = set(allphases).difference(phases) | |
|
228 | if not phases: | |
|
229 | return smartset.fullreposet(repo) | |
|
230 | if len(phases) == 1: | |
|
231 | [p] = phases | |
|
232 | revs = self._phasesets[p] | |
|
233 | else: | |
|
234 | revs = set.union(*[self._phasesets[p] for p in phases]) | |
|
235 | if not revs: | |
|
236 | return smartset.fullreposet(repo) | |
|
237 | return smartset.fullreposet(repo).filter(lambda r: r not in revs) | |
|
230 | 238 | |
|
231 | 239 | def copy(self): |
|
232 | 240 | # Shallow copy meant to ensure isolation in |
@@ -235,13 +243,14 b' class phasecache(object):' | |||
|
235 | 243 | ph.phaseroots = self.phaseroots[:] |
|
236 | 244 | ph.dirty = self.dirty |
|
237 | 245 | ph.opener = self.opener |
|
238 |
ph._phaserev |
|
|
246 | ph._phasemaxrev = self._phasemaxrev | |
|
239 | 247 | ph._phasesets = self._phasesets |
|
240 | 248 | return ph |
|
241 | 249 | |
|
242 | 250 | def replace(self, phcache): |
|
243 | 251 | """replace all values in 'self' with content of phcache""" |
|
244 |
for a in ('phaseroots', 'dirty', 'opener', '_phaserev |
|
|
252 | for a in ('phaseroots', 'dirty', 'opener', '_phasemaxrev', | |
|
253 | '_phasesets'): | |
|
245 | 254 | setattr(self, a, getattr(phcache, a)) |
|
246 | 255 | |
|
247 | 256 | def _getphaserevsnative(self, repo): |
@@ -253,42 +262,38 b' class phasecache(object):' | |||
|
253 | 262 | |
|
254 | 263 | def _computephaserevspure(self, repo): |
|
255 | 264 | repo = repo.unfiltered() |
|
256 |
|
|
|
257 |
self._phase |
|
|
258 | self._populatephaseroots(repo) | |
|
259 | for phase in trackedphases: | |
|
260 | roots = list(map(repo.changelog.rev, self.phaseroots[phase])) | |
|
261 |
|
|
|
262 |
|
|
|
263 | revs[rev] = phase | |
|
264 | for rev in repo.changelog.descendants(roots): | |
|
265 | revs[rev] = phase | |
|
265 | cl = repo.changelog | |
|
266 | self._phasesets = [set() for phase in allphases] | |
|
267 | roots = pycompat.maplist(cl.rev, self.phaseroots[secret]) | |
|
268 | if roots: | |
|
269 | ps = set(cl.descendants(roots)) | |
|
270 | for root in roots: | |
|
271 | ps.add(root) | |
|
272 | self._phasesets[secret] = ps | |
|
273 | roots = pycompat.maplist(cl.rev, self.phaseroots[draft]) | |
|
274 | if roots: | |
|
275 | ps = set(cl.descendants(roots)) | |
|
276 | for root in roots: | |
|
277 | ps.add(root) | |
|
278 | ps.difference_update(self._phasesets[secret]) | |
|
279 | self._phasesets[draft] = ps | |
|
280 | self._phasemaxrev = len(cl) | |
|
266 | 281 | |
|
267 | 282 | def loadphaserevs(self, repo): |
|
268 | 283 | """ensure phase information is loaded in the object""" |
|
269 |
if self._phase |
|
|
284 | if self._phasesets is None: | |
|
270 | 285 | try: |
|
271 | 286 | res = self._getphaserevsnative(repo) |
|
272 |
self._phaserev |
|
|
287 | self._phasemaxrev, self._phasesets = res | |
|
273 | 288 | except AttributeError: |
|
274 | 289 | self._computephaserevspure(repo) |
|
275 | 290 | |
|
276 | 291 | def invalidate(self): |
|
277 |
self._phaserev |
|
|
292 | self._phasemaxrev = nullrev | |
|
278 | 293 | self._phasesets = None |
|
279 | 294 | |
|
280 | def _populatephaseroots(self, repo): | |
|
281 | """Fills the _phaserevs cache with phases for the roots. | |
|
282 | """ | |
|
283 | cl = repo.changelog | |
|
284 | phaserevs = self._phaserevs | |
|
285 | for phase in trackedphases: | |
|
286 | roots = map(cl.rev, self.phaseroots[phase]) | |
|
287 | for root in roots: | |
|
288 | phaserevs[root] = phase | |
|
289 | ||
|
290 | 295 | def phase(self, repo, rev): |
|
291 |
# We need a repo argument here to be able to build _phase |
|
|
296 | # We need a repo argument here to be able to build _phasesets | |
|
292 | 297 | # if necessary. The repository instance is not stored in |
|
293 | 298 | # phasecache to avoid reference cycles. The changelog instance |
|
294 | 299 | # is not stored because it is a filecache() property and can |
@@ -297,10 +302,13 b' class phasecache(object):' | |||
|
297 | 302 | return public |
|
298 | 303 | if rev < nullrev: |
|
299 | 304 | raise ValueError(_('cannot lookup negative revision')) |
|
300 | if self._phaserevs is None or rev >= len(self._phaserevs): | |
|
305 | if rev >= self._phasemaxrev: | |
|
301 | 306 | self.invalidate() |
|
302 | 307 | self.loadphaserevs(repo) |
|
303 | return self._phaserevs[rev] | |
|
308 | for phase in trackedphases: | |
|
309 | if rev in self._phasesets[phase]: | |
|
310 | return phase | |
|
311 | return public | |
|
304 | 312 | |
|
305 | 313 | def write(self): |
|
306 | 314 | if not self.dirty: |
@@ -455,10 +463,10 b' class phasecache(object):' | |||
|
455 | 463 | if filtered: |
|
456 | 464 | self.dirty = True |
|
457 | 465 | # filterunknown is called by repo.destroyed, we may have no changes in |
|
458 |
# root but |
|
|
466 | # root but _phasesets contents is certainly invalid (or at least we | |
|
459 | 467 | # have not proper way to check that). related to issue 3858. |
|
460 | 468 | # |
|
461 |
# The other caller is __init__ that have no _phase |
|
|
469 | # The other caller is __init__ that have no _phasesets initialized | |
|
462 | 470 | # anyway. If this change we should consider adding a dedicated |
|
463 | 471 | # "destroyed" function to phasecache or a proper cache key mechanism |
|
464 | 472 | # (see branchmap one) |
General Comments 0
You need to be logged in to leave comments.
Login now