annotate mercurial/repoview.py @ 30978:fdecd24ca4dc

ui: log time spent blocked on stdio We use a wrapper around Mercurial at Facebook that logs key statistics (like elpased time) to our standard performance tooling. This is less useful than it could be, because we currently can't tell when a command is slow because we need to fix Mercurial versus when a command is slow because the user isn't interacting quickly. Teach Mercurial to log the time it spends blocked, so that our tooling can pick it up and submit it with the elapsed time - we can then do the math in our tooling to see if Mercurial is slow, or if the user simply failed to interact. Combining this with the command duration log means that we can ensure that we concentrate performance efforts on the things that bite Facebook users. The perfwrite microbenchmark shifts from: Linux: ! wall 3.213560 comb 0.410000 user 0.350000 sys 0.060000 (best of 4) Mac: ! wall 0.342325 comb 0.180000 user 0.110000 sys 0.070000 (best of 20) before this change to: ! wall 3.478070 comb 0.500000 user 0.420000 sys 0.080000 (best of 3) Mac: ! wall 0.218112 comb 0.220000 user 0.150000 sys 0.070000 (best of 15) showing a small hit in comb time, but firmly in the noise on wall time.
author Simon Farnsworth <simonfar@fb.com>
date Wed, 15 Feb 2017 13:50:06 -0800
parents 0d83ad967bf8
children 20027be9f23d
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
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
9 from __future__ import absolute_import
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
10
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
11 import copy
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29040
diff changeset
12 import hashlib
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
13 import heapq
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
14 import struct
25972
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
15
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
16 from .node import nullrev
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
17 from . import (
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
18 error,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
19 obsolete,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
20 phases,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
21 tags as tagsmod,
f279191124f3 repoview: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25149
diff changeset
22 )
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
23
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
24 def hideablerevs(repo):
28780
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
25 """Revision candidates to be hidden
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
26
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
27 This is a standalone function to allow extensions to wrap it.
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
28
28780
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
29 Because we use the set of immutable changesets as a fallback subset in
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
30 branchmap (see mercurial.branchmap.subsettable), you cannot set "public"
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
31 changesets as "hideable". Doing so would break multiple code assertions and
faff8c2b5ee3 hideablerevs: expand docstring to warn about possible traps
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28265
diff changeset
32 lead to crashes."""
18293
1f35d6737ed8 repoview: extract hideable revision computation in a dedicated function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18274
diff changeset
33 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
34
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
35 def _getstatichidden(repo):
24615
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
36 """Revision to be hidden (disregarding dynamic blocker)
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
37
24615
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
38 To keep a consistent graph, we cannot hide any revisions with
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
39 non-hidden descendants. This function computes the set of
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
40 revisions that could be hidden while keeping the graph consistent.
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
41
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
42 A second pass will be done to apply "dynamic blocker" like bookmarks or
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
43 working directory parents.
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
44
9e558b788daa repoview: update documentation of _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24565
diff changeset
45 """
20940
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
46 assert not repo.changelog.filteredrevs
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
47 hidden = set(hideablerevs(repo))
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
48 if hidden:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
49 getphase = repo._phasecache.phase
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
50 getparentrevs = repo.changelog.parentrevs
24618
cde57a8d8fe7 repoview: directly skip public head in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24617
diff changeset
51 # Skip heads which are public (guaranteed to not be hidden)
cde57a8d8fe7 repoview: directly skip public head in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24617
diff changeset
52 heap = [-r for r in repo.changelog.headrevs() if getphase(repo, r)]
24616
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
53 heapq.heapify(heap)
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
54 heappop = heapq.heappop
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
55 heappush = heapq.heappush
24620
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
56 seen = set() # no need to init it with heads, they have no children
24616
72d34c5a6614 repoview: use a heap in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24615
diff changeset
57 while heap:
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
58 rev = -heappop(heap)
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
59 # All children have been processed so at that point, if no children
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
60 # removed 'rev' from the 'hidden' set, 'rev' is going to be hidden.
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
61 blocker = rev not in hidden
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
62 for parent in getparentrevs(rev):
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
63 if parent == nullrev:
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
64 continue
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
65 if blocker:
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
66 # If visible, ensure parent will be visible too
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
67 hidden.discard(parent)
24620
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
68 # - Avoid adding the same revision twice
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
69 # - Skip nodes which are public (guaranteed to not be hidden)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
70 pre = len(seen)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
71 seen.add(parent)
7c6f9097e2e0 repoview: avoid processing the same rev twice in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24619
diff changeset
72 if pre < len(seen) and getphase(repo, rev):
24619
ad6dea5d96f2 repoview: skip public parent earlier in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24618
diff changeset
73 heappush(heap, -parent)
24617
f76595f6ed7c repoview: simplify process in _getstatichidden
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24616
diff changeset
74 return hidden
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
75
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
76 def _getdynamicblockers(repo):
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
77 """Non-cacheable revisions blocking hidden changesets from being filtered.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
78
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
79 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
80 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
81 with adding additional computation."""
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
82
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
83 cl = repo.changelog
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
84 blockers = set()
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
85 blockers.update([par.rev() for par in repo[None].parents()])
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
86 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
87
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
88 tags = {}
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
89 tagsmod.readlocaltags(repo.ui, repo, tags, {})
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
90 if tags:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
91 rev, nodemap = cl.rev, cl.nodemap
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
92 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
93 return blockers
b0822c23e80a repoview: add _gethiddenblockers method
Sean Farley <sean.michael.farley@gmail.com>
parents: 20939
diff changeset
94
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
95 cacheversion = 1
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
96 cachefile = 'cache/hidden'
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
97
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
98 def cachehash(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
99 """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
100
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
101 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
102 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
103 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
104 """
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29040
diff changeset
105 h = hashlib.sha1()
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
106 h.update(''.join(repo.heads()))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
107 h.update(str(hash(frozenset(hideable))))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
108 return h.digest()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
109
23378
47091002ae62 repoview: extract actual hidden cache writing in its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22773
diff changeset
110 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
111 """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
112 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
113 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
114 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
115 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
116
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
117 def trywritehiddencache(repo, hideable, hidden):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
118 """write cache of hidden changesets to disk
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
119
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
120 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
121 The cache consists of a head of 22byte:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
122 2 byte version number of the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
123 20 byte sha1 to validate the cache
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
124 n*4 byte hidden revs
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
125 """
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
126 wlock = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
127 try:
25086
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
128 wlock = repo.wlock(wait=False)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
129 # write cache to file
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
130 newhash = cachehash(repo, hideable)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
131 fh = repo.vfs.open(cachefile, 'w+b', atomictemp=True)
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
132 _writehiddencache(fh, newhash, hidden)
29040
a4dc5fe7bf54 repoview: ignore unwritable hidden cache
Matt Mackall <mpm@selenic.com>
parents: 28780
diff changeset
133 fh.close()
25086
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
134 except (IOError, OSError):
27916
9a09a9cfa503 repoview: add missing newline character in debug prints
Laurent Charignon <lcharignon@fb.com>
parents: 27258
diff changeset
135 repo.ui.debug('error writing hidden changesets cache\n')
25086
140c2d1e57e7 repoview: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents: 24620
diff changeset
136 except error.LockHeld:
27916
9a09a9cfa503 repoview: add missing newline character in debug prints
Laurent Charignon <lcharignon@fb.com>
parents: 27258
diff changeset
137 repo.ui.debug('cannot obtain lock to write hidden changesets cache\n')
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
138 finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
139 if wlock:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
140 wlock.release()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
141
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
142 def tryreadcache(repo, hideable):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
143 """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
144 hidden = fh = None
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
145 try:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
146 if repo.vfs.exists(cachefile):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
147 fh = repo.vfs.open(cachefile, 'rb')
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
148 version, = struct.unpack(">H", fh.read(2))
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
149 oldhash = fh.read(20)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
150 newhash = cachehash(repo, hideable)
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
151 if (cacheversion, oldhash) == (version, newhash):
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
152 # 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
153 data = fh.read()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
154 count = len(data) / 4
22282
4092d12ba18a repoview: fix 0L with pack/unpack for 2.4
Matt Mackall <mpm@selenic.com>
parents: 22261
diff changeset
155 hidden = frozenset(struct.unpack('>%ii' % count, data))
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
156 return hidden
27917
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
157 except struct.error:
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
158 repo.ui.debug('corrupted hidden cache\n')
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
159 # No need to fix the content as it will get rewritten
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
160 return None
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
161 except (IOError, OSError):
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
162 repo.ui.debug('cannot read hidden cache\n')
97e0dc6d248c repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Laurent Charignon <lcharignon@fb.com>
parents: 27916
diff changeset
163 return None
22150
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
164 finally:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
165 if fh:
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
166 fh.close()
45b5cd948a4d repoview: add caching bits
David Soria Parra <davidsp@fb.com>
parents: 22149
diff changeset
167
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
168 def computehidden(repo):
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
169 """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
170
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
171 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
172 assert not repo.changelog.filteredrevs
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
173
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
174 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
175 hideable = hideablerevs(repo)
18272
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
176 if hideable:
95ef7a87c053 performance: speedup computation of hidden revisions
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 18250
diff changeset
177 cl = repo.changelog
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
178 hidden = tryreadcache(repo, hideable)
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
179 if hidden is None:
24565
2f7cb6e6acdd repoview: improve compute staticblockers perf
Durham Goode <durham@fb.com>
parents: 24154
diff changeset
180 hidden = frozenset(_getstatichidden(repo))
22151
c0c369aec643 repoview: cache hidden changesets
David Soria Parra <davidsp@fb.com>
parents: 22150
diff changeset
181 trywritehiddencache(repo, hideable, hidden)
22149
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
182
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
183 # 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
184 # changesets and remove those.
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
185 dynamic = hidden & _getdynamicblockers(repo)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
186 if dynamic:
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
187 blocked = cl.ancestors(dynamic, inclusive=True)
16ef2c485f03 repoview: split _gethiddenblockers
David Soria Parra <davidsp@fb.com>
parents: 22148
diff changeset
188 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
189 return hidden
18242
e4687edec014 clfilter: introduces a hidden filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18233
diff changeset
190
18102
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
191 def computeunserved(repo):
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
192 """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
193
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
194 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
195 assert not repo.changelog.filteredrevs
3c7b67b76190 clfilter: introduce a "unserver" filtering mode
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18101
diff changeset
196 # 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
197 hiddens = filterrevs(repo, 'visible')
18273
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
198 if phases.hassecret(repo):
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
199 cl = repo.changelog
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
200 secret = phases.secret
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
201 getphase = repo._phasecache.phase
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
202 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
203 revs = cl.revs(start=first)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
204 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
205 return frozenset(hiddens | secrets)
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
206 else:
a2d54f68e13c performance: speedup computation of unserved revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18272
diff changeset
207 return hiddens
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
208
18245
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
209 def computemutable(repo):
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
210 """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
211
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
212 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
213 assert not repo.changelog.filteredrevs
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
214 # fast check to avoid revset call on huge repo
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 25086
diff changeset
215 if 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
216 getphase = repo._phasecache.phase
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
217 maymutable = filterrevs(repo, 'base')
18274
254b708fd37d performance: speedup computation of mutable revisions
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18273
diff changeset
218 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
219 return frozenset()
aff706b3a21c clfilter: add mutable filtering
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18242
diff changeset
220
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
221 def computeimpactable(repo):
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
222 """Everything impactable by mutable revision
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
223
18462
593eb3786165 documentation: update to new filter names
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18445
diff changeset
224 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
225 happen when:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
226
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
227 - you garbage collect hidden changeset,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
228 - public phase is moved backward,
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
229 - 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
230
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
231 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
232 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
233
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
234 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
235 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
236 assert not repo.changelog.filteredrevs
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
237 cl = repo.changelog
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
238 firstmutable = len(cl)
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
239 for roots in repo._phasecache.phaseroots[1:]:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
240 if roots:
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
241 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
242 # 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
243 firstmutable = max(0, firstmutable)
18246
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
244 return frozenset(xrange(firstmutable, len(cl)))
58ca19edc043 clfilter: add impactable filter
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18245
diff changeset
245
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
246 # 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
247 #
20549
2025315cfb0c comments: fix minor spelling issues found with spell checker
Mads Kiilerich <madski@unity3d.com>
parents: 20405
diff changeset
248 # 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
249 # 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
250 # 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
251 # from scratch (very slow).
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
252 filtertable = {'visible': computehidden,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
253 'served': computeunserved,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
254 'immutable': computemutable,
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
255 'base': computeimpactable}
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
256
18382
f3b21beb9802 filtering: rename filters to their antonyms
Kevin Bullock <kbullock@ringworld.org>
parents: 18293
diff changeset
257 def filterrevs(repo, filtername):
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
258 """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
259 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
260 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
261 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
262 return repo.filteredrevcache[filtername]
18100
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
263
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
264 class repoview(object):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
265 """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
266
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
267 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
268 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
269 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
270 - 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
271 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
272 - 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
273
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
274 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
275 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
276 - 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
277 - 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
278 - 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
279 from `repo.__dict__`.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
280
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
281 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
282 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
283 `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
284 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
285
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
286 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
287 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
288 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
289 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
290 `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
291 leads to the property below.
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
292
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
293 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
294
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
295 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
296 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
297 """
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
298
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
299 def __init__(self, repo, filtername):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
300 object.__setattr__(self, '_unfilteredrepo', repo)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
301 object.__setattr__(self, 'filtername', filtername)
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
302 object.__setattr__(self, '_clcachekey', None)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
303 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
304
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
305 # 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
306 @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
307 def changelog(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
308 """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
309
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
310 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
311 # some cache may be implemented later
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
312 unfi = self._unfilteredrepo
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
313 unfichangelog = unfi.changelog
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
314 # bypass call to changelog.method
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
315 unfiindex = unfichangelog.index
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
316 unfilen = len(unfiindex) - 1
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
317 unfinode = unfiindex[unfilen - 1][7]
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
318
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
319 revs = filterrevs(unfi, self.filtername)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
320 cl = self._clcache
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
321 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed)
28265
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
322 # if cl.index is not unfiindex, unfi.changelog would be
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
323 # recreated, and our clcache refers to garbage object
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
324 if (cl is not None and
332926212ef8 repoview: discard filtered changelog if index isn't shared with unfiltered
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27917
diff changeset
325 (cl.index is not unfiindex or newkey != self._clcachekey)):
27258
beda2c9dbbff repoview: bypass changelog method to computed cache key
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 27257
diff changeset
326 cl = None
18445
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
327 # 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
328 if cl is None:
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
329 cl = copy.copy(unfichangelog)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
330 cl.filteredrevs = revs
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
331 object.__setattr__(self, '_clcache', cl)
4d92e2d75cff repoview: cache filtered changelog
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18443
diff changeset
332 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
333 return cl
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
334
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
335 def unfiltered(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
336 """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
337 return self._unfilteredrepo
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
338
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
339 def filtered(self, name):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
340 """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
341 if name == self.filtername:
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
342 return self
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
343 return self.unfiltered().filtered(name)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
344
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
345 # 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
346 def __getattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
347 return getattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
348
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
349 def __setattr__(self, attr, value):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
350 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
351
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
352 def __delattr__(self, attr):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
353 return delattr(self._unfilteredrepo, attr)
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
354
18644
3e92772d5383 spelling: fix some minor issues found by spell checker
Mads Kiilerich <mads@kiilerich.com>
parents: 18495
diff changeset
355 # 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
356 # __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
357 # 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
358 @property
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
359 def requirements(self):
3a6ddacb7198 clfilter: add actual repo filtering mechanism
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
diff changeset
360 return self._unfilteredrepo.requirements