63 for p in pfunc(stack.pop()): |
63 for p in pfunc(stack.pop()): |
64 if p != nullrev and p in hidden: |
64 if p != nullrev and p in hidden: |
65 hidden.remove(p) |
65 hidden.remove(p) |
66 stack.append(p) |
66 stack.append(p) |
67 |
67 |
68 def computehidden(repo): |
68 def computehidden(repo, visibilityexceptions=None): |
69 """compute the set of hidden revision to filter |
69 """compute the set of hidden revision to filter |
70 |
70 |
71 During most operation hidden should be filtered.""" |
71 During most operation hidden should be filtered.""" |
72 assert not repo.changelog.filteredrevs |
72 assert not repo.changelog.filteredrevs |
73 |
73 |
74 hidden = hideablerevs(repo) |
74 hidden = hideablerevs(repo) |
75 if hidden: |
75 if hidden: |
76 hidden = set(hidden - pinnedrevs(repo)) |
76 hidden = set(hidden - pinnedrevs(repo)) |
|
77 if visibilityexceptions: |
|
78 hidden -= visibilityexceptions |
77 pfunc = repo.changelog.parentrevs |
79 pfunc = repo.changelog.parentrevs |
78 mutablephases = (phases.draft, phases.secret) |
80 mutablephases = (phases.draft, phases.secret) |
79 mutable = repo._phasecache.getrevset(repo, mutablephases) |
81 mutable = repo._phasecache.getrevset(repo, mutablephases) |
80 |
82 |
81 visible = mutable - hidden |
83 visible = mutable - hidden |
82 _revealancestors(pfunc, hidden, visible) |
84 _revealancestors(pfunc, hidden, visible) |
83 return frozenset(hidden) |
85 return frozenset(hidden) |
84 |
86 |
85 def computeunserved(repo): |
87 def computeunserved(repo, visibilityexceptions=None): |
86 """compute the set of revision that should be filtered when used a server |
88 """compute the set of revision that should be filtered when used a server |
87 |
89 |
88 Secret and hidden changeset should not pretend to be here.""" |
90 Secret and hidden changeset should not pretend to be here.""" |
89 assert not repo.changelog.filteredrevs |
91 assert not repo.changelog.filteredrevs |
90 # fast path in simple case to avoid impact of non optimised code |
92 # fast path in simple case to avoid impact of non optimised code |
98 secrets = set(r for r in revs if getphase(repo, r) >= secret) |
100 secrets = set(r for r in revs if getphase(repo, r) >= secret) |
99 return frozenset(hiddens | secrets) |
101 return frozenset(hiddens | secrets) |
100 else: |
102 else: |
101 return hiddens |
103 return hiddens |
102 |
104 |
103 def computemutable(repo): |
105 def computemutable(repo, visibilityexceptions=None): |
104 assert not repo.changelog.filteredrevs |
106 assert not repo.changelog.filteredrevs |
105 # fast check to avoid revset call on huge repo |
107 # fast check to avoid revset call on huge repo |
106 if any(repo._phasecache.phaseroots[1:]): |
108 if any(repo._phasecache.phaseroots[1:]): |
107 getphase = repo._phasecache.phase |
109 getphase = repo._phasecache.phase |
108 maymutable = filterrevs(repo, 'base') |
110 maymutable = filterrevs(repo, 'base') |
109 return frozenset(r for r in maymutable if getphase(repo, r)) |
111 return frozenset(r for r in maymutable if getphase(repo, r)) |
110 return frozenset() |
112 return frozenset() |
111 |
113 |
112 def computeimpactable(repo): |
114 def computeimpactable(repo, visibilityexceptions=None): |
113 """Everything impactable by mutable revision |
115 """Everything impactable by mutable revision |
114 |
116 |
115 The immutable filter still have some chance to get invalidated. This will |
117 The immutable filter still have some chance to get invalidated. This will |
116 happen when: |
118 happen when: |
117 |
119 |
143 filtertable = {'visible': computehidden, |
145 filtertable = {'visible': computehidden, |
144 'served': computeunserved, |
146 'served': computeunserved, |
145 'immutable': computemutable, |
147 'immutable': computemutable, |
146 'base': computeimpactable} |
148 'base': computeimpactable} |
147 |
149 |
148 def filterrevs(repo, filtername): |
150 def filterrevs(repo, filtername, visibilityexceptions=None): |
149 """returns set of filtered revision for this filter name""" |
151 """returns set of filtered revision for this filter name |
|
152 |
|
153 visibilityexceptions is a set of revs which must are exceptions for |
|
154 hidden-state and must be visible. They are dynamic and hence we should not |
|
155 cache it's result""" |
150 if filtername not in repo.filteredrevcache: |
156 if filtername not in repo.filteredrevcache: |
151 func = filtertable[filtername] |
157 func = filtertable[filtername] |
|
158 if visibilityexceptions: |
|
159 return func(repo.unfiltered, visibilityexceptions) |
152 repo.filteredrevcache[filtername] = func(repo.unfiltered()) |
160 repo.filteredrevcache[filtername] = func(repo.unfiltered()) |
153 return repo.filteredrevcache[filtername] |
161 return repo.filteredrevcache[filtername] |
154 |
162 |
155 class repoview(object): |
163 class repoview(object): |
156 """Provide a read/write view of a repo through a filtered changelog |
164 """Provide a read/write view of a repo through a filtered changelog |
208 # bypass call to changelog.method |
216 # bypass call to changelog.method |
209 unfiindex = unfichangelog.index |
217 unfiindex = unfichangelog.index |
210 unfilen = len(unfiindex) - 1 |
218 unfilen = len(unfiindex) - 1 |
211 unfinode = unfiindex[unfilen - 1][7] |
219 unfinode = unfiindex[unfilen - 1][7] |
212 |
220 |
213 revs = filterrevs(unfi, self.filtername) |
221 revs = filterrevs(unfi, self.filtername, self._visibilityexceptions) |
214 cl = self._clcache |
222 cl = self._clcache |
215 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed) |
223 newkey = (unfilen, unfinode, hash(revs), unfichangelog._delayed) |
216 # if cl.index is not unfiindex, unfi.changelog would be |
224 # if cl.index is not unfiindex, unfi.changelog would be |
217 # recreated, and our clcache refers to garbage object |
225 # recreated, and our clcache refers to garbage object |
218 if (cl is not None and |
226 if (cl is not None and |