Initial commit
[yaffs-website] / node_modules / grunt-contrib-watch / tasks / watch.js
1 /*
2  * grunt-contrib-watch
3  * http://gruntjs.com/
4  *
5  * Copyright (c) 2016 "Cowboy" Ben Alman, contributors
6  * Licensed under the MIT license.
7  */
8
9 'use strict';
10
11 var path = require('path');
12 var Gaze = require('gaze').Gaze;
13 var _ = require('lodash');
14 var waiting = 'Waiting...';
15 var changedFiles = Object.create(null);
16 var watchers = [];
17
18 module.exports = function(grunt) {
19
20   var taskrun = require('./lib/taskrunner')(grunt);
21
22   // Default date format logged
23   var dateFormat = function(time) {
24     grunt.log.writeln(String(
25       'Completed in ' +
26       time.toFixed(3) +
27       's at ' +
28       (new Date()).toString()
29     ).cyan + ' - ' + waiting);
30   };
31
32   // When task runner has started
33   taskrun.on('start', function() {
34     Object.keys(changedFiles).forEach(function(filepath) {
35       // Log which file has changed, and how.
36       grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.');
37     });
38     // Reset changedFiles
39     changedFiles = Object.create(null);
40   });
41
42   // When task runner has ended
43   taskrun.on('end', function(time) {
44     if (time > 0) {
45       dateFormat(time);
46     }
47   });
48
49   // When a task run has been interrupted
50   taskrun.on('interrupt', function() {
51     grunt.log.writeln('').write('Scheduled tasks have been interrupted...'.yellow);
52   });
53
54   // When taskrun is reloaded
55   taskrun.on('reload', function() {
56     taskrun.clearRequireCache(Object.keys(changedFiles));
57     grunt.log.writeln('').writeln('Reloading watch config...'.cyan);
58   });
59
60   grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) {
61     var self = this;
62     var name = self.name || 'watch';
63
64     // Close any previously opened watchers
65     watchers.forEach(function(watcher) {
66       watcher.close();
67     });
68     watchers = [];
69
70     // Never gonna give you up, never gonna let you down
71     if (grunt.config([name, 'options', 'forever']) !== false) {
72       taskrun.forever();
73     }
74
75     // If a custom dateFormat function
76     var df = grunt.config([name, 'options', 'dateFormat']);
77     if (typeof df === 'function') {
78       dateFormat = df;
79     }
80
81     if (taskrun.running === false) {
82       grunt.log.writeln(waiting);
83     }
84
85     // Initialize taskrun
86     var targets = taskrun.init(name, {target: target});
87
88     targets.forEach(function(target) {
89       if (typeof target.files === 'string') {
90         target.files = [target.files];
91       }
92
93       // Process into raw patterns
94       var patterns = _.chain(target.files).flatten().map(function(pattern) {
95         return grunt.config.process(pattern);
96       }).value();
97
98       // Validate the event option
99       if (typeof target.options.event === 'string') {
100         target.options.event = [target.options.event];
101       }
102
103       var eventCwd = process.cwd();
104       if (target.options.cwd && target.options.cwd.event) {
105         eventCwd = target.options.cwd.event;
106       }
107
108       // Set cwd if options.cwd.file is set
109       if (typeof target.options.cwd !== 'string' && target.options.cwd.files) {
110         target.options.cwd = target.options.cwd.files;
111       }
112
113       // Create watcher per target
114       watchers.push(new Gaze(patterns, target.options, function(err) {
115         if (err) {
116           if (typeof err === 'string') {
117             err = new Error(err);
118           }
119           grunt.log.writeln('ERROR'.red);
120           grunt.fatal(err);
121           return taskrun.done();
122         }
123
124         // Log all watched files with --verbose set
125         if (grunt.option('verbose')) {
126           var watched = this.watched();
127           Object.keys(watched).forEach(function(watchedDir) {
128             watched[watchedDir].forEach(function(watchedFile) {
129               grunt.log.writeln('Watching ' + path.relative(process.cwd(), watchedFile) + ' for changes.');
130             });
131           });
132         }
133
134         // On changed/added/deleted
135         this.on('all', function(status, filepath) {
136
137           // Skip events not specified
138           if (!_.contains(target.options.event, 'all') &&
139               !_.contains(target.options.event, status)) {
140             return;
141           }
142
143           filepath = path.relative(eventCwd, filepath);
144
145           // Skip empty filepaths
146           if (filepath === '') {
147             return;
148           }
149
150           // If Gruntfile.js changed, reload self task
151           if (target.options.reload || /gruntfile\.(js|coffee)/i.test(filepath)) {
152             taskrun.reload = true;
153           }
154
155           // Emit watch events if anyone is listening
156           if (grunt.event.listeners('watch').length > 0) {
157             grunt.event.emit('watch', status, filepath, target.name);
158           }
159
160           // Group changed files only for display
161           changedFiles[filepath] = status;
162
163           // Add changed files to the target
164           if (taskrun.targets[target.name]) {
165             if (!taskrun.targets[target.name].changedFiles) {
166               taskrun.targets[target.name].changedFiles = Object.create(null);
167             }
168             taskrun.targets[target.name].changedFiles[filepath] = status;
169           }
170
171           // Queue the target
172           if (taskrun.queue.indexOf(target.name) === -1) {
173             taskrun.queue.push(target.name);
174           }
175
176           // Run the tasks
177           taskrun.run();
178         });
179
180         // On watcher error
181         this.on('error', function(err) {
182           if (typeof err === 'string') {
183             err = new Error(err);
184           }
185           grunt.log.error(err.message);
186         });
187       }));
188     });
189
190   });
191 };