Mercurial > hg
changeset 41850:d80d48928eb1
setup: define build_doc command
Currently, various processes for packaging Mercurial state to
manually invoke `make -C doc` in order to generate the documentation.
This Makefile merely invokes `gendoc.py` and `runrst` to produce
man pages and HTML pages.
Not all environments may have the ability to easily run
Makefiles. Windows is notably in this set.
This commit ports the man page and HTML generation logic from
doc/Makefile to setup.py. We introduce a new build_doc command
which generates documentation by calling gendoc.py and runrst.
The documentation can now be built via pure Python by running
`python setup.py build_doc`.
We don't implement dependency tracking because IMO it is more
effort than it is worth.
We could potentially remove the duplicated functionality in
doc/Makefile. But I'm not sure what all is depending on it. So
I plan to keep it around.
# no-check-commit because forced foo_bar function names
Differential Revision: https://phab.mercurial-scm.org/D6063
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 03 Mar 2019 10:31:23 -0800 |
parents | d22198b4b3dd |
children | ed35057421ae |
files | doc/Makefile setup.py |
diffstat | 2 files changed, 115 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/Makefile Sun Mar 03 09:16:37 2019 -0800 +++ b/doc/Makefile Sun Mar 03 10:31:23 2019 -0800 @@ -17,6 +17,7 @@ html: $(HTML) +# This logic is duplicated in setup.py:hgbuilddoc() common.txt $(SOURCES) $(SOURCES:%.txt=%.gendoc.txt): $(GENDOC) ${PYTHON} gendoc.py "$(basename $@)" > $@.tmp mv $@.tmp $@
--- a/setup.py Sun Mar 03 09:16:37 2019 -0800 +++ b/setup.py Sun Mar 03 10:31:23 2019 -0800 @@ -240,9 +240,9 @@ except ImportError: py2exeloaded = False -def runcmd(cmd, env): +def runcmd(cmd, env, cwd=None): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, env=env) + stderr=subprocess.PIPE, env=env, cwd=cwd) out, err = p.communicate() return p.returncode, out, err @@ -702,6 +702,117 @@ dir = os.path.dirname(self.get_ext_fullpath('dummy')) return os.path.join(self.build_temp, dir, 'hg.exe') +class hgbuilddoc(Command): + description = 'build documentation' + user_options = [ + ('man', None, 'generate man pages'), + ('html', None, 'generate html pages'), + ] + + def initialize_options(self): + self.man = None + self.html = None + + def finalize_options(self): + # If --man or --html are set, only generate what we're told to. + # Otherwise generate everything. + have_subset = self.man is not None or self.html is not None + + if have_subset: + self.man = True if self.man else False + self.html = True if self.html else False + else: + self.man = True + self.html = True + + def run(self): + def normalizecrlf(p): + with open(p, 'rb') as fh: + orig = fh.read() + + if b'\r\n' not in orig: + return + + log.info('normalizing %s to LF line endings' % p) + with open(p, 'wb') as fh: + fh.write(orig.replace(b'\r\n', b'\n')) + + def gentxt(root): + txt = 'doc/%s.txt' % root + log.info('generating %s' % txt) + res, out, err = runcmd( + [sys.executable, 'gendoc.py', root], + os.environ, + cwd='doc') + if res: + raise SystemExit('error running gendoc.py: %s' % + '\n'.join([out, err])) + + with open(txt, 'wb') as fh: + fh.write(out) + + def gengendoc(root): + gendoc = 'doc/%s.gendoc.txt' % root + + log.info('generating %s' % gendoc) + res, out, err = runcmd( + [sys.executable, 'gendoc.py', '%s.gendoc' % root], + os.environ, + cwd='doc') + if res: + raise SystemExit('error running gendoc: %s' % + '\n'.join([out, err])) + + with open(gendoc, 'wb') as fh: + fh.write(out) + + def genman(root): + log.info('generating doc/%s' % root) + res, out, err = runcmd( + [sys.executable, 'runrst', 'hgmanpage', '--halt', 'warning', + '--strip-elements-with-class', 'htmlonly', + '%s.txt' % root, root], + os.environ, + cwd='doc') + if res: + raise SystemExit('error running runrst: %s' % + '\n'.join([out, err])) + + normalizecrlf('doc/%s' % root) + + def genhtml(root): + log.info('generating doc/%s.html' % root) + res, out, err = runcmd( + [sys.executable, 'runrst', 'html', '--halt', 'warning', + '--link-stylesheet', '--stylesheet-path', 'style.css', + '%s.txt' % root, '%s.html' % root], + os.environ, + cwd='doc') + if res: + raise SystemExit('error running runrst: %s' % + '\n'.join([out, err])) + + normalizecrlf('doc/%s.html' % root) + + # This logic is duplicated in doc/Makefile. + sources = {f for f in os.listdir('mercurial/help') + if re.search('[0-9]\.txt$', f)} + + # common.txt is a one-off. + gentxt('common') + + for source in sorted(sources): + assert source[-4:] == '.txt' + root = source[:-4] + + gentxt(root) + gengendoc(root) + + if self.man: + genman(root) + if self.html: + genhtml(root) + class hginstall(install): user_options = install.user_options + [ @@ -827,6 +938,7 @@ fp.write(data) cmdclass = {'build': hgbuild, + 'build_doc': hgbuilddoc, 'build_mo': hgbuildmo, 'build_ext': hgbuildext, 'build_py': hgbuildpy,