changeset 684:a9157ac17ff9 0.6.x

0.6dev: Merging [758:759] from trunk.
author osimons
date Fri, 11 Sep 2009 21:32:25 +0000
parents 9d462b71e852
children 24c04502b29f
files ChangeLog MANIFEST-SLAVE.in MANIFEST.in README.txt bitten/__init__.py bitten/admin.py bitten/slave_tests/recipe.py bitten/tests/master.py bitten/upgrades.py bitten/util/tests/xmlio.py doc/commands.txt doc/install.txt doc/recipes.txt setup-slave.py setup.py
diffstat 15 files changed, 218 insertions(+), 216 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,12 @@
 (???, from 0.6.x branch)
 http://svn.edgewall.org/repos/bitten/tags/0.6
 
- * ???
+ * Slave-only install changed to `./setup.py --without-master install` (or any
+   other valid distribution command).
+ * Tools namespace changed to `http://bitten.edgewall.org/tools/`. Both new and
+   old namespace will work, but Admin will issue a deprecation notice when
+   using the old namespace.
+
 
 Version 0.6b1
 (10 September 2009, from 0.6.x branch)
--- a/MANIFEST-SLAVE.in
+++ b/MANIFEST-SLAVE.in
@@ -1,19 +1,23 @@
 prune bitten/htdocs
 prune bitten/templates
 prune doc
-prune scripts
+
+exclude MANIFEST.in
+include setup.py
+include ChangeLog
+include COPYING
+include MANIFEST-SLAVE.in
+include README.txt
+
 exclude bitten/*.py
-include bitten/build/tests/*.py
 exclude bitten/report/*.py
 exclude bitten/report/tests/*.py
 exclude bitten/tests/*.py
-include setup.py
-exclude MANIFEST.in
 include bitten/__init__.py
 include bitten/build/*.py
+include bitten/build/tests/*.py
 include bitten/recipe.py
 include bitten/slave.py
 include bitten/slave_tests/*.py
 include bitten/util/*.py
 include bitten/util/tests/*.py
-
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,15 @@
+include ChangeLog
+include COPYING
+include MANIFEST-SLAVE.in
+include README.txt
+include bitten/htdocs/*.*
+include bitten/htdocs/charts_library/*.swf
+include bitten/templates/*.*
+include doc/*.*
 include doc/api/*.*
-include doc/*.html
+include doc/common/*.html
+include doc/common/*.py
+include doc/common/*.txt
+include doc/common/COPYING
+include doc/common/conf/*.ini
+include doc/common/style/*.*
--- a/README.txt
+++ b/README.txt
@@ -43,6 +43,10 @@
 
   $ python setup.py test
 
+It is also possible to install only the build slave, installing only the
+parts of Bitten that are needed by clients to run builds:
+
+  $ python setup.py --without-master install
 
 What's left to do now depends on whether you want to use the build master and
 web interface, or just the build slave. In the latter case, you're already
--- a/bitten/__init__.py
+++ b/bitten/__init__.py
@@ -14,7 +14,7 @@
 except:
     try:
         __version__ = __import__('pkg_resources').get_distribution(
-                                                    'Bitten-Slave').version
+                                                    'BittenSlave').version
     except:
         pass
 
--- a/bitten/admin.py
+++ b/bitten/admin.py
@@ -160,6 +160,18 @@
                     for warning in warnings:
                         add_warning(req, warning)
 
+                # FIXME: Deprecation notice for old namespace.
+                # Remove notice code when migration to new namespace is complete
+                if 'http://bitten.cmlenz.net/tools/' in config.recipe:
+                    add_notice(req, "Recipe uses a deprecated namespace. "
+                        "Replace 'http://bitten.cmlenz.net/tools/' with "
+                        "'http://bitten.edgewall.org/tools/'.")
+
+                # Add a notice if configuration is not active
+                if not warnings and not config.active and config.recipe:
+                    add_notice(req, "Configuration is not active. Activate "
+                        "from main 'Configurations' listing to enable it.")
+
                 # Prepare template variables
                 data['config'] = {
                     'name': config.name, 'label': config.label or config.name,
--- a/bitten/slave_tests/recipe.py
+++ b/bitten/slave_tests/recipe.py
@@ -40,7 +40,7 @@
     def test_run_wrong_arg(self):
         ctxt = Context(self.basedir)
         try:
-            ctxt.run(1, 'http://bitten.cmlenz.net/tools/sh', 'exec', {'foo':'bar'})
+            ctxt.run(1, 'http://bitten.edgewall.org/tools/sh', 'exec', {'foo':'bar'})
             self.fail("InvalidRecipeError expected")
         except InvalidRecipeError, e:
             self.failUnless("Unsupported argument 'foo'" in str(e))
--- a/bitten/tests/master.py
+++ b/bitten/tests/master.py
@@ -410,7 +410,7 @@
         inbody = StringIO("""<result step="foo" status="success"
                                      time="2007-04-01T15:30:00.0000"
                                      duration="3.45">
-    <log generator="http://bitten.cmlenz.net/tools/python#unittest">
+    <log generator="http://bitten.edgewall.org/tools/python#unittest">
         <message level="info">Doing stuff</message>
         <message level="error">Ouch that hurt</message>
     </log>
@@ -449,7 +449,7 @@
 
         logs = list(BuildLog.select(self.env, build=build.id, step='foo'))
         self.assertEqual(1, len(logs))
-        self.assertEqual('http://bitten.cmlenz.net/tools/python#unittest',
+        self.assertEqual('http://bitten.edgewall.org/tools/python#unittest',
                          logs[0].generator)
         self.assertEqual(2, len(logs[0].messages))
         self.assertEqual((u'info', u'Doing stuff'), logs[0].messages[0])
@@ -471,7 +471,7 @@
                                      time="2007-04-01T15:30:00.0000"
                                      duration="3.45">
     <report category="test"
-            generator="http://bitten.cmlenz.net/tools/python#unittest">
+            generator="http://bitten.edgewall.org/tools/python#unittest">
         <test fixture="my.Fixture" file="my/test/file.py">
             <stdout>Doing my thing</stdout>
         </test>
@@ -512,7 +512,7 @@
         reports = list(Report.select(self.env, build=build.id, step='foo'))
         self.assertEqual(1, len(reports))
         self.assertEqual('test', reports[0].category)
-        self.assertEqual('http://bitten.cmlenz.net/tools/python#unittest',
+        self.assertEqual('http://bitten.edgewall.org/tools/python#unittest',
                          reports[0].generator)
         self.assertEqual(1, len(reports[0].items))
         self.assertEqual({
@@ -615,7 +615,7 @@
         inbody = StringIO("""<result step="foo" status="success"
                                      time="2007-04-01T15:30:00.0000"
                                      duration="3.45">
-    <log generator="http://bitten.cmlenz.net/tools/python#unittest">
+    <log generator="http://bitten.edgewall.org/tools/python#unittest">
         <message level="info">Doing stuff</message>
         <message level="error">Ouch that hurt</message>
     </log>
@@ -665,7 +665,7 @@
         inbody = StringIO("""<result step="foo" status="success"
                                      time="2007-04-01T15:30:00.0000"
                                      duration="3.45">
-    <log generator="http://bitten.cmlenz.net/tools/python#unittest">
+    <log generator="http://bitten.edgewall.org/tools/python#unittest">
         <message level="info">Doing stuff</message>
         <message level="error">Ouch that hurt</message>
     </log>
@@ -705,7 +705,7 @@
         inbody = StringIO("""<result step="foo2" status="success"
                                      time="2007-04-01T15:45:00.0000"
                                      duration="4">
-    <log generator="http://bitten.cmlenz.net/tools/python#unittest">
+    <log generator="http://bitten.edgewall.org/tools/python#unittest">
         <message level="info">This is a step after invalidation</message>
     </log>
 </result>""")
--- a/bitten/upgrades.py
+++ b/bitten/upgrades.py
@@ -245,10 +245,10 @@
     messages and report data."""
 
     mapping = {
-        'pipe': 'http://bitten.cmlenz.net/tools/sh#pipe',
-        'make': 'http://bitten.cmlenz.net/tools/c#make',
-        'distutils': 'http://bitten.cmlenz.net/tools/python#distutils',
-        'exec_': 'http://bitten.cmlenz.net/tools/python#exec' # Ambigious
+        'pipe': 'http://bitten.edgewall.org/tools/sh#pipe',
+        'make': 'http://bitten.edgewall.org/tools/c#make',
+        'distutils': 'http://bitten.edgewall.org/tools/python#distutils',
+        'exec_': 'http://bitten.edgewall.org/tools/python#exec' # Ambigious
     }
     cursor = db.cursor()
     cursor.execute("SELECT id,generator FROM bitten_log "
@@ -259,9 +259,9 @@
                        "WHERE id=%s", (mapping[generator], log_id))
 
     mapping = {
-        'unittest': 'http://bitten.cmlenz.net/tools/python#unittest',
-        'trace': 'http://bitten.cmlenz.net/tools/python#trace',
-        'pylint': 'http://bitten.cmlenz.net/tools/python#pylint'
+        'unittest': 'http://bitten.edgewall.org/tools/python#unittest',
+        'trace': 'http://bitten.edgewall.org/tools/python#trace',
+        'pylint': 'http://bitten.edgewall.org/tools/python#pylint'
     }
     cursor.execute("SELECT id,generator FROM bitten_report "
                    "WHERE generator IN (%s)"
--- a/bitten/util/tests/xmlio.py
+++ b/bitten/util/tests/xmlio.py
@@ -19,7 +19,7 @@
 
     def test_parse(self):
         """Tests that simple test data is parsed correctly"""
-        s = """<build xmlns:c="http://bitten.cmlenz.net/tools/c">
+        s = """<build xmlns:c="http://bitten.edgewall.org/tools/c">
                  <step id="build" description="Configure and build">
                    <c:configure />
                  </step>\
--- a/doc/commands.txt
+++ b/doc/commands.txt
@@ -80,7 +80,7 @@
 A bundle of generic tools that are not specific to any programming language or
 tool-chain.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/sh``
+:Namespace: ``http://bitten.edgewall.org/tools/sh``
 :Common prefix: ``sh``
 
 
@@ -152,7 +152,7 @@
 These commands provide support for tools commonly used for development of C/C++
 applications on Unix platforms, such as ``make``.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/c``
+:Namespace: ``http://bitten.edgewall.org/tools/c``
 :Common prefix: ``c``
 
 
@@ -165,30 +165,22 @@
 Parameters
 ----------
 
-    :param force: consider all files obsolete
-    :param install: copy missing auxiliary files
-    :param symlink: install symbolic links instead of copies
-    :param warnings: report the warnings falling in CATEGORY
-    :prepend_include: prepend directories to search path
-    :include: append directories to search path
-
-
-+--------------+-------------------------------------------------------------+
-| Name         | Description                                                 |
-+==============+=============================================================+
-| ``force``    | Consider all files obsolete                                 |
-+--------------+-------------------------------------------------------------+
-| ``install``  | Copy missing auxiliary files                                |
-+--------------+-------------------------------------------------------------+
-| ``symlink``  | Install symbolic links instead of copies                    |
-+--------------+-------------------------------------------------------------+
-| ``warnings`` | Report the warnings related to category                     |
-|              | (which can actually be a comma separated list)              |
-+--------------+-------------------------------------------------------------+
++----------------------+-----------------------------------------------------+
+| Name                 | Description                                         |
++======================+=====================================================+
+| ``force``            | Consider all files obsolete                         |
++----------------------+-----------------------------------------------------+
+| ``install``          | Copy missing auxiliary files                        |
++----------------------+-----------------------------------------------------+
+| ``symlink``          | Install symbolic links instead of copies            |
++----------------------+-----------------------------------------------------+
+| ``warnings``         | Report the warnings related to category             |
+|                      | (which can actually be a comma separated list)      |
++----------------------+-----------------------------------------------------+
 | ``prepend_include``  | Prepend directories to search path                  |
-+--------------+-------------------------------------------------------------+
-| ``include``   | Append directories to search path                          |
-+--------------+-------------------------------------------------------------+
++----------------------+-----------------------------------------------------+
+| ``include``          | Append directories to search path                   |
++----------------------+-----------------------------------------------------+
 
 Examples
 --------
@@ -368,7 +360,7 @@
 
 A bundle of recipe commands that support tools commonly used by Java projects.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/java``
+:Namespace: ``http://bitten.edgewall.org/tools/java``
 :Common prefix: ``java``
 
 
@@ -489,7 +481,7 @@
 
 A bundle of recipe commands that support tools commonly used by Mono/.NET projects.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/mono``
+:Namespace: ``http://bitten.edgewall.org/tools/mono``
 :Common prefix: ``mono``
 
 ----------------
@@ -526,7 +518,7 @@
 
 A bundle of recipe commands for PHP_ projects.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/php``
+:Namespace: ``http://bitten.edgewall.org/tools/php``
 :Common prefix: ``php``
 
 .. _php: http://php.net/
@@ -628,7 +620,7 @@
 A bundle of recipe commands that support tools commonly used by Python_
 projects.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/python``
+:Namespace: ``http://bitten.edgewall.org/tools/python``
 :Common prefix: ``python``
 
 .. _python: http://www.python.org/
@@ -874,7 +866,7 @@
 
 .. _subversion: http://subversion.tigris.org/
 
-:Namespace: ``http://bitten.cmlenz.net/tools/svn``
+:Namespace: ``http://bitten.edgewall.org/tools/svn``
 :Common prefix: ``svn``
 
 
@@ -1013,7 +1005,7 @@
 
 A collection of recipe commands for XML processing.
 
-:Namespace: ``http://bitten.cmlenz.net/tools/xml``
+:Namespace: ``http://bitten.edgewall.org/tools/xml``
 :Common prefix: ``x``
 
 
@@ -1064,7 +1056,7 @@
 .. _mercurial: http://mercurial.selenic.com/
 
 
-:Namespace: ``http://bitten.cmlenz.net/tools/hg``
+:Namespace: ``http://bitten.edgewall.org/tools/hg``
 :Common prefix: ``hg``
 
 
--- a/doc/install.txt
+++ b/doc/install.txt
@@ -39,8 +39,7 @@
 It is also possible to install only the build slave, installing only the
 parts of Bitten that are needed by clients to run builds::
 
-  $ python setup-slave.py install
-
+  $ python setup.py --without-master install
 
 What's left to do now depends on whether you want to use the build master and
 web interface, or just the build slave. In the latter case, you're already
--- a/doc/recipes.txt
+++ b/doc/recipes.txt
@@ -45,8 +45,8 @@
 
 .. code-block:: xml
 
-  <build xmlns:python="http://bitten.cmlenz.net/tools/python"
-         xmlns:svn="http://bitten.cmlenz.net/tools/svn">
+  <build xmlns:python="http://bitten.edgewall.org/tools/python"
+         xmlns:svn="http://bitten.edgewall.org/tools/svn">
   
     <step id="checkout" description="Checkout source from repository">
       <svn:checkout url="http://svn.example.org/repos/foo"
deleted file mode 100755
--- a/setup-slave.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007 Edgewall Software
-# Copyright (C) 2005-2007 Christopher Lenz <cmlenz@gmx.de>
-# Copyright (C) 2005-2007 David Fraser <davidf@sjsoft.com>
-# All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://bitten.edgewall.org/wiki/License.
-
-from setuptools import setup as setup_slave
-from setuptools.command import egg_info
-
-from setup import recipe_commands, shared_args
-
-# TODO: there must be a way to pass this altered value in...
-egg_info.manifest_maker.template = "MANIFEST-SLAVE.in"
-
-if __name__ == '__main__':
-    setup_slave(
-        name = 'Bitten-Slave',
-        description = 'Continuous integration build slave for Trac',
-        long_description = \
-    """A slave for running builds and submitting them to Bitten, the continuous integration system for Trac""",
-
-        py_modules = ["bitten.__init__",
-                      "bitten.build.__init__",
-                      "bitten.build.api",
-                      "bitten.build.config",
-                      "bitten.build.ctools",
-                      "bitten.build.hgtools",
-                      "bitten.build.javatools",
-                      "bitten.build.monotools",
-                      "bitten.build.phptools",
-                      "bitten.build.pythontools",
-                      "bitten.build.shtools",
-                      "bitten.build.svntools",
-                      "bitten.build.tests.__init__",
-                      "bitten.build.tests.api",
-                      "bitten.build.tests.config",
-                      "bitten.build.tests.ctools",
-                      "bitten.build.tests.dummy",
-                      "bitten.build.tests.hgtools",
-                      "bitten.build.tests.javatools",
-                      "bitten.build.tests.monotools",
-                      "bitten.build.tests.phptools",
-                      "bitten.build.tests.pythontools",
-                      "bitten.build.tests.xmltools",
-                      "bitten.build.xmltools",
-                      "bitten.recipe",
-                      "bitten.slave",
-                      "bitten.slave_tests.__init__",
-                      "bitten.slave_tests.recipe",
-                      "bitten.slave_tests.slave",
-                      "bitten.util.__init__",
-                      "bitten.util.loc",
-                      "bitten.util.testrunner",
-                      "bitten.util.xmlio",
-                    ],
-        test_suite = 'bitten.slave_tests.suite',
-        tests_require = [
-            'figleaf',
-        ],
-        entry_points = {
-            'console_scripts': [
-                'bitten-slave = bitten.slave:main',
-            ],
-            'distutils.commands': [
-                'unittest = bitten.util.testrunner:unittest',
-            ],
-            'bitten.recipe_commands': recipe_commands
-        },
-        
-        **shared_args
-    )
--- a/setup.py
+++ b/setup.py
@@ -10,8 +10,9 @@
 # are also available at http://bitten.edgewall.org/wiki/License.
 
 import os
-from setuptools import setup, find_packages
 import sys
+from setuptools import setup, find_packages, Feature
+from setuptools.command import egg_info
 
 sys.path.append(os.path.join('doc', 'common'))
 try:
@@ -25,85 +26,134 @@
 if hasattr(logging, 'logMultiprocessing'):
     logging.logMultiprocessing = 0
 
-NS = 'http://bitten.cmlenz.net/tools/'
-recipe_commands = [
-        NS + 'sh#exec = bitten.build.shtools:exec_',
-        NS + 'sh#pipe = bitten.build.shtools:pipe',
-        NS + 'c#configure = bitten.build.ctools:configure',
-        NS + 'c#autoreconf = bitten.build.ctools:autoreconf',
-        NS + 'c#cppunit = bitten.build.ctools:cppunit',
-        NS + 'c#cunit = bitten.build.ctools:cunit',
-        NS + 'c#gcov = bitten.build.ctools:gcov',
-        NS + 'c#make = bitten.build.ctools:make',
-        NS + 'mono#nunit = bitten.build.monotools:nunit',
-        NS + 'java#ant = bitten.build.javatools:ant',
-        NS + 'java#junit = bitten.build.javatools:junit',
-        NS + 'java#cobertura = bitten.build.javatools:cobertura',
-        NS + 'php#phing = bitten.build.phptools:phing',
-        NS + 'php#phpunit = bitten.build.phptools:phpunit',
-        NS + 'php#coverage = bitten.build.phptools:coverage',
-        NS + 'python#coverage = bitten.build.pythontools:coverage',
-        NS + 'python#distutils = bitten.build.pythontools:distutils',
-        NS + 'python#exec = bitten.build.pythontools:exec_',
-        NS + 'python#figleaf = bitten.build.pythontools:figleaf',
-        NS + 'python#pylint = bitten.build.pythontools:pylint',
-        NS + 'python#trace = bitten.build.pythontools:trace',
-        NS + 'python#unittest = bitten.build.pythontools:unittest',
-        NS + 'svn#checkout = bitten.build.svntools:checkout',
-        NS + 'svn#export = bitten.build.svntools:export',
-        NS + 'svn#update = bitten.build.svntools:update',
-        NS + 'hg#pull = bitten.build.hgtools:pull',
-        NS + 'xml#transform = bitten.build.xmltools:transform'
+NS_old = 'http://bitten.cmlenz.net/tools/'
+NS_new = 'http://bitten.edgewall.org/tools/'
+tools = [
+        'sh#exec = bitten.build.shtools:exec_',
+        'sh#pipe = bitten.build.shtools:pipe',
+        'c#configure = bitten.build.ctools:configure',
+        'c#autoreconf = bitten.build.ctools:autoreconf',
+        'c#cppunit = bitten.build.ctools:cppunit',
+        'c#cunit = bitten.build.ctools:cunit',
+        'c#gcov = bitten.build.ctools:gcov',
+        'c#make = bitten.build.ctools:make',
+        'mono#nunit = bitten.build.monotools:nunit',
+        'java#ant = bitten.build.javatools:ant',
+        'java#junit = bitten.build.javatools:junit',
+        'java#cobertura = bitten.build.javatools:cobertura',
+        'php#phing = bitten.build.phptools:phing',
+        'php#phpunit = bitten.build.phptools:phpunit',
+        'php#coverage = bitten.build.phptools:coverage',
+        'python#coverage = bitten.build.pythontools:coverage',
+        'python#distutils = bitten.build.pythontools:distutils',
+        'python#exec = bitten.build.pythontools:exec_',
+        'python#figleaf = bitten.build.pythontools:figleaf',
+        'python#pylint = bitten.build.pythontools:pylint',
+        'python#trace = bitten.build.pythontools:trace',
+        'python#unittest = bitten.build.pythontools:unittest',
+        'svn#checkout = bitten.build.svntools:checkout',
+        'svn#export = bitten.build.svntools:export',
+        'svn#update = bitten.build.svntools:update',
+        'hg#pull = bitten.build.hgtools:pull',
+        'xml#transform = bitten.build.xmltools:transform'
     ]
-shared_args = {
-        'version': '0.6',
-        'author': 'Edgewall Software',
-        'author_email': 'info@edgewall.org',
-        'license': 'BSD',
-        'url':'http://bitten.edgewall.org/',
-        'download_url': 'http://bitten.edgewall.org/wiki/Download',
-        'zip_safe': False
-    }
+recipe_commands = [NS_old + tool for tool in tools] \
+                  + [NS_new + tool for tool in tools]
 
-if __name__ == '__main__':
-    setup(
-        name = 'Bitten',
-        description = 'Continuous integration for Trac',
-        long_description = \
-    """A Trac plugin for collecting software metrics via continuous integration.""",
+class MasterFeature(Feature):
 
-        packages = find_packages(exclude=['*.tests*']),
-        package_data = {
-            'bitten': ['htdocs/*.*',
-                       'htdocs/charts_library/*.swf',
-                       'templates/*.html',
-                       'templates/*.txt']
-        },
-        test_suite = 'bitten.tests.suite',
-        tests_require = [
-            'figleaf',
+    def exclude_from(self, dist):
+        # Called when master is disabled (--without-master)
+        pass
+
+    def include_in(self, dist):
+        # Called when master is enabled (default, or --with-master)
+        dist.metadata.name = 'Bitten'
+        dist.metadata.description = 'Continuous integration for Trac',
+        dist.long_description = "A Trac plugin for collecting software " \
+                                "metrics via continuous integration."""
+        # Use full manifest when master is included
+        egg_info.manifest_maker.template = "MANIFEST.in"
+        # Include tests in source distribution
+        if 'sdist' in dist.commands:
+            dist.packages = find_packages()
+        else:
+            dist.packages = find_packages(exclude=['*tests*'])
+        dist.test_suite = 'bitten.tests.suite'
+        dist.package_data = {
+              'bitten': ['htdocs/*.*',
+                    'htdocs/charts_library/*.swf',
+                    'templates/*.html',
+                    'templates/*.txt']}
+        dist.entry_points['trac.plugins'] = [
+                    'bitten.admin = bitten.admin',
+                    'bitten.main = bitten.main',
+                    'bitten.master = bitten.master',
+                    'bitten.web_ui = bitten.web_ui',
+                    'bitten.testing = bitten.report.testing',
+                    'bitten.coverage = bitten.report.coverage',
+                    'bitten.lint = bitten.report.lint',
+                    'bitten.notify = bitten.notify']
+
+master = MasterFeature(
+    description = "Bitten Master Trac plugin",
+    standard = True,
+    py_modules = [])
+
+egg_info.manifest_maker.template = "MANIFEST-SLAVE.in"
+
+if os.path.exists(os.path.join(os.path.dirname(__file__), 'MANIFEST.in')):
+    available_features = {"master": master}
+else:
+    # Building from a slave distribution
+    available_features = {}
+
+setup(
+    name = 'BittenSlave',
+    version =  '0.7',
+    author = 'Edgewall Software',
+    author_email = 'info@edgewall.org',
+    license = 'BSD',
+    url = 'http://bitten.edgewall.org/',
+    download_url = 'http://bitten.edgewall.org/wiki/Download',
+    zip_safe = False,
+    description = 'Continuous integration build slave for Trac',
+    long_description = "A slave for running builds and submitting them to " \
+                       "Bitten, the continuous integration system for Trac",
+    packages = {},
+    py_modules = ["bitten.__init__",
+                  "bitten.build.__init__",
+                  "bitten.build.api",
+                  "bitten.build.config",
+                  "bitten.build.ctools",
+                  "bitten.build.hgtools",
+                  "bitten.build.javatools",
+                  "bitten.build.monotools",
+                  "bitten.build.phptools",
+                  "bitten.build.pythontools",
+                  "bitten.build.shtools",
+                  "bitten.build.svntools",
+                  "bitten.build.xmltools",
+                  "bitten.recipe",
+                  "bitten.slave",
+                  "bitten.util.__init__",
+                  "bitten.util.loc",
+                  "bitten.util.testrunner",
+                  "bitten.util.xmlio",
+                ],
+    test_suite = 'bitten.slave_tests.suite',
+    tests_require = [
+        'figleaf',
+    ],
+    entry_points = {
+        'console_scripts': [
+            'bitten-slave = bitten.slave:main'
         ],
-        entry_points = {
-            'console_scripts': [
-                'bitten-slave = bitten.slave:main'
-            ],
-            'distutils.commands': [
-                'unittest = bitten.util.testrunner:unittest'
-            ],
-            'trac.plugins': [
-                'bitten.admin = bitten.admin',
-                'bitten.main = bitten.main',
-                'bitten.master = bitten.master',
-                'bitten.web_ui = bitten.web_ui',
-                'bitten.testing = bitten.report.testing',
-                'bitten.coverage = bitten.report.coverage',
-                'bitten.lint = bitten.report.lint',
-                'bitten.notify = bitten.notify'
-            ],
-            'bitten.recipe_commands': recipe_commands
-        },
-
-        cmdclass = {'build_doc': build_doc, 'test_doc': test_doc},
-        
-        **shared_args
-    )
+        'distutils.commands': [
+            'unittest = bitten.util.testrunner:unittest'
+        ],
+        'bitten.recipe_commands': recipe_commands
+    },
+    features = available_features,
+    cmdclass = {'build_doc': build_doc, 'test_doc': test_doc}
+)
Copyright (C) 2012-2017 Edgewall Software