annotate mercurial/repoview.py @ 24565:2f7cb6e6acdd

repoview: improve compute staticblockers perf Previously we would compute the repoview's static blockers by finding all the children of hidden commits that were not hidden. This was O(number of commits since first hidden change) since 'children' requires walking every commit from tip until the first hidden change. The new algorithm walks all heads down until it sees a public commit. This makes the computation O(number of draft) commits, which is much faster in large repositories with a large number of commits and a low number of drafts. On a large repo with 1000+ obsolete markers and the earliest draft commit around tip~200000, this improves computehidden perf by 200x (2s to 0.01s).
author Durham Goode <durham@fb.com>
date Wed, 01 Apr 2015 12:50:10 -0700
parents a41902aac76d
children 9e558b788daa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
1 # repoview.py - Filtered view of a localrepo object
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
2 #
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
4 # Logilab SA <contact@logilab.fr>
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
5 #
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
6 # This software may be used and distributed according to the terms of the
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
7 # GNU General Public License version 2 or any later version.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
8
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
9 import collections
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
10 import copy
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
11 import error
18102
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
12 import phases
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
13 import util
20405
cb63aa14aaf7 repoview: use repo.revs() instead of a private revset method
Augie Fackler <raf@durin42.com>
parents: 20196
diff changeset
14 import obsolete
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
15 import struct
20939
388af5d4e90c repoview: improve performance for computehidden (issue4206)
Sean Farley <sean.michael.farley@gmail.com>
parents: 20807
diff changeset
16 import tags as tagsmod
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
17 from node import nullrev
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
18
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
19 def hideablerevs(repo):
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
20 """Revisions candidates to be hidden
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
21
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
22 This is a standalone function to help extensions to wrap it."""
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
23 return obsolete.getrevs(repo, 'obsolete')
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
24
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
25 def _getstatichidden(repo):
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
26 """Cacheable revisions blocking hidden changesets from being filtered.
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
27
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
28 Additional non-cached hidden blockers are computed in _getdynamicblockers.
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
29 This is a standalone function to help extensions to wrap it."""
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
30 assert not repo.changelog.filteredrevs
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
31 hideable = hideablerevs(repo)
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
32 if hideable:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
33 actuallyhidden = {}
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
34 getphase = repo._phasecache.phase
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
35 getparentrevs = repo.changelog.parentrevs
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
36 queue = collections.deque((r, False) for r in repo.changelog.headrevs())
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
37 while queue:
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
38 rev, blocked = queue.popleft()
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
39 phase = getphase(repo, rev)
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
40 # Skip nodes which are public (guaranteed to not be hidden) and
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
41 # nodes which have already been processed and won't be blocked by
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
42 # the previous node.
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
43 if phase == 0 or (not blocked and rev in actuallyhidden):
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
44 continue
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
45 if rev in hideable:
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
46 if blocked:
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
47 actuallyhidden[rev] = False
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
48 else:
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
49 actuallyhidden.setdefault(rev, True)
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
50 else:
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
51 blocked = True
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
52
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
53 for parent in (p for p in getparentrevs(rev) if p != nullrev):
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
54 queue.append((parent, blocked))
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
55 return set(rev for rev, hidden in actuallyhidden.iteritems() if hidden)
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
56
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
57 def _getdynamicblockers(repo):
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
58 """Non-cacheable revisions blocking hidden changesets from being filtered.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
59
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
60 Get revisions that will block hidden changesets and are likely to change,
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
61 but unlikely to create hidden blockers. They won't be cached, so be careful
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
62 with adding additional computation."""
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
63
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
64 cl = repo.changelog
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
65 blockers = set()
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
66 blockers.update([par.rev() for par in repo[None].parents()])
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
67 blockers.update([cl.rev(bm) for bm in repo._bookmarks.values()])
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
68
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
69 tags = {}
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
70 tagsmod.readlocaltags(repo.ui, repo, tags, {})
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
71 if tags:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
72 rev, nodemap = cl.rev, cl.nodemap
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
73 blockers.update(rev(t[0]) for t in tags.values() if t[0] in nodemap)
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
74 return blockers
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
75
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
76 cacheversion = 1
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
77 cachefile = 'cache/hidden'
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
78
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
79 def cachehash(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
80 """return sha1 hash of repository data to identify a valid cache.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
81
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
82 We calculate a sha1 of repo heads and the content of the obsstore and write
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
83 it to the cache. Upon reading we can easily validate by checking the hash
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
84 against the stored one and discard the cache in case the hashes don't match.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
85 """
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
86 h = util.sha1()
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
87 h.update(''.join(repo.heads()))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
88 h.update(str(hash(frozenset(hideable))))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
89 return h.digest()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
90
23378
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
91 def _writehiddencache(cachefile, cachehash, hidden):
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
92 """write hidden data to a cache file"""
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
93 data = struct.pack('>%ii' % len(hidden), *sorted(hidden))
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
94 cachefile.write(struct.pack(">H", cacheversion))
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
95 cachefile.write(cachehash)
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
96 cachefile.write(data)
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
97
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
98 def trywritehiddencache(repo, hideable, hidden):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
99 """write cache of hidden changesets to disk
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
100
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
101 Will not write the cache if a wlock cannot be obtained lazily.
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
102 The cache consists of a head of 22byte:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
103 2 byte version number of the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
104 20 byte sha1 to validate the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
105 n*4 byte hidden revs
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
106 """
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
107 wlock = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
108 try:
22174
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
109 try:
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
110 wlock = repo.wlock(wait=False)
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
111 # write cache to file
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
112 newhash = cachehash(repo, hideable)
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
113 fh = repo.vfs.open(cachefile, 'w+b', atomictemp=True)
23378
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
114 _writehiddencache(fh, newhash, hidden)
22174
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
115 except (IOError, OSError):
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
116 repo.ui.debug('error writing hidden changesets cache')
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
117 except error.LockHeld:
0cc2db64c335 repoview: fix try/except/finally for py2.4
Matt Mackall <mpm@selenic.com>
parents: 22151
diff changeset
118 repo.ui.debug('cannot obtain lock to write hidden changesets cache')
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
119 finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
120 if fh:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
121 fh.close()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
122 if wlock:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
123 wlock.release()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
124
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
125 def tryreadcache(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
126 """read a cache if the cache exists and is valid, otherwise returns None."""
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
127 hidden = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
128 try:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
129 if repo.vfs.exists(cachefile):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
130 fh = repo.vfs.open(cachefile, 'rb')
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
131 version, = struct.unpack(">H", fh.read(2))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
132 oldhash = fh.read(20)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
133 newhash = cachehash(repo, hideable)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
134 if (cacheversion, oldhash) == (version, newhash):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
135 # cache is valid, so we can start reading the hidden revs
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
136 data = fh.read()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
137 count = len(data) / 4
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
138 hidden = frozenset(struct.unpack('>%ii' % count, data))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
139 return hidden
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
140 finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
141 if fh:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
142 fh.close()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
143
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
144 def computehidden(repo):
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
145 """compute the set of hidden revision to filter
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
146
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
147 During most operation hidden should be filtered."""
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
148 assert not repo.changelog.filteredrevs
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
149
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
150 hidden = frozenset()
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
151 hideable = hideablerevs(repo)
18272
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
152 if hideable:
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
153 cl = repo.changelog
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
154 hidden = tryreadcache(repo, hideable)
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
155 if hidden is None:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
156 hidden = frozenset(_getstatichidden(repo))
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
157 trywritehiddencache(repo, hideable, hidden)
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
158
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
159 # check if we have wd parents, bookmarks or tags pointing to hidden
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
160 # changesets and remove those.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
161 dynamic = hidden & _getdynamicblockers(repo)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
162 if dynamic:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
163 blocked = cl.ancestors(dynamic, inclusive=True)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
164 hidden = frozenset(r for r in hidden if r not in blocked)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
165 return hidden
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
166
18102
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
167 def computeunserved(repo):
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
168 """compute the set of revision that should be filtered when used a server
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
169
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
170 Secret and hidden changeset should not pretend to be here."""
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
171 assert not repo.changelog.filteredrevs
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
172 # fast path in simple case to avoid impact of non optimised code
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
173 hiddens = filterrevs(repo, 'visible')
18273
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
174 if phases.hassecret(repo):
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
175 cl = repo.changelog
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
176 secret = phases.secret
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
177 getphase = repo._phasecache.phase
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
178 first = min(cl.rev(n) for n in repo._phasecache.phaseroots[secret])
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
179 revs = cl.revs(start=first)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
180 secrets = set(r for r in revs if getphase(repo, r) >= secret)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
181 return frozenset(hiddens | secrets)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
182 else:
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
183 return hiddens
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
184
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
185 def computemutable(repo):
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
186 """compute the set of revision that should be filtered when used a server
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
187
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
188 Secret and hidden changeset should not pretend to be here."""
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
189 assert not repo.changelog.filteredrevs
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
190 # fast check to avoid revset call on huge repo
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
191 if util.any(repo._phasecache.phaseroots[1:]):
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
192 getphase = repo._phasecache.phase
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
193 maymutable = filterrevs(repo, 'base')
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
194 return frozenset(r for r in maymutable if getphase(repo, r))
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
195 return frozenset()
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
196
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
197 def computeimpactable(repo):
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
198 """Everything impactable by mutable revision
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
199
18462
593eb3786165 documentation: update to new filter names
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18445
diff changeset
200 The immutable filter still have some chance to get invalidated. This will
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
201 happen when:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
202
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
203 - you garbage collect hidden changeset,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
204 - public phase is moved backward,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
205 - something is changed in the filtering (this could be fixed)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
206
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
207 This filter out any mutable changeset and any public changeset that may be
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
208 impacted by something happening to a mutable revision.
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
209
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
210 This is achieved by filtered everything with a revision number egal or
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
211 higher than the first mutable changeset is filtered."""
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
212 assert not repo.changelog.filteredrevs
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
213 cl = repo.changelog
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
214 firstmutable = len(cl)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
215 for roots in repo._phasecache.phaseroots[1:]:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
216 if roots:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
217 firstmutable = min(firstmutable, min(cl.rev(r) for r in roots))
18443
64848f7fb764 repoview: protect `base` computation from weird phase root
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18382
diff changeset
218 # protect from nullrev root
64848f7fb764 repoview: protect `base` computation from weird phase root
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18382
diff changeset
219 firstmutable = max(0, firstmutable)
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
220 return frozenset(xrange(firstmutable, len(cl)))
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
221
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
222 # function to compute filtered set
20196
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
223 #
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 20405
diff changeset
224 # When adding a new filter you MUST update the table at:
20196
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
225 # mercurial.branchmap.subsettable
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
226 # Otherwise your filter will have to recompute all its branches cache
59198508b0bd filter: add a comment so that people do not forget to update subsettable
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 20032
diff changeset
227 # from scratch (very slow).
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
228 filtertable = {'visible': computehidden,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
229 'served': computeunserved,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
230 'immutable': computemutable,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
231 'base': computeimpactable}
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
232
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
233 def filterrevs(repo, filtername):
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
234 """returns set of filtered revision for this filter name"""
18101
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
235 if filtername not in repo.filteredrevcache:
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
236 func = filtertable[filtername]
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
237 repo.filteredrevcache[filtername] = func(repo.unfiltered())
a464deecc9dd clfilter: add a cache on repo for set of revision to filter for a given set.
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18100
diff changeset
238 return repo.filteredrevcache[filtername]
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
239
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
240 class repoview(object):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
241 """Provide a read/write view of a repo through a filtered changelog
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
242
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
243 This object is used to access a filtered version of a repository without
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
244 altering the original repository object itself. We can not alter the
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
245 original object for two main reasons:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
246 - It prevents the use of a repo with multiple filters at the same time. In
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
247 particular when multiple threads are involved.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
248 - It makes scope of the filtering harder to control.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
249
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
250 This object behaves very closely to the original repository. All attribute
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
251 operations are done on the original repository:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
252 - An access to `repoview.someattr` actually returns `repo.someattr`,
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
253 - A write to `repoview.someattr` actually sets value of `repo.someattr`,
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
254 - A deletion of `repoview.someattr` actually drops `someattr`
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
255 from `repo.__dict__`.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
256
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
257 The only exception is the `changelog` property. It is overridden to return
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
258 a (surface) copy of `repo.changelog` with some revisions filtered. The
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
259 `filtername` attribute of the view control the revisions that need to be
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
260 filtered. (the fact the changelog is copied is an implementation detail).
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
261
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
262 Unlike attributes, this object intercepts all method calls. This means that
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
263 all methods are run on the `repoview` object with the filtered `changelog`
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
264 property. For this purpose the simple `repoview` class must be mixed with
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
265 the actual class of the repository. This ensures that the resulting
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
266 `repoview` object have the very same methods than the repo object. This
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
267 leads to the property below.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
268
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
269 repoview.method() --> repo.__class__.method(repoview)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
270
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
271 The inheritance has to be done dynamically because `repo` can be of any
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
272 subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
273 """
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
274
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
275 def __init__(self, repo, filtername):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
276 object.__setattr__(self, '_unfilteredrepo', repo)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
277 object.__setattr__(self, 'filtername', filtername)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
278 object.__setattr__(self, '_clcachekey', None)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
279 object.__setattr__(self, '_clcache', None)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
280
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
281 # not a propertycache on purpose we shall implement a proper cache later
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
282 @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
283 def changelog(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
284 """return a filtered version of the changeset
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
285
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
286 this changelog must not be used for writing"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
287 # some cache may be implemented later
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
288 unfi = self._unfilteredrepo
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
289 unfichangelog = unfi.changelog
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
290 revs = filterrevs(unfi, self.filtername)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
291 cl = self._clcache
24154
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
292 newkey = (len(unfichangelog), unfichangelog.tip(), hash(revs),
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
293 unfichangelog._delayed)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
294 if cl is not None:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
295 # we need to check curkey too for some obscure reason.
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
296 # MQ test show a corruption of the underlying repo (in _clcache)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
297 # without change in the cachekey.
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
298 oldfilter = cl.filteredrevs
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
299 try:
22317
e1d5fcab58b6 repoview: fix typo in repoview.changelog
Mike Hommey <mh@glandium.org>
parents: 22106
diff changeset
300 cl.filteredrevs = () # disable filtering for tip
24154
a41902aac76d repoview: invalidate cached changelog if _delayed changes (issue4549)
Matt Mackall <mpm@selenic.com>
parents: 23636
diff changeset
301 curkey = (len(cl), cl.tip(), hash(oldfilter), cl._delayed)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
302 finally:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
303 cl.filteredrevs = oldfilter
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
304 if newkey != self._clcachekey or newkey != curkey:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
305 cl = None
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
306 # could have been made None by the previous if
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
307 if cl is None:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
308 cl = copy.copy(unfichangelog)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
309 cl.filteredrevs = revs
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
310 object.__setattr__(self, '_clcache', cl)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
311 object.__setattr__(self, '_clcachekey', newkey)
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
312 return cl
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
313
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
314 def unfiltered(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
315 """Return an unfiltered version of a repo"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
316 return self._unfilteredrepo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
317
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
318 def filtered(self, name):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
319 """Return a filtered version of a repository"""
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
320 if name == self.filtername:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
321 return self
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
322 return self.unfiltered().filtered(name)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
323
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
324 # everything access are forwarded to the proxied repo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
325 def __getattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
326 return getattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
327
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
328 def __setattr__(self, attr, value):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
329 return setattr(self._unfilteredrepo, attr, value)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
330
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
331 def __delattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
332 return delattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
333
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
334 # The `requirements` attribute is initialized during __init__. But
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
335 # __getattr__ won't be called as it also exists on the class. We need
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
336 # explicit forwarding to main repo here
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
337 @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
338 def requirements(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
339 return self._unfilteredrepo.requirements