bricks-cli
Version:
Command line tool for developing ambitious ember.js apps
73 lines (68 loc) • 2.79 kB
JavaScript
var fs = require('fs')
var walkSync = require('walk-sync')
var Writer = require('broccoli-writer')
var helpers = require('broccoli-kitchen-sink-helpers')
var mapSeries = require('promise-map-series')
module.exports = TreeMerger
TreeMerger.prototype = Object.create(Writer.prototype)
TreeMerger.prototype.constructor = TreeMerger
function TreeMerger (inputTrees, options) {
if (!(this instanceof TreeMerger)) return new TreeMerger(inputTrees, options)
if (!Array.isArray(inputTrees)) {
throw new Error('Expected array, got ' + inputTrees)
}
this.inputTrees = inputTrees
this.options = options || {}
}
TreeMerger.prototype.write = function (readTree, destDir) {
var self = this
var files = {}
var directories = {}
return mapSeries(this.inputTrees, readTree).then(function (treePaths) {
for (var i = treePaths.length - 1; i >= 0; i--) {
var treeContents = walkSync(treePaths[i])
var fileIndex
for (var j = 0; j < treeContents.length; j++) {
var relativePath = treeContents[j]
var destPath = destDir + '/' + relativePath
if (relativePath.slice(-1) === '/') { // is directory
relativePath = relativePath.slice(0, -1) // chomp "/"
fileIndex = files[relativePath]
if (fileIndex != null) {
throwFileAndDirectoryCollision(relativePath, fileIndex, i)
}
if (directories[relativePath] == null) {
fs.mkdirSync(destPath)
directories[relativePath] = i
}
} else { // is file
var directoryIndex = directories[relativePath]
if (directoryIndex != null) {
throwFileAndDirectoryCollision(relativePath, i, directoryIndex)
}
fileIndex = files[relativePath.toLowerCase()]
if (fileIndex != null) {
if (!self.options.overwrite) {
throw new Error('Merge error: ' +
'file "' + relativePath + '" exists in ' +
treePaths[i] + ' and ' + treePaths[fileIndex] + ' - ' +
'pass option { overwrite: true } to mergeTrees in order ' +
'to have the latter file win')
}
// Else, ignore this file. It is "overwritten" by a file we copied
// earlier, thanks to reverse iteration over trees
} else {
helpers.copyPreserveSync(
treePaths[i] + '/' + relativePath, destPath)
files[relativePath.toLowerCase()] = i
}
}
}
}
function throwFileAndDirectoryCollision (relativePath, fileIndex, directoryIndex) {
throw new Error('Merge error: "' + relativePath +
'" exists as a file in ' + treePaths[fileIndex] +
' but as a directory in ' + treePaths[directoryIndex])
}
})
}