Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #1635 from ajaxorg/fs_mkdirp

Added mkdirp to sandboxed fs
  • Loading branch information...
commit 372663b7224c67c68dee88719674208d27cdd2f3 2 parents c919687 + 0c2c2f5
@janjongboom janjongboom authored
View
3  plugins-server/cloud9.ide.revisions/revisions.js
@@ -294,12 +294,11 @@ require("util").inherits(RevisionsPlugin, Plugin);
};
if (!exists) {
- fs.mkdir(parentDir, "0755", createRevisionsFile);
+ fs.mkdirP(parentDir, "0755", createRevisionsFile);
}
else {
createRevisionsFile();
}
-
});
});
}
View
145 plugins-server/cloud9.sandbox.fs/fs.js
@@ -2,153 +2,218 @@ var Path = require("path");
var Fs = require("fs");
module.exports = function (projectDir, unixId) {
-
+
this.$normalizeCallback = function (fn) {
if (typeof fn !== "function") {
return function () {};
}
-
+
return fn;
};
-
+
/**
* Resolves the path given a path relative to a project folder
*/
this.$resolvePath = function (relativePath, callback) {
var path = Path.join(projectDir, relativePath);
path = Path.normalize(path);
-
+
if (path.indexOf(projectDir) !== 0) {
return callback("Can't step out project dir... " + path);
}
-
+
callback(null, path);
};
-
+
/**
* Wrapper around Path.exists
*/
this.exists = function (path, callback) {
- var self = this;
-
callback = this.$normalizeCallback(callback);
-
- self.$resolvePath(path, function (err, path) {
+ this.$resolvePath(path, function (err, path) {
if (err) return callback(err);
-
+
Path.exists(path, function (exists) {
callback(null, exists);
});
});
};
-
- this.$simpleWrapper = function (name, fnArgs) {
+
+ this.$simpleWrapper = function (name, fnArgs) {
var path = fnArgs[0];
var callback = this.$normalizeCallback(fnArgs[fnArgs.length - 1]);
-
+
this.$resolvePath(path, function (err, path) {
if (err) return callback(err);
-
+
// first copy the array with slice(0), then remove the first arg
var args = [].slice.call(fnArgs).slice(1);
Fs[name].apply(Fs, [path].concat(args));
- });
+ });
};
-
+
this.$chownWrapper = function (name, fnArgs) {
var path = fnArgs[0];
var callback = this.$normalizeCallback(fnArgs[fnArgs.length - 1]);
-
+
this.$resolvePath(path, function (err, path) {
if (err) return callback(err);
-
+
// first copy the array with slice(0), then remove the first arg
var args = [].slice.call(fnArgs).slice(1);
-
+
// pop the last argument cause we want to override it (if its a function of course)
var lastArg = args.pop();
if (typeof lastArg === "function") {
lastArg = function (err) {
if (err) return callback(err);
-
+
if (!unixId) {
return callback();
}
-
+
Fs.chown(path, unixId, unixId, function (err) {
if (err) return callback(err);
-
+
// @todo, do a chmod here?
-
+
callback();
});
};
}
-
+
Fs[name].apply(Fs, [path].concat(args).concat([lastArg]));
- });
+ });
};
-
+
/**
* Wrapper around fs.readFile
*/
this.readFile = function () {
return this.$simpleWrapper.call(this, "readFile", arguments);
};
-
+
/**
* Wrapper around fs.writeFile
*/
this.writeFile = function () {
- return this.$chownWrapper.call(this, "writeFile", arguments);
+ return this.$chownWrapper.call(this, "writeFile", arguments);
};
-
+
/**
* Wrapper around chmod
*/
this.chmod = function () {
return this.$simpleWrapper.call(this, "chmod", arguments);
};
-
+
/**
* Wrapper around rename
*/
this.rename = function () {
return this.$simpleWrapper.call(this, "rename", arguments);
- };
-
+ };
+
/**
* Wrapper around readdir
*/
this.readdir = function () {
- return this.$simpleWrapper.call(this, "readdir", arguments);
+ return this.$simpleWrapper.call(this, "readdir", arguments);
};
-
+
/**
* Wrapper around open
*/
this.open = function () {
- return this.$simpleWrapper.call(this, "open", arguments);
+ return this.$simpleWrapper.call(this, "open", arguments);
};
-
+
/**
* Wrapper around write
*/
this.write = function () {
Fs.write.apply(this, arguments);
};
-
+
/**
* Wrapper around close
*/
this.close = function () {
Fs.close.apply(this, arguments);
};
-
+
/**
* Wrapper around mkdir
*/
this.mkdir = function () {
return this.$chownWrapper.call(this, "mkdir", arguments);
};
-};
+
+ /**
+ * Equivalent to "mkdir - p"
+ * Adapted from https://github.com/substack/node-mkdirp
+ */
+ this.mkdirP = function mkdirP(path, mode, f, made) {
+ var self = this;
+ if (typeof mode === "function" || mode === undefined) {
+ f = mode;
+ mode = 0777 & (~process.umask());
+ }
+
+ if (!made) {
+ made = null;
+ }
+
+ var cb = f || function () {};
+ if (typeof mode === "string") {
+ mode = parseInt(mode, 8);
+ }
+
+ self.mkdir(path, mode, function (er) {
+ if (!er) {
+ made = made || path;
+ return cb(null, made);
+ }
+
+ switch (er.code) {
+ case "ENOENT":
+ mkdirP.call(self, Path.dirname(path), mode, function (er, made) {
+ if (er) {
+ cb(er, made);
+ }
+ else {
+ mkdirP.call(self, path, mode, cb, made);
+ }
+ });
+ break;
+
+ case "EROFS":
+ // a read-only file system.
+ // However, the dir could already exist, in which case
+ // the EROFS error will be obscuring a EEXIST!
+ // Fallthrough to that case.
+ case "EEXIST":
+ Fs.stat(path, function (er2, stat) {
+ // if the stat fails, then that's super weird.
+ // let the original EEXIST be the failure reason.
+ if (er2 || !stat.isDirectory()) {
+ cb(er, made);
+ }
+ else cb(null, made);
+ });
+ break;
+
+ default:
+ cb(er, made);
+ break;
+ }
+ });
+ };
+
+ /**
+ * Wrapper around unlink
+ */
+ this.unlink = function () {
+ return this.$simpleWrapper.call(this, "unlink", arguments);
+ };
+};
View
28 plugins-server/cloud9.sandbox.fs/fs_test.js
@@ -156,7 +156,33 @@ module.exports = {
next();
});
- }
+ },
+
+ "test mkdirP should chown": function (next) {
+ var mkdir = Fs.mkdir = sinon.stub().callsArgWith(2, null);
+ var chown = Fs.chown = sinon.stub().callsArgWith(3, null);
+ this.fs.mkdirP("somefolder/andItsChildren/andItsGrandChildren", "0775", function (err) {
+ assert.equal(err, null);
+ sinon.assert.calledWith(chown, "/usr/jan/1299/somefolder/andItsChildren/andItsGrandChildren", 987, 987);
+
+ next();
+ });
+ },
+
+ "test mkdirP should actually create the dir": function (next) {
+ var fs = new SandboxFs(__dirname, null);
+
+ fs.mkdirP("folder/child/grandchild", "0775", function (err) {
+ assert.equal(err, null);
+
+ fs.exists("folder/child/grandchild", function (err, exists) {
+ assert.equal(err, null);
+ assert.equal(exists, true);
+
+ require("rimraf")(__dirname + "/folder", next);
+ });
+ });
+ }
};
!module.parent && require("asyncjs").test.testcase(module.exports, "Sandbox.Fs").exec();
Please sign in to comment.
Something went wrong with that request. Please try again.