Merge remote-tracking branch 'origin/master' into revert-13609-revert-13539-all-ab-testing

Conflicts:
	configs/docker.js
	npm-shrinkwrap.json
pull/312/head
Lennart Kats 2016-05-23 10:06:18 +00:00
commit a3063c246f
34 zmienionych plików z 563 dodań i 206 usunięć

Wyświetl plik

@ -9,7 +9,10 @@
"https://cloud9beta.com/", "https://ide.cloud9beta.com/",
"http://localhost:8181/", "http://localhost: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",

Wyświetl plik

@ -689,11 +689,7 @@ module.exports = function(options) {
pubkey: options.user.pubkey,
date_add: options.user.date_add,
active: options.user.active,
alpha: options.user.alpha,
beta: options.user.beta,
c9version: options.user.c9version,
no_newsletter: options.user.no_newsletter,
subscription_on_signup: options.user.subscription_on_signup,
premium: options.user.premium,
region: options.user.region,
},
@ -920,6 +916,9 @@ module.exports = function(options) {
plugins.push({
packagePath: "plugins/c9.ide.language.codeintel/codeintel",
preinstalled: hosted && !options.ssh,
paths: {
php: ".:./vendor",
},
});
}

9
node_modules/c9/gce.js wygenerowano vendored
Wyświetl plik

@ -24,12 +24,15 @@ function runCommand(pattern, command, options, callback) {
return runCommand(pattern, command, {}, options);
}
var parallel = ""
var optionsArray = [];
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) {
return callback(err, stdout);
});

45
node_modules/c9/ratelimit.js wygenerowano vendored
Wyświetl plik

@ -1,4 +1,7 @@
var error = require("http-error");
var _ = require("lodash");
var MAX_EXPIRE_INTERVAL = 5000;
/**
* In memory rate limiter as connect middleware
@ -6,27 +9,39 @@ var error = require("http-error");
module.exports = ratelimit;
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) {
var handle = req.params[key];
var lim = limit[handle] || (limit[handle] = []);
var now = Date.now();
for (var i = 0; i < lim.length; i++) {
if (now - lim[i] > duration) {
lim.splice(i, 1);
i--;
}
else break;
}
if (lim.length > max) {
requests[handle] = requests[handle] || [];
if (requests[handle].length >= max) {
var err = new error.TooManyRequests("Rate limit exceeded");
err.retryIn = duration - (Date.now() - lim[0]);
next(err);
return;
err.retryIn = Math.min(duration, 5000);
return next(err);
}
lim.push(Date.now());
requests[handle].push(Date.now());
return next();
};
}

104
node_modules/c9/ratelimit_test.js wygenerowano vendored 100644
Wyświetl plik

@ -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);
});
});

4
node_modules/c9/scm_url_parse.js wygenerowano vendored
Wyświetl plik

@ -13,6 +13,7 @@ define(function(require, exports, module) {
"bitbucket.org": "bitbucket",
"github.com": "github",
"source.developers.google.com": "google",
"gitlab.com": "gitlab",
};
var defaultProvider = "unknown";
@ -75,6 +76,9 @@ define(function(require, exports, module) {
case "bitbucket":
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
break;
case "gitlab":
scm = "git";
break;
default:
scm = parsed.pathname.match(/\.git$/) ? "git": "hg";
}

99
node_modules/c9/scm_url_parse_test.js wygenerowano vendored
Wyświetl plik

@ -16,57 +16,60 @@ describe(__filename, function() {
describe("#parse", function() {
it("should parse ssh url", function(done) {
var url = parse("git@github.com:fjakobs/lispjs.git");
assert.equal(url.scm, "git");
assert.equal(url.protocol, "ssh:");
assert.equal(url.auth, "git");
assert.equal(url.hostname, "github.com");
assert.equal(url.pathname, "fjakobs/lispjs.git");
done();
var url = parse("git@github.com:fjakobs/lispjs.git");
assert.equal(url.scm, "git");
assert.equal(url.protocol, "ssh:");
assert.equal(url.provider, "github");
assert.equal(url.auth, "git");
assert.equal(url.hostname, "github.com");
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) {
var url = parse("git://github.com/fjakobs/lispjs.git");
assert.equal(url.scm, "git");
assert.equal(url.protocol, "git:");
assert.equal(url.hostname, "github.com");
assert.equal(url.pathname, "fjakobs/lispjs.git");
done();
it("should parse https url", function(done) {
var url = parse("https://fjakobs@github.com/fjakobs/lispjs.git");
assert.equal(url.protocol, "https:");
assert.equal(url.scm, "git");
assert.equal(url.auth, "fjakobs");
assert.equal(url.provider, "github");
assert.equal(url.hostname, "github.com");
assert.equal(url.pathname, "fjakobs/lispjs.git");
done();
}),
}),
it("should parse https url", function(done) {
var url = parse("https://fjakobs@github.com/fjakobs/lispjs.git");
assert.equal(url.protocol, "https:");
assert.equal(url.scm, "git");
assert.equal(url.auth, "fjakobs");
assert.equal(url.hostname, "github.com");
assert.equal(url.pathname, "fjakobs/lispjs.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 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.provider, "bitbucket");
assert.equal(url.hostname, "bitbucket.org");
assert.equal(url.pathname, "Richard/expressling.git");
done();
});
it("should parse Bitbucket hg ssh url", function(done) {
var url = parse("ssh://hg@bitbucket.org/fjakobs/juhu");
assert.equal(url.protocol, "ssh:");
assert.equal(url.scm, "hg");
assert.equal(url.provider, "bitbucket");
assert.equal(url.hostname, "bitbucket.org");
assert.equal(url.pathname, "fjakobs/juhu");
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");
assert.equal(url.protocol, "https:");
assert.equal(url.scm, "git");
@ -76,7 +79,27 @@ describe(__filename, function() {
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 = [
"https://github.com/arunoda/meteor-streams",
"https://fjakobs@github.com/fjakobs/lispjs.git",

Wyświetl plik

@ -39,7 +39,7 @@ module.exports = function setup(mount, vfs, mountOptions) {
if (path) {
entry.href = path + entry.name;
var mime = entry.linkStat ? entry.linkStat.mime : entry.mime;
if (mime && mime.match(/(directory|folder)$/)) {
if (/(directory|folder)$/.test(mime)) {
entry.href += "/";
}
}

10
node_modules/vfs-local/localfs.js wygenerowano vendored
Wyświetl plik

@ -9,7 +9,15 @@ var pathBasename = require("path").basename;
var dirname = require("path").dirname;
var basename = require("path").basename;
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 exists = fs.exists || require("path").exists;
var crypto = require("crypto");

Wyświetl plik

@ -1,7 +1,7 @@
{
"name": "c9",
"description": "New Cloud9 Client",
"version": "3.1.2362",
"version": "3.1.2495",
"author": "Ajax.org B.V. <info@ajax.org>",
"private": true,
"main": "bin/c9",
@ -58,7 +58,7 @@
"c9"
],
"c9plugins": {
"c9.ide.language": "#ebc064ef16",
"c9.ide.language": "#79bcb2fe06",
"c9.ide.language.css": "#be07d72209",
"c9.ide.language.generic": "#3949510863",
"c9.ide.language.html": "#22fdc74869",
@ -66,16 +66,16 @@
"c9.ide.language.javascript": "#e626169643",
"c9.ide.language.javascript.immediate": "#c8b1e5767a",
"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.jsonalyzer": "#d8183d84b4",
"c9.ide.language.codeintel": "#e92ace1a56",
"c9.ide.collab": "#cf93793700",
"c9.ide.language.codeintel": "#fc867feec4",
"c9.ide.collab": "#1c0f841985",
"c9.ide.local": "#10eb45842a",
"c9.ide.find": "#e33fbaed2f",
"c9.ide.find.infiles": "#c0a13737ef",
"c9.ide.find.replace": "#810ebf8bfb",
"c9.ide.run.debug": "#9acb7f3178",
"c9.ide.run.debug": "#3206c81cd4",
"c9.automate": "#47e2c429c9",
"c9.ide.ace.emmet": "#6dc4585e02",
"c9.ide.ace.gotoline": "#a8ff07c8f4",
@ -94,7 +94,7 @@
"c9.ide.imgeditor": "#612e75ef4f",
"c9.ide.immediate": "#0e0c18066c",
"c9.ide.installer": "#b2e4ba0a92",
"c9.ide.language.python": "#6572da93c1",
"c9.ide.language.python": "#aff0772c78",
"c9.ide.language.go": "#6ce1c7a7ef",
"c9.ide.mount": "#4c39359b87",
"c9.ide.navigate": "#5d5707058c",

Wyświetl plik

@ -30,85 +30,43 @@ define(function(require, exports, module) {
return '"' + name + '"';
};
var SupportedIcons = {
"c9search": "page_white_magnify",
"js": "page_white_code",
"jsx": "page_white_code_red",
"ts": "page_white_code",
"tsx": "page_white_code_red",
"json": "page_white_code",
"css": "css",
"scss": "css",
"sass": "css",
"less": "css",
"xml": "page_white_code_red",
"svg": "page_white_picture",
"php": "page_white_php",
"phtml": "page_white_php",
"html": "html",
"xhtml": "html",
"coffee": "page_white_cup",
"py": "page_white_code",
"go": "page_white_code",
"java": "page_white_cup",
"logic": "logiql",
"ru": "page_white_ruby",
"gemspec": "page_white_ruby",
"rake": "page_white_ruby",
"rb": "page_white_ruby",
"c": "page_white_c",
"cc": "page_white_c",
"cpp": "page_white_cplusplus",
"cxx": "page_white_c",
"h": "page_white_h",
"hh": "page_white_h",
"hpp": "page_white_h",
"bmp": "image",
"djv": "image",
"djvu": "image",
"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",
};
var SupportedIcons = (function() {
var extToClass = Object.create(null);
var classToExt = {
"page_white_magnify": "c9search",
"page_white_code": ["clj", "go", "js", "json", "ml", "mli", "py", "ts", "xq"],
"page_white_code_red": ["jsx", "tsx", "xml"],
"css": ["css", "less", "sass", "scss"],
"page_white_picture": "svg",
"page_white_php": ["php", "phtml"],
"html": ["html", "xhtml"],
"page_white_cup": ["coffee", "java"],
"logiql": "logic",
"page_white_ruby": ["gemspec", "rake", "rb", "ru"],
"page_white_c": ["c", "cc", "cxx"],
"page_white_cplusplus": "cpp",
"page_white_h": ["h", "hh", "hpp"],
"image": ["bmp", "djv", "djvu", "gif", "ico", "jpeg", "jpg", "pbm", "pgm", "png", "pnm", "ppm", "psd", "svgz", "tif", "tiff", "xbm", "xpm"],
"page_white_acrobat": "pdf",
"page_white_coldfusion": "cfm",
"page_white_database": ["db", "sql"],
"page_white_wrench": ["bash", "sh"],
"page_white_zip": ["bz", "gz", "tar", "xz", "zip"],
"page_white_compressed": "rar",
"page_white_swoosh": ["exe", "lnk", "o", "bin", "class"],
"page_white_text": "txt",
"page_white_gear": ["bashrc", "build", "gitignore", "profile", "run", "settings"]
};
Object.keys(classToExt).forEach(function(k) {
var exts = classToExt[k];
if (typeof exts == "string")
exts = [exts];
exts.forEach(function(ext) {
extToClass[ext] = k;
});
});
return extToClass;
})();
plugin.getFileIcon = function(name) {
var icon = "page_white_text";
var ext;

Wyświetl plik

@ -13,7 +13,7 @@
</p>
<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">Home</a>
</div>

Wyświetl plik

@ -13,7 +13,7 @@
</p>
<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/">Home</a>
</div>

Wyświetl plik

@ -30,7 +30,7 @@
<% } %>
<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/">Home</a>
</div>

Wyświetl plik

@ -29,7 +29,7 @@
<% } %>
<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/">Home</a>
</div>

Wyświetl plik

@ -27,7 +27,7 @@
<% } %>
<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">Home</a>
</div>

Wyświetl plik

@ -707,7 +707,7 @@ define(function(require, exports, module) {
status: "pending",
className: "projectRoot",
isEditable: false,
map: {}
map: Object.create(null)
};
var root = {};
root.map = Object.create(null);

Wyświetl plik

@ -0,0 +1 @@
e

Wyświetl plik

@ -0,0 +1 @@
v

Wyświetl plik

@ -0,0 +1 @@
i

Wyświetl plik

@ -0,0 +1 @@
l

Wyświetl plik

@ -2,7 +2,7 @@ define(function(require, exports, module) {
"use strict";
main.consumes = [
"Plugin", "c9", "ui", "menus", "tree", "info", "vfs"
"Plugin", "c9", "ui", "menus", "tree", "info", "vfs", "preferences", "settings"
];
main.provides = ["download"];
return main;
@ -15,7 +15,12 @@ define(function(require, exports, module) {
var tree = imports.tree;
var vfs = imports.vfs;
var info = imports.info;
var prefs = imports.preferences;
var settings = imports.settings;
var SETTING_NAME = "downloadFilesAs";
var SETTING_PATH = "user/general/@" + SETTING_NAME;
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
@ -40,6 +45,28 @@ define(function(require, exports, module) {
onclick: download
}), 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() {
@ -55,25 +82,40 @@ define(function(require, exports, module) {
if (node.isFolder && node.path == "/")
downloadProject();
else if (paths.length > 1)
vfs.download(paths);
downloadPaths(paths);
else if (node.isFolder)
downloadFolder(node.path);
else
downloadFile(node.path);
}
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) {
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) {
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 *****/

Wyświetl plik

@ -88,9 +88,11 @@ define(function(require, exports, module) {
}]);
statics.addStatics(externalPlugins.map(function(plugin) {
if (typeof plugin == "string")
plugin = { path: plugin, mount: plugin};
return {
path: __dirname + "/../../node_modules/" + plugin,
mount: "/plugins/" + plugin
path: __dirname + "/../../node_modules/" + plugin.path,
mount: "/plugins/" + plugin.mount
};
}));

Wyświetl plik

@ -12,7 +12,7 @@
</p>
<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">Home</a>
</div>

Wyświetl plik

@ -209,6 +209,7 @@ define(function(require, exports, module) {
}
function reconnect(callback) {
if (!connection) return;
connection.socket.setSocket(null);
vfsEndpoint.get(protocolVersion, function(err, urls) {
@ -336,6 +337,11 @@ define(function(require, exports, module) {
plugin.on("unload", function(){
loaded = false;
if (consumer)
consumer.disconnect();
if (connection)
connection.disconnect();
id = null;
buffer = [];
region = null;
@ -346,6 +352,7 @@ define(function(require, exports, module) {
serviceUrl = null;
eioOptions = null;
consumer = null;
connection = null;
vfs = null;
showErrorTimer = null;
showErrorTimerMessage = null;

Wyświetl plik

@ -80,41 +80,62 @@ define(function(require, exports, module) {
});
}
else {
// TODO add support for downloding as zip on windows
// 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", "-"];
paths.forEach(function(path) {
var executable, args, contentType;
if (/\.zip$/.test(filename)) {
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;
var dir = Path.dirname(path);
var name = Path.basename(path);
if (name[0] == "-")
name = "--add-file=" + name;
args.push("-C" + dir, name);
if (!cwd) {
cwd = dir;
}
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)
return next(err);
process = meta.process;
// once we receive data on stdout pipe it to the response
// once we receive data on stdout pipe it to the response
process.stdout.once("data", function (data) {
if (res.headerSent)
return;
res.writeHead(200, {
"Content-Type": "application/x-gzip",
"Content-Type": contentType,
"Content-Disposition": filenameHeader
});
res.write(data);
@ -125,7 +146,7 @@ define(function(require, exports, module) {
process.stderr.on("data", function (data) {
stderr += data;
});
process.on("exit", function(code, signal) {
if (res.headerSent)
return;
@ -133,16 +154,16 @@ define(function(require, exports, module) {
var err;
if (code == 127) {
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" +
" 'sudo apt-get install tar'");
" 'sudo apt-get install " + executable + "'");
} else if (code) {
err = new error.InternalServerError(
"'tar' utility failed with exit code " + code +
"'" + executable + "' utility failed with exit code " + code +
" and stderr:/n'" + stderr + "'");
} else if (signal) {
err = new error.InternalServerError(
"'tar' utility was terminated by signal " + signal
"'" + executable + "' utility was terminated by signal " + signal
);
}

Wyświetl plik

@ -53,8 +53,9 @@ describe(__filename, function(){
describe("download", function() {
it("should download", function(next) {
it("should download as tar", function(next) {
tmp.dir({unsafeCleanup: true}, function(err, path) {
path = path.replace(/\w:/, '');
var filename = path + "/download.tar.gz";
var file = fs.createWriteStream(filename);
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) {
path = path.replace(/\w:/, '');
assert.equal(err, null);
var filename = path + "/download.tar.gz";
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.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(
fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"),
fs.readFileSync(path + "/views/status.html.ejs", "utf8")
fs.readFileSync(__dirname + "/test/dir1/testdata1.txt", "utf8"),
fs.readFileSync(path + "/test/dir1/testdata1.txt", "utf8")
);
next();
});
@ -102,22 +104,180 @@ describe(__filename, function(){
it("should download without specifying a name", 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/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-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.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(
fs.readFileSync(__dirname + "/views/status.html.ejs", "utf8"),
fs.readFileSync(path + "/views/status.html.ejs", "utf8")
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 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();
});

Wyświetl plik

@ -0,0 +1 @@
test data 1

Wyświetl plik

@ -0,0 +1 @@
test data 2a

Wyświetl plik

@ -0,0 +1 @@
test data 2b

Wyświetl plik

@ -271,6 +271,7 @@
return cb();
setTimeout.paused = true;
window.app.services.vfs.connection.disconnect();
window.app.services["vfs.endpoint"].clearCache();
setTimeout.force(function() {
setTimeout.paused = false;
setTimeout.clear();