Comparing version 1.1.0 to 2.0.0
114
cprf.js
var fs = require('graceful-fs'); | ||
var path = require('path'); | ||
var async = require('async'); | ||
var parallel = require('run-parallel'); | ||
var stream = require('stream'); | ||
var events = require('events'); | ||
module.exports = copy; | ||
module.exports = cprf; | ||
module.exports.copy = copy; | ||
function cprf () { | ||
return copy.apply( | ||
new events.EventEmitter(), | ||
[].slice.call(arguments) | ||
); | ||
} | ||
function copy (src, dest, done) { | ||
var ee = this; | ||
function _error (err) { | ||
var deepError = new Error(err); | ||
ee.emit('error', deepError); | ||
return done(deepError); | ||
} | ||
fs.lstat(src, function (err, stats) { | ||
if (err) return done(new Error(err)); | ||
if (err) return _error(err); | ||
if (stats.isDirectory()) { | ||
return mkdir(dest, function (err) { | ||
if (err) return done(new Error(err)); | ||
return fs.readdir(src, function (err, files) { | ||
if (err) return done(new Error(err)); | ||
async.each(files, function (file, done) { | ||
copy(path.join(src, file), path.join(dest, file), done); | ||
}, done); | ||
}); | ||
}); | ||
ee.emit('copy', stats, src, dest, _copy); | ||
if (!ee.listeners('copy').length) { | ||
return _copy(src, dest, null); | ||
} | ||
if (stats.isSymbolicLink()) { | ||
return fs.readlink(src, function (err, link) { | ||
if (err) return done(new Error(err)); | ||
fs.symlink(link, dest, function (err) { | ||
done(); | ||
function _copy (src, dest, transform) { | ||
// Directory | ||
if (stats.isDirectory()) { | ||
return fs.mkdir(dest, function (err) { | ||
if (err && err.code !== 'EEXIST') { | ||
return _error(err); | ||
} | ||
fs.readdir(src, function (err, files) { | ||
if (err) return _error(err); | ||
parallel(files.map(function (file) { | ||
return copy.bind(ee, | ||
path.join(src, file), | ||
path.join(dest, file)); | ||
}), done); | ||
}); | ||
}); | ||
}); | ||
} | ||
} | ||
copyFile(src, dest, function (err) { | ||
if (err) return done(err); | ||
fs.chmod(dest, stats.mode, done); | ||
}); | ||
// Symlink | ||
if (stats.isSymbolicLink()) { | ||
return fs.readlink(src, function (err, link) { | ||
if (err) return _error(err); | ||
}); | ||
} | ||
fs.symlink(link, dest, function (err) { | ||
done(null); | ||
}); | ||
}); | ||
} | ||
function mkdir (dir, done) { | ||
fs.exists(dir, function (exists) { | ||
return exists ? done() : fs.mkdir(dir, done); | ||
}); | ||
} | ||
// File | ||
var fin = fs.createReadStream(src); | ||
fin.on('error', _error); | ||
function copyFile (src, dest, done) { | ||
var doneCalled = false; | ||
var fout = fs.createWriteStream(dest); | ||
fout.on('error', _error); | ||
var fin = fs.createReadStream(src); | ||
fin.on('error', finish); | ||
fout.on('finish', function () { | ||
fs.chmod(dest, stats.mode, done); | ||
}); | ||
var fout = fs.createWriteStream(dest); | ||
fout.on('error', finish); | ||
fout.on('close', finish); | ||
if (transform) { | ||
fin.pipe(transform).pipe(fout); | ||
} else { | ||
fin.pipe(fout); | ||
} | ||
} | ||
fin.pipe(fout); | ||
}); | ||
function finish (err) { | ||
if (doneCalled) return; | ||
doneCalled = true; | ||
done(err); | ||
} | ||
return ee; | ||
} |
{ | ||
"name": "cprf", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"description": "Recursively copy files and directories", | ||
"main": "cprf.js", | ||
"scripts": { | ||
"test": "node test/test" | ||
"test": "node test" | ||
}, | ||
@@ -28,9 +28,9 @@ "repository": { | ||
"dependencies": { | ||
"async": "~0.9.x", | ||
"graceful-fs": "~3.0.2", | ||
"rimraf": "~2.2.x" | ||
"run-parallel": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"tape": "2.14.0" | ||
"tape": "2.14.0", | ||
"rimraf": "~2.2.x" | ||
} | ||
} |
@@ -16,2 +16,3 @@ # cprf | ||
- Simple usage interface | ||
- Customizeable copy action | ||
- Fully asynchronous | ||
@@ -29,2 +30,4 @@ - Uses graceful-fs to retry EMFILE errors | ||
To copy `./my_source` to `./my_destination`: | ||
```javascript | ||
@@ -34,10 +37,40 @@ var cprf = require('cprf'); | ||
cprf('./my_source', './my_destination', function (err) { | ||
if (err) { | ||
console.error(err); | ||
} | ||
if (err) throw err; | ||
}); | ||
``` | ||
You can also completely customize the copy procedure by listening to the `copy` event. This allows you to do things like changing destination file names and modifying file contents on copy. | ||
```javascript | ||
var cprf = require('cprf'); | ||
var stream = require('stream'); | ||
var makeUpperCase = new stream.Transform(); | ||
makeUpperCase._transform = function (chunk, enc, cb) { | ||
cb(null, chunk.toString().toUpperCase()); | ||
}; | ||
cprf('./my_source', './my_destination', function (err) { | ||
if (err) throw err; | ||
}).on('copy', function (stats, src, dest, copy) { | ||
copy(src, dest, makeUpperCase); | ||
}); | ||
``` | ||
The `copy` event emits the following data: | ||
- `stats` - the `[fs.Stat](http://nodejs.org/api/fs.html#fs_class_fs_stats)` object resulting from running `[fs.lstat()](http://nodejs.org/api/fs.html#fs_fs_lstat_path_callback)` on the source; | ||
- `src` - the absolute source path; | ||
- `dest` - the absolute destination path; | ||
- `copy` - a function of signature `copy(src, dest, transform)`. You must call it if you wish to actually perform a copy operation. It takes the following arguments: | ||
- `src` - the absolute source path; | ||
- `dest` - the absolute destination path; | ||
- `transform` - a [stream.Transform](http://nodejs.org/api/stream.html#stream_class_stream_transform) instance through which the source file contents will be piped before being written to the destination. If the source is not a file, it will be ignored. | ||
## Changelog | ||
#### 2.0.0 | ||
- Add ability to customize copy procedure via the copy event. | ||
#### 1.1.0 | ||
@@ -44,0 +77,0 @@ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10196
2
19
188
93
2
1
+ Addedrun-parallel@^1.0.0
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedrun-parallel@1.2.0(transitive)
- Removedasync@~0.9.x
- Removedrimraf@~2.2.x
- Removedasync@0.9.2(transitive)
- Removedrimraf@2.2.8(transitive)