Comparing version 0.1.1 to 0.2.0
147
index.js
'use strict'; | ||
var fs = require('fs'); | ||
var gfs = require('graceful-fs'); | ||
var path = require('path'); | ||
var extend = require('extend-shallow'); | ||
var through = require('through2'); | ||
var mkdirp = require('mkdirp'); | ||
var stripBom = require('strip-bom'); | ||
var through2 = require('through2'); | ||
module.exports = function dest(dir, options) { | ||
var stream = through2.obj(function (file, enc, cb) { | ||
normalize(dir, file, options, function (err, fp) { | ||
var stream = through.obj(function (file, enc, cb) { | ||
var opts = normalizeOpts(file, options); | ||
if (typeof file.dest === 'function') { | ||
return file.dest(dir, opts, function (err, fp) { | ||
if (err) return cb(err); | ||
writeFile(fp, file, opts, cb); | ||
}); | ||
} | ||
normalize(dir, file, opts, function (err, fp) { | ||
if (err) return cb(err); | ||
writeContents(fp, file, cb); | ||
writeFile(fp, file, opts, cb); | ||
}); | ||
@@ -21,36 +30,67 @@ }); | ||
function streamFile(file, cb) { | ||
file.contents = fs.createReadStream(file.path).pipe(stripBom.stream()); | ||
function writeFile(fp, file, opts, cb) { | ||
// mkdirp the folder the file is going in | ||
mkdirp(path.dirname(fp), opts.dirMode, function (err) { | ||
if (err) return cb(err); | ||
writeContents(fp, file, cb); | ||
}); | ||
} | ||
function normalizeOpts(file, options) { | ||
var opts = extend({ | ||
cwd: process.cwd(), | ||
mode: (file.stat ? file.stat.mode : null), | ||
dirMode: null, | ||
overwrite: true | ||
}, options); | ||
opts.flag = (opts.overwrite ? 'w' : 'wx'); | ||
return opts; | ||
} | ||
function streamFile(file, opts, cb) { | ||
file.contents = fs.createReadStream(file.path); | ||
cb(null, file); | ||
} | ||
function writeContents(destDir, file, cb) { | ||
function writeContents(writePath, file, cb) { | ||
if (file.isDirectory()) { | ||
return writeDir(destDir, file, written); | ||
return writeDir(writePath, file, written); | ||
} | ||
if (file.isStream()) { | ||
return writeStream(destDir, file, written); | ||
return writeStream(writePath, file, written); | ||
} | ||
if (file.isBuffer()) { | ||
return writeBuffer(destDir, file, written); | ||
return writeBuffer(writePath, file, written); | ||
} | ||
if (file.symlink) { | ||
return writeSymbolicLink(writePath, file, written); | ||
} | ||
if (file.isNull()) { | ||
return done(); | ||
return complete(); | ||
} | ||
function done(err) { | ||
function complete(err) { | ||
cb(err, file); | ||
} | ||
function written(err) { | ||
if (isErrorFatal(err)) return done(err); | ||
if (!file.stat || typeof file.stat.mode !== 'number') { | ||
return done(); | ||
if (isErrorFatal(err)) { | ||
return complete(err); | ||
} | ||
fs.stat(destDir, function (err, st) { | ||
if (err) return done(err); | ||
// octal 7777 = decimal 4095 | ||
var currentMode = (st.mode & 4095); | ||
if (currentMode === file.stat.mode) { | ||
return done(); | ||
if (!file.stat || typeof file.stat.mode !== 'number' || file.symlink) { | ||
return complete(); | ||
} | ||
fs.stat(writePath, function(err, st) { | ||
if (err) { | ||
return complete(err); | ||
} | ||
fs.chmod(destDir, file.stat.mode, done); | ||
var currentMode = (st.mode & parseInt('0777', 8)); | ||
var expectedMode = (file.stat.mode & parseInt('0777', 8)); | ||
if (currentMode === expectedMode) { | ||
return complete(); | ||
} | ||
fs.chmod(writePath, expectedMode, complete); | ||
}); | ||
@@ -60,6 +100,12 @@ } | ||
function isErrorFatal(err) { | ||
if (!err) return false; | ||
if (err.code === 'EEXIST' && file.flag === 'wx') { | ||
if (!err) { | ||
return false; | ||
} | ||
// Handle scenario for file overwrite failures. | ||
else if (err.code === 'EEXIST' && file.flag === 'wx') { | ||
return false; | ||
} | ||
// Otherwise, this is a fatal error | ||
return true; | ||
@@ -71,3 +117,3 @@ } | ||
var opt = { mode: file.stat.mode, flag: file.flag }; | ||
fs.writeFile(destDir, file.contents, opt, cb); | ||
gfs.writeFile(destDir, file.contents, opt, cb); | ||
} | ||
@@ -80,5 +126,6 @@ | ||
function writeStream(destDir, file, cb) { | ||
var opt = { mode: file.stat.mode, flag: file.flag }; | ||
var opts = {mode: file.stat.mode, flag: file.flag}; | ||
var outStream = fs.createWriteStream(destDir, opt); | ||
var outStream = gfs.createWriteStream(destDir, opts); | ||
file.contents.once('error', complete); | ||
@@ -91,5 +138,6 @@ outStream.once('error', complete); | ||
function success() { | ||
streamFile(file, complete); | ||
streamFile(file, {}, complete); | ||
} | ||
// cleanup | ||
function complete(err) { | ||
@@ -103,11 +151,13 @@ file.contents.removeListener('error', cb); | ||
function normalize(dest, file, options, cb) { | ||
var opts = extend({ | ||
cwd: process.cwd(), | ||
mode: (file.stat ? file.stat.mode : null), | ||
dirMode: null, | ||
overwrite: true | ||
}, options); | ||
function writeSymbolicLink(destDir, file, cb) { | ||
gfs.symlink(file.symlink, destDir, function (err) { | ||
if (err && err.code !== 'EEXIST') { | ||
return cb(err); | ||
} | ||
cb(null, file); | ||
}); | ||
} | ||
opts.flag = (opts.overwrite ? 'w' : 'wx'); | ||
function normalize(dest, file, opts, cb) { | ||
opts = opts || {}; | ||
var cwd = path.resolve(opts.cwd); | ||
@@ -120,3 +170,16 @@ | ||
var destPath = (typeof dest === 'string' ? dest : dest(file)); | ||
var basePath = path.resolve(cwd, destPath); | ||
var base = opts.base; | ||
if (base && typeof base !== 'string' && typeof base !== 'function') { | ||
throw new Error('Invalid base option'); | ||
} | ||
var basePath = base | ||
? (typeof base === 'string' ? base : base(file)) | ||
: path.resolve(cwd, destPath); | ||
if (typeof basePath !== 'string') { | ||
throw new Error('Invalid base option'); | ||
} | ||
var filepath = path.resolve(basePath, path.basename(file.relative)); | ||
@@ -126,3 +189,3 @@ var dir = path.dirname(filepath); | ||
// wire up new properties | ||
file.stat = (file.stat || new fs.Stats()); | ||
file.stat = (file.stat || new gfs.Stats()); | ||
file.stat.mode = opts.mode; | ||
@@ -134,7 +197,3 @@ file.flag = opts.flag; | ||
// mkdirp the folder the file is going in | ||
mkdirp(dir, opts.dirMode, function (err) { | ||
if (err) return cb(err); | ||
cb(null, filepath); | ||
}); | ||
cb(null, filepath); | ||
} |
{ | ||
"name": "dest", | ||
"description": "Plugin for Template, for writing a file to the file system.", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/jonschlinkert/dest", | ||
@@ -23,8 +23,16 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"dependencies": { | ||
"extend-shallow": "^1.1.4", | ||
"extend-shallow": "^2.0.1", | ||
"graceful-fs": "^4.1.2", | ||
"mkdirp": "^0.5.1", | ||
"strip-bom": "^1.0.0", | ||
"through2": "^2.0.0" | ||
}, | ||
"devDependencies": {}, | ||
"devDependencies": { | ||
"buffer-equal": "0.0.1", | ||
"mocha": "^2.3.2", | ||
"rimraf": "^2.4.3", | ||
"should": "^7.1.0", | ||
"sinon": "^1.16.1", | ||
"vinyl": "^0.5.3", | ||
"vinyl-fs": "^1.0.0" | ||
}, | ||
"keywords": [ | ||
@@ -31,0 +39,0 @@ "dest", |
@@ -40,3 +40,3 @@ # dest [![NPM version](https://badge.fury.io/js/dest.svg)](http://badge.fury.io/js/dest) | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/dest/issues/new) | ||
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/dest/issues/new). | ||
@@ -57,2 +57,2 @@ ## Author | ||
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 11, 2015._ | ||
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on September 14, 2015._ |
7892
156
7
+ Addedgraceful-fs@^4.1.2
+ Addedextend-shallow@2.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedis-extendable@0.1.1(transitive)
- Removedstrip-bom@^1.0.0
- Removedextend-shallow@1.1.4(transitive)
- Removedfirst-chunk-stream@1.0.0(transitive)
- Removedis-utf8@0.2.1(transitive)
- Removedkind-of@1.1.0(transitive)
- Removedstrip-bom@1.0.0(transitive)
Updatedextend-shallow@^2.0.1