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