D6063: setup: define build_doc command

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Sun Mar 3 18:52:09 EST 2019


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.
  
  1. no-check-commit because forced foo_bar function names

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6063

AFFECTED FILES
  doc/Makefile
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -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,
diff --git a/doc/Makefile b/doc/Makefile
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -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 $@



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list