-
Notifications
You must be signed in to change notification settings - Fork 31.2k
/
Copy path_cli.js
149 lines (125 loc) Β· 3.88 KB
/
_cli.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
'use strict';
const fs = require('fs');
const path = require('path');
// Create an object of all benchmark scripts
const benchmarks = {};
fs.readdirSync(__dirname)
.filter((name) => {
return name !== 'fixtures' &&
fs.statSync(path.resolve(__dirname, name)).isDirectory();
})
.forEach((category) => {
benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category))
.filter((filename) => filename[0] !== '.' && filename[0] !== '_');
});
function CLI(usage, settings) {
if (process.argv.length < 3) {
this.abort(usage); // Abort will exit the process
}
this.usage = usage;
this.optional = {};
this.items = [];
this.test = false;
for (const argName of settings.arrayArgs) {
this.optional[argName] = [];
}
let currentOptional = null;
let mode = 'both'; // Possible states are: [both, option, item]
for (const arg of process.argv.slice(2)) {
if (arg === '--help') this.abort(usage);
if (arg === '--') {
// Only items can follow --
mode = 'item';
} else if (mode === 'both' && arg[0] === '-') {
// Optional arguments declaration
if (arg[1] === '-') {
currentOptional = arg.slice(2);
} else {
currentOptional = arg.slice(1);
}
if (settings.boolArgs && settings.boolArgs.includes(currentOptional)) {
this.optional[currentOptional] = true;
mode = 'both';
} else {
// Expect the next value to be option related (either -- or the value)
mode = 'option';
}
} else if (mode === 'option') {
// Optional arguments value
if (settings.arrayArgs.includes(currentOptional)) {
this.optional[currentOptional].push(arg);
} else {
this.optional[currentOptional] = arg;
}
// The next value can be either an option or an item
mode = 'both';
} else if (arg === 'test') {
this.test = true;
} else if (['both', 'item'].includes(mode)) {
// item arguments
this.items.push(arg);
// The next value must be an item
mode = 'item';
} else {
// Bad case, abort
this.abort(usage);
}
}
}
module.exports = CLI;
CLI.prototype.abort = function(msg) {
console.error(msg);
process.exit(1);
};
CLI.prototype.benchmarks = function() {
const paths = [];
if (this.items.includes('all')) {
this.items = Object.keys(benchmarks);
}
for (const category of this.items) {
if (benchmarks[category] === undefined) {
console.error(`The "${category}" category does not exist.`);
process.exit(1);
}
for (const scripts of benchmarks[category]) {
if (this.shouldSkip(scripts)) continue;
paths.push(path.join(category, scripts));
}
}
return paths;
};
CLI.prototype.shouldSkip = function(scripts) {
const filters = this.optional.filter || [];
const excludes = this.optional.exclude || [];
let skip = filters.length > 0;
for (const filter of filters) {
if (scripts.lastIndexOf(filter) !== -1) {
skip = false;
}
}
for (const exclude of excludes) {
if (scripts.lastIndexOf(exclude) !== -1) {
skip = true;
}
}
return skip;
};
/**
* Extracts the CPU core setting from the CLI arguments.
* @returns {string|null} The CPU core setting if found, otherwise null.
*/
CLI.prototype.getCpuCoreSetting = function() {
const cpuCoreSetting = this.optional.set.find((s) => s.startsWith('CPUSET='));
if (!cpuCoreSetting) return null;
const value = cpuCoreSetting.split('=')[1];
// Validate the CPUSET value to match patterns like "0", "0-2", "0,1,2", "0,2-4,6" or "0,0,1-2"
const isValid = /^(\d+(-\d+)?)(,\d+(-\d+)?)*$/.test(value);
if (!isValid) {
throw new Error(`
Invalid CPUSET format: "${value}". Please use a single core number (e.g., "0"),
a range of cores (e.g., "0-3"), or a list of cores/ranges
(e.g., "0,2,4" or "0-2,4").\n\n${this.usage}
`);
}
return value;
};