Skip to content

Commit 2d1ee4d

Browse files
committed
fix(mv): add -n option, make -f default behavior
1 parent 760c191 commit 2d1ee4d

File tree

5 files changed

+64
-13
lines changed

5 files changed

+64
-13
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,13 @@ Removes files. The wildcard `*` is accepted.
246246
### mv([options ,] source_array, dest')
247247
Available options:
248248

249-
+ `-f`: force
249+
+ `-f`: force (default behavior)
250+
+ `-n`: no-clobber
250251

251252
Examples:
252253

253254
```javascript
254-
mv('-f', 'file', 'dir/');
255+
mv('-n', 'file', 'dir/');
255256
mv('file1', 'file2', 'dir/');
256257
mv(['file1', 'file2'], 'dir/'); // same as above
257258
```

src/common.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ function parseOptions(str, map) {
7474

7575
// All options are false by default
7676
var options = {};
77-
for (var letter in map)
78-
options[map[letter]] = false;
77+
for (var letter in map) {
78+
if (!map[letter].match('^!'))
79+
options[map[letter]] = false;
80+
}
7981

8082
if (!str)
8183
return options; // defaults
@@ -91,11 +93,17 @@ function parseOptions(str, map) {
9193
// e.g. chars = ['R', 'f']
9294
var chars = match[1].split('');
9395

96+
var opt;
9497
chars.forEach(function(c) {
95-
if (c in map)
96-
options[map[c]] = true;
97-
else
98+
if (c in map) {
99+
opt = map[c];
100+
if (opt.match('^!'))
101+
options[opt.slice(1, opt.length-1)] = false;
102+
else
103+
options[opt] = true;
104+
} else {
98105
error('option not recognized: '+c);
106+
}
99107
});
100108

101109
return options;

src/mv.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,22 @@ var common = require('./common');
77
//@ ### mv([options ,] source_array, dest')
88
//@ Available options:
99
//@
10-
//@ + `-f`: force
10+
//@ + `-f`: force (default behavior)
11+
//@ + `-n`: no-clobber
1112
//@
1213
//@ Examples:
1314
//@
1415
//@ ```javascript
15-
//@ mv('-f', 'file', 'dir/');
16+
//@ mv('-n', 'file', 'dir/');
1617
//@ mv('file1', 'file2', 'dir/');
1718
//@ mv(['file1', 'file2'], 'dir/'); // same as above
1819
//@ ```
1920
//@
2021
//@ Moves files. The wildcard `*` is accepted.
2122
function _mv(options, sources, dest) {
2223
options = common.parseOptions(options, {
23-
'f': 'force'
24+
'f': '!no_force',
25+
'n': 'no_force'
2426
});
2527

2628
// Get sources, dest
@@ -47,7 +49,7 @@ function _mv(options, sources, dest) {
4749
common.error('dest is not a directory (too many sources)');
4850

4951
// Dest is an existing file, but no -f given
50-
if (exists && stats.isFile() && !options.force)
52+
if (exists && stats.isFile() && options.no_force)
5153
common.error('dest file already exists: ' + dest);
5254

5355
sources.forEach(function(src) {
@@ -64,7 +66,7 @@ function _mv(options, sources, dest) {
6466
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
6567
thisDest = path.normalize(dest + '/' + path.basename(src));
6668

67-
if (fs.existsSync(thisDest) && !options.force) {
69+
if (fs.existsSync(thisDest) && options.no_force) {
6870
common.error('dest file already exists: ' + thisDest, true);
6971
return; // skip file
7072
}

test/common.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,36 @@ var result = common.expand(['**/file*.js']);
4646
assert.equal(shell.error(), null);
4747
assert.deepEqual(result.sort(), ["resources/file1.js","resources/file2.js","resources/ls/file1.js","resources/ls/file2.js"].sort());
4848

49+
// common.parseOptions (normal case)
50+
var result = common.parseOptions('-Rf', {
51+
'R': 'recursive',
52+
'f': 'force',
53+
'r': 'reverse'
54+
});
55+
assert.ok(result.recursive === true);
56+
assert.ok(result.force === true);
57+
assert.ok(result.reverse === false);
58+
59+
// common.parseOptions (with mutually-negating options)
60+
var result = common.parseOptions('-f', {
61+
'n': 'no_force',
62+
'f': '!no_force',
63+
'R': 'recursive'
64+
});
65+
assert.ok(result.recursive === false);
66+
assert.ok(result.no_force === false);
67+
assert.ok(result.force === undefined); // this key shouldn't exist
68+
69+
// common.parseOptions (the last of the conflicting options should hold)
70+
var result = common.parseOptions('-fn', {
71+
'n': 'no_force',
72+
'f': '!no_force',
73+
'R': 'recursive'
74+
});
75+
assert.ok(result.recursive === false);
76+
assert.ok(result.no_force === true);
77+
assert.ok(result.force === undefined); // this key shouldn't exist
78+
4979
shell.exit(123);
5080

5181

test/mv.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,17 @@ assert.equal(fs.existsSync('tmp/asdfasdf2'), false);
4343
shell.mv('asdfasdf1', 'asdfasdf2', 'tmp/file1'); // too many sources (dest is file)
4444
assert.ok(shell.error());
4545

46-
shell.mv('tmp/file1', 'tmp/file2'); // dest already exists
46+
// -n is no-force/no-clobber
47+
shell.mv('-n', 'tmp/file1', 'tmp/file2'); // dest already exists
48+
assert.ok(shell.error());
49+
50+
// -f is the default behavior
51+
shell.cp('tmp/file1', 'tmp/tmp_file');
52+
shell.mv('tmp/tmp_file', 'tmp/file2'); // dest already exists (but that's ok)
53+
assert.ok(!shell.error());
54+
55+
// -fn is the same as -n
56+
shell.mv('-fn', 'tmp/file1', 'tmp/file2');
4757
assert.ok(shell.error());
4858

4959
shell.mv('tmp/file1', 'tmp/file2', 'tmp/a_file'); // too many sources (exist, but dest is file)

0 commit comments

Comments
 (0)