Merged buildbot-0.8.2rc2 into 'default', preserving local changes
authorDustin J. Mitchell <dustin@mozilla.com>
Thu, 28 Oct 2010 17:15:56 -0500
changeset 98 d23e1cd7604b797cd845b2290e8b9db06909f1c5
parent 95 58225ba726780fbe6ce9adce00690952b5920906 (current diff)
parent 97 c2e02e5bbfdb1c7a463cb44d75b06d45070597d3 (diff)
child 100 ff16a0ec34176008e2576f1ffc99a075e6638c9c
push id41
push userdmitchell@mozilla.com
push dateWed, 17 Nov 2010 14:22:22 +0000
Merged buildbot-0.8.2rc2 into 'default', preserving local changes
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/buildbot/changes/monotone.py
master/buildbot/process/base.py
master/buildbot/process/builder.py
master/buildbot/process/buildstep.py
master/buildbot/status/builder.py
master/buildbot/status/tinderbox.py
master/buildbot/status/web/xmlrpc.py
master/buildbot/steps/transfer.py
master/buildbot/test/unit/test_steps_transfer.py
slave/buildslave/bot.py
slave/buildslave/commands/mozilla.py
slave/buildslave/commands/registry.py
slave/buildslave/commands/vcs.py
slave/buildslave/test/unit/test_slave_commands_base.py
slave/buildslave/test/unit/test_slave_commands_utils.py
slave/buildslave/test/util.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.
-
-In addition to that, this class sets teh @code{useProgress} flag to False.
-Incremental builds will (or at least the ought to) compile as few files as
-necessary, so they will take an unpredictable amount of time to run. Therefore
-it would be misleading to claim to predict how long the build will take.
-
-This class is probably not of use to new projects.
-
-@node CPAN
-@subsection CPAN
-@bfindex buildbot.process.factory.CPAN
-
-Most Perl modules available from the @uref{http://www.cpan.org/, CPAN}
-archive use the @code{MakeMaker} module to provide configuration,
-build, and test services. The standard build routine for these modules
-looks like:
-
-@example
-% perl Makefile.PL
-% make
-% make test
-# make install
-@end example
-
-(except again Buildbot skips the install step)
-
-Buildbot provides a @code{CPAN} factory to compile and test these
-projects.
-
-Arguments:
-@table @code
-@item source
-(required): A step specification tuple, like that used by GNUAutoconf.
-
-@item perl
-A string which specifies the @code{perl} executable to use. Defaults
-to just @code{perl}.
-
-@end table
-
-@node Distutils
-@subsection Distutils
-
-@bfindex buildbot.process.factory.Distutils
-
-Most Python modules use the @code{distutils} package to provide
-configuration and build services. The standard build process looks
-like:
-
-@example
-% python ./setup.py build
-% python ./setup.py install
-@end example
-
-Unfortunately, although Python provides a standard unit-test framework
-named @code{unittest}, to the best of my knowledge @code{distutils}
-does not provide a standardized target to run such unit tests. (Please
-let me know if I'm wrong, and I will update this factory.)
-
-The @code{Distutils} factory provides support for running the build
-part of this process. It accepts the same @code{source=} parameter as
-the other build factories.
-
-Arguments:
-@table @code
-@item source
-(required): A step specification tuple, like that used by GNUAutoconf.
-
-@item python
-A string which specifies the @code{python} executable to use. Defaults
-to just @code{python}.
-
-@item test
-Provides a shell command which runs unit tests. This accepts either a
-string or a list. The default value is None, which disables the test
-step (since there is no common default command to run unit tests in
-distutils modules).
-
-@end table
-
-
-@node Trial (Factory)
-@subsection Trial
-
-@bfindex buildbot.process.factory.Trial
-
-Twisted provides a unit test tool named @code{trial} which provides a
-few improvements over Python's built-in @code{unittest} module. Many
-python projects which use Twisted for their networking or application
-services also use trial for their unit tests. These modules are
-usually built and tested with something like the following:
-
-@example
-% python ./setup.py build
-% PYTHONPATH=build/lib.linux-i686-2.3 trial -v PROJECTNAME.test
-% python ./setup.py install
-@end example
-
-Unfortunately, the @file{build/lib} directory into which the
-built/copied .py files are placed is actually architecture-dependent,
-and I do not yet know of a simple way to calculate its value. For many
-projects it is sufficient to import their libraries ``in place'' from
-the tree's base directory (@code{PYTHONPATH=.}).
-
-In addition, the @var{PROJECTNAME} value where the test files are
-located is project-dependent: it is usually just the project's
-top-level library directory, as common practice suggests the unit test
-files are put in the @code{test} sub-module. This value cannot be
-guessed, the @code{Trial} class must be told where to find the test
-files.
-
-The @code{Trial} class provides support for building and testing
-projects which use distutils and trial. If the test module name is
-specified, trial will be invoked. The library path used for testing
-can also be set.
-
-One advantage of trial is that the Buildbot happens to know how to
-parse trial output, letting it identify which tests passed and which
-ones failed. The Buildbot can then provide fine-grained reports about
-how many tests have failed, when individual tests fail when they had
-been passing previously, etc.
-
-Another feature of trial is that you can give it a series of source
-.py files, and it will search them for special @code{test-case-name}
-tags that indicate which test cases provide coverage for that file.
-Trial can then run just the appropriate tests. This is useful for
-quick builds, where you want to only run the test cases that cover the
-changed functionality.
-
-Arguments:
-@table @code
-@item testpath
-Provides a directory to add to @code{PYTHONPATH} when running the unit
-tests, if tests are being run. Defaults to @code{.} to include the
-project files in-place. The generated build library is frequently
-architecture-dependent, but may simply be @file{build/lib} for
-pure-python modules.
-
-@item python
-which python executable to use. This list will form the start of
-the argv array that will launch trial. If you use this,
-you should set @code{trial} to an explicit path (like
-@code{/usr/bin/trial} or @code{./bin/trial}). The parameter defaults to @code{None}, which
-leaves it out entirely (running @code{trial args} instead of
-@code{python ./bin/trial args}). Likely values are @code{['python']},
-@code{['python2.2']}, or @code{['python', '-Wall']}.
-
-@item trial
-provides the name of the @code{trial} command. It is occasionally
-useful to use an alternate executable, such as @code{trial2.2} which
-might run the tests under an older version of Python. Defaults to
-@code{trial}.
-
-@item trialMode
-a list of arguments to pass to trial, specifically to set the reporting mode.
-This defaults to @code{['--reporter=bwverbose']}, which only works for
-Twisted-2.1.0 and later.
-
-@item trialArgs
-a list of arguments to pass to trial, available to turn on any extra flags you
-like. Defaults to @code{[]}.
-
-@item tests
-Provides a module name or names which contain the unit tests for this
-project. Accepts a string, typically @code{PROJECTNAME.test}, or a
-list of strings. Defaults to None, indicating that no tests should be
-run. You must either set this or @code{testChanges}.
-
-@item testChanges
-if True, ignore the @code{tests} parameter and instead ask the Build for all
-the files that make up the Changes going into this build. Pass these filenames
-to trial and ask it to look for test-case-name tags, running just the tests
-necessary to cover the changes.
-
-@item recurse
-If @code{True}, tells Trial (with the @code{--recurse} argument) to look in all
-subdirectories for additional test cases.
-
-@item reactor
-which reactor to use, like 'gtk' or 'java'. If not provided, the Twisted's
-usual platform-dependent default is used.
-
-@item randomly
-If @code{True}, tells Trial (with the @code{--random=0} argument) to
-run the test cases in random order, which sometimes catches subtle
-inter-test dependency bugs. Defaults to @code{False}.
-@end table
-
-The step can also take any of the @code{ShellCommand} arguments, e.g.,
-@code{haltOnFailure}.
-
-Unless one of @code{tests} or @code{testChanges} are set, the step will
-generate an exception.
-
-@node Build Factory Index
-@subsection Build Factory Index
-@printindex bf
deleted file mode 100644
--- a/docs/cfg-buildslaves.texinfo
+++ /dev/null
@@ -1,395 +0,0 @@
-@bcindex c['slaves']
-
-The @code{c['slaves']} key is a list of known buildslaves. In the common case,
-each buildslave is defined by an instance of the BuildSlave class.  It
-represents a standard, manually started machine that will try to connect to
-the buildbot master as a slave.  Contrast these with the "on-demand" latent
-buildslaves, such as the Amazon Web Service Elastic Compute Cloud latent
-buildslave discussed below.
-
-The BuildSlave class is instantiated with two values: (slavename,
-slavepassword). These are the same two values that need to be provided to the
-buildslave administrator when they create the buildslave.
-
-The slavenames must be unique, of course. The password exists to
-prevent evildoers from interfering with the buildbot by inserting
-their own (broken) buildslaves into the system and thus displacing the
-real ones.
-
-Buildslaves with an unrecognized slavename or a non-matching password
-will be rejected when they attempt to connect, and a message
-describing the problem will be put in the log file (see @ref{Logfiles}).
-
-@example
-from buildbot.buildslave import BuildSlave
-c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd')
-               BuildSlave('bot-bsd', 'bsdpasswd')
-              ]
-@end example
-
-@cindex Properties
-@code{BuildSlave} objects can also be created with an optional
-@code{properties} argument, a dictionary specifying properties that
-will be available to any builds performed on this slave.  For example:
-
-@example
-from buildbot.buildslave import BuildSlave
-c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd',
-                    properties=@{'os':'solaris'@}),
-              ]
-@end example
-
-The @code{BuildSlave} constructor can also take an optional
-@code{max_builds} parameter to limit the number of builds that it
-will execute simultaneously:
-
-@example
-from buildbot.buildslave import BuildSlave
-c['slaves'] = [BuildSlave("bot-linux", "linuxpassword", max_builds=2)]
-@end example
-
-@menu
-* When Buildslaves Go Missing::
-* Latent Buildslaves::
-@end menu
-
-@node When Buildslaves Go Missing
-@subsection When Buildslaves Go Missing
-
-Sometimes, the buildslaves go away. One very common reason for this is
-when the buildslave process is started once (manually) and left
-running, but then later the machine reboots and the process is not
-automatically restarted.
-
-If you'd like to have the administrator of the buildslave (or other
-people) be notified by email when the buildslave has been missing for
-too long, just add the @code{notify_on_missing=} argument to the
-@code{BuildSlave} definition:
-
-@example
-c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd',
-                          notify_on_missing="bob@@example.com"),
-              ]
-@end example
-
-By default, this will send email when the buildslave has been
-disconnected for more than one hour. Only one email per
-connection-loss event will be sent. To change the timeout, use
-@code{missing_timeout=} and give it a number of seconds (the default
-is 3600).
-
-You can have the buildmaster send email to multiple recipients: just
-provide a list of addresses instead of a single one:
-
-@example
-c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd',
-                          notify_on_missing=["bob@@example.com",
-                                             "alice@@example.org"],
-                          missing_timeout=300, # notify after 5 minutes
-                          ),
-              ]
-@end example
-
-The email sent this way will use a MailNotifier (@pxref{MailNotifier})
-status target, if one is configured. This provides a way for you to
-control the ``from'' address of the email, as well as the relayhost
-(aka ``smarthost'') to use as an SMTP server. If no MailNotifier is
-configured on this buildmaster, the buildslave-missing emails will be
-sent using a default configuration.
-
-Note that if you want to have a MailNotifier for buildslave-missing
-emails but not for regular build emails, just create one with
-builders=[], as follows:
-
-@example
-from buildbot.status import mail
-m = mail.MailNotifier(fromaddr="buildbot@@localhost", builders=[],
-                      relayhost="smtp.example.org")
-c['status'].append(m)
-c['slaves'] = [BuildSlave('bot-solaris', 'solarispasswd',
-                          notify_on_missing="bob@@example.com"),
-              ]
-@end example
-
-@node Latent Buildslaves
-@subsection Latent Buildslaves
-
-The standard buildbot model has slaves started manually.  The previous section
-described how to configure the master for this approach.
-
-Another approach is to let the buildbot master start slaves when builds are
-ready, on-demand.  Thanks to services such as Amazon Web Services' Elastic
-Compute Cloud ("AWS EC2"), this is relatively easy to set up, and can be
-very useful for some situations.
-
-The buildslaves that are started on-demand are called "latent" buildslaves.
-As of this writing, buildbot ships with an abstract base class for building
-latent buildslaves, and a concrete implementation for AWS EC2.
-
-@menu
-* Amazon Web Services Elastic Compute Cloud ("AWS EC2")::
-* Dangers with Latent Buildslaves::
-* Writing New Latent Buildslaves::
-@end menu
-
-@node Amazon Web Services Elastic Compute Cloud ("AWS EC2")
-@subsubsection Amazon Web Services Elastic Compute Cloud ("AWS EC2")
-
-@url{http://aws.amazon.com/ec2/,,AWS EC2} is a web service that allows you to
-start virtual machines in an Amazon data center. Please see their website for
-details, incuding costs. Using the AWS EC2 latent buildslaves involves getting
-an EC2 account with AWS and setting up payment; customizing one or more EC2
-machine images ("AMIs") on your desired operating system(s) and publishing
-them (privately if needed); and configuring the buildbot master to know how to
-start your customized images for "substantiating" your latent slaves.
-
-@heading Get an AWS EC2 Account
-
-To start off, to use the AWS EC2 latent buildslave, you need to get an AWS
-developer account and sign up for EC2. These instructions may help you get
-started:
-
-@itemize @bullet
-@item
-Go to http://aws.amazon.com/ and click to "Sign Up Now" for an AWS account.
-
-@item
-Once you are logged into your account, you need to sign up for EC2.
-Instructions for how to do this have changed over time because Amazon changes
-their website, so the best advice is to hunt for it. After signing up for EC2,
-it may say it wants you to upload an x.509 cert. You will need this to create
-images (see below) but it is not technically necessary for the buildbot master
-configuration.
-
-@item
-You must enter a valid credit card before you will be able to use EC2. Do that
-under 'Payment Method'.
-
-@item
-Make sure you're signed up for EC2 by going to 'Your Account'->'Account
-Activity' and verifying EC2 is listed.
-@end itemize
-
-@heading Create an AMI
-
-Now you need to create an AMI and configure the master.  You may need to
-run through this cycle a few times to get it working, but these instructions
-should get you started.
-
-Creating an AMI is out of the scope of this document.  The
-@url{http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/,,EC2 Getting Started Guide}
-is a good resource for this task.  Here are a few additional hints.
-
-@itemize @bullet
-@item
-When an instance of the image starts, it needs to automatically start a
-buildbot slave that connects to your master (to create a buildbot slave,
-@pxref{Creating a buildslave}; to make a daemon,
-@pxref{Launching the daemons}).
-
-@item
-You may want to make an instance of the buildbot slave, configure it as a
-standard buildslave in the master (i.e., not as a latent slave), and test and
-debug it that way before you turn it into an AMI and convert to a latent
-slave in the master.
-@end itemize
-
-@heading Configure the Master with an EC2LatentBuildSlave
-
-Now let's assume you have an AMI that should work with the
-EC2LatentBuildSlave.  It's now time to set up your buildbot master
-configuration.
-
-You will need some information from your AWS account: the "Access Key Id" and
-the "Secret Access Key".  If you've built the AMI yourself, you probably
-already are familiar with these values.  If you have not, and someone has
-given you access to an AMI, these hints may help you find the necessary
-values:
-
-@itemize @bullet
-@item
-While logged into your AWS account, find the "Access Identifiers" link (either
-on the left, or via "Your Account" -> "Access Identifiers".
-
-@item
-On the page, you'll see alphanumeric values for "Your Access Key Id:" and
-"Your Secret Access Key:". Make a note of these. Later on, we'll call the
-first one your "identifier" and the second one your "secret_identifier."
-@end itemize
-
-When creating an EC2LatentBuildSlave in the buildbot master configuration,
-the first three arguments are required.  The name and password are the first
-two arguments, and work the same as with normal buildslaves.  The next
-argument specifies the type of the EC2 virtual machine (available options as
-of this writing include "m1.small", "m1.large", 'm1.xlarge", "c1.medium",
-and "c1.xlarge"; see the EC2 documentation for descriptions of these
-machines).
-
-Here is the simplest example of configuring an EC2 latent buildslave. It
-specifies all necessary remaining values explicitly in the instantiation.
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large',
-                                   ami='ami-12345',
-                                   identifier='publickey',
-                                   secret_identifier='privatekey'
-                                   )]
-@end example
-
-The "ami" argument specifies the AMI that the master should start.  The
-"identifier" argument specifies the AWS "Access Key Id," and the
-"secret_identifier" specifies the AWS "Secret Access Key." Both the AMI and
-the account information can be specified in alternate ways.
-
-Note that whoever has your identifier and secret_identifier values can request
-AWS work charged to your account, so these values need to be carefully
-protected. Another way to specify these access keys is to put them in a
-separate file. You can then make the access privileges stricter for this
-separate file, and potentially let more people read your main configuration
-file.
-
-By default, you can make an .ec2 directory in the home folder of the user
-running the buildbot master. In that directory, create a file called aws_id.
-The first line of that file should be your access key id; the second line
-should be your secret access key id. Then you can instantiate the build slave
-as follows.
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large',
-                                   ami='ami-12345')]
-@end example
-
-If you want to put the key information in another file, use the
-"aws_id_file_path" initialization argument.
-
-Previous examples used a particular AMI.  If the Buildbot master will be
-deployed in a process-controlled environment, it may be convenient to
-specify the AMI more flexibly.  Rather than specifying an individual AMI,
-specify one or two AMI filters.
-
-In all cases, the AMI that sorts last by its location (the S3 bucket and
-manifest name) will be preferred.
-
-One available filter is to specify the acceptable AMI owners, by AWS account
-number (the 12 digit number, usually rendered in AWS with hyphens like
-"1234-5678-9012", should be entered as in integer).
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-bot1 = EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large',
-                           valid_ami_owners=[11111111111,
-                                             22222222222],
-                           identifier='publickey',
-                           secret_identifier='privatekey'
-                           )
-@end example
-
-The other available filter is to provide a regular expression string that
-will be matched against each AMI's location (the S3 bucket and manifest name).
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-bot1 = EC2LatentBuildSlave(
-    'bot1', 'sekrit', 'm1.large',
-    valid_ami_location_regex=r'buildbot\-.*/image.manifest.xml',
-    identifier='publickey', secret_identifier='privatekey')
-@end example
-
-The regular expression can specify a group, which will be preferred for the
-sorting.  Only the first group is used; subsequent groups are ignored.
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-bot1 = EC2LatentBuildSlave(
-    'bot1', 'sekrit', 'm1.large',
-    valid_ami_location_regex=r'buildbot\-.*\-(.*)/image.manifest.xml',
-    identifier='publickey', secret_identifier='privatekey')
-@end example
-
-If the group can be cast to an integer, it will be.  This allows 10 to sort
-after 1, for instance.
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-bot1 = EC2LatentBuildSlave(
-    'bot1', 'sekrit', 'm1.large',
-    valid_ami_location_regex=r'buildbot\-.*\-(\d+)/image.manifest.xml',
-    identifier='publickey', secret_identifier='privatekey')
-@end example
-
-In addition to using the password as a handshake between the master and the
-slave, you may want to use a firewall to assert that only machines from a
-specific IP can connect as slaves.  This is possible with AWS EC2 by using
-the Elastic IP feature.  To configure, generate a Elastic IP in AWS, and then
-specify it in your configuration using the "elastic_ip" argument.
-
-@example
-from buildbot.ec2buildslave import EC2LatentBuildSlave
-c['slaves'] = [EC2LatentBuildSlave('bot1', 'sekrit', 'm1.large',
-                                   'ami-12345',
-                                   identifier='publickey',
-                                   secret_identifier='privatekey',
-                                   elastic_ip='208.77.188.166'
-                                   )]
-@end example
-
-The EC2LatentBuildSlave supports all other configuration from the standard
-BuildSlave.  The "missing_timeout" and "notify_on_missing" specify how long
-to wait for an EC2 instance to attach before considering the attempt to have
-failed, and email addresses to alert, respectively.  "missing_timeout"
-defaults to 20 minutes.
-
-The "build_wait_timeout" allows you to specify how long an EC2LatentBuildSlave
-should wait after a build for another build before it shuts down the EC2
-instance.  It defaults to 10 minutes.
-
-"keypair_name" and "security_name" allow you to specify different names for
-these AWS EC2 values.  They both default to "latent_buildbot_slave".
-
-@node Dangers with Latent Buildslaves
-@subsubsection Dangers with Latent Buildslaves
-
-Any latent build slave that interacts with a for-fee service, such as the
-EC2LatentBuildSlave, brings significant risks. As already identified, the
-configuraton will need access to account information that, if obtained by a
-criminal, can be used to charge services to your account. Also, bugs in the
-buildbot software may lead to unnecessary charges. In particular, if the
-master neglects to shut down an instance for some reason, a virtual machine
-may be running unnecessarily, charging against your account. Manual and/or
-automatic (e.g. nagios with a plugin using a library like boto)
-double-checking may be appropriate.
-
-A comparitively trivial note is that currently if two instances try to attach
-to the same latent buildslave, it is likely that the system will become
-confused.  This should not occur, unless, for instance, you configure a normal
-build slave to connect with the authentication of a latent buildbot.  If the
-situation occurs, stop all attached instances and restart the master.
-
-@node Writing New Latent Buildslaves
-@subsubsection Writing New Latent Buildslaves
-
-Writing a new latent buildslave should only require subclassing
-@code{buildbot.buildslave.AbstractLatentBuildSlave} and implementing
-start_instance and stop_instance.
-
-@example
-def start_instance(self):
-    # responsible for starting instance that will try to connect with this
-    # master. Should return deferred. Problems should use an errback. The
-    # callback value can be None, or can be an iterable of short strings to
-    # include in the "substantiate success" status message, such as
-    # identifying the instance that started.
-    raise NotImplementedError
-
-def stop_instance(self, fast=False):
-    # responsible for shutting down instance. Return a deferred. If `fast`,
-    # we're trying to shut the master down, so callback as soon as is safe.
-    # Callback value is ignored.
-    raise NotImplementedError
-@end example
-
-See @code{buildbot.ec2buildslave.EC2LatentBuildSlave} for an example, or see the
-test example @code{buildbot.test_slaves.FakeLatentBuildSlave}.
-
deleted file mode 100644
--- a/docs/cfg-buildsteps.texinfo
+++ /dev/null
@@ -1,2409 +0,0 @@
-@c TODO: go over this file to organize into classes
-@c and be sure all index entries are in place
-
-@c TODO:
-@c @bsindex buildbot.steps.python_twisted.HLint
-@c @bsindex buildbot.steps.python_twisted.Trial
-@c @bsindex buildbot.steps.python_twisted.ProcessDocs
-@c @bsindex buildbot.steps.python_twisted.BuildDebs
-@c @bsindex buildbot.steps.python_twisted.RemovePYCs
-
-@code{BuildStep}s are usually specified in the buildmaster's
-configuration file, in a list that goes into the @code{BuildFactory}.
-The @code{BuildStep} instances in this list are used as templates to
-construct new independent copies for each build (so that state can be
-kept on the @code{BuildStep} in one build without affecting a later
-build). Each @code{BuildFactory} can be created with a list of steps,
-or the factory can be created empty and then steps added to it using
-the @code{addStep} method:
-
-@example
-from buildbot.steps import source, shell
-from buildbot.process import factory
-
-f = factory.BuildFactory()
-f.addStep(source.SVN(svnurl="http://svn.example.org/Trunk/"))
-f.addStep(shell.ShellCommand(command=["make", "all"]))
-f.addStep(shell.ShellCommand(command=["make", "test"]))
-@end example
-
-The rest of this section lists all the standard BuildStep objects
-available for use in a Build, and the parameters which can be used to
-control each.
-
-@menu
-* Common Parameters::
-* Using Build Properties::
-* Source Checkout::
-* ShellCommand::
-* Python BuildSteps::
-* Transferring Files::
-* Steps That Run on the Master::
-* Triggering Schedulers::
-* Writing New BuildSteps::
-* Build Step Index::
-@end menu
-
-@node Common Parameters
-@subsection Common Parameters
-
-All BuildSteps accept some common parameters. Some of these control
-how their individual status affects the overall build. Others are used
-to specify which @code{Locks} (see @pxref{Interlocks}) should be
-acquired before allowing the step to run.
-
-Arguments common to all @code{BuildStep} subclasses:
-
-@table @code
-@item name
-the name used to describe the step on the status display. It is also
-used to give a name to any LogFiles created by this step.
-
-@item haltOnFailure
-if True, a FAILURE of this build step will cause the build to halt
-immediately. Steps with @code{alwaysRun=True} are still run. Generally
-speaking, haltOnFailure implies flunkOnFailure (the default for most
-BuildSteps). In some cases, particularly series of tests, it makes sense
-to haltOnFailure if something fails early on but not flunkOnFailure.
-This can be achieved with haltOnFailure=True, flunkOnFailure=False.
-
-@item flunkOnWarnings
-when True, a WARNINGS or FAILURE of this build step will mark the
-overall build as FAILURE. The remaining steps will still be executed.
-
-@item flunkOnFailure
-when True, a FAILURE of this build step will mark the overall build as
-a FAILURE. The remaining steps will still be executed.
-
-@item warnOnWarnings
-when True, a WARNINGS or FAILURE of this build step will mark the
-overall build as having WARNINGS. The remaining steps will still be
-executed.
-
-@item warnOnFailure
-when True, a FAILURE of this build step will mark the overall build as
-having WARNINGS. The remaining steps will still be executed.
-
-@item alwaysRun
-if True, this build step will always be run, even if a previous buildstep
-with @code{haltOnFailure=True} has failed.
-
-@item doStepIf
-A step can be configured to only run under certain conditions.  To do this, set
-the step's @code{doStepIf} to a boolean value, or to a function that returns a
-boolean value.  If the value or function result is false, then the step will
-return SKIPPED without doing anything.  Oherwise, the step will be executed
-normally.  If you set @code{doStepIf} to a function, that function should
-accept one parameter, which will be the @code{Step} object itself.
-
-@item locks
-a list of Locks (instances of @code{buildbot.locks.SlaveLock} or
-@code{buildbot.locks.MasterLock}) that should be acquired before starting this
-Step. The Locks will be released when the step is complete. Note that this is a
-list of actual Lock instances, not names. Also note that all Locks must have
-unique names.  See @ref{Interlocks}.
-
-@end table
-
-@node Using Build Properties
-@subsection Using Build Properties
-@cindex Properties
-
-Build properties are a generalized way to provide configuration
-information to build steps; see @ref{Build Properties}.
-
-Some build properties are inherited from external sources -- global
-properties, schedulers, or buildslaves.  Some build properties are
-set when the build starts, such as the SourceStamp information. Other
-properties can be set by BuildSteps as they run, for example the
-various Source steps will set the @code{got_revision} property to the
-source revision that was actually checked out (which can be useful
-when the SourceStamp in use merely requested the ``latest revision'':
-@code{got_revision} will tell you what was actually built).
-
-In custom BuildSteps, you can get and set the build properties with
-the @code{getProperty}/@code{setProperty} methods. Each takes a string
-for the name of the property, and returns or accepts an
-arbitrary@footnote{Build properties are serialized along with the
-build results, so they must be serializable. For this reason, the
-value of any build property should be simple inert data: strings,
-numbers, lists, tuples, and dictionaries. They should not contain
-class instances.} object. For example:
-
-@example
-class MakeTarball(ShellCommand):
-    def start(self):
-        if self.getProperty("os") == "win":
-            self.setCommand([ ... ]) # windows-only command
-        else:
-            self.setCommand([ ... ]) # equivalent for other systems
-        ShellCommand.start(self)
-@end example
-
-@menu
-* WithProperties::
-@end menu
-
-@node WithProperties
-@subsubsection WithProperties
-@cindex WithProperties
-
-You can use build properties in ShellCommands by using the
-@code{WithProperties} wrapper when setting the arguments of
-the ShellCommand. This interpolates the named build properties
-into the generated shell command.  Most step parameters accept
-@code{WithProperties}.  Please file bugs for any parameters which
-do not.
-
-@example
-from buildbot.steps.shell import ShellCommand
-from buildbot.process.properties import WithProperties
-
-f.addStep(ShellCommand(
-          command=["tar", "czf",
-                   WithProperties("build-%s.tar.gz", "revision"),
-                   "source"]))
-@end example
-
-If this BuildStep were used in a tree obtained from Subversion, it
-would create a tarball with a name like @file{build-1234.tar.gz}.
-
-The @code{WithProperties} function does @code{printf}-style string
-interpolation, using strings obtained by calling
-@code{build.getProperty(propname)}. Note that for every @code{%s} (or
-@code{%d}, etc), you must have exactly one additional argument to
-indicate which build property you want to insert.
-
-You can also use python dictionary-style string interpolation by using
-the @code{%(propname)s} syntax. In this form, the property name goes
-in the parentheses, and WithProperties takes @emph{no} additional
-arguments:
-
-@example
-f.addStep(ShellCommand(
-          command=["tar", "czf",
-                   WithProperties("build-%(revision)s.tar.gz"),
-                   "source"]))
-@end example
-
-Don't forget the extra ``s'' after the closing parenthesis! This is
-the cause of many confusing errors.
-
-The dictionary-style interpolation supports a number of more advanced
-syntaxes, too.
-
-@table @code
-
-@item propname:-replacement
-If @code{propname} exists, substitute its value; otherwise,
-substitute @code{replacement}.  @code{replacement} may be empty
-(@code{%(propname:-)s})
-
-@item propname:+replacement
-If @code{propname} exists, substitute @code{replacement}; otherwise,
-substitute an empty string.
-
-@end table
-
-Although these are similar to shell substitutions, no other
-substitutions are currently supported, and @code{replacement} in the
-above cannot contain more substitutions.
-
-Note: like python, you can either do positional-argument interpolation
-@emph{or} keyword-argument interpolation, not both. Thus you cannot use
-a string like @code{WithProperties("foo-%(revision)s-%s", "branch")}.
-
-@heading Common Build Properties
-
-The following build properties are set when the build is started, and
-are available to all steps.
-
-@table @code
-@item branch
-
-This comes from the build's SourceStamp, and describes which branch is
-being checked out. This will be @code{None} (which interpolates into
-@code{WithProperties} as an empty string) if the build is on the
-default branch, which is generally the trunk. Otherwise it will be a
-string like ``branches/beta1.4''. The exact syntax depends upon the VC
-system being used.
-
-@item revision
-
-This also comes from the SourceStamp, and is the revision of the source code
-tree that was requested from the VC system. When a build is requested of a
-specific revision (as is generally the case when the build is triggered by
-Changes), this will contain the revision specification. This is always a
-string, although the syntax depends upon the VC system in use: for SVN it is an
-integer, for Mercurial it is a short string, for Darcs it is a rather large
-string, etc.
-
-If the ``force build'' button was pressed, the revision will be @code{None},
-which means to use the most recent revision available.  This is a ``trunk
-build''. This will be interpolated as an empty string.
-
-@item got_revision
-
-This is set when a Source step checks out the source tree, and
-provides the revision that was actually obtained from the VC system.
-In general this should be the same as @code{revision}, except for
-trunk builds, where @code{got_revision} indicates what revision was
-current when the checkout was performed. This can be used to rebuild
-the same source code later.
-
-Note that for some VC systems (Darcs in particular), the revision is a
-large string containing newlines, and is not suitable for interpolation
-into a filename.
-
-@item buildername
-
-This is a string that indicates which Builder the build was a part of.
-The combination of buildername and buildnumber uniquely identify a
-build.
-
-@item buildnumber
-
-Each build gets a number, scoped to the Builder (so the first build
-performed on any given Builder will have a build number of 0). This
-integer property contains the build's number.
-
-@item slavename
-
-This is a string which identifies which buildslave the build is
-running on.
-
-@item scheduler
-
-If the build was started from a scheduler, then this property will
-contain the name of that scheduler.
-
-@item repository
-
-The repository of the sourcestamp for this build
-
-@item project
-
-The project of the sourcestamp for this build
-
-@end table
-
-@node Source Checkout
-@subsection Source Checkout
-
-The first step of any build is typically to acquire the source code
-from which the build will be performed. There are several classes to
-handle this, one for each of the different source control system that
-Buildbot knows about. For a description of how Buildbot treats source
-control in general, see @ref{Version Control Systems}.
-
-All source checkout steps accept some common parameters to control how
-they get the sources and where they should be placed. The remaining
-per-VC-system parameters are mostly to specify where exactly the
-sources are coming from.
-
-@table @code
-@item mode
-
-a string describing the kind of VC operation that is desired. Defaults
-to @code{update}.
-
-@table @code
-@item update
-specifies that the CVS checkout/update should be performed directly
-into the workdir. Each build is performed in the same directory,
-allowing for incremental builds. This minimizes disk space, bandwidth,
-and CPU time. However, it may encounter problems if the build process
-does not handle dependencies properly (sometimes you must do a ``clean
-build'' to make sure everything gets compiled), or if source files are
-deleted but generated files can influence test behavior (e.g. python's
-.pyc files), or when source directories are deleted but generated
-files prevent CVS from removing them. Builds ought to be correct
-regardless of whether they are done ``from scratch'' or incrementally,
-but it is useful to test both kinds: this mode exercises the
-incremental-build style.
-
-@item copy
-specifies that the CVS workspace should be maintained in a separate
-directory (called the 'copydir'), using checkout or update as
-necessary. For each build, a new workdir is created with a copy of the
-source tree (rm -rf workdir; cp -r copydir workdir). This doubles the
-disk space required, but keeps the bandwidth low (update instead of a
-full checkout). A full 'clean' build is performed each time. This
-avoids any generated-file build problems, but is still occasionally
-vulnerable to CVS problems such as a repository being manually
-rearranged, causing CVS errors on update which are not an issue with a
-full checkout.
-
-@c TODO: something is screwy about this, revisit. Is it the source
-@c directory or the working directory that is deleted each time?
-
-@item clobber
-specifes that the working directory should be deleted each time,
-necessitating a full checkout for each build. This insures a clean
-build off a complete checkout, avoiding any of the problems described
-above. This mode exercises the ``from-scratch'' build style.
-
-@item export
-this is like @code{clobber}, except that the 'cvs export' command is
-used to create the working directory. This command removes all CVS
-metadata files (the CVS/ directories) from the tree, which is
-sometimes useful for creating source tarballs (to avoid including the
-metadata in the tar file).
-@end table
-
-@item workdir
-like all Steps, this indicates the directory where the build will take
-place. Source Steps are special in that they perform some operations
-outside of the workdir (like creating the workdir itself).
-
-@item alwaysUseLatest
-if True, bypass the usual ``update to the last Change'' behavior, and
-always update to the latest changes instead.
-
-@item retry
-If set, this specifies a tuple of @code{(delay, repeats)} which means
-that when a full VC checkout fails, it should be retried up to
-@var{repeats} times, waiting @var{delay} seconds between attempts. If
-you don't provide this, it defaults to @code{None}, which means VC
-operations should not be retried. This is provided to make life easier
-for buildslaves which are stuck behind poor network connections.
-
-@item repository
-The name of this parameter might varies depending on the Source step you
-are running. The concept explained here is common to all steps and
-applies to @code{repourl} as well as for @code{baseURL} (when
-aplicable). Buildbot, now being aware of the repository name via the
-ChangeSource step might in some cases not need the repository url. There
-are multiple way to pass it through to this step, those correspond to
-the type of the parameter given to this step:
-
-@table @code
-@item None
-In the case where no paraneter is specified, the repository url will be
-taken exactly from the Change property. You are looking for that one if
-your ChangeSource step has all informations about how to reach the
-Change.
-
-@item string
-The parameter might be a string, in this case, this string will be taken
-as the repository url, and nothing more. the value coming from the
-ChangeSource step will be forgotten.
-
-@item format string
-If the parameter is a string containing @code{%s}, then this the
-repository property from the Change will be place in place of the
-@code{%s}. This is usefull when the ChangeSource step knows where the
-repository resides locally, but don't know the scheme used to access
-it. For instance @code{ssh://server/%s} makes sense if the the
-repository property is the local path of the repository.
-
-@item dict
-In this case, the repository URL will be the value indexed by the
-repository property in the dict given as parameter.
-
-@item callable
-The callable given as parameter will take the repository property from
-the Change and its return value will be used as repository URL.
-
-@end table
-@end table
-
-Note that this is quite similar to the mechanism used by the WebStatus
-for the @code{changecommentlink}, @code{projects} or @code{repositories} parameter.
-
-My habit as a developer is to do a @code{cvs update} and @code{make} each
-morning. Problems can occur, either because of bad code being checked in, or
-by incomplete dependencies causing a partial rebuild to fail where a
-complete from-scratch build might succeed. A quick Builder which emulates
-this incremental-build behavior would use the @code{mode='update'}
-setting.
-
-On the other hand, other kinds of dependency problems can cause a clean
-build to fail where a partial build might succeed. This frequently results
-from a link step that depends upon an object file that was removed from a
-later version of the tree: in the partial tree, the object file is still
-around (even though the Makefiles no longer know how to create it).
-
-``official'' builds (traceable builds performed from a known set of
-source revisions) are always done as clean builds, to make sure it is
-not influenced by any uncontrolled factors (like leftover files from a
-previous build). A ``full'' Builder which behaves this way would want
-to use the @code{mode='clobber'} setting.
-
-Each VC system has a corresponding source checkout class: their
-arguments are described on the following pages.
-
-
-@menu
-* CVS::
-* SVN::
-* Darcs::
-* Mercurial::
-* Arch::
-* Bazaar::
-* Bzr::
-* P4::
-* Git::
-* BitKeeper::
-@end menu
-
-@node CVS
-@subsubsection CVS
-@cindex CVS Checkout
-@bsindex buildbot.steps.source.CVS
-
-
-The @code{CVS} build step performs a @uref{http://www.nongnu.org/cvs/,
-CVS} checkout or update. It takes the following arguments:
-
-@table @code
-@item cvsroot
-(required): specify the CVSROOT value, which points to a CVS
-repository, probably on a remote machine. For example, the cvsroot
-value you would use to get a copy of the Buildbot source code is
-@code{:pserver:anonymous@@cvs.sourceforge.net:/cvsroot/buildbot}
-
-@item cvsmodule
-(required): specify the cvs @code{module}, which is generally a
-subdirectory of the CVSROOT. The cvsmodule for the Buildbot source
-code is @code{buildbot}.
-
-@item branch
-a string which will be used in a @code{-r} argument. This is most
-useful for specifying a branch to work on. Defaults to @code{HEAD}.
-
-@item global_options
-a list of flags to be put before the verb in the CVS command.
-
-@item checkout_options
-@item export_options
-@item extra_options
-a list of flags to be put after the verb in the CVS command.
-@code{checkout_options} is only used for checkout operations,
-@code{export_options} is only used for export operations, and
-@code{extra_options} is used for both.
-
-@item checkoutDelay
-if set, the number of seconds to put between the timestamp of the last
-known Change and the value used for the @code{-D} option. Defaults to
-half of the parent Build's treeStableTimer.
-
-@end table
-
-
-@node SVN
-@subsubsection SVN
-
-@cindex SVN Checkout
-@bsindex buildbot.steps.source.SVN
-
-
-The @code{SVN} build step performs a
-@uref{http://subversion.tigris.org, Subversion} checkout or update.
-There are two basic ways of setting up the checkout step, depending
-upon whether you are using multiple branches or not.
-
-The most versatile way to create the @code{SVN} step is with the
-@code{svnurl} argument:
-
-@table @code
-@item svnurl
-(required): this specifies the @code{URL} argument that will be given
-to the @code{svn checkout} command. It dictates both where the
-repository is located and which sub-tree should be extracted. In this
-respect, it is like a combination of the CVS @code{cvsroot} and
-@code{cvsmodule} arguments. For example, if you are using a remote
-Subversion repository which is accessible through HTTP at a URL of
-@code{http://svn.example.com/repos}, and you wanted to check out the
-@code{trunk/calc} sub-tree, you would use
-@code{svnurl="http://svn.example.com/repos/trunk/calc"} as an argument
-to your @code{SVN} step.
-@end table
-
-The @code{svnurl} argument can be considered as a universal means to
-create the @code{SVN} step as it ignores the branch information in the
-SourceStamp.
-
-Alternatively, if you are building from multiple branches, then you
-should preferentially create the @code{SVN} step with the
-@code{baseURL} and @code{defaultBranch} arguments instead:
-
-@table @code
-@item baseURL
-(required): this specifies the base repository URL, to which a branch
-name will be appended. It should probably end in a slash.
-
-@item defaultBranch
-(optional): this specifies the name of the branch to use when a Build
-does not provide one of its own. This will be appended to
-@code{baseURL} to create the string that will be passed to the
-@code{svn checkout} command.
-
-It is possible to mix to have a mix of @code{SVN} steps that use
-either the @code{svnurl} or @code{baseURL} arguments but not both at
-the same time.
-
-@item username
-(optional): if specified, this will be passed to the @code{svn}
-binary with a @code{--username} option.
-
-@item password
-(optional): if specified, this will be passed to the @code{svn}
-binary with a @code{--password} option.  The password itself will be
-suitably obfuscated in the logs.
-
-@item extra_args
-(optional): if specified, an array of strings that will be passed as
-extra arguments to the @code{svn} binary.
-
-@item keep_on_purge
-(optional): specific files or directories to keep between purges,
-like some build outputs that can be reused between builds.
-
-@item ignore_ignores
-(optional): when purging changes, don't use rules defined in
-svn:ignore properties and global-ignores in subversion/config.
-
-@item always_purge
-(optional): if set to True, always purge local changes before updating. This deletes unversioned files and reverts everything that would appear in a @code{svn status}.
-
-@item depth
-(optional): Specify depth argument to achieve sparse checkout.  Only available if slave has Subversion 1.5 or higher.
-
-If set to "empty" updates will not pull in any files or subdirectories not already present. If set to "files", updates will pull in any files not already present, but not directories.  If set to "immediates", updates willl pull in any files or subdirectories not already present, the new subdirectories will have depth: empty.  If set to "infinity", updates will pull in any files or subdirectories not already present; the new subdirectories will have depth-infinity. Infinity is equivalent to SVN default update behavior, without specifying any depth argument.
-
-@end table
-
-If you are using branches, you must also make sure your
-@code{ChangeSource} will report the correct branch names.
-
-@heading branch example
-
-Let's suppose that the ``MyProject'' repository uses branches for the
-trunk, for various users' individual development efforts, and for
-several new features that will require some amount of work (involving
-multiple developers) before they are ready to merge onto the trunk.
-Such a repository might be organized as follows:
-
-@example
-svn://svn.example.org/MyProject/trunk
-svn://svn.example.org/MyProject/branches/User1/foo
-svn://svn.example.org/MyProject/branches/User1/bar
-svn://svn.example.org/MyProject/branches/User2/baz
-svn://svn.example.org/MyProject/features/newthing
-svn://svn.example.org/MyProject/features/otherthing
-@end example
-
-Further assume that we want the Buildbot to run tests against the
-trunk and against all the feature branches (i.e., do a
-checkout/compile/build of branch X when a file has been changed on
-branch X, when X is in the set [trunk, features/newthing,
-features/otherthing]). We do not want the Buildbot to automatically
-build any of the user branches, but it should be willing to build a
-user branch when explicitly requested (most likely by the user who
-owns that branch).
-
-There are three things that need to be set up to accomodate this
-system. The first is a ChangeSource that is capable of identifying the
-branch which owns any given file. This depends upon a user-supplied
-function, in an external program that runs in the SVN commit hook and
-connects to the buildmaster's @code{PBChangeSource} over a TCP
-connection. (you can use the ``@code{buildbot sendchange}'' utility
-for this purpose, but you will still need an external program to
-decide what value should be passed to the @code{--branch=} argument).
-For example, a change to a file with the SVN url of
-``svn://svn.example.org/MyProject/features/newthing/src/foo.c'' should
-be broken down into a Change instance with
-@code{branch='features/newthing'} and @code{file='src/foo.c'}.
-
-The second piece is an @code{AnyBranchScheduler} which will pay
-attention to the desired branches. It will not pay attention to the
-user branches, so it will not automatically start builds in response
-to changes there. The AnyBranchScheduler class requires you to
-explicitly list all the branches you want it to use, but it would not
-be difficult to write a subclass which used
-@code{branch.startswith('features/'} to remove the need for this
-explicit list. Or, if you want to build user branches too, you can use
-AnyBranchScheduler with @code{branches=None} to indicate that you want
-it to pay attention to all branches.
-
-The third piece is an @code{SVN} checkout step that is configured to
-handle the branches correctly, with a @code{baseURL} value that
-matches the way the ChangeSource splits each file's URL into base,
-branch, and file.
-
-@example
-from buildbot.changes.pb import PBChangeSource
-from buildbot.scheduler import AnyBranchScheduler
-from buildbot.process import source, factory
-from buildbot.steps import source, shell
-
-c['change_source'] = PBChangeSource()
-s1 = AnyBranchScheduler('main',
-                        ['trunk', 'features/newthing', 'features/otherthing'],
-                        10*60, ['test-i386', 'test-ppc'])
-c['schedulers'] = [s1]
-
-f = factory.BuildFactory()
-f.addStep(source.SVN(mode='update',
-                     baseURL='svn://svn.example.org/MyProject/',
-                     defaultBranch='trunk'))
-f.addStep(shell.Compile(command="make all"))
-f.addStep(shell.Test(command="make test"))
-
-c['builders'] = [
-  @{'name':'test-i386', 'slavename':'bot-i386', 'builddir':'test-i386',
-                       'factory':f @},
-  @{'name':'test-ppc', 'slavename':'bot-ppc', 'builddir':'test-ppc',
-                      'factory':f @},
- ]
-@end example
-
-In this example, when a change arrives with a @code{branch} attribute
-of ``trunk'', the resulting build will have an SVN step that
-concatenates ``svn://svn.example.org/MyProject/'' (the baseURL) with
-``trunk'' (the branch name) to get the correct svn command. If the
-``newthing'' branch has a change to ``src/foo.c'', then the SVN step
-will concatenate ``svn://svn.example.org/MyProject/'' with
-``features/newthing'' to get the svnurl for checkout.
-
-@node Darcs
-@subsubsection Darcs
-
-@cindex Darcs Checkout
-@bsindex buildbot.steps.source.Darcs
-
-
-The @code{Darcs} build step performs a
-@uref{http://darcs.net/, Darcs} checkout or update.
-
-Like @xref{SVN}, this step can either be configured to always check
-out a specific tree, or set up to pull from a particular branch that
-gets specified separately for each build. Also like SVN, the
-repository URL given to Darcs is created by concatenating a
-@code{baseURL} with the branch name, and if no particular branch is
-requested, it uses a @code{defaultBranch}. The only difference in
-usage is that each potential Darcs repository URL must point to a
-fully-fledged repository, whereas SVN URLs usually point to sub-trees
-of the main Subversion repository. In other words, doing an SVN
-checkout of @code{baseURL} is legal, but silly, since you'd probably
-wind up with a copy of every single branch in the whole repository.
-Doing a Darcs checkout of @code{baseURL} is just plain wrong, since
-the parent directory of a collection of Darcs repositories is not
-itself a valid repository.
-
-The Darcs step takes the following arguments:
-
-@table @code
-@item repourl
-(required unless @code{baseURL} is provided): the URL at which the
-Darcs source repository is available.
-
-@item baseURL
-(required unless @code{repourl} is provided): the base repository URL,
-to which a branch name will be appended. It should probably end in a
-slash.
-
-@item defaultBranch
-(allowed if and only if @code{baseURL} is provided): this specifies
-the name of the branch to use when a Build does not provide one of its
-own. This will be appended to @code{baseURL} to create the string that
-will be passed to the @code{darcs get} command.
-@end table
-
-@node Mercurial
-@subsubsection Mercurial
-
-@cindex Mercurial Checkout
-@bsindex buildbot.steps.source.Mercurial
-
-
-The @code{Mercurial} build step performs a
-@uref{http://selenic.com/mercurial, Mercurial} (aka ``hg'') checkout
-or update.
-
-Branches are available in two modes: ''dirname'' like @xref{Darcs}, or
-''inrepo'', which uses the repository internal branches. Make sure this
-setting matches your changehook, if you have that installed.
-
-The Mercurial step takes the following arguments:
-
-@table @code
-@item repourl
-(required unless @code{baseURL} is provided): the URL at which the
-Mercurial source repository is available.
-
-@item baseURL
-(required unless @code{repourl} is provided): the base repository URL,
-to which a branch name will be appended. It should probably end in a
-slash.
-
-@item defaultBranch
-(allowed if and only if @code{baseURL} is provided): this specifies
-the name of the branch to use when a Build does not provide one of its
-own. This will be appended to @code{baseURL} to create the string that
-will be passed to the @code{hg clone} command.
-
-@item branchType
-either 'dirname' (default) or 'inrepo' depending on whether
-the branch name should be appended to the @code{baseURL}
-or the branch is a mercurial named branch and can be
-found within the @code{repourl}.
-
-@item clobberOnBranchChange
-boolean, defaults to True. If set and
-using inrepos branches, clobber the tree
-at each branch change. Otherwise, just
-update to the branch.
-
-@end table
-
-
-@node Arch
-@subsubsection Arch
-
-@cindex Arch Checkout
-@bsindex buildbot.steps.source.Arch
-
-
-The @code{Arch} build step performs an @uref{http://gnuarch.org/,
-Arch} checkout or update using the @code{tla} client. It takes the
-following arguments:
-
-@table @code
-@item url
-(required): this specifies the URL at which the Arch source archive is
-available.
-
-@item version
-(required): this specifies which ``development line'' (like a branch)
-should be used. This provides the default branch name, but individual
-builds may specify a different one.
-
-@item archive
-(optional): Each repository knows its own archive name. If this
-parameter is provided, it must match the repository's archive name.
-The parameter is accepted for compatibility with the @code{Bazaar}
-step, below.
-
-@end table
-
-@node Bazaar
-@subsubsection Bazaar
-
-@cindex Bazaar Checkout
-@bsindex buildbot.steps.source.Bazaar
-
-
-@code{Bazaar} is an alternate implementation of the Arch VC system,
-which uses a client named @code{baz}. The checkout semantics are just
-different enough from @code{tla} that there is a separate BuildStep for
-it.
-
-It takes exactly the same arguments as @code{Arch}, except that the
-@code{archive=} parameter is required. (baz does not emit the archive
-name when you do @code{baz register-archive}, so we must provide it
-ourselves).
-
-
-@node Bzr
-@subsubsection Bzr
-
-@cindex Bzr Checkout
-@bsindex buildbot.steps.source.Bzr
-
-@code{bzr} is a descendant of Arch/Baz, and is frequently referred to
-as simply ``Bazaar''. The repository-vs-workspace model is similar to
-Darcs, but it uses a strictly linear sequence of revisions (one
-history per branch) like Arch. Branches are put in subdirectories.
-This makes it look very much like Mercurial. It takes the following
-arguments:
-
-@table @code
-
-@item repourl
-(required unless @code{baseURL} is provided): the URL at which the
-Bzr source repository is available.
-
-@item baseURL
-(required unless @code{repourl} is provided): the base repository URL,
-to which a branch name will be appended. It should probably end in a
-slash.
-
-@item defaultBranch
-(allowed if and only if @code{baseURL} is provided): this specifies
-the name of the branch to use when a Build does not provide one of its
-own. This will be appended to @code{baseURL} to create the string that
-will be passed to the @code{bzr checkout} command.
-
-@item forceSharedRepo
-(boolean, optional, defaults to False): If set to True, the working directory
-will be made into a bzr shared repository if it is not already. Shared
-repository greatly reduces the amount of history data that needs to be
-downloaded if not using update/copy mode, or if using update/copy mode with
-multiple branches.
-@end table
-
-
-
-@node P4
-@subsubsection P4
-
-@cindex Perforce Update
-@bsindex buildbot.steps.source.P4
-@c TODO @bsindex buildbot.steps.source.P4Sync
-
-
-The @code{P4} build step creates a @uref{http://www.perforce.com/,
-Perforce} client specification and performs an update.
-
-@table @code
-@item p4base
-A view into the Perforce depot without branch name or trailing "...".
-Typically "//depot/proj/".
-@item defaultBranch
-A branch name to append on build requests if none is specified.
-Typically "trunk".
-@item p4port
-(optional): the host:port string describing how to get to the P4 Depot
-(repository), used as the -p argument for all p4 commands.
-@item p4user
-(optional): the Perforce user, used as the -u argument to all p4
-commands.
-@item p4passwd
-(optional): the Perforce password, used as the -p argument to all p4
-commands.
-@item p4extra_views
-(optional): a list of (depotpath, clientpath) tuples containing extra
-views to be mapped into the client specification. Both will have
-"/..." appended automatically. The client name and source directory
-will be prepended to the client path.
-@item p4client
-(optional): The name of the client to use. In mode='copy' and
-mode='update', it's particularly important that a unique name is used
-for each checkout directory to avoid incorrect synchronization. For
-this reason, Python percent substitution will be performed on this value
-to replace %(slave)s with the slave name and %(builder)s with the
-builder name. The default is "buildbot_%(slave)s_%(build)s".
-@end table
-
-
-@node Git
-@subsubsection Git
-
-@cindex Git Checkout
-@bsindex buildbot.steps.source.Git
-
-The @code{Git} build step clones or updates a @uref{http://git.or.cz/,
-Git} repository and checks out the specified branch or revision. Note
-that the buildbot supports Git version 1.2.0 and later: earlier
-versions (such as the one shipped in Ubuntu 'Dapper') do not support
-the @command{git init} command that the buildbot uses.
-
-The Git step takes the following arguments:
-
-@table @code
-@item repourl
-(required): the URL of the upstream Git repository.
-
-@item branch
-(optional): this specifies the name of the branch to use when a Build
-does not provide one of its own. If this this parameter is not
-specified, and the Build does not provide a branch, the ``master''
-branch will be used.
-
-@item ignore_ignores
-(optional): when purging changes, don't use .gitignore and
-.git/info/exclude.
-
-@item submodules
-(optional): when initializing/updating a Git repository, this decides whether
-or not buildbot should consider git submodules.  Default: False.
-
-@item shallow
-(optional): instructs git to attempt shallow clones (@code{--depth 1}).  If the
-user/scheduler asks for a specific revision, this parameter is ignored.
-
-@end table
-
-
-@node BitKeeper
-@subsubsection BitKeeper
-
-@cindex BitKeeper Checkout
-@bsindex buildbot.steps.source.BK
-
-The @code{BK} build step performs a @uref{http://www.bitkeeper.com/, BitKeeper}
-checkout or update.
-
-The BitKeeper step takes the following arguments:
-
-@table @code
-@item repourl
-(required unless @code{baseURL} is provided): the URL at which the
-BitKeeper source repository is available.
-
-@item baseURL
-(required unless @code{repourl} is provided): the base repository URL,
-to which a branch name will be appended. It should probably end in a
-slash.
-
-@end table
-
-@node ShellCommand
-@subsection ShellCommand
-
-Most interesting steps involve exectuing a process of some sort on the
-buildslave.  The @code{ShellCommand} class handles this activity.
-
-Several subclasses of ShellCommand are provided as starting points for
-common build steps.
-
-@menu
-* Using ShellCommands::
-* Configure::
-* Compile::
-* Visual C++::
-* Test::
-* TreeSize::
-* PerlModuleTest::
-* Testing with mysql-test-run::
-* SetProperty::
-* SubunitShellCommand::
-@end menu
-
-@node Using ShellCommands
-@subsubsection Using ShellCommands
-
-@bsindex buildbot.steps.shell.ShellCommand
-
-This is a useful base class for just about everything you might want
-to do during a build (except for the initial source checkout). It runs
-a single command in a child shell on the buildslave. All stdout/stderr
-is recorded into a LogFile. The step finishes with a status of FAILURE
-if the command's exit code is non-zero, otherwise it has a status of
-SUCCESS.
-
-The preferred way to specify the command is with a list of argv strings,
-since this allows for spaces in filenames and avoids doing any fragile
-shell-escaping. You can also specify the command with a single string, in
-which case the string is given to '/bin/sh -c COMMAND' for parsing.
-
-On Windows, commands are run via @code{cmd.exe /c} which works well. However,
-if you're running a batch file, the error level does not get propagated
-correctly unless you add 'call' before your batch file's name:
-@code{cmd=['call', 'myfile.bat', ...]}.
-
-@code{ShellCommand} arguments:
-
-@table @code
-@item command
-a list of strings (preferred) or single string (discouraged) which
-specifies the command to be run. A list of strings is preferred
-because it can be used directly as an argv array. Using a single
-string (with embedded spaces) requires the buildslave to pass the
-string to /bin/sh for interpretation, which raises all sorts of
-difficult questions about how to escape or interpret shell
-metacharacters.
-
-@item workdir
-All ShellCommands are run by default in the ``workdir'', which
-defaults to the ``@file{build}'' subdirectory of the slave builder's
-base directory. The absolute path of the workdir will thus be the
-slave's basedir (set as an option to @code{buildbot create-slave},
-@pxref{Creating a buildslave}) plus the builder's basedir (set in the
-builder's @code{c['builddir']} key in master.cfg) plus the workdir
-itself (a class-level attribute of the BuildFactory, defaults to
-``@file{build}'').
-
-For example:
-
-@example
-f.addStep(ShellCommand(command=["make", "test"],
-                       workdir="build/tests"))
-@end example
-
-@item env
-a dictionary of environment strings which will be added to the child
-command's environment. For example, to run tests with a different i18n
-language setting, you might use
-
-@example
-f.addStep(ShellCommand(command=["make", "test"],
-                       env=@{'LANG': 'fr_FR'@}))
-@end example
-
-These variable settings will override any existing ones in the
-buildslave's environment or the environment specified in the
-Builder. The exception is PYTHONPATH, which is merged
-with (actually prepended to) any existing $PYTHONPATH setting. The
-value is treated as a list of directories to prepend, and a single
-string is treated like a one-item list. For example, to prepend both
-@file{/usr/local/lib/python2.3} and @file{/home/buildbot/lib/python}
-to any existing $PYTHONPATH setting, you would do something like the
-following:
-
-@example
-f.addStep(ShellCommand(
-              command=["make", "test"],
-              env=@{'PYTHONPATH': ["/usr/local/lib/python2.3",
-                                   "/home/buildbot/lib/python"] @}))
-@end example
-
-Those variables support expansion so that if you just want to prepend
-@file{/home/buildbot/bin} to the PATH environment variable, you can do
-it by putting the value @code{$@{PATH@}} at the end of the string like
-in the example below. Variables that doesn't exists on the slave will be
-replaced by @code{""}.
-
-
-@example
-f.addStep(ShellCommand(
-              command=["make", "test"],
-              env=@{'PATH': "/home/buildbot/bin:$@{PATH@}"@}))
-@end example
-
-@item want_stdout
-if False, stdout from the child process is discarded rather than being
-sent to the buildmaster for inclusion in the step's LogFile.
-
-@item want_stderr
-like @code{want_stdout} but for stderr. Note that commands run through
-a PTY do not have separate stdout/stderr streams: both are merged into
-stdout.
-
-@item usePTY
-Should this command be run in a @code{pty}?  The default is to observe the
-configuration of the client (@pxref{Buildslave Options}), but specifying
-@code{True} or @code{False} here will override the default.
-
-The advantage of using a PTY is that ``grandchild'' processes are more likely
-to be cleaned up if the build is interrupted or times out (since it enables the
-use of a ``process group'' in which all child processes will be placed). The
-disadvantages: some forms of Unix have problems with PTYs, some of your unit
-tests may behave differently when run under a PTY (generally those which check
-to see if they are being run interactively), and PTYs will merge the stdout and
-stderr streams into a single output stream (which means the red-vs-black
-coloring in the logfiles will be lost).
-
-@item logfiles
-Sometimes commands will log interesting data to a local file, rather
-than emitting everything to stdout or stderr. For example, Twisted's
-``trial'' command (which runs unit tests) only presents summary
-information to stdout, and puts the rest into a file named
-@file{_trial_temp/test.log}. It is often useful to watch these files
-as the command runs, rather than using @command{/bin/cat} to dump
-their contents afterwards.
-
-The @code{logfiles=} argument allows you to collect data from these
-secondary logfiles in near-real-time, as the step is running. It
-accepts a dictionary which maps from a local Log name (which is how
-the log data is presented in the build results) to either a remote filename
-(interpreted relative to the build's working directory), or a dictionary
-of options. Each named file will be polled on a regular basis (every couple
-of seconds) as the build runs, and any new text will be sent over to the
-buildmaster.
-
-If you provide a dictionary of options instead of a string, you must specify
-the @code{filename} key. You can optionally provide a @code{follow} key which
-is a boolean controlling whether a logfile is followed or concatenated in its
-entirety.  Following is appropriate for logfiles to which the build step will
-append, where the pre-existing contents are not interesting.  The default value
-for @code{follow} is @code{False}, which gives the same behavior as just
-providing a string filename.
-
-@example
-f.addStep(ShellCommand(
-              command=["make", "test"],
-              logfiles=@{"triallog": "_trial_temp/test.log"@}))
-@end example
-
-@example
-f.addStep(ShellCommand(
-              command=["make", "test"],
-              logfiles=@{"triallog": @{"filename": "_trial_temp/test.log",
-			       "follow": True,@}@}))
-@end example
-
-
-@item lazylogfiles
-If set to @code{True}, logfiles will be tracked lazily, meaning that they will
-only be added when and if something is written to them. This can be used to
-suppress the display of empty or missing log files. The default is @code{False}.
-
-
-@item timeout
-if the command fails to produce any output for this many seconds, it
-is assumed to be locked up and will be killed.
-
-@item maxTime
-if the command takes longer than this many seconds, it will be killed.
-
-@item description
-This will be used to describe the command (on the Waterfall display)
-while the command is still running. It should be a single
-imperfect-tense verb, like ``compiling'' or ``testing''. The preferred
-form is a list of short strings, which allows the HTML 
-displays to create narrower columns by emitting a <br> tag between each
-word. You may also provide a single string.
-
-@item descriptionDone
-This will be used to describe the command once it has finished. A
-simple noun like ``compile'' or ``tests'' should be used. Like
-@code{description}, this may either be a list of short strings or a
-single string.
-
-If neither @code{description} nor @code{descriptionDone} are set, the
-actual command arguments will be used to construct the description.
-This may be a bit too wide to fit comfortably on the Waterfall
-display.
-
-@example
-f.addStep(ShellCommand(command=["make", "test"],
-                       description=["testing"],
-                       descriptionDone=["tests"]))
-@end example
-
-@item logEnviron
-If this option is true (the default), then the step's logfile will describe the
-environment variables on the slave.  In situations where the environment is not
-relevant and is long, it may be easier to set @code{logEnviron=False}.
-
-@end table
-
-@node Configure
-@subsubsection Configure
-
-@bsindex buildbot.steps.shell.Configure
-
-This is intended to handle the @code{./configure} step from
-autoconf-style projects, or the @code{perl Makefile.PL} step from perl
-MakeMaker.pm-style modules. The default command is @code{./configure}
-but you can change this by providing a @code{command=} parameter.
-
-@node Compile
-@subsubsection Compile
-
-@bsindex buildbot.steps.shell.Compile
-
-This is meant to handle compiling or building a project written in C.
-The default command is @code{make all}. When the compile is finished,
-the log file is scanned for GCC warning messages, a summary log is
-created with any problems that were seen, and the step is marked as
-WARNINGS if any were discovered. Through the @code{WarningCountingShellCommand}
-superclass, the number of warnings is stored in a Build Property named
-``warnings-count'', which is accumulated over all Compile steps (so if two
-warnings are found in one step, and three are found in another step, the
-overall build will have a ``warnings-count'' property of 5).
-
-The default regular expression used to detect a warning is
-@code{'.*warning[: ].*'} , which is fairly liberal and may cause
-false-positives. To use a different regexp, provide a
-@code{warningPattern=} argument, or use a subclass which sets the
-@code{warningPattern} attribute:
-
-@example
-f.addStep(Compile(command=["make", "test"],
-                  warningPattern="^Warning: "))
-@end example
-
-The @code{warningPattern=} can also be a pre-compiled python regexp
-object: this makes it possible to add flags like @code{re.I} (to use
-case-insensitive matching).
-
-Note that the compiled @code{warningPattern} will have its @code{match} method
-called, which is subtly different from a @code{search}. Your regular
-expression must match the from the beginning of the line. This means that to
-look for the word "warning" in the middle of a line, you will need to
-prepend @code{'.*'} to your regular expression.
-
-The @code{suppressionFile=} argument can be specified as the (relative) path
-of a file inside the workdir defining warnings to be suppressed from the
-warning counting and log file. The file will be uploaded to the master from
-the slave before compiling, and any warning matched by a line in the
-suppression file will be ignored. This is useful to accept certain warnings
-(eg. in some special module of the source tree or in cases where the compiler
-is being particularly stupid), yet still be able to easily detect and fix the
-introduction of new warnings.
-
-The file must contain one line per pattern of warnings to ignore. Empty lines
-and lines beginning with @code{#} are ignored. Other lines must consist of a
-regexp matching the file name, followed by a colon (@code{:}), followed by a
-regexp matching the text of the warning. Optionally this may be followed by
-another colon and a line number range. For example:
-
-@example
-# Sample warning suppression file
-
-mi_packrec.c : .*result of 32-bit shift implicitly converted to 64 bits.* : 560-600
-DictTabInfo.cpp : .*invalid access to non-static.*
-kernel_types.h : .*only defines private constructors and has no friends.* : 51
-@end example
-
-If no line number range is specified, the pattern matches the whole file; if
-only one number is given it matches only on that line.
-
-The default warningPattern regexp only matches the warning text, so line
-numbers and file names are ignored. To enable line number and file name
-matching, privide a different regexp and provide a function (callable) as the
-argument of @code{warningExtractor=}. The function is called with three
-arguments: the BuildStep object, the line in the log file with the warning,
-and the @code{SRE_Match} object of the regexp search for @code{warningPattern}. It
-should return a tuple @code{(filename, linenumber, warning_test)}. For
-example:
-
-@example
-f.addStep(Compile(command=["make"],
-                  warningPattern="^(.*?):([0-9]+): [Ww]arning: (.*)$",
-                  warningExtractor=Compile.warnExtractFromRegexpGroups,
-                  suppressionFile="support-files/compiler_warnings.supp"))
-@end example
-
-(@code{Compile.warnExtractFromRegexpGroups} is a pre-defined function that
-returns the filename, linenumber, and text from groups (1,2,3) of the regexp
-match).
-
-In projects with source files in multiple directories, it is possible to get
-full path names for file names matched in the suppression file, as long as the
-build command outputs the names of directories as they are entered into and
-left again. For this, specify regexps for the arguments
-@code{directoryEnterPattern=} and @code{directoryLeavePattern=}. The
-@code{directoryEnterPattern=} regexp should return the name of the directory
-entered into in the first matched group. The defaults, which are suitable for
-GNU Make, are these:
-
-@example
-directoryEnterPattern = "make.*: Entering directory [\"`'](.*)['`\"]"
-directoryLeavePattern = "make.*: Leaving directory"
-@end example
-
-(TODO: this step needs to be extended to look for GCC error messages
-as well, and collect them into a separate logfile, along with the
-source code filenames involved).
-
-@node Visual C++
-@subsubsection Visual C++
-
-@bsindex buildbot.steps.vstudio.VC6
-@bsindex buildbot.steps.vstudio.VC7
-@bsindex buildbot.steps.vstudio.VC8
-@bsindex buildbot.steps.vstudio.VS2003
-@bsindex buildbot.steps.vstudio.VS2005
-
-This step is meant to handle compilation using Microsoft compilers. 
-VC++ 6-8, VS2003, and VS2005 are supported. This step will take care
-of setting up a clean compilation environment, parse the generated
-output in real time and deliver as detailed as possible information
-about the compilation executed.
-
-All of the classes are in @code{buildbot.steps.vstudio}.  The available classes are:
-
-@table @code
-
-@item VC6
-
-@item VC7
-
-@item VC8
-
-@item VS2003
-
-@item VC2005
-
-@end table
-
-The available constructor arguments are
-
-@table @code
-@item mode
-The mode default to @code{"rebuild"}, which means that first all the
-remaining object files will be cleaned by the compiler. The alternate
-value is @code{"build"}, where only the updated files will be recompiled.
-
-@item projectfile
-This is a mandatory argument which specifies the project file to be used
-during the compilation.
-
-@item config
-This argument defaults to @code{"release"} an gives to the compiler the
-configuration to use.
-
-@item installdir
-This is the place where the compiler is installed. The default value is
-compiler specific and is the default place where the compiler is installed.
-
-@item useenv
-This boolean parameter, defaulting to @code{False} instruct the compiler
-to use its own settings or the one defined through the environment
-variables @code{%PATH%}, @code{%INCLUDE%}, and @code{%LIB%}. If any of
-the @code{INCLUDE} or @code{LIB} parameter is defined, this parameter
-automatically switches to @code{True}.
-
-@item PATH
-This is a list of path to be added to the PATH environment
-variable. The default value is the one defined in the compiler options.
-
-@item INCLUDE
-This is a list of path where the compiler will first look for include
-files. Then comes the default paths defined in the compiler options.
-
-@item LIB
-This is a list of path where the compiler will first look for
-libraries. Then comes the default path defined in the compiler options.
-
-@item arch
-That one is only available with the class VS2005 (VC8). It gives the
-target architecture of the built artifact. It defaults to @code{"x86''}.
-@end table
-
-Here is an example on how to use this step:
-
-@example
-from buildbot.steps.VisualStudio import VS2005
-
-f.addStep(VS2005(
-        projectfile="project.sln", config="release",
-        arch="x64", mode="build",
-        INCLUDE=[r'D:\WINDDK\Include\wnet'],
-        LIB=[r'D:\WINDDK\lib\wnet\amd64']))
-@end example
-
-@node Test
-@subsubsection Test
-
-@bsindex buildbot.steps.shell.Test
-