Merge pull request #152 from pbouianov/issue126

Added shell.mkdirp. Fixes issue #126.
This commit is contained in:
Alan K 2014-03-14 11:41:39 -04:00
commit 8945514285
4 changed files with 184 additions and 0 deletions

View File

@ -1109,6 +1109,7 @@ var sh = fs.Shell();
* [sh.cat(files, callback)](#cat) * [sh.cat(files, callback)](#cat)
* [sh.rm(path, [options], callback)](#rm) * [sh.rm(path, [options], callback)](#rm)
* [sh.tempDir(callback)](#tempDir) * [sh.tempDir(callback)](#tempDir)
* [sh.mkdirp(path, callback)](#mkdirp)
#### sh.cd(path, callback)<a name="cd"></a> #### sh.cd(path, callback)<a name="cd"></a>
@ -1298,3 +1299,19 @@ sh.tempDir(function(err, tmp) {
// tmp is now '/temporary', and /temporary exists // tmp is now '/temporary', and /temporary exists
}); });
``` ```
#### sh.mkdirp(callback)<a name="mkdirp"></a>
Recursively creates the directory at the provided path. If the
directory already exists, no error is returned. All parents must
be valid directories (not files).
Example:
```javascript
// Default empty filesystem
sh.mkdirp('/test/mkdirp', function(err) {
if(err) throw err;
// the root '/' now contains a directory 'test' containing the directory 'mkdirp'
});
```

View File

@ -353,6 +353,75 @@ define(function(require) {
}); });
}; };
/**
* Recursively creates the directory at `path`. If the parent
* of `path` does not exist, it will be created.
* Based off EnsureDir by Sam X. Xu
* https://www.npmjs.org/package/ensureDir
* MIT License
*/
Shell.prototype.mkdirp = function(path, callback) {
var fs = this.fs;
callback = callback || function(){};
if(!path) {
callback(new Errors.EInvalid());
return;
}
else if (path === '/'){
callback();
return;
}
function _mkdirp(path, callback){
fs.stat(path, function (err, stat) {
//doesn't exist
if (err && err.code === 'ENOENT') {
var parent = Path.dirname(path);
if(parent === '/'){ //parent is root
fs.mkdir(path, function (err) {
if (err && err.code != 'EEXIST') {
callback(err);
return;
}
callback();
return;
});
}
else { //parent is not root, make parent first
_mkdirp(parent, function (err) {
if (err) return callback(err);
fs.mkdir(path, function (err) { //then make dir
if (err && err.code != 'EEXIST') {
callback(err);
return;
}
callback();
return;
});
});
}
}
//other error
else if (err){
callback(err);
return;
}
//already exists
else if (stat.type === 'DIRECTORY') {
callback();
return;
}
//not a directory
else if (stat.type === 'FILE') {
callback(new Errors.ENotDirectory());
return;
}
});
}
_mkdirp(path, callback);
};
return Shell; return Shell;
}); });

View File

@ -0,0 +1,97 @@
define(["Filer", "util"], function(Filer, util) {
describe('FileSystemShell.mkdirp', function() {
beforeEach(util.setup);
afterEach(util.cleanup);
it('should be a function', function() {
var shell = util.shell();
expect(shell.mkdirp).to.be.a('function');
});
it('should fail without a path provided', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp(null, function(err) {
expect(err).to.exist;
expect(err.code).to.equal('EINVAL');
done();
});
});
it('should succeed if provided path is root', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp('/', function(err) {
expect(err).to.not.exist;
done();
});
});
it('should succeed if the directory exists', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.mkdir('/test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test',function(err) {
expect(err).to.not.exist;
done();
});
});
});
it('fail if a file name is provided', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test.txt', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done();
});
});
});
it('should succeed on a folder on root (\'/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp('/test', function(err) {
expect(err).to.not.exist;
fs.exists('/test', function(dir){
expect(dir).to.be.true;
done();
});
});
});
it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
shell.mkdirp('/test/test', function(err) {
expect(err).to.not.exist;
fs.exists('/test', function(dir1){
expect(dir1).to.be.true;
fs.exists('/test/test', function(dir2){
expect(dir2).to.be.true;
done();
});
});
});
});
it('should fail on a folder with a file for its parent (\'/test.txt/test\')', function(done) {
var fs = util.fs();
var shell = fs.Shell();
fs.writeFile('/test.txt', 'test', function(err){
expect(err).to.not.exist;
shell.mkdirp('/test.txt/test', function(err) {
expect(err).to.exist;
expect(err.code).to.equal('ENOTDIR');
done();
});
});
});
});
});

View File

@ -55,6 +55,7 @@ define([
"spec/shell/ls.spec", "spec/shell/ls.spec",
"spec/shell/rm.spec", "spec/shell/rm.spec",
"spec/shell/env.spec", "spec/shell/env.spec",
"spec/shell/mkdirp.spec",
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test) // Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
"spec/node-js/simple/test-fs-mkdir", "spec/node-js/simple/test-fs-mkdir",