##// END OF EJS Templates
registrar: replace "cmdtype" with an intent-based mechanism (API)...
Gregory Szorc -
r37734:dfc51a48 default
parent child Browse files
Show More
@@ -73,7 +73,7 b' table = {}'
73 table.update(debugcommandsmod.command._table)
73 table.update(debugcommandsmod.command._table)
74
74
75 command = registrar.command(table)
75 command = registrar.command(table)
76 readonly = registrar.command.readonly
76 INTENT_READONLY = registrar.INTENT_READONLY
77
77
78 # common command options
78 # common command options
79
79
@@ -1083,7 +1083,8 b' def branch(ui, repo, label=None, **opts)'
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1085 ] + formatteropts,
1085 ] + formatteropts,
1086 _('[-c]'), cmdtype=readonly)
1086 _('[-c]'),
1087 intents={INTENT_READONLY})
1087 def branches(ui, repo, active=False, closed=False, **opts):
1088 def branches(ui, repo, active=False, closed=False, **opts):
1088 """list repository named branches
1089 """list repository named branches
1089
1090
@@ -1282,7 +1283,8 b' def bundle(ui, repo, fname, dest=None, *'
1282 ('', 'decode', None, _('apply any matching decode filter')),
1283 ('', 'decode', None, _('apply any matching decode filter')),
1283 ] + walkopts + formatteropts,
1284 ] + walkopts + formatteropts,
1284 _('[OPTION]... FILE...'),
1285 _('[OPTION]... FILE...'),
1285 inferrepo=True, cmdtype=readonly)
1286 inferrepo=True,
1287 intents={INTENT_READONLY})
1286 def cat(ui, repo, file1, *pats, **opts):
1288 def cat(ui, repo, file1, *pats, **opts):
1287 """output the current or given revision of files
1289 """output the current or given revision of files
1288
1290
@@ -1633,7 +1635,8 b' def _docommit(ui, repo, *pats, **opts):'
1633 ('l', 'local', None, _('edit repository config')),
1635 ('l', 'local', None, _('edit repository config')),
1634 ('g', 'global', None, _('edit global config'))] + formatteropts,
1636 ('g', 'global', None, _('edit global config'))] + formatteropts,
1635 _('[-u] [NAME]...'),
1637 _('[-u] [NAME]...'),
1636 optionalrepo=True, cmdtype=readonly)
1638 optionalrepo=True,
1639 intents={INTENT_READONLY})
1637 def config(ui, repo, *values, **opts):
1640 def config(ui, repo, *values, **opts):
1638 """show combined config settings from all hgrc files
1641 """show combined config settings from all hgrc files
1639
1642
@@ -1802,7 +1805,8 b" def debugcomplete(ui, cmd='', **opts):"
1802 ('c', 'change', '', _('change made by revision'), _('REV'))
1805 ('c', 'change', '', _('change made by revision'), _('REV'))
1803 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1806 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1804 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1807 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1805 inferrepo=True, cmdtype=readonly)
1808 inferrepo=True,
1809 intents={INTENT_READONLY})
1806 def diff(ui, repo, *pats, **opts):
1810 def diff(ui, repo, *pats, **opts):
1807 """diff repository (or selected files)
1811 """diff repository (or selected files)
1808
1812
@@ -1895,7 +1899,8 b' def diff(ui, repo, *pats, **opts):'
1895 ('', 'switch-parent', None, _('diff against the second parent')),
1899 ('', 'switch-parent', None, _('diff against the second parent')),
1896 ('r', 'rev', [], _('revisions to export'), _('REV')),
1900 ('r', 'rev', [], _('revisions to export'), _('REV')),
1897 ] + diffopts + formatteropts,
1901 ] + diffopts + formatteropts,
1898 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1902 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
1903 intents={INTENT_READONLY})
1899 def export(ui, repo, *changesets, **opts):
1904 def export(ui, repo, *changesets, **opts):
1900 """dump the header and diffs for one or more changesets
1905 """dump the header and diffs for one or more changesets
1901
1906
@@ -1990,7 +1995,8 b' def export(ui, repo, *changesets, **opts'
1990 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1995 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1991 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1996 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1992 ] + walkopts + formatteropts + subrepoopts,
1997 ] + walkopts + formatteropts + subrepoopts,
1993 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1998 _('[OPTION]... [FILE]...'),
1999 intents={INTENT_READONLY})
1994 def files(ui, repo, *pats, **opts):
2000 def files(ui, repo, *pats, **opts):
1995 """list tracked files
2001 """list tracked files
1996
2002
@@ -2371,7 +2377,8 b' def _dograft(ui, repo, *revs, **opts):'
2371 ('d', 'date', None, _('list the date (short with -q)')),
2377 ('d', 'date', None, _('list the date (short with -q)')),
2372 ] + formatteropts + walkopts,
2378 ] + formatteropts + walkopts,
2373 _('[OPTION]... PATTERN [FILE]...'),
2379 _('[OPTION]... PATTERN [FILE]...'),
2374 inferrepo=True, cmdtype=readonly)
2380 inferrepo=True,
2381 intents={INTENT_READONLY})
2375 def grep(ui, repo, pattern, *pats, **opts):
2382 def grep(ui, repo, pattern, *pats, **opts):
2376 """search revision history for a pattern in specified files
2383 """search revision history for a pattern in specified files
2377
2384
@@ -2617,7 +2624,8 b' def grep(ui, repo, pattern, *pats, **opt'
2617 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2624 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2618 ('c', 'closed', False, _('show normal and closed branch heads')),
2625 ('c', 'closed', False, _('show normal and closed branch heads')),
2619 ] + templateopts,
2626 ] + templateopts,
2620 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2627 _('[-ct] [-r STARTREV] [REV]...'),
2628 intents={INTENT_READONLY})
2621 def heads(ui, repo, *branchrevs, **opts):
2629 def heads(ui, repo, *branchrevs, **opts):
2622 """show branch heads
2630 """show branch heads
2623
2631
@@ -2693,7 +2701,8 b' def heads(ui, repo, *branchrevs, **opts)'
2693 ('s', 'system', [], _('show help for specific platform(s)')),
2701 ('s', 'system', [], _('show help for specific platform(s)')),
2694 ],
2702 ],
2695 _('[-ecks] [TOPIC]'),
2703 _('[-ecks] [TOPIC]'),
2696 norepo=True, cmdtype=readonly)
2704 norepo=True,
2705 intents={INTENT_READONLY})
2697 def help_(ui, name=None, **opts):
2706 def help_(ui, name=None, **opts):
2698 """show help for a given topic or a help overview
2707 """show help for a given topic or a help overview
2699
2708
@@ -2735,7 +2744,8 b' def help_(ui, name=None, **opts):'
2735 ('B', 'bookmarks', None, _('show bookmarks')),
2744 ('B', 'bookmarks', None, _('show bookmarks')),
2736 ] + remoteopts + formatteropts,
2745 ] + remoteopts + formatteropts,
2737 _('[-nibtB] [-r REV] [SOURCE]'),
2746 _('[-nibtB] [-r REV] [SOURCE]'),
2738 optionalrepo=True, cmdtype=readonly)
2747 optionalrepo=True,
2748 intents={INTENT_READONLY})
2739 def identify(ui, repo, source=None, rev=None,
2749 def identify(ui, repo, source=None, rev=None,
2740 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2750 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2741 """identify the working directory or specified revision
2751 """identify the working directory or specified revision
@@ -3312,7 +3322,8 b' def locate(ui, repo, *pats, **opts):'
3312 _('do not display revision or any of its ancestors'), _('REV')),
3322 _('do not display revision or any of its ancestors'), _('REV')),
3313 ] + logopts + walkopts,
3323 ] + logopts + walkopts,
3314 _('[OPTION]... [FILE]'),
3324 _('[OPTION]... [FILE]'),
3315 inferrepo=True, cmdtype=readonly)
3325 inferrepo=True,
3326 intents={INTENT_READONLY})
3316 def log(ui, repo, *pats, **opts):
3327 def log(ui, repo, *pats, **opts):
3317 """show revision history of entire repository or files
3328 """show revision history of entire repository or files
3318
3329
@@ -3480,7 +3491,8 b' def log(ui, repo, *pats, **opts):'
3480 [('r', 'rev', '', _('revision to display'), _('REV')),
3491 [('r', 'rev', '', _('revision to display'), _('REV')),
3481 ('', 'all', False, _("list files from all revisions"))]
3492 ('', 'all', False, _("list files from all revisions"))]
3482 + formatteropts,
3493 + formatteropts,
3483 _('[-r REV]'), cmdtype=readonly)
3494 _('[-r REV]'),
3495 intents={INTENT_READONLY})
3484 def manifest(ui, repo, node=None, rev=None, **opts):
3496 def manifest(ui, repo, node=None, rev=None, **opts):
3485 """output the current or given revision of the project manifest
3497 """output the current or given revision of the project manifest
3486
3498
@@ -3758,7 +3770,7 b' def parents(ui, repo, file_=None, **opts'
3758 displayer.close()
3770 displayer.close()
3759
3771
3760 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3772 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3761 cmdtype=readonly)
3773 intents={INTENT_READONLY})
3762 def paths(ui, repo, search=None, **opts):
3774 def paths(ui, repo, search=None, **opts):
3763 """show aliases for remote repositories
3775 """show aliases for remote repositories
3764
3776
@@ -4696,7 +4708,7 b' def rollback(ui, repo, **opts):'
4696 return repo.rollback(dryrun=opts.get(r'dry_run'),
4708 return repo.rollback(dryrun=opts.get(r'dry_run'),
4697 force=opts.get(r'force'))
4709 force=opts.get(r'force'))
4698
4710
4699 @command('root', [], cmdtype=readonly)
4711 @command('root', [], intents={INTENT_READONLY})
4700 def root(ui, repo):
4712 def root(ui, repo):
4701 """print the root (top) of the current working directory
4713 """print the root (top) of the current working directory
4702
4714
@@ -4790,7 +4802,8 b' def serve(ui, repo, **opts):'
4790 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4802 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4791 ] + walkopts + subrepoopts + formatteropts,
4803 ] + walkopts + subrepoopts + formatteropts,
4792 _('[OPTION]... [FILE]...'),
4804 _('[OPTION]... [FILE]...'),
4793 inferrepo=True, cmdtype=readonly)
4805 inferrepo=True,
4806 intents={INTENT_READONLY})
4794 def status(ui, repo, *pats, **opts):
4807 def status(ui, repo, *pats, **opts):
4795 """show changed files in the working directory
4808 """show changed files in the working directory
4796
4809
@@ -4958,7 +4971,8 b' def status(ui, repo, *pats, **opts):'
4958
4971
4959 @command('^summary|sum',
4972 @command('^summary|sum',
4960 [('', 'remote', None, _('check for push and pull'))],
4973 [('', 'remote', None, _('check for push and pull'))],
4961 '[--remote]', cmdtype=readonly)
4974 '[--remote]',
4975 intents={INTENT_READONLY})
4962 def summary(ui, repo, **opts):
4976 def summary(ui, repo, **opts):
4963 """summarize working directory state
4977 """summarize working directory state
4964
4978
@@ -5359,7 +5373,7 b' def tag(ui, repo, name1, *names, **opts)'
5359 finally:
5373 finally:
5360 release(lock, wlock)
5374 release(lock, wlock)
5361
5375
5362 @command('tags', formatteropts, '', cmdtype=readonly)
5376 @command('tags', formatteropts, '', intents={INTENT_READONLY})
5363 def tags(ui, repo, **opts):
5377 def tags(ui, repo, **opts):
5364 """list repository tags
5378 """list repository tags
5365
5379
@@ -5596,7 +5610,8 b' def verify(ui, repo):'
5596 """
5610 """
5597 return hg.verify(repo)
5611 return hg.verify(repo)
5598
5612
5599 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5613 @command('version', [] + formatteropts, norepo=True,
5614 intents={INTENT_READONLY})
5600 def version_(ui, **opts):
5615 def version_(ui, **opts):
5601 """output version and copyright information"""
5616 """output version and copyright information"""
5602 opts = pycompat.byteskwargs(opts)
5617 opts = pycompat.byteskwargs(opts)
@@ -35,7 +35,6 b' from . import ('
35 hook,
35 hook,
36 profiling,
36 profiling,
37 pycompat,
37 pycompat,
38 registrar,
39 scmutil,
38 scmutil,
40 ui as uimod,
39 ui as uimod,
41 util,
40 util,
@@ -46,8 +45,6 b' from .utils import ('
46 stringutil,
45 stringutil,
47 )
46 )
48
47
49 unrecoverablewrite = registrar.command.unrecoverablewrite
50
51 class request(object):
48 class request(object):
52 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
49 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
53 ferr=None, prereposetups=None):
50 ferr=None, prereposetups=None):
@@ -562,7 +559,7 b' class cmdalias(object):'
562 return aliasargs(self.fn, args)
559 return aliasargs(self.fn, args)
563
560
564 def __getattr__(self, name):
561 def __getattr__(self, name):
565 adefaults = {r'norepo': True, r'cmdtype': unrecoverablewrite,
562 adefaults = {r'norepo': True, r'intents': set(),
566 r'optionalrepo': False, r'inferrepo': False}
563 r'optionalrepo': False, r'inferrepo': False}
567 if name not in adefaults:
564 if name not in adefaults:
568 raise AttributeError(name)
565 raise AttributeError(name)
@@ -138,15 +138,18 b' class command(_funcregistrarbase):'
138 potential repository locations. See ``findrepo()``. If a repository is
138 potential repository locations. See ``findrepo()``. If a repository is
139 found, it will be used and passed to the decorated function.
139 found, it will be used and passed to the decorated function.
140
140
141 There are three constants in the class which tells what type of the command
141 The `intents` argument defines a set of intended actions or capabilities
142 that is. That information will be helpful at various places. It will be also
142 the command is taking. These intents can be used to affect the construction
143 be used to decide what level of access the command has on hidden commits.
143 of the repository object passed to the command. For example, commands
144 The constants are:
144 declaring that they are read-only could receive a repository that doesn't
145 have any methods allowing repository mutation. Other intents could be used
146 to prevent the command from running if the requested intent could not be
147 fulfilled.
145
148
146 `unrecoverablewrite` is for those write commands which can't be recovered
149 The following intents are defined:
147 like push.
150
148 `recoverablewrite` is for write commands which can be recovered like commit.
151 readonly
149 `readonly` is for commands which are read only.
152 The command is read-only
150
153
151 The signature of the decorated function looks like this:
154 The signature of the decorated function looks like this:
152 def cmd(ui[, repo] [, <args>] [, <options>])
155 def cmd(ui[, repo] [, <args>] [, <options>])
@@ -161,29 +164,22 b' class command(_funcregistrarbase):'
161 descriptions and examples.
164 descriptions and examples.
162 """
165 """
163
166
164 unrecoverablewrite = "unrecoverable"
165 recoverablewrite = "recoverable"
166 readonly = "readonly"
167
168 possiblecmdtypes = {unrecoverablewrite, recoverablewrite, readonly}
169
170 def _doregister(self, func, name, options=(), synopsis=None,
167 def _doregister(self, func, name, options=(), synopsis=None,
171 norepo=False, optionalrepo=False, inferrepo=False,
168 norepo=False, optionalrepo=False, inferrepo=False,
172 cmdtype=unrecoverablewrite):
169 intents=None):
173
170
174 if cmdtype not in self.possiblecmdtypes:
175 raise error.ProgrammingError("unknown cmdtype value '%s' for "
176 "'%s' command" % (cmdtype, name))
177 func.norepo = norepo
171 func.norepo = norepo
178 func.optionalrepo = optionalrepo
172 func.optionalrepo = optionalrepo
179 func.inferrepo = inferrepo
173 func.inferrepo = inferrepo
180 func.cmdtype = cmdtype
174 func.intents = intents or set()
181 if synopsis:
175 if synopsis:
182 self._table[name] = func, list(options), synopsis
176 self._table[name] = func, list(options), synopsis
183 else:
177 else:
184 self._table[name] = func, list(options)
178 self._table[name] = func, list(options)
185 return func
179 return func
186
180
181 INTENT_READONLY = b'readonly'
182
187 class revsetpredicate(_funcregistrarbase):
183 class revsetpredicate(_funcregistrarbase):
188 """Decorator to register revset predicate
184 """Decorator to register revset predicate
189
185
@@ -192,7 +192,7 b' Test special hash/rev'
192 $ hg log -qr 'null:wdir() & 2147483647'
192 $ hg log -qr 'null:wdir() & 2147483647'
193 2147483647:ffffffffffff
193 2147483647:ffffffffffff
194
194
195 Commands with undefined cmdtype should not work right now
195 Commands with undefined intent should not work right now
196
196
197 $ hg phase -r 28ad74
197 $ hg phase -r 28ad74
198 abort: hidden revision '28ad74' was rewritten as: 2443a0e66469!
198 abort: hidden revision '28ad74' was rewritten as: 2443a0e66469!
General Comments 0
You need to be logged in to leave comments. Login now