opusdev/vector-similarity-api
1
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 directories45 // 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 directory74 // and then adds it to the watch list75 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 * anyway88 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('*.') === -197 ) {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 base113 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 monitor126 // 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 precedent139 const cwd = process.cwd();140 var rules = monitor141 .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 path168 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 path176 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 extension191 var ignored = 0;192 var watched = 0;193 var usedRules = [];194 var minimatchOpts = {195 dot: true,196 };197 198 // enable case-insensitivity on Windows199 if (utils.isWindows) {200 minimatchOpts.nocase = true;201 }202 203 files.forEach(function (file) {204 file = path.resolve(cwd, file);205 206 var matched = false;207 for (var i = 0; i < rules.length; i++) {208 if (rules[i].slice(0, 1) === '!') {209 if (!minimatch(file, rules[i], minimatchOpts)) {210 debug('ignored', file, 'rule:', rules[i]);211 ignored++;212 matched = true;213 break;214 }215 } else {216 debug('matched', file, 'rule:', rules[i]);217 if (minimatch(file, rules[i], minimatchOpts)) {218 watched++;219 220 // don't repeat the output if a rule is matched221 if (usedRules.indexOf(rules[i]) === -1) {222 usedRules.push(rules[i]);223 utils.log.detail('matched rule: ' + rules[i]);224 }225 226 // if the rule doesn't match the WATCH EVERYTHING227 // but *does* match a rule that ends with *.*, then228 // white list it - in that we don't run it through229 // the extension check too.230 if (231 rules[i] !== '**' + path.sep + '*.*' &&232 rules[i].slice(-3) === '*.*'233 ) {234 whitelist.push(file);235 } else if (path.basename(file) === path.basename(rules[i])) {236 // if the file matches the actual rule, then it's put on whitelist237 whitelist.push(file);238 } else {239 good.push(file);240 }241 matched = true;242 } else {243 // utils.log.detail('no match: ' + rules[i], file);244 }245 }246 }247 if (!matched) {248 ignored++;249 }250 });251 252 // finally check the good files against the extensions that we're monitoring253 if (ext) {254 if (ext.indexOf(',') === -1) {255 ext = '**/*.' + ext;256 } else {257 ext = '**/*.{' + ext + '}';258 }259 260 good = good.filter(function (file) {261 // only compare the filename to the extension test262 return minimatch(path.basename(file), ext, minimatchOpts);263 });264 debug('good (filtered by ext)', good);265 } else {266 // else assume *.*267 debug('good', good);268 }269 270 if (whitelist.length) debug('whitelist', whitelist);271 272 var result = good.concat(whitelist);273 274 if (utils.isWindows) {275 // fix for windows testing - I *think* this is okay to do276 result = result.map(function (file) {277 return file.slice(0, 1).toLowerCase() + file.slice(1);278 });279 }280 281 return {282 result: result,283 ignored: ignored,284 watched: watched,285 total: files.length,286 };287}288 