Mercurial > hg
view doc/gendoc.py @ 43385:6469c23a40a2 stable
fsmonitor: refresh pywatchman with upstream
This commit vendors pywatchman commit 259dc66dc9591f9b7ce76d0275bb1065f390c9b1
from upstream without modifications. The previously vendored pywatchman
from changeset 16f4b341288d was from Git commit c77452.
This commit effectively undoes the following Mercurial changesets:
* dd35abc409ee fsmonitor: correct an error message
* b1f62cd39b5c fsmonitor: layer on another hack in bser.c for os.stat()
compat (issue5811)
* c31ce080eb75 py3: convert arguments, cwd and env to native strings when
spawning subprocess
* 876494fd967d cleanup: delete lots of unused local variables
* 57264906a996 watchman: add the possibility to set the exact watchman
binary location
The newly-vendored code has support for specifying the binary location,
so 57264906a996 does not need applied. But we do need to modify our
code to specify a proper argument name.
876494fd967d is not important, so it will be ignored.
c31ce080eb75 globally changed the code base to always pass
str to subprocess. But pywatchman's code is Python 3 clean, so
we don't need to do this.
This leaves dd35abc409ee and b1f62cd39b5c, which will be re-applied in
subsequent commits.
Differential Revision: https://phab.mercurial-scm.org/D7201
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 02 Nov 2019 12:42:23 -0700 |
parents | 2372284d9457 |
children | 313e3a279828 |
line wrap: on
line source
#!/usr/bin/env python """usage: %s DOC ... where DOC is the name of a document """ from __future__ import absolute_import import os import sys import textwrap try: import msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) except ImportError: pass # This script is executed during installs and may not have C extensions # available. Relax C module requirements. os.environ[r'HGMODULEPOLICY'] = r'allow' # import from the live mercurial repo sys.path.insert(0, r"..") from mercurial import demandimport demandimport.enable() # Load util so that the locale path is set by i18n.setdatapath() before # calling _(). from mercurial import util util.datapath from mercurial import ( commands, encoding, extensions, help, minirst, pycompat, ui as uimod, ) from mercurial.i18n import ( gettext, _, ) table = commands.table globalopts = commands.globalopts helptable = help.helptable loaddoc = help.loaddoc def get_desc(docstr): if not docstr: return b"", b"" # sanitize docstr = docstr.strip(b"\n") docstr = docstr.rstrip() shortdesc = docstr.splitlines()[0].strip() i = docstr.find(b"\n") if i != -1: desc = docstr[i + 2 :] else: desc = shortdesc desc = textwrap.dedent(desc.decode('latin1')).encode('latin1') return (shortdesc, desc) def get_opts(opts): for opt in opts: if len(opt) == 5: shortopt, longopt, default, desc, optlabel = opt else: shortopt, longopt, default, desc = opt optlabel = _(b"VALUE") allopts = [] if shortopt: allopts.append(b"-%s" % shortopt) if longopt: allopts.append(b"--%s" % longopt) if isinstance(default, list): allopts[-1] += b" <%s[+]>" % optlabel elif (default is not None) and not isinstance(default, bool): allopts[-1] += b" <%s>" % optlabel if b'\n' in desc: # only remove line breaks and indentation desc = b' '.join(l.lstrip() for l in desc.split(b'\n')) desc += default and _(b" (default: %s)") % bytes(default) or b"" yield (b", ".join(allopts), desc) def get_cmd(cmd, cmdtable): d = {} attr = cmdtable[cmd] cmds = cmd.lstrip(b"^").split(b"|") d[b'cmd'] = cmds[0] d[b'aliases'] = cmd.split(b"|")[1:] d[b'desc'] = get_desc(gettext(pycompat.getdoc(attr[0]))) d[b'opts'] = list(get_opts(attr[1])) s = b'hg ' + cmds[0] if len(attr) > 2: if not attr[2].startswith(b'hg'): s += b' ' + attr[2] else: s = attr[2] d[b'synopsis'] = s.strip() return d def showdoc(ui): # print options ui.write(minirst.section(_(b"Options"))) multioccur = False for optstr, desc in get_opts(globalopts): ui.write(b"%s\n %s\n\n" % (optstr, desc)) if optstr.endswith(b"[+]>"): multioccur = True if multioccur: ui.write(_(b"\n[+] marked option can be specified multiple times\n")) ui.write(b"\n") # print cmds ui.write(minirst.section(_(b"Commands"))) commandprinter(ui, table, minirst.subsection, minirst.subsubsection) # print help topics # The config help topic is included in the hgrc.5 man page. helpprinter(ui, helptable, minirst.section, exclude=[b'config']) ui.write(minirst.section(_(b"Extensions"))) ui.write( _( b"This section contains help for extensions that are " b"distributed together with Mercurial. Help for other " b"extensions is available in the help system." ) ) ui.write( ( b"\n\n" b".. contents::\n" b" :class: htmlonly\n" b" :local:\n" b" :depth: 1\n\n" ) ) for extensionname in sorted(allextensionnames()): mod = extensions.load(ui, extensionname, None) ui.write(minirst.subsection(extensionname)) ui.write(b"%s\n\n" % gettext(pycompat.getdoc(mod))) cmdtable = getattr(mod, 'cmdtable', None) if cmdtable: ui.write(minirst.subsubsection(_(b'Commands'))) commandprinter( ui, cmdtable, minirst.subsubsubsection, minirst.subsubsubsubsection, ) def showtopic(ui, topic): extrahelptable = [ ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC), ([b"hg.1"], b'', loaddoc(b'hg.1'), help.TOPIC_CATEGORY_CONFIG), ([b"hg-ssh.8"], b'', loaddoc(b'hg-ssh.8'), help.TOPIC_CATEGORY_CONFIG), ( [b"hgignore.5"], b'', loaddoc(b'hgignore.5'), help.TOPIC_CATEGORY_CONFIG, ), ([b"hgrc.5"], b'', loaddoc(b'hgrc.5'), help.TOPIC_CATEGORY_CONFIG), ( [b"hgignore.5.gendoc"], b'', loaddoc(b'hgignore'), help.TOPIC_CATEGORY_CONFIG, ), ( [b"hgrc.5.gendoc"], b'', loaddoc(b'config'), help.TOPIC_CATEGORY_CONFIG, ), ] helpprinter(ui, helptable + extrahelptable, None, include=[topic]) def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]): for h in helptable: names, sec, doc = h[0:3] if exclude and names[0] in exclude: continue if include and names[0] not in include: continue for name in names: ui.write(b".. _%s:\n" % name) ui.write(b"\n") if sectionfunc: ui.write(sectionfunc(sec)) if callable(doc): doc = doc(ui) ui.write(doc) ui.write(b"\n") def commandprinter(ui, cmdtable, sectionfunc, subsectionfunc): """Render restructuredtext describing a list of commands and their documentations, grouped by command category. Args: ui: UI object to write the output to cmdtable: a dict that maps a string of the command name plus its aliases (separated with pipes) to a 3-tuple of (the command's function, a list of its option descriptions, and a string summarizing available options). Example, with aliases added for demonstration purposes: 'phase|alias1|alias2': ( <function phase at 0x7f0816b05e60>, [ ('p', 'public', False, 'set changeset phase to public'), ..., ('r', 'rev', [], 'target revision', 'REV')], '[-p|-d|-s] [-f] [-r] [REV...]' ) sectionfunc: minirst function to format command category headers subsectionfunc: minirst function to format command headers """ h = {} for c, attr in cmdtable.items(): f = c.split(b"|")[0] f = f.lstrip(b"^") h[f] = c cmds = h.keys() def helpcategory(cmd): """Given a canonical command name from `cmds` (above), retrieve its help category. If helpcategory is None, default to CATEGORY_NONE. """ fullname = h[cmd] details = cmdtable[fullname] helpcategory = details[0].helpcategory return helpcategory or help.registrar.command.CATEGORY_NONE cmdsbycategory = {category: [] for category in help.CATEGORY_ORDER} for cmd in cmds: # If a command category wasn't registered, the command won't get # rendered below, so we raise an AssertionError. if helpcategory(cmd) not in cmdsbycategory: raise AssertionError( "The following command did not register its (category) in " "help.CATEGORY_ORDER: %s (%s)" % (cmd, helpcategory(cmd)) ) cmdsbycategory[helpcategory(cmd)].append(cmd) # Print the help for each command. We present the commands grouped by # category, and we use help.CATEGORY_ORDER as a guide for a helpful order # in which to present the categories. for category in help.CATEGORY_ORDER: categorycmds = cmdsbycategory[category] if not categorycmds: # Skip empty categories continue # Print a section header for the category. # For now, the category header is at the same level as the headers for # the commands in the category; this is fixed in the next commit. ui.write(sectionfunc(help.CATEGORY_NAMES[category])) # Print each command in the category for f in sorted(categorycmds): if f.startswith(b"debug"): continue d = get_cmd(h[f], cmdtable) ui.write(subsectionfunc(d[b'cmd'])) # short description ui.write(d[b'desc'][0]) # synopsis ui.write(b"::\n\n") synopsislines = d[b'synopsis'].splitlines() for line in synopsislines: # some commands (such as rebase) have a multi-line # synopsis ui.write(b" %s\n" % line) ui.write(b'\n') # description ui.write(b"%s\n\n" % d[b'desc'][1]) # options opt_output = list(d[b'opts']) if opt_output: opts_len = max([len(line[0]) for line in opt_output]) ui.write(_(b"Options:\n\n")) multioccur = False for optstr, desc in opt_output: if desc: s = b"%-*s %s" % (opts_len, optstr, desc) else: s = optstr ui.write(b"%s\n" % s) if optstr.endswith(b"[+]>"): multioccur = True if multioccur: ui.write( _( b"\n[+] marked option can be specified" b" multiple times\n" ) ) ui.write(b"\n") # aliases if d[b'aliases']: ui.write(_(b" aliases: %s\n\n") % b" ".join(d[b'aliases'])) def allextensionnames(): return set(extensions.enabled().keys()) | set(extensions.disabled().keys()) if __name__ == "__main__": doc = b'hg.1.gendoc' if len(sys.argv) > 1: doc = encoding.strtolocal(sys.argv[1]) ui = uimod.ui.load() if doc == b'hg.1.gendoc': showdoc(ui) else: showtopic(ui, encoding.strtolocal(sys.argv[1]))