kopia lustrzana https://github.com/c9/core
Merge remote-tracking branch 'origin/master' into revert-13609-revert-13539-all-ab-testing
Conflicts: configs/docker.js npm-shrinkwrap.jsonpull/312/head
commit
a3063c246f
|
@ -9,7 +9,10 @@
|
||||||
"https://cloud9beta.com/", "https://ide.cloud9beta.com/",
|
"https://cloud9beta.com/", "https://ide.cloud9beta.com/",
|
||||||
"http://localhost:8181/", "http://localhost:5252/",
|
"http://localhost:8181/", "http://localhost:5252/",
|
||||||
"https://c9.vm:8181/", "https://c9.vm:5252/",
|
"https://c9.vm:8181/", "https://c9.vm:5252/",
|
||||||
"https://c9.dev/", "https://ide.c9.dev/"
|
"https://c9.dev/", "https://ide.c9.dev/",
|
||||||
|
"https://ide.dev.smartface.io",
|
||||||
|
"https://ide.cs50.io",
|
||||||
|
"https://ide.mbed.com"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"description": "Cloud9 is an online platform for development that makes developing applications more convenient than ever",
|
"description": "Cloud9 is an online platform for development that makes developing applications more convenient than ever",
|
||||||
|
|
|
@ -689,11 +689,7 @@ module.exports = function(options) {
|
||||||
pubkey: options.user.pubkey,
|
pubkey: options.user.pubkey,
|
||||||
date_add: options.user.date_add,
|
date_add: options.user.date_add,
|
||||||
active: options.user.active,
|
active: options.user.active,
|
||||||
alpha: options.user.alpha,
|
|
||||||
beta: options.user.beta,
|
|
||||||
c9version: options.user.c9version,
|
c9version: options.user.c9version,
|
||||||
no_newsletter: options.user.no_newsletter,
|
|
||||||
subscription_on_signup: options.user.subscription_on_signup,
|
|
||||||
premium: options.user.premium,
|
premium: options.user.premium,
|
||||||
region: options.user.region,
|
region: options.user.region,
|
||||||
},
|
},
|
||||||
|
@ -920,6 +916,9 @@ module.exports = function(options) {
|
||||||
plugins.push({
|
plugins.push({
|
||||||
packagePath: "plugins/c9.ide.language.codeintel/codeintel",
|
packagePath: "plugins/c9.ide.language.codeintel/codeintel",
|
||||||
preinstalled: hosted && !options.ssh,
|
preinstalled: hosted && !options.ssh,
|
||||||
|
paths: {
|
||||||
|
php: ".:./vendor",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,15 @@ function runCommand(pattern, command, options, callback) {
|
||||||
return runCommand(pattern, command, {}, options);
|
return runCommand(pattern, command, {}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
var parallel = ""
|
var optionsArray = [];
|
||||||
if (options.parallel) {
|
if (options.parallel) {
|
||||||
parallel = " -P"
|
optionsArray.push("-P");
|
||||||
|
}
|
||||||
|
if (options.cacheOnly) {
|
||||||
|
optionsArray.push("--cache-only");
|
||||||
}
|
}
|
||||||
|
|
||||||
var gsshCommand = GSSH + " " + parallel + " " + pattern + " '" + command + "'";
|
var gsshCommand = GSSH + " " + optionsArray.join(" ") + " " + pattern + " '" + command + "'";
|
||||||
childProcess.exec(gsshCommand, function (err, stdout) {
|
childProcess.exec(gsshCommand, function (err, stdout) {
|
||||||
return callback(err, stdout);
|
return callback(err, stdout);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
var error = require("http-error");
|
var error = require("http-error");
|
||||||
|
var _ = require("lodash");
|
||||||
|
|
||||||
|
var MAX_EXPIRE_INTERVAL = 5000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In memory rate limiter as connect middleware
|
* In memory rate limiter as connect middleware
|
||||||
|
@ -6,27 +9,39 @@ var error = require("http-error");
|
||||||
module.exports = ratelimit;
|
module.exports = ratelimit;
|
||||||
|
|
||||||
function ratelimit(key, duration, max) {
|
function ratelimit(key, duration, max) {
|
||||||
var limit = {};
|
var requests = Object.create(null); // in case there handles like 'constructor'
|
||||||
|
setInterval(function() {
|
||||||
|
Object.keys(requests).forEach(expireRequests);
|
||||||
|
}, Math.min(duration * 0.75, MAX_EXPIRE_INTERVAL));
|
||||||
|
|
||||||
|
function expireRequests(handle) {
|
||||||
|
var requestsForHandle = requests[handle];
|
||||||
|
var totalToSplice = 0;
|
||||||
|
var expireTime = Date.now() - duration;
|
||||||
|
/* Requests are already sorted by date as they are appended, so we just loop
|
||||||
|
until we find one that shouldn't have expired and splice them from the list */
|
||||||
|
for (totalToSplice = 0; totalToSplice < requestsForHandle.length; totalToSplice++) {
|
||||||
|
if (requestsForHandle[totalToSplice] >= expireTime) break;
|
||||||
|
}
|
||||||
|
requests[handle].splice(0, totalToSplice);
|
||||||
|
if (requests[handle].length == 0) {
|
||||||
|
delete requests[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return function(req, res, next) {
|
return function(req, res, next) {
|
||||||
var handle = req.params[key];
|
var handle = req.params[key];
|
||||||
|
|
||||||
var lim = limit[handle] || (limit[handle] = []);
|
requests[handle] = requests[handle] || [];
|
||||||
var now = Date.now();
|
if (requests[handle].length >= max) {
|
||||||
for (var i = 0; i < lim.length; i++) {
|
|
||||||
if (now - lim[i] > duration) {
|
|
||||||
lim.splice(i, 1);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
if (lim.length > max) {
|
|
||||||
var err = new error.TooManyRequests("Rate limit exceeded");
|
var err = new error.TooManyRequests("Rate limit exceeded");
|
||||||
err.retryIn = duration - (Date.now() - lim[0]);
|
err.retryIn = Math.min(duration, 5000);
|
||||||
next(err);
|
return next(err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
lim.push(Date.now());
|
|
||||||
|
|
||||||
|
requests[handle].push(Date.now());
|
||||||
return next();
|
return next();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
require("c9/inline-mocha")(module);
|
||||||
|
|
||||||
|
var ratelimit = require("./ratelimit");
|
||||||
|
var assert = require("assert");
|
||||||
|
var async = require("async");
|
||||||
|
|
||||||
|
describe("ratelimit", function() {
|
||||||
|
|
||||||
|
it("Should limit based on key", function (done) {
|
||||||
|
var limiter = ratelimit("username", 10, 1);
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(err);
|
||||||
|
assert.equal(err.code, 429);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should work with different keys", function (done) {
|
||||||
|
var limiter = ratelimit("username", 10, 1);
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
limiter({params: {username: "aloha"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
it("Should work again after a delay", function (done) {
|
||||||
|
var limiter = ratelimit("username", 10, 1);
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
setTimeout(function() {
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, 25);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should work with many requests", function (done) {
|
||||||
|
var MAX_REQUESTS = 5;
|
||||||
|
var limiter = ratelimit("username", 10, MAX_REQUESTS);
|
||||||
|
var successfulRequests = 0;
|
||||||
|
async.times(10, function(n, next) {
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
if (err) return next(err);
|
||||||
|
successfulRequests++;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
assert.equal(successfulRequests, MAX_REQUESTS);
|
||||||
|
setTimeout(function() {
|
||||||
|
limiter({params: {username: "super"}}, null, function (err) {
|
||||||
|
assert(!err, err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, 25);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should expire keys at the correct times", function (done) {
|
||||||
|
var limiter = ratelimit("username", 50, 2);
|
||||||
|
async.series([
|
||||||
|
function(next) {
|
||||||
|
limiter({params: {username: "mario"}}, null, function(err) {
|
||||||
|
assert(!err, err);
|
||||||
|
setTimeout(next, 25);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
limiter({params: {username: "mario"}}, null, function(err) {
|
||||||
|
assert(!err, err);
|
||||||
|
setTimeout(next, 40);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
limiter({params: {username: "mario"}}, null, function(err) {
|
||||||
|
assert(!err, err);
|
||||||
|
limiter({params: {username: "mario"}}, null, function(err) {
|
||||||
|
assert(err);
|
||||||
|
assert.equal(err.code, 429);
|
||||||
|
setTimeout(next, 20);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
limiter({params: {username: "mario"}}, null, function(err) {
|
||||||
|
assert(!err, err);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], done);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -13,6 +13,7 @@ define(function(require, exports, module) {
|
||||||
"bitbucket.org": "bitbucket",
|
"bitbucket.org": "bitbucket",
|
||||||
"github.com": "github",
|
"github.com": "github",
|
||||||
"source.developers.google.com": "google",
|
"source.developers.google.com": "google",
|
||||||
|
"gitlab.com": "gitlab",
|
||||||
};
|
};
|
||||||
var defaultProvider = "unknown";
|
var defaultProvider = "unknown";
|
||||||
|
|
||||||
|
@ -75,6 +76,9 @@ define(function(require, exports, module) {
|
||||||
case "bitbucket":
|
case "bitbucket":
|
||||||
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
|
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
|
||||||
break;
|
break;
|
||||||
|
case "gitlab":
|
||||||
|
scm = "git";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
|
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,57 +16,60 @@ describe(__filename, function() {
|
||||||
|
|
||||||
describe("#parse", function() {
|
describe("#parse", function() {
|
||||||
it("should parse ssh url", function(done) {
|
it("should parse ssh url", function(done) {
|
||||||
var url = parse("git@github.com:fjakobs/lispjs.git");
|
var url = parse("git@github.com:fjakobs/lispjs.git");
|
||||||
assert.equal(url.scm, "git");
|
assert.equal(url.scm, "git");
|
||||||
assert.equal(url.protocol, "ssh:");
|
assert.equal(url.protocol, "ssh:");
|
||||||
assert.equal(url.auth, "git");
|
assert.equal(url.provider, "github");
|
||||||
assert.equal(url.hostname, "github.com");
|
assert.equal(url.auth, "git");
|
||||||
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
assert.equal(url.hostname, "github.com");
|
||||||
done();
|
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
||||||
|
done();
|
||||||
|
}),
|
||||||
|
|
||||||
}),
|
it("should parse git url", function(done) {
|
||||||
|
var url = parse("git://github.com/fjakobs/lispjs.git");
|
||||||
|
assert.equal(url.scm, "git");
|
||||||
|
assert.equal(url.protocol, "git:");
|
||||||
|
assert.equal(url.provider, "github");
|
||||||
|
assert.equal(url.hostname, "github.com");
|
||||||
|
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
||||||
|
done();
|
||||||
|
}),
|
||||||
|
|
||||||
it("should parse git url", function(done) {
|
it("should parse https url", function(done) {
|
||||||
var url = parse("git://github.com/fjakobs/lispjs.git");
|
var url = parse("https://fjakobs@github.com/fjakobs/lispjs.git");
|
||||||
assert.equal(url.scm, "git");
|
assert.equal(url.protocol, "https:");
|
||||||
assert.equal(url.protocol, "git:");
|
assert.equal(url.scm, "git");
|
||||||
assert.equal(url.hostname, "github.com");
|
assert.equal(url.auth, "fjakobs");
|
||||||
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
assert.equal(url.provider, "github");
|
||||||
done();
|
assert.equal(url.hostname, "github.com");
|
||||||
|
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
||||||
|
done();
|
||||||
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
it("should parse https url", function(done) {
|
it("should parse Bitbucket url", function(done) {
|
||||||
var url = parse("https://fjakobs@github.com/fjakobs/lispjs.git");
|
var url = parse("git@bitbucket.org/Richard/expressling.git");
|
||||||
assert.equal(url.protocol, "https:");
|
assert.equal(url.protocol, "ssh:");
|
||||||
assert.equal(url.scm, "git");
|
assert.equal(url.scm, "git");
|
||||||
assert.equal(url.auth, "fjakobs");
|
assert.equal(url.auth, "git");
|
||||||
assert.equal(url.hostname, "github.com");
|
assert.equal(url.provider, "bitbucket");
|
||||||
assert.equal(url.pathname, "fjakobs/lispjs.git");
|
assert.equal(url.hostname, "bitbucket.org");
|
||||||
done();
|
assert.equal(url.pathname, "Richard/expressling.git");
|
||||||
|
done();
|
||||||
}),
|
});
|
||||||
|
|
||||||
it("should parse Bitbucket url", function(done) {
|
|
||||||
var url = parse("git@bitbucket.org/Richard/expressling.git");
|
|
||||||
assert.equal(url.protocol, "ssh:");
|
|
||||||
assert.equal(url.scm, "git");
|
|
||||||
assert.equal(url.auth, "git");
|
|
||||||
assert.equal(url.hostname, "bitbucket.org");
|
|
||||||
assert.equal(url.pathname, "Richard/expressling.git");
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should parse Bitbucket hg ssh url", function(done) {
|
it("should parse Bitbucket hg ssh url", function(done) {
|
||||||
var url = parse("ssh://hg@bitbucket.org/fjakobs/juhu");
|
var url = parse("ssh://hg@bitbucket.org/fjakobs/juhu");
|
||||||
assert.equal(url.protocol, "ssh:");
|
assert.equal(url.protocol, "ssh:");
|
||||||
assert.equal(url.scm, "hg");
|
assert.equal(url.scm, "hg");
|
||||||
|
assert.equal(url.provider, "bitbucket");
|
||||||
assert.equal(url.hostname, "bitbucket.org");
|
assert.equal(url.hostname, "bitbucket.org");
|
||||||
assert.equal(url.pathname, "fjakobs/juhu");
|
assert.equal(url.pathname, "fjakobs/juhu");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse github URL without .git", function(done) {
|
it("should parse Github url without .git", function(done) {
|
||||||
var url = parse("https://github.com/arunoda/meteor-streams");
|
var url = parse("https://github.com/arunoda/meteor-streams");
|
||||||
assert.equal(url.protocol, "https:");
|
assert.equal(url.protocol, "https:");
|
||||||
assert.equal(url.scm, "git");
|
assert.equal(url.scm, "git");
|
||||||
|
@ -76,7 +79,27 @@ describe(__filename, function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should refuse a git url with dangerous shell chars in it", function() {
|
it("should parse Gitlab url", function(done) {
|
||||||
|
var url = parse("git@gitlab.com:bdewachter/testfiles.git");
|
||||||
|
assert.equal(url.scm, "git");
|
||||||
|
assert.equal(url.protocol, "ssh:");
|
||||||
|
assert.equal(url.provider, "gitlab");
|
||||||
|
assert.equal(url.hostname, "gitlab.com");
|
||||||
|
assert.equal(url.pathname, "bdewachter/testfiles.git");
|
||||||
|
done();
|
||||||
|
}),
|
||||||
|
|
||||||
|
it("should parse Gitlab url without .git", function(done) {
|
||||||
|
var url = parse("https://gitlab.com/bdewachter/testfiles.git");
|
||||||
|
assert.equal(url.protocol, "https:");
|
||||||
|
assert.equal(url.scm, "git");
|
||||||
|
assert.equal(url.provider, "gitlab");
|
||||||
|
assert.equal(url.hostname, "gitlab.com");
|
||||||
|
assert.equal(url.pathname, "bdewachter/testfiles.git");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should refuse a git url with dangerous shell chars in it", function() {
|
||||||
var validUrls = [
|
var validUrls = [
|
||||||
"https://github.com/arunoda/meteor-streams",
|
"https://github.com/arunoda/meteor-streams",
|
||||||
"https://fjakobs@github.com/fjakobs/lispjs.git",
|
"https://fjakobs@github.com/fjakobs/lispjs.git",
|
||||||
|
|
|
@ -39,7 +39,7 @@ module.exports = function setup(mount, vfs, mountOptions) {
|
||||||
if (path) {
|
if (path) {
|
||||||
entry.href = path + entry.name;
|
entry.href = path + entry.name;
|
||||||
var mime = entry.linkStat ? entry.linkStat.mime : entry.mime;
|
var mime = entry.linkStat ? entry.linkStat.mime : entry.mime;
|
||||||
if (mime && mime.match(/(directory|folder)$/)) {
|
if (/(directory|folder)$/.test(mime)) {
|
||||||
entry.href += "/";
|
entry.href += "/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,15 @@ var pathBasename = require("path").basename;
|
||||||
var dirname = require("path").dirname;
|
var dirname = require("path").dirname;
|
||||||
var basename = require("path").basename;
|
var basename = require("path").basename;
|
||||||
var Stream = require("stream").Stream;
|
var Stream = require("stream").Stream;
|
||||||
var getMime = require("simple-mime")("application/octet-stream");
|
var getMime = (function(simpleMime) {
|
||||||
|
// workaround for a bug in simple-mime
|
||||||
|
return function(path) {
|
||||||
|
var mime = simpleMime(path);
|
||||||
|
if (typeof mime != "string")
|
||||||
|
return "application/octet-stream"
|
||||||
|
return mime;
|
||||||
|
}
|
||||||
|
})(require("simple-mime")());
|
||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
var exists = fs.exists || require("path").exists;
|
var exists = fs.exists || require("path").exists;
|
||||||
var crypto = require("crypto");
|
var crypto = require("crypto");
|
||||||
|
|
14
package.json
14
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "c9",
|
"name": "c9",
|
||||||
"description": "New Cloud9 Client",
|
"description": "New Cloud9 Client",
|
||||||
"version": "3.1.2362",
|
"version": "3.1.2495",
|
||||||
"author": "Ajax.org B.V. <info@ajax.org>",
|
"author": "Ajax.org B.V. <info@ajax.org>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "bin/c9",
|
"main": "bin/c9",
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
"c9"
|
"c9"
|
||||||
],
|
],
|
||||||
"c9plugins": {
|
"c9plugins": {
|
||||||
"c9.ide.language": "#ebc064ef16",
|
"c9.ide.language": "#79bcb2fe06",
|
||||||
"c9.ide.language.css": "#be07d72209",
|
"c9.ide.language.css": "#be07d72209",
|
||||||
"c9.ide.language.generic": "#3949510863",
|
"c9.ide.language.generic": "#3949510863",
|
||||||
"c9.ide.language.html": "#22fdc74869",
|
"c9.ide.language.html": "#22fdc74869",
|
||||||
|
@ -66,16 +66,16 @@
|
||||||
"c9.ide.language.javascript": "#e626169643",
|
"c9.ide.language.javascript": "#e626169643",
|
||||||
"c9.ide.language.javascript.immediate": "#c8b1e5767a",
|
"c9.ide.language.javascript.immediate": "#c8b1e5767a",
|
||||||
"c9.ide.language.javascript.eslint": "#4de5457db1",
|
"c9.ide.language.javascript.eslint": "#4de5457db1",
|
||||||
"c9.ide.language.javascript.tern": "#b55d0069bb",
|
"c9.ide.language.javascript.tern": "#64ab01f271",
|
||||||
"c9.ide.language.javascript.infer": "#18acb93a3a",
|
"c9.ide.language.javascript.infer": "#18acb93a3a",
|
||||||
"c9.ide.language.jsonalyzer": "#d8183d84b4",
|
"c9.ide.language.jsonalyzer": "#d8183d84b4",
|
||||||
"c9.ide.language.codeintel": "#e92ace1a56",
|
"c9.ide.language.codeintel": "#fc867feec4",
|
||||||
"c9.ide.collab": "#cf93793700",
|
"c9.ide.collab": "#1c0f841985",
|
||||||
"c9.ide.local": "#10eb45842a",
|
"c9.ide.local": "#10eb45842a",
|
||||||
"c9.ide.find": "#e33fbaed2f",
|
"c9.ide.find": "#e33fbaed2f",
|
||||||
"c9.ide.find.infiles": "#c0a13737ef",
|
"c9.ide.find.infiles": "#c0a13737ef",
|
||||||
"c9.ide.find.replace": "#810ebf8bfb",
|
"c9.ide.find.replace": "#810ebf8bfb",
|
||||||
"c9.ide.run.debug": "#9acb7f3178",
|
"c9.ide.run.debug": "#3206c81cd4",
|
||||||
"c9.automate": "#47e2c429c9",
|
"c9.automate": "#47e2c429c9",
|
||||||
"c9.ide.ace.emmet": "#6dc4585e02",
|
"c9.ide.ace.emmet": "#6dc4585e02",
|
||||||
"c9.ide.ace.gotoline": "#a8ff07c8f4",
|
"c9.ide.ace.gotoline": "#a8ff07c8f4",
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
"c9.ide.imgeditor": "#612e75ef4f",
|
"c9.ide.imgeditor": "#612e75ef4f",
|
||||||
"c9.ide.immediate": "#0e0c18066c",
|
"c9.ide.immediate": "#0e0c18066c",
|
||||||
"c9.ide.installer": "#b2e4ba0a92",
|
"c9.ide.installer": "#b2e4ba0a92",
|
||||||
"c9.ide.language.python": "#6572da93c1",
|
"c9.ide.language.python": "#aff0772c78",
|
||||||
"c9.ide.language.go": "#6ce1c7a7ef",
|
"c9.ide.language.go": "#6ce1c7a7ef",
|
||||||
"c9.ide.mount": "#4c39359b87",
|
"c9.ide.mount": "#4c39359b87",
|
||||||
"c9.ide.navigate": "#5d5707058c",
|
"c9.ide.navigate": "#5d5707058c",
|
||||||
|
|
|
@ -30,85 +30,43 @@ define(function(require, exports, module) {
|
||||||
return '"' + name + '"';
|
return '"' + name + '"';
|
||||||
};
|
};
|
||||||
|
|
||||||
var SupportedIcons = {
|
var SupportedIcons = (function() {
|
||||||
"c9search": "page_white_magnify",
|
var extToClass = Object.create(null);
|
||||||
"js": "page_white_code",
|
var classToExt = {
|
||||||
"jsx": "page_white_code_red",
|
"page_white_magnify": "c9search",
|
||||||
"ts": "page_white_code",
|
"page_white_code": ["clj", "go", "js", "json", "ml", "mli", "py", "ts", "xq"],
|
||||||
"tsx": "page_white_code_red",
|
"page_white_code_red": ["jsx", "tsx", "xml"],
|
||||||
"json": "page_white_code",
|
"css": ["css", "less", "sass", "scss"],
|
||||||
"css": "css",
|
"page_white_picture": "svg",
|
||||||
"scss": "css",
|
"page_white_php": ["php", "phtml"],
|
||||||
"sass": "css",
|
"html": ["html", "xhtml"],
|
||||||
"less": "css",
|
"page_white_cup": ["coffee", "java"],
|
||||||
"xml": "page_white_code_red",
|
"logiql": "logic",
|
||||||
"svg": "page_white_picture",
|
"page_white_ruby": ["gemspec", "rake", "rb", "ru"],
|
||||||
"php": "page_white_php",
|
"page_white_c": ["c", "cc", "cxx"],
|
||||||
"phtml": "page_white_php",
|
"page_white_cplusplus": "cpp",
|
||||||
"html": "html",
|
"page_white_h": ["h", "hh", "hpp"],
|
||||||
"xhtml": "html",
|
"image": ["bmp", "djv", "djvu", "gif", "ico", "jpeg", "jpg", "pbm", "pgm", "png", "pnm", "ppm", "psd", "svgz", "tif", "tiff", "xbm", "xpm"],
|
||||||
"coffee": "page_white_cup",
|
"page_white_acrobat": "pdf",
|
||||||
"py": "page_white_code",
|
"page_white_coldfusion": "cfm",
|
||||||
"go": "page_white_code",
|
"page_white_database": ["db", "sql"],
|
||||||
"java": "page_white_cup",
|
"page_white_wrench": ["bash", "sh"],
|
||||||
"logic": "logiql",
|
"page_white_zip": ["bz", "gz", "tar", "xz", "zip"],
|
||||||
"ru": "page_white_ruby",
|
"page_white_compressed": "rar",
|
||||||
"gemspec": "page_white_ruby",
|
"page_white_swoosh": ["exe", "lnk", "o", "bin", "class"],
|
||||||
"rake": "page_white_ruby",
|
"page_white_text": "txt",
|
||||||
"rb": "page_white_ruby",
|
"page_white_gear": ["bashrc", "build", "gitignore", "profile", "run", "settings"]
|
||||||
"c": "page_white_c",
|
};
|
||||||
"cc": "page_white_c",
|
Object.keys(classToExt).forEach(function(k) {
|
||||||
"cpp": "page_white_cplusplus",
|
var exts = classToExt[k];
|
||||||
"cxx": "page_white_c",
|
if (typeof exts == "string")
|
||||||
"h": "page_white_h",
|
exts = [exts];
|
||||||
"hh": "page_white_h",
|
exts.forEach(function(ext) {
|
||||||
"hpp": "page_white_h",
|
extToClass[ext] = k;
|
||||||
"bmp": "image",
|
});
|
||||||
"djv": "image",
|
});
|
||||||
"djvu": "image",
|
return extToClass;
|
||||||
"gif": "image",
|
})();
|
||||||
"ico": "image",
|
|
||||||
"jpeg": "image",
|
|
||||||
"jpg": "image",
|
|
||||||
"pbm": "image",
|
|
||||||
"pgm": "image",
|
|
||||||
"png": "image",
|
|
||||||
"pnm": "image",
|
|
||||||
"ppm": "image",
|
|
||||||
"psd": "image",
|
|
||||||
"svgz": "image",
|
|
||||||
"tif": "image",
|
|
||||||
"tiff": "image",
|
|
||||||
"xbm": "image",
|
|
||||||
"xpm": "image",
|
|
||||||
"pdf": "page_white_acrobat",
|
|
||||||
"clj": "page_white_code",
|
|
||||||
"ml": "page_white_code",
|
|
||||||
"mli": "page_white_code",
|
|
||||||
"cfm": "page_white_coldfusion",
|
|
||||||
"sql": "page_white_database",
|
|
||||||
"db": "page_white_database",
|
|
||||||
"sh": "page_white_wrench",
|
|
||||||
"bash": "page_white_wrench",
|
|
||||||
"xq": "page_white_code",
|
|
||||||
"xz": "page_white_zip",
|
|
||||||
"gz": "page_white_zip",
|
|
||||||
"bz": "page_white_zip",
|
|
||||||
"zip": "page_white_zip",
|
|
||||||
"tar": "page_white_zip",
|
|
||||||
"rar": "page_white_compressed",
|
|
||||||
"exe": "page_white_swoosh",
|
|
||||||
"o": "page_white_swoosh",
|
|
||||||
"lnk": "page_white_swoosh",
|
|
||||||
"txt": "page_white_text",
|
|
||||||
"settings": "page_white_gear",
|
|
||||||
"run": "page_white_gear",
|
|
||||||
"build": "page_white_gear",
|
|
||||||
"gitignore": "page_white_gear",
|
|
||||||
"profile": "page_white_gear",
|
|
||||||
"bashrc": "page_white_gear",
|
|
||||||
};
|
|
||||||
|
|
||||||
plugin.getFileIcon = function(name) {
|
plugin.getFileIcon = function(name) {
|
||||||
var icon = "page_white_text";
|
var icon = "page_white_text";
|
||||||
var ext;
|
var ext;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io">Home</a>
|
<a href="https://c9.io">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io/">Home</a>
|
<a href="https://c9.io/">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io/">Home</a>
|
<a href="https://c9.io/">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io/">Home</a>
|
<a href="https://c9.io/">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io">Home</a>
|
<a href="https://c9.io">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -707,7 +707,7 @@ define(function(require, exports, module) {
|
||||||
status: "pending",
|
status: "pending",
|
||||||
className: "projectRoot",
|
className: "projectRoot",
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
map: {}
|
map: Object.create(null)
|
||||||
};
|
};
|
||||||
var root = {};
|
var root = {};
|
||||||
root.map = Object.create(null);
|
root.map = Object.create(null);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
e
|
|
@ -0,0 +1 @@
|
||||||
|
v
|
|
@ -0,0 +1 @@
|
||||||
|
i
|
|
@ -0,0 +1 @@
|
||||||
|
l
|
|
@ -2,7 +2,7 @@ define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
main.consumes = [
|
main.consumes = [
|
||||||
"Plugin", "c9", "ui", "menus", "tree", "info", "vfs"
|
"Plugin", "c9", "ui", "menus", "tree", "info", "vfs", "preferences", "settings"
|
||||||
];
|
];
|
||||||
main.provides = ["download"];
|
main.provides = ["download"];
|
||||||
return main;
|
return main;
|
||||||
|
@ -15,6 +15,11 @@ define(function(require, exports, module) {
|
||||||
var tree = imports.tree;
|
var tree = imports.tree;
|
||||||
var vfs = imports.vfs;
|
var vfs = imports.vfs;
|
||||||
var info = imports.info;
|
var info = imports.info;
|
||||||
|
var prefs = imports.preferences;
|
||||||
|
var settings = imports.settings;
|
||||||
|
|
||||||
|
var SETTING_NAME = "downloadFilesAs";
|
||||||
|
var SETTING_PATH = "user/general/@" + SETTING_NAME;
|
||||||
|
|
||||||
/***** Initialization *****/
|
/***** Initialization *****/
|
||||||
|
|
||||||
|
@ -40,6 +45,28 @@ define(function(require, exports, module) {
|
||||||
onclick: download
|
onclick: download
|
||||||
}), 140, plugin);
|
}), 140, plugin);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Preferences
|
||||||
|
prefs.add({
|
||||||
|
"General" : {
|
||||||
|
"Tree & Navigate" : {
|
||||||
|
"Download Files As" : {
|
||||||
|
type: "dropdown",
|
||||||
|
path: SETTING_PATH,
|
||||||
|
items: [
|
||||||
|
{ caption : "auto", value : "auto" },
|
||||||
|
{ caption : "tar.gz", value : "tar.gz" },
|
||||||
|
{ caption : "zip", value : "zip" }
|
||||||
|
],
|
||||||
|
position: 5000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, plugin);
|
||||||
|
|
||||||
|
settings.on("read", function() {
|
||||||
|
settings.setDefaults("user/general", [[SETTING_NAME, "auto"]]);
|
||||||
|
}, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function download() {
|
function download() {
|
||||||
|
@ -55,7 +82,7 @@ define(function(require, exports, module) {
|
||||||
if (node.isFolder && node.path == "/")
|
if (node.isFolder && node.path == "/")
|
||||||
downloadProject();
|
downloadProject();
|
||||||
else if (paths.length > 1)
|
else if (paths.length > 1)
|
||||||
vfs.download(paths);
|
downloadPaths(paths);
|
||||||
else if (node.isFolder)
|
else if (node.isFolder)
|
||||||
downloadFolder(node.path);
|
downloadFolder(node.path);
|
||||||
else
|
else
|
||||||
|
@ -64,17 +91,32 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadProject() {
|
function downloadProject() {
|
||||||
vfs.download("/", info.getWorkspace().name + ".tar.gz");
|
vfs.download("/", info.getWorkspace().name + getArchiveFileExtension());
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadPaths(paths) {
|
||||||
|
vfs.download(paths, info.getWorkspace().name + getArchiveFileExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadFolder(path) {
|
function downloadFolder(path) {
|
||||||
vfs.download(path.replace(/\/*$/, "/"));
|
var withTrailingSlash = path.replace(/\/*$/, "/");
|
||||||
|
var parts = withTrailingSlash.split("/");
|
||||||
|
var lastPart = parts[parts.length - 2];
|
||||||
|
vfs.download(withTrailingSlash, lastPart + getArchiveFileExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadFile(path) {
|
function downloadFile(path) {
|
||||||
vfs.download(path.replace(/\/*$/, ""), null, true);
|
vfs.download(path.replace(/\/*$/, ""), null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getArchiveFileExtension() {
|
||||||
|
var downloadFilesAs = settings.get(SETTING_PATH);
|
||||||
|
if (downloadFilesAs === 'auto' || !downloadFilesAs) {
|
||||||
|
downloadFilesAs = /Win/.test(navigator.platform) ? 'zip' : 'tar.gz';
|
||||||
|
}
|
||||||
|
return '.' + downloadFilesAs;
|
||||||
|
}
|
||||||
|
|
||||||
/***** Lifecycle *****/
|
/***** Lifecycle *****/
|
||||||
|
|
||||||
plugin.on("load", function(){
|
plugin.on("load", function(){
|
||||||
|
|
|
@ -88,9 +88,11 @@ define(function(require, exports, module) {
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
statics.addStatics(externalPlugins.map(function(plugin) {
|
statics.addStatics(externalPlugins.map(function(plugin) {
|
||||||
|
if (typeof plugin == "string")
|
||||||
|
plugin = { path: plugin, mount: plugin};
|
||||||
return {
|
return {
|
||||||
path: __dirname + "/../../node_modules/" + plugin,
|
path: __dirname + "/../../node_modules/" + plugin.path,
|
||||||
mount: "/plugins/" + plugin
|
mount: "/plugins/" + plugin.mount
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="http://status.c9.io">Status Page</a> |
|
<a href="http://status.c9.io">Status Page</a> |
|
||||||
<a href="mailto:support@c9.io">Support</a> |
|
<a href="https://c9.io/support">Support</a> |
|
||||||
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
<a href="https://c9.io/dashboard.html">Dashboard</a> |
|
||||||
<a href="https://c9.io">Home</a>
|
<a href="https://c9.io">Home</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -209,6 +209,7 @@ define(function(require, exports, module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function reconnect(callback) {
|
function reconnect(callback) {
|
||||||
|
if (!connection) return;
|
||||||
connection.socket.setSocket(null);
|
connection.socket.setSocket(null);
|
||||||
|
|
||||||
vfsEndpoint.get(protocolVersion, function(err, urls) {
|
vfsEndpoint.get(protocolVersion, function(err, urls) {
|
||||||
|
@ -336,6 +337,11 @@ define(function(require, exports, module) {
|
||||||
plugin.on("unload", function(){
|
plugin.on("unload", function(){
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
|
||||||
|
if (consumer)
|
||||||
|
consumer.disconnect();
|
||||||
|
if (connection)
|
||||||
|
connection.disconnect();
|
||||||
|
|
||||||
id = null;
|
id = null;
|
||||||
buffer = [];
|
buffer = [];
|
||||||
region = null;
|
region = null;
|
||||||
|
@ -346,6 +352,7 @@ define(function(require, exports, module) {
|
||||||
serviceUrl = null;
|
serviceUrl = null;
|
||||||
eioOptions = null;
|
eioOptions = null;
|
||||||
consumer = null;
|
consumer = null;
|
||||||
|
connection = null;
|
||||||
vfs = null;
|
vfs = null;
|
||||||
showErrorTimer = null;
|
showErrorTimer = null;
|
||||||
showErrorTimerMessage = null;
|
showErrorTimerMessage = null;
|
||||||
|
|
|
@ -80,29 +80,50 @@ define(function(require, exports, module) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO add support for downloding as zip on windows
|
var executable, args, contentType;
|
||||||
// var cwd;
|
|
||||||
// var args = ["-r", "-"];
|
|
||||||
// paths.forEach(function(path) {
|
|
||||||
// if (!path) return;
|
|
||||||
// var dir = Path.dirname(path);
|
|
||||||
// if (!cwd) cwd = dir;
|
|
||||||
// var name = Path.relative(cwd, path);
|
|
||||||
// if (name[0] == "-") name = "./" + name;
|
|
||||||
// args.push(name);
|
|
||||||
// });
|
|
||||||
// vfs.spawn("zip", { args: args, cwd: cwd }
|
|
||||||
|
|
||||||
var args = ["-zcf", "-"];
|
if (/\.zip$/.test(filename)) {
|
||||||
paths.forEach(function(path) {
|
executable = "zip";
|
||||||
|
args = ["-r", "-", "--"];
|
||||||
|
contentType = "application/zip"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
executable = "tar";
|
||||||
|
args = ["-zcf", "-", "--"];
|
||||||
|
contentType = "application/x-gzip"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the longest common parent directory of all the paths.
|
||||||
|
var cwd = null;
|
||||||
|
paths.forEach(function (path) {
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
var dir = Path.dirname(path);
|
var dir = Path.dirname(path);
|
||||||
var name = Path.basename(path);
|
if (!cwd) {
|
||||||
if (name[0] == "-")
|
cwd = dir;
|
||||||
name = "--add-file=" + name;
|
}
|
||||||
args.push("-C" + dir, name);
|
else {
|
||||||
|
var relative = Path.relative(cwd, dir).split(Path.sep);
|
||||||
|
var i = 0;
|
||||||
|
while (relative[i] === '..') {
|
||||||
|
cwd = Path.resolve(cwd, '..');
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
vfs.spawn("tar", { args: args }, function (err, meta) {
|
paths.forEach(function(path) {
|
||||||
|
if (!path) return;
|
||||||
|
path = Path.relative(cwd, path);
|
||||||
|
// tar misinterprets the Windows path separator as an escape sequence, so use forward slash.
|
||||||
|
if (Path.sep === '\\') {
|
||||||
|
path = path.replace(/\\/g, '/');
|
||||||
|
}
|
||||||
|
args.push(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
vfs.spawn(executable, {
|
||||||
|
args: args,
|
||||||
|
cwd: cwd
|
||||||
|
}, function (err, meta) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
||||||
|
@ -114,7 +135,7 @@ define(function(require, exports, module) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
"Content-Type": "application/x-gzip",
|
"Content-Type": contentType,
|
||||||
"Content-Disposition": filenameHeader
|
"Content-Disposition": filenameHeader
|
||||||
});
|
});
|
||||||
res.write(data);
|
res.write(data);
|
||||||
|
@ -133,16 +154,16 @@ define(function(require, exports, module) {
|
||||||
var err;
|
var err;
|
||||||
if (code == 127) {
|
if (code == 127) {
|
||||||
err = new error.PreconditionFailed(
|
err = new error.PreconditionFailed(
|
||||||
"Your instance seems to be missing the 'tar' utility\n" +
|
"Your instance seems to be missing the '" + executable + "' utility\n" +
|
||||||
"If you are using an SSH workspace, please do:\n" +
|
"If you are using an SSH workspace, please do:\n" +
|
||||||
" 'sudo apt-get install tar'");
|
" 'sudo apt-get install " + executable + "'");
|
||||||
} else if (code) {
|
} else if (code) {
|
||||||
err = new error.InternalServerError(
|
err = new error.InternalServerError(
|
||||||
"'tar' utility failed with exit code " + code +
|
"'" + executable + "' utility failed with exit code " + code +
|
||||||
" and stderr:/n'" + stderr + "'");
|
" and stderr:/n'" + stderr + "'");
|
||||||
} else if (signal) {
|
} else if (signal) {
|
||||||
err = new error.InternalServerError(
|
err = new error.InternalServerError(
|
||||||
"'tar' utility was terminated by signal " + signal
|
"'" + executable + "' utility was terminated by signal " + signal
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,9 @@ describe(__filename, function(){
|
||||||
|
|
||||||
describe("download", function() {
|
describe("download", function() {
|
||||||
|
|
||||||
it("should download", function(next) {
|
it("should download as tar", function(next) {
|
||||||
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
var filename = path + "/download.tar.gz";
|
var filename = path + "/download.tar.gz";
|
||||||
var file = fs.createWriteStream(filename);
|
var file = fs.createWriteStream(filename);
|
||||||
http.get("http://localhost:8787/?download=download.tar.gz", function(res) {
|
http.get("http://localhost:8787/?download=download.tar.gz", function(res) {
|
||||||
|
@ -77,21 +78,22 @@ describe(__filename, function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should download sub directory", function(next) {
|
it("should download sub directory as tar", function(next) {
|
||||||
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
assert.equal(err, null);
|
assert.equal(err, null);
|
||||||
|
|
||||||
var filename = path + "/download.tar.gz";
|
var filename = path + "/download.tar.gz";
|
||||||
var file = fs.createWriteStream(filename);
|
var file = fs.createWriteStream(filename);
|
||||||
http.get("http://localhost:8787/views?download=download.tar.gz", function(res) {
|
http.get("http://localhost:8787/test?download=download.tar.gz", function(res) {
|
||||||
res.pipe(file);
|
res.pipe(file);
|
||||||
|
|
||||||
res.on("end", function() {
|
res.on("end", function() {
|
||||||
execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) {
|
execFile("tar", ["-zxvf", filename, "test/dir1/testdata1.txt"], {cwd: path}, function(err) {
|
||||||
assert.equal(err, null);
|
assert.equal(err, null);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"),
|
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
|
||||||
fs.readFileSync(path + "/views/status.html.ejs", "utf8")
|
fs.readFileSync(path + "/test/dir1/testdata1.txt", "utf8")
|
||||||
);
|
);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
@ -102,22 +104,180 @@ describe(__filename, function(){
|
||||||
|
|
||||||
it("should download without specifying a name", function(next) {
|
it("should download without specifying a name", function(next) {
|
||||||
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
assert.equal(err, null);
|
assert.equal(err, null);
|
||||||
|
|
||||||
var filename = path + "/download.tar.gz";
|
var filename = path + "/download.tar.gz";
|
||||||
var file = fs.createWriteStream(filename);
|
var file = fs.createWriteStream(filename);
|
||||||
http.get("http://localhost:8787/views?download", function(res) {
|
http.get("http://localhost:8787/test?download", function(res) {
|
||||||
assert.equal(res.headers["content-type"], "application/x-gzip");
|
assert.equal(res.headers["content-type"], "application/x-gzip");
|
||||||
assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''views.tar.gz");
|
assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''test.tar.gz");
|
||||||
|
|
||||||
res.pipe(file);
|
res.pipe(file);
|
||||||
|
|
||||||
res.on("end", function() {
|
res.on("end", function() {
|
||||||
execFile("tar", ["-zxvf", filename, "views/status.html.ejs"], {cwd: path}, function(err) {
|
execFile("tar", ["-zxvf", filename, "test/dir1/testdata1.txt"], {cwd: path}, function(err) {
|
||||||
assert.equal(err, null);
|
assert.equal(err, null);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"),
|
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
|
||||||
fs.readFileSync(path + "/views/status.html.ejs", "utf8")
|
fs.readFileSync(path + "/test/dir1/testdata1.txt", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download several files in same directory as tar", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
assert.equal(err, null);
|
||||||
|
|
||||||
|
var filename = path + "/download.tar.gz";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/test/dir2/testdata2a.txt,/test/dir2/testdata2b.txt?download=download.tar.gz", function(res) {
|
||||||
|
res.pipe(file);
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("tar", ["-zxvf", filename], {cwd: path}, function(err) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2a.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/testdata2a.txt", "utf8")
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2b.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/testdata2b.txt", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download several files in different directories as tar", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
assert.equal(err, null);
|
||||||
|
|
||||||
|
var filename = path + "/download.tar.gz";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/test/dir1/testdata1.txt,/test/dir2/testdata2a.txt?download=download.tar.gz", function(res) {
|
||||||
|
res.pipe(file);
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("tar", ["-zxvf", filename], {cwd: path}, function(err) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/dir1/testdata1.txt", "utf8")
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2a.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/dir2/testdata2a.txt", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download as zip", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
var filename = path + "/download.zip";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/?download=download.zip", function(res) {
|
||||||
|
assert.equal(res.headers["content-type"], "application/zip");
|
||||||
|
assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''download.zip");
|
||||||
|
|
||||||
|
res.pipe(file);
|
||||||
|
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("unzip", [filename, "c9.vfs.server/download.js"], {cwd: path}, function(err, stdout, stderr) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/download.js", "utf8"),
|
||||||
|
fs.readFileSync(path + "/c9.vfs.server/download.js", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download sub directory as zip", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
assert.equal(err, null);
|
||||||
|
|
||||||
|
var filename = path + "/download.zip";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/test?download=download.zip", function(res) {
|
||||||
|
res.pipe(file);
|
||||||
|
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("unzip", [filename, "test/dir1/testdata1.txt"], {cwd: path}, function(err) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/test/dir1/testdata1.txt", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download several files in same directory as zip", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
assert.equal(err, null);
|
||||||
|
|
||||||
|
var filename = path + "/download.zip";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/test/dir2/testdata2a.txt,/test/dir2/testdata2b.txt?download=download.zip", function(res) {
|
||||||
|
res.pipe(file);
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("unzip", [filename], {cwd: path}, function(err) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2a.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/testdata2a.txt", "utf8")
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2b.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/testdata2b.txt", "utf8")
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should download several files in different directories as zip", function(next) {
|
||||||
|
tmp.dir({unsafeCleanup: true}, function(err, path) {
|
||||||
|
path = path.replace(/\w:/, '');
|
||||||
|
assert.equal(err, null);
|
||||||
|
|
||||||
|
var filename = path + "/download.zip";
|
||||||
|
var file = fs.createWriteStream(filename);
|
||||||
|
http.get("http://localhost:8787/test/dir1/testdata1.txt,/test/dir2/testdata2a.txt?download=download.zip", function(res) {
|
||||||
|
res.pipe(file);
|
||||||
|
res.on("end", function() {
|
||||||
|
execFile("unzip", [filename], {cwd: path}, function(err) {
|
||||||
|
assert.equal(err, null);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/dir1/testdata1.txt", "utf8")
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
fs.readFileSync(__dirname + "/test/dir2/testdata2a.txt", "utf8"),
|
||||||
|
fs.readFileSync(path + "/dir2/testdata2a.txt", "utf8")
|
||||||
);
|
);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
test data 1
|
|
@ -0,0 +1 @@
|
||||||
|
test data 2a
|
|
@ -0,0 +1 @@
|
||||||
|
test data 2b
|
|
@ -271,6 +271,7 @@
|
||||||
return cb();
|
return cb();
|
||||||
setTimeout.paused = true;
|
setTimeout.paused = true;
|
||||||
window.app.services.vfs.connection.disconnect();
|
window.app.services.vfs.connection.disconnect();
|
||||||
|
window.app.services["vfs.endpoint"].clearCache();
|
||||||
setTimeout.force(function() {
|
setTimeout.force(function() {
|
||||||
setTimeout.paused = false;
|
setTimeout.paused = false;
|
||||||
setTimeout.clear();
|
setTimeout.clear();
|
||||||
|
|
Ładowanie…
Reference in New Issue