Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/fileset.py @ 27461:afa76585c955
fileset: use decorator to mark a predicate as "status caller"
Before this patch, predicates calling 'matchctx.status()' are listed
up by immediate list value in 'getfileset()'.
This prevents 3rd party extensions from adding specific predicate
calling 'matchctx.status()'.
This uses decorator to mark a predicate as "status caller".
This can also localize changes for adding (or removing) a "status
caller" predicate function in source code.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Mon, 21 Dec 2015 22:31:16 +0900 |
parents | 11286ac374f3 |
children | 470ea34ba593 |
comparison
equal
deleted
inserted
replaced
27460:11286ac374f3 | 27461:afa76585c955 |
---|---|
135 # with: | 135 # with: |
136 # mctx - current matchctx instance | 136 # mctx - current matchctx instance |
137 # x - argument in tree form | 137 # x - argument in tree form |
138 symbols = {} | 138 symbols = {} |
139 | 139 |
140 def predicate(decl): | 140 # filesets using matchctx.status() |
141 _statuscallers = [] | |
142 | |
143 def predicate(decl, callstatus=False): | |
141 """Return a decorator for fileset predicate function | 144 """Return a decorator for fileset predicate function |
142 | 145 |
143 'decl' argument is the declaration (including argument list like | 146 'decl' argument is the declaration (including argument list like |
144 'adds(pattern)') or the name (for internal use only) of predicate. | 147 'adds(pattern)') or the name (for internal use only) of predicate. |
148 | |
149 Optional 'callstatus' argument indicates whether predicate implies | |
150 'matchctx.status()' at runtime or not (False, by default). | |
145 """ | 151 """ |
146 def decorator(func): | 152 def decorator(func): |
147 i = decl.find('(') | 153 i = decl.find('(') |
148 if i > 0: | 154 if i > 0: |
149 name = decl[:i] | 155 name = decl[:i] |
150 else: | 156 else: |
151 name = decl | 157 name = decl |
152 symbols[name] = func | 158 symbols[name] = func |
159 if callstatus: | |
160 _statuscallers.append(name) | |
153 if func.__doc__: | 161 if func.__doc__: |
154 func.__doc__ = "``%s``\n %s" % (decl, func.__doc__.strip()) | 162 func.__doc__ = "``%s``\n %s" % (decl, func.__doc__.strip()) |
155 return func | 163 return func |
156 return decorator | 164 return decorator |
157 | 165 |
158 @predicate('modified()') | 166 @predicate('modified()', callstatus=True) |
159 def modified(mctx, x): | 167 def modified(mctx, x): |
160 """File that is modified according to :hg:`status`. | 168 """File that is modified according to :hg:`status`. |
161 """ | 169 """ |
162 # i18n: "modified" is a keyword | 170 # i18n: "modified" is a keyword |
163 getargs(x, 0, 0, _("modified takes no arguments")) | 171 getargs(x, 0, 0, _("modified takes no arguments")) |
164 s = mctx.status().modified | 172 s = mctx.status().modified |
165 return [f for f in mctx.subset if f in s] | 173 return [f for f in mctx.subset if f in s] |
166 | 174 |
167 @predicate('added()') | 175 @predicate('added()', callstatus=True) |
168 def added(mctx, x): | 176 def added(mctx, x): |
169 """File that is added according to :hg:`status`. | 177 """File that is added according to :hg:`status`. |
170 """ | 178 """ |
171 # i18n: "added" is a keyword | 179 # i18n: "added" is a keyword |
172 getargs(x, 0, 0, _("added takes no arguments")) | 180 getargs(x, 0, 0, _("added takes no arguments")) |
173 s = mctx.status().added | 181 s = mctx.status().added |
174 return [f for f in mctx.subset if f in s] | 182 return [f for f in mctx.subset if f in s] |
175 | 183 |
176 @predicate('removed()') | 184 @predicate('removed()', callstatus=True) |
177 def removed(mctx, x): | 185 def removed(mctx, x): |
178 """File that is removed according to :hg:`status`. | 186 """File that is removed according to :hg:`status`. |
179 """ | 187 """ |
180 # i18n: "removed" is a keyword | 188 # i18n: "removed" is a keyword |
181 getargs(x, 0, 0, _("removed takes no arguments")) | 189 getargs(x, 0, 0, _("removed takes no arguments")) |
182 s = mctx.status().removed | 190 s = mctx.status().removed |
183 return [f for f in mctx.subset if f in s] | 191 return [f for f in mctx.subset if f in s] |
184 | 192 |
185 @predicate('deleted()') | 193 @predicate('deleted()', callstatus=True) |
186 def deleted(mctx, x): | 194 def deleted(mctx, x): |
187 """Alias for ``missing()``. | 195 """Alias for ``missing()``. |
188 """ | 196 """ |
189 # i18n: "deleted" is a keyword | 197 # i18n: "deleted" is a keyword |
190 getargs(x, 0, 0, _("deleted takes no arguments")) | 198 getargs(x, 0, 0, _("deleted takes no arguments")) |
191 s = mctx.status().deleted | 199 s = mctx.status().deleted |
192 return [f for f in mctx.subset if f in s] | 200 return [f for f in mctx.subset if f in s] |
193 | 201 |
194 @predicate('missing()') | 202 @predicate('missing()', callstatus=True) |
195 def missing(mctx, x): | 203 def missing(mctx, x): |
196 """File that is missing according to :hg:`status`. | 204 """File that is missing according to :hg:`status`. |
197 """ | 205 """ |
198 # i18n: "missing" is a keyword | 206 # i18n: "missing" is a keyword |
199 getargs(x, 0, 0, _("missing takes no arguments")) | 207 getargs(x, 0, 0, _("missing takes no arguments")) |
200 s = mctx.status().deleted | 208 s = mctx.status().deleted |
201 return [f for f in mctx.subset if f in s] | 209 return [f for f in mctx.subset if f in s] |
202 | 210 |
203 @predicate('unknown()') | 211 @predicate('unknown()', callstatus=True) |
204 def unknown(mctx, x): | 212 def unknown(mctx, x): |
205 """File that is unknown according to :hg:`status`. These files will only be | 213 """File that is unknown according to :hg:`status`. These files will only be |
206 considered if this predicate is used. | 214 considered if this predicate is used. |
207 """ | 215 """ |
208 # i18n: "unknown" is a keyword | 216 # i18n: "unknown" is a keyword |
209 getargs(x, 0, 0, _("unknown takes no arguments")) | 217 getargs(x, 0, 0, _("unknown takes no arguments")) |
210 s = mctx.status().unknown | 218 s = mctx.status().unknown |
211 return [f for f in mctx.subset if f in s] | 219 return [f for f in mctx.subset if f in s] |
212 | 220 |
213 @predicate('ignored()') | 221 @predicate('ignored()', callstatus=True) |
214 def ignored(mctx, x): | 222 def ignored(mctx, x): |
215 """File that is ignored according to :hg:`status`. These files will only be | 223 """File that is ignored according to :hg:`status`. These files will only be |
216 considered if this predicate is used. | 224 considered if this predicate is used. |
217 """ | 225 """ |
218 # i18n: "ignored" is a keyword | 226 # i18n: "ignored" is a keyword |
219 getargs(x, 0, 0, _("ignored takes no arguments")) | 227 getargs(x, 0, 0, _("ignored takes no arguments")) |
220 s = mctx.status().ignored | 228 s = mctx.status().ignored |
221 return [f for f in mctx.subset if f in s] | 229 return [f for f in mctx.subset if f in s] |
222 | 230 |
223 @predicate('clean()') | 231 @predicate('clean()', callstatus=True) |
224 def clean(mctx, x): | 232 def clean(mctx, x): |
225 """File that is clean according to :hg:`status`. | 233 """File that is clean according to :hg:`status`. |
226 """ | 234 """ |
227 # i18n: "clean" is a keyword | 235 # i18n: "clean" is a keyword |
228 getargs(x, 0, 0, _("clean takes no arguments")) | 236 getargs(x, 0, 0, _("clean takes no arguments")) |
521 | 529 |
522 def getfileset(ctx, expr): | 530 def getfileset(ctx, expr): |
523 tree = parse(expr) | 531 tree = parse(expr) |
524 | 532 |
525 # do we need status info? | 533 # do we need status info? |
526 if (_intree(['modified', 'added', 'removed', 'deleted', | 534 if (_intree(_statuscallers, tree) or |
527 'missing', 'unknown', 'ignored', 'clean'], tree) or | |
528 # Using matchctx.existing() on a workingctx requires us to check | 535 # Using matchctx.existing() on a workingctx requires us to check |
529 # for deleted files. | 536 # for deleted files. |
530 (ctx.rev() is None and _intree(_existingcallers, tree))): | 537 (ctx.rev() is None and _intree(_existingcallers, tree))): |
531 unknown = _intree(['unknown'], tree) | 538 unknown = _intree(['unknown'], tree) |
532 ignored = _intree(['ignored'], tree) | 539 ignored = _intree(['ignored'], tree) |