-
Notifications
You must be signed in to change notification settings - Fork 0
/
run-for-every-file.js
executable file
·158 lines (140 loc) · 5.04 KB
/
run-for-every-file.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
#!/usr/bin/env node
/**
* Small node.js utility that enumerates files and runs a shell command for every file.
* @author Konstantin Smolyanin
* @license MIT
*/
'use strict';
const fs = require('fs');
const path = require('path');
const execSync = require('child_process').execSync;
const vm = require('vm');
const glob = require('glob');
const minimist = require('minimist');
/**
* It substitutes params in template.
* @param {string} template
* @param {Object} params
* @param {string} [srcDir]
* @param {string} [srcFile]
* @param {string} [destDir]
* @param {string} [destFile]
* @return {string}
*/
function placeParams(template, params, srcDir = null, srcFile = null, destDir = null, destFile = null) {
return template.replace(/{{([^{}]+)}}/g, (_, name) => {
if (name === 'src-file') {
if (srcFile) {
return srcFile;
} else {
throw new Error('Cannot get source path to substitute {{src-file}} param!');
}
} else if (name === 'dest-file') {
if (destFile) {
return destFile;
} else {
throw new Error('Cannot get destination path to substitute {{dest-file}} param!');
}
} else if (['file', 'file-path', 'file-name', 'file-ext', 'file-name-ext'].includes(name)) {
let relPath;
if (srcFile) {
relPath = srcFile.substr((srcDir || '').length);
} else if (destFile) {
relPath = destFile.substr((destDir || '').length);
} else {
throw new Error('Cannot get path to substitute {{' + name + '}} param!');
}
switch (name) {
case 'file':
return relPath;
case 'file-path':
return path.dirname(relPath);
case 'file-name':
const basename = path.basename(relPath);
return basename.substr(0, basename.length - path.extname(relPath).length);
case 'file-ext':
return path.extname(relPath).substr(1);
case 'file-name-ext':
return path.basename(relPath);
}
} else if (['run', 'run-js'].includes(name)) { // not replaceable params
return '{{' + name + '}}';
} else { // optional replaceable params
return name in params ? params[name] : '{{' + name + '}}';
}
});
}
/**
* It finds all files in source dir that are suited for passed patterns.
* @param {string} srcDir
* @param {string|Array} globPattern
* @param {string|Array} globAntiPattern
* @param {Object} globOptions
* @return {Array}
*/
function findFiles(srcDir, globPattern, globAntiPattern = '', globOptions = {}) {
const search = (dir, pattern, globOptions) => {
pattern = Array.isArray(pattern) ? pattern : [pattern];
return pattern.reduce((files, pattern) => {
return files.concat(glob.sync(dir + pattern, globOptions));
}, []);
};
let result = [];
const includeFiles = search(srcDir, globPattern, globOptions);
if (globAntiPattern) {
const excludeFiles = search(srcDir, globAntiPattern, globOptions);
result = includeFiles.filter((file) => !excludeFiles.includes(file));
} else {
result = includeFiles;
}
if (onlyFiles) {
result = includeFiles.filter((file) => fs.lstatSync(file).isFile());
}
return result;
}
/**
* It executes shell command or evaluates JS string.
* @param {boolean} isJsCommand
* @param {string} command
* @param {boolean} isSilent
*/
function run(isJsCommand, command, isSilent = false) {
!isSilent && process.stdout.write(`COMMAND: ${command}\n`);
if (isJsCommand) {
vm.runInThisContext('(function (require) { ' + command + ' });')(require);
} else {
const output = execSync(command) || '';
!isSilent && process.stdout.write(output);
}
}
const params = minimist(process.argv.slice(2));
const srcDir = params.src || null;
const destDir = params.dest || null;
const globPattern = params.file || '';
const globAntiPattern = params['not-file'] || '';
const command = params.run || params['run-js'] || null;
const isJsCommand = 'run-js' in params;
const isSilent = Boolean(params.silent);
const includeDots = Boolean(params.dot);
const onlyFiles = Boolean(params["only-files"]);
const globOptions = {
mark: true,
strict: true,
dot: includeDots
};
if (!command) {
throw new Error('Required parameter "run" not provided!');
}
if (!srcDir) {
run(isJsCommand, placeParams(command, params), isSilent);
process.exit();
}
const srcFiles = findFiles(srcDir, globPattern, globAntiPattern, globOptions);
if (!srcFiles.length) {
!isSilent && console.warn('No one file has been found! Command didn\'t run.');
process.exit();
}
srcFiles.forEach((srcFile) => {
const destFile = destDir ? destDir + srcFile.substr(srcDir.length) : null;
run(isJsCommand, placeParams(command, params, srcDir, srcFile, destDir, destFile), isSilent);
});