function dest(outFolder, opt) {
if (!opt) {
opt = {};
}
function saveFile(file, enc, cb) {
prepareWrite(outFolder, file, opt, function(err, writePath) {
if (err) {
return cb(err);
}
writeContents(writePath, file, cb);
});
}
var saveStream = through2.obj(opt, saveFile);
if (!opt.sourcemaps) {
// Sink the save stream to start flowing
// Do this on nextTick, it will flow at slowest speed of piped streams
process.nextTick(sink(saveStream));
return saveStream;
}
var sourcemapOpt = opt.sourcemaps;
if (typeof sourcemapOpt === 'boolean') {
sourcemapOpt = {};
}
if (typeof sourcemapOpt === 'string') {
sourcemapOpt = {
path: sourcemapOpt,
};
}
var mapStream = sourcemaps.write(sourcemapOpt.path, sourcemapOpt);
var outputStream = duplexify.obj(mapStream, saveStream);
mapStream.pipe(saveStream);
// Sink the output stream to start flowing
// Do this on nextTick, it will flow at slowest speed of piped streams
process.nextTick(sink(outputStream));
return outputStream;
}...
- [103bb8c](https://github.com/gulpjs/vinyl-fs/commit/103bb8ca0b16e888ee44146603d5591220e228f4) update glob-watcher (@contra)
- [a319889](https://github.com/gulpjs/vinyl-fs/commit/a319889b9cbad1db0097d041ad02e0e2f76640bf) check src and dest args, closes #
8 (@contra)
- [671197a](https://github.com/gulpjs/vinyl-fs/commit/671197a54ddda0277abdc0c1c9fce27cc8ab9b86) drop support for 0.9 (@contra)
- [f89e03e](https://github.com/gulpjs/vinyl-fs/commit/f89e03e62cb62dc6c28d0ebe6f146123be2232a7) 0.1.0 (@contra)
- [bb34369](https://github.com/gulpjs/vinyl-fs/commit/bb343692f3bbeab08b40b4bb1ee20af7205f2837) comment (@contra)
- [c1c866a](https://github.com/gulpjs/vinyl-fs/commit/c1c866a5277038056d52fb106b2bca8cea430e59) mergit (@contra)
- [cc81580](https://github.com/gulpjs/vinyl-fs/commit/cc81580a4818e2260a367c54bdcc42b0b4d0a5cc) respect file modes in dest, add
mode option to dest (@contra)
- [#10](https://github.com/gulpjs/vinyl-fs/pull/10) Allow piping streaming vinyls through multiple .dest()'s (@hughsk)
- [d5566b2](https://github.com/gulpjs/vinyl-fs/commit/d5566b213b7e90a94b20aad35d4c08b2861c8247) Use ./src/streamFile for re-streaming
.dest() streams (@hughsk)
- [868a3ec](https://github.com/gulpjs/vinyl-fs/commit/868a3ecc7945e798ee702cc30c5bcfff2af3ecd5) Allow piping streaming vinyls through
multiple .dest()'s (@hughsk)
- [191d4ae](https://github.com/gulpjs/vinyl-fs/commit/191d4ae3672c76eb0cf0d46a2404c8e60e587d85) update file paths as they cruise
through .dest (@contra)
- [cb69aa6](https://github.com/gulpjs/vinyl-fs/commit/cb69aa6c7ead7a435067fdfc89f89cd8af1215d4) cleanup (@contra)
- [f50d669](https://github.com/gulpjs/vinyl-fs/commit/f50d669a968f6f69ef07a0cc34b11704829c9c9f) add tests for relative cwd (@contra
)
- [39dfc18](https://github.com/gulpjs/vinyl-fs/commit/39dfc189367154136718fa0958712b1b14ea5e5a) fix tests (@contra)
- [60dac5f](https://github.com/gulpjs/vinyl-fs/commit/60dac5fa38c3470556d987b01405d3ccca6af9ec) remove async dep (@contra)
...function src(glob, opt) {
var options = assign({
read: true,
buffer: true,
stripBOM: true,
sourcemaps: false,
passthrough: false,
followSymlinks: true,
}, opt);
// Don't pass `read` option on to through2
var read = options.read !== false;
options.read = undefined;
var inputPass;
if (!isValidGlob(glob)) {
throw new Error('Invalid glob argument: ' + glob);
}
var globStream = gs.create(glob, options);
var outputStream = globStream
.pipe(wrapWithVinylFile(options));
if (options.since != null) {
outputStream = outputStream
.pipe(filterSince(options.since));
}
if (read) {
outputStream = outputStream
.pipe(getContents(options));
}
if (options.passthrough === true) {
inputPass = through2.obj(options);
outputStream = duplexify.obj(inputPass, merge(outputStream, inputPass));
}
if (options.sourcemaps === true) {
outputStream = outputStream
.pipe(sourcemaps.init({ loadMaps: true }));
}
globStream.on('error', outputStream.emit.bind(outputStream, 'error'));
return outputStream;
}...
var vfs = require('vinyl-fs');
var log = function(file, cb) {
console.log(file.path);
cb(null, file);
};
vfs.src(['./js/**/*.js', '!./js/vendor/*.js'])
.pipe(map(log))
.pipe(vfs.dest('./output'));
```
## API
### `src(globs[, options])`
...function symlink(outFolder, opt) {
function linkFile(file, enc, cb) {
var srcPath = file.path;
var symType = (file.isDirectory() ? 'dir' : 'file');
prepareWrite(outFolder, file, opt, function(err, writePath) {
if (err) {
return cb(err);
}
fs.symlink(srcPath, writePath, symType, function(err) {
if (err && err.code !== 'EEXIST') {
return cb(err);
}
cb(null, file);
});
});
}
var stream = through2.obj(opt, linkFile);
// TODO: option for either backpressure or lossy
stream.resume();
return stream;
}...
Type: `String`
Default: `process.cwd()`
##### `options.base`
The folder relative to the cwd. This is used to determine the file names when saving in `.symlink
()`. Can also be a function that takes in a file and returns a folder path.
Type: `String` or `Function`
Default: The `cwd` resolved to the folder path.
##### `options.dirMode`
...function closeFd(propagatedErr, fd, callback) {
if (typeof fd !== 'number') {
return callback(propagatedErr);
}
fs.close(fd, onClosed);
function onClosed(closeErr) {
if (propagatedErr || closeErr) {
return callback(propagatedErr || closeErr);
}
callback();
}
}...
flag: file.flag,
};
fo.writeFile(writePath, file.contents, opt, onWriteFile);
function onWriteFile(writeErr, fd) {
if (writeErr) {
return fo.closeFd(writeErr, fd, written);
}
fo.updateMetadata(fd, file, onUpdate);
}
function onUpdate(statErr, fd) {
fo.closeFd(statErr, fd, written);
...function getModeDiff(fsMode, vinylMode) {
var modeDiff = 0;
if (typeof vinylMode === 'number') {
modeDiff = (vinylMode ^ fsMode) & MASK_MODE;
}
return modeDiff;
}n/a
function getTimesDiff(fsStat, vinylStat) {
if (!isValidDate(vinylStat.mtime)) {
return;
}
if (isEqual(vinylStat.mtime, fsStat.mtime) &&
isEqual(vinylStat.atime, fsStat.atime)) {
return;
}
var atime;
if (isValidDate(vinylStat.atime)) {
atime = vinylStat.atime;
} else {
atime = fsStat.atime;
}
if (!isValidDate(atime)) {
atime = undefined;
}
var timesDiff = {
mtime: vinylStat.mtime,
atime: atime,
};
return timesDiff;
}n/a
function isOwner(fsStat) {
var hasGetuid = (typeof process.getuid === 'function');
var hasGeteuid = (typeof process.geteuid === 'function');
// If we don't have either, assume we don't have permissions.
// This should only happen on Windows.
// Windows basically noops fchmod and errors on futimes called on directories.
if (!hasGeteuid && !hasGetuid) {
return false;
}
var uid;
if (hasGeteuid) {
uid = process.geteuid();
} else {
uid = process.getuid();
}
if (fsStat.uid !== uid && uid !== 0) {
return false;
}
return true;
}n/a
function updateMetadata(fd, file, callback) {
fs.fstat(fd, onStat);
function onStat(err, stat) {
if (err) {
return callback(err, fd);
}
// Check if mode needs to be updated
var modeDiff = getModeDiff(stat.mode, file.stat.mode);
// Check if atime/mtime need to be updated
var timesDiff = getTimesDiff(stat, file.stat);
// Set file.stat to the reflect current state on disk
assign(file.stat, stat);
// Nothing to do
if (!modeDiff && !timesDiff) {
return callback(null, fd);
}
// Check access, `futimes` and `fchmod` only work if we own the file,
// or if we are effectively root.
if (!isOwner(stat)) {
return callback(null, fd);
}
if (modeDiff) {
return mode();
}
times();
function mode() {
var mode = stat.mode ^ modeDiff;
fs.fchmod(fd, mode, onFchmod);
function onFchmod(fchmodErr) {
if (!fchmodErr) {
file.stat.mode = mode;
}
if (timesDiff) {
return times(fchmodErr);
}
callback(fchmodErr, fd);
}
}
function times(fchmodErr) {
fs.futimes(fd, timesDiff.atime, timesDiff.mtime, onFutimes);
function onFutimes(futimesErr) {
if (!futimesErr) {
file.stat.atime = timesDiff.atime;
file.stat.mtime = timesDiff.mtime;
}
callback(fchmodErr || futimesErr, fd);
}
}
}
}...
fo.writeFile(writePath, file.contents, opt, onWriteFile);
function onWriteFile(writeErr, fd) {
if (writeErr) {
return fo.closeFd(writeErr, fd, written);
}
fo.updateMetadata(fd, file, onUpdate);
}
function onUpdate(statErr, fd) {
fo.closeFd(statErr, fd, written);
}
}
...function writeFile(path, data, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
if (!Buffer.isBuffer(data)) {
callback(new TypeError('Data must be a Buffer'));
return;
}
if (!options) {
options = {};
}
// Default the same as node
var mode = options.mode || DEFAULT_FILE_MODE;
var flag = options.flag || 'w';
var position = APPEND_MODE_REGEXP.test(flag) ? null : 0;
fs.open(path, flag, mode, onOpen);
function onOpen(err, fd) {
if (err) {
return onComplete(err);
}
fs.write(fd, data, 0, data.length, position, onComplete);
function onComplete(err) {
callback(err, fd);
}
}
}...
function writeBuffer(writePath, file, written) {
var opt = {
mode: file.stat.mode,
flag: file.flag,
};
fo.writeFile(writePath, file.contents, opt, onWriteFile);
function onWriteFile(writeErr, fd) {
if (writeErr) {
return fo.closeFd(writeErr, fd, written);
}
fo.updateMetadata(fd, file, onUpdate);
...