Skip to content

Commit f9c8fc0

Browse files
committed
Merge pull request #341 from shelljs/feat-valued-options
fix(touch): enhance parseOptions and fix touch's -r flag
2 parents a35f9dd + dc79d7e commit f9c8fc0

File tree

6 files changed

+65
-38
lines changed

6 files changed

+65
-38
lines changed

src/common.js

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,46 +67,57 @@ function getUserHome() {
6767
}
6868
exports.getUserHome = getUserHome;
6969

70-
// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
70+
// Returns {'alice': true, 'bob': false} when passed a string and dictionary as follows:
7171
// parseOptions('-a', {'a':'alice', 'b':'bob'});
72-
function parseOptions(str, map) {
72+
// Returns {'reference': 'string-value', 'bob': false} when passed two dictionaries of the form:
73+
// parseOptions({'-r': 'string-value'}, {'r':'reference', 'b':'bob'});
74+
function parseOptions(opt, map) {
7375
if (!map)
7476
error('parseOptions() internal error: no map given');
7577

7678
// All options are false by default
7779
var options = {};
7880
for (var letter in map) {
79-
if (!map[letter].match('^!'))
81+
if (map[letter][0] !== '!')
8082
options[map[letter]] = false;
8183
}
8284

83-
if (!str)
85+
if (!opt)
8486
return options; // defaults
8587

86-
if (typeof str !== 'string')
87-
error('parseOptions() internal error: wrong str');
88-
89-
// e.g. match[1] = 'Rf' for str = '-Rf'
90-
var match = str.match(/^\-(.+)/);
91-
if (!match)
92-
return options;
93-
94-
// e.g. chars = ['R', 'f']
95-
var chars = match[1].split('');
96-
97-
var opt;
98-
chars.forEach(function(c) {
99-
if (c in map) {
100-
opt = map[c];
101-
if (opt.match('^!'))
102-
options[opt.slice(1, opt.length-1)] = false;
103-
else
104-
options[opt] = true;
105-
} else {
106-
error('option not recognized: '+c);
107-
}
108-
});
88+
var optionName;
89+
if (typeof opt === 'string') {
90+
if (opt[0] !== '-')
91+
return options;
10992

93+
// e.g. chars = ['R', 'f']
94+
var chars = opt.slice(1).split('');
95+
96+
chars.forEach(function(c) {
97+
if (c in map) {
98+
optionName = map[c];
99+
if (optionName[0] === '!')
100+
options[optionName.slice(1, optionName.length-1)] = false;
101+
else
102+
options[optionName] = true;
103+
} else {
104+
error('option not recognized: '+c);
105+
}
106+
});
107+
} else if (typeof opt === 'object') {
108+
for (var key in opt) {
109+
// key is a string of the form '-r', '-d', etc.
110+
var c = key[1];
111+
if (c in map) {
112+
optionName = map[c];
113+
options[optionName] = opt[key]; // assign the given value
114+
} else {
115+
error('option not recognized: '+c);
116+
}
117+
}
118+
} else {
119+
error('options must be strings or key-value pairs');
120+
}
110121
return options;
111122
}
112123
exports.parseOptions = parseOptions;
@@ -213,8 +224,11 @@ function wrap(cmd, fn, options) {
213224
if (options && options.notUnix) {
214225
retValue = fn.apply(this, args);
215226
} else {
216-
if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-')
227+
if (typeof args[0] === 'object' && args[0].constructor.name === 'Object') {
228+
args = args; // object count as options
229+
} else if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') {
217230
args.unshift(''); // only add dummy option if '-option' not already present
231+
}
218232
// Expand the '~' if appropriate
219233
var homeDir = getUserHome();
220234
args = args.map(function(arg) {

src/touch.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ function _touch(opts, files) {
3535
common.error('no paths given');
3636
}
3737

38-
3938
if (Array.isArray(files)) {
4039
files.forEach(function(f) {
4140
touchFile(opts, f);

test/common.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ assert.ok(result.recursive === false);
7676
assert.ok(result.no_force === true);
7777
assert.ok(result.force === undefined); // this key shouldn't exist
7878

79+
// common.parseOptions using an object to hold options
80+
var result = common.parseOptions({'-v': 'some text here'}, {
81+
'v': 'value',
82+
'f': 'force',
83+
'r': 'reverse'
84+
});
85+
assert.ok(result.value === 'some text here');
86+
assert.ok(result.force === false);
87+
assert.ok(result.reverse === false);
88+
7989
shell.exit(123);
8090

8191

test/exec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ if (process.version >= 'v0.11') { // this option doesn't work on v0.10
9999
}
100100

101101
// set timeout option
102-
result = shell.exec('node resources/exec/slow.js'); // default timeout is ok
102+
result = shell.exec('node resources/exec/slow.js 100'); // default timeout is ok
103103
assert.ok(!shell.error());
104104
assert.equal(result.code, 0);
105105
if (process.version >= 'v0.11') { // this option doesn't work on v0.10
106-
result = shell.exec('node resources/exec/slow.js', {timeout: 10}); // times out
106+
result = shell.exec('node resources/exec/slow.js 100', {timeout: 10}); // times out
107107
assert.ok(shell.error());
108108
}
109109

test/resources/exec/slow.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env node
2-
// sleep for 5 seconds
32
setTimeout(function() {
43
console.log('slow');
5-
}, 100);
4+
}, parseInt(process.argv[2], 10));

test/touch.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var shell = require('../shell.js');
1+
var shell = require('..');
22
var assert = require('assert');
33
var fs = require('fs');
44
var crypto = require('crypto');
@@ -39,11 +39,16 @@ assert.ok(shell.error());
3939
// uses a reference file for mtime
4040
var testFile = tmpFile(false);
4141
var testFile2 = tmpFile();
42-
var testFile2Stat = resetUtimes(testFile2);
43-
42+
shell.touch(testFile2);
43+
shell.exec('node resources/exec/slow.js 3000');
44+
shell.touch(testFile);
45+
assert.ok(!shell.error());
46+
assert.notEqual(fs.statSync(testFile).mtime.getTime(), fs.statSync(testFile2).mtime.getTime());
47+
assert.notEqual(fs.statSync(testFile).atime.getTime(), fs.statSync(testFile2).atime.getTime());
4448
shell.touch({'-r': testFile2}, testFile);
45-
var testFileStat = resetUtimes(testFile);
46-
assert.strictEqual(testFileStat.mtime.getTime(), testFile2Stat.mtime.getTime());
49+
assert.ok(!shell.error());
50+
assert.equal(fs.statSync(testFile).mtime.getTime(), fs.statSync(testFile2).mtime.getTime());
51+
assert.equal(fs.statSync(testFile).atime.getTime(), fs.statSync(testFile2).atime.getTime());
4752

4853
// sets mtime
4954
var testFile = tmpFile();

0 commit comments

Comments
 (0)