#!/usr/bin/env python
-from distutils.core import setup
+from distutils.core import setup, Command
+from distutils.command.build import build
+from distutils.command.build_py import build_py
+from distutils.command.install import install
+from distutils import log
+import os
import os.path
+import sys
-from libbe import _version
+try:
+ import docutils
+ import docutils.core
+except ImportError, e:
+ log.warn(
+ 'cannot import docutils (required to build documentation): %s' % e)
+ docutils = None
-rev_id = _version.version_info["revision"]
-rev_date = _version.version_info["date"]
+try:
+ import sphinx
+except ImportError, e:
+ log.warn('cannot import sphinx (required to build user guide): %s' % e)
+ sphinx = None
-data_files = []
+from libbe.version import version
+from libbe.util.subproc import invoke
+
+
+_this_dir = os.path.dirname(__file__)
+
+
+class _build_py (build_py):
+ def run(self):
+ target_dir = os.path.join(self.build_lib, 'libbe')
+ if os.path.exists('.git'):
+ self._generate_version(target_dir)
+ # distutils uses old-style classes, so no super()
+ build_py.run(self)
+
+ def _generate_version(self, target_dir):
+ version_path = os.path.join(target_dir, '_version.py')
+ log.info('generate %s using git' % version_path)
+ if not self.dry_run:
+ format = (
+ '"Autogenerated by make libbe/_version.py"%n'
+ 'version_info = {%n'
+ ' "date":"%cd",%n'
+ ' "revision":"%H",%n'
+ ' "committer":"%cn"}%n'
+ )
+ status,stdout,stderr = invoke(
+ ['git', 'log', '-1', '--date=short',
+ "--pretty='format:%s'" % format])
+
+
+class build_doc (Command):
+ description = "build package documentation"
+
+ user_options = [
+ ('man', None, 'compile man page (with docutils) [default]'),
+ ('no-man', None, "don't compile man page"),
+ ('guide', None, 'compile user guide (with sphinx) [default]'),
+ ('no-guide', None, "don't compile user guide"),
+ ]
+
+ boolean_options = ['man', 'guide']
+ negative_opt = {'no-man': 'man', 'no-guide': 'guide'}
+
+ def initialize_options(self):
+ self.man = True
+ self.guide = True
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ if self.man:
+ self._build_man()
+ if self.guide:
+ self._build_guide()
+
+ def _build_man(self):
+ if docutils == None:
+ log.error('cannot build man page without docutils')
+ return
+ man_dir = os.path.join(_this_dir, 'doc', 'man')
+ for filename in os.listdir(man_dir):
+ basename,extension = os.path.splitext(filename)
+ if extension == '.txt':
+ source_path = os.path.join(man_dir, filename)
+ destination_path = os.path.join(man_dir, basename)
+ log.info('converting %s -> %s' % (source_path, destination_path))
+ if not self.dry_run:
+ docutils.core.publish_file(
+ source_path=source_path,
+ destination_path=destination_path,
+ writer_name='manpage')
+
+ def _build_guide(self):
+ if docutils == None:
+ log.error('cannot build user guide without docutils')
+ return
+ if sphinx == None:
+ log.error('cannot build user guide without sphinx')
+ return
+ log.info('building user guide')
+ doc_dir = os.path.join(_this_dir, 'doc')
+ doctree_dir = os.path.join(doc_dir, '.build', 'doctrees')
+ html_dir = os.path.join(doc_dir, '.build', 'html')
+ log.info('generating autodoc/automodule pages for API documentation')
+ if not self.dry_run:
+ cwd = os.getcwd()
+ try:
+ os.chdir(doc_dir)
+ status,stdout,stderr = invoke(
+ [sys.executable, 'generate-libbe-txt.py'])
+ finally:
+ os.chdir(cwd)
+ log.info('building user guide with sphinx')
+ if not self.dry_run:
+ ret = sphinx.main([
+ 'sphinx-build', '-d', doctree_dir,
+ '-b', 'html', doc_dir, html_dir])
+ if ret != 0:
+ log.error('errors building user guide')
+
+
+build.sub_commands.append(('build_doc', None))
+
+
+class install_doc (Command):
+ description = "install package documentation"
+
+ user_options = [
+ ('install-dir=', 'd',
+ "base directory for installing doc files "
+ "(default: installation base dir)"),
+ ('root=', None,
+ "install everything relative to this alternate root directory"),
+ ('man', None, 'install man page [default]'),
+ ('no-man', None, "don't install man page"),
+ ('man-dir=', None, 'man page installation directory'),
+ ('guide', None, 'install user guide [default]'),
+ ('no-guide', None, "don't install user guide"),
+ ('guide-dir=', None, 'guide installation directory'),
+ ]
+
+ boolean_options = ['man', 'guide']
+ negative_opt = {'no-man': 'man', 'no-guide': 'guide'}
+
+ def initialize_options(self):
+ self.install_dir = None
+ self.root = None
+ self.man = True
+ self.man_dir = None
+ self.guide = True
+ self.guide_dir = None
+ self.outfiles = []
+
+ def finalize_options(self):
+ self.set_undefined_options('install',
+ ('install_data', 'install_dir'),
+ ('root', 'root'),
+ )
+ if not self.man_dir:
+ self.man_dir = os.path.join(
+ self.install_dir, 'share', 'man')
+ if not self.guide_dir:
+ self.guide_dir = os.path.join(
+ self.install_dir, 'share', 'doc', 'be')
+
+ def run(self):
+ if self.man:
+ self._install_man()
+ if self.guide:
+ self._install_guide()
+
+ def _install_man(self):
+ if docutils == None:
+ log.error('cannot build man page without docutils')
+ return
+ man_dir = os.path.join(_this_dir, 'doc', 'man')
+ for filename in os.listdir(man_dir):
+ basename,extension = os.path.splitext(filename)
+ if extension == '.txt':
+ man_path = os.path.join(man_dir, basename)
+ if not os.path.exists(man_path):
+ log.warn('expected man page %s not found' % man_path)
+ continue
+ page,dot_section = os.path.splitext(basename)
+ section = dot_section.lstrip('.')
+ section_dir = os.path.join(self.man_dir, 'man%s' % section)
+ outfile = os.path.join(section_dir, basename)
+ self.mkpath(section_dir)
+ self.copy_file(infile=man_path, outfile=outfile)
+ self.outfiles.append(outfile)
+
+ def _install_guide(self):
+ return
+ if docutils == None:
+ log.error('cannot build user guide without docutils')
+ return
+ if sphinx == None:
+ log.error('cannot build user guide without sphinx')
+ return
+ log.info('building user guide')
+ doc_dir = os.path.join(_this_dir, 'doc')
+ doctree_dir = os.path.join(doc_dir, '.build', 'doctrees')
+ html_dir = os.path.join(doc_dir, '.build', 'html')
+ log.info('generating autodoc/automodule pages for API documentation')
+ if not self.dry_run:
+ cwd = os.getcwd()
+ try:
+ os.chdir(doc_dir)
+ status,stdout,stderr = invoke(
+ [sys.executable, 'generate-libbe-txt.py'])
+ finally:
+ os.chdir(cwd)
+ log.info('building user guide with sphinx')
+ if not self.dry_run:
+ ret = sphinx.main([
+ 'sphinx-build', '-d', doctree_dir,
+ '-b', 'html', doc_dir, html_dir])
+ if ret != 0:
+ log.error('errors building user guide')
+
+
+ # add an entry to data_files
+ data_files.append(('share/doc/be/html', [html_dir]))
+ log.info('data files: %s' % data_files)
+
+ def get_outputs(self):
+ return self.outfiles
+
+
+install.sub_commands.append(('install_doc', None))
-man_path = os.path.join('doc', 'man', 'be.1')
-if os.path.exists(man_path):
- data_files.append(('share/man/man1', [man_path]))
setup(
name='Bugs Everywhere',
- version=rev_date,
+ version=version(),
+ maintainer='Chris Ball',
+ maintainer_email='be-devel@bugseverywhere.org',
description='Bugtracker supporting distributed revision control',
+ long_description=open(os.path.join(_this_dir, 'README'), 'r').read(),
url='http://bugseverywhere.org/',
+ license='GNU GPLv2',
packages=['libbe',
'libbe.command',
'libbe.storage',
'libbe.ui.util',
'libbe.util'],
scripts=['be'],
- data_files=data_files,
+ data_files=[],
+ cmdclass={'build_py': _build_py, 'build_doc': build_doc,
+ 'install_doc': install_doc},
)