• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const fs = require('fs');
4const path = require('path');
5
6// Create an object of all benchmark scripts
7const benchmarks = {};
8fs.readdirSync(__dirname)
9  .filter((name) => {
10    return name !== 'fixtures' &&
11           fs.statSync(path.resolve(__dirname, name)).isDirectory();
12  })
13  .forEach((category) => {
14    benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category))
15      .filter((filename) => filename[0] !== '.' && filename[0] !== '_');
16  });
17
18function CLI(usage, settings) {
19  if (process.argv.length < 3) {
20    this.abort(usage); // Abort will exit the process
21  }
22
23  this.usage = usage;
24  this.optional = {};
25  this.items = [];
26  this.test = false;
27
28  for (const argName of settings.arrayArgs) {
29    this.optional[argName] = [];
30  }
31
32  let currentOptional = null;
33  let mode = 'both'; // Possible states are: [both, option, item]
34
35  for (const arg of process.argv.slice(2)) {
36    if (arg === '--') {
37      // Only items can follow --
38      mode = 'item';
39    } else if (mode === 'both' && arg[0] === '-') {
40      // Optional arguments declaration
41
42      if (arg[1] === '-') {
43        currentOptional = arg.slice(2);
44      } else {
45        currentOptional = arg.slice(1);
46      }
47
48      if (settings.boolArgs && settings.boolArgs.includes(currentOptional)) {
49        this.optional[currentOptional] = true;
50        mode = 'both';
51      } else {
52        // Expect the next value to be option related (either -- or the value)
53        mode = 'option';
54      }
55    } else if (mode === 'option') {
56      // Optional arguments value
57
58      if (settings.arrayArgs.includes(currentOptional)) {
59        this.optional[currentOptional].push(arg);
60      } else {
61        this.optional[currentOptional] = arg;
62      }
63
64      // The next value can be either an option or an item
65      mode = 'both';
66    } else if (arg === 'test') {
67      this.test = true;
68    } else if (['both', 'item'].includes(mode)) {
69      // item arguments
70      this.items.push(arg);
71
72      // The next value must be an item
73      mode = 'item';
74    } else {
75      // Bad case, abort
76      this.abort(usage);
77    }
78  }
79}
80module.exports = CLI;
81
82CLI.prototype.abort = function(msg) {
83  console.error(msg);
84  process.exit(1);
85};
86
87CLI.prototype.benchmarks = function() {
88  const paths = [];
89
90  if (this.items.includes('all')) {
91    this.items = Object.keys(benchmarks);
92  }
93
94  for (const category of this.items) {
95    if (benchmarks[category] === undefined) {
96      console.error(`The "${category}" category does not exist.`);
97      process.exit(1);
98    }
99    for (const scripts of benchmarks[category]) {
100      if (this.shouldSkip(scripts)) continue;
101
102      paths.push(path.join(category, scripts));
103    }
104  }
105
106  return paths;
107};
108
109CLI.prototype.shouldSkip = function(scripts) {
110  const filters = this.optional.filter || [];
111  const excludes = this.optional.exclude || [];
112  let skip = filters.length > 0;
113
114  for (const filter of filters) {
115    if (scripts.lastIndexOf(filter) !== -1) {
116      skip = false;
117    }
118  }
119
120  for (const exclude of excludes) {
121    if (scripts.lastIndexOf(exclude) !== -1) {
122      skip = true;
123    }
124  }
125
126  return skip;
127};
128