-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
185 lines (163 loc) · 4.21 KB
/
index.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
'use strict';
var fs = require('fs');
var spawn = require('cross-spawn');
var extend = require('extend-shallow');
var isWindows = require('is-windows');
var isExtglob = require('is-extglob');
var bashPath;
/**
* Returns true if `str` matches the given `pattern`.
*
* ```js
* var bash = require('bash-match');
* console.log(bash('foo', 'f*'));
* //=> true
*
* console.log(bash('foo', 'b*'));
* //=> false
* ```
*
* @param {String} `str`
* @param {String} `pattern`
* @param {Options} `options` Set `strictErrors` to true to throw when bash throws an error. Otherwise it just returns false.
* @return {Boolean}
* @details false
* @api public
*/
function bash(str, pattern, options) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
if (typeof pattern !== 'string') {
throw new TypeError('expected a string');
}
if (isWindows()) {
throw new Error('bash-match does not work on windows');
}
try {
var opts = createOptions(pattern, options);
var res = spawn.sync(getBashPath(), cmd(str, pattern, opts), opts);
var err = toString(res.stderr);
if (err) {
return handleError(err, opts);
}
return !!toString(res.stdout);
} catch (err) {
return handleError(err, opts);
}
}
/**
* Returns true if `str` matches the given `pattern`. Alias for the [main export](#bash).
*
* ```js
* var bash = require('bash-match');
* console.log(bash.isMatch('foo', 'f*'));
* //=> true
*
* console.log(bash.isMatch('foo', 'b*'));
* //=> false
* ```
*
* @param {String} `str`
* @param {String} `pattern`
* @param {Options} `options` Set `strictErrors` to true to throw when bash throws an error. Otherwise it just returns false.
* @return {Boolean}
* @api public
*/
bash.isMatch = function(fixture, pattern, options) {
return bash(fixture, pattern, options);
};
/**
* Takes a `list` of strings and a glob `pattern`, and returns an array
* of strings that match the pattern.
*
* ```js
* var bash = require('bash-match');
* console.log(bash.match(['foo', 'bar'], 'b*'));
* //=> ['bar']
* ```
*
* @param {Array} `array` List of strings to match
* @param {String} `pattern` Glob pattern
* @param {Options} `options` Set `strictErrors` to true to throw when bash throws an error. Otherwise it just returns false.
* @return {Boolean}
* @api public
*/
bash.match = function(list, pattern, options) {
list = Array.isArray(list) ? list : [list];
var matches = [];
var len = list.length;
var idx = -1;
while (++idx < len) {
var fixture = list[idx];
if (bash.isMatch(fixture, pattern, options)) {
matches.push(fixture);
}
}
return matches;
};
/**
* Create the command to use
*/
function cmd(str, pattern, options) {
var valid = ['dotglob', 'extglob', 'failglob', 'globstar', 'nocaseglob', 'nullglob'];
var args = [];
for (var key in options) {
if (options.hasOwnProperty(key) && valid.indexOf(key) !== -1) {
args.push('-O', key);
}
}
args.push('-c', 'IFS=$"\n"; if [[ "' + str + '" = ' + pattern + ' ]]; then echo true; fi');
return args;
}
/**
* Stringify `buf`
*/
function toString(buf) {
return (buf && buf.toString() || '').trim();
}
/**
* Handle errors
*/
function handleError(err, options) {
if (options && options.strictErrors === true) {
throw err;
}
return false;
}
/**
* Shallow clone and create options
*/
function createOptions(pattern, options) {
if (options && options.normalized === true) return options;
var opts = extend({cwd: process.cwd()}, options);
if (opts.nocase === true) opts.nocaseglob = true;
if (opts.nonull === true) opts.nullglob = true;
if (opts.dot === true) opts.dotglob = true;
if (!opts.hasOwnProperty('globstar') && pattern.indexOf('**') !== -1) {
opts.globstar = true;
}
if (!opts.hasOwnProperty('extglob') && isExtglob(pattern)) {
opts.extglob = true;
}
opts.normalized = true;
return opts;
}
/**
* Get bash path
*/
function getBashPath() {
if (bashPath) return bashPath;
if (fs.existsSync('/usr/local/bin/bash')) {
bashPath = '/usr/local/bin/bash';
} else if (fs.existsSync('/bin/bash')) {
bashPath = '/bin/bash';
} else {
bashPath = 'bash';
}
return bashPath;
}
/**
* Expose `bash`
*/
module.exports = bash;