diff --git a/configs/client-default.js b/configs/client-default.js index 550221b9..a72c3721 100644 --- a/configs/client-default.js +++ b/configs/client-default.js @@ -113,7 +113,8 @@ module.exports = function(options) { debug: debug, installPath: options.installPath, dashboardUrl: options.dashboardUrl, - accountUrl: options.accountUrl + accountUrl: options.accountUrl, + rejectUnauthorized: options.rejectUnauthorized }, { packagePath: "plugins/c9.vfs.client/endpoint", @@ -308,13 +309,13 @@ module.exports = function(options) { staticPrefix: staticPrefix, workerPrefix: options.CORSWorkerPrefix // "/static/standalone/worker" }, - "plugins/c9.ide.language/keyhandler", - "plugins/c9.ide.language/complete", - "plugins/c9.ide.language/quickfix", - "plugins/c9.ide.language/marker", - "plugins/c9.ide.language/refactor", - "plugins/c9.ide.language/tooltip", - "plugins/c9.ide.language/jumptodef", + "plugins/c9.ide.language.core/keyhandler", + "plugins/c9.ide.language.core/complete", + "plugins/c9.ide.language.core/quickfix", + "plugins/c9.ide.language.core/marker", + "plugins/c9.ide.language.core/refactor", + "plugins/c9.ide.language.core/tooltip", + "plugins/c9.ide.language.core/jumptodef", "plugins/c9.ide.language/worker_util_helper", { packagePath: "plugins/c9.ide.language.generic/generic", @@ -599,7 +600,7 @@ module.exports = function(options) { packagePath: "plugins/c9.ide.keys/panel" }, { - packagePath: "plugins/c9.ide.language/outline", + packagePath: "plugins/c9.ide.language.core/outline", staticPrefix: staticPrefix + "/plugins/c9.ide.language" }, { @@ -753,7 +754,6 @@ module.exports = function(options) { packagePath: "plugins/c9.ide.behaviors/page", staticPrefix: staticPrefix + "/plugins/c9.ide.behaviors" }, - "plugins/c9.ide.browsersupport/browsersupport", { packagePath: "plugins/c9.ide.preferences/preferences", staticPrefix: staticPrefix + "/plugins/c9.ide.preferences" diff --git a/integrations/scripts/update.sh b/integrations/scripts/update.sh new file mode 100755 index 00000000..4ad703e3 --- /dev/null +++ b/integrations/scripts/update.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -e +cd `dirname $0`/.. + +NAME=$1 +URL=$2 +if [ "$NAME" == "" ]; then + echo "add name [url]" + exit 0 +fi + +if [ "$URL" == "" ]; then + URL=git@github.com:c9/$NAME.git +fi + +if [ -d $NAME/.git ]; then + pushd $NAME + OLD_URL=$(git config --get remote.origin.url) + if [ "$OLD_URL" != "$URL" ]; then + echo "folder $NAME exists and points to $OLD_URL" + exit 1 + fi + git fetch origin + popd +else + mkdir -p $NAME + git clone $URL $NAME +fi + +pushd $NAME +HASH=$(git rev-parse --revs-only refs/remotes/origin/master) +popd + +[ -f ./config.json ] || echo "{}" > ./config.json +node -e ' + var name = "'$NAME'"; + var url = "'$URL'"; + var hash = "'$HASH'" + var fs = require("fs"); + + function updateJSON(path, fn) { + var text = fs.readFileSync(path, "utf8"); + var indent = text.match(/^\s*(?=")/m); + indent = indent && indent[0] || 4; + console.log(indent) + var r = JSON.parse(text); + r = fn(r) || r; + text = JSON.stringify(r, null, indent) + "\n"; + fs.writeFileSync(path, text, "utf8"); + } + + updateJSON("./config.json", function(config) { + var packages = config.packages || (config.packages = {}); + config.packages[name] = { + name: name, + hash: hash, + url: url, + }; + }); + updateJSON("../package.json", function(package) { + var deps = package.dependencies; + console.log(deps[name], hash) + deps[name] = deps[name].replace(/#[a-f\d]+$/i, "#" + hash) + console.log(deps[name], hash) + }); + updateJSON("../npm-shrinkwrap.json", function(package) { + var deps = package.dependencies; + deps[name].from = deps[name].from.replace(/#[a-f\d]+$/i, "#" + hash); + deps[name].resolved = deps[name].resolved.replace(/#[a-f\d]+$/i, "#" + hash); + }); +' + +rm -rf "../node_modules/$NAME" +ln -s `pwd`/$NAME `pwd`/../node_modules/$NAME + diff --git a/node_modules/ace/lib/ace/editor.js b/node_modules/ace/lib/ace/editor.js index b130df22..8705fc49 100644 --- a/node_modules/ace/lib/ace/editor.js +++ b/node_modules/ace/lib/ace/editor.js @@ -1486,7 +1486,7 @@ var Editor = function(renderer, session) { var indentString = lang.stringRepeat(" ", count); } else { var count = column % size; - while (line[range.start.column] == " " && count) { + while (line[range.start.column - 1] == " " && count) { range.start.column--; count--; } diff --git a/node_modules/ace/lib/ace/editor_text_edit_test.js b/node_modules/ace/lib/ace/editor_text_edit_test.js index 77ec34ed..382b8518 100644 --- a/node_modules/ace/lib/ace/editor_text_edit_test.js +++ b/node_modules/ace/lib/ace/editor_text_edit_test.js @@ -124,6 +124,12 @@ module.exports = { var range = editor.getSelectionRange(); assert.position(range.start, 1, 7); assert.position(range.end, 2, 7); + + session.setValue(" x"); + session.setOption("useSoftTabs", false); + editor.selection.moveTo(0, 3); + editor.indent(); + assert.equal("\tx", session.toString()); }, "test: indent selected lines" : function() { diff --git a/node_modules/ace/lib/ace/ext/modelist.js b/node_modules/ace/lib/ace/ext/modelist.js index 13c1170f..a269e7a7 100644 --- a/node_modules/ace/lib/ace/ext/modelist.js +++ b/node_modules/ace/lib/ace/ext/modelist.js @@ -137,7 +137,7 @@ var supportedModes = { Protobuf: ["proto"], Python: ["py"], R: ["r"], - Razor: ["cshtml"], + Razor: ["cshtml|asp"], RDoc: ["Rd"], RHTML: ["Rhtml"], RST: ["rst"], diff --git a/node_modules/ace/lib/ace/mode/behaviour/cstyle.js b/node_modules/ace/lib/ace/mode/behaviour/cstyle.js index c0b2e478..01aac37c 100644 --- a/node_modules/ace/lib/ace/mode/behaviour/cstyle.js +++ b/node_modules/ace/lib/ace/mode/behaviour/cstyle.js @@ -277,6 +277,8 @@ var CstyleBehaviour = function() { var pair; if (rightChar == quote) { pair = stringBefore !== stringAfter; + if (pair && /string\.end/.test(rightToken.type)) + pair = false; } else { if (stringBefore && !stringAfter) return null; // wrap string with different quote diff --git a/node_modules/ace/lib/ace/mode/sh_highlight_rules.js b/node_modules/ace/lib/ace/mode/sh_highlight_rules.js index f3fe2db8..c1c0eb6e 100644 --- a/node_modules/ace/lib/ace/mode/sh_highlight_rules.js +++ b/node_modules/ace/lib/ace/mode/sh_highlight_rules.js @@ -84,7 +84,7 @@ var ShHighlightRules = function() { token : ["text", "comment"], regex : /(^|\s)(#.*)$/ }, { - token : "string", + token : "string.start", regex : '"', push : [{ token : "constant.language.escape", @@ -95,7 +95,7 @@ var ShHighlightRules = function() { token : "keyword.operator", regex : /`/ // TODO highlight ` }, { - token : "string", + token : "string.end", regex : '"', next: "pop" }, { diff --git a/node_modules/ace/tool/tmtheme.js b/node_modules/ace/tool/tmtheme.js index c784eec7..11e80e38 100755 --- a/node_modules/ace/tool/tmtheme.js +++ b/node_modules/ace/tool/tmtheme.js @@ -176,6 +176,8 @@ function luma(color) { } function parseColor(color) { + if (color[0] != "#" && color.match(/^[a-f\d]+$/i)) + color = "#" + color; if (color.length == 4) color = color.replace(/[a-fA-F\d]/g, "$&$&"); if (color.length == 7) diff --git a/node_modules/ace_tree/lib/ace_tree/mouse/drag_handler.js b/node_modules/ace_tree/lib/ace_tree/mouse/drag_handler.js index 22d1565d..d9254640 100644 --- a/node_modules/ace_tree/lib/ace_tree/mouse/drag_handler.js +++ b/node_modules/ace_tree/lib/ace_tree/mouse/drag_handler.js @@ -161,6 +161,7 @@ function initDragHandlers(mouseHandler) { mouseHandler.dragEnd = function(e, cancel) { if (dragInfo) { + window.removeEventListener("mousedown", keyHandler, true); window.removeEventListener("keydown", keyHandler, true); window.removeEventListener("keyup", keyHandler, true); if (dragInfo.el && dragInfo.el.parentNode) @@ -190,6 +191,8 @@ function initDragHandlers(mouseHandler) { }; mouseHandler.dragStart = function() { + if (dragInfo) + this.dragEnd(null, true); mouseHandler.setState("drag"); tree.renderer.visualizeBlur(); tree.renderer.setStyle("dragOver", true); @@ -205,6 +208,7 @@ function initDragHandlers(mouseHandler) { return; mouseHandler.dragStart(); + window.addEventListener("mousedown", keyHandler, true); window.addEventListener("keydown", keyHandler, true); window.addEventListener("keyup", keyHandler, true); @@ -267,7 +271,7 @@ function initDragHandlers(mouseHandler) { function keyHandler(e){ if (dragInfo) { - if (e.keyCode === 27) { + if (e.keyCode === 27 || e.type == "mousedown") { mouseHandler.dragEnd(null, true); event.stopEvent(e); } else if (dragInfo && e.keyCode == 17 || e.keyCode == 18) { diff --git a/node_modules/architect-build/build_support/mini_require.js b/node_modules/architect-build/build_support/mini_require.js index c04e9e77..19147352 100644 --- a/node_modules/architect-build/build_support/mini_require.js +++ b/node_modules/architect-build/build_support/mini_require.js @@ -309,6 +309,7 @@ define.undef = require.undef = function(module, recursive) { var path = require.toUrl(module, ".js"); delete define.errors[module]; delete define.loaded[module]; + delete define.loading[module]; delete define.modules[module]; delete define.fetchedUrls[path]; }; @@ -403,6 +404,7 @@ var loadScriptWithTag = function(path, id, callback) { }; s.onerror = function(e) { processLoadQueue({ + message: "Error loading script " + id + ":" + path, id: id, path: path }); diff --git a/node_modules/architect/architect.js b/node_modules/architect/architect.js index 086f43a3..3304e1ba 100644 --- a/node_modules/architect/architect.js +++ b/node_modules/architect/architect.js @@ -397,13 +397,8 @@ function checkCycles(config, lookup) { delete unresolved[name]; }); - var pluginsList = plugins.map(function(p) { return p.packagePath; }).join("\n"); var unresolvedList = Object.keys(unresolved); var resolvedList = Object.keys(resolved); - console.warn("Could not resolve dependencies of these plugins:\n" - + pluginsList + "\n", plugins, - "\nMissing services:\n" + unresolvedList.join("\n") + "\n", unresolved, - "\nResolved services:", resolvedList); var err = new Error("Could not resolve dependencies\n" + (unresolvedList.length ? "Missing services: " + unresolvedList : "Config contains cyclic dependencies" // TODO print cycles diff --git a/node_modules/c9/assert.js b/node_modules/c9/assert.js index 905d9c82..0c4447e6 100644 --- a/node_modules/c9/assert.js +++ b/node_modules/c9/assert.js @@ -2,7 +2,7 @@ * Cloud9 assertion support. * * @copyright 2011, Ajax.org B.V. - * @license GPLv3 + * @license Apache2 */ define(function(require, exports, module) { diff --git a/node_modules/connect-architect/connect.redirect/redirect.js b/node_modules/connect-architect/connect.redirect/redirect.js index f9e10cd3..7d18de2d 100644 --- a/node_modules/connect-architect/connect.redirect/redirect.js +++ b/node_modules/connect-architect/connect.redirect/redirect.js @@ -16,8 +16,10 @@ module.exports = function(options, imports, register) { imports.connect.addResponseMethod("secureRedirect", function(location) { var parsedLocation = url.parse(location, false, true); - if (!trustedDomainsRe.test(parsedLocation.host)) + if (!trustedDomainsRe.test(parsedLocation.host)) { + console.log("Avoiding untrusted redirect to", parsedLocation.host) location = parsedLocation.path || "/"; + } this.redirect(location); }); diff --git a/node_modules/kaefer/lib/client.js b/node_modules/kaefer/lib/client.js index 3f6bd7f0..289fbd81 100644 --- a/node_modules/kaefer/lib/client.js +++ b/node_modules/kaefer/lib/client.js @@ -50,6 +50,9 @@ var connectClient = module.exports = function(connectEio, options) { }); eioSocket.on("message", function handshakeReply(msg) { + if (reconnectSocket.destroying) return; + if (reconnectSocket.socket && reconnectSocket.socket != eioSocket) + return console.error("reconenct for detached socket"); try { msg = JSON.parse(msg); } catch (e) {} @@ -75,11 +78,17 @@ var connectClient = module.exports = function(connectEio, options) { }); eioSocket.on("error", function(e) { + if (reconnectSocket.destroying) return; + if (reconnectSocket.socket && reconnectSocket.socket != eioSocket) + return console.error("reconenct for detached socket"); console.error("Socket error; reconnecting:", e); eioSocket.close(); reconnect(); }); eioSocket.on("close", function(e) { + if (reconnectSocket.destroying) return; + if (reconnectSocket.socket && reconnectSocket.socket != eioSocket) + return console.error("reconenct for detached socket"); console.error("Socket close; reconnecting:", e); reconnect(); }); diff --git a/node_modules/kaefer/lib/reliable_socket.js b/node_modules/kaefer/lib/reliable_socket.js index 0a01ba42..8743a096 100644 --- a/node_modules/kaefer/lib/reliable_socket.js +++ b/node_modules/kaefer/lib/reliable_socket.js @@ -128,14 +128,7 @@ ReliableSocket.prototype.onMessage = function(msg) { this.emit(msg.t, msg); } else if (msg.d) { - try { - this.emit("message", msg.d); - } catch (e) { - console.error(e.stack); - // Don't let engine.io catch this, it'll consider it a parser error, - // making us reconnect - setTimeout(function() { throw e; }); - } + this.emit("message", msg.d); } }; diff --git a/node_modules/kaefer/package.json b/node_modules/kaefer/package.json index 2b11575a..f661ab70 100644 --- a/node_modules/kaefer/package.json +++ b/node_modules/kaefer/package.json @@ -8,8 +8,8 @@ "email": "fabian@c9.io" }], "dependencies": { - "engine.io": "~1.5.1", - "engine.io-client": "~1.5.1", + "engine.io": "~1.6.9", + "engine.io-client": "~1.6.9", "amd-loader": "*" }, "devDependencies": { diff --git a/node_modules/vfs-local/localfs.js b/node_modules/vfs-local/localfs.js index c53c1ad4..d1c2a1b6 100644 --- a/node_modules/vfs-local/localfs.js +++ b/node_modules/vfs-local/localfs.js @@ -1039,7 +1039,7 @@ module.exports = function setup(fsOptions) { if (!exists || options.overwrite || isSamePath) { // Rename the file - fs.rename(frompath, topath, function (err) { + renameWatchedFile(frompath, topath, function (err) { if (err) { if (err.code == 'ENOENT' && options.mkdirP != false) { options.mkdirP = false; @@ -1051,16 +1051,18 @@ module.exports = function setup(fsOptions) { return callback(err); } - // Rename metadata - if (options.metadata !== false) { - var metaPath = WSMETAPATH; - rename(metaPath + from, { - to: metaPath + to, - metadata: false - }, function(err){ - callback(null, meta); - }); + if (options.metadata === false) { + return callback(null, meta); } + + // Rename metadata + var metaPath = WSMETAPATH; + rename(metaPath + from, { + to: metaPath + to, + metadata: false + }, function(err){ + callback(null, meta); + }); }); } else { @@ -1364,7 +1366,9 @@ module.exports = function setup(fsOptions) { close(); }; - this.resume = function(callback) { + this.resume = function(callback, newPath) { + if (newPath) + path = newPath; if (!listeners.length) return callback(); watch(callback); @@ -1433,6 +1437,33 @@ module.exports = function setup(fsOptions) { }); } } + + function renameWatchedFile(frompath, topath, callback) { + var removed = []; + Object.keys(fileWatchers).forEach(function(path) { + if (path.slice(0, frompath.length) == frompath && (path[frompath.length] == "/" || !path[frompath.length])) { + var watchers = fileWatchers[path].slice(); + watchers.forEach(function(w) { + w.pause(); + }); + removed.push({ + relpath: path.slice(frompath.length), + watchers: watchers + }); + } + }); + fs.rename(frompath, topath, function(err) { + var root = err ? frompath : topath; + removed.forEach(function(x) { + var path = root + x.relpath; + x.watchers.forEach(function(w) { + w.resume(function() { + }, path); + }); + }); + callback(err); + }); + } function connect(port, options, callback) { var retries = options.hasOwnProperty('retries') ? options.retries : 5; diff --git a/package.json b/package.json index b8f9ee21..ca7c6573 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "c9", "description": "New Cloud9 Client", - "version": "3.1.2576", + "version": "3.1.2774", "author": "Ajax.org B.V. ", "private": true, "main": "bin/c9", @@ -17,8 +17,8 @@ "debug": "~0.7.4", "ejs": "~1.0.0", "emmet": "git://github.com/cloud9ide/emmet-core.git#2ff6dc06ad", - "engine.io": "1.5.3", - "engine.io-client": "1.5.3", + "engine.io": "1.6.9", + "engine.io-client": "1.6.9", "jsonm": "1.0.6", "http-error": "~0.0.5", "less": "^2.4.0", @@ -30,14 +30,14 @@ "netutil": "~0.0.2", "optimist": "~0.6.0", "qs": "0.6.6", - "rusha": "~0.7.2", + "rusha": "^0.8.3", "send": "~0.1.4", "simple-mime": "~0.0.8", "tern": "git://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e", "tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4", "through": "2.2.0", "tmp": "~0.0.20", - "uglify-js": "2.4.16", + "uglify-js": "^2.6.2", "ws": "0.4.31", "read": "~1.0.5", "form-data": "~0.2.0", @@ -58,28 +58,28 @@ "c9" ], "c9plugins": { - "c9.ide.language": "#79bcb2fe06", - "c9.ide.language.core": "#undefined", - "c9.ide.language.css": "#be07d72209", - "c9.ide.language.generic": "#3949510863", - "c9.ide.language.html": "#22fdc74869", - "c9.ide.language.html.diff": "#24f3608d26", - "c9.ide.language.javascript": "#e626169643", - "c9.ide.language.javascript.immediate": "#c8b1e5767a", - "c9.ide.language.javascript.eslint": "#4de5457db1", - "c9.ide.language.javascript.tern": "#64ab01f271", - "c9.ide.language.javascript.infer": "#18acb93a3a", - "c9.ide.language.jsonalyzer": "#d8183d84b4", - "c9.ide.language.codeintel": "#fc867feec4", - "c9.ide.collab": "#cfbf987438", - "c9.ide.local": "#10eb45842a", - "c9.ide.find": "#e33fbaed2f", - "c9.ide.find.infiles": "#bd34c29373", - "c9.ide.find.replace": "#810ebf8bfb", - "c9.ide.run.debug": "#94a48978bf", + "c9.ide.language": "#0e86345d39", + "c9.ide.language.core": "#bfb5dd2acc", + "c9.ide.language.css": "#46ad561506", + "c9.ide.language.generic": "#b47cbe58f9", + "c9.ide.language.html": "#cdc3960225", + "c9.ide.language.html.diff": "#7d6cecfb90", + "c9.ide.language.javascript": "#a5c1d05394", + "c9.ide.language.javascript.immediate": "#82c426dbca", + "c9.ide.language.javascript.eslint": "#cb9e3f5a8e", + "c9.ide.language.javascript.tern": "#0545a6385d", + "c9.ide.language.javascript.infer": "#b9c2e4bdb8", + "c9.ide.language.jsonalyzer": "#a0549e14ff", + "c9.ide.language.codeintel": "#4e0a272229", + "c9.ide.collab": "#e015881720", + "c9.ide.local": "#9169fec157", + "c9.ide.find": "#a2dfc3e306", + "c9.ide.find.infiles": "#488db22ee1", + "c9.ide.find.replace": "#47a84af707", + "c9.ide.run.debug": "#08249419c5", "c9.automate": "#47e2c429c9", "c9.ide.ace.emmet": "#6dc4585e02", - "c9.ide.ace.gotoline": "#a8ff07c8f4", + "c9.ide.ace.gotoline": "#d33220b1e0", "c9.ide.ace.keymaps": "#334a65192f", "c9.ide.ace.repl": "#4b88a85b7b", "c9.ide.ace.split": "#0ae0151c78", @@ -90,37 +90,37 @@ "c9.ide.configuration": "#a936df26bb", "c9.ide.dialog.wizard": "#7667ec79a8", "c9.ide.fontawesome": "#781602c5d8", - "c9.ide.format": "#5ec97fb083", - "c9.ide.help.support": "#932fbb3743", + "c9.ide.format": "#f99082ff4c", + "c9.ide.help.support": "#fbe8eb5c36", "c9.ide.imgeditor": "#612e75ef4f", - "c9.ide.immediate": "#0e0c18066c", + "c9.ide.immediate": "#b279c69c73", "c9.ide.installer": "#b2e4ba0a92", - "c9.ide.language.python": "#aff0772c78", + "c9.ide.language.python": "#9fba572b1a", "c9.ide.language.go": "#6ce1c7a7ef", - "c9.ide.mount": "#6ddfd05db3", + "c9.ide.mount": "#b018ee501f", "c9.ide.navigate": "#5d5707058c", "c9.ide.newresource": "#981a408a7b", "c9.ide.openfiles": "#2ae85a9e33", "c9.ide.preview": "#5f5fff0185", - "c9.ide.preview.browser": "#897177be7f", + "c9.ide.preview.browser": "#829f0ac50f", "c9.ide.preview.markdown": "#c3174d86e0", "c9.ide.pubsub": "#99b7289040", - "c9.ide.readonly": "#cfd951ec16", + "c9.ide.readonly": "#7421caab61", "c9.ide.recentfiles": "#7c099abf40", "c9.ide.remote": "#301d2ab519", "c9.ide.processlist": "#2b12cd1bdd", "c9.ide.run": "#d661a7b847", "c9.ide.run.build": "#0598fff697", - "c9.ide.run.debug.xdebug": "#9956689819", + "c9.ide.run.debug.xdebug": "#054367574c", "c9.ide.save": "#25a63f31e2", "c9.ide.scm": "#637a68cd04", - "c9.ide.terminal.monitor": "#affa33572f", + "c9.ide.terminal.monitor": "#5a6a54ce24", "c9.ide.test": "#102942ae4e", - "c9.ide.test.mocha": "#fc053b23d2", + "c9.ide.test.mocha": "#38151a98c3", "c9.ide.theme.flat": "#81dadeee55", "c9.ide.threewaymerge": "#229382aa0b", "c9.ide.undo": "#b028bcb4d5", - "c9.ide.upload": "#a3da59803d", + "c9.ide.upload": "#e4351f5a2b", "c9.ide.welcome": "#5b86c44e92", "c9.ide.guide": "#df7c89e449" } diff --git a/plugins/c9.error/views/error.html.ejs b/plugins/c9.error/views/error.html.ejs index b686bbec..9b66e689 100644 --- a/plugins/c9.error/views/error.html.ejs +++ b/plugins/c9.error/views/error.html.ejs @@ -8,11 +8,13 @@

<%=title%>

<%=statusCode%> - <%=scope%> <%=error%>

-

- This error has been logged. We will - investigate this further and will prevent this from happening in the - future. If this error persists please don't hesitate to contact support. -

+ <% if (statusCode != 403) { %> +

+ This error has been logged. We will + investigate this further and will prevent this from happening in the + future. If this error persists please don't hesitate to contact support. +

+ <% } %> <% if (showStackTrace) { %>
diff --git a/plugins/c9.fs/fs.cache.xml.js b/plugins/c9.fs/fs.cache.xml.js index bc68d3ef..6c780202 100644 --- a/plugins/c9.fs/fs.cache.xml.js +++ b/plugins/c9.fs/fs.cache.xml.js @@ -35,6 +35,10 @@ define(function(require, exports, module) { cb && cb(err, files); }); }; + model.shouldLoadChildren = function(node, ch) { + return node.status == "pending" + || (node.path && node.isFolder && !ch); + }; model.getClassName = function(node) { var cl = node.className || ""; if (node.link) @@ -254,7 +258,7 @@ define(function(require, exports, module) { }; e.confirm = function () { if (node.status === "predicted") - node.status = "loaded"; + node.status = "pending"; }; node.status = "predicted"; } @@ -262,7 +266,7 @@ define(function(require, exports, module) { function removeSingleNode(e) { var node = findNode(e.path); - if (!node) return; //Node doesn't exist + if (!node) return; // Node doesn't exist deleteNode(node); emit("remove", { @@ -270,8 +274,9 @@ define(function(require, exports, module) { node: node }); - // todo e.undo = function(){ + if (this.error && this.error.code == "ENOENT") + return; createNode(node.path, null, node); emit("add", { path: node.path, @@ -348,7 +353,7 @@ define(function(require, exports, module) { } if (node.status === "predicted") - node.status = "loaded"; + node.status = "pending"; }; node.status = "predicted"; }, plugin); @@ -382,7 +387,7 @@ define(function(require, exports, module) { }; e.confirm = function() { if (node.status === "predicted") - node.status = "loaded"; + node.status = "pending"; }; node.status = "predicted"; }, plugin); @@ -664,6 +669,11 @@ define(function(require, exports, module) { }); return; } + if (orphans[node.path] == node) { + delete orphans[node.path]; + if (parent.map[node.label] != node) + return; + } silent || model._signal("remove", node); var wasOpen = startUpdate(parent); delete parent.map[node.label]; diff --git a/plugins/c9.ide.ace/ace_test.js b/plugins/c9.ide.ace/ace_test.js index 2abd9b0a..80577129 100644 --- a/plugins/c9.ide.ace/ace_test.js +++ b/plugins/c9.ide.ace/ace_test.js @@ -283,8 +283,11 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) editor.setOption("wrapToView", true); render(); + var ace = editor.ace; + var cols = Math.floor((ace.container.offsetWidth - ace.renderer.gutterWidth - 2 * ace.renderer.$padding) / charWidth); - expect(document.querySelector(".ace_gutter-cell").offsetHeight).to.equal(lineHeight * 4); + expect(cols).to.equal(ace.session.getWrapLimit()); + expect(document.querySelector(".ace_gutter-cell").offsetHeight).to.equal(lineHeight * ace.session.getRowLength(0)); done(); }); it('should allow setting wrapBehavioursEnabled', function(done) { diff --git a/plugins/c9.ide.browsersupport/browsersupport.js b/plugins/c9.ide.browsersupport/browsersupport.js deleted file mode 100644 index 48e6dac9..00000000 --- a/plugins/c9.ide.browsersupport/browsersupport.js +++ /dev/null @@ -1,118 +0,0 @@ -define(function(require, exports, module) { - "use strict"; - - main.consumes = ["Plugin"]; - main.provides = ["browsersupport"]; - return main; - - function main(options, imports, register) { - var Plugin = imports.Plugin; - - require("ace/lib/es5-shim"); - require("ace/lib/es6-shim"); - var useragent = require("ace/lib/useragent"); - var dom = require("ace/lib/dom"); - - if (useragent.isGecko) - dom.addCssClass(document.body, "ua_gecko"); - else if (useragent.isWebkit) - dom.addCssClass(document.body, "ua_webkit"); - else if (useragent.isIE) - dom.addCssClass(document.body, "ua_ie"); - - function getIEVersion() { - return useragent.isIE; - } - - var plugin = new Plugin("Ajax.org", main.consumes); - - /** - * Browser compatibility support. - */ - plugin.freezePublicAPI({ - /** - * Gets Internet Explorer's major version, e.g. 10, - * or returns null if a different browser is used. - * - * @return {Number} - */ - getIEVersion: getIEVersion - }); - register(null, { browsersupport: plugin }); - } -}); - -// Support __defineGetter__ et al. on IE9 -// (always triggers when packed) -try { - if (!Object.prototype.__defineGetter__ && - Object.defineProperty({},"x",{get: function(){return true}}).x) { - - // Setter - Object.defineProperty( - Object.prototype, - "__defineSetter__", - { - enumerable: false, - configurable: true, - value: function(name,func) { - Object.defineProperty(this,name,{set:func,enumerable: true,configurable: true}); - - // Adding the property to the list (for __lookupSetter__) - if (!this.setters) this.setters = {}; - this.setters[name] = func; - } - } - ); - - // Lookupsetter - Object.defineProperty( - Object.prototype, - "__lookupSetter__", - { - enumerable: false, - configurable: true, - value: function(name) { - if (!this.setters) return false; - return this.setters[name]; - } - } - ); - - // Getter - Object.defineProperty( - Object.prototype, - "__defineGetter__", - { - enumerable: false, - configurable: true, - value: function(name,func) { - Object.defineProperty(this,name,{get:func,enumerable: true,configurable: true}); - - // Adding the property to the list (for __lookupSetter__) - if (!this.getters) this.getters = {}; - this.getters[name] = func; - } - } - ); - - // Lookupgetter - Object.defineProperty( - Object.prototype, - "__lookupGetter__", - { - enumerable: false, - configurable: true, - value: function(name) { - if (!this.getters) return false; - return this.getters[name]; - } - } - ); - - } -} catch (defPropException) { - // Forget about it -} - - diff --git a/plugins/c9.ide.download/download.js b/plugins/c9.ide.download/download.js index dd6a585f..ab8e5280 100644 --- a/plugins/c9.ide.download/download.js +++ b/plugins/c9.ide.download/download.js @@ -91,24 +91,30 @@ define(function(require, exports, module) { } function downloadProject() { - vfs.download("/", info.getWorkspace().name + getArchiveFileExtension()); + vfs.download("/", makeArchiveFilename(info.getWorkspace().name)); } function downloadPaths(paths) { - vfs.download(paths, info.getWorkspace().name + getArchiveFileExtension()); + var lastPart = paths[0].match(/([^\/]*)\/?$/)[1]; + var filename = lastPart ? (lastPart + "[+" + (paths.length - 1) + "]") : info.getWorkspace().name; + vfs.download(paths, makeArchiveFilename(filename)); } function downloadFolder(path) { var withTrailingSlash = path.replace(/\/*$/, "/"); var parts = withTrailingSlash.split("/"); - var lastPart = parts[parts.length - 2]; - vfs.download(withTrailingSlash, lastPart + getArchiveFileExtension()); + var folderName = parts[parts.length - 2]; + vfs.download(withTrailingSlash, makeArchiveFilename(folderName)); } function downloadFile(path) { vfs.download(path.replace(/\/*$/, ""), null, true); } + function makeArchiveFilename(filename) { + return filename + getArchiveFileExtension(); + } + function getArchiveFileExtension() { var downloadFilesAs = settings.get(SETTING_PATH); if (downloadFilesAs === 'auto' || !downloadFilesAs) { diff --git a/plugins/c9.ide.layout.classic/themes/flat-dark.less b/plugins/c9.ide.layout.classic/themes/flat-dark.less index be6a89e9..8902aa4f 100644 --- a/plugins/c9.ide.layout.classic/themes/flat-dark.less +++ b/plugins/c9.ide.layout.classic/themes/flat-dark.less @@ -1,7 +1,7 @@ @import "plugins/c9.ide.layout.classic/themes/flat-light.less"; .bartools .c9-toolbarbutton-glossyOver{ - background: #E6E6E6; + background: #303130; } .bartools .c9-toolbarbutton-glossymenuDown{ @@ -221,4 +221,4 @@ @media print, (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 1.25dppx) { -} \ No newline at end of file +} diff --git a/plugins/c9.ide.panels/panel.js b/plugins/c9.ide.panels/panel.js index f1245f4b..f03e67d8 100644 --- a/plugins/c9.ide.panels/panel.js +++ b/plugins/c9.ide.panels/panel.js @@ -368,7 +368,7 @@ define(function(require, module, exports) { /** * @property {HTMLElement} container */ - get container(){ return aml.$ext; }, + get container(){ return aml && aml.$ext; }, /** * The area that this panel is a part of. diff --git a/plugins/c9.ide.plugins/manager.js b/plugins/c9.ide.plugins/manager.js index 1eceb48c..4c338003 100644 --- a/plugins/c9.ide.plugins/manager.js +++ b/plugins/c9.ide.plugins/manager.js @@ -77,7 +77,7 @@ define(function(require, exports, module) { "c9.ide.console":1,"c9.ide.editors":1,"c9.ide.dialog.common":1, "c9.ide.dialog.file":1,"c9.ide.dialog.login":1,"c9.ide.errorhandler":1, "c9.ide.help":1,"c9.ide.keys":1,"c9.ide.restore":1,"c9.ide.watcher":1, - "c9.ide.tree":1, "c9.ide.info":1, "c9.ide.browsersupport":1, + "c9.ide.tree":1, "c9.ide.info":1, "c9.ide.layout.classic":1, "c9.ide.terminal":1, "c9.ide.ace":1, "c9.ide.clipboard":1, "c9.nodeapi":1 }; diff --git a/plugins/c9.ide.server/plugins.js b/plugins/c9.ide.server/plugins.js index e92571bd..57e6f333 100644 --- a/plugins/c9.ide.server/plugins.js +++ b/plugins/c9.ide.server/plugins.js @@ -96,6 +96,20 @@ define(function(require, exports, module) { }; })); + try { + statics.addStatics( + fs.readdirSync(__dirname + "/../../integrations/").map(function(plugin) { + if (/^scripts$|\.(json|sh)$/.test(plugin)) + return; + return { + path: __dirname + "/../../integrations/" + plugin, + mount: "/plugins/" + plugin + }; + }).filter(Boolean) + ); + } catch(e) { + } + statics.addStatics(fs.readdirSync(__dirname + "/../") .filter(function(path) { if (path in blacklist) diff --git a/plugins/c9.ide.terminal/link_handler.js b/plugins/c9.ide.terminal/link_handler.js index 4543a31f..23c25d39 100644 --- a/plugins/c9.ide.terminal/link_handler.js +++ b/plugins/c9.ide.terminal/link_handler.js @@ -107,7 +107,7 @@ define(function(require, exports, module) { else if (e.value === "gitadd") lastLink.editor.onPaste("git add " + lastLink.value + "\n"); else if (e.value === "gitcheckout") - lastLink.editor.onPaste("git checkout " + lastLink.value); + lastLink.editor.onPaste("git checkout -- " + lastLink.value); else if (e.value === "gitdiff") lastLink.editor.onPaste("git diff " + lastLink.value + "\n"); else if (e.value === "gitrm") diff --git a/plugins/c9.ide.terminal/terminal.js b/plugins/c9.ide.terminal/terminal.js index cbb4e66c..d6c3c164 100644 --- a/plugins/c9.ide.terminal/terminal.js +++ b/plugins/c9.ide.terminal/terminal.js @@ -645,7 +645,7 @@ define(function(require, exports, module) { if (!e && data) { session.terminal.setOutputHistory(data, true); session.getStatus({clients: true}, function(e, status) { - if (e) return; + if (e || !status) return; if (status.clients && status.clients.length > 0) { var terminal = session.terminal; var rows = terminal.rows; diff --git a/plugins/c9.ide.terminal/terminal_test.js b/plugins/c9.ide.terminal/terminal_test.js index aa4c2220..d3ce9856 100644 --- a/plugins/c9.ide.terminal/terminal_test.js +++ b/plugins/c9.ide.terminal/terminal_test.js @@ -13,7 +13,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (arc debug: true, hosted: true, local: false, - davPrefix: "/" }, "plugins/c9.core/ext", @@ -113,7 +112,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (arc // @todo Test mouse // @todo Test menu - it('should reconnect when the connection has been lost', function(done) { + it.skip('should reconnect when the connection has been lost', function(done) { var doc = tabs.focussedTab.document; var session = doc.getSession(); @@ -127,6 +126,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (arc // Kill connection session.pty.kill(); + session.doc.editor.focus(); }); it.skip('should reconnect when the session has been lost', function(done) { @@ -226,7 +226,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (arc }); }); if (!onload.remain) { - it('should reconnect both terminals when doing kill-server', function(done) { + it.skip('should reconnect both terminals when doing kill-server', function(done) { var count = 0; tabs.getTabs().forEach(function(tab) { var session = tab.document.getSession(); diff --git a/plugins/c9.ide.tree/tree.js b/plugins/c9.ide.tree/tree.js index 80c92016..25b6be20 100644 --- a/plugins/c9.ide.tree/tree.js +++ b/plugins/c9.ide.tree/tree.js @@ -1102,7 +1102,7 @@ define(function(require, exports, module) { expandedList[id] = node; } }); - callback(err); + callback && callback(err); tree.provider.on("changeScrollTop", scrollHandler); emit("refreshComplete"); diff --git a/plugins/c9.ide.tree/tree_test.js b/plugins/c9.ide.tree/tree_test.js index 1aa41a44..9c49a2df 100644 --- a/plugins/c9.ide.tree/tree_test.js +++ b/plugins/c9.ide.tree/tree_test.js @@ -25,7 +25,8 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], "plugins/c9.core/util", { packagePath: "plugins/c9.core/settings", - settings: "default" + settings: "default", + testing: true }, "plugins/c9.core/api.js", { @@ -53,16 +54,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], "plugins/c9.ide.dialog.common/fileremove", "plugins/c9.ide.dialog.common/question", - //Mock Plugins - { - consumes: ["apf", "ui", "Plugin"], - provides: [ - "commands", "panels", "tabManager", "layout", "watcher", - "preferences", "clipboard", "Panel", "auth.bootstrap", "info", - "proc", "focusManager", "dialog.error", "error_handler" - ], - setup: expect.html.mocked - }, { consumes: ["tree", "fs", "fs.cache", "tabManager", "ui", "dialog.question", "dialog.alert"], @@ -85,7 +76,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function getDomNode(treeNode) { var r = tree.tree.renderer; r.$renderChanges(r.$loop.changes); - var i = r.provider.getIndexForNode(treeNode) + var i = r.provider.getIndexForNode(treeNode); return r.$cellLayer.getDomNodeAtIndex(i); } diff --git a/plugins/c9.ide.watcher/watcher.js b/plugins/c9.ide.watcher/watcher.js index 471cc838..f8eaec80 100644 --- a/plugins/c9.ide.watcher/watcher.js +++ b/plugins/c9.ide.watcher/watcher.js @@ -46,10 +46,29 @@ define(function(require, exports, module) { } } + function unwatchChildren(e) { + e.watchers = []; + Object.keys(handlers).forEach(function(path) { + if (path == e.path || path.startsWith(e.path + "/")) { + if (unwatch(path)) + e.watchers.push(path.slice(e.path.length)); + } + }); + ignoreHandler(e); + } + + function rewatchChildren(e) { + doneHandler(e); + var toPath = e.result[0] ? e.path : e.args[1]; + e.watchers.forEach(function(path) { + watch(toPath + path); + }); + } + fs.on("beforeWriteFile", ignoreHandler, plugin); fs.on("afterWriteFile", doneHandler, plugin); - fs.on("beforeRename", ignoreHandler, plugin); - fs.on("afterRename", doneHandler, plugin); + fs.on("beforeRename", unwatchChildren, plugin); + fs.on("afterRename", rewatchChildren, plugin); fs.on("beforeMkdir", ignoreHandler, plugin); fs.on("afterMkdir", doneHandler, plugin); fs.on("beforeMkdirP", ignoreHandler, plugin); diff --git a/plugins/c9.nodeapi/assert.js b/plugins/c9.nodeapi/assert.js index 8ec96273..1e768ba8 100644 --- a/plugins/c9.nodeapi/assert.js +++ b/plugins/c9.nodeapi/assert.js @@ -46,7 +46,12 @@ assert.AssertionError = function AssertionError(options) { this.operator = options.operator; this.message = options.message || getMessage(this); var stackStartFunction = options.stackStartFunction || fail; - Error.captureStackTrace(this, stackStartFunction); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } else { + var err = new Error(); + this.stack = err.stack; + } }; // assert.AssertionError instanceof Error diff --git a/plugins/c9.preview/preview.handler.js b/plugins/c9.preview/preview.handler.js index ba05e5b1..fdd2c81c 100644 --- a/plugins/c9.preview/preview.handler.js +++ b/plugins/c9.preview/preview.handler.js @@ -160,24 +160,34 @@ define(function(require, exports, module) { } debug("proxy call %s", url); - httpModule.get({ - path: parsedUrl.path, - hostname: parsedUrl.hostname, - port: parsedUrl.port, - headers: req.headers - }, function(request) { - if (request.statusCode >= 400) - handleError(request); - else if (isDir) - serveListing(request); - else if (request.headers["content-type"] == "text/html") - serveHtml(request, parsedUrl.hostname, req); - else - serveFile(request); - }).on("error", function(err) { + try { + httpModule.get({ + path: parsedUrl.path, + hostname: parsedUrl.hostname, + port: parsedUrl.port, + headers: req.headers + }, function(request) { + if (request.statusCode >= 400) + handleError(request); + else if (isDir) + serveListing(request); + else if (request.headers["content-type"] == "text/html") + serveHtml(request, parsedUrl.hostname, req); + else + serveFile(request); + }).on("error", function(err) { + metrics.increment("preview.failed.error"); + next(err); + }); + } catch (e) { + logError(new Error("httpModule.get threw unexpected error"), { + message: e.message, + url: url, + headers: req.headers + }); metrics.increment("preview.failed.error"); - next(err); - }); + return next(new error.BadRequest(e.message)); + } function handleError(request) { var body = ""; diff --git a/plugins/c9.static/build.js b/plugins/c9.static/build.js index b8e69593..f53dc540 100644 --- a/plugins/c9.static/build.js +++ b/plugins/c9.static/build.js @@ -234,7 +234,7 @@ function main(options, imports, register) { function buildWorker(module, pathConfig, callback) { var modules = [module]; - if (module == "plugins/c9.ide.language/worker") { + if (module == "plugins/c9.ide.language.core/worker") { // jsonalyzer is missing in built version of local var jsonalyzer = require("../c9.ide.language.jsonalyzer/default_plugins"); var extraPackages = [ @@ -251,7 +251,7 @@ function main(options, imports, register) { } catch(e) {} // TODO find a saner method for managing files loaded in language worker modules = [ - "plugins/c9.ide.language/worker", + "plugins/c9.ide.language.core/worker", "plugins/c9.ide.language.generic/local_completer", "plugins/c9.ide.language.generic/snippet_completer", "plugins/c9.ide.language.generic/mode_completer", diff --git a/plugins/c9.vfs.client/vfs.ping.js b/plugins/c9.vfs.client/vfs.ping.js index 4e02ade7..380d42e1 100644 --- a/plugins/c9.vfs.client/vfs.ping.js +++ b/plugins/c9.vfs.client/vfs.ping.js @@ -9,6 +9,7 @@ define(function(require, exports, module) { var Plugin = imports.Plugin; var c9 = imports.c9; var ext = imports.ext; + var vfs = imports.vfs; /***** Initialization *****/ @@ -60,7 +61,10 @@ define(function(require, exports, module) { }; } - if (!api) return callback(new Error("Client is offline")); + if (!api || !vfs.connection) return callback(new Error("Client is offline")); + + if (!vfs.isIdle()) + return vfs.connection.once("message", ping.bind(null, callback)); var start = Date.now(); api.ping("serverTime", function(err, response) { diff --git a/plugins/c9.vfs.client/vfs_client.js b/plugins/c9.vfs.client/vfs_client.js index 0fb2d9c6..dd0c974c 100644 --- a/plugins/c9.vfs.client/vfs_client.js +++ b/plugins/c9.vfs.client/vfs_client.js @@ -198,7 +198,8 @@ define(function(require, exports, module) { } window.open(vfsUrl(path) + extraPaths + "?download" - + (filename ? "=" + escape(filename) : "") + // Escape '+', otherwise it gets interpreted as a space. + + (filename ? "=" + escape(filename) : "").replace(/\+/g, "%2B") + (isfile ? "&isfile=1" : "")); } @@ -240,9 +241,10 @@ define(function(require, exports, module) { path: parsedSocket.path, host: parsedSocket.host, port: parsedSocket.port - || parsedSocket.protocol == "https:" ? "443" : null, + || (parsedSocket.protocol == "https:" ? "443" : null), secure: parsedSocket.protocol - ? parsedSocket.protocol == "https:" : true + ? parsedSocket.protocol == "https:" : true, + rejectUnauthorized: options.rejectUnauthorized }; callback(); }); @@ -329,6 +331,13 @@ define(function(require, exports, module) { bufferedVfsCalls.push([method, path, options, callback]); } + function isIdle() { + if (!connection || !consumer) + return false; + return !Object.keys(connection.unacked).length && + !Object.keys(consumer.callbacks || {}).length; + } + /***** Lifecycle *****/ plugin.on("load", function(){ @@ -336,7 +345,8 @@ define(function(require, exports, module) { }); plugin.on("unload", function(){ loaded = false; - + if (connection && connection.socket) + connection.socket.destroying = true; if (consumer) consumer.disconnect(); if (connection) @@ -429,7 +439,9 @@ define(function(require, exports, module) { // Extending the API use: vfsCall.bind(null, "use"), extend: vfsCall.bind(null, "extend"), - unextend: vfsCall.bind(null, "unextend") + unextend: vfsCall.bind(null, "unextend"), + + isIdle: isIdle, }); register(null, { diff --git a/plugins/c9.vfs.server/download.js b/plugins/c9.vfs.server/download.js index b1dbea6f..066982fa 100644 --- a/plugins/c9.vfs.server/download.js +++ b/plugins/c9.vfs.server/download.js @@ -44,11 +44,11 @@ define(function(require, exports, module) { filename += (paths.length > 1 ? "[+" + (paths.length - 1) + "]" : "") + ".tar.gz"; } } - var filenameHeader = "attachment; filename*=utf-8''" + encodeURIComponent(filename); + var filenameHeader = "attachment; filename*=utf-8''" + escape(filename); - var process; + var proc; req.on("close", function() { - if (process) process.kill(); + if (proc) proc.kill(); }); if (req.uri.query.isfile) { @@ -73,6 +73,17 @@ define(function(require, exports, module) { meta.stream.pipe(res); }); + meta.stream.once("close", function() { + if (res.headerSent) + return; + + res.writeHead(200, { + "Content-Type": "octet/stream", + "Content-Disposition": filenameHeader + }); + res.end(); + }); + meta.stream.on("error", function(err){ res.writeHead(500); res.end(err.message); @@ -113,24 +124,26 @@ define(function(require, exports, module) { 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, '/'); + if (process.platform == "win32") { + // Quote the path to escape unusual characters and spaces. + // NB: Double quotes are illegal within the actual path on Windows. + path = '"' + path.replace(/"/g, "") + '"'; } args.push(path); }); vfs.spawn(executable, { args: args, - cwd: cwd + cwd: cwd, + windowsVerbatimArguments: true // Prevents Node from escaping the double quotes added above. }, function (err, meta) { if (err) return next(err); - process = meta.process; + proc = meta.process; // once we receive data on stdout pipe it to the response - process.stdout.once("data", function (data) { + proc.stdout.once("data", function (data) { if (res.headerSent) return; @@ -139,15 +152,15 @@ define(function(require, exports, module) { "Content-Disposition": filenameHeader }); res.write(data); - process.stdout.pipe(res); + proc.stdout.pipe(res); }); var stderr = ""; - process.stderr.on("data", function (data) { + proc.stderr.on("data", function (data) { stderr += data; }); - process.on("exit", function(code, signal) { + proc.on("exit", function(code, signal) { if (res.headerSent) return; diff --git a/plugins/c9.vfs.server/download_test.js b/plugins/c9.vfs.server/download_test.js index ab170687..1eeef768 100755 --- a/plugins/c9.vfs.server/download_test.js +++ b/plugins/c9.vfs.server/download_test.js @@ -19,6 +19,7 @@ var execFile = require('child_process').execFile; describe(__filename, function(){ this.timeout(4000); + var base; beforeEach(function(next) { var that = this; @@ -35,6 +36,7 @@ describe(__filename, function(){ registerExtension: function() { } } }, function(err, api) { + assert.equal(err, null); var download = api["vfs.download"].download; that.server = http.createServer(function(req, res, next) { req.uri = urlParse(req.url, true); @@ -43,7 +45,16 @@ describe(__filename, function(){ assert.fail(err); }); }); - that.server.listen(8787, "0.0.0.0", next); + function tryNext(retries, err) { + if (retries < 0) return next(err); + var port = 20000 + Math.round(Math.random() * 20000); + base = "http://localhost:" + port; + that.server.listen(port, "localhost", function() { + if (err) return tryNext(retries - 1, err); + next(); + }); + } + tryNext(4); }); }); @@ -55,10 +66,10 @@ describe(__filename, function(){ 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) { + assert.equal(err, null); + var filename = "download.tar.gz"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/?download=download.tar.gz", function(res) { assert.equal(res.headers["content-type"], "application/x-gzip"); assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''download.tar.gz"); @@ -80,12 +91,11 @@ describe(__filename, function(){ 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/test?download=download.tar.gz", function(res) { + var filename = "download.tar.gz"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/test?download=download.tar.gz", function(res) { res.pipe(file); res.on("end", function() { @@ -104,12 +114,11 @@ 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/test?download", function(res) { + var filename = "download.tar.gz"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/test?download", function(res) { assert.equal(res.headers["content-type"], "application/x-gzip"); assert.equal(res.headers["content-disposition"], "attachment; filename*=utf-8''test.tar.gz"); @@ -131,12 +140,11 @@ describe(__filename, function(){ 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) { + var filename = "download.tar.gz"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/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) { @@ -158,12 +166,11 @@ describe(__filename, function(){ 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) { + var filename = "download.tar.gz"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/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) { @@ -185,10 +192,10 @@ describe(__filename, function(){ 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(err, null); + var filename = "download.zip"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/?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"); @@ -210,12 +217,11 @@ describe(__filename, function(){ 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) { + var filename = "download.zip"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/test?download=download.zip", function(res) { res.pipe(file); res.on("end", function() { @@ -234,12 +240,11 @@ describe(__filename, function(){ 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) { + var filename = "download.zip"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/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) { @@ -261,12 +266,11 @@ describe(__filename, function(){ 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) { + var filename = "download.zip"; + var file = fs.createWriteStream(path + "/" + filename); + http.get(base + "/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) { diff --git a/plugins/c9.vfs.standalone/www/test.html b/plugins/c9.vfs.standalone/www/test.html index b4c1320e..fe3c75f0 100644 --- a/plugins/c9.vfs.standalone/www/test.html +++ b/plugins/c9.vfs.standalone/www/test.html @@ -24,6 +24,7 @@ mocha.setup('bdd'); mocha.bail(false); mocha.ignoreLeaks(true); + mocha.fullTrace && mocha.fullTrace(); window.onerror=function(msg){ var el=document.getElementById('jserror'); el.innerHTML+="
"+msg+"
";}; /* wrap setTimeout to prevent any plugins leaking timeouts to the next test*/ @@ -120,6 +121,8 @@ runner.on('test end', function(test) { stats.percent = stats.tests / runner.total * 100 | 0; tests.push(test); + if (mocha._onSubTest) + mocha._onSubTest(test); }); runner.on('end', function() { @@ -127,7 +130,6 @@ // e.g. using on instead of once can call done second time during app unload // so we save the report at the time when test runner ended. mocha.lastReport = mocha.getReport(); - console.log(mocha.report); }); function parseError(err) { @@ -263,7 +265,7 @@ } function getReport() { - return mocha.lastReport; + return mocha.lastReport || { failures: "didn't complete" }; } function safeDisconnect(cb) { @@ -382,7 +384,11 @@ return !/text!/.test(x); }); function cleanupRequireModules() { - Object.keys(define.modules).forEach(function(x) { + [].concat( + Object.keys(define.modules), + Object.keys(define.errors), + Object.keys(define.loading) + ).forEach(function(x) { if (/text!/.test(x) || defaultModules.indexOf(x) != -1) return; if (/^ace|^treehugger|\/ctags\/ctags$/.test(x) && !/_test/.test(x)) @@ -390,12 +396,13 @@ require.undef(x); }); + define.fetchedUrls = Object.create(null); } if (require == requirejs) { require = function(a, b, c) { if (!c && Array.isArray(a)) c = function(err) { - lastDone && lastDone(err.message); + lastDone && lastDone(err.message || err); }; // workaround for sync minirequire behaviour var bt = b && function() { diff --git a/plugins/c9.vfs.standalone/www/test.js b/plugins/c9.vfs.standalone/www/test.js index 73255d54..1fd0abcb 100644 --- a/plugins/c9.vfs.standalone/www/test.js +++ b/plugins/c9.vfs.standalone/www/test.js @@ -238,7 +238,7 @@ require([ layout.initMenus = function() {}; layout.findParent = function(){ - if (!bar || bar.$amlDestroyed) { + if (!bar || bar.$amlDestroyed || !bar.$ext || !bar.$ext.parentNode) { bar = apf.document.documentElement.appendChild( new imports.ui.bar()); bar.$ext.style.position = "fixed"; @@ -530,6 +530,12 @@ require([ x.unregister = function(){}; return x; })(), + "terminal.monitor.message_view": (function(){ + var x = new EventEmitter(); + x.show = function(){}; + x.hide = function(){}; + return x; + })() }); }; @@ -557,7 +563,6 @@ require([ if (err.missingMock.length) { console.error("Missing mock services for " + err.missingMock); } else { - console.warn("Adding mock services for " + err.unresolved); return expect.setupArchitectTest(config, architect, { mockPlugins: config.unresolved, existingPlugins: err.resolved diff --git a/scripts/makelocal.sh b/scripts/makelocal.sh index 0d585e44..476edce6 100755 --- a/scripts/makelocal.sh +++ b/scripts/makelocal.sh @@ -31,7 +31,7 @@ CDN="../server.js $CDN_SETTINGS --settings local --version=standalone --cache $C mkdir -p "$CACHE/standalone/modules/lib/emmet" cp "$CURDIR/../node_modules/emmet/emmet.js" "$CACHE/standalone/modules/lib/emmet/" -WORKER=plugins/c9.ide.language/worker +WORKER=plugins/c9.ide.language.core/worker echo building worker $WORKER $CDN --worker $WORKER echo $CDN --worker $WORKER diff --git a/scripts/makestandalone.sh b/scripts/makestandalone.sh index 9fe3aefa..622efe2e 100755 --- a/scripts/makestandalone.sh +++ b/scripts/makestandalone.sh @@ -31,7 +31,7 @@ CDN="$CURDIR/../server.js cdn-cli -s standalone --server-config standalone --ser # build async loaded ace modules $CDN --module ace -WORKER=plugins/c9.ide.language/worker +WORKER=plugins/c9.ide.language.core/worker echo building worker $WORKER $CDN --worker $WORKER echo $CDN --worker $WORKER diff --git a/settings/standalone.js b/settings/standalone.js index 178905aa..b445b4ba 100644 --- a/settings/standalone.js +++ b/settings/standalone.js @@ -15,12 +15,8 @@ module.exports = function(manifest, installPath) { var sdk = !manifest.sdk; var win32 = process.platform == "win32"; - if (win32) { - if (process.env.HOME === undefined) - process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH; - if (!/msys\/bin|Git\/bin/.test(process.env.PATH)) - process.env.PATH = path.join(process.env.HOME, ".c9", "msys/bin") + ";" + process.env.PATH; - } + if (win32) + readWin32Settings(); var home = process.env.HOME; @@ -142,3 +138,21 @@ module.exports = function(manifest, installPath) { return config; }; + + +function readWin32Settings() { + var path = require("path"); + var fs = require("fs"); + if (process.env.HOME === undefined) + process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH; + if (!/msys\/bin|Git\/bin/.test(process.env.PATH)) + process.env.PATH = path.join(process.env.HOME, ".c9", "msys/bin") + path.delimiter + process.env.PATH; + var settingsPath = path.join(process.env.HOME, ".c9", "standalone.settings"); + try { + var s = fs.readFileSync(settingsPath, "utf8"); + process.env.PATH = JSON.parse(s).bashDir + path.delimiter + process.env.PATH; + } catch(e) { + if (!fs.existsSync(path.join(process.env.HOME, ".c9", "msys/bin/bash.exe"))) + console.error(e); + } +}