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