diff -rN -u old-builderEnv/buildbot/process/base.py new-builderEnv/buildbot/process/base.py
--- old-builderEnv/buildbot/process/base.py	2008-12-06 00:35:11.000000000 -0500
+++ new-builderEnv/buildbot/process/base.py	2008-12-06 00:35:12.000000000 -0500
@@ -193,6 +193,9 @@
     def setLocks(self, locks):
         self.locks = locks
 
+    def setSlaveEnvironment(self, env):
+        self.slaveEnvironment = env
+
     def getSourceStamp(self):
         return self.source
 
diff -rN -u old-builderEnv/buildbot/process/builder.py new-builderEnv/buildbot/process/builder.py
--- old-builderEnv/buildbot/process/builder.py	2008-12-06 00:35:11.000000000 -0500
+++ new-builderEnv/buildbot/process/builder.py	2008-12-06 00:35:12.000000000 -0500
@@ -278,6 +278,8 @@
         self.builddir = setup['builddir']
         self.buildFactory = setup['factory']
         self.locks = setup.get("locks", [])
+        self.env = setup.get('env', {})
+        assert isinstance(self.env, dict)
         if setup.has_key('periodicBuildTime'):
             raise ValueError("periodicBuildTime can no longer be defined as"
                              " part of the Builder: use scheduler.Periodic"
@@ -587,6 +589,8 @@
         build = self.buildFactory.newBuild(requests)
         build.setBuilder(self)
         build.setLocks(self.locks)
+        if len(self.env) > 0:
+            build.setSlaveEnvironment(self.env)
 
         # start it
         self.startBuild(build, sb)
diff -rN -u old-builderEnv/buildbot/steps/shell.py new-builderEnv/buildbot/steps/shell.py
--- old-builderEnv/buildbot/steps/shell.py	2008-12-06 00:35:11.000000000 -0500
+++ new-builderEnv/buildbot/steps/shell.py	2008-12-06 00:35:12.000000000 -0500
@@ -135,17 +135,20 @@
         return ["'%s" % words[0], "%s" % words[1], "...'"]
 
     def setupEnvironment(self, cmd):
-        # XXX is this used? documented? replaced by properties?
-        # merge in anything from Build.slaveEnvironment . Earlier steps
-        # (perhaps ones which compile libraries or sub-projects that need to
-        # be referenced by later steps) can add keys to
-        # self.build.slaveEnvironment to affect later steps.
+        # merge in anything from Build.slaveEnvironment
+        # This can be set from a Builder-level environment, or from earlier
+        # BuildSteps. The latter method is deprecated and superceded by
+        # BuildProperties.
+        # Environment variables passed in by a BuildStep override
+        # those passed in at the Builder level.
         properties = self.build.getProperties()
         slaveEnv = self.build.slaveEnvironment
         if slaveEnv:
             if cmd.args['env'] is None:
                 cmd.args['env'] = {}
-            cmd.args['env'].update(properties.render(slaveEnv))
+            fullSlaveEnv = slaveEnv.copy()
+            fullSlaveEnv.update(cmd.args['env'])
+            cmd.args['env'] = properties.render(fullSlaveEnv)
             # note that each RemoteShellCommand gets its own copy of the
             # dictionary, so we shouldn't be affecting anyone but ourselves.
 
diff -rN -u old-builderEnv/buildbot/test/test_run.py new-builderEnv/buildbot/test/test_run.py
--- old-builderEnv/buildbot/test/test_run.py	2008-12-06 00:35:11.000000000 -0500
+++ new-builderEnv/buildbot/test/test_run.py	2008-12-06 00:35:12.000000000 -0500
@@ -843,3 +843,80 @@
 # of the bug where I forgot to make Waterfall inherit from StatusReceiver
 # such that buildSetSubmitted failed.
 
+config_test_builder = config_base + """
+from buildbot.scheduler import Scheduler
+c['schedulers'] = [Scheduler('quick', 'dummy', 0.1, ['dummy']),
+                   Scheduler('quick2', 'dummy2', 0.1, ['dummy2']),
+                   Scheduler('quick3', 'dummy3', 0.1, ['dummy3'])]
+
+from buildbot.steps.shell import ShellCommand
+f3 = factory.BuildFactory([
+    s(ShellCommand, command="sleep 3", env={'blah':'blah'})
+    ])
+
+c['builders'] = [{'name': 'dummy', 'slavename': 'bot1', 'env': {'foo':'bar'},
+                  'builddir': 'dummy', 'factory': f3}]
+
+c['builders'].append({'name': 'dummy2', 'slavename': 'bot1',
+                       'env': {'blah':'bar'}, 'builddir': 'dummy2',
+                       'factory': f3})
+
+f4 = factory.BuildFactory([
+    s(ShellCommand, command="sleep 3")
+    ])
+
+c['builders'].append({'name': 'dummy3', 'slavename': 'bot1',
+                       'env': {'blah':'bar'}, 'builddir': 'dummy3',
+                       'factory': f4})
+"""
+
+class TestBuilder(RunMixin, unittest.TestCase):
+    def setUp(self):
+        RunMixin.setUp(self)
+        self.master.loadConfig(config_test_builder)
+        self.master.readConfig = True
+        self.master.startService()
+        self.connectSlave(builders=["dummy", "dummy2", "dummy3"])
+
+    def doBuilderEnvTest(self, branch, cb):
+        c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed",
+                           branch=branch)
+        self.master.change_svc.addChange(c)
+
+        d = defer.Deferred()
+        reactor.callLater(0.5, d.callback, None)
+        d.addCallback(cb)
+
+        return d
+
+    def testBuilderEnv(self):
+        return self.doBuilderEnvTest("dummy", self._testBuilderEnv1)
+
+    def _testBuilderEnv1(self, res):
+        b = self.master.botmaster.builders['dummy']
+        build = b.building[0]
+        s = build.currentStep
+        self.failUnless('foo' in s.cmd.args['env'])
+        self.failUnlessEqual('bar', s.cmd.args['env']['foo'])
+        self.failUnless('blah' in s.cmd.args['env'])
+        self.failUnlessEqual('blah', s.cmd.args['env']['blah'])
+
+    def testBuilderEnvOverride(self):
+        return self.doBuilderEnvTest("dummy2", self._testBuilderEnvOverride1)
+
+    def _testBuilderEnvOverride1(self, res):
+        b = self.master.botmaster.builders['dummy2']
+        build = b.building[0]
+        s = build.currentStep
+        self.failUnless('blah' in s.cmd.args['env'])
+        self.failUnlessEqual('blah', s.cmd.args['env']['blah'])
+
+    def testBuilderNoStepEnv(self):
+        return self.doBuilderEnvTest("dummy3", self._testBuilderNoStepEnv1)
+
+    def _testBuilderNoStepEnv1(self, res):
+        b = self.master.botmaster.builders['dummy3']
+        build = b.building[0]
+        s = build.currentStep
+        self.failUnless('blah' in s.cmd.args['env'])
+        self.failUnlessEqual('bar', s.cmd.args['env']['blah'])
diff -rN -u old-builderEnv/docs/buildbot.texinfo new-builderEnv/docs/buildbot.texinfo
--- old-builderEnv/docs/buildbot.texinfo	2008-12-06 00:35:12.000000000 -0500
+++ new-builderEnv/docs/buildbot.texinfo	2008-12-06 00:35:13.000000000 -0500
@@ -1769,6 +1769,28 @@
 Linux or Solaris builds) should naturally be associated with an
 OS-X-based buildslave.
 
+A @code{Builder} may be given a set of environments variables to be used
+in its @pxref{ShellCommand}s. These variables will override anything in the
+buildslave's environment. Variables passed directly to a 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'] = [
+  @{'name': 'test', 'slavenames': ['slave1', 'slave2', 'slave3', 'slave4',
+                                   'slave5', 'slave6'],
+    'builddir': 'test', 'factory': f',
+    'env': {'PATH': '/opt/local/bin:/opt/app/bin:/usr/local/bin:/usr/bin'}}
+
+@end example
 
 @node Users, Build Properties, Builder, Concepts
 @section Users
@@ -4843,7 +4865,8 @@
 @end example
 
 These variable settings will override any existing ones in the
-buildslave's environment. The exception is PYTHONPATH, which is merged
+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


