source: node_modules/nodemon/lib/monitor/match.js

main
Last change on this file was 81bc7da, checked in by Klimentina Efremova <klimentina08642@…>, 3 months ago

Initial commit

  • Property mode set to 100644
File size: 6.9 KB
RevLine 
[81bc7da]1const { minimatch } = require('minimatch');
2const path = require('path');
3const fs = require('fs');
4const debug = require('debug')('nodemon:match');
5const utils = require('../utils');
6
7module.exports = match;
8module.exports.rulesToMonitor = rulesToMonitor;
9
10function rulesToMonitor(watch, ignore, config) {
11 var monitor = [];
12
13 if (!Array.isArray(ignore)) {
14 if (ignore) {
15 ignore = [ignore];
16 } else {
17 ignore = [];
18 }
19 }
20
21 if (!Array.isArray(watch)) {
22 if (watch) {
23 watch = [watch];
24 } else {
25 watch = [];
26 }
27 }
28
29 if (watch && watch.length) {
30 monitor = utils.clone(watch);
31 }
32
33 if (ignore) {
34 [].push.apply(
35 monitor,
36 (ignore || []).map(function (rule) {
37 return '!' + rule;
38 })
39 );
40 }
41
42 var cwd = process.cwd();
43
44 // next check if the monitored paths are actual directories
45 // or just patterns - and expand the rule to include *.*
46 monitor = monitor.map(function (rule) {
47 var not = rule.slice(0, 1) === '!';
48
49 if (not) {
50 rule = rule.slice(1);
51 }
52
53 if (rule === '.' || rule === '.*') {
54 rule = '*.*';
55 }
56
57 var dir = path.resolve(cwd, rule);
58
59 try {
60 var stat = fs.statSync(dir);
61 if (stat.isDirectory()) {
62 rule = dir;
63 if (rule.slice(-1) !== '/') {
64 rule += '/';
65 }
66 rule += '**/*';
67
68 // `!not` ... sorry.
69 if (!not) {
70 config.dirs.push(dir);
71 }
72 } else {
73 // ensures we end up in the check that tries to get a base directory
74 // and then adds it to the watch list
75 throw new Error();
76 }
77 } catch (e) {
78 var base = tryBaseDir(dir);
79 if (!not && base) {
80 if (config.dirs.indexOf(base) === -1) {
81 config.dirs.push(base);
82 }
83 }
84 }
85
86 if (rule.slice(-1) === '/') {
87 // just slap on a * anyway
88 rule += '*';
89 }
90
91 // if the url ends with * but not **/* and not *.*
92 // then convert to **/* - somehow it was missed :-\
93 if (
94 rule.slice(-4) !== '**/*' &&
95 rule.slice(-1) === '*' &&
96 rule.indexOf('*.') === -1
97 ) {
98 if (rule.slice(-2) !== '**') {
99 rule += '*/*';
100 }
101 }
102
103 return (not ? '!' : '') + rule;
104 });
105
106 return monitor;
107}
108
109function tryBaseDir(dir) {
110 var stat;
111 if (/[?*\{\[]+/.test(dir)) {
112 // if this is pattern, then try to find the base
113 try {
114 var base = path.dirname(dir.replace(/([?*\{\[]+.*$)/, 'foo'));
115 stat = fs.statSync(base);
116 if (stat.isDirectory()) {
117 return base;
118 }
119 } catch (error) {
120 // console.log(error);
121 }
122 } else {
123 try {
124 stat = fs.statSync(dir);
125 // if this path is actually a single file that exists, then just monitor
126 // that, *specifically*.
127 if (stat.isFile() || stat.isDirectory()) {
128 return dir;
129 }
130 } catch (e) { }
131 }
132
133 return false;
134}
135
136function match(files, monitor, ext) {
137 // sort the rules by highest specificity (based on number of slashes)
138 // ignore rules (!) get sorted highest as they take precedent
139 const cwd = process.cwd();
140 var rules = monitor
141 .sort(function (a, b) {
142 var r = b.split(path.sep).length - a.split(path.sep).length;
143 var aIsIgnore = a.slice(0, 1) === '!';
144 var bIsIgnore = b.slice(0, 1) === '!';
145
146 if (aIsIgnore || bIsIgnore) {
147 if (aIsIgnore) {
148 return -1;
149 }
150
151 return 1;
152 }
153
154 if (r === 0) {
155 return b.length - a.length;
156 }
157 return r;
158 })
159 .map(function (s) {
160 var prefix = s.slice(0, 1);
161
162 if (prefix === '!') {
163 if (s.indexOf('!' + cwd) === 0) {
164 return s;
165 }
166
167 // if it starts with a period, then let's get the relative path
168 if (s.indexOf('!.') === 0) {
169 return '!' + path.resolve(cwd, s.substring(1));
170 }
171
172 return '!**' + (prefix !== path.sep ? path.sep : '') + s.slice(1);
173 }
174
175 // if it starts with a period, then let's get the relative path
176 if (s.indexOf('.') === 0) {
177 return path.resolve(cwd, s);
178 }
179
180 if (s.indexOf(cwd) === 0) {
181 return s;
182 }
183
184 return '**' + (prefix !== path.sep ? path.sep : '') + s;
185 });
186
187 debug('rules', rules);
188
189 var good = [];
190 var whitelist = []; // files that we won't check against the extension
191 var ignored = 0;
192 var watched = 0;
193 var usedRules = [];
194 var minimatchOpts = {
195 dot: true,
196 };
197
198 // enable case-insensitivity on Windows
199 if (utils.isWindows) {
200 minimatchOpts.nocase = true;
201 minimatchOpts.windowsPathsNoEscape = true;
202 }
203
204 files.forEach(function (file) {
205 file = path.resolve(cwd, file);
206
207 var matched = false;
208 for (var i = 0; i < rules.length; i++) {
209 if (rules[i].slice(0, 1) === '!') {
210 if (!minimatch(file, rules[i], minimatchOpts)) {
211 debug('ignored', file, 'rule:', rules[i]);
212 ignored++;
213 matched = true;
214 break;
215 }
216 } else {
217 debug('matched', file, 'rule:', rules[i]);
218 if (minimatch(file, rules[i], minimatchOpts)) {
219 watched++;
220
221 // don't repeat the output if a rule is matched
222 if (usedRules.indexOf(rules[i]) === -1) {
223 usedRules.push(rules[i]);
224 utils.log.detail('matched rule: ' + rules[i]);
225 }
226
227 // if the rule doesn't match the WATCH EVERYTHING
228 // but *does* match a rule that ends with *.*, then
229 // white list it - in that we don't run it through
230 // the extension check too.
231 if (
232 rules[i] !== '**' + path.sep + '*.*' &&
233 rules[i].slice(-3) === '*.*'
234 ) {
235 whitelist.push(file);
236 } else if (path.basename(file) === path.basename(rules[i])) {
237 // if the file matches the actual rule, then it's put on whitelist
238 whitelist.push(file);
239 } else {
240 good.push(file);
241 }
242 matched = true;
243 } else {
244 // utils.log.detail('no match: ' + rules[i], file);
245 }
246 }
247 }
248 if (!matched) {
249 ignored++;
250 }
251 });
252
253 // finally check the good files against the extensions that we're monitoring
254 if (ext) {
255 if (ext.indexOf(',') === -1) {
256 ext = '**/*.' + ext;
257 } else {
258 ext = '**/*.{' + ext + '}';
259 }
260
261 good = good.filter(function (file) {
262 // only compare the filename to the extension test
263 return minimatch(path.basename(file), ext, minimatchOpts);
264 });
265 debug('good (filtered by ext)', good);
266 } else {
267 // else assume *.*
268 debug('good', good);
269 }
270
271 if (whitelist.length) debug('whitelist', whitelist);
272
273 var result = good.concat(whitelist);
274
275 if (utils.isWindows) {
276 // fix for windows testing - I *think* this is okay to do
277 result = result.map(function (file) {
278 return file.slice(0, 1).toLowerCase() + file.slice(1);
279 });
280 }
281
282 return {
283 result: result,
284 ignored: ignored,
285 watched: watched,
286 total: files.length,
287 };
288}
Note: See TracBrowser for help on using the repository browser.