##// END OF EJS Templates
registrar: clarify the documentation about some byte strings being required...
Matt Harbison -
r46615:c1bb0273 default
parent child Browse files
Show More
@@ -1,537 +1,537 b''
1 # registrar.py - utilities to register function for specific purpose
1 # registrar.py - utilities to register function for specific purpose
2 #
2 #
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from . import (
10 from . import (
11 configitems,
11 configitems,
12 error,
12 error,
13 pycompat,
13 pycompat,
14 util,
14 util,
15 )
15 )
16
16
17 # unlike the other registered items, config options are neither functions or
17 # unlike the other registered items, config options are neither functions or
18 # classes. Registering the option is just small function call.
18 # classes. Registering the option is just small function call.
19 #
19 #
20 # We still add the official API to the registrar module for consistency with
20 # We still add the official API to the registrar module for consistency with
21 # the other items extensions want might to register.
21 # the other items extensions want might to register.
22 configitem = configitems.getitemregister
22 configitem = configitems.getitemregister
23
23
24
24
25 class _funcregistrarbase(object):
25 class _funcregistrarbase(object):
26 """Base of decorator to register a function for specific purpose
26 """Base of decorator to register a function for specific purpose
27
27
28 This decorator stores decorated functions into own dict 'table'.
28 This decorator stores decorated functions into own dict 'table'.
29
29
30 The least derived class can be defined by overriding 'formatdoc',
30 The least derived class can be defined by overriding 'formatdoc',
31 for example::
31 for example::
32
32
33 class keyword(_funcregistrarbase):
33 class keyword(_funcregistrarbase):
34 _docformat = ":%s: %s"
34 _docformat = ":%s: %s"
35
35
36 This should be used as below:
36 This should be used as below:
37
37
38 keyword = registrar.keyword()
38 keyword = registrar.keyword()
39
39
40 @keyword('bar')
40 @keyword(b'bar')
41 def barfunc(*args, **kwargs):
41 def barfunc(*args, **kwargs):
42 '''Explanation of bar keyword ....
42 '''Explanation of bar keyword ....
43 '''
43 '''
44 pass
44 pass
45
45
46 In this case:
46 In this case:
47
47
48 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
48 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
49 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
49 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
50 """
50 """
51
51
52 def __init__(self, table=None):
52 def __init__(self, table=None):
53 if table is None:
53 if table is None:
54 self._table = {}
54 self._table = {}
55 else:
55 else:
56 self._table = table
56 self._table = table
57
57
58 def __call__(self, decl, *args, **kwargs):
58 def __call__(self, decl, *args, **kwargs):
59 return lambda func: self._doregister(func, decl, *args, **kwargs)
59 return lambda func: self._doregister(func, decl, *args, **kwargs)
60
60
61 def _doregister(self, func, decl, *args, **kwargs):
61 def _doregister(self, func, decl, *args, **kwargs):
62 name = self._getname(decl)
62 name = self._getname(decl)
63
63
64 if name in self._table:
64 if name in self._table:
65 msg = b'duplicate registration for name: "%s"' % name
65 msg = b'duplicate registration for name: "%s"' % name
66 raise error.ProgrammingError(msg)
66 raise error.ProgrammingError(msg)
67
67
68 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
68 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
69 func._origdoc = func.__doc__.strip()
69 func._origdoc = func.__doc__.strip()
70 doc = pycompat.sysbytes(func._origdoc)
70 doc = pycompat.sysbytes(func._origdoc)
71 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
71 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
72
72
73 self._table[name] = func
73 self._table[name] = func
74 self._extrasetup(name, func, *args, **kwargs)
74 self._extrasetup(name, func, *args, **kwargs)
75
75
76 return func
76 return func
77
77
78 def _merge(self, registrarbase):
78 def _merge(self, registrarbase):
79 """Merge the entries of the given registrar object into this one.
79 """Merge the entries of the given registrar object into this one.
80
80
81 The other registrar object must not contain any entries already in the
81 The other registrar object must not contain any entries already in the
82 current one, or a ProgrammmingError is raised. Additionally, the types
82 current one, or a ProgrammmingError is raised. Additionally, the types
83 of the two registrars must match.
83 of the two registrars must match.
84 """
84 """
85 if not isinstance(registrarbase, type(self)):
85 if not isinstance(registrarbase, type(self)):
86 msg = b"cannot merge different types of registrar"
86 msg = b"cannot merge different types of registrar"
87 raise error.ProgrammingError(msg)
87 raise error.ProgrammingError(msg)
88
88
89 dups = set(registrarbase._table).intersection(self._table)
89 dups = set(registrarbase._table).intersection(self._table)
90
90
91 if dups:
91 if dups:
92 msg = b'duplicate registration for names: "%s"' % b'", "'.join(dups)
92 msg = b'duplicate registration for names: "%s"' % b'", "'.join(dups)
93 raise error.ProgrammingError(msg)
93 raise error.ProgrammingError(msg)
94
94
95 self._table.update(registrarbase._table)
95 self._table.update(registrarbase._table)
96
96
97 def _parsefuncdecl(self, decl):
97 def _parsefuncdecl(self, decl):
98 """Parse function declaration and return the name of function in it"""
98 """Parse function declaration and return the name of function in it"""
99 i = decl.find(b'(')
99 i = decl.find(b'(')
100 if i >= 0:
100 if i >= 0:
101 return decl[:i]
101 return decl[:i]
102 else:
102 else:
103 return decl
103 return decl
104
104
105 def _getname(self, decl):
105 def _getname(self, decl):
106 """Return the name of the registered function from decl
106 """Return the name of the registered function from decl
107
107
108 Derived class should override this, if it allows more
108 Derived class should override this, if it allows more
109 descriptive 'decl' string than just a name.
109 descriptive 'decl' string than just a name.
110 """
110 """
111 return decl
111 return decl
112
112
113 _docformat = None
113 _docformat = None
114
114
115 def _formatdoc(self, decl, doc):
115 def _formatdoc(self, decl, doc):
116 """Return formatted document of the registered function for help
116 """Return formatted document of the registered function for help
117
117
118 'doc' is '__doc__.strip()' of the registered function.
118 'doc' is '__doc__.strip()' of the registered function.
119 """
119 """
120 return self._docformat % (decl, doc)
120 return self._docformat % (decl, doc)
121
121
122 def _extrasetup(self, name, func):
122 def _extrasetup(self, name, func):
123 """Execute extra setup for registered function, if needed"""
123 """Execute extra setup for registered function, if needed"""
124
124
125
125
126 class command(_funcregistrarbase):
126 class command(_funcregistrarbase):
127 """Decorator to register a command function to table
127 """Decorator to register a command function to table
128
128
129 This class receives a command table as its argument. The table should
129 This class receives a command table as its argument. The table should
130 be a dict.
130 be a dict.
131
131
132 The created object can be used as a decorator for adding commands to
132 The created object can be used as a decorator for adding commands to
133 that command table. This accepts multiple arguments to define a command.
133 that command table. This accepts multiple arguments to define a command.
134
134
135 The first argument is the command name (as bytes).
135 The first argument is the command name (as bytes).
136
136
137 The `options` keyword argument is an iterable of tuples defining command
137 The `options` keyword argument is an iterable of tuples defining command
138 arguments. See ``mercurial.fancyopts.fancyopts()`` for the format of each
138 arguments. See ``mercurial.fancyopts.fancyopts()`` for the format of each
139 tuple.
139 tuple.
140
140
141 The `synopsis` argument defines a short, one line summary of how to use the
141 The `synopsis` argument defines a short, one line summary of how to use the
142 command. This shows up in the help output.
142 command. This shows up in the help output.
143
143
144 There are three arguments that control what repository (if any) is found
144 There are three arguments that control what repository (if any) is found
145 and passed to the decorated function: `norepo`, `optionalrepo`, and
145 and passed to the decorated function: `norepo`, `optionalrepo`, and
146 `inferrepo`.
146 `inferrepo`.
147
147
148 The `norepo` argument defines whether the command does not require a
148 The `norepo` argument defines whether the command does not require a
149 local repository. Most commands operate against a repository, thus the
149 local repository. Most commands operate against a repository, thus the
150 default is False. When True, no repository will be passed.
150 default is False. When True, no repository will be passed.
151
151
152 The `optionalrepo` argument defines whether the command optionally requires
152 The `optionalrepo` argument defines whether the command optionally requires
153 a local repository. If no repository can be found, None will be passed
153 a local repository. If no repository can be found, None will be passed
154 to the decorated function.
154 to the decorated function.
155
155
156 The `inferrepo` argument defines whether to try to find a repository from
156 The `inferrepo` argument defines whether to try to find a repository from
157 the command line arguments. If True, arguments will be examined for
157 the command line arguments. If True, arguments will be examined for
158 potential repository locations. See ``findrepo()``. If a repository is
158 potential repository locations. See ``findrepo()``. If a repository is
159 found, it will be used and passed to the decorated function.
159 found, it will be used and passed to the decorated function.
160
160
161 The `intents` argument defines a set of intended actions or capabilities
161 The `intents` argument defines a set of intended actions or capabilities
162 the command is taking. These intents can be used to affect the construction
162 the command is taking. These intents can be used to affect the construction
163 of the repository object passed to the command. For example, commands
163 of the repository object passed to the command. For example, commands
164 declaring that they are read-only could receive a repository that doesn't
164 declaring that they are read-only could receive a repository that doesn't
165 have any methods allowing repository mutation. Other intents could be used
165 have any methods allowing repository mutation. Other intents could be used
166 to prevent the command from running if the requested intent could not be
166 to prevent the command from running if the requested intent could not be
167 fulfilled.
167 fulfilled.
168
168
169 If `helpcategory` is set (usually to one of the constants in the help
169 If `helpcategory` is set (usually to one of the constants in the help
170 module), the command will be displayed under that category in the help's
170 module), the command will be displayed under that category in the help's
171 list of commands.
171 list of commands.
172
172
173 The following intents are defined:
173 The following intents are defined:
174
174
175 readonly
175 readonly
176 The command is read-only
176 The command is read-only
177
177
178 The signature of the decorated function looks like this:
178 The signature of the decorated function looks like this:
179 def cmd(ui[, repo] [, <args>] [, <options>])
179 def cmd(ui[, repo] [, <args>] [, <options>])
180
180
181 `repo` is required if `norepo` is False.
181 `repo` is required if `norepo` is False.
182 `<args>` are positional args (or `*args`) arguments, of non-option
182 `<args>` are positional args (or `*args`) arguments, of non-option
183 arguments from the command line.
183 arguments from the command line.
184 `<options>` are keyword arguments (or `**options`) of option arguments
184 `<options>` are keyword arguments (or `**options`) of option arguments
185 from the command line.
185 from the command line.
186
186
187 See the WritingExtensions and MercurialApi documentation for more exhaustive
187 See the WritingExtensions and MercurialApi documentation for more exhaustive
188 descriptions and examples.
188 descriptions and examples.
189 """
189 """
190
190
191 # Command categories for grouping them in help output.
191 # Command categories for grouping them in help output.
192 # These can also be specified for aliases, like:
192 # These can also be specified for aliases, like:
193 # [alias]
193 # [alias]
194 # myalias = something
194 # myalias = something
195 # myalias:category = repo
195 # myalias:category = repo
196 CATEGORY_REPO_CREATION = b'repo'
196 CATEGORY_REPO_CREATION = b'repo'
197 CATEGORY_REMOTE_REPO_MANAGEMENT = b'remote'
197 CATEGORY_REMOTE_REPO_MANAGEMENT = b'remote'
198 CATEGORY_COMMITTING = b'commit'
198 CATEGORY_COMMITTING = b'commit'
199 CATEGORY_CHANGE_MANAGEMENT = b'management'
199 CATEGORY_CHANGE_MANAGEMENT = b'management'
200 CATEGORY_CHANGE_ORGANIZATION = b'organization'
200 CATEGORY_CHANGE_ORGANIZATION = b'organization'
201 CATEGORY_FILE_CONTENTS = b'files'
201 CATEGORY_FILE_CONTENTS = b'files'
202 CATEGORY_CHANGE_NAVIGATION = b'navigation'
202 CATEGORY_CHANGE_NAVIGATION = b'navigation'
203 CATEGORY_WORKING_DIRECTORY = b'wdir'
203 CATEGORY_WORKING_DIRECTORY = b'wdir'
204 CATEGORY_IMPORT_EXPORT = b'import'
204 CATEGORY_IMPORT_EXPORT = b'import'
205 CATEGORY_MAINTENANCE = b'maintenance'
205 CATEGORY_MAINTENANCE = b'maintenance'
206 CATEGORY_HELP = b'help'
206 CATEGORY_HELP = b'help'
207 CATEGORY_MISC = b'misc'
207 CATEGORY_MISC = b'misc'
208 CATEGORY_NONE = b'none'
208 CATEGORY_NONE = b'none'
209
209
210 def _doregister(
210 def _doregister(
211 self,
211 self,
212 func,
212 func,
213 name,
213 name,
214 options=(),
214 options=(),
215 synopsis=None,
215 synopsis=None,
216 norepo=False,
216 norepo=False,
217 optionalrepo=False,
217 optionalrepo=False,
218 inferrepo=False,
218 inferrepo=False,
219 intents=None,
219 intents=None,
220 helpcategory=None,
220 helpcategory=None,
221 helpbasic=False,
221 helpbasic=False,
222 ):
222 ):
223 func.norepo = norepo
223 func.norepo = norepo
224 func.optionalrepo = optionalrepo
224 func.optionalrepo = optionalrepo
225 func.inferrepo = inferrepo
225 func.inferrepo = inferrepo
226 func.intents = intents or set()
226 func.intents = intents or set()
227 func.helpcategory = helpcategory
227 func.helpcategory = helpcategory
228 func.helpbasic = helpbasic
228 func.helpbasic = helpbasic
229 if synopsis:
229 if synopsis:
230 self._table[name] = func, list(options), synopsis
230 self._table[name] = func, list(options), synopsis
231 else:
231 else:
232 self._table[name] = func, list(options)
232 self._table[name] = func, list(options)
233 return func
233 return func
234
234
235 def rename(self, old, new):
235 def rename(self, old, new):
236 """rename a command. Used to add aliases, debugstrip ->
236 """rename a command. Used to add aliases, debugstrip ->
237 debugstrip|strip
237 debugstrip|strip
238 """
238 """
239 self._table[new] = self._table.pop(old)
239 self._table[new] = self._table.pop(old)
240
240
241
241
242 INTENT_READONLY = b'readonly'
242 INTENT_READONLY = b'readonly'
243
243
244
244
245 class revsetpredicate(_funcregistrarbase):
245 class revsetpredicate(_funcregistrarbase):
246 """Decorator to register revset predicate
246 """Decorator to register revset predicate
247
247
248 Usage::
248 Usage::
249
249
250 revsetpredicate = registrar.revsetpredicate()
250 revsetpredicate = registrar.revsetpredicate()
251
251
252 @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
252 @revsetpredicate(b'mypredicate(arg1, arg2[, arg3])')
253 def mypredicatefunc(repo, subset, x):
253 def mypredicatefunc(repo, subset, x):
254 '''Explanation of this revset predicate ....
254 '''Explanation of this revset predicate ....
255 '''
255 '''
256 pass
256 pass
257
257
258 The first string argument is used also in online help.
258 The first string argument is used also in online help.
259
259
260 Optional argument 'safe' indicates whether a predicate is safe for
260 Optional argument 'safe' indicates whether a predicate is safe for
261 DoS attack (False by default).
261 DoS attack (False by default).
262
262
263 Optional argument 'takeorder' indicates whether a predicate function
263 Optional argument 'takeorder' indicates whether a predicate function
264 takes ordering policy as the last argument.
264 takes ordering policy as the last argument.
265
265
266 Optional argument 'weight' indicates the estimated run-time cost, useful
266 Optional argument 'weight' indicates the estimated run-time cost, useful
267 for static optimization, default is 1. Higher weight means more expensive.
267 for static optimization, default is 1. Higher weight means more expensive.
268 Usually, revsets that are fast and return only one revision has a weight of
268 Usually, revsets that are fast and return only one revision has a weight of
269 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
269 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
270 changelog have weight 10 (ex. author); revsets reading manifest deltas have
270 changelog have weight 10 (ex. author); revsets reading manifest deltas have
271 weight 30 (ex. adds); revset reading manifest contents have weight 100
271 weight 30 (ex. adds); revset reading manifest contents have weight 100
272 (ex. contains). Note: those values are flexible. If the revset has a
272 (ex. contains). Note: those values are flexible. If the revset has a
273 same big-O time complexity as 'contains', but with a smaller constant, it
273 same big-O time complexity as 'contains', but with a smaller constant, it
274 might have a weight of 90.
274 might have a weight of 90.
275
275
276 'revsetpredicate' instance in example above can be used to
276 'revsetpredicate' instance in example above can be used to
277 decorate multiple functions.
277 decorate multiple functions.
278
278
279 Decorated functions are registered automatically at loading
279 Decorated functions are registered automatically at loading
280 extension, if an instance named as 'revsetpredicate' is used for
280 extension, if an instance named as 'revsetpredicate' is used for
281 decorating in extension.
281 decorating in extension.
282
282
283 Otherwise, explicit 'revset.loadpredicate()' is needed.
283 Otherwise, explicit 'revset.loadpredicate()' is needed.
284 """
284 """
285
285
286 _getname = _funcregistrarbase._parsefuncdecl
286 _getname = _funcregistrarbase._parsefuncdecl
287 _docformat = b"``%s``\n %s"
287 _docformat = b"``%s``\n %s"
288
288
289 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
289 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
290 func._safe = safe
290 func._safe = safe
291 func._takeorder = takeorder
291 func._takeorder = takeorder
292 func._weight = weight
292 func._weight = weight
293
293
294
294
295 class filesetpredicate(_funcregistrarbase):
295 class filesetpredicate(_funcregistrarbase):
296 """Decorator to register fileset predicate
296 """Decorator to register fileset predicate
297
297
298 Usage::
298 Usage::
299
299
300 filesetpredicate = registrar.filesetpredicate()
300 filesetpredicate = registrar.filesetpredicate()
301
301
302 @filesetpredicate('mypredicate()')
302 @filesetpredicate(b'mypredicate()')
303 def mypredicatefunc(mctx, x):
303 def mypredicatefunc(mctx, x):
304 '''Explanation of this fileset predicate ....
304 '''Explanation of this fileset predicate ....
305 '''
305 '''
306 pass
306 pass
307
307
308 The first string argument is used also in online help.
308 The first string argument is used also in online help.
309
309
310 Optional argument 'callstatus' indicates whether a predicate
310 Optional argument 'callstatus' indicates whether a predicate
311 implies 'matchctx.status()' at runtime or not (False, by
311 implies 'matchctx.status()' at runtime or not (False, by
312 default).
312 default).
313
313
314 Optional argument 'weight' indicates the estimated run-time cost, useful
314 Optional argument 'weight' indicates the estimated run-time cost, useful
315 for static optimization, default is 1. Higher weight means more expensive.
315 for static optimization, default is 1. Higher weight means more expensive.
316 There are predefined weights in the 'filesetlang' module.
316 There are predefined weights in the 'filesetlang' module.
317
317
318 ====== =============================================================
318 ====== =============================================================
319 Weight Description and examples
319 Weight Description and examples
320 ====== =============================================================
320 ====== =============================================================
321 0.5 basic match patterns (e.g. a symbol)
321 0.5 basic match patterns (e.g. a symbol)
322 10 computing status (e.g. added()) or accessing a few files
322 10 computing status (e.g. added()) or accessing a few files
323 30 reading file content for each (e.g. grep())
323 30 reading file content for each (e.g. grep())
324 50 scanning working directory (ignored())
324 50 scanning working directory (ignored())
325 ====== =============================================================
325 ====== =============================================================
326
326
327 'filesetpredicate' instance in example above can be used to
327 'filesetpredicate' instance in example above can be used to
328 decorate multiple functions.
328 decorate multiple functions.
329
329
330 Decorated functions are registered automatically at loading
330 Decorated functions are registered automatically at loading
331 extension, if an instance named as 'filesetpredicate' is used for
331 extension, if an instance named as 'filesetpredicate' is used for
332 decorating in extension.
332 decorating in extension.
333
333
334 Otherwise, explicit 'fileset.loadpredicate()' is needed.
334 Otherwise, explicit 'fileset.loadpredicate()' is needed.
335 """
335 """
336
336
337 _getname = _funcregistrarbase._parsefuncdecl
337 _getname = _funcregistrarbase._parsefuncdecl
338 _docformat = b"``%s``\n %s"
338 _docformat = b"``%s``\n %s"
339
339
340 def _extrasetup(self, name, func, callstatus=False, weight=1):
340 def _extrasetup(self, name, func, callstatus=False, weight=1):
341 func._callstatus = callstatus
341 func._callstatus = callstatus
342 func._weight = weight
342 func._weight = weight
343
343
344
344
345 class _templateregistrarbase(_funcregistrarbase):
345 class _templateregistrarbase(_funcregistrarbase):
346 """Base of decorator to register functions as template specific one"""
346 """Base of decorator to register functions as template specific one"""
347
347
348 _docformat = b":%s: %s"
348 _docformat = b":%s: %s"
349
349
350
350
351 class templatekeyword(_templateregistrarbase):
351 class templatekeyword(_templateregistrarbase):
352 """Decorator to register template keyword
352 """Decorator to register template keyword
353
353
354 Usage::
354 Usage::
355
355
356 templatekeyword = registrar.templatekeyword()
356 templatekeyword = registrar.templatekeyword()
357
357
358 # new API (since Mercurial 4.6)
358 # new API (since Mercurial 4.6)
359 @templatekeyword('mykeyword', requires={'repo', 'ctx'})
359 @templatekeyword(b'mykeyword', requires={b'repo', b'ctx'})
360 def mykeywordfunc(context, mapping):
360 def mykeywordfunc(context, mapping):
361 '''Explanation of this template keyword ....
361 '''Explanation of this template keyword ....
362 '''
362 '''
363 pass
363 pass
364
364
365 The first string argument is used also in online help.
365 The first string argument is used also in online help.
366
366
367 Optional argument 'requires' should be a collection of resource names
367 Optional argument 'requires' should be a collection of resource names
368 which the template keyword depends on.
368 which the template keyword depends on.
369
369
370 'templatekeyword' instance in example above can be used to
370 'templatekeyword' instance in example above can be used to
371 decorate multiple functions.
371 decorate multiple functions.
372
372
373 Decorated functions are registered automatically at loading
373 Decorated functions are registered automatically at loading
374 extension, if an instance named as 'templatekeyword' is used for
374 extension, if an instance named as 'templatekeyword' is used for
375 decorating in extension.
375 decorating in extension.
376
376
377 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
377 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
378 """
378 """
379
379
380 def _extrasetup(self, name, func, requires=()):
380 def _extrasetup(self, name, func, requires=()):
381 func._requires = requires
381 func._requires = requires
382
382
383
383
384 class templatefilter(_templateregistrarbase):
384 class templatefilter(_templateregistrarbase):
385 """Decorator to register template filer
385 """Decorator to register template filer
386
386
387 Usage::
387 Usage::
388
388
389 templatefilter = registrar.templatefilter()
389 templatefilter = registrar.templatefilter()
390
390
391 @templatefilter('myfilter', intype=bytes)
391 @templatefilter(b'myfilter', intype=bytes)
392 def myfilterfunc(text):
392 def myfilterfunc(text):
393 '''Explanation of this template filter ....
393 '''Explanation of this template filter ....
394 '''
394 '''
395 pass
395 pass
396
396
397 The first string argument is used also in online help.
397 The first string argument is used also in online help.
398
398
399 Optional argument 'intype' defines the type of the input argument,
399 Optional argument 'intype' defines the type of the input argument,
400 which should be (bytes, int, templateutil.date, or None for any.)
400 which should be (bytes, int, templateutil.date, or None for any.)
401
401
402 'templatefilter' instance in example above can be used to
402 'templatefilter' instance in example above can be used to
403 decorate multiple functions.
403 decorate multiple functions.
404
404
405 Decorated functions are registered automatically at loading
405 Decorated functions are registered automatically at loading
406 extension, if an instance named as 'templatefilter' is used for
406 extension, if an instance named as 'templatefilter' is used for
407 decorating in extension.
407 decorating in extension.
408
408
409 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
409 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
410 """
410 """
411
411
412 def _extrasetup(self, name, func, intype=None):
412 def _extrasetup(self, name, func, intype=None):
413 func._intype = intype
413 func._intype = intype
414
414
415
415
416 class templatefunc(_templateregistrarbase):
416 class templatefunc(_templateregistrarbase):
417 """Decorator to register template function
417 """Decorator to register template function
418
418
419 Usage::
419 Usage::
420
420
421 templatefunc = registrar.templatefunc()
421 templatefunc = registrar.templatefunc()
422
422
423 @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3',
423 @templatefunc(b'myfunc(arg1, arg2[, arg3])', argspec=b'arg1 arg2 arg3',
424 requires={'ctx'})
424 requires={b'ctx'})
425 def myfuncfunc(context, mapping, args):
425 def myfuncfunc(context, mapping, args):
426 '''Explanation of this template function ....
426 '''Explanation of this template function ....
427 '''
427 '''
428 pass
428 pass
429
429
430 The first string argument is used also in online help.
430 The first string argument is used also in online help.
431
431
432 If optional 'argspec' is defined, the function will receive 'args' as
432 If optional 'argspec' is defined, the function will receive 'args' as
433 a dict of named arguments. Otherwise 'args' is a list of positional
433 a dict of named arguments. Otherwise 'args' is a list of positional
434 arguments.
434 arguments.
435
435
436 Optional argument 'requires' should be a collection of resource names
436 Optional argument 'requires' should be a collection of resource names
437 which the template function depends on.
437 which the template function depends on.
438
438
439 'templatefunc' instance in example above can be used to
439 'templatefunc' instance in example above can be used to
440 decorate multiple functions.
440 decorate multiple functions.
441
441
442 Decorated functions are registered automatically at loading
442 Decorated functions are registered automatically at loading
443 extension, if an instance named as 'templatefunc' is used for
443 extension, if an instance named as 'templatefunc' is used for
444 decorating in extension.
444 decorating in extension.
445
445
446 Otherwise, explicit 'templatefuncs.loadfunction()' is needed.
446 Otherwise, explicit 'templatefuncs.loadfunction()' is needed.
447 """
447 """
448
448
449 _getname = _funcregistrarbase._parsefuncdecl
449 _getname = _funcregistrarbase._parsefuncdecl
450
450
451 def _extrasetup(self, name, func, argspec=None, requires=()):
451 def _extrasetup(self, name, func, argspec=None, requires=()):
452 func._argspec = argspec
452 func._argspec = argspec
453 func._requires = requires
453 func._requires = requires
454
454
455
455
456 class internalmerge(_funcregistrarbase):
456 class internalmerge(_funcregistrarbase):
457 """Decorator to register in-process merge tool
457 """Decorator to register in-process merge tool
458
458
459 Usage::
459 Usage::
460
460
461 internalmerge = registrar.internalmerge()
461 internalmerge = registrar.internalmerge()
462
462
463 @internalmerge('mymerge', internalmerge.mergeonly,
463 @internalmerge(b'mymerge', internalmerge.mergeonly,
464 onfailure=None, precheck=None,
464 onfailure=None, precheck=None,
465 binary=False, symlink=False):
465 binary=False, symlink=False):
466 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
466 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
467 toolconf, files, labels=None):
467 toolconf, files, labels=None):
468 '''Explanation of this internal merge tool ....
468 '''Explanation of this internal merge tool ....
469 '''
469 '''
470 return 1, False # means "conflicted", "no deletion needed"
470 return 1, False # means "conflicted", "no deletion needed"
471
471
472 The first string argument is used to compose actual merge tool name,
472 The first string argument is used to compose actual merge tool name,
473 ":name" and "internal:name" (the latter is historical one).
473 ":name" and "internal:name" (the latter is historical one).
474
474
475 The second argument is one of merge types below:
475 The second argument is one of merge types below:
476
476
477 ========== ======== ======== =========
477 ========== ======== ======== =========
478 merge type precheck premerge fullmerge
478 merge type precheck premerge fullmerge
479 ========== ======== ======== =========
479 ========== ======== ======== =========
480 nomerge x x x
480 nomerge x x x
481 mergeonly o x o
481 mergeonly o x o
482 fullmerge o o o
482 fullmerge o o o
483 ========== ======== ======== =========
483 ========== ======== ======== =========
484
484
485 Optional argument 'onfailure' is the format of warning message
485 Optional argument 'onfailure' is the format of warning message
486 to be used at failure of merging (target filename is specified
486 to be used at failure of merging (target filename is specified
487 at formatting). Or, None or so, if warning message should be
487 at formatting). Or, None or so, if warning message should be
488 suppressed.
488 suppressed.
489
489
490 Optional argument 'precheck' is the function to be used
490 Optional argument 'precheck' is the function to be used
491 before actual invocation of internal merge tool itself.
491 before actual invocation of internal merge tool itself.
492 It takes as same arguments as internal merge tool does, other than
492 It takes as same arguments as internal merge tool does, other than
493 'files' and 'labels'. If it returns false value, merging is aborted
493 'files' and 'labels'. If it returns false value, merging is aborted
494 immediately (and file is marked as "unresolved").
494 immediately (and file is marked as "unresolved").
495
495
496 Optional argument 'binary' is a binary files capability of internal
496 Optional argument 'binary' is a binary files capability of internal
497 merge tool. 'nomerge' merge type implies binary=True.
497 merge tool. 'nomerge' merge type implies binary=True.
498
498
499 Optional argument 'symlink' is a symlinks capability of inetrnal
499 Optional argument 'symlink' is a symlinks capability of inetrnal
500 merge function. 'nomerge' merge type implies symlink=True.
500 merge function. 'nomerge' merge type implies symlink=True.
501
501
502 'internalmerge' instance in example above can be used to
502 'internalmerge' instance in example above can be used to
503 decorate multiple functions.
503 decorate multiple functions.
504
504
505 Decorated functions are registered automatically at loading
505 Decorated functions are registered automatically at loading
506 extension, if an instance named as 'internalmerge' is used for
506 extension, if an instance named as 'internalmerge' is used for
507 decorating in extension.
507 decorating in extension.
508
508
509 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
509 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
510 """
510 """
511
511
512 _docformat = b"``:%s``\n %s"
512 _docformat = b"``:%s``\n %s"
513
513
514 # merge type definitions:
514 # merge type definitions:
515 nomerge = None
515 nomerge = None
516 mergeonly = b'mergeonly' # just the full merge, no premerge
516 mergeonly = b'mergeonly' # just the full merge, no premerge
517 fullmerge = b'fullmerge' # both premerge and merge
517 fullmerge = b'fullmerge' # both premerge and merge
518
518
519 def _extrasetup(
519 def _extrasetup(
520 self,
520 self,
521 name,
521 name,
522 func,
522 func,
523 mergetype,
523 mergetype,
524 onfailure=None,
524 onfailure=None,
525 precheck=None,
525 precheck=None,
526 binary=False,
526 binary=False,
527 symlink=False,
527 symlink=False,
528 ):
528 ):
529 func.mergetype = mergetype
529 func.mergetype = mergetype
530 func.onfailure = onfailure
530 func.onfailure = onfailure
531 func.precheck = precheck
531 func.precheck = precheck
532
532
533 binarycap = binary or mergetype == self.nomerge
533 binarycap = binary or mergetype == self.nomerge
534 symlinkcap = symlink or mergetype == self.nomerge
534 symlinkcap = symlink or mergetype == self.nomerge
535
535
536 # actual capabilities, which this internal merge tool has
536 # actual capabilities, which this internal merge tool has
537 func.capabilities = {b"binary": binarycap, b"symlink": symlinkcap}
537 func.capabilities = {b"binary": binarycap, b"symlink": symlinkcap}
General Comments 0
You need to be logged in to leave comments. Login now