Code coverage report for lib/monitor/match.js

Statements: 41.33% (31 / 75)      Branches: 35.59% (21 / 59)      Functions: 37.5% (3 / 8)      Lines: 41.33% (31 / 75)     

All files » lib/monitor/ » match.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 1681   1         1 1   1 3   3               3               3 3     3 3 6       3       3 9   9 6     9   9 9 2 2 2   2           2           9             9             9     3     1                                                                                                                                                          
'use strict';
 
var minimatch = require('minimatch'),
    path = require('path'),
    fs = require('fs'),
    utils = require('../utils');
 
module.exports = match;
module.exports.rulesToMonitor = rulesToMonitor;
 
function rulesToMonitor(watch, ignore, config) {
  var monitor = [];
 
  Iif (!Array.isArray(ignore)) {
    if (ignore) {
      ignore = [ignore];
    } else {
      ignore = [];
    }
  }
 
  Iif (!Array.isArray(watch)) {
    if (watch) {
      watch = [watch];
    } else {
      watch = [];
    }
  }
 
  Eif (watch && watch.length) {
    monitor = utils.clone(watch);
  }
 
  Eif (ignore) {
    [].push.apply(monitor, (ignore || []).map(function (rule) {
      return '!' + rule;
    }));
  }
 
  var cwd = process.cwd();
 
  // next check if the monitored paths are actual directories
  // or just patterns - and expand the rule to include *.*
  monitor = monitor.map(function (rule) {
    var not = rule.slice(0, 1) === '!';
 
    if (not) {
      rule = rule.slice(1);
    }
 
    var dir = path.resolve(cwd, rule);
 
    try {
      var stat = fs.statSync(dir);
      Eif (stat.isDirectory()) {
        Eif (rule.slice(-1) !== '/') {
          rule += '/';
        }
        rule += '**/*';
 
        // only needed for mac, because on mac we use `find` and it needs some
        // narrowing down otherwise it tries to find on the entire drive...which
        // is a bit batty.
        // `!not` ... lolz (sorry).
        Iif (utils.isMac && !not) {
          config.dirs.push(dir);
        }
      }
    } catch (e) {}
 
    Iif (rule.slice(-1) === '/') {
      // just slap on a * anyway
      rule += '*';
    }
 
    // if the url ends with * but not **/* and not *.*
    // then convert to **/* - somehow it was missed :-\
    Iif (rule.slice(-4) !== '**/*' &&
        rule.slice(-1) === '*' &&
        rule.indexOf('*.') === -1) {
      rule += '*/*';
    }
 
 
    return (not ? '!' : '') + rule;
  });
 
  return monitor;
}
 
function match(files, monitor, ext) {
  // sort the rules by highest specificity (based on number of slashes)
  // TODO actually check separator rules work on windows
  var rules = monitor.sort(function (a, b) {
    var r = b.split(path.sep).length - a.split(path.sep).length;
 
    if (r === 0) {
      return b.length - a.length;
    }
    return r;
  }).map(function (s) {
    var prefix = s.slice(0, 1);
 
    if (prefix === '!') {
      return '!**' + (s.slice(0, 1) !== path.sep ? path.sep : '') + s.slice(1);
    }
    return '**' + (s.slice(0, 1) !== path.sep ? path.sep : '') + s;
  });
 
  var good = [],
      whitelist = [], // files that we won't check against the extension
      ignored = 0,
      watched = 0;
 
  files.forEach(function (file) {
    var matched = false;
    for (var i = 0; i < rules.length; i++) {
      if (rules[i].slice(0, 1) === '!') {
        if (!minimatch(file, rules[i])) {
          ignored++;
          matched = true;
          break;
        }
      } else {
        if (minimatch(file, rules[i])) {
          watched++;
          utils.log.detail('matched rule: ' + rules[i]);
 
          // if the rule doesn't match the WATCH EVERYTHING
          // but *does* match a rule that ends with *.*, then
          // white list it - in that we don't run it through
          // the extension check too.
          if (rules[i] !== '**' + path.sep + '*.*' && rules[i].slice(-3) === '*.*') {
            whitelist.push(file);
          } else {
            good.push(file);
          }
          matched = true;
          break;
        }
      }
    }
    if (!matched) {
      ignored++;
    }
  });
 
  // finally check the good files against the extensions that we're monitoring
  if (ext) {
    if (ext.indexOf(',') === -1) {
      ext = '**/*.' + ext;
    } else {
      ext = '**/*.{' + ext + '}';
    }
 
    good = good.filter(function(file) {
      // only compare the filename to the extension test, so we use path.basename
      return minimatch(path.basename(file), ext);
    });
  } // else assume *.*
 
  return {
    result: good.concat(whitelist),
    ignored: ignored,
    watched: watched,
    total: files.length
  };
}