Mercurial > hg
comparison setup.py @ 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 | aaad36b88298 |
children | ed35057421ae |
comparison
equal
deleted
inserted
replaced
41849:d22198b4b3dd | 41850:d80d48928eb1 |
---|---|
238 # import py2exe's patched Distribution class | 238 # import py2exe's patched Distribution class |
239 from distutils.core import Distribution | 239 from distutils.core import Distribution |
240 except ImportError: | 240 except ImportError: |
241 py2exeloaded = False | 241 py2exeloaded = False |
242 | 242 |
243 def runcmd(cmd, env): | 243 def runcmd(cmd, env, cwd=None): |
244 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, | 244 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, |
245 stderr=subprocess.PIPE, env=env) | 245 stderr=subprocess.PIPE, env=env, cwd=cwd) |
246 out, err = p.communicate() | 246 out, err = p.communicate() |
247 return p.returncode, out, err | 247 return p.returncode, out, err |
248 | 248 |
249 class hgcommand(object): | 249 class hgcommand(object): |
250 def __init__(self, cmd, env): | 250 def __init__(self, cmd, env): |
700 @property | 700 @property |
701 def hgexepath(self): | 701 def hgexepath(self): |
702 dir = os.path.dirname(self.get_ext_fullpath('dummy')) | 702 dir = os.path.dirname(self.get_ext_fullpath('dummy')) |
703 return os.path.join(self.build_temp, dir, 'hg.exe') | 703 return os.path.join(self.build_temp, dir, 'hg.exe') |
704 | 704 |
705 class hgbuilddoc(Command): | |
706 description = 'build documentation' | |
707 user_options = [ | |
708 ('man', None, 'generate man pages'), | |
709 ('html', None, 'generate html pages'), | |
710 ] | |
711 | |
712 def initialize_options(self): | |
713 self.man = None | |
714 self.html = None | |
715 | |
716 def finalize_options(self): | |
717 # If --man or --html are set, only generate what we're told to. | |
718 # Otherwise generate everything. | |
719 have_subset = self.man is not None or self.html is not None | |
720 | |
721 if have_subset: | |
722 self.man = True if self.man else False | |
723 self.html = True if self.html else False | |
724 else: | |
725 self.man = True | |
726 self.html = True | |
727 | |
728 def run(self): | |
729 def normalizecrlf(p): | |
730 with open(p, 'rb') as fh: | |
731 orig = fh.read() | |
732 | |
733 if b'\r\n' not in orig: | |
734 return | |
735 | |
736 log.info('normalizing %s to LF line endings' % p) | |
737 with open(p, 'wb') as fh: | |
738 fh.write(orig.replace(b'\r\n', b'\n')) | |
739 | |
740 def gentxt(root): | |
741 txt = 'doc/%s.txt' % root | |
742 log.info('generating %s' % txt) | |
743 res, out, err = runcmd( | |
744 [sys.executable, 'gendoc.py', root], | |
745 os.environ, | |
746 cwd='doc') | |
747 if res: | |
748 raise SystemExit('error running gendoc.py: %s' % | |
749 '\n'.join([out, err])) | |
750 | |
751 with open(txt, 'wb') as fh: | |
752 fh.write(out) | |
753 | |
754 def gengendoc(root): | |
755 gendoc = 'doc/%s.gendoc.txt' % root | |
756 | |
757 log.info('generating %s' % gendoc) | |
758 res, out, err = runcmd( | |
759 [sys.executable, 'gendoc.py', '%s.gendoc' % root], | |
760 os.environ, | |
761 cwd='doc') | |
762 if res: | |
763 raise SystemExit('error running gendoc: %s' % | |
764 '\n'.join([out, err])) | |
765 | |
766 with open(gendoc, 'wb') as fh: | |
767 fh.write(out) | |
768 | |
769 def genman(root): | |
770 log.info('generating doc/%s' % root) | |
771 res, out, err = runcmd( | |
772 [sys.executable, 'runrst', 'hgmanpage', '--halt', 'warning', | |
773 '--strip-elements-with-class', 'htmlonly', | |
774 '%s.txt' % root, root], | |
775 os.environ, | |
776 cwd='doc') | |
777 if res: | |
778 raise SystemExit('error running runrst: %s' % | |
779 '\n'.join([out, err])) | |
780 | |
781 normalizecrlf('doc/%s' % root) | |
782 | |
783 def genhtml(root): | |
784 log.info('generating doc/%s.html' % root) | |
785 res, out, err = runcmd( | |
786 [sys.executable, 'runrst', 'html', '--halt', 'warning', | |
787 '--link-stylesheet', '--stylesheet-path', 'style.css', | |
788 '%s.txt' % root, '%s.html' % root], | |
789 os.environ, | |
790 cwd='doc') | |
791 if res: | |
792 raise SystemExit('error running runrst: %s' % | |
793 '\n'.join([out, err])) | |
794 | |
795 normalizecrlf('doc/%s.html' % root) | |
796 | |
797 # This logic is duplicated in doc/Makefile. | |
798 sources = {f for f in os.listdir('mercurial/help') | |
799 if re.search('[0-9]\.txt$', f)} | |
800 | |
801 # common.txt is a one-off. | |
802 gentxt('common') | |
803 | |
804 for source in sorted(sources): | |
805 assert source[-4:] == '.txt' | |
806 root = source[:-4] | |
807 | |
808 gentxt(root) | |
809 gengendoc(root) | |
810 | |
811 if self.man: | |
812 genman(root) | |
813 if self.html: | |
814 genhtml(root) | |
815 | |
705 class hginstall(install): | 816 class hginstall(install): |
706 | 817 |
707 user_options = install.user_options + [ | 818 user_options = install.user_options + [ |
708 ('old-and-unmanageable', None, | 819 ('old-and-unmanageable', None, |
709 'noop, present for eggless setuptools compat'), | 820 'noop, present for eggless setuptools compat'), |
825 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape)) | 936 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape)) |
826 with open(outfile, 'wb') as fp: | 937 with open(outfile, 'wb') as fp: |
827 fp.write(data) | 938 fp.write(data) |
828 | 939 |
829 cmdclass = {'build': hgbuild, | 940 cmdclass = {'build': hgbuild, |
941 'build_doc': hgbuilddoc, | |
830 'build_mo': hgbuildmo, | 942 'build_mo': hgbuildmo, |
831 'build_ext': hgbuildext, | 943 'build_ext': hgbuildext, |
832 'build_py': hgbuildpy, | 944 'build_py': hgbuildpy, |
833 'build_scripts': hgbuildscripts, | 945 'build_scripts': hgbuildscripts, |
834 'build_hgextindex': buildhgextindex, | 946 'build_hgextindex': buildhgextindex, |