[Pkg-javascript-commits] [node-gulp-newer] 01/03: Import Upstream version 1.3.0
Paolo Greppi
paolog-guest at moszumanska.debian.org
Sun Dec 25 14:22:45 UTC 2016
This is an automated email from the git hooks/post-receive script.
paolog-guest pushed a commit to branch master
in repository node-gulp-newer.
commit 0c5c46bb25ff52c70e4b2a4fc284fe8129f31ff1
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date: Sun Dec 25 14:16:41 2016 +0000
Import Upstream version 1.3.0
---
.gitignore | 1 +
.travis.yml | 4 +
index.js | 229 ++++++++++++++++++
package.json | 45 ++++
readme.md | 81 +++++++
spec.js | 770 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 1130 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2ccbe46
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/node_modules/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..85b914c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+sudo: false
+language: node_js
+node_js:
+ - "4"
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..3ad16c7
--- /dev/null
+++ b/index.js
@@ -0,0 +1,229 @@
+var Transform = require('stream').Transform;
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+var glob = require('glob');
+
+var Q = require('kew');
+var gutil = require('gulp-util');
+
+var PluginError = gutil.PluginError;
+
+var PLUGIN_NAME = 'gulp-newer';
+
+function Newer(options) {
+ Transform.call(this, {objectMode: true});
+
+ if (!options) {
+ throw new PluginError(PLUGIN_NAME,
+ 'Requires a dest string or options object');
+ }
+
+ if (typeof options === 'string') {
+ options = {dest: options};
+ } else if (options.dest && typeof options.dest !== 'string') {
+ throw new PluginError(PLUGIN_NAME, 'Requires a dest string');
+ }
+
+ if (options.ext && typeof options.ext !== 'string') {
+ throw new PluginError(PLUGIN_NAME, 'Requires ext to be a string');
+ }
+
+ if (options.map && typeof options.map !== 'function') {
+ throw new PluginError(PLUGIN_NAME, 'Requires map to be a function');
+ }
+
+ if (!options.dest && !options.map) {
+ throw new PluginError(PLUGIN_NAME, 'Requires either options.dest or options.map or both');
+ }
+
+ if (options.extra) {
+ if (typeof options.extra === 'string') {
+ options.extra = [options.extra];
+ } else if (!Array.isArray(options.extra)) {
+ throw new PluginError(PLUGIN_NAME, 'Requires options.extra to be a string or array');
+ }
+ }
+
+ /**
+ * Path to destination directory or file.
+ * @type {string}
+ */
+ this._dest = options.dest;
+
+ /**
+ * Optional extension for destination files.
+ * @type {string}
+ */
+ this._ext = options.ext;
+
+ /**
+ * Optional function for mapping relative source files to destination files.
+ * @type {function(string): string}
+ */
+ this._map = options.map;
+
+ /**
+ * Promise for the dest file/directory stats.
+ * @type {[type]}
+ */
+ this._destStats = this._dest ? Q.nfcall(fs.stat, this._dest) : Q.resolve(null);
+
+ /**
+ * If the provided dest is a file, we want to pass through all files if any
+ * one of the source files is newer than the dest. To support this, source
+ * files need to be buffered until a newer file is found. When a newer file
+ * is found, buffered source files are flushed (and the `_all` flag is set).
+ * @type {[type]}
+ */
+ this._bufferedFiles = null;
+
+ /**
+ * Indicates that all files should be passed through. This is set when the
+ * provided dest is a file and we have already encountered a newer source
+ * file. When true, all remaining source files should be passed through.
+ * @type {boolean}
+ */
+ this._all = false;
+
+ /**
+ * Indicates that there are extra files (configuration files, etc.)
+ * that are not to be fed into the stream, but that should force
+ * all files to be rebuilt if *any* are older than one of the extra
+ * files.
+ */
+ this._extraStats = null;
+
+ if (options.extra) {
+ var extraFiles = [];
+ for (var i = 0; i < options.extra.length; ++i) {
+ extraFiles.push(Q.nfcall(glob, options.extra[i]));
+ }
+ this._extraStats = Q.all(extraFiles)
+ .then(function(fileArrays) {
+ // First collect all the files in all the glob result arrays
+ var allFiles = [];
+ var i;
+ for (i = 0; i < fileArrays.length; ++i) {
+ allFiles = allFiles.concat(fileArrays[i]);
+ }
+ var extraStats = [];
+ for (i = 0; i < allFiles.length; ++i) {
+ extraStats.push(Q.nfcall(fs.stat, allFiles[i]));
+ }
+ return Q.all(extraStats);
+ })
+ .then(function(resolvedStats) {
+ // We get all the file stats here; find the *latest* modification.
+ var latestStat = resolvedStats[0];
+ for (var j = 1; j < resolvedStats.length; ++j) {
+ if (resolvedStats[j].mtime > latestStat.mtime) {
+ latestStat = resolvedStats[j];
+ }
+ }
+ return latestStat;
+ })
+ .fail(function(error) {
+ if (error && error.path) {
+ throw new PluginError(PLUGIN_NAME, 'Failed to read stats for an extra file: ' + error.path);
+ } else {
+ throw new PluginError(PLUGIN_NAME, 'Failed to stat extra files; unknown error: ' + error);
+ }
+ });
+ }
+
+}
+util.inherits(Newer, Transform);
+
+
+/**
+ * Pass through newer files only.
+ * @param {File} srcFile A vinyl file.
+ * @param {string} encoding Encoding (ignored).
+ * @param {function(Error, File)} done Callback.
+ */
+Newer.prototype._transform = function(srcFile, encoding, done) {
+ if (!srcFile || !srcFile.stat) {
+ done(new PluginError(PLUGIN_NAME, 'Expected a source file with stats'));
+ return;
+ }
+ var self = this;
+ Q.resolve([this._destStats, this._extraStats])
+ .spread(function(destStats, extraStats) {
+ if ((destStats && destStats.isDirectory()) || self._ext || self._map) {
+ // stat dest/relative file
+ var relative = srcFile.relative;
+ var ext = path.extname(relative);
+ var destFileRelative = self._ext ?
+ relative.substr(0, relative.length - ext.length) + self._ext :
+ relative;
+ if (self._map) {
+ destFileRelative = self._map(destFileRelative);
+ }
+ var destFileJoined = self._dest ?
+ path.join(self._dest, destFileRelative) : destFileRelative;
+ return Q.all([Q.nfcall(fs.stat, destFileJoined), extraStats]);
+ } else {
+ // wait to see if any are newer, then pass through all
+ if (!self._bufferedFiles) {
+ self._bufferedFiles = [];
+ }
+ return [destStats, extraStats];
+ }
+ }).fail(function(err) {
+ if (err.code === 'ENOENT') {
+ // dest file or directory doesn't exist, pass through all
+ return Q.resolve([null, this._extraStats]);
+ } else {
+ // unexpected error
+ return Q.reject(err);
+ }
+ }).spread(function(destFileStats, extraFileStats) {
+ var newer = !destFileStats || srcFile.stat.mtime > destFileStats.mtime;
+ // If *any* extra file is newer than a destination file, then ALL
+ // are newer.
+ if (extraFileStats && extraFileStats.mtime > destFileStats.mtime) {
+ newer = true;
+ }
+ if (self._all) {
+ self.push(srcFile);
+ } else if (!newer) {
+ if (self._bufferedFiles) {
+ self._bufferedFiles.push(srcFile);
+ }
+ } else {
+ if (self._bufferedFiles) {
+ // flush buffer
+ self._bufferedFiles.forEach(function(file) {
+ self.push(file);
+ });
+ self._bufferedFiles.length = 0;
+ // pass through all remaining files as well
+ self._all = true;
+ }
+ self.push(srcFile);
+ }
+ done();
+ }).fail(done).end();
+
+};
+
+
+/**
+ * Remove references to buffered files.
+ * @param {function(Error)} done Callback.
+ */
+Newer.prototype._flush = function(done) {
+ this._bufferedFiles = null;
+ done();
+};
+
+
+/**
+ * Only pass through source files that are newer than the provided destination.
+ * @param {Object} options An options object or path to destination.
+ * @return {Newer} A transform stream.
+ */
+module.exports = function(options) {
+ return new Newer(options);
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..bff8f85
--- /dev/null
+++ b/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "gulp-newer",
+ "version": "1.3.0",
+ "description": "Only pass through newer source files",
+ "homepage": "https://github.com/tschaub/gulp-newer",
+ "author": {
+ "name": "Tim Schaub",
+ "url": "http://tschaub.net/"
+ },
+ "keywords": [
+ "gulp",
+ "gulpplugin",
+ "newer",
+ "mtime"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/tschaub/gulp-newer.git"
+ },
+ "bugs": {
+ "url": "https://github.com/tschaub/gulp-newer/issues"
+ },
+ "license": "MIT",
+ "main": "index.js",
+ "scripts": {
+ "pretest": "eslint index.js spec.js",
+ "test": "mocha spec.js"
+ },
+ "devDependencies": {
+ "chai": "^3.5.0",
+ "eslint": "^3.7.1",
+ "eslint-config-tschaub": "^6.0.0",
+ "gulp": "^3.9.1",
+ "mocha": "^3.1.0",
+ "mock-fs": "^3.11.0"
+ },
+ "dependencies": {
+ "glob": "^7.0.3",
+ "gulp-util": "^3.0.7",
+ "kew": "^0.7.0"
+ },
+ "eslintConfig": {
+ "extends": "tschaub"
+ }
+}
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..015a79d
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,81 @@
+# `gulp-newer`
+
+A [Gulp](http://gulpjs.com/) plugin for passing through only those source files that are newer than corresponding destination files.
+
+## Install
+
+```
+npm install gulp-newer --save-dev
+```
+
+## Example
+
+### Using `newer` with 1:1 source:dest mappings
+
+The default task in the example below sets up a watch that minifies images on changes. Piping the source files to `newer` before `imagemin` ensures that only those images that have changed are minified. The `newer` plugin is configured with the directory path for minified images.
+
+```js
+var gulp = require('gulp');
+var newer = require('gulp-newer');
+var imagemin = require('gulp-imagemin');
+
+var imgSrc = 'src/img/**';
+var imgDest = 'build/img';
+
+// Minify any new images
+gulp.task('images', function() {
+
+ // Add the newer pipe to pass through newer images only
+ return gulp.src(imgSrc)
+ .pipe(newer(imgDest))
+ .pipe(imagemin())
+ .pipe(gulp.dest(imgDest));
+
+});
+
+gulp.task('default', function() {
+ gulp.watch(imgSrc, ['images']);
+});
+```
+
+### Using `newer` with many:1 source:dest mappings
+
+Plugins like `gulp-concat` take many source files and generate a single destination file. In this case, the `newer` stream will pass through *all* source files if *any one* of them is newer than the destination file. The `newer` plugin is configured with the destination file path.
+
+```js
+var gulp = require('gulp');
+var newer = require('gulp-newer');
+var concat = require('gulp-concat');
+
+// Concatenate all if any are newer
+gulp.task('concat', function() {
+
+ // Add the newer pipe to pass through all sources if any are newer
+ return gulp.src('lib/*.js')
+ .pipe(newer('dist/all.js'))
+ .pipe(concat('all.js'))
+ .pipe(gulp.dest('dist'));
+
+});
+```
+
+
+## API
+
+### `newer(dest)`
+* **dest** - `string` Path to destination directory or file.
+
+### `newer(options)`
+
+ * **options.dest** - `string` As above, *required*.
+ * **options.ext** - `string` Source files will be matched to destination files with the provided extension (e.g. '.css').
+ * **options.map** - `function` Map relative source paths to relative destination paths (e.g. `function(relativePath) { return relativePath + '.bak'; }`)
+ * **options.extra** - `string` or `array` An extra file, file glob, or list of extra files and/or globs, to check for updated time stamp(s). If any of these files are newer than the destination files, then all source files will be passed into the stream.
+
+Create a [transform stream](http://nodejs.org/api/stream.html#stream_class_stream_transform_1) that passes through files whose modification time is more recent than the corresponding destination file's modification time.
+
+If `dest` is a directory path, the `newer` stream will check for files in the destination directory with the same relative path as source files. Source files that have been modified more recently than the resolved destination file will be passed through. If the `dest` directory or resolved destination file does not exist, all source files will be passed through.
+
+If `dest` is a file path, the `newer` stream will pass through *all* files if *any one* of them has been modified more recently than the destination file. If the `dest` file does not exist, all source files will be passed through.
+
+[![Current Status](https://secure.travis-ci.org/tschaub/gulp-newer.png?branch=master)](https://travis-ci.org/tschaub/gulp-newer)
diff --git a/spec.js b/spec.js
new file mode 100644
index 0000000..69d6f36
--- /dev/null
+++ b/spec.js
@@ -0,0 +1,770 @@
+/* eslint-env mocha */
+
+var Transform = require('stream').Transform;
+var fs = require('fs');
+var path = require('path');
+
+var chai = require('chai');
+var gutil = require('gulp-util');
+var mock = require('mock-fs');
+
+var newer = require('./index.js');
+
+chai.config.includeStack = true;
+
+var File = gutil.File;
+var assert = chai.assert;
+
+/**
+ * Test utility function. Create File instances for each of the provided paths
+ * and write to the provided stream. Call stream.end() when done.
+ * @param {stream.Transform} stream Transform stream.
+ * @param {Array.<string>} paths Array of file paths.
+ */
+function write(stream, paths) {
+ paths.forEach(function(filePath) {
+ stream.write(new File({
+ contents: fs.readFileSync(filePath),
+ path: path.resolve(filePath),
+ stat: fs.statSync(filePath)
+ }));
+ });
+ stream.end();
+}
+
+describe('newer()', function() {
+
+ it('creates a transform stream', function() {
+ var stream = newer('foo');
+ assert.instanceOf(stream, Transform);
+ });
+
+ it('requires a string dest or an object with the dest property', function() {
+
+ assert.throws(function() {
+ newer();
+ });
+
+ assert.throws(function() {
+ newer(123);
+ });
+
+ assert.throws(function() {
+ newer({});
+ });
+ });
+
+ describe('config.ext', function() {
+
+ it('must be a string', function() {
+
+ assert.throws(function() {
+ newer({dest: 'foo', ext: 1});
+ });
+
+ assert.throws(function() {
+ newer({dest: 'foo', ext: {}});
+ });
+ });
+ });
+
+ describe('config.map', function() {
+
+ it('must be a function', function() {
+ assert.throws(function() {
+ newer({dest: 'foo', map: 1});
+ });
+
+ assert.throws(function() {
+ newer({dest: 'foo', map: 'bar'});
+ });
+ });
+
+ it('makes the dest config optional', function() {
+ assert.doesNotThrow(function() {
+ newer({map: function() {}});
+ });
+ });
+
+ });
+
+ describe('config.extra', function() {
+
+ beforeEach(function() {
+ mock({
+ main: mock.file({
+ content: 'main content',
+ mtime: new Date(1)
+ }),
+ imported: mock.file({
+ content: '2: other content, used by main',
+ mtime: new Date(3)
+ }),
+ collected: mock.file({
+ content: 'main content\n1: other content, used by main',
+ mtime: new Date(2)
+ })
+ });
+ });
+ afterEach(mock.restore);
+
+ it('must be a string or an array', function() {
+ assert.throws(function() {
+ newer({dest: 'foo', extra: 1});
+ });
+
+ assert.throws(function() {
+ newer({dest: 'foo', extra: function() {}});
+ });
+
+ assert.doesNotThrow(function() {
+ newer({dest: 'foo', extra: 'extra1'});
+ });
+
+ assert.doesNotThrow(function() {
+ newer({dest: 'foo', extra: ['extra1', 'extra2']});
+ });
+ });
+
+ it('must not be passed into stream', function(done) {
+ var stream = newer({dest: 'collected', extra: 'imported'});
+
+ var paths = ['main'];
+
+ stream.on('data', function(file) {
+ assert.notEqual(file.path, path.resolve('imported'));
+ });
+ stream.on('error', done);
+ stream.on('end', done);
+
+ write(stream, paths);
+ });
+
+ it('must let other files through stream if an "extra" is newer', function(done) {
+ var stream = newer({dest: 'collected', extra: 'imported'});
+
+ var paths = ['main'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest dir that does not exist', function() {
+
+ beforeEach(function() {
+ mock({
+ source1: 'source1 content',
+ source2: 'source2 content',
+ source3: 'source3 content'
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all files', function(done) {
+ var stream = newer('new/dir');
+
+ var paths = ['source1', 'source2', 'source3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file that does not exist', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: 'file1 content',
+ file2: 'file2 content',
+ file3: 'file3 content',
+ dest: {}
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all files', function(done) {
+ var stream = newer('dest/concat');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('empty dest dir', function() {
+
+ beforeEach(function() {
+ mock({
+ source1: 'source1 content',
+ source2: 'source2 content',
+ source3: 'source3 content',
+ dest: {}
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all files', function(done) {
+ var stream = newer('dest');
+
+ var paths = ['source1', 'source2', 'source3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest dir with one older file', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: 'file1 content',
+ file2: 'file2 content',
+ file3: 'file3 content',
+ dest: {
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(1)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all files', function(done) {
+ var stream = newer('dest');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest dir with one newer file', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(200)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through two newer files', function(done) {
+ var stream = newer('dest');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.notEqual(file.path, path.resolve('file2'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length - 1);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest dir with two newer and one older file', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(150)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(50)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(150)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through one newer file', function(done) {
+ var stream = newer('dest');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve('file2'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, 1);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file with first source file newer', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(200)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ output: mock.file({
+ content: 'file2 content',
+ mtime: new Date(150)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all source files', function(done) {
+ var stream = newer('dest/output');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file with second source file newer', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(200)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ output: mock.file({
+ content: 'file2 content',
+ mtime: new Date(150)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all source files', function(done) {
+ var stream = newer('dest/output');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file with last source file newer', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(200)
+ }),
+ dest: {
+ output: mock.file({
+ content: 'file2 content',
+ mtime: new Date(150)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through all source files', function(done) {
+ var stream = newer('dest/output');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve(paths[calls]));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, paths.length);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file with no newer source files', function() {
+
+ beforeEach(function() {
+ mock({
+ file1: mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ file2: mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ file3: mock.file({
+ content: 'file3 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ output: mock.file({
+ content: 'file2 content',
+ mtime: new Date(150)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through no source files', function(done) {
+ var stream = newer('dest/output');
+
+ var paths = ['file1', 'file2', 'file3'];
+
+ var calls = 0;
+ stream.on('data', function() {
+ done(new Error('Expected no source files'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, 0);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('dest file ext and two files', function() {
+
+ beforeEach(function() {
+ mock({
+ 'file1.ext1': mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ 'file2.ext1': mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ 'file1.ext2': mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ 'file2.ext2': mock.file({
+ content: 'file2 content',
+ mtime: new Date(50)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through one newer file', function(done) {
+ var stream = newer({dest: 'dest', ext: '.ext2'});
+
+ var paths = ['file1.ext1', 'file2.ext1'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve('file2.ext1'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, 1);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('custom mapping between source and dest', function() {
+
+ beforeEach(function() {
+ mock({
+ 'file1.ext1': mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ 'file2.ext1': mock.file({
+ content: 'file2 content',
+ mtime: new Date(100)
+ }),
+ dest: {
+ 'file1.ext2': mock.file({
+ content: 'file1 content',
+ mtime: new Date(100)
+ }),
+ 'file2.ext2': mock.file({
+ content: 'file2 content',
+ mtime: new Date(50)
+ })
+ }
+ });
+ });
+ afterEach(mock.restore);
+
+ it('passes through one newer file', function(done) {
+ var stream = newer({
+ dest: 'dest',
+ map: function(destPath) {
+ return destPath.replace('.ext1', '.ext2');
+ }
+ });
+
+ var paths = ['file1.ext1', 'file2.ext1'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve('file2.ext1'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, 1);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ it('allows people to join to dest themselves', function(done) {
+ var stream = newer({
+ map: function(destPath) {
+ return path.join('dest', destPath.replace('.ext1', '.ext2'));
+ }
+ });
+
+ var paths = ['file1.ext1', 'file2.ext1'];
+
+ var calls = 0;
+ stream.on('data', function(file) {
+ assert.equal(file.path, path.resolve('file2.ext1'));
+ ++calls;
+ });
+
+ stream.on('error', done);
+
+ stream.on('end', function() {
+ assert.equal(calls, 1);
+ done();
+ });
+
+ write(stream, paths);
+ });
+
+ });
+
+ describe('reports errors', function() {
+ beforeEach(function() {
+ mock({
+ 'q': mock.file({
+ mtime: new Date(100)
+ }),
+ dest: {}
+ });
+ });
+ afterEach(mock.restore);
+
+ it('in "data" handlers', function(done) {
+ var stream = newer('dest');
+
+ var err = new Error('test');
+
+ stream.on('data', function() {
+ throw err;
+ });
+
+ stream.on('error', function(caught) {
+ assert.equal(caught, err);
+ done();
+ });
+
+ write(stream, ['q']);
+ });
+
+ });
+
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-gulp-newer.git
More information about the Pkg-javascript-commits
mailing list