Imported Buildbot-0.8.2rc2 source upstream
authorDustin J. Mitchell <dustin@mozilla.com>
Thu, 28 Oct 2010 16:17:53 -0500
branchupstream
changeset 97 c2e02e5bbfdb1c7a463cb44d75b06d45070597d3
parent 79 5d373392f58dcce9060aa862f5e5018a5e9aff2c
child 98 d23e1cd7604b797cd845b2290e8b9db06909f1c5
child 99 27c8ebbbf2b5189bd47be6fa8504610d5d8d11d3
push id41
push userdmitchell@mozilla.com
push dateWed, 17 Nov 2010 14:22:22 +0000
Imported Buildbot-0.8.2rc2 source
.coveragerc
.gitignore
.mailmap
Makefile
apidocs/Makefile
apidocs/epyrun
apidocs/gen-reference
contrib/README.txt
contrib/arch_buildbot.py
contrib/bb_applet.py
contrib/bitbucket_buildbot.py
contrib/bk_buildbot.py
contrib/bzr_buildbot.py
contrib/coverage2text.py
contrib/css/sample1.css
contrib/css/sample2.css
contrib/darcs_buildbot.py
contrib/fakechange.py
contrib/fix_changes_pickle_encoding.py
contrib/generate_changelog.py
contrib/git_buildbot.py
contrib/github_buildbot.py
contrib/googlecode_atom.py
contrib/hg_buildbot.py
contrib/os-x/README
contrib/os-x/net.sourceforge.buildbot.master.plist
contrib/os-x/net.sourceforge.buildbot.slave.plist
contrib/run_maxq.py
contrib/svn_buildbot.py
contrib/svn_watcher.py
contrib/svnpoller.py
contrib/trac/README.md
contrib/trac/TODO.md
contrib/trac/bbwatcher/__init__.py
contrib/trac/bbwatcher/api.py
contrib/trac/bbwatcher/model.py
contrib/trac/bbwatcher/templates/bbw_allbuilders.html
contrib/trac/bbwatcher/templates/bbw_builder.html
contrib/trac/bbwatcher/templates/bbw_welcome.html
contrib/trac/bbwatcher/web_ui.py
contrib/trac/setup.py
contrib/viewcvspoll.py
contrib/webhook_status.py
contrib/windows/buildbot2.bat
contrib/windows/setup.py
docs/.gitignore
docs/Makefile
docs/PyCon-2003/Makefile
docs/PyCon-2003/bb-slides.py
docs/PyCon-2003/source/buildbot.lore
docs/PyCon-2003/source/overview.svg
docs/PyCon-2003/source/slave.svg
docs/PyCon-2003/source/template.tpl
docs/PyCon-2003/stylesheet.css
docs/PyCon-2003/waterfall.png
docs/buildbot.texinfo
docs/cfg-builders.texinfo
docs/cfg-buildfactories.texinfo
docs/cfg-buildslaves.texinfo
docs/cfg-buildsteps.texinfo
docs/cfg-changesources.texinfo
docs/cfg-global.texinfo
docs/cfg-interlocks.texinfo
docs/cfg-schedulers.texinfo
docs/cfg-statustargets.texinfo
docs/cmdline.texinfo
docs/concepts.texinfo
docs/configuration.texinfo
docs/developer.texinfo
docs/epyrun
docs/examples/hello.cfg
docs/examples/twisted_master.cfg
docs/gen-reference
docs/hexnut32.png
docs/hexnut48.png
docs/hexnut64.png
docs/images/.gitignore
docs/images/Makefile
docs/images/icon.blend
docs/images/master.ai
docs/images/master.png
docs/images/master.svg
docs/images/master.txt
docs/images/overview.ai
docs/images/overview.png
docs/images/overview.svg
docs/images/overview.txt
docs/images/slaves.ai
docs/images/slaves.png
docs/images/slaves.svg
docs/images/slaves.txt
docs/images/status.ai
docs/images/status.png
docs/images/status.svg
docs/images/status.txt
docs/installation.texinfo
docs/introduction.texinfo
docs/resources.texinfo
docs/version.py
master/MANIFEST.in
master/Makefile
master/NEWS
master/README
master/buildbot/__init__.py
master/buildbot/buildslave.py
master/buildbot/changes/changes.py
master/buildbot/changes/gitpoller.py
master/buildbot/changes/mail.py
master/buildbot/changes/manager.py
master/buildbot/changes/monotone.py
master/buildbot/changes/svnpoller.py
master/buildbot/clients/sendchange.py
master/buildbot/clients/tryclient.py
master/buildbot/db/connector.py
master/buildbot/db/dbspec.py
master/buildbot/db/schema/manager.py
master/buildbot/db/schema/tables.sql
master/buildbot/db/schema/v1.py
master/buildbot/db/schema/v2.py
master/buildbot/db/schema/v4.py
master/buildbot/db/schema/v5.py
master/buildbot/db/schema/v6.py
master/buildbot/ec2buildslave.py
master/buildbot/interfaces.py
master/buildbot/libvirtbuildslave.py
master/buildbot/locks.py
master/buildbot/master.py
master/buildbot/process/base.py
master/buildbot/process/builder.py
master/buildbot/process/buildstep.py
master/buildbot/process/properties.py
master/buildbot/process/subunitlogobserver.py
master/buildbot/schedulers/base.py
master/buildbot/schedulers/basic.py
master/buildbot/schedulers/filter.py
master/buildbot/schedulers/timed.py
master/buildbot/scripts/runner.py
master/buildbot/scripts/sample.cfg
master/buildbot/sourcestamp.py
master/buildbot/status/builder.py
master/buildbot/status/mail.py
master/buildbot/status/persistent_queue.py
master/buildbot/status/status_push.py
master/buildbot/status/tinderbox.py
master/buildbot/status/web/authz.py
master/buildbot/status/web/base.py
master/buildbot/status/web/baseweb.py
master/buildbot/status/web/build.py
master/buildbot/status/web/builder.py
master/buildbot/status/web/buildstatus.py
master/buildbot/status/web/change_hook.py
master/buildbot/status/web/console.py
master/buildbot/status/web/feeds.py
master/buildbot/status/web/files/default.css
master/buildbot/status/web/files/robots.txt
master/buildbot/status/web/grid.py
master/buildbot/status/web/hooks/__init__.py
master/buildbot/status/web/hooks/base.py
master/buildbot/status/web/hooks/github.py
master/buildbot/status/web/root.py
master/buildbot/status/web/slaves.py
master/buildbot/status/web/status_json.py
master/buildbot/status/web/step.py
master/buildbot/status/web/templates/build.html
master/buildbot/status/web/templates/builder.html
master/buildbot/status/web/templates/buildslave.html
master/buildbot/status/web/templates/buildslaves.html
master/buildbot/status/web/templates/buildstatus.html
master/buildbot/status/web/templates/change.html
master/buildbot/status/web/templates/console.html
master/buildbot/status/web/templates/forms.html
master/buildbot/status/web/templates/layout.html
master/buildbot/status/web/templates/testresult.html
master/buildbot/status/web/tests.py
master/buildbot/status/web/xmlrpc.py
master/buildbot/status/words.py
master/buildbot/steps/master.py
master/buildbot/steps/python_twisted.py
master/buildbot/steps/shell.py
master/buildbot/steps/source.py
master/buildbot/steps/subunit.py
master/buildbot/steps/transfer.py
master/buildbot/steps/vstudio.py
master/buildbot/test/fake/fakedb.py
master/buildbot/test/regressions/test_import_weird_changes.py
master/buildbot/test/regressions/test_sourcestamp_revision.py
master/buildbot/test/regressions/test_steps_shell_WarningCountingShellCommand.py
master/buildbot/test/unit/test_changes_mail_CVSMaildirSource.py
master/buildbot/test/unit/test_contrib_buildbot_cvs_mail.py
master/buildbot/test/unit/test_db_connector.py
master/buildbot/test/unit/test_db_dbspec.py
master/buildbot/test/unit/test_db_schema_master.py
master/buildbot/test/unit/test_gitpoller.py
master/buildbot/test/unit/test_master_cleanshutdown.py
master/buildbot/test/unit/test_oldpaths.py
master/buildbot/test/unit/test_process_base.py
master/buildbot/test/unit/test_process_buildstep.py
master/buildbot/test/unit/test_process_properties.py
master/buildbot/test/unit/test_schedulers_filter.py
master/buildbot/test/unit/test_schedulers_timed_Nightly.py
master/buildbot/test/unit/test_source_repourl.py
master/buildbot/test/unit/test_status_builder.py
master/buildbot/test/unit/test_status_mail_MailNotifier.py
master/buildbot/test/unit/test_status_web_change_hook.py
master/buildbot/test/unit/test_status_web_change_hooks_github.py
master/buildbot/test/unit/test_steps_transfer.py
master/buildbot/test/unit/test_util_loop.py
master/buildbot/test/util/threads.py
master/buildbot/test/util/web.py
master/buildbot/util/__init__.py
master/buildbot/util/collections.py
master/contrib/README.txt
master/contrib/bb_applet.py
master/contrib/bitbucket_buildbot.py
master/contrib/bk_buildbot.py
master/contrib/buildbot_cvs_mail.py
master/contrib/bzr_buildbot.py
master/contrib/coverage2text.py
master/contrib/css/sample1.css
master/contrib/css/sample2.css
master/contrib/darcs_buildbot.py
master/contrib/fakechange.py
master/contrib/fix_changes_pickle_encoding.py
master/contrib/generate_changelog.py
master/contrib/git_buildbot.py
master/contrib/github_buildbot.py
master/contrib/googlecode_atom.py
master/contrib/hg_buildbot.py
master/contrib/init-scripts/buildmaster.default
master/contrib/init-scripts/buildmaster.init.sh
master/contrib/libvirt/network.xml
master/contrib/libvirt/vmbuilder
master/contrib/os-x/README
master/contrib/os-x/net.sourceforge.buildbot.master.plist
master/contrib/post_build_request.py
master/contrib/run_maxq.py
master/contrib/svn_buildbot.py
master/contrib/svn_watcher.py
master/contrib/svnpoller.py
master/contrib/trac/README.md
master/contrib/trac/TODO.md
master/contrib/trac/bbwatcher/__init__.py
master/contrib/trac/bbwatcher/api.py
master/contrib/trac/bbwatcher/model.py
master/contrib/trac/bbwatcher/templates/bbw_allbuilders.html
master/contrib/trac/bbwatcher/templates/bbw_builder.html
master/contrib/trac/bbwatcher/templates/bbw_welcome.html
master/contrib/trac/bbwatcher/web_ui.py
master/contrib/trac/setup.py
master/contrib/viewcvspoll.py
master/contrib/webhook_status.py
master/contrib/windows/buildbot_service.py
master/docs/.gitignore
master/docs/Makefile
master/docs/PyCon-2003/Makefile
master/docs/PyCon-2003/bb-slides.py
master/docs/PyCon-2003/source/buildbot.lore
master/docs/PyCon-2003/source/overview.svg
master/docs/PyCon-2003/source/slave.svg
master/docs/PyCon-2003/source/template.tpl
master/docs/PyCon-2003/stylesheet.css
master/docs/PyCon-2003/waterfall.png
master/docs/buildbot.1
master/docs/buildbot.texinfo
master/docs/buildslave.1
master/docs/cfg-builders.texinfo
master/docs/cfg-buildfactories.texinfo
master/docs/cfg-buildslaves.texinfo
master/docs/cfg-buildsteps.texinfo
master/docs/cfg-changesources.texinfo
master/docs/cfg-global.texinfo
master/docs/cfg-interlocks.texinfo
master/docs/cfg-schedulers.texinfo
master/docs/cfg-statustargets.texinfo
master/docs/cmdline.texinfo
master/docs/concepts.texinfo
master/docs/configuration.texinfo
master/docs/developer.texinfo
master/docs/examples/hello.cfg
master/docs/examples/twisted_master.cfg
master/docs/hexnut32.png
master/docs/hexnut48.png
master/docs/hexnut64.png
master/docs/images/.gitignore
master/docs/images/Makefile
master/docs/images/icon.blend
master/docs/images/master.ai
master/docs/images/master.png
master/docs/images/master.svg
master/docs/images/master.txt
master/docs/images/overview.ai
master/docs/images/overview.png
master/docs/images/overview.svg
master/docs/images/overview.txt
master/docs/images/slaves.ai
master/docs/images/slaves.png
master/docs/images/slaves.svg
master/docs/images/slaves.txt
master/docs/images/status.ai
master/docs/images/status.png
master/docs/images/status.svg
master/docs/images/status.txt
master/docs/installation.texinfo
master/docs/introduction.texinfo
master/docs/resources.texinfo
master/docs/version.py
master/setup.py
slave/MANIFEST.in
slave/NEWS
slave/README
slave/buildslave/__init__.py
slave/buildslave/bot.py
slave/buildslave/commands/base.py
slave/buildslave/commands/bk.py
slave/buildslave/commands/bzr.py
slave/buildslave/commands/cvs.py
slave/buildslave/commands/darcs.py
slave/buildslave/commands/git.py
slave/buildslave/commands/hg.py
slave/buildslave/commands/p4.py
slave/buildslave/commands/registry.py
slave/buildslave/commands/shell.py
slave/buildslave/commands/svn.py
slave/buildslave/commands/transfer.py
slave/buildslave/commands/utils.py
slave/buildslave/commands/vcs.py
slave/buildslave/exceptions.py
slave/buildslave/pbutil.py
slave/buildslave/runprocess.py
slave/buildslave/scripts/runner.py
slave/buildslave/test/__init__.py
slave/buildslave/test/fake/__init__.py
slave/buildslave/test/fake/remote.py
slave/buildslave/test/fake/runprocess.py
slave/buildslave/test/fake/slavebuilder.py
slave/buildslave/test/unit/test_bot.py
slave/buildslave/test/unit/test_bot_BuildSlave.py
slave/buildslave/test/unit/test_commands_base.py
slave/buildslave/test/unit/test_commands_bk.py
slave/buildslave/test/unit/test_commands_bzr.py
slave/buildslave/test/unit/test_commands_cvs.py
slave/buildslave/test/unit/test_commands_darcs.py
slave/buildslave/test/unit/test_commands_git.py
slave/buildslave/test/unit/test_commands_hg.py
slave/buildslave/test/unit/test_commands_p4.py
slave/buildslave/test/unit/test_commands_registry.py
slave/buildslave/test/unit/test_commands_shell.py
slave/buildslave/test/unit/test_commands_svn.py
slave/buildslave/test/unit/test_commands_transfer.py
slave/buildslave/test/unit/test_commands_utils.py
slave/buildslave/test/unit/test_runprocess.py
slave/buildslave/test/unit/test_slave_commands_base.py
slave/buildslave/test/unit/test_slave_commands_utils.py
slave/buildslave/test/unit/test_util.py
slave/buildslave/test/util.py
slave/buildslave/test/util/__init__.py
slave/buildslave/test/util/command.py
slave/buildslave/test/util/misc.py
slave/buildslave/test/util/sourcecommand.py
slave/buildslave/util.py
slave/contrib/init-scripts/buildslave.default
slave/contrib/init-scripts/buildslave.init.sh
slave/contrib/os-x/README
slave/contrib/os-x/net.sourceforge.buildbot.slave.plist
slave/contrib/windows/buildbot_service.py
slave/setup.py
new file mode 100644
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,28 @@
+[report]
+# Regexes for lines to exclude from consideration
+exclude_lines =
+    # Have to re-enable the standard pragma
+    pragma: no cover
+
+    # Don't complain about missing debug-only code:
+    def __repr__
+    if self\.debug
+
+    # Don't complain if tests don't hit defensive assertion code:
+    raise AssertionError
+    raise NotImplementedError
+
+    # Don't complain if non-runnable code isn't run:
+    if 0:
+    if __name__ == .__main__.:
+    if runtime.platformType  == 'win32'
+
+include =
+    master/*
+    slave/*
+
+omit =
+    # omit all of our tests
+    */test/*
+    # templates cause coverage errors
+    */templates/*
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+# All files to globally ignore
+*.pyc
+*.pyo
+*$py.class
+*.swp
+*.patch
+*.orig
+*.rej
+*#
+*~
+MANIFEST
+_trial_temp*
+dist
+build
+.build
+*.egg-info
+master/docs/buildbot.html
+master/docs/buildbot.info
+master/docs/buildbot.info-1
+master/docs/buildbot.info-2
+master/docs/images/master.png
+master/docs/images/overview.png
+master/docs/images/slavebuilder.png
+master/docs/images/slaves.png
+master/docs/images/status.png
+.stgit-edit.txt
+.project
+.pydevproject
+.settings
+master/docs/buildbot
+master/docs/version.texinfo
+master/docs/docs.tgz
+master/docs/latest
+twisted/plugins/dropin.cache
+.coverage
+coverage-html
+apidocs/reference
+apidocs/reference.tgz
new file mode 100644
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,35 @@
+Brian Warner <warner@lothar.com>
+Brian Warner <warner@lothar.com> <warner>
+Brian Warner <warner@lothar.com> <warner@allmydata.com>
+Brian Warner <warner@lothar.com> <warner-buildbot@lothar.com>
+Dustin J. Mitchell <dustin@zmanda.com> <dustin@v.igoro.us>
+Dustin J. Mitchell <dustin@zmanda.com>
+Marcus Lindblom <macke@yar.nu>
+Marc-Antoine Ruel <maruel@chromium.org>
+Steve "Ashcrow" Milner <smilner@redhat.com> <smilner+buildbot@redhat.com>
+Daniel Dunbar <daniel@zuster.org> <ddunbar@smooshlab.apple.com>
+Ian Zimmerman <itz@dell-itz.office.sproutsys.com> <itz@sproutsys.com> 
+Joshua Kugler <jkugler@hosanna.kugler.localdomain> <joshua@eeinternet.com>
+Zooko Wilcox-O'Hearn <zooko@zooko.com>
+Randall Bosetti <rbosetti+gh@gmail.com> <randall@alyosha.(none)>
+Randall Bosetti <rbosetti+gh@gmail.com>
+Stefan Seefeld <seefeld@sympatico.ca>
+Stefan Seefeld <seefeld@sympatico.ca> <stefan@quasimodo.(none)>
+Ben Hearsum <bhearsum@mozilla.com> <bhearsum@bitters-2.local>
+Ben Hearsum <bhearsum@mozilla.com> <bhearsum@voot.(none)>
+Daniel Dunbar <daniel@zuster.org> <ddunbar@lordcrumb.apple.com>
+Douglas Hubler <dhubler@bigbird.(none)> <dhubler@localhost.(none)>
+Gary Poster <gary@imposter.home> <gary@gary-ubuntu.(none)>
+Gary Poster <gary@imposter.home> <gary@imposter.local>
+Geraud Boyer <geraud@gbox.local> <geraud@sparkle.(none)>
+Kristian Nielsen <knmeister@gmail.com> <knielsen@knielsen-hq.org>
+Nicolas Sylvain <nsylvain@chromium.org> <nsylvain@google.com>
+John O'Duinn <john@oduinn.com>
+Quentin Raynaud <buildbot@undoso.eu> <quentin@LAYLA.KUBUNTU>
+Rene Müller <rene.mueller@tracetronic.de>
+Rene Müller <rene.mueller@tracetronic.de> <rene@spiwi.tracetronic.de> 
+Neil Hemingway <neil.hemingway@googlemail.com>
+Neil Hemingway <neil.hemingway@googlemail.com> <neil.hemingway@greyhavens.org.uk>
+Michael MacDonald <mjmac@pobox.com>
+Michael MacDonald <mjmac@pobox.com> <mjmac@vpn-129-150-66-84.east.sun.com>
+A. T. Hofkamp <a.t.hofkamp@tue.nl>
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,16 @@
 # developer utilities
 
-.PHONY: docs apidocs some-apidocs paper
+.PHONY: docs apidocs pylint
+
 docs:
-	$(MAKE) -C docs
+	$(MAKE) -C master/docs
 
-reference:
-	cd docs; ./gen-reference
+apidocs:
+	$(MAKE) -C apidocs
 
 pylint:
 	cd master; $(MAKE) pylint
 	cd slave; $(MAKE) pylint
+
+pyflakes:
+	cd master; $(MAKE) pyflakes
new file mode 100644
--- /dev/null
+++ b/apidocs/Makefile
@@ -0,0 +1,15 @@
+.PHONY: all reference cleanpyc
+
+all: reference.tgz
+
+cleanpyc:
+	cd .. && find master slave -name '*.pyc' -exec rm \{} \; || exit 1
+
+reference: cleanpyc
+	rm -rf reference
+	cd .. && python apidocs/epyrun -o apidocs/reference \
+			--exclude="buildbot\\.test" --exclude="buildslave\\.test" \
+			buildbot buildslave
+
+reference.tgz: reference
+	tar -zcf reference.tgz reference
new file mode 100644
--- /dev/null
+++ b/apidocs/epyrun
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+import sys
+import os
+
+from twisted.python import reflect
+from twisted.internet import reactor
+
+# epydoc
+import epydoc
+from epydoc.cli import cli
+
+if epydoc.__version__[0] == '2':
+    # Fix support for epydoc 2.x. Unneeded for 3.x
+    class FakeModule:
+        def __init__(self, name, level):
+            self.__level = level
+            self.__name__ = name
+
+        def __repr__(self):
+            return '<Fake %s>' % self.__name__
+        __str__ = __repr__
+
+        def __nonzero__(self):
+            return 1
+
+        def __call__(self, *args, **kw):
+            pass #print 'Called:', args
+
+        def __getattr__(self, attr):
+            if self.__level == 0:
+                raise AttributeError
+            return FakeModule(self.__name__+'.'+attr, self.__level-1)
+
+        def __cmp__(self, other):
+            if not hasattr(other, '___name__'):
+                return -1
+            return cmp(self.__name__, other.__name__)
+
+
+    def fakeOut(modname):
+        modpath = modname.split('.')
+        prevmod = None
+        for m in range(len(modpath)):
+            mp = '.'.join(modpath[:m+1])
+            nm = FakeModule(mp, 4)
+            if prevmod:
+                setattr(prevmod, modpath[m], nm)
+            sys.modules[mp] = nm
+            prevmod = nm
+
+    #fakeOut("twisted")
+
+    # HACK: Another "only doc what we tell you". We don't want epydoc to
+    # automatically recurse into subdirectories: "twisted"'s presence was
+    # causing "twisted/test" to be docced, even thought we explicitly
+    # didn't put any twisted/test in our modnames.
+
+    from epydoc import imports
+    orig_find_modules = imports.find_modules
+
+    import re
+
+    def find_modules(dirname):
+        if not os.path.isdir(dirname): return []
+        found_init = 0
+        modules = {}
+        dirs = []
+
+        # Search for directories & modules, and check for __init__.py.
+        # Don't include duplicates (like foo.py and foo.pyc), and give
+        # precedance to the .py files.
+        for file in os.listdir(dirname):
+            filepath = os.path.join(dirname, file)
+            if os.path.isdir(filepath): dirs.append(filepath)
+            elif not re.match(r'\w+.py.?', file):
+                continue # Ignore things like ".#foo.py" or "a-b.py"
+            elif file[-3:] == '.py':
+                modules[file] = os.path.join(dirname, file)
+                if file == '__init__.py': found_init = 1
+            elif file[-4:-1] == '.py':
+                modules.setdefault(file[:-1], file)
+                if file[:-1] == '__init__.py': found_init = 1
+        modules = modules.values()
+
+        # If there was no __init__.py, then this isn't a package
+        # directory; return nothing.
+        if not found_init: return []
+
+        # Recurse to the child directories.
+        # **twisted** here's the change: commented next line out
+        #for d in dirs: modules += find_modules(d)
+        return modules
+
+    imports.find_modules = find_modules
+
+
+# Now, set up the list of modules for epydoc to document
+modnames = []
+def addMod(arg, path, files):
+    for fn in files:
+        file = os.path.join(path, fn).replace('%s__init__'%os.sep, '')
+        if file.count('%stest%s' % (os.sep,os.sep)): continue
+        if file.count('%sbroken_test%s' % (os.sep,os.sep)): continue
+        if file[-3:] == '.py':
+            modName = file[:-3].replace(os.sep,'.')
+            try:
+                #print 'pre-loading', modName
+                reflect.namedModule(modName)
+            except ImportError, e:
+                print 'import error:', modName, e
+            except Exception, e:
+                print 'other error:', modName, e
+            else:
+                modnames.append(modName)
+
+def main():
+    document_all = True # are we doing a full build?
+    names = ['buildbot/'] #default, may be overriden below
+
+    #get list of modules/pkgs on cmd-line
+    try:
+        i = sys.argv.index("--modules")
+    except:
+        pass
+    else:
+        names = sys.argv[i+1:]
+        document_all = False
+        sys.argv[i:] = []
+        #sanity check on names
+        for i in range(len(names)):
+            try:
+                j = names[i].rindex('buildbot/')
+            except:
+                raise SystemExit, 'You can only specify buildbot modules or packages'
+            else:
+                #strip off any leading directories before the 'twisted/'
+                #dir. this makes it easy to specify full paths, such as
+                #from TwistedEmacs
+                names[i] = names[i][j:]
+
+        old_out_dir = "html"
+        #if -o was specified, we need to change it to point to a tmp dir
+        #otherwise add our own -o option
+        try:
+            i = sys.argv.index('-o')
+            old_out_dir = sys.argv[i+1]
+            try:
+                os.mkdir(tmp_dir)
+            except OSError:
+                pass
+            sys.argv[i+1] = tmp_dir
+        except ValueError:
+            sys.argv[1:1] = ['-o', tmp_dir]
+
+    osrv = sys.argv
+    sys.argv=["IGNORE"]
+
+    for name in names:
+        if name.endswith(".py"):
+            # turn it in to a python module name
+            name = name[:-3].replace(os.sep, ".")
+            try:
+                reflect.namedModule(name)
+            except ImportError:
+                print 'import error:', name
+            except:
+                print 'other error:', name
+            else:
+                modnames.append(name)
+        else: #assume it's a dir
+            os.path.walk(name, addMod, None)
+
+    sys.argv = osrv
+
+    if 'buildbot.test' in modnames:
+        modnames.remove('buildbot.test')
+    if 'buildbot.broken_test' in modnames:
+        modnames.remove('buildbot.broken_test')
+    ##if 'twisted' in modnames:
+    ##    modnames.remove('twisted')
+
+    sys.argv.extend(modnames)
+
+    import buildbot
+
+    sys.argv[1:1] = [
+        '-n', 'BuildBot %s' % buildbot.version,
+        '-u', 'http://buildbot.net/trac', '--no-private']
+
+    # Make it easy to profile epyrun
+    if 0:
+        import profile
+        profile.run('cli()', 'epyrun.prof')
+    else:
+        cli()
+
+    print 'Done!'
+
+
+if __name__ == '__main__':
+    main()
new file mode 100755
--- /dev/null
+++ b/apidocs/gen-reference
@@ -0,0 +1,7 @@
+#!/bin/bash
+echo $(dirname $0)
+cd $(dirname $0)
+cd ..
+find master slave -name '*.pyc' -exec rm \{} \; || exit 1
+# excludes both test suites
+python docs/epyrun -o docs/reference --exclude="buildbot\\.test" --exclude="buildslave\\.test" buildbot buildslave
deleted file mode 100644
--- a/contrib/README.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-Utility scripts, things contributed by users but not strictly a part of
-buildbot:
-
-fakechange.py: connect to a running bb and submit a fake change to trigger
-               builders
-
-generate_changelog.py: generated changelog entry using git. Requires git to
-                       be installed.
-
-run_maxq.py: a builder-helper for running maxq under buildbot
-
-svn_buildbot.py: a script intended to be run from a subversion hook-script
-                 which submits changes to svn (requires python 2.3)
-
-svnpoller.py: this script is intended to be run from a cronjob, and uses 'svn
-              log' to poll a (possibly remote) SVN repository for changes.
-              For each change it finds, it runs 'buildbot sendchange' to
-              deliver them to a waiting PBChangeSource on a (possibly remote)
-              buildmaster. Modify the svnurl to point at your own SVN
-              repository, and of course the user running the script must have
-              read permissions to that repository. It keeps track of the last
-              revision in a file, change 'fname' to set the location of this
-              state file. Modify the --master argument to the 'buildbot
-              sendchange' command to point at your buildmaster. Contributed
-              by John Pye. Note that if there are multiple changes within a
-              single polling interval, this will miss all but the last one.
-
-svn_watcher.py: adapted from svnpoller.py by Niklaus Giger to add options and
-                run under windows. Runs as a standalone script (it loops
-                internally rather than expecting to run from a cronjob),
-                polls an SVN repository every 10 minutes. It expects the
-                svnurl and buildmaster location as command-line arguments.
-
-viewcvspoll.py: a standalone script which loops every 60 seconds and polls a
-                (local?) MySQL database (presumably maintained by ViewCVS?)
-                for information about new CVS changes, then delivers them
-                over PB to a remote buildmaster's PBChangeSource. Contributed
-                by Stephen Kennedy.
-
-css/*.css: alternative HTML stylesheets to make the Waterfall display look
-           prettier. Copy them somewhere, then pass the filename to the
-           css= argument of the Waterfall() constructor.
deleted file mode 100755
--- a/contrib/arch_buildbot.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#! /usr/bin/python
-
-# this script is meant to run as an Arch post-commit hook (and also as a
-# pre-commit hook), using the "arch-meta-hook" framework. See
-# http://wiki.gnuarch.org/NdimMetaHook for details. The pre-commit hook
-# creates a list of files (and log comments), while the post-commit hook
-# actually notifies the buildmaster.
-
-# this script doesn't handle partial commits quite right: it will tell the
-# buildmaster that everything changed, not just the filenames you give to
-# 'tla commit'.
-
-import os
-import commands
-import cStringIO
-
-from buildbot.scripts import runner
-
-# Just modify the appropriate values below and then put this file in two
-# places: ~/.arch-params/hooks/ARCHIVE/=precommit/90buildbot.py and
-# ~/.arch-params/hooks/ARCHIVE/=commit/10buildbot.py
-
-master = "localhost:9989"
-username = "myloginname"
-
-# Remember that for this to work, your buildmaster's master.cfg needs to have
-# a c['change_source'] list which includes a pb.PBChangeSource instance.
-
-os.chdir(os.getenv("ARCH_TREE_ROOT"))
-filelist = ",,bb-files"
-commentfile = ",,bb-comments"
-
-if os.getenv("ARCH_HOOK_ACTION") == "precommit":
-    files = []
-    out = commands.getoutput("tla changes")
-    for line in cStringIO.StringIO(out).readlines():
-        if line[0] in "AMD": # add, modify, delete
-            files.append(line[3:])
-    if files:
-        f = open(filelist, "w")
-        f.write("".join(files))
-        f.close()
-    # comments
-    logfiles = [f for f in os.listdir(".") if f.startswith("++log.")]
-    if len(logfiles) > 1:
-        print ("Warning, multiple ++log.* files found, getting comments "
-               "from the first one")
-    if logfiles:
-        open(commentfile, "w").write(open(logfiles[0], "r").read())
-
-elif os.getenv("ARCH_HOOK_ACTION") == "commit":
-    revision = os.getenv("ARCH_REVISION")
-
-    files = []
-    if os.path.exists(filelist):
-        f = open(filelist, "r")
-        for line in f.readlines():
-            files.append(line.rstrip())
-    if not files:
-        # buildbot insists upon having at least one modified file (otherwise
-        # the prefix-stripping mechanism will ignore the change)
-        files = ["dummy"]
-
-    if os.path.exists(commentfile):
-        comments = open(commentfile, "r").read()
-    else:
-        comments = "commit from arch"
-
-    c = {'master': master, 'username': username,
-         'revision': revision, 'comments': comments, 'files': files}
-    runner.sendchange(c, True)
-
-    if os.path.exists(filelist):
-        os.unlink(filelist)
-    if os.path.exists(commentfile):
-        os.unlink(commentfile)
deleted file mode 100755
--- a/contrib/bb_applet.py
+++ /dev/null
@@ -1,413 +0,0 @@
-#! /usr/bin/python
-
-# This is a Gnome-2 panel applet that uses the
-# buildbot.status.client.PBListener interface to display a terse summary of
-# the buildmaster. It displays one column per builder, with a box on top for
-# the status of the most recent build (red, green, or orange), and a somewhat
-# smaller box on the bottom for the current state of the builder (white for
-# idle, yellow for building, red for offline). There are tooltips available
-# to tell you which box is which.
-
-# Edit the line at the beginning of the MyApplet class to fill in the host
-# and portnumber of your buildmaster's PBListener status port. Eventually
-# this will move into a preferences dialog, but first we must create a
-# preferences dialog.
-
-# See the notes at the end for installation hints and support files (you
-# cannot simply run this script from the shell). You must create a bonobo
-# .server file that points to this script, and put the .server file somewhere
-# that bonobo will look for it. Only then will this applet appear in the
-# panel's "Add Applet" menu.
-
-# Note: These applets are run in an environment that throws away stdout and
-# stderr. Any logging must be done with syslog or explicitly to a file.
-# Exceptions are particularly annoying in such an environment.
-
-#   -Brian Warner, warner@lothar.com
-
-if 0:
-    import sys
-    dpipe = open("/tmp/applet.log", "a", 1)
-    sys.stdout = dpipe
-    sys.stderr = dpipe
-    print "starting"
-
-from twisted.internet import gtk2reactor
-gtk2reactor.install() #@UndefinedVariable
-
-import gtk #@UnresolvedImport
-import gnomeapplet #@UnresolvedImport
-
-# preferences are not yet implemented
-MENU = """
-<popup name="button3">
- <menuitem name="Connect" verb="Connect" label="Connect"
-           pixtype="stock" pixname="gtk-refresh"/>
- <menuitem name="Disconnect" verb="Disconnect" label="Disconnect"
-           pixtype="stock" pixname="gtk-stop"/>
- <menuitem name="Prefs" verb="Props" label="_Preferences..."
-           pixtype="stock" pixname="gtk-properties"/>
-</popup>
-"""
-
-from twisted.spread import pb
-from twisted.cred import credentials
-
-# sigh, these constants should cross the wire as strings, not integers
-SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION = range(5)
-Results = ["success", "warnings", "failure", "skipped", "exception"]
-
-
-class Box:
-
-    def __init__(self, buildername, hbox, tips, size, hslice):
-        self.buildername = buildername
-        self.hbox = hbox
-        self.tips = tips
-        self.state = "idle"
-        self.eta = None
-        self.last_results = None
-        self.last_text = None
-        self.size = size
-        self.hslice = hslice
-
-    def create(self):
-        self.vbox = gtk.VBox(False)
-        l = gtk.Label(".")
-        self.current_box = box = gtk.EventBox()
-        # these size requests are somewhat non-deterministic. I think it
-        # depends upon how large label is, or how much space was already
-        # consumed when the box is added.
-        self.current_box.set_size_request(self.hslice, self.size * 0.75)
-        box.add(l)
-        self.vbox.pack_end(box)
-        self.current_box.modify_bg(gtk.STATE_NORMAL,
-                                   gtk.gdk.color_parse("gray50"))
-
-        l2 = gtk.Label(".")
-        self.last_box = gtk.EventBox()
-        self.current_box.set_size_request(self.hslice, self.size * 0.25)
-        self.last_box.add(l2)
-        self.vbox.pack_end(self.last_box, True, True)
-        self.vbox.show_all()
-        self.hbox.pack_start(self.vbox, True, True)
-
-    def remove(self):
-        self.hbox.remove(self.box)
-
-    def set_state(self, state):
-        self.state = state
-        self.update()
-
-    def set_eta(self, eta):
-        self.eta = eta
-        self.update()
-
-    def set_last_build_results(self, results):
-        self.last_results = results
-        self.update()
-
-    def set_last_build_text(self, text):
-        self.last_text = text
-        self.update()
-
-    def update(self):
-        currentmap = {"offline": "red",
-                      "idle": "white",
-                      "waiting": "yellow",
-                      "interlocked": "yellow",
-                      "building": "yellow",
-        }
-        color = currentmap[self.state]
-        self.current_box.modify_bg(gtk.STATE_NORMAL,
-                                   gtk.gdk.color_parse(color))
-        lastmap = {None: "gray50",
-                   SUCCESS: "green",
-                   WARNINGS: "orange",
-                   FAILURE: "red",
-                   EXCEPTION: "purple",
-                   }
-        last_color = lastmap[self.last_results]
-        self.last_box.modify_bg(gtk.STATE_NORMAL,
-                                gtk.gdk.color_parse(last_color))
-        current_tip = "%s:\n%s" % (self.buildername, self.state)
-        if self.eta is not None:
-            current_tip += " (ETA=%ds)" % self.eta
-        self.tips.set_tip(self.current_box, current_tip)
-        last_tip = "%s:\n" % self.buildername
-        if self.last_text:
-            last_tip += "\n".join(self.last_text)
-        else:
-            last_tip += "no builds"
-        self.tips.set_tip(self.last_box, last_tip)
-
-
-class MyApplet(pb.Referenceable):
-    # CHANGE THIS TO POINT TO YOUR BUILDMASTER
-    buildmaster = "buildmaster.example.org", 12345
-    filled = None
-
-    def __init__(self, container):
-        self.applet = container
-        self.size = container.get_size()
-        self.hslice = self.size / 4
-        container.set_size_request(self.size, self.size)
-        self.fill_nut()
-        verbs = [("Props", self.menu_preferences),
-                 ("Connect", self.menu_connect),
-                 ("Disconnect", self.menu_disconnect),
-        ]
-        container.setup_menu(MENU, verbs)
-        self.boxes = {}
-        self.connect()
-
-    def fill(self, what):
-        if self.filled:
-            self.applet.remove(self.filled)
-            self.filled = None
-        self.applet.add(what)
-        self.filled = what
-        self.applet.show_all()
-
-    def fill_nut(self):
-        i = gtk.Image()
-        i.set_from_file("/tmp/nut32.png")
-        self.fill(i)
-
-    def fill_hbox(self):
-        self.hbox = gtk.HBox(True)
-        self.fill(self.hbox)
-
-    def connect(self):
-        host, port = self.buildmaster
-        cf = pb.PBClientFactory()
-        creds = credentials.UsernamePassword("statusClient", "clientpw")
-        d = cf.login(creds)
-        reactor.connectTCP(host, port, cf)
-        d.addCallback(self.connected)
-        return d
-
-    def connected(self, ref):
-        print "connected"
-        ref.notifyOnDisconnect(self.disconnected)
-        self.remote = ref
-        self.remote.callRemote("subscribe", "steps", 5, self)
-        self.fill_hbox()
-        self.tips = gtk.Tooltips()
-        self.tips.enable()
-
-    def disconnect(self):
-        self.remote.broker.transport.loseConnection()
-
-    def disconnected(self, *args):
-        print "disconnected"
-        self.fill_nut()
-
-    def remote_builderAdded(self, buildername, builder):
-        print "builderAdded", buildername
-        box = Box(buildername, self.hbox, self.tips, self.size, self.hslice)
-        self.boxes[buildername] = box
-        box.create()
-        self.applet.set_size_request(self.hslice * len(self.boxes),
-                                     self.size)
-        d = builder.callRemote("getLastFinishedBuild")
-
-        def _got(build):
-            if build:
-                d1 = build.callRemote("getResults")
-                d1.addCallback(box.set_last_build_results)
-                d2 = build.callRemote("getText")
-                d2.addCallback(box.set_last_build_text)
-        d.addCallback(_got)
-
-    def remote_builderRemoved(self, buildername):
-        self.boxes[buildername].remove()
-        del self.boxes[buildername]
-        self.applet.set_size_request(self.hslice * len(self.boxes),
-                                     self.size)
-
-    def remote_builderChangedState(self, buildername, state, eta):
-        self.boxes[buildername].set_state(state)
-        self.boxes[buildername].set_eta(eta)
-        print "change", buildername, state, eta
-
-    def remote_buildStarted(self, buildername, build):
-        print "buildStarted", buildername
-
-    def remote_buildFinished(self, buildername, build, results):
-        print "buildFinished", results
-        box = self.boxes[buildername]
-        box.set_eta(None)
-        d1 = build.callRemote("getResults")
-        d1.addCallback(box.set_last_build_results)
-        d2 = build.callRemote("getText")
-        d2.addCallback(box.set_last_build_text)
-
-    def remote_buildETAUpdate(self, buildername, build, eta):
-        self.boxes[buildername].set_eta(eta)
-        print "ETA", buildername, eta
-
-    def remote_stepStarted(self, buildername, build, stepname, step):
-        print "stepStarted", buildername, stepname
-
-    def remote_stepFinished(self, buildername, build, stepname, step, results):
-        pass
-
-    def menu_preferences(self, event, data=None):
-        print "prefs!"
-        p = Prefs(self)
-        p.create()
-
-    def set_buildmaster(self, buildmaster):
-        host, port = buildmaster.split(":")
-        self.buildmaster = host, int(port)
-        self.disconnect()
-        reactor.callLater(0.5, self.connect)
-
-    def menu_connect(self, event, data=None):
-        self.connect()
-
-    def menu_disconnect(self, event, data=None):
-        self.disconnect()
-
-
-class Prefs:
-
-    def __init__(self, parent):
-        self.parent = parent
-
-    def create(self):
-        self.w = w = gtk.Window()
-        v = gtk.VBox()
-        h = gtk.HBox()
-        h.pack_start(gtk.Label("buildmaster (host:port) : "))
-        self.buildmaster_entry = b = gtk.Entry()
-        if self.parent.buildmaster:
-            host, port = self.parent.buildmaster
-            b.set_text("%s:%d" % (host, port))
-        h.pack_start(b)
-        v.add(h)
-
-        b = gtk.Button("Ok")
-        b.connect("clicked", self.done)
-        v.add(b)
-
-        w.add(v)
-        w.show_all()
-
-    def done(self, widget):
-        buildmaster = self.buildmaster_entry.get_text()
-        self.parent.set_buildmaster(buildmaster)
-        self.w.unmap()
-
-
-def factory(applet, iid):
-    MyApplet(applet)
-    applet.show_all()
-    return True
-
-
-from twisted.internet import reactor
-
-# instead of reactor.run(), we do the following:
-reactor.startRunning()
-reactor.simulate()
-gnomeapplet.bonobo_factory("OAFIID:GNOME_Buildbot_Factory",
-                           gnomeapplet.Applet.__gtype__,
-                           "buildbot", "0", factory)
-
-# code ends here: bonobo_factory runs gtk.mainloop() internally and
-# doesn't return until the program ends
-
-# SUPPORTING FILES:
-
-# save the following as ~/lib/bonobo/servers/bb_applet.server, and update all
-# the pathnames to match your system
-bb_applet_server = """
-<oaf_info>
-
-<oaf_server iid="OAFIID:GNOME_Buildbot_Factory"
-            type="exe"
-            location="/home/warner/stuff/buildbot-trunk/contrib/bb_applet.py">
-
-        <oaf_attribute name="repo_ids" type="stringv">
-            <item value="IDL:Bonobo/GenericFactory:1.0"/>
-            <item value="IDL:Bonobo/Unknown:1.0"/>
-        </oaf_attribute>
-        <oaf_attribute name="name" type="string" value="Buildbot Factory"/>
-        <oaf_attribute name="description" type="string" value="Test"/>
-</oaf_server>
-
-<oaf_server iid="OAFIID:GNOME_Buildbot"
-            type="factory"
-            location="OAFIID:GNOME_Buildbot_Factory">
-
-        <oaf_attribute name="repo_ids" type="stringv">
-                <item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
-                <item value="IDL:Bonobo/Control:1.0"/>
-                <item value="IDL:Bonobo/Unknown:1.0"/>
-        </oaf_attribute>
-        <oaf_attribute name="name" type="string" value="Buildbot"/>
-        <oaf_attribute name="description" type="string"
-          value="Watch Buildbot status"
-        />
-        <oaf_attribute name="panel:category" type="string" value="Utility"/>
-        <oaf_attribute name="panel:icon" type="string"
- value="/home/warner/stuff/buildbot-trunk/doc/hexnut32.png"
- />
-
-</oaf_server>
-
-</oaf_info>
-"""
-
-# a quick rundown on the Gnome2 applet scheme (probably wrong: there are
-# better docs out there that you should be following instead)
-#  http://www.pycage.de/howto_bonobo.html describes a lot of
-#   the base Bonobo stuff.
-#  http://www.daa.com.au/pipermail/pygtk/2002-September/003393.html
-
-# bb_applet.server must be in your $BONOBO_ACTIVATION_PATH . I use
-# ~/lib/bonobo/servers . This environment variable is read by
-# bonobo-activation-server, so it must be set before you start any Gnome
-# stuff. I set it in ~/.bash_profile . You can also put it in
-# /usr/lib/bonobo/servers/ , which is probably on the default
-# $BONOBO_ACTIVATION_PATH, so you won't have to update anything.
-
-# It is safest to put this in place before bonobo-activation-server is
-# started, which may mean before any Gnome program is running. It may or may
-# not detect bb_applet.server if it is installed afterwards.. there seem to
-# be hooks, some of which involve FAM, but I never managed to make them work.
-# The file must have a name that ends in .server or it will be ignored.
-
-# The .server file registers two OAF ids and tells the activation-server how
-# to create those objects. The first is the GNOME_Buildbot_Factory, and is
-# created by running the bb_applet.py script. The second is the
-# GNOME_Buildbot applet itself, and is created by asking the
-# GNOME_Buildbot_Factory to make it.
-
-# gnome-panel's "Add To Panel" menu will gather all the OAF ids that claim
-# to implement the "IDL:GNOME/Vertigo/PanelAppletShell:1.0" in its
-# "repo_ids" attribute. The sub-menu is determined by the "panel:category"
-# attribute. The icon comes from "panel:icon", the text displayed in the
-# menu comes from "name", the text in the tool-tip comes from "description".
-
-# The factory() function is called when a new applet is created. It receives
-# a container that should be populated with the actual applet contents (in
-# this case a Button).
-
-# If you're hacking on the code, just modify bb_applet.py and then kill -9
-# the running applet: the panel will ask you if you'd like to re-load the
-# applet, and when you say 'yes', bb_applet.py will be re-executed. Note that
-# 'kill PID' won't work because the program is sitting in C code, and SIGINT
-# isn't delivered until after it surfaces to python, which will be never.
-
-# Running bb_applet.py by itself will result in a factory instance being
-# created and then sitting around forever waiting for the activation-server
-# to ask it to make an applet. This isn't very useful.
-
-# The "location" filename in bb_applet.server must point to bb_applet.py, and
-# bb_applet.py must be executable.
-
-# Enjoy!
-#  -Brian Warner
deleted file mode 100755
--- a/contrib/bitbucket_buildbot.py
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/env python
-"""Change source forwarder for bitbucket.org POST service.
-
-bitbucket_buildbot.py will determine the repository information from
-the JSON HTTP POST it receives from bitbucket.org and build the
-appropriate repository.
-
-If your bitbucket repository is private, you must add a ssh key to the
-bitbucket repository for the user who initiated bitbucket_buildbot.py
-
-bitbucket_buildbot.py is based on github_buildbot.py
-"""
-
-import logging
-from optparse import OptionParser
-import sys
-import tempfile
-import traceback
-
-from twisted.web import server, resource
-from twisted.internet import reactor
-from twisted.spread import pb
-from twisted.cred import credentials
-
-try:
-    import json
-except ImportError:
-    import simplejson as json
-
-
-class BitBucketBuildBot(resource.Resource):
-    """
-    BitBucketBuildBot creates the webserver that responds to the
-    BitBucket POST Service Hook.
-    """
-    isLeaf = True
-    bitbucket = None
-    master = None
-    port = None
-    private = False
-
-    def render_POST(self, request):
-        """
-        Reponds only to POST events and starts the build process
-
-        :arguments:
-            request
-                the http request object
-        """
-        try:
-            payload = json.loads(request.args['payload'][0])
-            logging.debug("Payload: " + str(payload))
-            self.process_change(payload)
-        except Exception:
-            logging.error("Encountered an exception:")
-            for msg in traceback.format_exception(*sys.exc_info()):
-                logging.error(msg.strip())
-
-    def process_change(self, payload):
-        """
-        Consumes the JSON as a python object and actually starts the build.
-
-        :arguments:
-            payload
-                Python Object that represents the JSON sent by Bitbucket POST
-                Service Hook.
-        """
-        if self.private:
-            repo_url = 'ssh://hg@%s%s' % (
-                self.bitbucket,
-                payload['repository']['absolute_url'],
-                )
-        else:
-            repo_url = 'http://%s%s' % (
-                self.bitbucket,
-                payload['repository']['absolute_url'],
-                )
-        changes = []
-        for commit in payload['commits']:
-            files = [file_info['file'] for file_info in commit['files']]
-            revlink = 'http://%s%s/changeset/%s/' % (
-                self.bitbucket,
-                payload['repository']['absolute_url'],
-                commit['node'],
-                )
-            change = {
-                'revision': commit['node'],
-                'revlink': revlink,
-                'comments': commit['message'],
-                'who': commit['author'],
-                'files': files,
-                'links': [revlink],
-                'properties': dict(repository=repo_url),
-                }
-            changes.append(change)
-        # Submit the changes, if any
-        if not changes:
-            logging.warning("No changes found")
-            return
-        host, port = self.master.split(':')
-        port = int(port)
-        factory = pb.PBClientFactory()
-        deferred = factory.login(credentials.UsernamePassword("change",
-                                                              "changepw"))
-        reactor.connectTCP(host, port, factory)
-        deferred.addErrback(self.connectFailed)
-        deferred.addCallback(self.connected, changes)
-
-    def connectFailed(self, error):
-        """
-        If connection is failed.  Logs the error.
-        """
-        logging.error("Could not connect to master: %s"
-                % error.getErrorMessage())
-        return error
-
-    def addChange(self, dummy, remote, changei):
-        """
-        Sends changes from the commit to the buildmaster.
-        """
-        logging.debug("addChange %s, %s" % (repr(remote), repr(changei)))
-        try:
-            change = changei.next()
-        except StopIteration:
-            remote.broker.transport.loseConnection()
-            return None
-
-        logging.info("New revision: %s" % change['revision'][:8])
-        for key, value in change.iteritems():
-            logging.debug("  %s: %s" % (key, value))
-
-        deferred = remote.callRemote('addChange', change)
-        deferred.addCallback(self.addChange, remote, changei)
-        return deferred
-
-    def connected(self, remote, changes):
-        """
-        Reponds to the connected event.
-        """
-        return self.addChange(None, remote, changes.__iter__())
-
-
-def main():
-    """
-    The main event loop that starts the server and configures it.
-    """
-    usage = "usage: %prog [options]"
-    parser = OptionParser(usage)
-    parser.add_option(
-        "-p", "--port",
-        help="Port the HTTP server listens to for the Bitbucket Service Hook"
-        " [default: %default]", default=4000, type=int, dest="port")
-    parser.add_option(
-        "-m", "--buildmaster",
-        help="Buildbot Master host and port. ie: localhost:9989 [default:"
-        + " %default]", default="localhost:9989", dest="buildmaster")
-    parser.add_option(
-        "-l", "--log",
-        help="The absolute path, including filename, to save the log to"
-        " [default: %default]",
-        default = tempfile.gettempdir() + "/bitbucket_buildbot.log",
-        dest="log")
-    parser.add_option(
-        "-L", "--level",
-        help="The logging level: debug, info, warn, error, fatal [default:"
-        " %default]", default='warn', dest="level")
-    parser.add_option(
-        "-g", "--bitbucket",
-        help="The bitbucket serve [default: %default]",
-        default='bitbucket.org',
-        dest="bitbucket")
-    parser.add_option(
-        '-P', '--private',
-        help='Use SSH to connect, for private repositories.',
-        dest='private',
-        default=False,
-        action='store_true',
-        )
-    (options, _) = parser.parse_args()
-    # Set up logging.
-    levels = {
-        'debug': logging.DEBUG,
-        'info': logging.INFO,
-        'warn': logging.WARNING,
-        'error': logging.ERROR,
-        'fatal': logging.FATAL,
-        }
-    filename = options.log
-    log_format = "%(asctime)s - %(levelname)s - %(message)s"
-    logging.basicConfig(filename=filename, format=log_format,
-                        level=levels[options.level])
-    # Start listener.
-    bitbucket_bot = BitBucketBuildBot()
-    bitbucket_bot.bitbucket = options.bitbucket
-    bitbucket_bot.master = options.buildmaster
-    bitbucket_bot.private = options.private
-    site = server.Site(bitbucket_bot)
-    reactor.listenTCP(options.port, site)
-    reactor.run()
-
-
-if __name__ == '__main__':
-    main()
deleted file mode 100755
--- a/contrib/bk_buildbot.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/local/bin/python
-#
-# BitKeeper hook script.
-#
-# svn_buildbot.py was used as a base for this file, if you find any bugs or
-# errors please email me.
-#
-# Amar Takhar <amar@ntp.org>
-
-
-'''
-/path/to/bk_buildbot.py --repository "$REPOS" --revision "$REV" --branch \
-"<branch>" --bbserver localhost --bbport 9989
-'''
-
-import commands
-import sys
-import os
-import re
-if sys.version_info < (2, 6):
-    import sets
-
-# We have hackish "-d" handling here rather than in the Options
-# subclass below because a common error will be to not have twisted in
-# PYTHONPATH; we want to be able to print that error to the log if
-# debug mode is on, so we set it up before the imports.
-
-DEBUG = None
-
-if '-d' in sys.argv:
-    i = sys.argv.index('-d')
-    DEBUG = sys.argv[i+1]
-    del sys.argv[i]
-    del sys.argv[i]
-
-if DEBUG:
-    f = open(DEBUG, 'a')
-    sys.stderr = f
-    sys.stdout = f
-
-
-from twisted.internet import defer, reactor
-from twisted.python import usage
-from twisted.spread import pb
-from twisted.cred import credentials
-
-
-class Options(usage.Options):
-    optParameters = [
-        ['repository', 'r', None,
-         "The repository that was changed."],
-        ['revision', 'v', None,
-         "The revision that we want to examine (default: latest)"],
-        ['branch', 'b', None,
-         "Name of the branch to insert into the branch field. (REQUIRED)"],
-        ['category', 'c', None,
-         "Schedular category."],
-        ['bbserver', 's', 'localhost',
-         "The hostname of the server that buildbot is running on"],
-        ['bbport', 'p', 8007,
-         "The port that buildbot is listening on"]
-        ]
-    optFlags = [
-        ['dryrun', 'n', "Do not actually send changes"],
-        ]
-
-    def __init__(self):
-        usage.Options.__init__(self)
-
-    def postOptions(self):
-        if self['repository'] is None:
-            raise usage.error("You must pass --repository")
-
-class ChangeSender:
-
-    def getChanges(self, opts):
-        """Generate and stash a list of Change dictionaries, ready to be sent
-        to the buildmaster's PBChangeSource."""
-
-        # first we extract information about the files that were changed
-        repo = opts['repository']
-        print "Repo:", repo
-        rev_arg = ''
-        if opts['revision']:
-            rev_arg = '-r"%s"' % (opts['revision'], )
-        changed = commands.getoutput("bk changes -v %s -d':GFILE:\\n' '%s'" % (
-            rev_arg, repo)).split('\n')
-
-        # Remove the first line, it's an info message you can't remove (annoying)
-        del changed[0]
-
-        change_info = commands.getoutput("bk changes %s -d':USER:\\n$each(:C:){(:C:)\\n}' '%s'" % (
-            rev_arg, repo)).split('\n')
-
-        # Remove the first line, it's an info message you can't remove (annoying)
-        del change_info[0]
-
-        who = change_info.pop(0)
-        branch = opts['branch']
-        message = '\n'.join(change_info)
-        revision = opts.get('revision')
-
-        changes = {'who': who,
-                 'branch': branch,
-                 'files': changed,
-                 'comments': message,
-                 'revision': revision}
-
-        if opts.get('category'):
-            changes['category'] = opts.get('category')
-
-        return changes
-
-
-    def sendChanges(self, opts, changes):
-        pbcf = pb.PBClientFactory()
-        reactor.connectTCP(opts['bbserver'], int(opts['bbport']), pbcf)
-        d = pbcf.login(credentials.UsernamePassword('change', 'changepw'))
-        d.addCallback(self.sendAllChanges, changes)
-        return d
-
-    def sendAllChanges(self, remote, changes):
-        dl = remote.callRemote('addChange', changes)
-        return dl
-
-    def run(self):
-        opts = Options()
-        try:
-            opts.parseOptions()
-            if not opts['branch']:
-                print "You must supply a branch with -b or --branch."
-                sys.exit(1);
-
-        except usage.error, ue:
-            print opts
-            print "%s: %s" % (sys.argv[0], ue)
-            sys.exit()
-
-        changes = self.getChanges(opts)
-        if opts['dryrun']:
-            for k in changes.keys():
-                print "[%10s]: %s" % (k, changes[k])
-            print "*NOT* sending any changes"
-            return
-
-        d = self.sendChanges(opts, changes)
-
-        def quit(*why):
-            print "quitting! because", why
-            reactor.stop()
-
-        def failed(f):
-            print "FAILURE: %s" % f
-            reactor.stop()
-
-        d.addErrback(failed)
-        d.addCallback(quit, "SUCCESS")
-        reactor.callLater(60, quit, "TIMEOUT")
-
-        reactor.run()
-
-
-if __name__ == '__main__':
-    s = ChangeSender()
-    s.run()
deleted file mode 100755
--- a/contrib/bzr_buildbot.py
+++ /dev/null
@@ -1,483 +0,0 @@
-# Copyright (C) 2008-2009 Canonical
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""\
-bzr buildbot integration
-========================
-
-This file contains both bzr commit/change hooks and a bzr poller.
-
-------------
-Requirements
-------------
-
-This has been tested with buildbot 0.7.9, bzr 1.10, and Twisted 8.1.0.  It
-should work in subsequent releases.
-
-For the hook to work, Twisted must be installed in the same Python that bzr
-uses.
-
------
-Hooks
------
-
-To install, put this file in a bzr plugins directory (e.g.,
-~/.bazaar/plugins). Then, in one of your bazaar conf files (e.g.,
-~/.bazaar/locations.conf), set the location you want to connect with buildbot
-with these keys:
-
-- buildbot_on: one of 'commit', 'push, or 'change'.  Turns the plugin on to
-  report changes via commit, changes via push, or any changes to the trunk.
-  'change' is recommended.
-
-- buildbot_server: (required to send to a buildbot master) the URL of the
-  buildbot master to which you will connect (as of this writing, the same
-  server and port to which slaves connect).
-
-- buildbot_port: (optional, defaults to 9989) the port of the buildbot master
-  to which you will connect (as of this writing, the same server and port to
-  which slaves connect)
-
-- buildbot_pqm: (optional, defaults to not pqm) Normally, the user that
-  commits the revision is the user that is responsible for the change.  When
-  run in a pqm (Patch Queue Manager, see https://launchpad.net/pqm)
-  environment, the user that commits is the Patch Queue Manager, and the user
-  that committed the *parent* revision is responsible for the change.  To turn
-  on the pqm mode, set this value to any of (case-insensitive) "Yes", "Y",
-  "True", or "T".
-
-- buildbot_dry_run: (optional, defaults to not a dry run) Normally, the
-  post-commit hook will attempt to communicate with the configured buildbot
-  server and port. If this parameter is included and any of (case-insensitive)
-  "Yes", "Y", "True", or "T", then the hook will simply print what it would
-  have sent, but not attempt to contact the buildbot master.
-
-- buildbot_send_branch_name: (optional, defaults to not sending the branch
-  name) If your buildbot's bzr source build step uses a repourl, do
-  *not* turn this on. If your buildbot's bzr build step uses a baseURL, then
-  you may set this value to any of (case-insensitive) "Yes", "Y", "True", or
-  "T" to have the buildbot master append the branch name to the baseURL.
-
-When buildbot no longer has a hardcoded password, it will be a configuration
-option here as well.
-
-------
-Poller
-------
-
-Put this file somewhere that your buildbot configuration can import it.  Even
-in the same directory as the master.cfg should work.  Install the poller in
-the buildbot configuration as with any other change source.  Minimally,
-provide a URL that you want to poll (bzr://, bzr+ssh://, or lp:), though make
-sure the buildbot user has necessary privileges.  You may also want to specify
-these optional values.
-
-poll_interval: the number of seconds to wait between polls.  Defaults to 10
-               minutes.
-
-branch_name: any value to be used as the branch name.  Defaults to None, or
-             specify a string, or specify the constants from this file SHORT
-             or FULL to get the short branch name or full branch address.
-
-blame_merge_author: normally, the user that commits the revision is the user
-                    that is responsible for the change. When run in a pqm
-                    (Patch Queue Manager, see https://launchpad.net/pqm)
-                    environment, the user that commits is the Patch Queue
-                    Manager, and the user that committed the merged, *parent*
-                    revision is responsible for the change. set this value to
-                    True if this is pointed against a PQM-managed branch.
-
--------------------
-Contact Information
--------------------
-
-Maintainer/author: gary.poster@canonical.com
-"""
-
-try:
-    import buildbot.util
-    import buildbot.changes.base
-    import buildbot.changes.changes
-except ImportError:
-    DEFINE_POLLER = False
-else:
-    DEFINE_POLLER = True
-import bzrlib.branch
-import bzrlib.errors
-import bzrlib.trace
-import twisted.cred.credentials
-import twisted.internet.base
-import twisted.internet.defer
-import twisted.internet.reactor
-import twisted.internet.selectreactor
-import twisted.internet.task
-import twisted.internet.threads
-import twisted.python.log
-import twisted.spread.pb
-
-
-#############################################################################
-# This is the code that the poller and the hooks share.
-
-def generate_change(branch,
-                    old_revno=None, old_revid=None,
-                    new_revno=None, new_revid=None,
-                    blame_merge_author=False):
-    """Return a dict of information about a change to the branch.
-
-    Dict has keys of "files", "who", "comments", and "revision", as used by
-    the buildbot Change (and the PBChangeSource).
-
-    If only the branch is given, the most recent change is returned.
-
-    If only the new_revno is given, the comparison is expected to be between
-    it and the previous revno (new_revno -1) in the branch.
-
-    Passing old_revid and new_revid is only an optimization, included because
-    bzr hooks usually provide this information.
-
-    blame_merge_author means that the author of the merged branch is
-    identified as the "who", not the person who committed the branch itself.
-    This is typically used for PQM.
-    """
-    change = {} # files, who, comments, revision; NOT branch (= branch.nick)
-    if new_revno is None:
-        new_revno = branch.revno()
-    if new_revid is None:
-        new_revid = branch.get_rev_id(new_revno)
-    # TODO: This falls over if this is the very first revision
-    if old_revno is None:
-        old_revno = new_revno -1
-    if old_revid is None:
-        old_revid = branch.get_rev_id(old_revno)
-    repository = branch.repository
-    new_rev = repository.get_revision(new_revid)
-    if blame_merge_author:
-        # this is a pqm commit or something like it
-        change['who'] = repository.get_revision(
-            new_rev.parent_ids[-1]).get_apparent_author()
-    else:
-        change['who'] = new_rev.get_apparent_author()
-    # maybe useful to know:
-    # name, email = bzrtools.config.parse_username(change['who'])
-    change['comments'] = new_rev.message
-    change['revision'] = new_revno
-    files = change['files'] = []
-    changes = repository.revision_tree(new_revid).changes_from(
-        repository.revision_tree(old_revid))
-    for (collection, name) in ((changes.added, 'ADDED'),
-                               (changes.removed, 'REMOVED'),
-                               (changes.modified, 'MODIFIED')):
-        for info in collection:
-            path = info[0]
-            kind = info[2]
-            files.append(' '.join([path, kind, name]))
-    for info in changes.renamed:
-        oldpath, newpath, id, kind, text_modified, meta_modified = info
-        elements = [oldpath, kind,'RENAMED', newpath]
-        if text_modified or meta_modified:
-            elements.append('MODIFIED')
-        files.append(' '.join(elements))
-    return change
-
-#############################################################################
-# poller
-
-# We don't want to make the hooks unnecessarily depend on buildbot being
-# installed locally, so we conditionally create the BzrPoller class.
-if DEFINE_POLLER:
-
-    FULL = object()
-    SHORT = object()
-
-
-    class BzrPoller(buildbot.changes.base.ChangeSource,
-                    buildbot.util.ComparableMixin):
-
-        compare_attrs = ['url']
-
-        def __init__(self, url, poll_interval=10*60, blame_merge_author=False,
-                     branch_name=None, category=None):
-            # poll_interval is in seconds, so default poll_interval is 10
-            # minutes.
-            # bzr+ssh://bazaar.launchpad.net/~launchpad-pqm/launchpad/devel/
-            # works, lp:~launchpad-pqm/launchpad/devel/ doesn't without help.
-            if url.startswith('lp:'):
-                url = 'bzr+ssh://bazaar.launchpad.net/' + url[3:]
-            self.url = url
-            self.poll_interval = poll_interval
-            self.loop = twisted.internet.task.LoopingCall(self.poll)
-            self.blame_merge_author = blame_merge_author
-            self.branch_name = branch_name
-            self.category = category
-
-        def startService(self):
-            twisted.python.log.msg("BzrPoller(%s) starting" % self.url)
-            buildbot.changes.base.ChangeSource.startService(self)
-            if self.branch_name is FULL:
-                ourbranch = self.url
-            elif self.branch_name is SHORT:
-                # We are in a bit of trouble, as we cannot really know what our
-                # branch is until we have polled new changes.
-                # Seems we would have to wait until we polled the first time,
-                # and only then do the filtering, grabbing the branch name from
-                # whatever we polled.
-                # For now, leave it as it was previously (compare against
-                # self.url); at least now things work when specifying the
-                # branch name explicitly.
-                ourbranch = self.url
-            else:
-                ourbranch = self.branch_name
-            for change in reversed(self.parent.changes):
-                if change.branch == ourbranch:
-                    self.last_revision = change.revision
-                    break
-            else:
-                self.last_revision = None
-            self.polling = False
-            twisted.internet.reactor.callWhenRunning(
-                self.loop.start, self.poll_interval)
-
-        def stopService(self):
-            twisted.python.log.msg("BzrPoller(%s) shutting down" % self.url)
-            self.loop.stop()
-            return buildbot.changes.base.ChangeSource.stopService(self)
-
-        def describe(self):
-            return "BzrPoller watching %s" % self.url
-
-        @twisted.internet.defer.inlineCallbacks
-        def poll(self):
-            if self.polling: # this is called in a loop, and the loop might
-                # conceivably overlap.
-                return
-            self.polling = True
-            try:
-                # On a big tree, even individual elements of the bzr commands
-                # can take awhile. So we just push the bzr work off to a
-                # thread.
-                try:
-                    changes = yield twisted.internet.threads.deferToThread(
-                        self.getRawChanges)
-                except (SystemExit, KeyboardInterrupt):
-                    raise
-                except:
-                    # we'll try again next poll.  Meanwhile, let's report.
-                    twisted.python.log.err()
-                else:
-                    for change in changes:
-                        yield self.addChange(
-                            buildbot.changes.changes.Change(**change))
-                        self.last_revision = change['revision']
-            finally:
-                self.polling = False
-
-        def getRawChanges(self):
-            branch = bzrlib.branch.Branch.open_containing(self.url)[0]
-            if self.branch_name is FULL:
-                branch_name = self.url
-            elif self.branch_name is SHORT:
-                branch_name = branch.nick
-            else: # presumably a string or maybe None
-                branch_name = self.branch_name
-            changes = []
-            change = generate_change(
-                branch, blame_merge_author=self.blame_merge_author)
-            if (self.last_revision is None or
-                change['revision'] > self.last_revision):
-                change['branch'] = branch_name
-                change['category'] = self.category
-                changes.append(change)
-                if self.last_revision is not None:
-                    while self.last_revision + 1 < change['revision']:
-                        change = generate_change(
-                            branch, new_revno=change['revision']-1,
-                            blame_merge_author=self.blame_merge_author)
-                        change['branch'] = branch_name
-                        changes.append(change)
-            changes.reverse()
-            return changes
-
-        def addChange(self, change):
-            d = twisted.internet.defer.Deferred()
-            def _add_change():
-                d.callback(
-                    self.parent.addChange(change))
-            twisted.internet.reactor.callLater(0, _add_change)
-            return d
-
-#############################################################################
-# hooks
-
-HOOK_KEY = 'buildbot_on'
-SERVER_KEY = 'buildbot_server'
-PORT_KEY = 'buildbot_port'
-DRYRUN_KEY = 'buildbot_dry_run'
-PQM_KEY = 'buildbot_pqm'
-SEND_BRANCHNAME_KEY = 'buildbot_send_branch_name'
-
-PUSH_VALUE = 'push'
-COMMIT_VALUE = 'commit'
-CHANGE_VALUE = 'change'
-
-def _is_true(config, key):
-    val = config.get_user_option(key)
-    return val is not None and val.lower().strip() in (
-        'y', 'yes', 't', 'true')
-
-def _installed_hook(branch):
-    value = branch.get_config().get_user_option(HOOK_KEY)
-    if value is not None:
-        value = value.strip().lower()
-        if value not in (PUSH_VALUE, COMMIT_VALUE, CHANGE_VALUE):
-            raise bzrlib.errors.BzrError(
-                '%s, if set, must be one of %s, %s, or %s' % (
-                    HOOK_KEY, PUSH_VALUE, COMMIT_VALUE, CHANGE_VALUE))
-    return value
-
-##########################
-# Work around Twisted bug.
-# See http://twistedmatrix.com/trac/ticket/3591
-import operator
-import socket
-from twisted.internet import defer
-from twisted.python import failure
-
-# replaces twisted.internet.thread equivalent
-def _putResultInDeferred(reactor, deferred, f, args, kwargs):
-    """
-    Run a function and give results to a Deferred.
-    """
-    try:
-        result = f(*args, **kwargs)
-    except:
-        f = failure.Failure()
-        reactor.callFromThread(deferred.errback, f)
-    else:
-        reactor.callFromThread(deferred.callback, result)
-
-# would be a proposed addition.  deferToThread could use it
-def deferToThreadInReactor(reactor, f, *args, **kwargs):
-    """
-    Run function in thread and return result as Deferred.
-    """
-    d = defer.Deferred()
-    reactor.callInThread(_putResultInDeferred, reactor, d, f, args, kwargs)
-    return d
-
-# uses its own reactor for the threaded calls, unlike Twisted's
-class ThreadedResolver(twisted.internet.base.ThreadedResolver):
-    def getHostByName(self, name, timeout = (1, 3, 11, 45)):
-        if timeout:
-            timeoutDelay = reduce(operator.add, timeout)
-        else:
-            timeoutDelay = 60
-        userDeferred = defer.Deferred()
-        lookupDeferred = deferToThreadInReactor(
-            self.reactor, socket.gethostbyname, name)
-        cancelCall = self.reactor.callLater(
-            timeoutDelay, self._cleanup, name, lookupDeferred)
-        self._runningQueries[lookupDeferred] = (userDeferred, cancelCall)
-        lookupDeferred.addBoth(self._checkTimeout, name, lookupDeferred)
-        return userDeferred
-##########################
-
-def send_change(branch, old_revno, old_revid, new_revno, new_revid, hook):
-    config = branch.get_config()
-    server = config.get_user_option(SERVER_KEY)
-    if not server:
-        bzrlib.trace.warning(
-            'bzr_buildbot: ERROR.  If %s is set, %s must be set',
-            HOOK_KEY, SERVER_KEY)
-        return
-    change = generate_change(
-        branch, old_revno, old_revid, new_revno, new_revid,
-        blame_merge_author=_is_true(config, PQM_KEY))
-    if _is_true(config, SEND_BRANCHNAME_KEY):
-        change['branch'] = branch.nick
-    # as of this writing (in Buildbot 0.7.9), 9989 is the default port when
-    # you make a buildbot master.
-    port = int(config.get_user_option(PORT_KEY) or 9989)
-    # if dry run, stop.
-    if _is_true(config, DRYRUN_KEY):
-        bzrlib.trace.note("bzr_buildbot DRY RUN "
-                          "(*not* sending changes to %s:%d on %s)",
-                          server, port, hook)
-        keys = change.keys()
-        keys.sort()
-        for k in keys:
-            bzrlib.trace.note("[%10s]: %s", k, change[k])
-        return
-    # We instantiate our own reactor so that this can run within a server.
-    reactor = twisted.internet.selectreactor.SelectReactor()
-    # See other reference to http://twistedmatrix.com/trac/ticket/3591
-    # above.  This line can go away with a release of Twisted that addresses
-    # this issue.
-    reactor.resolver = ThreadedResolver(reactor)
-    pbcf = twisted.spread.pb.PBClientFactory()
-    reactor.connectTCP(server, port, pbcf)
-    deferred = pbcf.login(
-        twisted.cred.credentials.UsernamePassword('change', 'changepw'))
-
-    def sendChanges(remote):
-        """Send changes to buildbot."""
-        bzrlib.trace.mutter("bzrbuildout sending changes: %s", change)
-        return remote.callRemote('addChange', change)
-
-    deferred.addCallback(sendChanges)
-
-    def quit(ignore, msg):
-        bzrlib.trace.note("bzrbuildout: %s", msg)
-        reactor.stop()
-
-    def failed(failure):
-        bzrlib.trace.warning("bzrbuildout: FAILURE\n %s", failure)
-        reactor.stop()
-
-    deferred.addCallback(quit, "SUCCESS")
-    deferred.addErrback(failed)
-    reactor.callLater(60, quit, None, "TIMEOUT")
-    bzrlib.trace.note(
-        "bzr_buildbot: SENDING CHANGES to buildbot master %s:%d on %s",
-        server, port, hook)
-    reactor.run(installSignalHandlers=False) # run in a thread when in server
-
-def post_commit(local_branch, master_branch, # branch is the master_branch
-                old_revno, old_revid, new_revno, new_revid):
-    if _installed_hook(master_branch) == COMMIT_VALUE:
-        send_change(master_branch,
-                     old_revid, old_revid, new_revno, new_revid, COMMIT_VALUE)
-
-def post_push(result):
-    if _installed_hook(result.target_branch) == PUSH_VALUE:
-        send_change(result.target_branch,
-                     result.old_revid, result.old_revid,
-                     result.new_revno, result.new_revid, PUSH_VALUE)
-
-def post_change_branch_tip(result):
-    if _installed_hook(result.branch) == CHANGE_VALUE:
-        send_change(result.branch,
-                     result.old_revid, result.old_revid,
-                     result.new_revno, result.new_revid, CHANGE_VALUE)
-
-bzrlib.branch.Branch.hooks.install_named_hook(
-    'post_commit', post_commit,
-    'send change to buildbot master')
-bzrlib.branch.Branch.hooks.install_named_hook(
-    'post_push', post_push,
-    'send change to buildbot master')
-bzrlib.branch.Branch.hooks.install_named_hook(
-    'post_change_branch_tip', post_change_branch_tip,
-    'send change to buildbot master')
deleted file mode 100755
--- a/contrib/coverage2text.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-from coverage import coverage
-from coverage.results import Numbers
-from coverage.summary import SummaryReporter
-from twisted.python import usage
-
-# this is an adaptation of the code behind "coverage report", modified to
-# display+sortby "lines uncovered", which (IMHO) is more important of a
-# metric than lines covered or percentage covered. Concentrating on the files
-# with the most uncovered lines encourages getting the tree and test suite
-# into a state that provides full line-coverage on all files.
-
-# much of this code was adapted from coverage/summary.py in the 'coverage'
-# distribution, and is used under their BSD license.
-
-class Options(usage.Options):
-    optParameters = [
-        ("sortby", "s", "uncovered", "how to sort: uncovered, covered, name"),
-        ]
-
-class MyReporter(SummaryReporter):
-    def report(self, outfile=None, sortby="uncovered"):
-        self.find_code_units(None, ["/System", "/Library", "/usr/lib",
-                                    "buildbot/test", "simplejson"])
-
-        # Prepare the formatting strings
-        max_name = max([len(cu.name) for cu in self.code_units] + [5])
-        fmt_name = "%%- %ds  " % max_name
-        fmt_err = "%s   %s: %s\n"
-        header1 = (fmt_name % ""    ) + "     Statements    "
-        header2 = (fmt_name % "Name") + " Uncovered  Covered"
-        fmt_coverage = fmt_name + "%9d  %7d "
-        if self.branches:
-            header1 += "   Branches   "
-            header2 += " Found  Excutd"
-            fmt_coverage += " %6d %6d"
-        header1 += "  Percent"
-        header2 += "  Covered"
-        fmt_coverage += " %7d%%"
-        if self.show_missing:
-            header1 += "          "
-            header2 += "   Missing"
-            fmt_coverage += "   %s"
-        rule = "-" * len(header1) + "\n"
-        header1 += "\n"
-        header2 += "\n"
-        fmt_coverage += "\n"
-
-        if not outfile:
-            outfile = sys.stdout
-
-        # Write the header
-        outfile.write(header1)
-        outfile.write(header2)
-        outfile.write(rule)
-
-        total = Numbers()
-        total_uncovered = 0
-
-        lines = []
-        for cu in self.code_units:
-            try:
-                analysis = self.coverage._analyze(cu)
-                nums = analysis.numbers
-                uncovered = nums.n_statements - nums.n_executed
-                total_uncovered += uncovered
-                args = (cu.name, uncovered, nums.n_executed)
-                if self.branches:
-                    args += (nums.n_branches, nums.n_executed_branches)
-                args += (nums.pc_covered,)
-                if self.show_missing:
-                    args += (analysis.missing_formatted(),)
-                if sortby == "covered":
-                    sortkey = nums.pc_covered
-                elif sortby == "uncovered":
-                    sortkey = uncovered
-                else:
-                    sortkey = cu.name
-                lines.append((sortkey, fmt_coverage % args))
-                total += nums
-            except KeyboardInterrupt:                       # pragma: no cover
-                raise
-            except:
-                if not self.ignore_errors:
-                    typ, msg = sys.exc_info()[:2]
-                    outfile.write(fmt_err % (cu.name, typ.__name__, msg))
-        lines.sort()
-        if sortby in ("uncovered", "covered"):
-            lines.reverse()
-        for sortkey,line in lines:
-            outfile.write(line)
-
-        if total.n_files > 1:
-            outfile.write(rule)
-            args = ("TOTAL", total_uncovered, total.n_executed)
-            if self.branches:
-                args += (total.n_branches, total.n_executed_branches)
-            args += (total.pc_covered,)
-            if self.show_missing:
-                args += ("",)
-            outfile.write(fmt_coverage % args)
-
-def report(o):
-    c = coverage()
-    c.load()
-    r = MyReporter(c, show_missing=False, ignore_errors=False)
-    r.report(sortby=o['sortby'])
-
-if __name__ == '__main__':
-    o = Options()
-    o.parseOptions()
-    report(o)
-
-
-
deleted file mode 100644
--- a/contrib/css/sample1.css
+++ /dev/null
@@ -1,53 +0,0 @@
-* {
-	font-family: Verdana, Cursor;
-	font-size: 10px;
-	font-weight: bold;
-}
-
-a:link,a:visited,a:active {
-	color: #666666;
-}
-a:hover {
-	color: #FFFFFF;
-}
-
-.table {
-	border-spacing: 2px;
-}
-
-td.Event, td.Activity, td.Change, td.Time, td.Builder {
-	color: #333333;
-	border: 1px solid #666666;
-	background-color: #CCCCCC;
-}
-
-/* LastBuild, BuildStep states */
-.success {
-	color: #FFFFFF;
-	border: 1px solid #2f8f0f;
-	background-color: #8fdf5f;
-}
-
-.failure {
-	color: #FFFFFF;
-	border: 1px solid #f33636;
-	background-color: #e98080;
-}
-
-.warnings {
-	color: #FFFFFF;
-	border: 1px solid #fc901f;
-	background-color: #ffc343;
-}
-
-.exception, td.offline {
-	color: #FFFFFF;
-	border: 1px solid #8000c0;
-	background-color: #e0b0ff;
-}
-
-.start,.running, td.building {
-	color: #666666;
-	border: 1px solid #ffff00;
-	background-color: #fffc6c;
-}
deleted file mode 100644
--- a/contrib/css/sample2.css
+++ /dev/null
@@ -1,53 +0,0 @@
-* {
-        font-family: Verdana, Cursor;
-        font-size: 12px;
-        font-weight: bold;
-}
-
-a:link,a:visited,a:active {
-        color: #666666;
-}
-a:hover {
-        color: #FFFFFF;
-}
-
-.table {
-        border-spacing: 2px;
-}
-
-td.Event, td.Activity, td.Change, td.Time, td.Builder {
-        color: #333333;
-        border: 1px solid #666666;
-        background-color: #CCCCCC;
-}
-
-/* LastBuild, BuildStep states */
-.success {
-        color: #FFFFFF;
-        border: 1px solid #2f8f0f;
-        background-color: #72ff75;
-}
-
-.failure {
-        color: #FFFFFF;
-        border: 1px solid #f33636;
-        background-color: red;
-}
-
-.warnings {
-        color: #FFFFFF;
-        border: 1px solid #fc901f;
-        background-color: #ffc343;
-}
-
-.exception, td.offline {
-        color: #FFFFFF;
-        border: 1px solid #8000c0;
-        background-color: red;
-}
-
-.start,.running, td.building {
-        color: #666666;
-        border: 1px solid #ffff00;
-        background-color: yellow;
-}
deleted file mode 100755
--- a/contrib/darcs_buildbot.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#! /usr/bin/python
-
-# This is a script which delivers Change events from Darcs to the buildmaster
-# each time a patch is pushed into a repository. Add it to the 'apply' hook
-# on your canonical "central" repository, by putting something like the
-# following in the _darcs/prefs/defaults file of that repository:
-#
-#  apply posthook /PATH/TO/darcs_buildbot.py BUILDMASTER:PORT
-#  apply run-posthook
-#
-# (the second command is necessary to avoid the usual "do you really want to
-# run this hook" prompt. Note that you cannot have multiple 'apply posthook'
-# lines: if you need this, you must create a shell script to run all your
-# desired commands, then point the posthook at that shell script.)
-#
-# Note that both Buildbot and Darcs must be installed on the repository
-# machine. You will also need the Python/XML distribution installed (the
-# "python2.3-xml" package under debian).
-
-import os
-import sys
-import commands
-import xml
-
-from buildbot.clients import sendchange
-from twisted.internet import defer, reactor
-from xml.dom import minidom
-
-
-def getText(node):
-    return "".join([cn.data
-                    for cn in node.childNodes
-                    if cn.nodeType == cn.TEXT_NODE])
-
-
-def getTextFromChild(parent, childtype):
-    children = parent.getElementsByTagName(childtype)
-    if not children:
-        return ""
-    return getText(children[0])
-
-
-def makeChange(p):
-    author = p.getAttribute("author")
-    revision = p.getAttribute("hash")
-    comments = (getTextFromChild(p, "name") + "\n" +
-                getTextFromChild(p, "comment"))
-
-    summary = p.getElementsByTagName("summary")[0]
-    files = []
-    for filenode in summary.childNodes:
-        if filenode.nodeName in ("add_file", "modify_file", "remove_file"):
-            filename = getText(filenode).strip()
-            files.append(filename)
-        elif filenode.nodeName == "move":
-            from_name = filenode.getAttribute("from")
-            to_name = filenode.getAttribute("to")
-            files.append(to_name)
-
-    # note that these are all unicode. Because PB can't handle unicode, we
-    # encode them into ascii, which will blow up early if there's anything we
-    # can't get to the far side. When we move to something that *can* handle
-    # unicode (like newpb), remove this.
-    author = author.encode("ascii", "replace")
-    comments = comments.encode("ascii", "replace")
-    files = [f.encode("ascii", "replace") for f in files]
-    revision = revision.encode("ascii", "replace")
-
-    change = {
-        # note: this is more likely to be a full email address, which would
-        # make the left-hand "Changes" column kind of wide. The buildmaster
-        # should probably be improved to display an abbreviation of the
-        # username.
-        'username': author,
-        'revision': revision,
-        'comments': comments,
-        'files': files,
-        }
-    return change
-
-
-def getChangesFromCommand(cmd, count):
-    out = commands.getoutput(cmd)
-    try:
-        doc = minidom.parseString(out)
-    except xml.parsers.expat.ExpatError, e:
-        print "failed to parse XML"
-        print str(e)
-        print "purported XML is:"
-        print "--BEGIN--"
-        print out
-        print "--END--"
-        sys.exit(1)
-
-    c = doc.getElementsByTagName("changelog")[0]
-    changes = []
-    for i, p in enumerate(c.getElementsByTagName("patch")):
-        if i >= count:
-            break
-        changes.append(makeChange(p))
-    return changes
-
-
-def getSomeChanges(count):
-    cmd = "darcs changes --last=%d --xml-output --summary" % count
-    return getChangesFromCommand(cmd, count)
-
-
-LASTCHANGEFILE = ".darcs_buildbot-lastchange"
-
-
-def findNewChanges():
-    if os.path.exists(LASTCHANGEFILE):
-        f = open(LASTCHANGEFILE, "r")
-        lastchange = f.read()
-        f.close()
-    else:
-        return getSomeChanges(1)
-    lookback = 10
-    while True:
-        changes = getSomeChanges(lookback)
-        # getSomeChanges returns newest-first, so changes[0] is the newest.
-        # we want to scan the newest first until we find the changes we sent
-        # last time, then deliver everything newer than that (and send them
-        # oldest-first).
-        for i, c in enumerate(changes):
-            if c['revision'] == lastchange:
-                newchanges = changes[:i]
-                newchanges.reverse()
-                return newchanges
-        if 2*lookback > 100:
-            raise RuntimeError("unable to find our most recent change "
-                               "(%s) in the last %d changes" % (lastchange,
-                                                                lookback))
-        lookback = 2*lookback
-
-
-def sendChanges(master):
-    changes = findNewChanges()
-    s = sendchange.Sender(master, None)
-
-    d = defer.Deferred()
-    reactor.callLater(0, d.callback, None)
-
-    if not changes:
-        print "darcs_buildbot.py: weird, no changes to send"
-        return
-    elif len(changes) == 1:
-        print "sending 1 change to buildmaster:"
-    else:
-        print "sending %d changes to buildmaster:" % len(changes)
-
-    # the Darcs Source class expects revision to be a context, not a
-    # hash of a patch (which is what we have in c['revision']).  For
-    # the moment, we send None for everything but the most recent, because getting
-    # contexts is Hard.
-
-    # get the context for the most recent change
-    latestcontext = commands.getoutput("darcs changes --context")
-    changes[-1]['context'] = latestcontext
-
-    def _send(res, c):
-        branch = None
-        print " %s" % c['revision']
-        return s.send(branch, c.get('context'), c['comments'], c['files'],
-                      c['username'])
-    for c in changes:
-        d.addCallback(_send, c)
-
-    d.addCallbacks(s.printSuccess, s.printFailure)
-    d.addBoth(s.stop)
-    s.run()
-
-    if changes:
-        lastchange = changes[-1]['revision']
-        f = open(LASTCHANGEFILE, "w")
-        f.write(lastchange)
-        f.close()
-
-
-if __name__ == '__main__':
-    MASTER = sys.argv[1]
-    sendChanges(MASTER)
deleted file mode 100755
--- a/contrib/fakechange.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#! /usr/bin/python
-
-"""
-This is an example of how to use the remote ChangeMaster interface, which is
-a port that allows a remote program to inject Changes into the buildmaster.
-
-The buildmaster can either pull changes in from external sources (see
-buildbot.changes.changes.ChangeMaster.addSource for an example), or those
-changes can be pushed in from outside. This script shows how to do the
-pushing.
-
-Changes are just dictionaries with three keys:
-
- 'who': a simple string with a username. Responsibility for this change will
- be assigned to the named user (if something goes wrong with the build, they
- will be blamed for it).
-
- 'files': a list of strings, each with a filename relative to the top of the
- source tree.
-
- 'comments': a (multiline) string with checkin comments.
-
-Each call to .addChange injects a single Change object: each Change
-represents multiple files, all changed by the same person, and all with the
-same checkin comments.
-
-The port that this script connects to is the same 'slavePort' that the
-buildslaves and other debug tools use. The ChangeMaster service will only be
-available on that port if 'change' is in the list of services passed to
-buildbot.master.makeApp (this service is turned ON by default).
-"""
-
-import sys
-import commands
-import random
-import os.path
-
-from twisted.spread import pb
-from twisted.cred import credentials
-from twisted.internet import reactor
-from twisted.python import log
-
-
-def done(*args):
-    reactor.stop()
-
-
-users = ('zaphod', 'arthur', 'trillian', 'marvin', 'sbfast')
-dirs = ('src', 'doc', 'tests')
-sources = ('foo.c', 'bar.c', 'baz.c', 'Makefile')
-docs = ('Makefile', 'index.html', 'manual.texinfo')
-
-
-def makeFilename():
-    d = random.choice(dirs)
-    if d in ('src', 'tests'):
-        f = random.choice(sources)
-    else:
-        f = random.choice(docs)
-    return os.path.join(d, f)
-
-
-def send_change(remote):
-    who = random.choice(users)
-    if len(sys.argv) > 1:
-        files = sys.argv[1:]
-    else:
-        files = [makeFilename()]
-    comments = commands.getoutput("fortune")
-    change = {'who': who, 'files': files, 'comments': comments}
-    d = remote.callRemote('addChange', change)
-    d.addCallback(done)
-    print "%s: %s" % (who, " ".join(files))
-
-
-f = pb.PBClientFactory()
-d = f.login(credentials.UsernamePassword("change", "changepw"))
-reactor.connectTCP("localhost", 8007, f)
-err = lambda f: (log.err(), reactor.stop())
-d.addCallback(send_change).addErrback(err)
-
-reactor.run()
deleted file mode 100644
--- a/contrib/fix_changes_pickle_encoding.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/python
-"""%prog [options] [changes.pck] old_encoding
-
-Re-encodes changes in a pickle file to UTF-8 from the given encoding
-"""
-
-if __name__ == '__main__':
-    import sys, os
-    from cPickle import load, dump
-    from optparse import OptionParser
-
-    parser = OptionParser(__doc__)
-
-    options, args = parser.parse_args()
-
-    if len(args) == 2:
-        changes_file = args[0]
-        old_encoding = args[1]
-    elif len(args) == 1:
-        changes_file = "changes.pck"
-        old_encoding = args[0]
-    else:
-        parser.error("Need at least one argument")
-
-    print "opening %s" % (changes_file,)
-    try:
-        fp = open(changes_file)
-    except IOError, e:
-        parser.error("Couldn't open %s: %s" % (changes_file, str(e)))
-
-    changemgr = load(fp)
-    fp.close()
-
-    print "decoding bytestrings in %s using %s" % (changes_file, old_encoding)
-    changemgr.recode_changes(old_encoding)
-
-    changes_backup = changes_file + ".old"
-    i = 0
-    while os.path.exists(changes_backup):
-        i += 1
-        changes_backup = changes_file + ".old.%i" % i
-    print "backing up %s to %s" % (changes_file, changes_backup)
-    os.rename(changes_file, changes_backup)
-
-    dump(changemgr, open(changes_file, "w"))
deleted file mode 100755
--- a/contrib/generate_changelog.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008
-# Steve 'Ashcrow' Milner <smilner+buildbot@redhat.com>
-#
-# This software may be freely redistributed under the terms of the GNU
-# general public license.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-"""
-Generates changelog information using git.
-"""
-
-__docformat__ = 'restructuredtext'
-
-
-import os
-import sys
-
-
-def print_err(msg):
-    """
-    Wrapper to make printing to stderr nicer.
-
-    :Parameters:
-       - `msg`: the message to print.
-    """
-    sys.stderr.write(msg)
-    sys.stderr.write('\n')
-
-
-def usage():
-    """
-    Prints out usage information to stderr.
-    """
-    print_err('Usage: %s git-binary since' % sys.argv[0])
-    print_err(('Example: %s /usr/bin/git f5067523dfae9c7cdefc82'
-               '8721ec593ac7be62db' % sys.argv[0]))
-
-
-def main(args):
-    """
-    Main entry point.
-
-    :Parameters:
-       - `args`: same as sys.argv[1:]
-    """
-    # Make sure we have the arguments we need, else show usage
-    try:
-        git_bin = args[0]
-        since = args[1]
-    except IndexError, ie:
-        usage()
-        return 1
-
-    if not os.access(git_bin, os.X_OK):
-        print_err('Can not access %s' % git_bin)
-        return 1
-
-    # Open a pipe and force the format
-    pipe = os.popen((git_bin + ' log --pretty="format:%ad  %ae%n'
-                     '  * %s" ' + since + '..'))
-    print pipe.read()
-    pipe.close()
-    return 0
-
-
-if __name__ == '__main__':
-    raise SystemExit(main(sys.argv[1:]))
deleted file mode 100755
--- a/contrib/git_buildbot.py
+++ /dev/null
@@ -1,352 +0,0 @@
-#! /usr/bin/env python
-
-# This script expects one line for each new revision on the form
-#   <oldrev> <newrev> <refname>
-#
-# For example:
-#   aa453216d1b3e49e7f6f98441fa56946ddcd6a20
-#   68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-#
-# Each of these changes will be passed to the buildbot server along
-# with any other change information we manage to extract from the
-# repository.
-#
-# This script is meant to be run from hooks/post-receive in the git
-# repository. It can also be run at client side with hooks/post-merge
-# after using this wrapper:
-
-#!/bin/sh
-# PRE=$(git rev-parse 'HEAD@{1}')
-# POST=$(git rev-parse HEAD)
-# SYMNAME=$(git rev-parse --symbolic-full-name HEAD)
-# echo "$PRE $POST $SYMNAME" | git_buildbot.py
-#
-# Largely based on contrib/hooks/post-receive-email from git.
-
-import commands
-import logging
-import os
-import re
-import sys
-
-from twisted.spread import pb
-from twisted.cred import credentials
-from twisted.internet import reactor, defer
-
-from optparse import OptionParser
-
-# Modify this to fit your setup, or pass in --master server:host on the
-# command line
-
-master = "localhost:9989"
-
-# When sending the notification, send this category iff
-# it's set (via --category)
-
-category = None
-
-# When sending the notification, send this repository iff
-# it's set (via --repository)
-
-repository = None
-
-# When converting strings to unicode, assume this encoding. 
-# (set with --encoding)
-
-encoding = 'utf8'
-
-# The GIT_DIR environment variable must have been set up so that any
-# git commands that are executed will operate on the repository we're
-# installed in.
-
-changes = []
-
-def connectFailed(error):
-    logging.error("Could not connect to %s: %s"
-            % (master, error.getErrorMessage()))
-    return error
-
-
-def addChanges(remote, changei):
-    logging.debug("addChanges %s, %s" % (repr(remote), repr(changei)))
-    def addChange(c):
-        logging.info("New revision: %s" % c['revision'][:8])
-        for key, value in c.iteritems():
-            logging.debug("  %s: %s" % (key, value))
-
-        d = remote.callRemote('addChange', c)
-        return d
-
-    finished_d = defer.Deferred()
-    def iter():
-        try:
-            c = changei.next()
-            d = addChange(c)
-            # handle successful completion by re-iterating, but not immediately
-            # as that will blow out the Python stack
-            def cb(_):
-                reactor.callLater(0, iter)
-            d.addCallback(cb)
-            # and pass errors along to the outer deferred
-            d.addErrback(finished_d.errback)
-        except StopIteration:
-            remote.broker.transport.loseConnection()
-            finished_d.callback(None)
-
-    iter()
-    return finished_d
-
-
-def connected(remote):
-    return addChanges(remote, changes.__iter__())
-
-
-def grab_commit_info(c, rev):
-    # Extract information about committer and files using git show
-    f = os.popen("git show --raw --pretty=full %s" % rev, 'r')
-
-    files = []
-
-    while True:
-        line = f.readline()
-        if not line:
-            break
-
-        m = re.match(r"^:.*[MAD]\s+(.+)$", line)
-        if m:
-            logging.debug("Got file: %s" % m.group(1))
-            files.append(unicode(m.group(1), encoding=encoding))
-            continue
-
-        m = re.match(r"^Author:\s+(.+)$", line)
-        if m:
-            logging.debug("Got author: %s" % m.group(1))
-            c['who'] = unicode(m.group(1), encoding=encoding)
-
-        if re.match(r"^Merge: .*$", line):
-            files.append('merge')
-
-    c['files'] = files
-    status = f.close()
-    if status:
-        logging.warning("git show exited with status %d" % status)
-
-
-def gen_changes(input, branch):
-    while True:
-        line = input.readline()
-        if not line:
-            break
-
-        logging.debug("Change: %s" % line)
-
-        m = re.match(r"^([0-9a-f]+) (.*)$", line.strip())
-        c = {'revision': m.group(1),
-             'comments': unicode(m.group(2), encoding=encoding),
-             'branch': unicode(branch, encoding=encoding),
-        }
-
-        if category:
-            c['category'] = unicode(category, encoding=encoding)
-
-        if repository:
-            c['repository'] = unicode(repository, encoding=encoding)
-
-        grab_commit_info(c, m.group(1))
-        changes.append(c)
-
-
-def gen_create_branch_changes(newrev, refname, branch):
-    # A new branch has been created. Generate changes for everything
-    # up to `newrev' which does not exist in any branch but `refname'.
-    #
-    # Note that this may be inaccurate if two new branches are created
-    # at the same time, pointing to the same commit, or if there are
-    # commits that only exists in a common subset of the new branches.
-
-    logging.info("Branch `%s' created" % branch)
-
-    f = os.popen("git rev-parse --not --branches"
-            + "| grep -v $(git rev-parse %s)" % refname
-            + "| git rev-list --reverse --pretty=oneline --stdin %s" % newrev,
-            'r')
-
-    gen_changes(f, branch)
-
-    status = f.close()
-    if status:
-        logging.warning("git rev-list exited with status %d" % status)
-
-
-def gen_update_branch_changes(oldrev, newrev, refname, branch):
-    # A branch has been updated. If it was a fast-forward update,
-    # generate Change events for everything between oldrev and newrev.
-    #
-    # In case of a forced update, first generate a "fake" Change event
-    # rewinding the branch to the common ancestor of oldrev and
-    # newrev. Then, generate Change events for each commit between the
-    # common ancestor and newrev.
-
-    logging.info("Branch `%s' updated %s .. %s"
-            % (branch, oldrev[:8], newrev[:8]))
-
-    baserev = commands.getoutput("git merge-base %s %s" % (oldrev, newrev))
-    logging.debug("oldrev=%s newrev=%s baserev=%s" % (oldrev, newrev, baserev))
-    if baserev != oldrev:
-        c = {'revision': baserev,
-             'comments': "Rewind branch",
-             'branch': unicode(branch, encoding=encoding),
-             'who': "dummy",
-        }
-        logging.info("Branch %s was rewound to %s" % (branch, baserev[:8]))
-        files = []
-        f = os.popen("git diff --raw %s..%s" % (oldrev, baserev), 'r')
-        while True:
-            line = f.readline()
-            if not line:
-                break
-
-            file = re.match(r"^:.*[MAD]\s*(.+)$", line).group(1)
-            logging.debug("  Rewound file: %s" % file)
-            files.append(unicode(file, encoding=encoding))
-
-        status = f.close()
-        if status:
-            logging.warning("git diff exited with status %d" % status)
-
-        if category:
-            c['category'] = unicode(category, encoding=encoding)
-
-        if repository:
-            c['repository'] = unicode(repository, encoding=encoding)
-
-        if files:
-            c['files'] = files
-            changes.append(c)
-
-    if newrev != baserev:
-        # Not a pure rewind
-        f = os.popen("git rev-list --reverse --pretty=oneline %s..%s"
-                % (baserev, newrev), 'r')
-        gen_changes(f, branch)
-
-        status = f.close()
-        if status:
-            logging.warning("git rev-list exited with status %d" % status)
-
-
-def cleanup(res):
-    reactor.stop()
-
-
-def process_changes():
-    # Read branch updates from stdin and generate Change events
-    while True:
-        line = sys.stdin.readline()
-        if not line:
-            break
-
-        [oldrev, newrev, refname] = line.split(None, 2)
-
-        # We only care about regular heads, i.e. branches
-        m = re.match(r"^refs\/heads\/(.+)$", refname)
-        if not m:
-            logging.info("Ignoring refname `%s': Not a branch" % refname)
-            continue
-
-        branch = m.group(1)
-
-        # Find out if the branch was created, deleted or updated. Branches
-        # being deleted aren't really interesting.
-        if re.match(r"^0*$", newrev):
-            logging.info("Branch `%s' deleted, ignoring" % branch)
-            continue
-        elif re.match(r"^0*$", oldrev):
-            gen_create_branch_changes(newrev, refname, branch)
-        else:
-            gen_update_branch_changes(oldrev, newrev, refname, branch)
-
-    # Submit the changes, if any
-    if not changes:
-        logging.warning("No changes found")
-        return
-
-    host, port = master.split(':')
-    port = int(port)
-
-    f = pb.PBClientFactory()
-    d = f.login(credentials.UsernamePassword("change", "changepw"))
-    reactor.connectTCP(host, port, f)
-
-    d.addErrback(connectFailed)
-    d.addCallback(connected)
-    d.addBoth(cleanup)
-
-    reactor.run()
-
-
-def parse_options():
-    parser = OptionParser()
-    parser.add_option("-l", "--logfile", action="store", type="string",
-            help="Log to the specified file")
-    parser.add_option("-v", "--verbose", action="count",
-            help="Be more verbose. Ignored if -l is not specified.")
-    master_help = ("Build master to push to. Default is %(master)s" % 
-                   { 'master' : master })
-    parser.add_option("-m", "--master", action="store", type="string",
-            help=master_help)
-    parser.add_option("-c", "--category", action="store",
-                      type="string", help="Scheduler category to notify.")
-    parser.add_option("-r", "--repository", action="store",
-                      type="string", help="Git repository URL to send.")
-    encoding_help = ("Encoding to use when converting strings to "
-                     "unicode. Default is %(encoding)s." % 
-                     { "encoding" : encoding })
-    parser.add_option("-e", "--encoding", action="store", type="string", 
-                      help=encoding_help)
-    options, args = parser.parse_args()
-    return options
-
-
-# Log errors and critical messages to stderr. Optionally log
-# information to a file as well (we'll set that up later.)
-stderr = logging.StreamHandler(sys.stderr)
-fmt = logging.Formatter("git_buildbot: %(levelname)s: %(message)s")
-stderr.setLevel(logging.ERROR)
-stderr.setFormatter(fmt)
-logging.getLogger().addHandler(stderr)
-logging.getLogger().setLevel(logging.DEBUG)
-
-try:
-    options = parse_options()
-    level = logging.WARNING
-    if options.verbose:
-        level -= 10 * options.verbose
-        if level < 0:
-            level = 0
-
-    if options.logfile:
-        logfile = logging.FileHandler(options.logfile)
-        logfile.setLevel(level)
-        fmt = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
-        logfile.setFormatter(fmt)
-        logging.getLogger().addHandler(logfile)
-
-    if options.master:
-        master=options.master
-
-    if options.category:
-        category = options.category
-
-    if options.repository:
-        repository = options.repository
-
-    if options.encoding:
-        encoding = options.encoding
-
-    process_changes()
-except SystemExit:
-    pass
-except:
-    logging.exception("Unhandled exception")
-    sys.exit(1)
deleted file mode 100755
--- a/contrib/github_buildbot.py
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/env python
-"""
-github_buildbot.py is based on git_buildbot.py
-
-github_buildbot.py will determine the repository information from the JSON 
-HTTP POST it receives from github.com and build the appropriate repository.
-If your github repository is private, you must add a ssh key to the github
-repository for the user who initiated the build on the buildslave.
-
-"""
-
-import tempfile
-import logging
-import re
-import sys
-import traceback
-from twisted.web import server, resource
-from twisted.internet import reactor
-from twisted.spread import pb
-from twisted.cred import credentials
-from optparse import OptionParser
-
-try:
-    import json
-except ImportError:
-    import simplejson as json
-
-
-class GitHubBuildBot(resource.Resource):
-    """
-    GitHubBuildBot creates the webserver that responds to the GitHub Service
-    Hook.
-    """
-    isLeaf = True
-    master = None
-    port = None
-    
-    def render_POST(self, request):
-        """
-        Reponds only to POST events and starts the build process
-        
-        :arguments:
-            request
-                the http request object
-        """
-        try:
-            payload = json.loads(request.args['payload'][0])
-            user = payload['repository']['owner']['name']
-            repo = payload['repository']['name']
-            repo_url = payload['repository']['url']
-            self.private = payload['repository']['private']
-            logging.debug("Payload: " + str(payload))
-            self.process_change(payload, user, repo, repo_url)
-        except Exception:
-            logging.error("Encountered an exception:")
-            for msg in traceback.format_exception(*sys.exc_info()):
-                logging.error(msg.strip())
-
-    def process_change(self, payload, user, repo, repo_url):
-        """
-        Consumes the JSON as a python object and actually starts the build.
-        
-        :arguments:
-            payload
-                Python Object that represents the JSON sent by GitHub Service
-                Hook.
-        """
-        changes = []
-        newrev = payload['after']
-        refname = payload['ref']
-        
-        # We only care about regular heads, i.e. branches
-        match = re.match(r"^refs\/heads\/(.+)$", refname)
-        if not match:
-            logging.info("Ignoring refname `%s': Not a branch" % refname)
-
-        branch = match.group(1)
-        # Find out if the branch was created, deleted or updated. Branches
-        # being deleted aren't really interesting.
-        if re.match(r"^0*$", newrev):
-            logging.info("Branch `%s' deleted, ignoring" % branch)
-        else: 
-            for commit in payload['commits']:
-                files = []
-                files.extend(commit['added'])
-                files.extend(commit['modified'])
-                files.extend(commit['removed'])
-                change = {'revision': commit['id'],
-                     'revlink': commit['url'],
-                     'comments': commit['message'],
-                     'branch': branch,
-                     'who': commit['author']['name'] 
-                            + " <" + commit['author']['email'] + ">",
-                     'files': files,
-                     'links': [commit['url']],
-                     'properties': {'repository': repo_url},
-                }
-                changes.append(change)
-        
-        # Submit the changes, if any
-        if not changes:
-            logging.warning("No changes found")
-            return
-                    
-        host, port = self.master.split(':')
-        port = int(port)
-
-        factory = pb.PBClientFactory()
-        deferred = factory.login(credentials.UsernamePassword("change",
-                                                                "changepw"))
-        reactor.connectTCP(host, port, factory)
-        deferred.addErrback(self.connectFailed)
-        deferred.addCallback(self.connected, changes)
-
-
-    def connectFailed(self, error):
-        """
-        If connection is failed.  Logs the error.
-        """
-        logging.error("Could not connect to master: %s"
-                % error.getErrorMessage())
-        return error
-
-    def addChange(self, dummy, remote, changei):
-        """
-        Sends changes from the commit to the buildmaster.
-        """
-        logging.debug("addChange %s, %s" % (repr(remote), repr(changei)))
-        try:
-            change = changei.next()
-        except StopIteration:
-            remote.broker.transport.loseConnection()
-            return None
-    
-        logging.info("New revision: %s" % change['revision'][:8])
-        for key, value in change.iteritems():
-            logging.debug("  %s: %s" % (key, value))
-    
-        deferred = remote.callRemote('addChange', change)
-        deferred.addCallback(self.addChange, remote, changei)
-        return deferred
-
-    def connected(self, remote, changes):
-        """
-        Reponds to the connected event.
-        """
-        return self.addChange(None, remote, changes.__iter__())
-
-def main():
-    """
-    The main event loop that starts the server and configures it.
-    """
-    usage = "usage: %prog [options]"
-    parser = OptionParser(usage)
-        
-    parser.add_option("-p", "--port", 
-        help="Port the HTTP server listens to for the GitHub Service Hook"
-            + " [default: %default]", default=4000, type=int, dest="port")
-        
-    parser.add_option("-m", "--buildmaster",
-        help="Buildbot Master host and port. ie: localhost:9989 [default:" 
-            + " %default]", default="localhost:9989", dest="buildmaster")
-        
-    parser.add_option("-l", "--log", 
-        help="The absolute path, including filename, to save the log to"
-            + " [default: %default]", 
-            default = tempfile.gettempdir() + "/github_buildbot.log",
-            dest="log")
-        
-    parser.add_option("-L", "--level", 
-        help="The logging level: debug, info, warn, error, fatal [default:" 
-            + " %default]", default='warn', dest="level")
-        
-    parser.add_option("-g", "--github", 
-        help="The github server.  Changing this is useful if you've specified"      
-            + "  a specific HOST handle in ~/.ssh/config for github "   
-            + "[default: %default]", default='github.com',
-        dest="github")
-        
-    (options, _) = parser.parse_args()
-    
-    levels = {
-        'debug':logging.DEBUG,
-        'info':logging.INFO,
-        'warn':logging.WARNING,
-        'error':logging.ERROR,
-        'fatal':logging.FATAL,
-    }
-    
-    filename = options.log
-    log_format = "%(asctime)s - %(levelname)s - %(message)s" 
-    logging.basicConfig(filename=filename, format=log_format, 
-                        level=levels[options.level])
-    
-    github_bot = GitHubBuildBot()
-    github_bot.github = options.github
-    github_bot.master = options.buildmaster
-    
-    site = server.Site(github_bot)
-    reactor.listenTCP(options.port, site)
-    reactor.run()
-            
-if __name__ == '__main__':
-    main()
\ No newline at end of file
deleted file mode 100644
--- a/contrib/googlecode_atom.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# GoogleCode Atom Feed Poller
-# Author: Srivats P. <pstavirs>
-# Based on Mozilla's HgPoller
-#     http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/tools/buildbot/buildbot/changes/Attic/hgpoller.py&revision=1.1.4.2
-# see http://code.google.com/p/pitaara/
-
-from time import strptime
-from calendar import timegm 
-from xml.dom import minidom, Node
-
-from twisted.python import log, failure
-from twisted.internet import defer, reactor
-from twisted.internet.task import LoopingCall
-from twisted.web.client import getPage
-
-from buildbot.changes import base, changes
-
-class GoogleCodeAtomPoller(base.ChangeSource):
-    """This source will poll a GoogleCode Atom feed for changes and 
-    submit them to the change master. Works for both Svn and Hg repos.
-    TODO: branch processing
-    """
-
-    compare_attrs = ['feedurl', 'pollinterval']
-    parent = None
-    loop = None
-    volatile = ['loop']
-    working = False
-    
-    def __init__(self, feedurl, pollinterval=3600):
-        """
-        @type   feedurl:        string
-        @param  feedurl:        The Atom feed URL of the GoogleCode repo
-                                (e.g. http://code.google.com/feeds/p/ostinato/hgchanges/basic)
-
-        @type   pollinterval:   int
-        @param  pollinterval:   The time (in seconds) between queries for
-                                changes (default is 1 hour)
-        """
-        
-        self.feedurl = feedurl
-        self.branch = None
-        self.pollinterval = pollinterval
-        self.lastChange = None
-        self.loop = LoopingCall(self.poll)
-    
-    def startService(self):
-        log.msg("GoogleCodeAtomPoller starting")
-        base.ChangeSource.startService(self)
-        reactor.callLater(0, self.loop.start, self.pollinterval)
-
-    def stopService(self):
-        log.msg("GoogleCodeAtomPoller stoppping")
-        self.loop.stop()
-        return base.ChangeSource.stopService(self)
-    
-    def describe(self):
-        return "Getting changes from the GoogleCode repo changes feed %s" % \
-               self._make_url()
-    
-    def poll(self):
-        if self.working:
-            log.msg("Not polling because last poll is still working")
-        else:
-            self.working = True
-            d = self._get_changes()
-            d.addCallback(self._process_changes)
-            d.addCallbacks(self._finished_ok, self._finished_failure)
-
-    def _finished_ok(self, res):
-        assert self.working
-        self.working = False
-        log.msg("GoogleCodeAtomPoller poll success")
-
-        return res
-
-    def _finished_failure(self, res):
-        log.msg("GoogleCodeAtomPoller poll failed: %s" % res)
-        assert self.working
-        self.working = False
-        return None
-
-    def _make_url(self):
-        return "%s" % (self.feedurl)
-    
-    def _get_changes(self):
-        url = self._make_url()
-        log.msg("GoogleCodeAtomPoller polling %s" % url)
-        
-        return getPage(url, timeout=self.pollinterval)
-
-    def _parse_changes(self, query):
-        dom = minidom.parseString(query)
-        entries = dom.getElementsByTagName("entry")
-        changes = []
-        # Entries come in reverse chronological order
-        for i in entries:
-            d = {}
-
-            # revision is the last part of the 'id' url
-            d["revision"] = i.getElementsByTagName("id")[0] \
-                             .firstChild.data.split('/')[-1]
-            if d["revision"] == self.lastChange:
-                break  # no more new changes
-
-            d["when"] = timegm(strptime(
-        		i.getElementsByTagName("updated")[0].firstChild.data,
-	        	"%Y-%m-%dT%H:%M:%SZ"))
-            d["author"] = i.getElementsByTagName("author")[0] \
-                           .getElementsByTagName("name")[0].firstChild.data
-            # files and commit msg are separated by 2 consecutive <br/>
-            content = i.getElementsByTagName("content")[0].firstChild.data \
-                       .split("<br/>\n <br/>")
-            # Remove the action keywords from the file list
-            fl = content[0].replace( \
-                u' \xa0\xa0\xa0\xa0Add\xa0\xa0\xa0\xa0', '').replace( \
-                u' \xa0\xa0\xa0\xa0Delete\xa0\xa0\xa0\xa0', '').replace( \
-                u' \xa0\xa0\xa0\xa0Modify\xa0\xa0\xa0\xa0', '')
-            # Get individual files and remove the 'header'
-            d["files"] = fl.encode("ascii", "replace").split("<br/>")[1:]
-            d["files"] = [f.strip() for f in d["files"]]
-            try:
-                d["comments"] = content[1].encode("ascii", "replace")
-            except:
-                d["comments"] = "No commit message provided" 
-
-            changes.append(d)
-
-        changes.reverse() # want them in chronological order
-        return changes
-    
-    def _process_changes(self, query):
-        change_list = self._parse_changes(query)
-
-        # Skip calling addChange() if this is the first successful poll.
-        if self.lastChange is not None:
-            for change in change_list:
-                c = changes.Change(revision = change["revision"],
-                                   who = change["author"],
-                                   files = change["files"], 
-                                   comments = change["comments"],
-                                   when = change["when"],
-                                   branch = self.branch)
-                self.parent.addChange(c)
-        if change_list:
-            self.lastChange = change_list[-1]["revision"]
deleted file mode 100755
--- a/contrib/hg_buildbot.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#! /usr/bin/python
-
-# This is a script which delivers Change events from Mercurial to the
-# buildmaster each time a changeset is pushed into a repository. Add it to
-# the 'incoming' commit hook on your canonical "central" repository, by
-# putting something like the following in the .hg/hgrc file of that
-# repository:
-#
-#  [hooks]
-#  incoming.buildbot = /PATH/TO/hg_buildbot.py BUILDMASTER:PORT
-#
-# Note that both Buildbot and Mercurial must be installed on the repository
-# machine.
-
-import os
-import sys
-import commands
-
-from StringIO import StringIO
-from buildbot.scripts import runner
-
-MASTER = sys.argv[1]
-
-CHANGESET_ID = os.environ["HG_NODE"]
-
-# TODO: consider doing 'import mercurial.hg' and extract this information
-# using the native python
-out = commands.getoutput(
-    "hg log -r %s --template '{author}\n{files}\n{desc}'" % CHANGESET_ID)
-
-s = StringIO(out)
-user = s.readline().strip()
-# NOTE: this fail when filenames contain spaces. I cannot find a way to get
-# hg to use some other filename separator.
-files = s.readline().strip().split()
-comments = "".join(s.readlines())
-
-change = {
-    'master': MASTER,
-    # note: this is more likely to be a full email address, which would make
-    # the left-hand "Changes" column kind of wide. The buildmaster should
-    # probably be improved to display an abbreviation of the username.
-    'username': user,
-    'revision': CHANGESET_ID,
-    'comments': comments,
-    'files': files,
-}
-
-runner.sendchange(change, True)
deleted file mode 100644
--- a/contrib/os-x/README
+++ /dev/null
@@ -1,23 +0,0 @@
-Mark Pauley contributed the two launchd plist files for OS-X (10.4+) to start
-a buildmaster or buildslave automatically at startup:
-
- contrib/OS-X/net.sourceforge.buildbot.master.plist
- contrib/OS-X/net.sourceforge.buildbot.slave.plist
-
-His email message is as follows:
-
-  Message-Id: <C0E57556-0432-4EB6-9A6C-22CDC72208E9@apple.com>
-  From: Mark Pauley <mpauley@apple.com>
-  To: buildbot-devel <buildbot-devel@lists.sourceforge.net>
-  Date: Wed, 24 Jan 2007 11:05:44 -0800
-  Subject: [Buildbot-devel] Sample buildbot launchd plists for MacOS 10.4+
-
-  Hi guys,
-  	I've had these kicking around for a while and thought that maybe
-  someone would like to see them.  Installing either of these two to /
-  Library/LaunchDaemons will cause the bulidbot slave or master to auto-
-  start as whatever user you like on launch.  This is the "right way to
-  do this" going forward, startupitems are deprecated.  Please note that
-  this means any tests that require a windowserver connection on os x
-  won't work.
-
deleted file mode 100644
--- a/contrib/os-x/net.sourceforge.buildbot.master.plist
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd 
-">
-<plist version="1.0">
-<dict>
-         <key>Label</key>
-         <string>net.sourceforge.buildbot.slave</string>
-
-         <!-- Change this to the user you want to run buildbot as -->
-         <key>UserName</key>
-         <string>buildbot</string>
-
-         <!-- Change this to your buildbot working directory -->
-         <key>WorkingDirectory</key>
-         <string>/Users/buildbot/Buildbot_Master</string>
-
-         <key>ProgramArguments</key>
-         <array>
-                 <string>/usr/bin/twistd</string>
-                 <string>--nodaemon</string>
-                 <string>--python=buildbot.tac</string>
-                 <string>--logfile=buildbot.log</string>
-                 <string>--prefix=master</string>
-         </array>
-
-         <!-- Hack to keep buildbot running even if it crashes -->
-         <key>QueueDirectories</key>
-         <array> <string>/</string> </array>
-
-	<key>KeepAlive</key>
-         <dict>
-                 <key>SuccessfulExit</key>
-                 <false/>
-         </dict>
-
-         <key>RunAtLoad</key>
-         <true/>
-
-         <key>StandardErrorPath</key>
-         <string>/var/log/build_master.log</string>
-</dict>
-</plist>
deleted file mode 100644
--- a/contrib/os-x/net.sourceforge.buildbot.slave.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd 
-">
-<plist version="1.0">
-<dict>
-         <key>Label</key>
-         <string>net.sourceforge.buildbot.slave</string>
-
-         <!-- Change this to the user you want to run buildbot as -->
-         <key>UserName</key>
-         <string>buildbot</string>
-
-         <!-- Change this to your buildbot working directory -->
-         <key>WorkingDirectory</key>
-         <string>/Users/buildbot/Buildbot_Slave</string>
-
-         <key>ProgramArguments</key>
-         <array>
-                 <string>/usr/bin/twistd</string>
-                 <string>--nodaemon</string>
-                 <string>--python=buildbot.tac</string>
-                 <string>--logfile=buildbot.log</string>
-                 <string>--prefix=slave</string>
-         </array>
-
-         <key>KeepAlive</key>
-         <dict>
-                 <key>SuccessfulExit</key>
-                 <false/>
-         </dict>
-
-         <key>RunAtLoad</key>
-         <true/>
-
-</dict>
-</plist>
deleted file mode 100755
--- a/contrib/run_maxq.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env jython
-
-import sys
-import glob
-
-testdir = sys.argv[1]
-
-orderfiles = glob.glob(testdir + '/*.tests')
-
-# wee. just be glad I didn't make this one gigantic nested listcomp.
-# anyway, this builds a once-nested list of files to test.
-
-#open!
-files = [open(fn) for fn in orderfiles]
-
-#create prelim list of lists of files!
-files = [f.readlines() for f in files]
-
-#shwack newlines and filter out empties!
-files = [filter(None, [fn.strip() for fn in fs]) for fs in files]
-
-#prefix with testdir
-files = [[testdir + '/' + fn.strip() for fn in fs] for fs in files]
-
-print "Will run these tests:", files
-
-i = 0
-
-for testlist in files:
-
-    print "==========================="
-    print "running tests from testlist", orderfiles[i]
-    print "---------------------------"
-    i = i + 1
-
-    for test in testlist:
-        print "running test", test
-
-        try:
-            execfile(test, globals().copy())
-
-        except:
-            ei = sys.exc_info()
-            print "TEST FAILURE:", ei[1]
-
-        else:
-            print "SUCCESS"
deleted file mode 100755
--- a/contrib/svn_buildbot.py
+++ /dev/null
@@ -1,260 +0,0 @@
-#!/usr/bin/python
-
-# this requires python >=2.3 for the 'sets' module.
-
-# The sets.py from python-2.3 appears to work fine under python2.2 . To
-# install this script on a host with only python2.2, copy
-# /usr/lib/python2.3/sets.py from a newer python into somewhere on your
-# PYTHONPATH, then edit the #! line above to invoke python2.2
-
-# python2.1 is right out
-
-# If you run this program as part of your SVN post-commit hooks, it will
-# deliver Change notices to a buildmaster that is running a PBChangeSource
-# instance.
-
-# edit your svn-repository/hooks/post-commit file, and add lines that look
-# like this:
-
-'''
-# set up PYTHONPATH to contain Twisted/buildbot perhaps, if not already
-# installed site-wide
-. ~/.environment
-
-/path/to/svn_buildbot.py --repository "$REPOS" --revision "$REV" \
---bbserver localhost --bbport 9989
-'''
-
-import commands
-import sys
-import os
-import re
-import sets
-
-# We have hackish "-d" handling here rather than in the Options
-# subclass below because a common error will be to not have twisted in
-# PYTHONPATH; we want to be able to print that error to the log if
-# debug mode is on, so we set it up before the imports.
-
-DEBUG = None
-
-if '-d' in sys.argv:
-    i = sys.argv.index('-d')
-    DEBUG = sys.argv[i+1]
-    del sys.argv[i]
-    del sys.argv[i]
-
-if DEBUG:
-    f = open(DEBUG, 'a')
-    sys.stderr = f
-    sys.stdout = f
-
-
-from twisted.internet import defer, reactor
-from twisted.python import usage
-from twisted.spread import pb
-from twisted.cred import credentials
-
-
-class Options(usage.Options):
-    optParameters = [
-        ['repository', 'r', None,
-         "The repository that was changed."],
-        ['revision', 'v', None,
-         "The revision that we want to examine (default: latest)"],
-        ['bbserver', 's', 'localhost',
-         "The hostname of the server that buildbot is running on"],
-        ['bbport', 'p', 8007,
-         "The port that buildbot is listening on"],
-        ['include', 'f', None,
-         '''\
-Search the list of changed files for this regular expression, and if there is
-at least one match notify buildbot; otherwise buildbot will not do a build.
-You may provide more than one -f argument to try multiple
-patterns.  If no filter is given, buildbot will always be notified.'''],
-        ['filter', 'f', None, "Same as --include.  (Deprecated)"],
-        ['exclude', 'F', None,
-         '''\
-The inverse of --filter.  Changed files matching this expression will never
-be considered for a build.
-You may provide more than one -F argument to try multiple
-patterns.  Excludes override includes, that is, patterns that match both an
-include and an exclude will be excluded.'''],
-        ]
-    optFlags = [
-        ['dryrun', 'n', "Do not actually send changes"],
-        ]
-
-    def __init__(self):
-        usage.Options.__init__(self)
-        self._includes = []
-        self._excludes = []
-        self['includes'] = None
-        self['excludes'] = None
-
-    def opt_include(self, arg):
-        self._includes.append('.*%s.*' % (arg, ))
-
-    opt_filter = opt_include
-
-    def opt_exclude(self, arg):
-        self._excludes.append('.*%s.*' % (arg, ))
-
-    def postOptions(self):
-        if self['repository'] is None:
-            raise usage.error("You must pass --repository")
-        if self._includes:
-            self['includes'] = '(%s)' % ('|'.join(self._includes), )
-        if self._excludes:
-            self['excludes'] = '(%s)' % ('|'.join(self._excludes), )
-
-
-def split_file_dummy(changed_file):
-    """Split the repository-relative filename into a tuple of (branchname,
-    branch_relative_filename). If you have no branches, this should just
-    return (None, changed_file).
-    """
-    return (None, changed_file)
-
-
-# this version handles repository layouts that look like:
-#  trunk/files..                  -> trunk
-#  branches/branch1/files..       -> branches/branch1
-#  branches/branch2/files..       -> branches/branch2
-#
-
-
-def split_file_branches(changed_file):
-    pieces = changed_file.split(os.sep)
-    if pieces[0] == 'branches':
-        return (os.path.join(*pieces[:2]),
-                os.path.join(*pieces[2:]))
-    if pieces[0] == 'trunk':
-        return (pieces[0], os.path.join(*pieces[1:]))
-    ## there are other sibilings of 'trunk' and 'branches'. Pretend they are
-    ## all just funny-named branches, and let the Schedulers ignore them.
-    #return (pieces[0], os.path.join(*pieces[1:]))
-
-    raise RuntimeError("cannot determine branch for '%s'" % changed_file)
-
-
-split_file = split_file_dummy
-
-
-class ChangeSender:
-
-    def getChanges(self, opts):
-        """Generate and stash a list of Change dictionaries, ready to be sent
-        to the buildmaster's PBChangeSource."""
-
-        # first we extract information about the files that were changed
-        repo = opts['repository']
-        print "Repo:", repo
-        rev_arg = ''
-        if opts['revision']:
-            rev_arg = '-r %s' % (opts['revision'], )
-        changed = commands.getoutput('svnlook changed %s "%s"' % (
-            rev_arg, repo)).split('\n')
-        # the first 4 columns can contain status information
-        changed = [x[4:] for x in changed]
-
-        message = commands.getoutput('svnlook log %s "%s"' % (rev_arg, repo))
-        who = commands.getoutput('svnlook author %s "%s"' % (rev_arg, repo))
-        revision = opts.get('revision')
-        if revision is not None:
-            revision = str(int(revision))
-
-        # see if we even need to notify buildbot by looking at filters first
-        changestring = '\n'.join(changed)
-        fltpat = opts['includes']
-        if fltpat:
-            included = sets.Set(re.findall(fltpat, changestring))
-        else:
-            included = sets.Set(changed)
-
-        expat = opts['excludes']
-        if expat:
-            excluded = sets.Set(re.findall(expat, changestring))
-        else:
-            excluded = sets.Set([])
-        if len(included.difference(excluded)) == 0:
-            print changestring
-            print """\
-    Buildbot was not interested, no changes matched any of these filters:\n %s
-    or all the changes matched these exclusions:\n %s\
-    """ % (fltpat, expat)
-            sys.exit(0)
-
-        # now see which branches are involved
-        files_per_branch = {}
-        for f in changed:
-            branch, filename = split_file(f)
-            if branch in files_per_branch.keys():
-                files_per_branch[branch].append(filename)
-            else:
-                files_per_branch[branch] = [filename]
-
-        # now create the Change dictionaries
-        changes = []
-        for branch in files_per_branch.keys():
-            d = {'who': who,
-                 'branch': branch,
-                 'files': files_per_branch[branch],
-                 'comments': message,
-                 'revision': revision}
-            changes.append(d)
-
-        return changes
-
-    def sendChanges(self, opts, changes):
-        pbcf = pb.PBClientFactory()
-        reactor.connectTCP(opts['bbserver'], int(opts['bbport']), pbcf)
-        d = pbcf.login(credentials.UsernamePassword('change', 'changepw'))
-        d.addCallback(self.sendAllChanges, changes)
-        return d
-
-    def sendAllChanges(self, remote, changes):
-        dl = [remote.callRemote('addChange', change)
-              for change in changes]
-        return defer.DeferredList(dl)
-
-    def run(self):
-        opts = Options()
-        try:
-            opts.parseOptions()
-        except usage.error, ue:
-            print opts
-            print "%s: %s" % (sys.argv[0], ue)
-            sys.exit()
-
-        changes = self.getChanges(opts)
-        if opts['dryrun']:
-            for i, c in enumerate(changes):
-                print "CHANGE #%d" % (i+1)
-                keys = c.keys()
-                keys.sort()
-                for k in keys:
-                    print "[%10s]: %s" % (k, c[k])
-            print "*NOT* sending any changes"
-            return
-
-        d = self.sendChanges(opts, changes)
-
-        def quit(*why):
-            print "quitting! because", why
-            reactor.stop()
-
-        def failed(f):
-            print "FAILURE"
-            print f
-            reactor.stop()
-
-        d.addCallback(quit, "SUCCESS")
-        d.addErrback(failed)
-        reactor.callLater(60, quit, "TIMEOUT")
-        reactor.run()
-
-
-if __name__ == '__main__':
-    s = ChangeSender()
-    s.run()
deleted file mode 100755
--- a/contrib/svn_watcher.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/python
-
-# This is a program which will poll a (remote) SVN repository, looking for
-# new revisions. It then uses the 'buildbot sendchange' command to deliver
-# information about the Change to a (remote) buildmaster. It can be run from
-# a cron job on a periodic basis, or can be told (with the 'watch' option) to
-# automatically repeat its check every 10 minutes.  
-
-# This script does not store any state information, so to avoid spurious
-# changes you must use the 'watch' option and let it run forever.
-
-# You will need to provide it with the location of the buildmaster's
-# PBChangeSource port (in the form hostname:portnum), and the svnurl of the
-# repository to watch.
-
-
-# 15.03.06 by John Pye
-# 29.03.06 by Niklaus Giger, added support to run under windows,
-# added invocation option
-# 22.03.10 by Johnnie Pittman, added support for category and interval
-# options.
-
-import subprocess
-import xml.dom.minidom
-from xml.parsers.expat import ExpatError
-import sys
-import time
-from optparse import OptionParser
-import os
-
-
-if sys.platform == 'win32':
-    import win32pipe
-
-
-def getoutput(cmd):
-    p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
-    return p.stdout.read()
-
-
-def sendchange_cmd(master, revisionData):
-    cmd = [
-        "buildbot", 
-        "sendchange",
-        "--master=%s" % master,
-        "--revision=%s" % revisionData['revision'],
-        "--username=%s" % revisionData['author'],
-        "--comments=%s" % revisionData['comments'],
-        ]
-    if opts.category:
-        cmd.append("--category=%s" % opts.category)
-    for path in revisionData['paths']:
-        cmd.append(path)
-        
-
-    if opts.verbose == True:
-        print cmd
-        
-    return cmd 
-
-def parseChangeXML(raw_xml):
-    """Parse the raw xml and return a dict with key pairs set.
-    
-    Commmand we're parsing:
-
-    svn log --non-interactive --xml --verbose --limit=1 <repo url>
-
-    With an output that looks like this:
-
-    <?xml version="1.0"?>
-     <log>
-      <logentry revision="757">
-       <author>mwiggins</author>
-       <date>2009-11-11T17:16:48.012357Z</date>
-       <paths>
-        <path kind="" copyfrom-path="/trunk" copyfrom-rev="756" action="A">/tags/Latest</path>
-       </paths>
-       <msg>Updates/latest</msg>
-      </logentry>
-     </log>
-    """
-    
-    data = dict()
-    
-    # parse the xml string and grab the first log entry.
-    try:
-        doc = xml.dom.minidom.parseString(raw_xml)
-    except ExpatError:
-        print "\nError: Got an empty response with an empty changeset.\n"
-        raise
-    log_entry = doc.getElementsByTagName("logentry")[0]
-
-    # grab the appropriate meta data we need
-    data['revision'] = log_entry.getAttribute("revision")
-    data['author'] = "".join([t.data for t in
-                              log_entry.getElementsByTagName("author")[0].childNodes])
-    data['comments'] = "".join([t.data for t in
-                                log_entry.getElementsByTagName("msg")[0].childNodes])
-    
-    # grab the appropriate file paths that changed.
-    pathlist = log_entry.getElementsByTagName("paths")[0]
-    paths = []
-    for path in pathlist.getElementsByTagName("path"):
-        paths.append("".join([t.data for t in path.childNodes]))
-    data['paths'] = paths
-    
-    return data
-
-
-def checkChanges(repo, master, oldRevision=-1):
-    cmd = ["svn", "log", "--non-interactive", "--xml", "--verbose",
-           "--limit=1", repo]
-    
-    if opts.verbose == True:
-        print "Getting last revision of repository: " + repo
-
-    if sys.platform == 'win32':
-        f = win32pipe.popen(cmd)
-        xml1 = ''.join(f.readlines())
-        f.close()
-    else:
-        xml1 = getoutput(cmd)
-
-    if opts.verbose == True:
-        print "XML\n-----------\n"+xml1+"\n\n"
-
-    revisionData = parseChangeXML(xml1)
-
-    if opts.verbose == True:
-        print "PATHS"
-        print revisionData['paths']
-
-    if  revisionData['revision'] != oldRevision:
-        
-        cmd = sendchange_cmd(master, revisionData)
-
-        if sys.platform == 'win32':
-            f = win32pipe.popen(cmd)
-            pretty_time = time.strftime("%H.%M.%S ") 
-            print "%s Revision %s: %s" % (pretty_time, revisionData['revision'], 
-                                          ''.join(f.readlines()))
-            f.close()
-        else:
-            xml1 = getoutput(cmd)
-    else:
-        pretty_time = time.strftime("%H.%M.%S ")
-        print "%s nothing has changed since revision %s" % (pretty_time, 
-                                                            revisionData['revision'])
-
-    return revisionData['revision']
-
-def build_parser():
-    usagestr = "%prog [options] <repo url> <buildbot master:port>"
-    parser = OptionParser(usage=usagestr)
-    
-    parser.add_option(
-        "-c", "--category", dest="category", action="store", default="",
-        help="""Store a category name to be associated with sendchange msg."""
-        )
-
-    parser.add_option(
-        "-i", "--interval", dest="interval", action="store", default=0,
-        help="Implies watch option and changes the time in minutes to the value specified.",
-        )
-
-    parser.add_option(
-        "-v", "--verbose", dest="verbose", action="store_true", default=False,
-        help="Enables more information to be presented on the command line.",
-        )
-
-    parser.add_option(
-        "", "--watch", dest="watch", action="store_true", default=False,
-        help="Automatically check the repo url every 10 minutes.",
-        )
-    
-    return parser
-
-def validate_args(args):
-    """Validate our arguments and exit if we don't have what we want."""
-    if not args:
-        print "\nError: No arguments were specified.\n"
-        parser.print_help()
-        sys.exit(1)
-    elif len(args) > 2:
-        print "\nToo many arguments specified.\n"
-        parser.print_help()
-        sys.exit(2)
-    
-
-if __name__ == '__main__':
-
-    # build our parser and validate our args
-    parser = build_parser()
-    (opts, args) = parser.parse_args()
-    validate_args(args)
-    if opts.interval:
-        try:
-            int(opts.interval)
-        except ValueError:
-            print "\nError: Value of the interval option must be a number."
-            parser.print_help()
-            sys.exit(3)
-
-    # grab what we need
-    repo_url = args[0]
-    bbmaster = args[1]
-
-    # if watch is specified, run until stopped
-    if opts.watch or opts.interval:
-        oldRevision = -1
-        print "Watching for changes in repo %s for master %s." % (repo_url, bbmaster)
-        while 1:
-            try:
-                oldRevision = checkChanges(repo_url, bbmaster, oldRevision)
-            except ExpatError:
-                # had an empty changeset.  Trapping the exception and moving on.
-                pass
-            try:
-                if opts.interval:
-                    # Check the repository every interval in minutes the user specified.
-                    time.sleep(int(opts.interval) * 60)
-                else:
-                    # Check the repository every 10 minutes
-                    time.sleep(10*60)
-            except KeyboardInterrupt:
-                print "\nReceived interrupt via keyboard.  Shutting Down."
-                sys.exit(0)
-
-    # default action if watch isn't specified 
-    checkChanges(repo_url, bbmaster)
deleted file mode 100755
--- a/contrib/svnpoller.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python
-"""
- svn.py
- Script for BuildBot to monitor a remote Subversion repository.
- Copyright (C) 2006 John Pye
-"""
-# This script is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-
-import commands
-import xml.dom.minidom
-import ConfigParser
-import os.path
-
-# change these settings to match your project
-svnurl = "https://pse.cheme.cmu.edu/svn/ascend/code/trunk"
-statefilename = "~/changemonitor/config.ini"
-buildmaster = "buildbot.example.org:9989" # connects to a PBChangeSource
-
-xml1 = commands.getoutput(
-    "svn log --non-interactive --verbose --xml --limit=1 " + svnurl)
-#print "XML\n-----------\n"+xml1+"\n\n"
-
-try:
-    doc = xml.dom.minidom.parseString(xml1)
-    el = doc.getElementsByTagName("logentry")[0]
-    revision = el.getAttribute("revision")
-    author = "".join([t.data for t in el.getElementsByTagName(
-        "author")[0].childNodes])
-    comments = "".join([t.data for t in el.getElementsByTagName(
-        "msg")[0].childNodes])
-
-    pathlist = el.getElementsByTagName("paths")[0]
-    paths = []
-    for p in pathlist.getElementsByTagName("path"):
-        paths.append("".join([t.data for t in p.childNodes]))
-    #print "PATHS"
-    #print paths
-except xml.parsers.expat.ExpatError, e:
-    print "FAILED TO PARSE 'svn log' XML:"
-    print str(e)
-    print "----"
-    print "RECEIVED TEXT:"
-    print xml1
-    import sys
-    sys.exit(1)
-
-fname = statefilename
-fname = os.path.expanduser(fname)
-ini = ConfigParser.SafeConfigParser()
-
-try:
-    ini.read(fname)
-except:
-    print "Creating changemonitor config.ini:", fname
-    ini.add_section("CurrentRevision")
-    ini.set("CurrentRevision", -1)
-
-try:
-    lastrevision = ini.get("CurrentRevision", "changeset")
-except ConfigParser.NoOptionError:
-    print "NO OPTION FOUND"
-    lastrevision = -1
-except ConfigParser.NoSectionError:
-    print "NO SECTION FOUND"
-    lastrevision = -1
-
-if lastrevision != revision:
-
-    #comments = codecs.encodings.unicode_escape.encode(comments)
-    cmd = "buildbot sendchange --master="+buildmaster+" --branch=trunk \
---revision=\""+revision+"\" --username=\""+author+"\" --comments=\""+\
-comments+"\" "+" ".join(paths)
-
-    #print cmd
-    res = commands.getoutput(cmd)
-
-    print "SUBMITTING NEW REVISION", revision
-    if not ini.has_section("CurrentRevision"):
-        ini.add_section("CurrentRevision")
-    try:
-        ini.set("CurrentRevision", "changeset", revision)
-        f = open(fname, "w")
-        ini.write(f)
-        #print "WROTE CHANGES TO",fname
-    except:
-        print "FAILED TO RECORD INI FILE"
deleted file mode 100644
--- a/contrib/trac/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# What Is It?
-BuildBot Watcher is a [Trac](http://trac.edgewall.org) plugin. It watches a
-BuildBot status webserver and incorporates build information into the
-standard Trac timeline.
-
-# Prereqs
-## For the Trac site
-This plugin does not require anything other than Trac 0.11+. It makes use
-of the standard Trac CSS classes, so it will theme appropriately.
-
-## For the BuildMaster
-For now, you'll need to run a BuildBot using my patched XML-RPC server.
-
-	git clone git://github.com/djmitche/buildbot.git buildbot
-	cd buildbot
-	git pull git://github.com/rbosetti/buildbot.git
-
-# Installation
-Follow the standard fetch, cook, copy procedure:
-
-	git clone git://github.com/rbosetti/buildbot.git buildbot
-	cd buildbot
-	python setup.py bdist_egg
-	cp dist/*.egg /path/to/trac/env/plugins
deleted file mode 100644
--- a/contrib/trac/TODO.md
+++ /dev/null
@@ -1,6 +0,0 @@
-The plan is to eventually offer the same controls that webstatus does.
-
-# Missing
- * Force Builds
- * The grid display
- * The waterfall display (replaced by a Timeline contributor for Trac)
deleted file mode 100644
--- a/contrib/trac/bbwatcher/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-__version__ = '0.1'
deleted file mode 100644
--- a/contrib/trac/bbwatcher/api.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import xmlrpclib
-import urlparse
-
-from model import Builder, Build
-
-class BuildBotSystem(object):
-	def __init__(self, url):
-		try:
-			scheme, loc, _, _, _ = urlparse.urlsplit(url, scheme='http')
-			url = '%s://%s/xmlrpc'%(scheme, loc)
-			self.server = xmlrpclib.ServerProxy(url)
-		except Exception, e:
-			raise ValueError('Invalid BuildBot XML-RPC server %s: %s'%(url, e))
-	def getAllBuildsInInterval(self, start, stop):
-		return self.server.getAllBuildsInInterval(start, stop)
-	def getBuilder(self, name):
-		builds = []
-		for i in range(1, 5+1):
-			try:
-				builds.append(Build(self.server.getBuild(name, -i)))
-			except Exception, e:
-				self.env.log.debug('Cannot fetch build-info: %s'%(e))
-				break
-		return Builder(name, builds, [])
-	def getAllBuilders(self):
-		return self.server.getAllBuilders()
deleted file mode 100644
--- a/contrib/trac/bbwatcher/model.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from datetime import datetime
-from trac.util.datefmt import utc
-
-class Builder(object):
-	def __init__(self, name, builds, slaves):
-		self.name = name
-		self.current = builds[0]
-		self.recent = builds
-		self.slaves = slaves
-
-class Build(object):
-	def __init__(self, build_results):
-		for attr in ('builder_name', 'reason', 'slavename', 'results',
-					'text', 'start', 'end', 'steps', 'branch', 'revision', 'number'):
-			setattr(self, attr, build_results.get(attr, 'UNDEFINED'))
-		try:
-			self.start = datetime.fromtimestamp(self.start, utc)
-			self.end = datetime.fromtimestamp(self.end, utc)
-		except Exception, e:
-			pass
-	def __str__(self):
-		return 'Slave <%s>'%(self.slave)
deleted file mode 100644
--- a/contrib/trac/bbwatcher/templates/bbw_allbuilders.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html
-    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:py="http://genshi.edgewall.org/"
-      xmlns:xi="http://www.w3.org/2001/XInclude">
-  <xi:include href="layout.html" />
-  <xi:include href="macros.html" />
-  <head>
-    <title py:if="title">$title</title>
-    <meta py:if="version" name="ROBOTS" content="NOINDEX, NOFOLLOW" />
-  </head>
-
-  <body>
-    <div id="content">
-      <h1>Active Builders</h1>
-      <ol py:if="names">
-        <li py:for="name in names">
-          <a href="${href.buildbot('builder/'+name)}">${name}</a>
-        </li>
-      </ol>
-    </div>
-  </body>
-</html>
deleted file mode 100644
--- a/contrib/trac/bbwatcher/templates/bbw_builder.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html
-    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:py="http://genshi.edgewall.org/"
-      xmlns:xi="http://www.w3.org/2001/XInclude">
-  <xi:include href="layout.html" />
-  <xi:include href="macros.html" />
-  <head>
-    <title py:if="title">$title</title>
-    <meta py:if="version" name="ROBOTS" content="NOINDEX, NOFOLLOW" />
-  </head>
-
-  <body>
-    <div id="content">
-      <h1>Builder: ${builder.name}</h1>
-      <h2 py:if="builder.current">Running Build</h2>
-      <div>
-        <ul style="list-style: none">
-          <li>Slave: ${builder.current.slavename}</li>
-          <li>Revision: ${wiki_to_oneliner(context, '[wiki:TryBuildUsage Forced Build]')}</li>
-          <li>Status: <strong>${builder.current.results and 'failed' or 'successful'}</strong></li>
-        </ul>
-      </div>
-      <h2>Recent Builds</h2>
-      <div py:if="builder.recent" id="changelog">
-        <div py:for="build in builder.recent" class="comment" xml:space="preserve">
-            (${format_date(build.end)}) rev=[${build.branch or 'trunk'}@${build.revision and href.changeset(build.revision) or '??'}] <a href="${href.buildbot('builder/%s/build/%s'%(build.builder_name, build.number))}">#${build.number}</a><blockquote>${build.reason}</blockquote>
-        </div>
-      </div>
-      <div py:if="builder.slaves">
-        <h2>Buildslaves</h2>
-        <ol>
-          <li py:for="slave in builder.slaves">
-            <div>Status: ${slave.connected and 'Connected' or 'Disconnected'}</div>
-            <div>Admin: ${author_info(slave.admin)}</div>
-            <div>Host: <pre>${slave.description}</pre></div>
-          </li>
-        </ol>
-      </div>
-    </div>
-  </body>
-</html>
deleted file mode 100644
--- a/contrib/trac/bbwatcher/templates/bbw_welcome.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html
-    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:py="http://genshi.edgewall.org/"
-      xmlns:xi="http://www.w3.org/2001/XInclude">
-  <xi:include href="layout.html" />
-  <xi:include href="macros.html" />
-  <head>
-    <title py:if="title">$title</title>
-    <meta py:if="version" name="ROBOTS" content="NOINDEX, NOFOLLOW" />
-  </head>
-
-  <body>
-    <div id="content">
-      <h1>BuildBot Watcher</h1>
-      <p class="wiki">This Trac instance is watching the BuildBot server at <pre>${url}</pre>.</p>
-      <h2>For now, you can obtain information about:</h2>
-      <ul>
-        <li><a href="${href.buildbot('builder')}">All Builders</a></li>
-      </ul>
-    </div>
-  </body>
-</html>
deleted file mode 100644
--- a/contrib/trac/bbwatcher/web_ui.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import pkg_resources
-import re
-
-from genshi.builder import tag
-
-from trac.core import Component, implements
-from trac.config import Option
-from trac.wiki.formatter import format_to_oneliner
-from trac.util.datefmt import to_timestamp, to_datetime
-from trac.mimeview.api import Context
-
-# Interfaces
-from trac.timeline.api import ITimelineEventProvider
-from trac.web import IRequestHandler
-from trac.web.chrome import INavigationContributor, ITemplateProvider
-
-from api import BuildBotSystem
-
-class TracBuildBotWatcher(Component):
-	implements(ITimelineEventProvider, IRequestHandler, ITemplateProvider,
-		INavigationContributor)
-	buildbot_url = Option('bbwatcher', 'buildmaster', '127.0.0.1:8010',
-		'The location of the BuildBot webserver. Do not include the /xmlrpc')
-
-	BUILDER_REGEX = r'/buildbot/builder(?:/(.+))?$'
-	BUILDER_RE = re.compile(BUILDER_REGEX)
-	# Template Provider
-	def get_htdocs_dirs(self):
-		return []
-	def get_templates_dirs(self):
-		return [pkg_resources.resource_filename('bbwatcher', 'templates')]
-
-	# Nav Contributor
-	def get_active_navigation_item(self, req):
-		return 'buildbot'
-	def get_navigation_items(self, req):
-		yield 'mainnav', 'buildbot', tag.a('BuildBot',href=req.href.buildbot())
-
-	# Timeline Methods
-	def get_timeline_filters(self, req):
-		yield  ('bbwatcher', 'Builds', False)
-
-	def get_timeline_events(self, req, start, stop, filters):
-		#if not 'bbwatcher' in filters:
-		#	return
-		try:
-			master = BuildBotSystem(self.buildbot_url)
-		except Exception, e:
-			print 'Error hitting BuildBot', e
-			return
-		# This was a comprehension: the loop is clearer
-		for build in master.getAllBuildsInInterval(to_timestamp(start), to_timestamp(stop)):
-			# BuildBot builds are reported as
-			# (builder_name, num, end, branch, rev, results, text)
-			print 'Reporting build', build
-			yield ('build', to_datetime(build[2]), '', build)
-
-	def render_timeline_event(self, context, field, event):
-		builder_name, num, end, branch, rev, results, text = event[3]
-		if field == 'url':
-			return None
-		elif field == 'title':
-			return tag('Build ', tag.a('#%s'%num, href=context.href.buildbot('builder/%s/%s'%(builder_name, num))),
-				' of ', builder_name, ' ', results == 'success' and tag.span('passed', style="color: #080") or tag.span('failed', style="color: #f00"))
-		elif field == 'description':
-			return format_to_oneliner(self.env, context, 'Built from %s'%(rev and 'r%s sources'%rev or 'local changes (see TryBuildUsage)'))
-
-	# RequestHandler
-	def _handle_builder(self, req):
-		m = self.BUILDER_RE.match(req.path_info)
-		try:
-			builder = m.group(1) or None
-		except Exception, e:
-			builder = None
-		master = BuildBotSystem(self.buildbot_url)
-		if builder is None:
-			data = { 'names': master.getAllBuilders() }
-			return 'bbw_allbuilders.html', data, 'text/html'
-		else:
-			class Foo:
-				pass
-			b = Foo()
-			b.name = str(builder)
-			b.current = 'CURRENT-TEXT'
-			b.recent = []
-			b.slaves = []
-			data = { 'builder': b }
-			try:
-				master = BuildBotSystem(self.buildbot_url)
-				data = { 'builder': master.getBuilder(builder) }
-			except Exception, e:
-				print 'Error fetching builder stats', e
-			data['context'] = Context.from_request(req, ('buildbot', builder))
-			return 'bbw_builder.html', data, 'text/html'
-
-	def match_request(self, req):
-		return req.path_info.startswith('/buildbot') and 1 or 0
-
-	def process_request(self, req):
-		if req.path_info.startswith('/buildbot/builder'):
-			return self._handle_builder(req)
-		return 'bbw_welcome.html', { 'url': self.buildbot_url }, 'text/html'
deleted file mode 100644
--- a/contrib/trac/setup.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from setuptools import setup
-
-from bbwatcher import __version__
-
-setup(
-    name='Trac-BuildBot-Watcher',
-    version=__version__,
-    packages=['bbwatcher'],
-    package_data={
-        'bbwatcher': ['htdocs/*', 'templates/*.html'],
-        },
-    author='Randall Bosetti',
-    description='A plugin to fetch/integrate status updates from the BuildBot XML-RPC interface',
-    license='GPL',
-    entry_points={
-        'trac.plugins': 'bbwatcher.web_ui=bbwatcher.web_ui',
-        }
-)
deleted file mode 100755
--- a/contrib/viewcvspoll.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#! /usr/bin/python
-
-"""Based on the fakechanges.py contrib script"""
-
-import os.path
-import time
-import MySQLdb #@UnresolvedImport
-
-from twisted.spread import pb
-from twisted.cred import credentials
-from twisted.internet import reactor
-from twisted.python import log
-
-
-class ViewCvsPoller:
-
-    def __init__(self):
-
-        def _load_rc():
-            import user
-            ret = {}
-            for line in open(os.path.join(
-                user.home, ".cvsblamerc")).readlines():
-                if line.find("=") != -1:
-                    key, val = line.split("=")
-                    ret[key.strip()] = val.strip()
-            return ret
-        # maybe add your own keys here db=xxx, user=xxx, passwd=xxx
-        self.cvsdb = MySQLdb.connect("cvs", **_load_rc())
-        #self.last_checkin = "2005-05-11" # for testing
-        self.last_checkin = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
-
-    def get_changes(self):
-        changes = []
-
-        def empty_change():
-            return {'who': None, 'files': [], 'comments': None}
-        change = empty_change()
-
-        cursor = self.cvsdb.cursor()
-        cursor.execute("""SELECT whoid, descid, fileid, dirid, branchid, \
-ci_when FROM checkins WHERE ci_when>='%s'""" % self.last_checkin)
-        last_checkin = None
-        for whoid, descid, fileid, dirid, branchid, ci_when in \
-cursor.fetchall():
-            if branchid != 1: # only head
-                continue
-            cursor.execute("""SELECT who from people where id=%s""" % whoid)
-            who = cursor.fetchone()[0]
-            cursor.execute("""SELECT description from descs where id=%s""" % (
-                descid))
-            desc = cursor.fetchone()[0]
-            cursor.execute("""SELECT file from files where id=%s""" % fileid)
-            filename = cursor.fetchone()[0]
-            cursor.execute("""SELECT dir from dirs where id=%s""" % dirid)
-            dirname = cursor.fetchone()[0]
-            if who == change["who"] and desc == change["comments"]:
-                change["files"].append("%s/%s" % (dirname, filename))
-            elif change["who"]:
-                changes.append(change)
-                change = empty_change()
-            else:
-                change["who"] = who
-                change["files"].append("%s/%s" % (dirname, filename))
-                change["comments"] = desc
-            if last_checkin == None or ci_when > last_checkin:
-                last_checkin = ci_when
-        if last_checkin:
-            self.last_checkin = last_checkin
-        return changes
-
-
-poller = ViewCvsPoller()
-
-
-def error(*args):
-    log.err()
-    reactor.stop()
-
-
-def poll_changes(remote):
-    print "GET CHANGES SINCE", poller.last_checkin,
-    changes = poller.get_changes()
-    for change in changes:
-        print change["who"], "\n *", "\n * ".join(change["files"])
-        remote.callRemote('addChange', change).addErrback(error)
-    print
-    reactor.callLater(60, poll_changes, remote)
-
-
-factory = pb.PBClientFactory()
-reactor.connectTCP("localhost", 9999, factory)
-deferred = factory.login(credentials.UsernamePassword("change", "changepw"))
-deferred.addCallback(poll_changes).addErrback(error)
-
-reactor.run()
deleted file mode 100644
--- a/contrib/webhook_status.py
+++ /dev/null
@@ -1,178 +0,0 @@
-import urllib
-
-from twisted.python import log
-from twisted.internet import reactor
-from twisted.web import client, error
-
-from buildbot import status
-
-MAX_ATTEMPTS     = 10
-RETRY_MULTIPLIER = 5
-
-class WebHookTransmitter(status.base.StatusReceiverMultiService):
-    """
-    A webhook status listener for buildbot.
-
-    WebHookTransmitter listens for build events and sends the events
-    as http POSTs to one or more webhook URLs.
-
-    The easiest way to deploy this is to place it next to your
-    master.cfg and do something like this (assuming you've got a
-    postbin URL for purposes of demonstration):
-
-      from webhook_status import WebHookTransmitter
-      c['status'].append(WebHookTransmitter('http://www.postbin.org/xxxxxxx'))
-
-    Alternatively, you may provide a list of URLs and each one will
-    receive information on every event.
-
-    The following optional parameters influence when and what data is
-    transmitted:
-
-    categories:       If provided, only events belonging to one of the
-                      categories listed will be transmitted.
-
-    extra_params:     Additional parameters to be supplied with every request.
-
-    max_attempts:     The maximum number of times to retry transmission
-                      on failure.          Default: 10
-
-    retry_multiplier: A value multiplied by the retry number to wait before
-                      attempting a retry.  Default 5
-    """
-
-    agent = 'buildbot webhook'
-
-    def __init__(self, url, categories=None, extra_params={},
-                 max_attempts=MAX_ATTEMPTS, retry_multiplier=RETRY_MULTIPLIER):
-        status.base.StatusReceiverMultiService.__init__(self)
-        if isinstance(url, basestring):
-            self.urls = [url]
-        else:
-            self.urls = url
-        self.categories = categories
-        self.extra_params = extra_params
-        self.max_attempts = max_attempts
-        self.retry_multiplier = retry_multiplier
-
-    def _transmit(self, event, params={}):
-
-        cat = dict(params).get('category', None)
-        if (cat and self.categories) and cat not in self.categories:
-            log.msg("Ignoring request for unhandled category:  %s" % cat)
-            return
-
-        new_params = [('event', event)]
-        new_params.extend(list(self.extra_params.items()))
-        if hasattr(params, "items"):
-            new_params.extend(params.items())
-        else:
-            new_params.extend(params)
-        encoded_params = urllib.urlencode(new_params)
-
-        log.msg("WebHookTransmitter announcing a %s event" % event)
-        for u in self.urls:
-            self._retrying_fetch(u, encoded_params, event, 0)
-
-    def _retrying_fetch(self, u, data, event, attempt):
-        d = client.getPage(u, method='POST', agent=self.agent,
-                           postdata=data, followRedirect=0)
-
-        def _maybe_retry(e):
-            log.err()
-            if attempt < self.max_attempts:
-                reactor.callLater(attempt * self.retry_multiplier,
-                                  self._retrying_fetch, u, data, event, attempt + 1)
-            else:
-                return e
-
-        def _trap_status(x, *acceptable):
-            x.trap(error.Error)
-            if int(x.value.status) in acceptable:
-                log.msg("Terminating retries of event %s with a %s response"
-                        % (event, x.value.status))
-                return None
-            else:
-                return x
-
-        # Any sort of redirect is considered success
-        d.addErrback(lambda x: x.trap(error.PageRedirect))
-
-        # Any of these status values are considered delivered, or at
-        # least not something that should be retried.
-        d.addErrback(_trap_status,
-                     # These are all actually successes
-                     201, 202, 204,
-                     # These tell me I'm sending stuff it doesn't want.
-                     400, 401, 403, 405, 406, 407, 410, 413, 414, 415,
-                     # This tells me the server can't deal with what I sent
-                     501)
-
-        d.addCallback(lambda x: log.msg("Completed %s event hook on attempt %d" %
-                                        (event, attempt+1)))
-        d.addErrback(_maybe_retry)
-        d.addErrback(lambda e: log.err("Giving up delivering %s to %s" % (event, u)))
-
-    def builderAdded(self, builderName, builder):
-        builder.subscribe(self)
-        self._transmit('builderAdded',
-                       {'builder': builderName,
-                        'category': builder.getCategory()})
-
-    def builderRemoved(self, builderName, builder):
-        self._transmit('builderRemoved',
-                       {'builder': builderName,
-                        'category': builder.getCategory()})
-
-    def buildStarted(self, builderName, build):
-        build.subscribe(self)
-
-        args = {'builder': builderName,
-                'category': build.getBuilder().getCategory(),
-                'reason': build.getReason(),
-                'revision': build.getSourceStamp().revision,
-                'buildNumber': build.getNumber()}
-
-        if build.getSourceStamp().patch:
-            args['patch'] = build.getSourceStamp().patch[1]
-
-        self._transmit('buildStarted', args)
-
-    def buildFinished(self, builderName, build, results):
-        self._transmit('buildFinished',
-                       {'builder': builderName,
-                        'category': build.getBuilder().getCategory(),
-                        'result': status.builder.Results[results],
-                        'revision': build.getSourceStamp().revision,
-                        'had_patch': bool(build.getSourceStamp().patch),
-                        'buildNumber': build.getNumber()})
-
-    def stepStarted(self, build, step):
-        step.subscribe(self)
-        self._transmit('stepStarted',
-                       [('builder', build.getBuilder().getName()),
-                        ('category', build.getBuilder().getCategory()),
-                        ('buildNumber', build.getNumber()),
-                        ('step', step.getName())])
-
-    def stepFinished(self, build, step, results):
-        gu = self.status.getURLForThing
-        self._transmit('stepFinished',
-                       [('builder', build.getBuilder().getName()),
-                        ('category', build.getBuilder().getCategory()),
-                        ('buildNumber', build.getNumber()),
-                        ('resultStatus', status.builder.Results[results[0]]),
-                        ('resultString', ' '.join(results[1])),
-                        ('step', step.getName())]
-                       + [('logFile', gu(l)) for l in step.getLogs()])
-
-    def _subscribe(self):
-        self.status.subscribe(self)
-
-    def setServiceParent(self, parent):
-        status.base.StatusReceiverMultiService.setServiceParent(self, parent)
-        self.status = parent.getStatus()
-
-        self._transmit('startup')
-
-        self._subscribe()
deleted file mode 100644
--- a/contrib/windows/buildbot2.bat
+++ /dev/null
@@ -1,98 +0,0 @@
-@echo off
-rem This is Windows helper batch file for Buildbot
-rem NOTE: You will need Windows NT5/XP to use some of the syntax here.
-
-rem Please note you must have Twisted Matrix installed to use this build system
-rem Details: http://twistedmatrix.com/ (Version 1.3.0 or more, preferrably 2.0+)
-
-rem NOTE: --reactor=win32 argument is need because of Twisted
-rem The Twisted default reactor is select based (ie. posix) (why?!)
-
-rem Keep environmental settings local to this file
-setlocal
-
-rem Change the following settings to suite your environment
-
-rem This is where you want Buildbot installed
-set BB_DIR=z:\Tools\PythonLibs
-
-rem Assuming you have TortoiseCVS installed [for CVS.exe].
-set CVS_EXE="c:\Program Files\TortoiseCVS\cvs.exe"
-
-rem Trial: --spew will give LOADS of information. Use -o for verbose.
-set TRIAL=python C:\Python23\scripts\trial.py -o --reactor=win32
-set BUILDBOT_TEST_VC=c:\temp
-
-if "%1"=="helper" (
-	goto print_help
-)
-
-if "%1"=="bbinstall" (
-	rem You will only need to run this when you install Buildbot
-	echo BB: Install BuildBot at the location you set in the config:
-	echo BB: BB_DIR= %BB_DIR%
-	echo BB: You must be in the buildbot-x.y.z directory to run this:
-	python setup.py install --prefix %BB_DIR% --install-lib %BB_DIR%
-	goto end
-)
-
-if "%1"=="cvsco" (
-	echo BB: Getting Buildbot from Sourceforge CVS [if CVS in path].
-	if "%2"=="" (
-		echo BB ERROR: Please give a root path for the check out, eg. z:\temp
-		goto end
-	)
-
-	cd %2
-	echo BB: Hit return as there is no password
-	%CVS_EXE% -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot login 
-	%CVS_EXE% -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot co -P buildbot 
-	goto end
-)
-
-if "%1"=="cvsup" (
-	echo BB: Updating Buildbot from Sourceforge CVS [if CVS in path].
-	echo BB: Make sure you have the project checked out in local VCS.
-	
-	rem we only want buildbot code, the rest is from the install
-	cd %BB_DIR%
-	echo BB: Hit return as there is no password
-	%CVS_EXE% -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot login 
-	%CVS_EXE% -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/buildbot up -P -d buildbot buildbot/buildbot
-	goto end
-)
-
-if "%1"=="test" (
-	rem Trial is a testing framework supplied by the Twisted Matrix package.
-	rem It installs itself in the Python installation directory in a "scripts" folder,
-	rem e.g. c:\python23\scripts
-	rem This is just a convenience function because that directory is not in our path.
-		
-	if "%2" NEQ "" (
-		echo BB: TEST: buildbot.test.%2
-		%TRIAL% -m buildbot.test.%2
-	) else (
-		echo BB: Running ALL buildbot tests...
-		%TRIAL% buildbot.test
-	)
-	goto end
-)
-
-rem Okay, nothing that we recognised to pass to buildbot
-echo BB: Running buildbot...
-python -c "from buildbot.scripts import runner; runner.run()" %*
-goto end
-
-:print_help
-echo Buildbot helper script commands:
-echo	helper		This help message
-echo	test		Test buildbot is set up correctly
-echo Maintenance:
-echo	bbinstall	Install Buildbot from package
-echo	cvsup		Update from cvs
-echo	cvsco [dir]	Check buildbot out from cvs into [dir]
-
-:end
-rem End environment scope
-endlocal
-
deleted file mode 100755
--- a/contrib/windows/setup.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# setup.py
-# A distutils setup script to create py2exe binaries for buildbot.
-# Both a service and standard executable are created.
-# Usage:
-# % setup.py py2exe
-
-import sys
-import os
-import tempfile
-import shutil
-
-from os.path import dirname, join, abspath, splitext
-
-this_dir = abspath(dirname(__file__))
-bb_root_dir = abspath(join(this_dir, "..", ".."))
-
-from distutils.core import setup
-
-includes = []
-
-# We try and bundle *all* modules in the following packages:
-for package in ["buildbot.changes", "buildbot.process", "buildbot.status"]:
-    __import__(package)
-    p = sys.modules[package]
-    for fname in os.listdir(p.__path__[0]):
-        base, ext = splitext(fname)
-        if not fname.startswith("_") and ext == ".py":
-            includes.append(p.__name__ + "." + base)
-
-# Other misc modules dynamically imported, so missed by py2exe
-includes.extend("""
-            buildbot.scheduler
-            buildbot.slave.bot
-            buildbot.master
-            twisted.internet.win32eventreactor
-            twisted.web.resource""".split())
-
-# Turn into "," sep py2exe requires
-includes = ",".join(includes)
-
-py2exe_options = {"bundle_files": 1,
-                  "includes": includes,
-                 }
-
-# Each "target" executable we create
-buildbot_target = {
-    "script": join(bb_root_dir, "bin", "buildbot"),
-}
-# Due to the way py2exe works, we need to rebuild the service code as a
-# normal console process - this will be executed by the service itself.
-
-service_target = {
-    "modules": ["buildbot_service"],
-    "cmdline_style": "custom",
-}
-
-# We use the py2exe "bundle" option, so servicemanager.pyd
-# (which has the message resources) does not exist.  Take a copy
-# of it with a "friendlier" name.  The service runtime arranges for this
-# to be used.
-import servicemanager
-
-msg_file = join(tempfile.gettempdir(), "buildbot.msg")
-shutil.copy(servicemanager.__file__, msg_file)
-
-data_files = [
-    ["", [msg_file]],
-    ["", [join(bb_root_dir, "buildbot", "status", "web", "default.css")]],
-    ["", [join(bb_root_dir, "buildbot", "buildbot.png")]],
-]
-
-try:
-    setup(name="buildbot",
-          # The buildbot script as a normal executable
-          console=[buildbot_target],
-          service=[service_target],
-          options={'py2exe': py2exe_options},
-          data_files = data_files,
-          zipfile = "buildbot.library", # 'library.zip' invites trouble :)
-    )
-finally:
-    os.unlink(msg_file)
deleted file mode 100644
--- a/docs/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.info*
-buildbot.html
deleted file mode 100644
--- a/docs/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-all: docs.tgz
-
-VERSION=$(shell python -c 'g = {}; execfile("../master/buildbot/__init__.py",g); print g["version"]')
-
-buildbot.info: buildbot.texinfo
-	echo "@set VERSION $(VERSION)" > version.texinfo
-	makeinfo --fill-column=70 $<
-
-buildbot.html: buildbot.texinfo images-png
-	echo "@set VERSION $(VERSION)" > version.texinfo
-	makeinfo --no-split --html $<
-
-docs.tgz: buildbot.html images-png
-	echo "@set VERSION $(VERSION)" > version.texinfo
-	rm -rf $(VERSION)
-	makeinfo --html --output $(VERSION) buildbot.texinfo
-	cp buildbot.html $(VERSION)/full.html
-	mkdir $(VERSION)/images
-	cp images/*.png $(VERSION)/images
-	tar -zcf $@ $(VERSION)
-
-buildbot.ps: buildbot.texinfo images-eps
-	echo "@set VERSION $(VERSION)" > version.texinfo
-	rm -rf buildbot
-	texi2dvi $<
-	dvips buildbot.dvi
-	rm buildbot.aux buildbot.cp buildbot.cps buildbot.fn buildbot.ky buildbot.log buildbot.pg buildbot.toc buildbot.tp buildbot.vr
-	rm buildbot.dvi
-
-.PHONY: images images-png images-eps
-images:
-	$(MAKE) -C images all
-images-png:
-	# rule disabled, since the .png's are in git
-	#$(MAKE) -C images images-png
-images-eps:
-	$(MAKE) -C images images-eps
deleted file mode 100644
--- a/docs/PyCon-2003/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-LORE=lore
-IMAGES = overview.png slave.png
-
-all: buildbot.html images
-
-buildbot.html: source/buildbot.lore source/template.tpl
-	$(LORE) -p --config template=source/template.tpl $<
-	mv source/buildbot.html $@
-
-.PHONY: hlint
-hlint: source/buildbot.lore
-	$(LORE) --output lint $<
-
-.PHONY: tarball
-tarball: buildbot.html images
-	rm -rf buildbot-pycon
-	mkdir buildbot-pycon
-	cp buildbot.html stylesheet.css buildbot-pycon/
-	cp *.png buildbot-pycon/
-	tar czf buildbot-pycon.tar.gz buildbot-pycon
-	rm -rf buildbot-pycon
-
-clean:
-	rm -f buildbot.html $(IMAGES)
-
-.PHONY: images
-images: $(IMAGES) sizes
-
-sizes:
-	@for i in *.png; do \
-	 echo $$i `pngtopnm $$i |pnmfile`; \
-	done
-
-%.png: source/%.svg
-	inkscape --export-png $@ $<
deleted file mode 100644
--- a/docs/PyCon-2003/bb-slides.py
+++ /dev/null
@@ -1,195 +0,0 @@
-#! /usr/bin/python
-from slides import Lecture, NumSlide, Slide, Bullet, SubBullet, PRE, URL
-
-class Raw:
-    def __init__(self, title, html):
-        self.title = title
-        self.html = html
-    def toHTML(self):
-        return self.html
-
-class HTML(Raw):
-    def __init__(self, html):
-        self.html = html
-
-lecture = Lecture(
-    "BuildBot: Build/Test Automation",
-    Slide("The BuildBot: Build/Test Automation",
-          Bullet("Home page: ",
-                 URL("http://buildbot.sourceforge.net/"),
-                 ),
-          Bullet("Brian Warner  < warner-buildbot @ lothar . com >"),
-          ),
-
-    # quick description of what it does
-    # motivation: what is the problem it is trying to solve
-    # architecture: master+slaves
-    # design
-    #  starting the build: changes, tree-stable timers
-    #  doing the build: builders, processes
-    #  describing the build: status
-    #  status clients
-    # configuration: examples of Step, setup script
-    # demos: glib, show twisted status page
-    # future directions
-    # current status, availability, more info
-
-    Slide("Overview",
-          Bullet("What is the BuildBot?"),
-          Bullet("Motivation: What problem is it trying to solve?"),
-          Bullet("Architecture: What does it look like?"),
-          Bullet("Design: How does it work?"),
-          Bullet("Configuration: How do I make it do my bidding?"),
-          Bullet("Demo: Show me the code!"),
-          Bullet("Future Directons: What will it do in the future?"),
-          Bullet("More Information: How do I find out more?"),
-          ),
-
-    # description
-    Slide("Automating the Compile/Test cycle",
-          Bullet("CVS commits trigger new builds"),
-          Bullet("Builds run on multiple machines to cover various platforms and environments"),
-          Bullet("Builds include running tests"),
-          Bullet("Build status easy to retrieve, can be pushed to developers"),
-          Bullet("inspired by Tinderbox"),
-          ),
-
-    # motivation
-    Slide("Distributed cross-platform projects are tricky",
-          Bullet("Distance means poor communication"),
-          Bullet("Size leads to specialization: " + \
-                 "Not everyone knows the whole tree"),
-          Bullet("Multiple platforms: hard to do sufficient testing"),
-          Bullet("Somebody has to keep it all working"),
-          ),
-    # personal experience as chief harassment officer
-    
-    Slide("Automating away the job of 'Build Sheriff'",
-          Bullet("Give quick feedback about build problems"),
-          Bullet("minimize inconvenience to other developers"),
-          Bullet("provide (gentle) incentive to fix bugs"),
-          Bullet("provide (less gentle) encouragement to fix bugs"),
-          Bullet("provide (outright hostile) harassment to STOP BREAKING STUFF!"),
-          Bullet("Help developers to Do The Right Thing"),
-          ),
-
-    Slide("Features",
-          Bullet("Runs builds (and tests) when code is changed, report failures quickly"),
-          Bullet("Performs tests on a variety of slave platforms"),
-          Bullet("Handles arbitrary build processes: C, Python, Perl, etc"),
-          Bullet("Status delivery through web page, email, other protocols"),
-          Bullet("Track builds in progress, provide estimated completion time"),
-          Bullet("Flexible configuration by subclassing generic build process classes"),
-          Bullet("Minimal host requirements: Python and Twisted"),
-          Bullet("Released under the GPL"),
-          ),
-                 
-    # master and slaves
-    # slaves can be behind a firewall if they can still do checkout
-    Raw("Architecture",
-        """<h2>Architecture</h2>
-        <img src=\"../overview.png\" />
-        """
-        ),
-
-    # design
-    Slide("Starting the Build",
-          Bullet("Changes come from the version control system",
-                 SubBullet("CVSToys listener"),
-                 SubBullet("Parse cvs-commit email"),
-                 ),
-          Bullet("Builders wait for tree to be stable"),
-          Bullet("Builders can ignore some files which won't affect the build",
-                 SubBullet("Documentation files"),
-                 SubBullet("Example code"),
-                 ),
-          ),
-
-    Slide("Running a Build",
-          Bullet("Build class defines each kind of build process",
-                 SubBullet("Quick vs. clobber"),
-                 SubBullet("Optimized vs. debug"),
-                 SubBullet("Different versions of python, gcc, etc"),
-                 ),
-          Bullet("Sequence of Steps: CVS, Compile, Test",
-                 SubBullet("Steps defined by subclasses of BuildStep"),
-                 SubBullet("Steps invoke RemoteCommands on a connected slave"),
-                 ),
-          Bullet("Each Builder attaches to a BuildSlave (by name)"),
-          ),
-    
-    Slide("Describing the Build",
-          Bullet("Overall Status: success, fail, in-between"),
-          Bullet("Each step has status text, color, log files"),
-          Bullet("Progress events are distributed to HTML logger and status clients"),
-          ),
-
-    Raw("HTML Build Status",
-        """
-        <img src="../waterfall.png" alt="waterfall display" width="323" height="457" align="right" />
-
-        <h2>HTML Build Status</h2>
-        <ul>
-        <li>web server listens on arbitrary port</li>
-        <li>waterfall display shows time, commits, build results</li>
-        <li>Log files and build information are available through links</li>
-        <li>Alternate displays with different URLs</li>
-        </ul>
-        """
-        ),
-          
-    Slide("Status Delivery",
-          Bullet("Build progress and status is given to a delivery object ..",
-                 SubBullet(".. which can distribute it through arbitrary protocols"),
-                 ),
-          Bullet("HTML logger stores events, uses them to build waterfall display"),
-          Bullet("PB-based real-time status client",
-                 SubBullet("Shows current activity, Time-Remaining for current build"),
-                 ),
-          ),
-
-
-    Slide("Configuration",
-          Bullet("Everything driven by the buildmaster"),
-          # minimal slave setup: buildmaster location, dir, name/pw
-          Bullet("Classes provided for common build processes",
-                 SubBullet("autoconf (C)"),
-                 SubBullet("Makefile.PL (perl)"),
-                 ),
-          Bullet("Other BuildProcesses created by making subclasses"),
-          ),
-    
-    Slide("Demo",
-          Bullet("glib-1.2.10: simple C module with several self-tests"),
-          Bullet("python: Twisted BuildBot instance"),
-          ),
-    
-    Slide("Future Projects",
-          Bullet("Status Delivery through other protocols",
-                 SubBullet("Email with build results and logfiles"),
-                 SubBullet("IRC notification, interactive status queries"),
-                 SubBullet("panel applet with highly summarized status"),
-                 ),
-          Bullet("Tracking test failures, history of each test"),
-          Bullet("Project-specific blame assignment, owner notification"),
-          Bullet("Web-based Builder Configuration"),
-          Bullet("bug-tracking integration"),
-          Bullet("'try': run tests on not-yet-committed changes"),
-          ),
-
-    Slide("More Information",
-          Bullet("Home Page: ",
-                 URL("http://buildbot.sourceforge.net/")),
-          Bullet("Sourceforge project page",
-                 SubBullet("This paper and slides"),
-                 SubBullet("Source available in CVS"),
-                 SubBullet("Mailing list"),
-                 SubBullet("Pointers to existing installations"),
-                 ),
-          Bullet("Please join the mailing list to find out about releases"),
-          ),
-    
-    
-    )
-
-lecture.renderHTML("slides", "slide-%02d.html", css="main.css")
deleted file mode 100644
--- a/docs/PyCon-2003/source/buildbot.lore
+++ /dev/null
@@ -1,433 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>BuildBot: build/test automation</title>
- </head>
-
-<body>
-
-<h1>BuildBot: build/test automation</h1>
-
-<ul>
-  <li>Author: Brian Warner &lt;<code>warner@lothar.com</code>&gt;</li>
-  <li>BuildBot Home Page:
-  <a href="http://buildbot.sourceforge.net">http://buildbot.sourceforge.net</a>
-  </li>
-</ul>
-
-<h2>Abstract</h2>
-
-<p>The BuildBot is a system to automate the compile/test cycle required by
-most software projects to validate code changes. By automatically rebuilding
-and testing the tree each time something has changed, build problems are
-pinpointed quickly, before other developers are inconvenienced by the
-failure. The guilty developer can be identified and harassed without human
-intervention. By running the builds on a variety of platforms, developers
-who do not have the facilities to test their changes everywhere before
-checkin will at least know shortly afterwards whether they have broken the
-build or not. Warning counts, lint checks, image size, compile time, and
-other build parameters can be tracked over time, are more visible, and are
-therefore easier to improve.</p>
-
-<p>The overall goal is to reduce tree breakage and provide a platform to run
-tests or code-quality checks that are too annoying or pedantic for any human
-to waste their time with. Developers get immediate (and potentially public)
-feedback about their changes, encouraging them to be more careful about
-testing before checkin.</p>
-
-
-<h2>Features</h2>
-
-<ul>
- <li> run builds on a variety of slave platforms</li>
- <li> arbitrary build process: handles projects using C, Python, whatever</li>
- <li> minimal host requirements: python and Twisted</li>
- <li> slaves can be behind a firewall if they can still do checkout</li>
- <li> status delivery through web page, email, IRC, other protocols</li>
- <li> track builds in progress, provide estimated completion time</li>
- <li> flexible configuration by subclassing generic build process classes</li>
- <li> debug tools to force a new build, submit fake Changes, query slave
- status</li>
- <li> released under the GPL</li>
-</ul>
-
-<h2>Overview</h2>
-
-<img src="waterfall.png" alt="waterfall display"
-     width="323" height="457" align="right" />
-
-<p>In general, the buildbot watches a source code repository (CVS or other
-version control system) for <q>interesting</q> changes to occur, then
-triggers builds with various steps (checkout, compile, test, etc). The
-Builds are run on a variety of slave machines, to allow testing on different
-architectures, compilation against different libraries, kernel versions,
-etc. The results of the builds are collected and analyzed: compile succeeded
-/ failed / had warnings, which tests passed or failed, memory footprint of
-generated executables, total tree size, etc. The results are displayed on a
-central web page in a <q>waterfall</q> display: time along the vertical
-axis, build platform along the horizontal, <q>now</q> at the top. The
-overall build status (red for failing, green for successful) is at the very
-top of the page. After developers commit a change, they can check the web
-page to watch the various builds complete. They are on the hook until they
-see green for all builds: after that point they can reasonably assume that
-they did not break anything. If they see red, they can examine the build
-logs to find out what they broke.</p>
-
-<p>The status information can be retrieved by a variety of means. The main
-web page is one path, but the underlying Twisted framework allows other
-protocols to be used: IRC or email, for example. A live status client (using
-Gtk+ or Tkinter) can run on the developers desktop, with a box per builder
-that turns green or red as the builds succeed or fail. Once the build has
-run a few times, the build process knows about how long it ought to take (by
-measuring elapsed time, quantity of text output by the compile process,
-searching for text indicating how many unit tests have been run, etc), so it
-can provide a progress bar and ETA display.</p>
-
-<p>Each build involves a list of <q>Changes</q>: files that were changed
-since the last build. If a build fails where it used to succeed, there is a
-good chance that one of the Changes is to blame, so the developers who
-submitted those Changes are put on the <q>blamelist</q>. The unfortunates on
-this list are responsible for fixing their problems, and can be reminded of
-this responsibility in increasingly hostile ways. They can receive private
-mail, the main web page can put their name up in lights, etc. If the
-developers use IRC to communicate, the buildbot can sit in on the channel
-and tell developers directly about build status or failures.</p>
-
-<p>The build master also provides a place where long-term statistics about
-the build can be tracked. It is occasionally useful to create a graph
-showing how the size of the compiled image or source tree has changed over
-months or years: by collecting such metrics on each build and archiving
-them, the historical data is available for later processing.</p>
-
-
-<h2>Design</h2>
-
-<p>The BuildBot consists of a master and a set of build slaves. The master
-runs on any conveniently-accessible host: it provides the status web server
-and must be reachable by the build slaves, so for public projects it should
-be reachable from the general internet. The slaves connect to the master and
-actually perform the builds: they can be behind a firewall as long as they
-can reach the master and check out source files.</p>
-
-<h3>Build Master</h3>
-
-<img src="overview.png"  alt="overview diagram" width="595" height="383" />
-
-<p>The master receives information about changed source files from various
-sources: it can connect to a CVSToys server, or watch a mailbox that is
-subscribed to a CVS commit list of the type commonly provided for widely
-distributed development projects. New forms of change notification (e.g. for
-other version control systems) can be handled by writing an appropriate
-class: all are responsible for creating Change objects and delivering them
-to the ChangeMaster service inside the master.</p>
-
-<p>The build master is given a working directory where it is allowed to save
-persistent information. It is told which TCP ports to use for slave
-connections, status client connections, the built-in HTTP server, etc. The
-master is also given a list of <q>build slaves</q> that are allowed to
-connect, described below. Each slave gets a name and a password to use. The
-buildbot administrator must give a password to each person who runs a build
-slave.</p>
-
-<p>The build master is the central point of control. All the decisions about
-what gets built are made there, all the file change notices are sent there,
-all the status information is distributed from there. Build slave
-configuration is minimal: everything is controlled on the master side by the
-buildbot administrator. On the other hand, the build master does no actual
-compilation or testing. It does not have to be able to checkout or build the
-tree. The build slaves are responsible for doing any work that actually
-touches the project's source code.</p>
-
-<h3>Builders and BuildProcesses</h3>
-
-<p>Each <q>build process</q> is defined by an instance of a Builder class
-which receives a copy of every Change that goes into the repository. It gets
-to decide which changes are interesting (e.g. a Builder which only compiles
-C code could ignore changes to documentation files). It can decide how long
-to wait until starting the build: a quick build that just updates the files
-that were changed (and will probably finish quickly) could start after 30
-seconds, whereas a full build (remove the old tree, checkout a new tree,
-compile everything, test everything) would want to wait longer. The default
-10 minute delay gives developers a chance to finish checking in a set of
-related files while still providing timely feedback about the consequences
-of those changes.</p>
-
-<p>Once the build is started, the build process controls how it proceeds
-with a series of BuildSteps, which are things like shell commands, CVS
-update or checkout commands, etc. Each BuildStep can invoke SlaveCommands on
-a connected slave. One generic command is ShellCommand, which takes a
-string, hands it to <code>/bin/sh</code>, and returns exit status and
-stdout/stderr text. Other commands are layered on top of ShellCommand:
-CVSCheckout, MakeTarget, CountKLOC, and so on. Some operations are faster or
-easier to do with python code on the slave side, some are easier to do on
-the master side.</p>
-
-<p>The Builder walks through a state machine, starting BuildSteps and
-receiving a callback when they complete. Steps which fail may stop the
-overall build (if the CVS checkout fails, there is little point in
-attempting a compile), or may allow it to continue (unit tests could fail
-but documentation may still be buildable). When the last step finishes, the
-entire build is complete, and a function combines the completion status of
-all the steps to decide how the overall build should be described:
-successful, failing, or somewhere in between.</p>
-
-<p>At each point in the build cycle (waiting to build, starting build,
-starting a BuildStep, finishing the build), status information is delivered
-to a special Status object. This information is used to update the main
-status web page, and can be delivered to real-time status clients that are
-attached at that moment. Intermediate status (stdout from a ShellCommand,
-for example) is also delivered while the Step runs. This status can be used
-to estimate how long the individual Step (or the overall build) has left
-before it is finished, so an ETA can be listed on the web page or in the
-status client.</p>
-
-<p>The build master is persisted to disk when it is stopped with SIGINT,
-preserving the status and historical build statistics.</p>
-
-<p>Builders are set up by the buildbot administrator. Each one gets a name
-and a BuildProcess object (which may be parameterized with things like which
-CVS repository to use, which targets to build, which version or python or
-gcc it should use, etc). Builders are also assigned to a BuildSlave,
-described below. In the current implementation, Builders are defined by
-adding lines to the setup script, but an HTML-based <q>create a builder</q>
-scheme is planned for the future.</p>
-
-<h3>Build Slaves</h3>
-
-<p>BuildSlaves are where the actual compilation and testing gets done. They
-are programs which run on a variety of platforms, and communicate with the
-BuildMaster over TCP connections.</p>
-
-<p>Each build slave is given a name and a working directory. They are also
-given the buildmaster's contact information: hostname, port number, and a
-password. This information must come from the buildbot administrator, who
-has created a corresponding entry in the buildmaster. The password exists to
-make it clear that build slave operators need to coordinate with the
-buildbot administrator.</p>
-
-<p>When the Builders are created, they are given a name (like
-<q>quick-bsd</q> or <q>full-linux</q>), and are tied to a particular slave.
-When that slave comes online, a RemoteBuilder object is created inside it,
-where all the SlaveCommands are run. Each RemoteBuilder gets a separate
-subdirectory inside the slave's working directory. Multiple Builders can
-share the same slave: typically all Builders for a given architecture would
-run inside the same slave.</p>
-
-<img src="slave.png"  alt="overview diagram" width="595" height="354" />
-
-<h3>Build Status</h3>
-
-<p>The waterfall display holds short-term historical build status.
-Developers can easily see what the buildbot is doing right now, how long it
-will be until the current build is finished, and what are the results of
-each step of the build process. Change comments and compile/test logs are
-one click away. The top row shows overall status: green is good, red is bad,
-yellow is a build still in progress.</p>
-
-<p>Also available through the web page is information on the individual
-builders: static information like what purpose the builder serves (specified
-by the admin when configuring the buildmaster), and non-build status
-information like which build slave it wants to use, whether the slave is
-online or not, and how frequently the build has succeeded in the last 10
-attempts. Build slave information is available here too, both data provided
-by the build slave operator (which machine the slave is running on, who to
-thank for the compute cycles being donated) and data extracted from the
-system automatically (CPU type, OS name, versions of various build
-tools).</p>
-
-<p>The live status client shows the results of the last build, but does not
-otherwise show historical information. It provides extensive information
-about the current build: overall ETA, individual step ETA, data about what
-changes are being processed. It will be possible to get at the error logs
-from the last build through this interface.</p>
-
-<p>Eventually, e-mail and IRC notices can be sent when builds have succeeded
-or failed. Mail messages can include the compile/test logs or summaries
-thereof. The buildmaster can sit on the IRC channel and accept queries about
-current build status, such as <q>how long until the current build
-finishes</q>, or <q>what tests are currently failing</q>.</p>
-
-<p>Other status displays are possible. Test and compile errors can be
-tracked by filename or test case name, providing view on how that one file
-has fared over time. Errors can be tracked by username, giving a history of
-how one developer has affected the build over time. </p>
-
-
-<h2>Installation</h2>
-
-<p>The buildbot administrator will find a publically-reachable machine to
-host the buildmaster. They decide upon the BuildProcesses to be run, and
-create the Builders that use them. Creating complex build processes will
-involve writing a new python class to implement the necessary
-decision-making, but it will be possible to create simple ones like
-<q>checkout, make, make test</q> from the command line or through a
-web-based configuration interface. They also decide upon what forms of
-status notification should be used: what TCP port should be used for the web
-server, where mail should be sent, what IRC channels should receive
-success/failure messages.</p>
-
-<p>Next, they need to arrange for change notification. If the repository is
-using <a href="http://purl.net/net/CVSToys">CVSToys</a>, then they simply
-tell the buildmaster the host, port, and login information for the CVSToys
-server. When the buildmaster starts up, it will contact the server and
-subscribe to hear about all CVS changes. If not, a <q>cvs-commits</q>
-mailing list is needed. Most large projects have such a list: every time a
-change is committed, an email is sent to everyone on the list which contains
-details about what was changed and why (the checkin comments). The admin
-should subscribe to this list, and dump the resulting mail into a
-qmail-style <q>maildir</q>. (It doesn't matter who is subscribed, it could
-be the admin themselves or a buildbot-specific account, just as long as the
-mail winds up in the right place). Then they tell the buildmaster to monitor
-that maildir. Each time a message arrives, it will be parsed, and the
-contents used to trigger the buildprocess. All forms of CVS notification
-include a filtering prefix, to tell the buildmaster it should ignore commits
-outside a certain directory. This is useful if the repository is used for
-multiple projects.</p>
-
-<p>Finally, they need to arrange for build slaves. Some projects use
-dedicated machines for this purpose, but many do not have that luxury and
-simply use developer's personal workstations. Projects that would benefit
-from testing on multiple platforms will want to find build slaves on a
-variety of operating systems. Frequently these build slaves are run by
-volunteers or developers involved in the project who have access to the
-right equipment. The admin will give each of these people a name/password
-for their build slave, as well as the location (host/port) of the
-buildmaster. The build slave owners simply start a process on their systems
-with the appropriate parameters and it will connect to the build master.</p>
-
-<p>Both the build master and the build slaves are Twisted
-<code>Application</code> instances. A <code>.tap</code> file holds the
-pickled application state, and a daemon-launching program called
-<code>twistd</code> is used to start the process, detach from the current
-tty, log output to a file, etc. When the program is terminated, it saves its
-state to another <code>.tap</code> file. Next time, <code>twistd</code> is
-told to start from that file and the application will be restarted exactly
-where it left off.</p>
-
-
-<h2>Security</h2>
-
-<p>The master is intended to be publically available, but of course
-limitations can be put on it for private projects. User accounts and
-passwords can be required for live status clients that want to connect, or
-the master can allow arbitrary anonymous access to status information.
-Twisted's <q>Perspective Broker</q> RPC system and careful design provides
-security for the real-time status client port: those clients are read-only,
-and cannot do anything to disrupt the build master or the build processes
-running on the slaves.</p>
-
-<p>Build slaves each have a name and password, and typically the project
-coordinator would provide these to developers or volunteers who wished to
-offer a host machine for builds. The build slaves connect to the master, so
-they can be behind a firewall or NAT box, as long as they can still do a
-checkout and compile. Registering build slaves helps prevent DoS attacks
-where idiots attach fake build slaves that are not actually capable of
-performing the build, displacing the actual slave.</p>
-
-<p>Running a build slave on your machine is equivalent to giving a local
-account to everyone who can commit code to the repository. Any such
-developer could add an <q><code>rm -rf /</code></q> or code to start a
-remotely-accessible shell to a Makefile and then do naughty things with the
-account under which the build slave was launched. If this is a concern, the
-build slave can be run inside a chroot jail or other means (like a
-user-mode-linux sub-kernel), as long as it is still capable of checking out
-a tree and running all commands necessary for the build.</p>
-
-
-<h2>Inspirations and Competition</h2>
-
-<p>Buildbot was originally inspired by Mozilla's Tinderbox project, but is
-intended to conserve resources better (tinderbox uses dedicated build
-machines to continually rebuild the tree, buildbot only rebuilds when
-something has changed, and not even then for some builds) and deliver more
-useful status information. I've seen other projects with similar goals
-[CruiseControl on sourceforge is a java-based one], but I believe this one
-is more flexible.</p>
-
-
-<h2>Current Status</h2>
-
-<p>Buildbot is currently under development. Basic builds, web-based status
-reporting, and a basic Gtk+-based real-time status client are all
-functional. More work is being done to make the build process more flexible
-and easier to configure, add better status reporting, and add new kinds of
-build steps. An instance has been running against the Twisted source tree
-(which includes extensive unit tests) since February 2003.</p>
-
-<h2>Future Directions</h2>
-
-<p>Once the configuration process is streamlined and a release is made, the
-next major feature is the <q>try</q> command. This will be a tool to which
-they developer can submit a series of <em>potential</em> changes, before
-they are actually checked in. <q>try</q> will assemble the changed and/or
-new files and deliver them to the build master, which will then initiate a
-build cycle with the current tree plus the potential changes. This build is
-private, just for the developer who requested it, so failures will not be
-announced publically. It will run all the usual tests from a full build and
-report the results back to the developer. This way, a developer can verify
-their changes, on more platforms then they directly have access to, with a
-single command. By making it easy to thoroughly test their changes before
-checkin, developers will have no excuse for breaking the build.</p>
-
-<p>For projects that have unit tests which can be broken up into individual
-test cases, the BuildProcess will have some steps to track each test case
-separately. Developers will be able to look at the history of individual
-tests, to find out things like <q>test_import passed until foo.c was changed
-on monday, then failed until bar.c was changed last night</q>. This can also
-be used to make breaking a previously-passing test a higher crime than
-failing to fix an already-broken one. It can also help to detect
-intermittent failures, ones that need to be fixed but which can't be blamed
-on the last developer to commit changes. For test cases that represent new
-functionality which has not yet been implemented, the list of failing test
-cases can serve as a convenient TODO list.</p>
-
-<p>If a large number of changes occur at the same time and the build fails
-afterwards, a clever process could try modifying one file (or one
-developer's files) at a time, to find one which is the actual cause of the
-failure. Intermittent test failures could be identified by re-running the
-failing test a number of times, looking for changes in the results.</p>
-
-<p>Project-specific methods can be developed to identify the guilty
-developer more precisely, for example grepping through source files for a
-<q>Maintainer</q> tag, or a static table of module owners. Build failures
-could be reported to the owner of the module as well as the developer who
-made the offending change.</p>
-
-<p>The Builder could update entries in a bug database automatically: a
-change could have comments which claim it <q>fixes #12345</q>, so the bug DB is
-queried to find out that test case ABC should be used to verify the bug. If
-test ABC was failing before and now passes, the bug DB can be told to mark
-#12345 as machine-verified. Such entries could also be used to identify
-which tests to run, for a quick build that wasn't running the entire test
-suite.</p>
-
-<p>The Buildbot could be integrated into the release cycle: once per week,
-any build which passes a full test suite is automatically tagged and release
-tarballs are created.</p>
-
-<p>It should be possible to create and configure the Builders from the main
-status web page, at least for processes that use a generic <q>checkout /
-make / make test</q> sequence. Twisted's <q>Woven</q> framework provides a
-powerful HTML tool that could be used create the necessary controls.</p>
-
-<p>If the master or a slave is interrupted during a build, it is frequently
-possible to re-start the interrupted build. Some steps can simply be
-re-invoked (<q>make</q> or <q>cvs update</q>). Interrupting others may
-require the entire build to be re-started from scratch (<q>cvs export</q>).
-The Buildbot will be extended so that both master and slaves can report to
-the other what happened while they were disconnected, and as much work can
-be salvaged as possible.</p>
-
-<h2>More Information</h2>
-
-<p>The BuildBot home page is at <a
-href="http://buildbot.sourceforge.net">http://buildbot.sourceforge.net</a>,
-and has pointers to publically-visible BuildBot installations. Mailing
-lists, bug reporting, and of course source downloads are reachable from that
-page. </p>
-
-<!-- $Id: buildbot.lore,v 1.1 2003/03/19 01:27:51 warner Exp $ -->
-
-</body> </html>
deleted file mode 100644
--- a/docs/PyCon-2003/source/overview.svg
+++ /dev/null
@@ -1,399 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
-<svg
-   id="svg101"
-   sodipodi:version="0.31"
-   width="210mm"
-   height="135mm"
-   sodipodi:docname="overview.svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:xlink="http://www.w3.org/1999/xlink">
-  <defs
-     id="defs103" />
-  <sodipodi:namedview
-     id="base"
-     showgrid="true"
-     snaptoguides="false" />
-  <path
-     sodipodi:type="arc"
-     style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.32592;"
-     id="path134"
-     d="M 334.577759 117.917908 A 70.437424 62.398376 0 1 0 193.702896,117.917908 A 70.4374 62.3984 0 1 0 334.578 117.918 L 264.140320 117.917908 z"
-     sodipodi:cx="264.140320"
-     sodipodi:cy="117.917908"
-     sodipodi:rx="70.437424"
-     sodipodi:ry="62.398376"
-     transform="matrix(1.33097,0,0,1.50244,-53.799,-53.3473)" />
-  <text
-     style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;"
-     x="171.756"
-     y="85.3248"
-     id="text109"
-     transform="translate(64.67,-5.6235)">
-    <tspan
-       x="171.756"
-       y="85.3248"
-       sodipodi:role="line"
-       id="tspan112">
-BuildMaster</tspan>
-  </text>
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;"
-     d="M 115.828 341.652 L 177.995 205.386 "
-     id="path155"
-     transform="translate(64.67,-5.6235)"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;"
-     d="M 245.24 327.175 L 237.717 223.362 "
-     id="path124"
-     transform="translate(64.67,-5.6235)" />
-  <g
-     id="g134"
-     transform="translate(64.67,-5.6235)"
-     style="font-size:12;">
-    <path
-       sodipodi:type="arc"
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.49836;"
-       id="path105"
-       d="M 179.381500 607.448853 A 73.168770 76.709229 0 1 0 33.043961,607.448853 A 73.1688 76.7092 0 1 0 179.382 607.449 L 106.212730 607.448853 z"
-       sodipodi:cx="106.212730"
-       sodipodi:cy="607.448853"
-       sodipodi:rx="73.168770"
-       sodipodi:ry="76.709229"
-       transform="matrix(0.85419,0,0,0.814765,2.45788,-95.137)" />
-    <text
-       style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;font-style:normal;text-anchor:start;writing-mode:lr;"
-       x="65.6396"
-       y="365.564"
-       id="text114">
-      <tspan
-         x="65.6396"
-         y="365.564"
-         sodipodi:role="line"
-         id="tspan130">
-Build</tspan>
-      <tspan
-         x="65.6396"
-         y="389.564"
-         sodipodi:role="line"
-         id="tspan132">
-Slave</tspan>
-    </text>
-  </g>
-  <g
-     id="g141"
-     transform="translate(395.668,-49.2551)"
-     style="font-size:12;">
-    <path
-       sodipodi:type="arc"
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.49836;"
-       id="path142"
-       d="M 179.381500 607.448853 A 73.168770 76.709229 0 1 0 33.043961,607.448853 A 73.1688 76.7092 0 1 0 179.382 607.449 L 106.212730 607.448853 z"
-       sodipodi:cx="106.212730"
-       sodipodi:cy="607.448853"
-       sodipodi:rx="73.168770"
-       sodipodi:ry="76.709229"
-       transform="matrix(0.85419,0,0,0.814765,2.45788,-95.137)" />
-    <text
-       style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;font-style:normal;text-anchor:start;writing-mode:lr;"
-       x="65.6396"
-       y="365.564"
-       id="text143">
-      <tspan
-         x="65.6396"
-         y="365.564"
-         sodipodi:role="line"
-         id="tspan144">
-Build</tspan>
-      <tspan
-         x="65.6396"
-         y="389.564"
-         sodipodi:role="line"
-         id="tspan146">
-Slave</tspan>
-    </text>
-  </g>
-  <g
-     id="g148"
-     transform="translate(237.692,-19.1644)"
-     style="font-size:12;">
-    <path
-       sodipodi:type="arc"
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.49836;"
-       id="path149"
-       d="M 179.381500 607.448853 A 73.168770 76.709229 0 1 0 33.043961,607.448853 A 73.1688 76.7092 0 1 0 179.382 607.449 L 106.212730 607.448853 z"
-       sodipodi:cx="106.212730"
-       sodipodi:cy="607.448853"
-       sodipodi:rx="73.168770"
-       sodipodi:ry="76.709229"
-       transform="matrix(0.85419,0,0,0.814765,2.45788,-95.137)" />
-    <text
-       style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;font-style:normal;text-anchor:start;writing-mode:lr;"
-       x="65.6396"
-       y="365.564"
-       id="text150">
-      <tspan
-         x="65.6396"
-         y="365.564"
-         sodipodi:role="line"
-         id="tspan151">
-Build</tspan>
-      <tspan
-         x="65.6396"
-         y="389.564"
-         sodipodi:role="line"
-         id="tspan153">
-Slave</tspan>
-    </text>
-  </g>
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.875;"
-     d="M 313.381 177.167 L 385.474 306.636 "
-     id="path183"
-     transform="translate(64.67,-5.6235)"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.875;"
-     d="M 378.982 295.337 L 380.74 310.958 "
-     id="path185"
-     sodipodi:nodetypes="cc"
-     transform="translate(69.4055,-9.94649)" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.875;"
-     d="M 307.666 185.486 L 380.17 311.578 "
-     id="path187"
-     transform="translate(64.67,-5.62348)"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.875;"
-     d="M 315.974 196.344 L 312.644 177.554 "
-     id="path188"
-     sodipodi:nodetypes="cc"
-     transform="translate(59.6922,2.30869)" />
-  <text
-     style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;"
-     x="337.755"
-     y="-247.182"
-     id="text189"
-     transform="matrix(0.495343,0.868698,-0.868698,0.495343,0,0)">
-    <tspan
-       x="337.755"
-       y="-247.182"
-       sodipodi:role="line"
-       id="tspan197">
-Commands</tspan>
-  </text>
-  <rect
-     style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.25;stroke-dasharray:none;"
-     id="rect157"
-     width="90.420172"
-     height="56.630016"
-     x="10.683041"
-     y="133.779876" />
-  <text
-     style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;"
-     x="34.1392"
-     y="159.653"
-     id="text161">
-    <tspan
-       id="tspan162">
-CVS</tspan>
-  </text>
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;"
-     d="M 483.315 144.074 L 379.553 172.269 "
-     id="path170"
-     sodipodi:nodetypes="cc"
-     transform="translate(-278.786,-9.57294)" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;"
-     d="M 325.132 145.896 L 338.152 148.492 "
-     id="path171"
-     sodipodi:nodetypes="cc"
-     transform="translate(-133.623,-13.9906)" />
-  <path
-     style="font-size:12;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;"
-     d="M 329.861 140.221 L 340.021 130.843 "
-     id="path172"
-     sodipodi:nodetypes="cc"
-     transform="translate(-135.492,3.65842)" />
-  <text
-     style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;"
-     x="61.8297"
-     y="178.877"
-     id="text175"
-     transform="matrix(0.962658,-0.270725,0.270725,0.962658,0,0)">
-    <tspan
-       x="61.8297"
-       y="178.877"
-       sodipodi:role="line"
-       id="tspan178">
-Changes</tspan>
-  </text>
-  <g
-     id="g334"
-     transform="translate(-36.6653,-7.12939)">
-    <rect
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.25;stroke-dasharray:none;"
-       id="rect318"
-       width="97.774006"
-       height="58.053266"
-       x="478.684952"
-       y="23.698329" />
-    <text
-       style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-       x="494.981"
-       y="48.1418"
-       id="text321">
-      <tspan
-         id="tspan322">
-Browser</tspan>
-    </text>
-  </g>
-  <g
-     id="g339"
-     transform="translate(109.995,-9.16652)">
-    <rect
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke-width:1pt;stroke:#000000;stroke-opacity:1;fill-opacity:1;"
-       id="rect319"
-       width="124.254"
-       height="62.1272"
-       x="487.851"
-       y="136.75" />
-    <text
-       style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-       x="505.166"
-       y="157.119"
-       id="text324">
-      <tspan
-         id="tspan325">
-Status Client</tspan>
-    </text>
-  </g>
-  <g
-     id="g344"
-     transform="translate(101.848,-11.2033)">
-    <rect
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.25;stroke-dasharray:none;"
-       id="rect320"
-       width="101.848366"
-       height="57.034844"
-       x="521.461026"
-       y="213.134920" />
-    <text
-       style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-       x="557.108"
-       y="234.524"
-       id="text327">
-      <tspan
-         id="tspan328">
-IRC</tspan>
-    </text>
-  </g>
-  <g
-     id="g349"
-     transform="translate(-85.5523,-27.499)">
-    <rect
-       style="font-size:12;fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:1.25;stroke-dasharray:none;"
-       id="rect333"
-       width="83.515350"
-       height="46.850033"
-       x="633.493759"
-       y="98.047092" />
-    <text
-       style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-       x="652.846"
-       y="116.38"
-       id="text330">
-      <tspan
-         id="tspan331">
-email</tspan>
-    </text>
-  </g>
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 377.856 75.6408 L 441.963 55.955 "
-     id="path355"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 430.496 65.6275 L 441.001 56.2897 "
-     id="path356"
-     sodipodi:nodetypes="cc"
-     transform="translate(0.962296,0.0418015)" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 427.445 54.6311 L 441.001 56.2897 "
-     id="path357"
-     sodipodi:nodetypes="cc"
-     transform="translate(0.920448,-0.627563)" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 382.948 85.8256 L 546.923 94.9919 "
-     id="path358" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 533.733 102.199 L 546.923 94.9919 "
-     id="path359"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 532.867 86.0032 L 546.923 94.9919 "
-     id="path360"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 391.096 107.214 L 596.829 140.823 "
-     id="path361" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 580.686 147.343 L 596.829 140.823 "
-     id="path362"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 582.162 130.664 L 596.829 140.823 "
-     id="path364"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 391.096 124.528 L 622.291 210.08 "
-     id="path365" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 610.094 198.468 L 622.291 210.08 "
-     id="path366"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 605.868 211.329 L 622.291 210.08 "
-     id="path367"
-     sodipodi:nodetypes="cc" />
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="444.866"
-     y="38.2709"
-     id="text368"
-     transform="matrix(0.976454,0.215725,-0.215725,0.976454,0,0)">
-    <tspan
-       id="tspan369">
-Build Status</tspan>
-  </text>
-  <text
-     style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Nimbus Roman No9 L;font-style:normal;text-anchor:start;writing-mode:lr;"
-     x="-479.649"
-     y="229.559"
-     id="text196"
-     transform="matrix(-0.498825,-0.866703,0.866703,-0.498825,0,0)">
-    <tspan
-       x="-479.649"
-       y="229.559"
-       sodipodi:role="line"
-       id="tspan198">
-Results</tspan>
-  </text>
-</svg>
deleted file mode 100644
--- a/docs/PyCon-2003/source/slave.svg
+++ /dev/null
@@ -1,344 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
-"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
-<svg
-   id="svg374"
-   sodipodi:version="0.31"
-   width="210mm"
-   height="125mm"
-   sodipodi:docname="slave.svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:xlink="http://www.w3.org/1999/xlink">
-  <defs
-     id="defs376" />
-  <sodipodi:namedview
-     id="base"
-     snaptoguides="false" />
-  <path
-     sodipodi:type="arc"
-     style="fill-rule:evenodd;stroke:#000000;fill:#e6e6e6;fill-opacity:1;stroke-opacity:1;stroke-width:1.65887;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-     id="path377"
-     d="M 377.296570 264.107605 A 99.245399 93.503922 0 1 0 178.805786,264.107605 A 99.2454 93.5039 0 1 0 377.297 264.108 L 278.051178 264.107605 z"
-     sodipodi:cx="278.051178"
-     sodipodi:cy="264.107605"
-     sodipodi:rx="99.245399"
-     sodipodi:ry="93.503922"
-     transform="matrix(1.46281,0,0,1.55263,-174.617,-197.627)" />
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:24;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="201.772"
-     y="96.7843"
-     id="text378">
-    <tspan
-       x="201.772"
-       y="96.7843"
-       sodipodi:role="line"
-       id="tspan383">
-Build</tspan>
-    <tspan
-       x="201.772"
-       y="120.784"
-       sodipodi:role="line"
-       id="tspan385">
-Slave</tspan>
-  </text>
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 124.672 113.189 C 124.672 113.189 218.176 187.008 333.005 109.908 "
-     id="path388"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 145.997 329.724 L 185.367 139.436 "
-     id="path389" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.875;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 260.827 141.076 L 314.738 332.894 "
-     id="path390"
-     sodipodi:nodetypes="cc" />
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Mono L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="108.268"
-     y="185.367"
-     id="text391">
-    <tspan
-       x="108.268"
-       y="185.367"
-       sodipodi:role="line"
-       id="tspan394">
-quick</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Mono L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="183.727"
-     y="226.378"
-     id="text396">
-    <tspan
-       x="183.727"
-       y="226.378"
-       sodipodi:role="line"
-       id="tspan399">
-full-2.1</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Mono L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="283.793"
-     y="205.052"
-     id="text401">
-    <tspan
-       x="283.793"
-       y="205.052"
-       sodipodi:role="line"
-       id="tspan404">
-full-2.2</tspan>
-  </text>
-  <a
-     id="a585"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="translate(18.0446,57.3687)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path586"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <a
-     id="a583"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="matrix(1.00002,0,0,1,18.0348,47.3687)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path584"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <a
-     id="a579"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="matrix(1.00002,0,0,1,18.0348,37.3687)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path578"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 305.118 85.3018 L 501.872 151.39 "
-     id="path595"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 479.841 129.844 L 501.872 151.39 "
-     id="path599"
-     transform="translate(0.000457764,-0.000205994)"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 469.137 157.769 L 501.872 151.39 "
-     id="path600"
-     sodipodi:nodetypes="cc" />
-  <a
-     id="a607"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="translate(109.908,154.154)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path608"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <a
-     id="a609"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="translate(-109.908,287.028)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path610"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <a
-     id="a611"
-     style="font-size:12;fill:#e6e6ff;stroke:#000000;stroke-width:1.25;"
-     transform="translate(4.92108,216.49)">
-    <path
-       sodipodi:type="arc"
-       style="fill-rule:evenodd;stroke:#000000;fill:#e6e6ff;fill-opacity:1;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;"
-       id="path612"
-       d="M 572.506592 120.570831 A 45.111572 22.145672 0 1 0 482.283447,120.570831 A 45.1116 22.1457 0 1 0 572.507 120.571 L 527.395020 120.570831 z"
-       sodipodi:cx="527.395020"
-       sodipodi:cy="120.570831"
-       sodipodi:rx="45.111572"
-       sodipodi:ry="22.145672" />
-  </a>
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 129.593 206.692 L 376.931 397.192 "
-     id="path614"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 224.738 234.58 L 492.3 325.857 "
-     id="path615"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 331.365 211.614 L 592.697 269.934 "
-     id="path616"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 572.507 195.21 L 633.202 253.5 "
-     id="path617"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 541.339 201.772 L 531.496 315.503 "
-     id="path618"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 511.811 195.21 L 416.013 385.276 "
-     id="path619"
-     sodipodi:nodetypes="cc" />
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Sans L;font-style:normal;font-weight:normal;font-size:24;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="504.529"
-     y="101.706"
-     id="text620">
-    <tspan
-       x="504.529"
-       y="101.706"
-       sodipodi:role="line"
-       id="tspan625">
-base</tspan>
-    <tspan
-       sodipodi:role="line"
-       id="tspan627"
-       x="504.529"
-       y="125.706">
-directory</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Sans L;font-style:normal;font-weight:normal;font-size:24;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="497.047"
-     y="395.341"
-     id="text629">
-    <tspan
-       id="tspan630">
-build</tspan>
-    <tspan
-       sodipodi:role="line"
-       id="tspan632"
-       x="497.047"
-       y="419.341">
-subdirectories</tspan>
-  </text>
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 367.683 381.34 L 376.931 397.192 "
-     id="path637"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 358.877 393.669 L 376.931 397.192 "
-     id="path640"
-     transform="translate(0.000267029,0.000289917)"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 480.851 315.73 L 492.3 325.857 "
-     id="path642"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 477.768 326.738 L 492.3 325.857 "
-     id="path643"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 580.808 261.127 L 592.697 269.934 "
-     id="path646"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-opacity:1;stroke-width:1.25;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 577.285 273.897 L 592.697 269.934 "
-     id="path647"
-     sodipodi:nodetypes="cc" />
-  <path
-     style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-opacity:1;stroke-width:2.5;stroke-linejoin:miter;stroke-linecap:butt;stroke-dasharray:none;fill-opacity:1;"
-     d="M 225.781 66.7357 L 253.45 21.533 "
-     id="path649"
-     sodipodi:nodetypes="cc" />
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Sans L;font-style:normal;font-weight:normal;font-size:18;text-anchor:start;writing-mode:lr;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
-     x="223.199"
-     y="18.3484"
-     id="text650">
-    <tspan
-       x="223.199"
-       y="18.3484"
-       sodipodi:role="line"
-       id="tspan653">
-to master</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:14;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;text-anchor:start;writing-mode:lr;"
-     x="181.871"
-     y="178.295"
-     id="text163">
-    <tspan
-       x="181.871"
-       y="178.295"
-       sodipodi:role="line"
-       id="tspan174">
-RemoteBuilder</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:12;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;text-anchor:start;writing-mode:lr;"
-     x="277.548"
-     y="153.299"
-     id="text168">
-    <tspan
-       x="277.548"
-       y="153.299"
-       sodipodi:role="line"
-       id="tspan169">
-RemoteBuilder</tspan>
-  </text>
-  <text
-     style="fill:black;stroke:none;font-family:Nimbus Roman No9 L;font-style:normal;font-weight:normal;font-size:12;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;text-anchor:start;writing-mode:lr;"
-     x="106.882"
-     y="150.713"
-     id="text171">
-    <tspan
-       x="106.882"
-       y="150.713"
-       sodipodi:role="line"
-       id="tspan172">
-RemoteBuilder</tspan>
-  </text>
-</svg>
deleted file mode 100644
--- a/docs/PyCon-2003/source/template.tpl
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
-  <head>
-    <title></title>
-    <link type="text/css" rel="stylesheet" href="stylesheet.css" />
-  </head>
-
-  <body bgcolor="white">
-    <h1 class="title"></h1>
-    <div class="toc"></div>
-    <div class="body">
-	
-    </div>
-
-  </body>
-</html>
-
deleted file mode 100644
--- a/docs/PyCon-2003/stylesheet.css
+++ /dev/null
@@ -1,180 +0,0 @@
-
-body
-{
-  margin-left: 2em;
-  margin-right: 2em;
-  border: 0px;
-  padding: 0px;
-  font-family: sans-serif;
-  }
-
-.done { color: #005500; background-color: #99ff99 }
-.notdone { color: #550000; background-color: #ff9999;}
-
-pre
-{
-  padding: 1em;
-  font-family: Neep Alt, Courier New, Courier;
-  font-size: 12pt;
-  border: thin black solid;
-}
-
-.boxed
-{
-  padding: 1em;
-  border: thin black solid;
-}
-
-.shell
-{ 
-  background-color: #ffffdd;
-}
-
-.python
-{
-  background-color: #dddddd;
-}
-
-.htmlsource
-{
-  background-color: #dddddd;
-}
-
-.py-prototype
-{
-  background-color: #ddddff;
-}
-
-
-.python-interpreter
-{
-  background-color: #ddddff;
-}
-
-.doit 
-{
-  border: thin blue dashed ;
-  background-color: #0ef
-}
-
-.py-src-comment
-{
-  color: #1111CC
-}
-
-.py-src-keyword
-{
-  color: #3333CC;
-  font-weight: bold;
-}
-
-.py-src-parameter
-{
-  color: #000066;
-  font-weight: bold;
-}
-
-.py-src-identifier
-{
-  color: #CC0000
-}
-
-.py-src-string
-{
-  
-  color: #115511
-}
-
-.py-src-endmarker
-{
-  display: block; /* IE hack; prevents following line from being sucked into the py-listing box. */
-}
-
-.py-listing 
-{
-  margin: 1ex;
-  border: thin solid black;
-  background-color: #eee;
-}
-
-.py-listing pre
-{
-  margin: 0px;
-  border: none;
-  border-bottom: thin solid black;
-}
-
-.py-listing .python 
-{
-  margin-top: 0;
-  margin-bottom: 0;
-  border: none;
-  border-bottom: thin solid black;
-  }
-
-.py-listing .htmlsource
-{
-  margin-top: 0;
-  margin-bottom: 0;
-  border: none;
-  border-bottom: thin solid black;
-  }
-
-.py-caption
-{
-  text-align: center;
-  padding-top: 0.5em;
-  padding-bottom: 0.5em;
-}
-
-.py-filename
-{
-  font-style: italic;
-  }
-
-.manhole-output
-{
-  color: blue;
-}
-
-hr
-{
-  display: inline;
-  }
-
-ul
-{
-  padding: 0px;
-  margin: 0px;
-  margin-left: 1em;
-  padding-left: 1em;
-  border-left: 1em;
-  }
-
-li
-{
-  padding: 2px;
-  }
-
-dt
-{
-  font-weight: bold;
-  margin-left: 1ex;
-  }
-
-dd
-{
-  margin-bottom: 1em;
-  }
-
-div.note
-{
-  background-color: #FFFFCC;
-  margin-top: 1ex;
-  margin-left: 5%;
-  margin-right: 5%;
-  padding-top: 1ex;
-  padding-left: 5%;
-  padding-right: 5%;
-  border: thin black solid;
-}
deleted file mode 100644
index 5df830584f709d3be93a43c5bd2172c752be5623..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/docs/buildbot.texinfo
+++ /dev/null
@@ -1,97 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename buildbot.info
-@include version.texinfo
-@settitle BuildBot Manual - @value{VERSION}
-@defcodeindex cs
-@defcodeindex sl
-@defcodeindex bf
-@defcodeindex bs
-@defcodeindex st
-@defcodeindex bc
-@defcodeindex dv
-@c %**end of header
-
-@c these indices are for classes useful in a master.cfg config file
-@c @csindex : Change Sources
-@c @slindex : Schedulers and Locks
-@c @bfindex : Build Factories
-@c @bsindex : Build Steps
-@c @stindex : Status Targets
-@c @dvindex : Developer Reference
-
-@c @bcindex : keys that make up BuildmasterConfig
-
-@copying
-This is the BuildBot manual for Buildbot version @value{VERSION}.
-
-Copyright (C) 2005, 2006, 2009, 2010 Brian Warner
-
-Copying and distribution of this file, with or without
-modification, are permitted in any medium without royalty
-provided the copyright notice and this notice are preserved.
-
-@end copying
-
-@titlepage
-@title BuildBot
-@subtitle @value{VERSION}
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@c Output the table of the contents at the beginning.
-@contents
-
-@ifnottex
-@node Top, Introduction, (dir), (dir)
-@top BuildBot
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction::                What the BuildBot does.
-* Installation::                Installing and setting up a Builbot system
-* Concepts::                    What goes on in the buildbot's little mind.
-* Configuration::               Controlling the buildbot.
-* Command-line Tool::           The 'buildbot' utility
-* Resources::                   Getting help
-* Developer Information::       Stuff Buildbot hackers should know
-* Index::                       Concept Index
-@end menu
-
-@node Introduction
-@chapter Introduction
-@include introduction.texinfo
-
-@node Installation
-@chapter Installation
-@include installation.texinfo
-
-@node Concepts
-@chapter Concepts
-@include concepts.texinfo
-
-@node Configuration
-@chapter Configuration
-@include configuration.texinfo
-
-@node Command-line Tool
-@chapter Command-line Tool
-@include cmdline.texinfo
-
-@node Resources
-@chapter Resources
-@include resources.texinfo
-
-@node Developer Information
-@chapter Developer Information
-@include developer.texinfo
-
-@node Index
-@unnumbered Index
-@printindex cp
-
-@bye
deleted file mode 100644
--- a/docs/cfg-builders.texinfo
+++ /dev/null
@@ -1,136 +0,0 @@
-@bcindex c['builders']
-
-The @code{c['builders']} key is a list of objects giving configuration for the
-Builders.  For more information, @xref{Builder}.  The class definition for the
-builder configuration is in @code{buildbot.config}.  In the configuration file,
-its use looks like:
-
-@example
-from buildbot.config import BuilderConfig
-c['builders'] = [
-    BuilderConfig(name='quick', slavenames=['bot1', 'bot2'], factory=f_quick),
-    BuilderConfig(name='thorough', slavename='bot1', factory=f_thorough),
-]
-@end example
-
-The constructor takes the following keyword arguments:
-
-@table @code
-@item name
-This specifies the Builder's name, which is used in status
-reports.
-
-@item slavename
-@item slavenames
-These arguments specify the buildslave or buildslaves that will be used by this
-Builder.  All slaves names must appear in the @code{c['slaves']} list. Each
-buildslave can accomodate multiple Builders.  The @code{slavenames} parameter
-can be a list of names, while @code{slavename} can specify only one slave.
-
-@item factory
-This is a @code{buildbot.process.factory.BuildFactory} instance which
-controls how the build is performed. Full details appear in their own
-section, @xref{Build Factories}. Parameters like the location of the CVS
-repository and the compile-time options used for the build are
-generally provided as arguments to the factory's constructor.
-
-@end table
-
-Other optional keys may be set on each Builder:
-
-@table @code
-
-@item builddir
-Specifies the name of a subdirectory (under the base directory) in which
-everything related to this builder will be placed on the buildmaster.
-This holds build status information. If not set, defaults to @code{name}
-with some characters escaped. Each builder must have a unique build
-directory.
-
-@item slavebuilddir
-Specifies the name of a subdirectory (under the base directory) in which
-everything related to this builder will be placed on the buildslave.
-This is where checkouts, compiles, and tests are run. If not set,
-defaults to @code{builddir}. If a slave is connected to multiple builders
-that share the same @code{slavebuilddir}, make sure the slave is set to
-run one build at a time or ensure this is fine to run multiple builds from
-the same directory simultaneously.
-
-@item category
-If provided, this is a string that identifies a category for the
-builder to be a part of. Status clients can limit themselves to a
-subset of the available categories. A common use for this is to add
-new builders to your setup (for a new module, or for a new buildslave)
-that do not work correctly yet and allow you to integrate them with
-the active builders. You can put these new builders in a test
-category, make your main status clients ignore them, and have only
-private status clients pick them up. As soon as they work, you can
-move them over to the active category.
-
-@item nextSlave
-If provided, this is a function that controls which slave will be assigned
-future jobs. The function is passed two arguments, the @code{Builder}
-object which is assigning a new job, and a list of @code{BuildSlave}
-objects. The function should return one of the @code{BuildSlave}
-objects, or @code{None} if none of the available slaves should be
-used.
-
-@item nextBuild
-If provided, this is a function that controls which build request will be
-handled next. The function is passed two arguments, the @code{Builder}
-object which is assigning a new job, and a list of @code{BuildRequest}
-objects of pending builds. The function should return one of the
-@code{BuildRequest} objects, or @code{None} if none of the pending
-builds should be started.
-
-@item locks
-This argument specifies a list of locks that apply to this builder; @xref{Interlocks}.
-
-@item env
-A Builder may be given a dictionary of environment variables in this parameter.
-The variables are used in @pxref{ShellCommand} steps in builds created by this
-builder. The environment variables will override anything in the buildslave's
-environment. Variables passed directly to a @code{ShellCommand} will override
-variables of the same name passed to the Builder.
-
-For example, if you a pool of identical slaves it is often easier to manage
-variables like PATH from Buildbot rather than manually editing it inside of
-the slaves' environment.
-
-@example
-f = factory.BuildFactory
-f.addStep(ShellCommand(
-              command=['bash', './configure']))
-f.addStep(Compile())
-
-c['builders'] = [
-  BuilderConfig(name='test', factory=f,
-        slavenames=['slave1', 'slave2', 'slave3', 'slave4'],
-        env=@{'PATH': '/opt/local/bin:/opt/app/bin:/usr/local/bin:/usr/bin'@}),
-]
-@end example
-
-@item mergeRequests
-This boolean defaults to True, which means that the Builder might
-attempt to merge @code{BuildRequest}s into a single build. If False,
-the Builder will never attempt to merge requests.
-
-Merging requests helps to reduce the total number of builds, but loses
-information about which exact change might have caused a build
-problem. Requests can only be merged for compatible SourceStamps, for
-example two Changes that occur on the same branch, or two requests to
-build 'HEAD' (i.e. the latest checkin) on the same branch.
-
-The buildmaster's @code{c['mergeRequests']} hook function is evaluated
-only if the Builder's @code{mergeRequests} key is True, so merging
-only takes place if both allow it. @pxref{Merging BuildRequests}.
-
-@item properties
-A builder may be given a dictionnary of @pxref{Build Properties}
-specific for this builder in this parameter. Those values can be used
-later on like other properties. @pxref{WithProperties}.
-
-@end table
-
-
-
deleted file mode 100644
--- a/docs/cfg-buildfactories.texinfo
+++ /dev/null
@@ -1,524 +0,0 @@
-Each Builder is equipped with a ``build factory'', which is
-responsible for producing the actual @code{Build} objects that perform
-each build. This factory is created in the configuration file, and
-attached to a Builder through the @code{factory} element of its
-dictionary.
-
-The standard @code{BuildFactory} object creates @code{Build} objects
-by default. These Builds will each execute a collection of BuildSteps
-in a fixed sequence. Each step can affect the results of the build,
-but in general there is little intelligence to tie the different steps
-together. 
-
-The steps used by these builds are all subclasses of @code{BuildStep}.
-The standard ones provided with Buildbot are documented later,
-@xref{Build Steps}. You can also write your own subclasses to use in
-builds.
-
-The basic behavior for a @code{BuildStep} is to:
-
-@itemize @bullet
-@item
-run for a while, then stop
-@item
-possibly invoke some RemoteCommands on the attached build slave
-@item
-possibly produce a set of log files
-@item
-finish with a status described by one of four values defined in
-buildbot.status.builder: SUCCESS, WARNINGS, FAILURE, SKIPPED
-@item
-provide a list of short strings to describe the step
-@end itemize
-
-@menu
-* BuildFactory::
-* GNUAutoconf::
-* BasicBuildFactory::
-* BasicSVN::
-* QuickBuildFactory::
-* CPAN::
-* Distutils::
-* Trial (Factory)::
-* Build Factory Index::
-@end menu
-
-@node BuildFactory
-@subsection BuildFactory
-
-@bfindex buildbot.process.factory.BuildFactory
-
-A BuildFactory defines the steps that every build will follow.  Think of it as
-a glorified script.  For example, a build which consists of a CVS checkout
-followed by a @code{make build} would be constructed as follows:
-
-@example
-from buildbot.steps import source, shell
-from buildbot.process import factory
-
-f = factory.BuildFactory()
-f.addStep(source.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"))
-f.addStep(shell.Compile(command=["make", "build"]))
-@end example
-
-It is also possible to pass a list of steps into the
-@code{BuildFactory} when it is created. Using @code{addStep} is
-usually simpler, but there are cases where is is more convenient to
-create the list of steps ahead of time, perhaps using some Python
-tricks to generate the steps.
-
-@example
-from buildbot.steps import source, shell
-from buildbot.process import factory
-
-all_steps = [
-    source.CVS(cvsroot=CVSROOT, cvsmodule="project", mode="update"),
-    shell.Compile(command=["make", "build"]),
-]
-f = factory.BuildFactory(all_steps)
-@end example
-
-Finally, you can also add a sequence of steps all at once:
-
-@example
-f.addSteps(all_steps)
-@end example
-
-@heading Attributes
-
-@table @code
-
-@item useProgress
-(defaults to True): if True, the buildmaster keeps track of how long
-each step takes, so it can provide estimates of how long future builds
-will take. If builds are not expected to take a consistent amount of
-time (such as incremental builds in which a random set of files are
-recompiled or tested each time), this should be set to False to
-inhibit progress-tracking.
-
-@item workdir
-(defaults to 'build'): workdir given to every build step created by
-this factory as default. The workdir can be overridden in a build step
-definition.
-If this attribute is set to a string, that string will be used
-for constructing the workdir (buildslave base + builder builddir +
-workdir). If this attributed is set to a Python callable, that
-callable will be called with SourceStamp as single parameter and
-is supposed to return a string which will be used as above.
-The latter is useful in scenarios with multiple repositories
-submitting changes to BuildBot. In this case you likely will want
-to have a dedicated workdir per repository, since otherwise a
-sourcing step with mode = "update" will fail as a workdir with
-a working copy of repository A can't be "updated" for changes
-from a repository B. Here is an example how you can achive
-workdir-per-repo:
-
-@example
-#
-# pre-repository working directory
-#
-def workdir (source_stamp):
-    return hashlib.md5 (source_stamp.repository).hexdigest ()[:8]
-
-build = factory.BuildFactory()
-build.workdir = workdir
-
-build.addStep (Git (mode = "update"))
-...
-builders.append (@{'name': 'mybuilder',
-                  'slavename': 'myslave',
-                  'builddir': 'mybuilder',
-                  'factory': build@})
-
-# You'll end up with workdirs like:
-#
-# Repo1 => <buildslave-base>/mybuilder/a78890ba
-# Repo2	=> <buildslave-base>/mybuilder/0823ba88
-# ...
-@end example
-
-You could make the workdir() function compute other paths, based on
-parts of the repo URL in the sourcestamp, or lookup in a lookup table
-based on repo URL. As long as there is a permanent 1:1 mapping between
-repos and workdir this will work.
-@end table
-
-@heading Implementation Note
-
-The default @code{BuildFactory}, provided in the
-@code{buildbot.process.factory} module, contains an internal list of
-``BuildStep specifications'': a list of @code{(step_class, kwargs)}
-tuples for each. These specification tuples are constructed when the
-config file is read, by asking the instances passed to @code{addStep}
-for their subclass and arguments.
-
-To support config files from buildbot-0.7.5 and earlier,
-@code{addStep} also accepts the @code{f.addStep(shell.Compile,
-command=["make","build"])} form, although its use is discouraged
-because then the @code{Compile} step doesn't get to validate or
-complain about its arguments until build time. The modern
-pass-by-instance approach allows this validation to occur while the
-config file is being loaded, where the admin has a better chance of
-noticing problems.
-
-When asked to create a Build, the @code{BuildFactory} puts a copy of
-the list of step specifications into the new Build object. When the
-Build is actually started, these step specifications are used to
-create the actual set of BuildSteps, which are then executed one at a
-time. This serves to give each Build an independent copy of each step.
-
-Each step can affect the build process in the following ways:
-
-@itemize @bullet
-@item
-If the step's @code{haltOnFailure} attribute is True, then a failure
-in the step (i.e. if it completes with a result of FAILURE) will cause
-the whole build to be terminated immediately: no further steps will be
-executed, with the exception of steps with @code{alwaysRun} set to
-True. @code{haltOnFailure} is useful for setup steps upon which the
-rest of the build depends: if the CVS checkout or @code{./configure}
-process fails, there is no point in trying to compile or test the
-resulting tree.
-
-@item
-If the step's @code{alwaysRun} attribute is True, then it will always
-be run, regardless of if previous steps have failed. This is useful
-for cleanup steps that should always be run to return the build
-directory or build slave into a good state.
-
-@item
-If the @code{flunkOnFailure} or @code{flunkOnWarnings} flag is set,
-then a result of FAILURE or WARNINGS will mark the build as a whole as
-FAILED. However, the remaining steps will still be executed. This is
-appropriate for things like multiple testing steps: a failure in any
-one of them will indicate that the build has failed, however it is
-still useful to run them all to completion.
-
-@item
-Similarly, if the @code{warnOnFailure} or @code{warnOnWarnings} flag
-is set, then a result of FAILURE or WARNINGS will mark the build as
-having WARNINGS, and the remaining steps will still be executed. This
-may be appropriate for certain kinds of optional build or test steps.
-For example, a failure experienced while building documentation files
-should be made visible with a WARNINGS result but not be serious
-enough to warrant marking the whole build with a FAILURE.
-
-@end itemize
-
-In addition, each Step produces its own results, may create logfiles,
-etc. However only the flags described above have any effect on the
-build as a whole.
-
-The pre-defined BuildSteps like @code{CVS} and @code{Compile} have
-reasonably appropriate flags set on them already. For example, without
-a source tree there is no point in continuing the build, so the
-@code{CVS} class has the @code{haltOnFailure} flag set to True. Look
-in @file{buildbot/steps/*.py} to see how the other Steps are
-marked.
-
-Each Step is created with an additional @code{workdir} argument that
-indicates where its actions should take place. This is specified as a
-subdirectory of the slave builder's base directory, with a default
-value of @code{build}. This is only implemented as a step argument (as
-opposed to simply being a part of the base directory) because the
-CVS/SVN steps need to perform their checkouts from the parent
-directory.
-
-@node GNUAutoconf
-@subsection GNUAutoconf
-@bfindex buildbot.process.factory.GNUAutoconf
-
-@uref{http://www.gnu.org/software/autoconf/, GNU Autoconf} is a
-software portability tool, intended to make it possible to write
-programs in C (and other languages) which will run on a variety of
-UNIX-like systems. Most GNU software is built using autoconf. It is
-frequently used in combination with GNU automake. These tools both
-encourage a build process which usually looks like this:
-
-@example
-% CONFIG_ENV=foo ./configure --with-flags
-% make all
-% make check
-# make install
-@end example
-
-(except of course the Buildbot always skips the @code{make install}
-part).
-
-The Buildbot's @code{buildbot.process.factory.GNUAutoconf} factory is
-designed to build projects which use GNU autoconf and/or automake. The
-configuration environment variables, the configure flags, and command
-lines used for the compile and test are all configurable, in general
-the default values will be suitable.
-
-Example:
-
-@example
-f = factory.GNUAutoconf(source=source.SVN(svnurl=URL, mode="copy"),
-                        flags=["--disable-nls"])
-@end example
-
-Required Arguments:
-
-@table @code
-@item source
-This argument must be a step specification tuple that provides a
-BuildStep to generate the source tree.
-@end table
-
-Optional Arguments:
-
-@table @code
-@item configure
-The command used to configure the tree. Defaults to
-@code{./configure}. Accepts either a string or a list of shell argv
-elements.
-
-@item configureEnv
-The environment used for the initial configuration step. This accepts
-a dictionary which will be merged into the buildslave's normal
-environment. This is commonly used to provide things like
-@code{CFLAGS="-O2 -g"} (to turn off debug symbols during the compile).
-Defaults to an empty dictionary.
-
-@item configureFlags
-A list of flags to be appended to the argument list of the configure
-command. This is commonly used to enable or disable specific features
-of the autoconf-controlled package, like @code{["--without-x"]} to
-disable windowing support. Defaults to an empty list.
-
-@item compile
-this is a shell command or list of argv values which is used to
-actually compile the tree. It defaults to @code{make all}. If set to
-None, the compile step is skipped.
-
-@item test
-this is a shell command or list of argv values which is used to run
-the tree's self-tests. It defaults to @code{make check}. If set to
-None, the test step is skipped.
-
-@end table
-
-@node BasicBuildFactory
-@subsection BasicBuildFactory
-@bfindex buildbot.process.factory.BasicBuildFactory
-
-This is a subclass of @code{GNUAutoconf} which assumes the source is in CVS,
-and uses @code{mode='clobber'} to always build from a clean working copy.
-
-@node BasicSVN
-@subsection BasicSVN
-@bfindex buildbot.process.factory.BasicSVN
-
-This class is similar to @ref{BasicBuildFactory}, but uses SVN instead of CVS.
-
-@node QuickBuildFactory
-@subsection QuickBuildFactory
-@bfindex buildbot.process.factory.QuickBuildFactory
-
-The @code{QuickBuildFactory} class is a subclass of @code{GNUAutoconf} which
-assumes the source is in CVS, and uses @code{mode='update'} to get incremental
-updates.
-
-The difference between a ``full build'' and a ``quick build'' is that
-quick builds are generally done incrementally, starting with the tree
-where the previous build was performed. That simply means that the
-source-checkout step should be given a @code{mode='update'} flag, to
-do the source update in-place.
-