Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have nonull: true cause the task to warn and abort. #106

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ module.exports = function(grunt) {
'tmp/custom_options': ['test/fixtures/file1', 'test/fixtures/file2']
}
},
handling_invalid_files: {
src: ['test/fixtures/file1', 'invalid_file/should_warn/but_not_fail', 'test/fixtures/file2'],
dest: 'tmp/handling_invalid_files',
nonull: true
},
process_function: {
options: {
process: function(src, filepath) {
Expand Down Expand Up @@ -160,6 +155,31 @@ module.exports = function(grunt) {

});

// Encapsulates tasks which invoke `grunt.fail.warn` and should abort.
grunt.registerTask('concat-warn', function() {
grunt.config('concat', {
handling_invalid_files: {
src: ['test/fixtures/file1', 'invalid_file/should_warn/and_abort', 'test/fixtures/file2'],
dest: 'tmp/handling_invalid_files',
nonull: true
}
});
grunt.task.run(['concat']);
});

// Encapsulates tasks which invoke `grunt.fail.warn` and should abort, but the
// test is checking behavior in the case of a user-specified `--force` flag.
grunt.registerTask('concat-force', function() {
grunt.config('concat', {
handling_invalid_files_force: {
src: ['test/fixtures/file1', 'invalid_file/should_warn/but_not_fail', 'test/fixtures/file2'],
dest: 'tmp/handling_invalid_files_force',
nonull: true
}
});
grunt.task.run(['concat']);
});

// Actually load this plugin's task(s).
grunt.loadTasks('tasks');

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ grunt.initConfig({
```

#### Invalid or Missing Files Warning
If you would like the `concat` task to warn if a given file is missing or invalid be sure to set `nonull` to `true`:
If you would like the `concat` task to warn and abort if a given file is missing or invalid be sure to set `nonull` to `true`:

```js
grunt.initConfig({
Expand All @@ -249,6 +249,8 @@ grunt.initConfig({
});
```

Additionally invoke grunt with `--force` to skip over missing files.

See [configuring files for a task](http://gruntjs.com/configuring-tasks#files) for how to configure file globbing in Grunt.


Expand Down Expand Up @@ -298,4 +300,4 @@ grunt.initConfig({

Task submitted by ["Cowboy" Ben Alman](http://benalman.com/)

*This file was generated on Wed Apr 20 2016 08:41:44.*
*This file was generated on Sun Jun 05 2016 08:36:20.*
4 changes: 3 additions & 1 deletion docs/concat-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ grunt.initConfig({
```

## Invalid or Missing Files Warning
If you would like the `concat` task to warn if a given file is missing or invalid be sure to set `nonull` to `true`:
If you would like the `concat` task to warn and abort if a given file is missing or invalid be sure to set `nonull` to `true`:

```js
grunt.initConfig({
Expand All @@ -150,6 +150,8 @@ grunt.initConfig({
});
```

Additionally invoke grunt with `--force` to skip over missing files.

See [configuring files for a task](http://gruntjs.com/configuring-tasks#files) for how to configure file globbing in Grunt.


Expand Down
120 changes: 69 additions & 51 deletions tasks/concat.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,62 +60,80 @@ module.exports = function(grunt) {
sourceMap = false;
}

// Iterate over all src-dest file pairs.
this.files.forEach(function(f) {
// Initialize source map objects.
var sourceMapHelper;
if (sourceMap) {
sourceMapHelper = sourcemap.helper(f, options);
sourceMapHelper.add(banner);
}

// Concat banner + specified files + footer.
var src = banner + f.src.filter(function(filepath) {
// Warn on and remove invalid source files (if nonull was set).
if (!grunt.file.exists(filepath)) {
grunt.log.warn('Source file "' + filepath + '" not found.');
return false;
}
return true;
}).map(function(filepath, i) {
if (grunt.file.isDir(filepath)) {
return;
}
// Read file source.
var src = grunt.file.read(filepath);
// Process files as templates if requested.
if (typeof options.process === 'function') {
src = options.process(src, filepath);
} else if (options.process) {
src = grunt.template.process(src, options.process);
}
// Strip banners if requested.
if (options.stripBanners) {
src = comment.stripBanner(src, options.stripBanners);
var exitEarly = {};
try {
// Iterate over all src-dest file pairs.
this.files.forEach(function(f) {
// Initialize source map objects.
var sourceMapHelper;
if (sourceMap) {
sourceMapHelper = sourcemap.helper(f, options);
sourceMapHelper.add(banner);
}
// Add the lines of this file to our map.
if (sourceMapHelper) {
src = sourceMapHelper.addlines(src, filepath);
if (i < f.src.length - 1) {
sourceMapHelper.add(options.separator);

// Concat banner + specified files + footer.
var src = banner + f.src.filter(function(filepath) {
// Warn on invalid source files (if nonull was set). They will be
// removed if --force is specified.
if (!grunt.file.exists(filepath)) {
grunt.fail.warn('Source file "' + filepath + '" not found.');
if (!grunt.option('force')) {
// See the catch clause below for why we do this.
throw exitEarly;
}
return false;
}
}
return src;
}).join(options.separator) + footer;
return true;
}).map(function(filepath, i) {
if (grunt.file.isDir(filepath)) {
return;
}
// Read file source.
var src = grunt.file.read(filepath);
// Process files as templates if requested.
if (typeof options.process === 'function') {
src = options.process(src, filepath);
} else if (options.process) {
src = grunt.template.process(src, options.process);
}
// Strip banners if requested.
if (options.stripBanners) {
src = comment.stripBanner(src, options.stripBanners);
}
// Add the lines of this file to our map.
if (sourceMapHelper) {
src = sourceMapHelper.addlines(src, filepath);
if (i < f.src.length - 1) {
sourceMapHelper.add(options.separator);
}
}
return src;
}).join(options.separator) + footer;

if (sourceMapHelper) {
sourceMapHelper.add(footer);
sourceMapHelper.write();
// Add sourceMappingURL to the end.
src += sourceMapHelper.url();
}
if (sourceMapHelper) {
sourceMapHelper.add(footer);
sourceMapHelper.write();
// Add sourceMappingURL to the end.
src += sourceMapHelper.url();
}

// Write the destination file.
grunt.file.write(f.dest, src);
// Write the destination file.
grunt.file.write(f.dest, src);

// Print a success message.
grunt.verbose.write('File ' + chalk.cyan(f.dest) + ' created.');
});
// Print a success message.
grunt.verbose.write('File ' + chalk.cyan(f.dest) + ' created.');
});
} catch (reason) {
if (reason === exitEarly) {
// grunt.fail.warn uses the "exit" library, which doesn't stop the
// process synchronously on Node.js 0.10 on Windows, which could result
// in files still being concatenated even when some are missing. See:
// https://github.com/nodejs/node-v0.x-archive/issues/3584#issuecomment-8034529
// Therefore, we throw a unique reference to emulate exiting early.
return;
}
throw reason;
}
});

};
32 changes: 27 additions & 5 deletions test/concat_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

var grunt = require('grunt');
var comment = require('../tasks/lib/comment').init(grunt);
var exec = require('child_process').exec;
var path = require('path');
var fs = require('fs');

var execOptions = {cwd: path.join(__dirname, '..')};

function getNormalizedFile(filepath) {
return grunt.util.normalizelf(grunt.file.read(filepath));
Expand All @@ -27,13 +32,30 @@ exports.concat = {
test.done();
},
handling_invalid_files: function(test) {
test.expect(1);
test.expect(3);

var actual = getNormalizedFile('tmp/handling_invalid_files');
var expected = getNormalizedFile('test/expected/handling_invalid_files');
test.equal(actual, expected, 'will have warned, but should not fail.');
exec('grunt concat-warn', execOptions, function(error, stdout) {
test.ok(stdout.indexOf('Warning:') > -1, 'should print a warning.');
test.ok(stdout.indexOf('Aborted due to warnings.') > -1, 'should abort.');

test.done();
fs.exists('tmp/handling_invalid_files', function(exists) {
test.ok(!exists, 'should not have created a file.');
test.done();
});
});
},
handling_invalid_files_force: function(test) {
test.expect(2);

exec('grunt concat-force --force', execOptions, function(error, stdout) {
test.ok(stdout.indexOf('Warning:') > -1, 'should print a warning.');

var actual = getNormalizedFile('tmp/handling_invalid_files_force');
var expected = getNormalizedFile('test/expected/handling_invalid_files_force');
test.equal(actual, expected, 'should not fail.');

test.done();
});
},
strip_banner: function(test) {
test.expect(10);
Expand Down