chushihua
This commit is contained in:
+250
@@ -0,0 +1,250 @@
|
||||
// imported from ncp (this is temporary, will rewrite)
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var path = require('path')
|
||||
|
||||
function ncp (source, dest, options, callback) {
|
||||
var cback = callback
|
||||
|
||||
if (!callback) {
|
||||
cback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
var basePath = process.cwd()
|
||||
var currentPath = path.resolve(basePath, source)
|
||||
var targetPath = path.resolve(basePath, dest)
|
||||
|
||||
var filter = options.filter
|
||||
var transform = options.transform
|
||||
var clobber = options.clobber !== false
|
||||
var dereference = options.dereference
|
||||
|
||||
var errs = null
|
||||
|
||||
var started = 0
|
||||
var finished = 0
|
||||
var running = 0
|
||||
// this is pretty useless now that we're using graceful-fs
|
||||
// consider removing
|
||||
var limit = options.limit || 512
|
||||
|
||||
startCopy(currentPath)
|
||||
|
||||
function startCopy(source) {
|
||||
started++
|
||||
if (filter) {
|
||||
if (filter instanceof RegExp) {
|
||||
if (!filter.test(source)) {
|
||||
return cb(true)
|
||||
}
|
||||
}
|
||||
else if (typeof filter === 'function') {
|
||||
if (!filter(source)) {
|
||||
return cb(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
return getStats(source)
|
||||
}
|
||||
|
||||
function getStats(source) {
|
||||
var defer = global.setImmediate || process.nextTick
|
||||
var stat = dereference ? fs.stat : fs.lstat
|
||||
if (running >= limit) {
|
||||
return defer(function () {
|
||||
getStats(source)
|
||||
})
|
||||
}
|
||||
running++
|
||||
stat(source, function (err, stats) {
|
||||
var item = {}
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
|
||||
// We need to get the mode from the stats object and preserve it.
|
||||
item.name = source
|
||||
item.mode = stats.mode
|
||||
item.mtime = stats.mtime //modified time
|
||||
item.atime = stats.atime //access time
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
return onDir(item)
|
||||
}
|
||||
else if (stats.isFile()) {
|
||||
return onFile(item)
|
||||
}
|
||||
else if (stats.isSymbolicLink()) {
|
||||
// Symlinks don't really need to know about the mode.
|
||||
return onLink(source)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onFile(file) {
|
||||
var target = file.name.replace(currentPath, targetPath)
|
||||
isWritable(target, function (writable) {
|
||||
if (writable) {
|
||||
copyFile(file, target)
|
||||
} else {
|
||||
if(clobber) {
|
||||
rmFile(target, function () {
|
||||
copyFile(file, target)
|
||||
})
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function copyFile(file, target) {
|
||||
var readStream = fs.createReadStream(file.name),
|
||||
writeStream = fs.createWriteStream(target, { mode: file.mode })
|
||||
|
||||
readStream.on('error', onError)
|
||||
writeStream.on('error', onError)
|
||||
|
||||
if(transform) {
|
||||
transform(readStream, writeStream, file)
|
||||
} else {
|
||||
writeStream.on('open', function() {
|
||||
readStream.pipe(writeStream)
|
||||
})
|
||||
}
|
||||
|
||||
//presumably old node then
|
||||
var eventName = global.setImmediate ? 'finish' : 'close'
|
||||
writeStream.once(eventName, function() {
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
function rmFile(file, done) {
|
||||
fs.unlink(file, function (err) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
return done()
|
||||
})
|
||||
}
|
||||
|
||||
function onDir(dir) {
|
||||
var target = dir.name.replace(currentPath, targetPath)
|
||||
isWritable(target, function (writable) {
|
||||
if (writable) {
|
||||
return mkDir(dir, target)
|
||||
}
|
||||
copyDir(dir.name)
|
||||
})
|
||||
}
|
||||
|
||||
function mkDir(dir, target) {
|
||||
fs.mkdir(target, dir.mode, function (err) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
copyDir(dir.name)
|
||||
})
|
||||
}
|
||||
|
||||
function copyDir(dir) {
|
||||
fs.readdir(dir, function (err, items) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
items.forEach(function (item) {
|
||||
startCopy(path.join(dir, item))
|
||||
})
|
||||
return cb()
|
||||
})
|
||||
}
|
||||
|
||||
function onLink(link) {
|
||||
var target = link.replace(currentPath, targetPath)
|
||||
fs.readlink(link, function (err, resolvedPath) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
checkLink(resolvedPath, target)
|
||||
})
|
||||
}
|
||||
|
||||
function checkLink(resolvedPath, target) {
|
||||
if (dereference) {
|
||||
resolvedPath = path.resolve(basePath, resolvedPath)
|
||||
}
|
||||
isWritable(target, function (writable) {
|
||||
if (writable) {
|
||||
return makeLink(resolvedPath, target)
|
||||
}
|
||||
fs.readlink(target, function (err, targetDest) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
if (dereference) {
|
||||
targetDest = path.resolve(basePath, targetDest)
|
||||
}
|
||||
if (targetDest === resolvedPath) {
|
||||
return cb()
|
||||
}
|
||||
return rmFile(target, function () {
|
||||
makeLink(resolvedPath, target)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function makeLink(linkPath, target) {
|
||||
fs.symlink(linkPath, target, function (err) {
|
||||
if (err) {
|
||||
return onError(err)
|
||||
}
|
||||
return cb()
|
||||
})
|
||||
}
|
||||
|
||||
function isWritable(path, done) {
|
||||
fs.lstat(path, function (err) {
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') return done(true)
|
||||
return done(false)
|
||||
}
|
||||
return done(false)
|
||||
})
|
||||
}
|
||||
|
||||
function onError(err) {
|
||||
if (options.stopOnError) {
|
||||
return cback(err)
|
||||
}
|
||||
else if (!errs && options.errs) {
|
||||
errs = fs.createWriteStream(options.errs)
|
||||
}
|
||||
else if (!errs) {
|
||||
errs = []
|
||||
}
|
||||
if (typeof errs.write === 'undefined') {
|
||||
errs.push(err)
|
||||
}
|
||||
else {
|
||||
errs.write(err.stack + '\n\n')
|
||||
}
|
||||
return cb()
|
||||
}
|
||||
|
||||
function cb(skipped) {
|
||||
if (!skipped) running--
|
||||
finished++
|
||||
if ((started === finished) && (running === 0)) {
|
||||
if (cback !== undefined ) {
|
||||
return errs ? cback(errs) : cback(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo, make this just export ncp
|
||||
module.exports.ncp = ncp
|
||||
|
||||
Reference in New Issue
Block a user