1 // imported from ncp (this is temporary, will rewrite)
3 var fs = require('graceful-fs')
4 var path = require('path')
5 var utimes = require('../util/utimes')
7 function ncp (source, dest, options, callback) {
13 var basePath = process.cwd()
14 var currentPath = path.resolve(basePath, source)
15 var targetPath = path.resolve(basePath, dest)
17 var filter = options.filter
18 var transform = options.transform
19 var clobber = options.clobber !== false
20 var dereference = options.dereference
21 var preserveTimestamps = options.preserveTimestamps === true
28 // this is pretty useless now that we're using graceful-fs
30 var limit = options.limit || 512
32 startCopy(currentPath)
34 function startCopy (source) {
37 if (filter instanceof RegExp) {
38 if (!filter.test(source)) {
41 } else if (typeof filter === 'function') {
42 if (!filter(source)) {
47 return getStats(source)
50 function getStats (source) {
51 var stat = dereference ? fs.stat : fs.lstat
52 if (running >= limit) {
53 return setImmediate(function () {
58 stat(source, function (err, stats) {
59 if (err) return onError(err)
61 // We need to get the mode from the stats object and preserve it.
65 mtime: stats.mtime, // modified time
66 atime: stats.atime, // access time
67 stats: stats // temporary
70 if (stats.isDirectory()) {
72 } else if (stats.isFile() || stats.isCharacterDevice() || stats.isBlockDevice()) {
74 } else if (stats.isSymbolicLink()) {
75 // Symlinks don't really need to know about the mode.
81 function onFile (file) {
82 var target = file.name.replace(currentPath, targetPath)
83 isWritable(target, function (writable) {
85 copyFile(file, target)
88 rmFile(target, function () {
89 copyFile(file, target)
98 function copyFile (file, target) {
99 var readStream = fs.createReadStream(file.name)
100 var writeStream = fs.createWriteStream(target, { mode: file.mode })
102 readStream.on('error', onError)
103 writeStream.on('error', onError)
106 transform(readStream, writeStream, file)
108 writeStream.on('open', function () {
109 readStream.pipe(writeStream)
113 writeStream.once('finish', function () {
114 fs.chmod(target, file.mode, function (err) {
115 if (err) return onError(err)
116 if (preserveTimestamps) {
117 utimes.utimesMillis(target, file.atime, file.mtime, function (err) {
118 if (err) return onError(err)
128 function rmFile (file, done) {
129 fs.unlink(file, function (err) {
130 if (err) return onError(err)
135 function onDir (dir) {
136 var target = dir.name.replace(currentPath, targetPath)
137 isWritable(target, function (writable) {
139 return mkDir(dir, target)
145 function mkDir (dir, target) {
146 fs.mkdir(target, dir.mode, function (err) {
147 if (err) return onError(err)
148 // despite setting mode in fs.mkdir, doesn't seem to work
149 // so we set it here.
150 fs.chmod(target, dir.mode, function (err) {
151 if (err) return onError(err)
157 function copyDir (dir) {
158 fs.readdir(dir, function (err, items) {
159 if (err) return onError(err)
160 items.forEach(function (item) {
161 startCopy(path.join(dir, item))
167 function onLink (link) {
168 var target = link.replace(currentPath, targetPath)
169 fs.readlink(link, function (err, resolvedPath) {
170 if (err) return onError(err)
171 checkLink(resolvedPath, target)
175 function checkLink (resolvedPath, target) {
177 resolvedPath = path.resolve(basePath, resolvedPath)
179 isWritable(target, function (writable) {
181 return makeLink(resolvedPath, target)
183 fs.readlink(target, function (err, targetDest) {
184 if (err) return onError(err)
187 targetDest = path.resolve(basePath, targetDest)
189 if (targetDest === resolvedPath) {
192 return rmFile(target, function () {
193 makeLink(resolvedPath, target)
199 function makeLink (linkPath, target) {
200 fs.symlink(linkPath, target, function (err) {
201 if (err) return onError(err)
206 function isWritable (path, done) {
207 fs.lstat(path, function (err) {
209 if (err.code === 'ENOENT') return done(true)
216 function onError (err) {
217 if (options.stopOnError) {
219 } else if (!errs && options.errs) {
220 errs = fs.createWriteStream(options.errs)
224 if (typeof errs.write === 'undefined') {
227 errs.write(err.stack + '\n\n')
232 function doneOne (skipped) {
233 if (!skipped) running--
235 if ((started === finished) && (running === 0)) {
236 if (callback !== undefined) {
237 return errs ? callback(errs) : callback(null)