Show More
@@ -883,7 +883,7 b' class queue(object):' | |||
|
883 | 883 | def finish(self, repo, revs): |
|
884 | 884 | # Manually trigger phase computation to ensure phasedefaults is |
|
885 | 885 | # executed before we remove the patches. |
|
886 |
repo._phase |
|
|
886 | repo._phasecache | |
|
887 | 887 | patches = self._revpatches(repo, sorted(revs)) |
|
888 | 888 | qfinished = self._cleanup(patches, len(patches)) |
|
889 | 889 | if qfinished and repo.ui.configbool('mq', 'secret', False): |
@@ -4378,7 +4378,7 b' def phase(ui, repo, *revs, **opts):' | |||
|
4378 | 4378 | nodes = [ctx.node() for ctx in repo.set('%ld', revs)] |
|
4379 | 4379 | if not nodes: |
|
4380 | 4380 | raise util.Abort(_('empty revision set')) |
|
4381 | olddata = repo._phaserev[:] | |
|
4381 | olddata = repo._phasecache.getphaserevs(repo)[:] | |
|
4382 | 4382 | phases.advanceboundary(repo, targetphase, nodes) |
|
4383 | 4383 | if opts['force']: |
|
4384 | 4384 | phases.retractboundary(repo, targetphase, nodes) |
@@ -4386,7 +4386,7 b' def phase(ui, repo, *revs, **opts):' | |||
|
4386 | 4386 | lock.release() |
|
4387 | 4387 | if olddata is not None: |
|
4388 | 4388 | changes = 0 |
|
4389 | newdata = repo._phaserev | |
|
4389 | newdata = repo._phasecache.getphaserevs(repo) | |
|
4390 | 4390 | changes = sum(o != newdata[i] for i, o in enumerate(olddata)) |
|
4391 | 4391 | rejected = [n for n in nodes |
|
4392 | 4392 | if newdata[repo[n].rev()] < targetphase] |
@@ -191,12 +191,7 b' class changectx(object):' | |||
|
191 | 191 | def bookmarks(self): |
|
192 | 192 | return self._repo.nodebookmarks(self._node) |
|
193 | 193 | def phase(self): |
|
194 | if self._rev == -1: | |
|
195 | return phases.public | |
|
196 | if self._rev >= len(self._repo._phaserev): | |
|
197 | # outdated cache | |
|
198 | del self._repo._phaserev | |
|
199 | return self._repo._phaserev[self._rev] | |
|
194 | return self._repo._phasecache.phase(self._repo, self._rev) | |
|
200 | 195 | def phasestr(self): |
|
201 | 196 | return phases.phasenames[self.phase()] |
|
202 | 197 | def mutable(self): |
@@ -105,7 +105,7 b' def findcommonoutgoing(repo, other, only' | |||
|
105 | 105 | og.commonheads, _any, _hds = commoninc |
|
106 | 106 | |
|
107 | 107 | # compute outgoing |
|
108 | if not repo._phaseroots[phases.secret]: | |
|
108 | if not repo._phasecache.phaseroots[phases.secret]: | |
|
109 | 109 | og.missingheads = onlyheads or repo.heads() |
|
110 | 110 | elif onlyheads is None: |
|
111 | 111 | # use visible heads as it should be cached |
@@ -41,7 +41,6 b' class localrepository(repo.repository):' | |||
|
41 | 41 | self.wopener = scmutil.opener(self.root) |
|
42 | 42 | self.baseui = baseui |
|
43 | 43 | self.ui = baseui.copy() |
|
44 | self._dirtyphases = False | |
|
45 | 44 | # A list of callback to shape the phase if no data were found. |
|
46 | 45 | # Callback are in the form: func(repo, roots) --> processed root. |
|
47 | 46 | # This list it to be filled by extension during repo setup |
@@ -182,22 +181,8 b' class localrepository(repo.repository):' | |||
|
182 | 181 | bookmarks.write(self) |
|
183 | 182 | |
|
184 | 183 | @storecache('phaseroots') |
|
185 |
def _phase |
|
|
186 | phaseroots, self._dirtyphases = phases.readroots( | |
|
187 | self, self._phasedefaults) | |
|
188 | return phaseroots | |
|
189 | ||
|
190 | @propertycache | |
|
191 | def _phaserev(self): | |
|
192 | cache = [phases.public] * len(self) | |
|
193 | for phase in phases.trackedphases: | |
|
194 | roots = map(self.changelog.rev, self._phaseroots[phase]) | |
|
195 | if roots: | |
|
196 | for rev in roots: | |
|
197 | cache[rev] = phase | |
|
198 | for rev in self.changelog.descendants(*roots): | |
|
199 | cache[rev] = phase | |
|
200 | return cache | |
|
184 | def _phasecache(self): | |
|
185 | return phases.phasecache(self, self._phasedefaults) | |
|
201 | 186 | |
|
202 | 187 | @storecache('00changelog.i') |
|
203 | 188 | def changelog(self): |
@@ -604,10 +589,11 b' class localrepository(repo.repository):' | |||
|
604 | 589 | |
|
605 | 590 | def known(self, nodes): |
|
606 | 591 | nm = self.changelog.nodemap |
|
592 | pc = self._phasecache | |
|
607 | 593 | result = [] |
|
608 | 594 | for n in nodes: |
|
609 | 595 | r = nm.get(n) |
|
610 |
resp = not (r is None or self |
|
|
596 | resp = not (r is None or pc.phase(self, r) >= phases.secret) | |
|
611 | 597 | result.append(resp) |
|
612 | 598 | return result |
|
613 | 599 | |
@@ -863,7 +849,6 b' class localrepository(repo.repository):' | |||
|
863 | 849 | pass |
|
864 | 850 | |
|
865 | 851 | delcache('_tagscache') |
|
866 | delcache('_phaserev') | |
|
867 | 852 | |
|
868 | 853 | self._branchcache = None # in UTF-8 |
|
869 | 854 | self._branchcachetip = None |
@@ -931,9 +916,8 b' class localrepository(repo.repository):' | |||
|
931 | 916 | |
|
932 | 917 | def unlock(): |
|
933 | 918 | self.store.write() |
|
934 |
if self |
|
|
935 |
|
|
|
936 | self._dirtyphases = False | |
|
919 | if '_phasecache' in vars(self): | |
|
920 | self._phasecache.write() | |
|
937 | 921 | for k, ce in self._filecache.items(): |
|
938 | 922 | if k == 'dirstate': |
|
939 | 923 | continue |
@@ -99,7 +99,7 b' Note: old client behave as publish serve' | |||
|
99 | 99 | """ |
|
100 | 100 | |
|
101 | 101 | import errno |
|
102 | from node import nullid, bin, hex, short | |
|
102 | from node import nullid, nullrev, bin, hex, short | |
|
103 | 103 | from i18n import _ |
|
104 | 104 | |
|
105 | 105 | allphases = public, draft, secret = range(3) |
@@ -124,7 +124,7 b' def _filterunknown(ui, changelog, phaser' | |||
|
124 | 124 | updated = True |
|
125 | 125 | return updated |
|
126 | 126 | |
|
127 | def readroots(repo, phasedefaults=None): | |
|
127 | def _readroots(repo, phasedefaults=None): | |
|
128 | 128 | """Read phase roots from disk |
|
129 | 129 | |
|
130 | 130 | phasedefaults is a list of fn(repo, roots) callable, which are |
@@ -156,15 +156,51 b' def readroots(repo, phasedefaults=None):' | |||
|
156 | 156 | dirty = True |
|
157 | 157 | return roots, dirty |
|
158 | 158 | |
|
159 | def writeroots(repo, phaseroots): | |
|
160 | """Write phase roots from disk""" | |
|
161 | f = repo.sopener('phaseroots', 'w', atomictemp=True) | |
|
162 | try: | |
|
163 | for phase, roots in enumerate(phaseroots): | |
|
164 | for h in roots: | |
|
165 | f.write('%i %s\n' % (phase, hex(h))) | |
|
166 | finally: | |
|
167 | f.close() | |
|
159 | class phasecache(object): | |
|
160 | def __init__(self, repo, phasedefaults): | |
|
161 | self.phaseroots, self.dirty = _readroots(repo, phasedefaults) | |
|
162 | self.opener = repo.sopener | |
|
163 | self._phaserevs = None | |
|
164 | ||
|
165 | def getphaserevs(self, repo, rebuild=False): | |
|
166 | if rebuild or self._phaserevs is None: | |
|
167 | revs = [public] * len(repo.changelog) | |
|
168 | for phase in trackedphases: | |
|
169 | roots = map(repo.changelog.rev, self.phaseroots[phase]) | |
|
170 | if roots: | |
|
171 | for rev in roots: | |
|
172 | revs[rev] = phase | |
|
173 | for rev in repo.changelog.descendants(*roots): | |
|
174 | revs[rev] = phase | |
|
175 | self._phaserevs = revs | |
|
176 | return self._phaserevs | |
|
177 | ||
|
178 | def invalidatephaserevs(self): | |
|
179 | self._phaserevs = None | |
|
180 | ||
|
181 | def phase(self, repo, rev): | |
|
182 | # We need a repo argument here to be able to build _phaserev | |
|
183 | # if necessary. The repository instance is not stored in | |
|
184 | # phasecache to avoid reference cycles. The changelog instance | |
|
185 | # is not stored because it is a filecache() property and can | |
|
186 | # be replaced without us being notified. | |
|
187 | if rev == nullrev: | |
|
188 | return public | |
|
189 | if self._phaserevs is None or rev >= len(self._phaserevs): | |
|
190 | self._phaserevs = self.getphaserevs(repo, rebuild=True) | |
|
191 | return self._phaserevs[rev] | |
|
192 | ||
|
193 | def write(self): | |
|
194 | if not self.dirty: | |
|
195 | return | |
|
196 | f = self.opener('phaseroots', 'w', atomictemp=True) | |
|
197 | try: | |
|
198 | for phase, roots in enumerate(self.phaseroots): | |
|
199 | for h in roots: | |
|
200 | f.write('%i %s\n' % (phase, hex(h))) | |
|
201 | finally: | |
|
202 | f.close() | |
|
203 | self.dirty = False | |
|
168 | 204 | |
|
169 | 205 | def advanceboundary(repo, targetphase, nodes): |
|
170 | 206 | """Add nodes to a phase changing other nodes phases if necessary. |
@@ -173,6 +209,8 b' def advanceboundary(repo, targetphase, n' | |||
|
173 | 209 | in the target phase or kept in a *lower* phase. |
|
174 | 210 | |
|
175 | 211 | Simplify boundary to contains phase roots only.""" |
|
212 | phcache = repo._phasecache | |
|
213 | ||
|
176 | 214 | delroots = [] # set of root deleted by this path |
|
177 | 215 | for phase in xrange(targetphase + 1, len(allphases)): |
|
178 | 216 | # filter nodes that are not in a compatible phase already |
@@ -181,16 +219,15 b' def advanceboundary(repo, targetphase, n' | |||
|
181 | 219 | nodes = [n for n in nodes if repo[n].phase() >= phase] |
|
182 | 220 | if not nodes: |
|
183 | 221 | break # no roots to move anymore |
|
184 |
roots = |
|
|
222 | roots = phcache.phaseroots[phase] | |
|
185 | 223 | olds = roots.copy() |
|
186 | 224 | ctxs = list(repo.set('roots((%ln::) - (%ln::%ln))', olds, olds, nodes)) |
|
187 | 225 | roots.clear() |
|
188 | 226 | roots.update(ctx.node() for ctx in ctxs) |
|
189 | 227 | if olds != roots: |
|
190 | 228 | # invalidate cache (we probably could be smarter here |
|
191 | if '_phaserev' in vars(repo): | |
|
192 | del repo._phaserev | |
|
193 | repo._dirtyphases = True | |
|
229 | phcache.invalidatephaserevs() | |
|
230 | phcache.dirty = True | |
|
194 | 231 | # some roots may need to be declared for lower phases |
|
195 | 232 | delroots.extend(olds - roots) |
|
196 | 233 | # declare deleted root in the target phase |
@@ -205,22 +242,23 b' def retractboundary(repo, targetphase, n' | |||
|
205 | 242 | in the target phase or kept in a *higher* phase. |
|
206 | 243 | |
|
207 | 244 | Simplify boundary to contains phase roots only.""" |
|
208 | currentroots = repo._phaseroots[targetphase] | |
|
245 | phcache = repo._phasecache | |
|
246 | ||
|
247 | currentroots = phcache.phaseroots[targetphase] | |
|
209 | 248 | newroots = [n for n in nodes if repo[n].phase() < targetphase] |
|
210 | 249 | if newroots: |
|
211 | 250 | currentroots.update(newroots) |
|
212 | 251 | ctxs = repo.set('roots(%ln::)', currentroots) |
|
213 | 252 | currentroots.intersection_update(ctx.node() for ctx in ctxs) |
|
214 | if '_phaserev' in vars(repo): | |
|
215 | del repo._phaserev | |
|
216 | repo._dirtyphases = True | |
|
253 | phcache.invalidatephaserevs() | |
|
254 | phcache.dirty = True | |
|
217 | 255 | |
|
218 | 256 | |
|
219 | 257 | def listphases(repo): |
|
220 | 258 | """List phases root for serialisation over pushkey""" |
|
221 | 259 | keys = {} |
|
222 | 260 | value = '%i' % draft |
|
223 | for root in repo._phaseroots[draft]: | |
|
261 | for root in repo._phasecache.phaseroots[draft]: | |
|
224 | 262 | keys[hex(root)] = value |
|
225 | 263 | |
|
226 | 264 | if repo.ui.configbool('phases', 'publish', True): |
@@ -263,7 +301,7 b' def pushphase(repo, nhex, oldphasestr, n' | |||
|
263 | 301 | def visibleheads(repo): |
|
264 | 302 | """return the set of visible head of this repo""" |
|
265 | 303 | # XXX we want a cache on this |
|
266 | sroots = repo._phaseroots[secret] | |
|
304 | sroots = repo._phasecache.phaseroots[secret] | |
|
267 | 305 | if sroots: |
|
268 | 306 | # XXX very slow revset. storing heads or secret "boundary" would help. |
|
269 | 307 | revset = repo.set('heads(not (%ln::))', sroots) |
@@ -279,7 +317,7 b' def visiblebranchmap(repo):' | |||
|
279 | 317 | """return a branchmap for the visible set""" |
|
280 | 318 | # XXX Recomputing this data on the fly is very slow. We should build a |
|
281 | 319 | # XXX cached version while computin the standard branchmap version. |
|
282 | sroots = repo._phaseroots[secret] | |
|
320 | sroots = repo._phasecache.phaseroots[secret] | |
|
283 | 321 | if sroots: |
|
284 | 322 | vbranchmap = {} |
|
285 | 323 | for branch, nodes in repo.branchmap().iteritems(): |
@@ -463,7 +463,8 b' def draft(repo, subset, x):' | |||
|
463 | 463 | """``draft()`` |
|
464 | 464 | Changeset in draft phase.""" |
|
465 | 465 | getargs(x, 0, 0, _("draft takes no arguments")) |
|
466 | return [r for r in subset if repo._phaserev[r] == phases.draft] | |
|
466 | pc = repo._phasecache | |
|
467 | return [r for r in subset if pc.phase(repo, r) == phases.draft] | |
|
467 | 468 | |
|
468 | 469 | def filelog(repo, subset, x): |
|
469 | 470 | """``filelog(pattern)`` |
@@ -852,7 +853,8 b' def public(repo, subset, x):' | |||
|
852 | 853 | """``public()`` |
|
853 | 854 | Changeset in public phase.""" |
|
854 | 855 | getargs(x, 0, 0, _("public takes no arguments")) |
|
855 | return [r for r in subset if repo._phaserev[r] == phases.public] | |
|
856 | pc = repo._phasecache | |
|
857 | return [r for r in subset if pc.phase(repo, r) == phases.public] | |
|
856 | 858 | |
|
857 | 859 | def remote(repo, subset, x): |
|
858 | 860 | """``remote([id [,path]])`` |
@@ -1031,7 +1033,8 b' def secret(repo, subset, x):' | |||
|
1031 | 1033 | """``secret()`` |
|
1032 | 1034 | Changeset in secret phase.""" |
|
1033 | 1035 | getargs(x, 0, 0, _("secret takes no arguments")) |
|
1034 | return [r for r in subset if repo._phaserev[r] == phases.secret] | |
|
1036 | pc = repo._phasecache | |
|
1037 | return [r for r in subset if pc.phase(repo, r) == phases.secret] | |
|
1035 | 1038 | |
|
1036 | 1039 | def sort(repo, subset, x): |
|
1037 | 1040 | """``sort(set[, [-]key...])`` |
General Comments 0
You need to be logged in to leave comments.
Login now