##// END OF EJS Templates
phases: drop the list with phase of each rev, always comput phase sets...
Joerg Sonnenberger -
r35310:d1352633 default
parent child Browse files
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 = 3;
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 *phaseslist = NULL;
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 phaseslist = PyList_New(len);
689 if (phaseslist == NULL)
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, phaseslist, phasessetlist);
704 ret = PyTuple_Pack(2, phasessize, phasessetlist);
711 705
712 706 release:
713 Py_XDECREF(phaseslist);
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 # _phaserevs and _phasesets depend on changelog. what we need is to
692 # call _phasecache.invalidate() if '00changelog.i' was changed, but it
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._phaserevs = None
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 if len(phases) > 1:
219 revs = revs.copy() # only copy when needed
220 for p in phases[1:]:
221 revs.update(self._phasesets[p])
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 phase = self.phase
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._phaserevs = self._phaserevs
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', '_phaserevs', '_phasesets'):
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 revs = [public] * len(repo.changelog)
257 self._phaserevs = revs
258 self._populatephaseroots(repo)
259 for phase in trackedphases:
260 roots = list(map(repo.changelog.rev, self.phaseroots[phase]))
265 cl = repo.changelog
266 self._phasesets = [set() for phase in allphases]
267 roots = pycompat.maplist(cl.rev, self.phaseroots[secret])
261 268 if roots:
262 for rev in roots:
263 revs[rev] = phase
264 for rev in repo.changelog.descendants(roots):
265 revs[rev] = phase
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._phaserevs is None:
284 if self._phasesets is None:
270 285 try:
271 286 res = self._getphaserevsnative(repo)
272 self._phaserevs, self._phasesets = res
287 self._phasemaxrev, self._phasesets = res
273 288 except AttributeError:
274 289 self._computephaserevspure(repo)
275 290
276 291 def invalidate(self):
277 self._phaserevs = None
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 _phaserevs
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 phaserevs contents is certainly invalid (or at least we
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 _phaserevs initialized
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)
@@ -75,7 +75,7 b' def _importfrom(pkgname, modname):'
75 75 (r'cext', r'diffhelpers'): 1,
76 76 (r'cext', r'mpatch'): 1,
77 77 (r'cext', r'osutil'): 1,
78 (r'cext', r'parsers'): 3,
78 (r'cext', r'parsers'): 4,
79 79 }
80 80
81 81 # map import request to other package or module
General Comments 0
You need to be logged in to leave comments. Login now