var fs = require('fs')
var path = require('path')
var mktemp = require('mktemp')
var rimraf = require('rimraf')
var synchronized = require('synchronized')


exports.Builder = Builder
function Builder (options) {
  var self = this

  this.reader = options.reader
  this.transformer = options.transformer

  this.tmpDir = mktemp.createDirSync('broccoli-XXXXXX.tmp')
  process.on('exit', function () {
    self.cleanupTmpDir()
  })

  this.cacheDir = path.join(this.tmpDir, 'cache.tmp')
  fs.mkdirSync(this.cacheDir)

  this.buildScheduled = false
}

// outputDir is optional
Builder.prototype.build = function (outputDir, callback) {
  var self = this

  if (this.buildScheduled) return
  this.buildScheduled = true

  synchronized(this, function (done) {
    self.buildScheduled = false

    var startTime = Date.now()

    self.buildError = null

    self.cleanupBuildProducts() // remove last build's directories
    if (outputDir == null) {
      self.outputTmpDir = mktemp.createDirSync(path.join(self.tmpDir, 'output-XXXXXX.tmp'))
      outputDir = self.outputTmpDir
    }
    self.buildTmpDir = mktemp.createDirSync(path.join(self.tmpDir, 'build-XXXXXX.tmp'))

    var readerDest = mktemp.createDirSync(path.join(self.buildTmpDir, 'reader-XXXXXX.tmp'))
    self.reader._setup({
      tmpDir: self.buildTmpDir,
      cacheDir: self.cacheDir
    })
    self.reader.read(readerDest, function (err) {
      if (err) {
        finish(err)
        return
      }
      self.transformer._setup({
        tmpDir: self.buildTmpDir,
        cacheDir: self.cacheDir
      })
      self.transformer.transform(readerDest, outputDir, function (err) {
        finish(err)
      })
    })

    function finish (err) {
      if (err) self.buildError = err
      console.log('Built ' + (err ? 'with error ' : '') + '(' + (Date.now() - startTime) + ' ms)')
      done()
      if (callback != null) callback()
    }
  })
}

Builder.prototype.cleanupTmpDir = function (exitCode) {
  if (this.tmpDir != null) {
    rimraf.sync(this.tmpDir)
  }
}

Builder.prototype.cleanupBuildProducts = function () {
  var fields = ['buildTmpDir', 'outputTmpDir']
  for (var i = 0; i < fields.length; i++) {
    if (this[fields[i]] != null) {
      rimraf.sync(this[fields[i]])
      this[fields[i]] = null
    }
  }
}

@@ -74,16 +74,47 @@
 ktemp')%0A
+var mkdirp = require('mkdirp')%0A
 var rimr
@@ -328,16 +328,83 @@
 former%0A%0A
+  var tmpBaseDir = options.tmpDir %7C%7C '.'%0A  mkdirp.sync(tmpBaseDir)%0A
   this.t
@@ -432,16 +432,38 @@
 DirSync(
+path.join(tmpBaseDir, 
 'broccol
@@ -476,16 +476,17 @@
 XX.tmp')
+)
 %0A  proce

Allow for configurable tmpDir in builder