Merge branch 'master' of github.com:c9/newclient into merge-account-profile

Conflicts:
	plugins/c9.ide.server/plugins.js
pull/85/head
Nikolai Onken 2015-03-24 16:37:38 +00:00
rodzic eee93a429e
commit 8d01ba39ef
28 zmienionych plików z 273 dodań i 183 usunięć

Wyświetl plik

@ -17,7 +17,7 @@ rules:
no-cond-assign: [1, "except-parens"]
no-debugger: 3
no-dupe-keys: 3
no-eval: 2
no-eval: 3
no-func-assign: 1
no-invalid-regexp: 1
no-irregular-whitespace: 3

1
.gitignore vendored
Wyświetl plik

@ -8,6 +8,7 @@ plugins/c9.ide.layout.classic/less/*.css
plugins/c9.vfs.standalone/www/less.html
plugins/c9.ide.run/todo
plugins/c9.vfs.standalone/www/charts
plugins/c9.ide.language.javascript.tern/util/sigs_ts
scripts/build
build/output
build/standalone/

Wyświetl plik

@ -1,5 +1,5 @@
Cloud9 3.0 SDK for Plugin Development
=======================================
======================================
This is the core repository for the Cloud9 v3 SDK. The SDK allows you to run a version of Cloud9 that allows you to develop plugins and create a custom IDE based on Cloud9.

Wyświetl plik

@ -19,7 +19,7 @@ Base
Tabs vs Spaces
--------------
We use 4 spaces of indenteation.
We use 4 spaces of indentation.
Line Termination
----------------
@ -100,7 +100,7 @@ Your opening braces go on the same line as the statement.
Also, notice the use of whitespace before and after the condition statement.
Closing braces are always followed by a new line. This is releavant for `else`, `catch` and `finally`.
Closing braces are always followed by a new line. This is relevant for `else`, `catch` and `finally`.
*Right*:

Wyświetl plik

@ -1038,6 +1038,7 @@ var VirtualRenderer = function(container, theme) {
};
this.$updateLines = function() {
if (!this.$changedLines) return;
var firstRow = this.$changedLines.firstRow;
var lastRow = this.$changedLines.lastRow;
this.$changedLines = null;

Wyświetl plik

@ -65,15 +65,15 @@ function DefaultHandlers(mouseHandler) {
var editor = this.editor;
var node = e.getNode();
var title;
var title, provider = editor.provider;
if (!node) {
title = "";
} else if (editor.provider.columns) {
} else if (provider.columns) {
var pos = e.getDocumentPosition();
var columnData = editor.renderer.$headingLayer.findColumn(pos.x);
title = columnData ? columnData.column.getText(node) : "";
} else {
title = editor.provider.getText(node);
title = provider.getTooltipText ? provider.getTooltipText(node) : provider.getText(node);
}
if (editor.container.title != title)

4
node_modules/c9/inline-mocha.js wygenerowano vendored
Wyświetl plik

@ -1,10 +1,10 @@
module.exports = function(module, reporter) {
module.exports = function(module, reporter, options) {
if (typeof module !== "undefined" && module === require.main) {
if (typeof global.onload === "undefined")
global.onload = undefined;
var file = module.filename;
var Mocha = require("mocha");
var mocha = new Mocha();
var mocha = new Mocha(options || {});
mocha.reporter(reporter || "spec");
var suite = mocha.suite;
suite.emit('pre-require', global, file, mocha);

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

@ -1380,23 +1380,21 @@ module.exports = function setup(fsOptions) {
});
callback(done);
function loop(watchers, path, event, callback) {
function done(callback) {
if (!watchers.length)
return callback();
// Notify each watcher of changes and reactivate it
var watcher = watchers.pop();
watcher.handleWatchEvent(event, basename(path), true);
fs.stat(path, function(err, stat) {
if (err || !stat) return;
stat.vfsWrite = true;
watcher.sendToAllListeners("change", basename(path), stat);
});
watcher.resume(function() {
loop(watchers, path, event, callback);
done(callback);
});
}
function done(callback) {
loop(watchers, path, "change", function() {
loop(dirWatchers, parentDir, "directory", callback);
});
}
}
function connect(port, options, callback) {

Wyświetl plik

@ -36,7 +36,7 @@
"send": "~0.1.4",
"simple-mime": "~0.0.8",
"tern": "git://github.com/lennartcl/tern.git#97464df789dbb4d81ca4579383a02b320c69563d",
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#b8b3d555e545aa41ed8d0df054ef38416a578faa",
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#6a0107e602b0d044fe1753533cf31f52cf5fb95a",
"through": "2.2.0",
"tmp": "~0.0.20",
"uglify-js": "2.4.16",
@ -49,17 +49,17 @@
},
"licenses": [],
"c9plugins": {
"c9.ide.language": "#4a23a36945",
"c9.ide.language": "#de3c644b88",
"c9.ide.language.css": "#afda1f867c",
"c9.ide.language.generic": "#87a4a44671",
"c9.ide.language.html": "#fa4833e117",
"c9.ide.language.html.diff": "#a7311cfc9f",
"c9.ide.language.javascript": "#8479d0a9c1",
"c9.ide.language.javascript": "#ec9ecf31cf",
"c9.ide.language.javascript.immediate": "#9a2cce9121",
"c9.ide.language.javascript.eslint": "#8832423ad1",
"c9.ide.language.javascript.tern": "#7aab8b0b6a",
"c9.ide.language.javascript.infer": "#ebb2daf81a",
"c9.ide.language.jsonalyzer": "#a1057f20db",
"c9.ide.language.jsonalyzer": "#d82c60fcb9",
"c9.ide.collab": "#7b09419b5c",
"c9.ide.local": "#2bfd7ff051",
"c9.ide.find": "#989c06e6a7",
@ -94,8 +94,8 @@
"c9.ide.pubsub": "#92ec19ed3a",
"c9.ide.readonly": "#f6f07bbe42",
"c9.ide.recentfiles": "#7c099abf40",
"c9.ide.remote": "#cd45e81d2f",
"c9.ide.run": "#e510a39b4b",
"c9.ide.remote": "#f531d62cfb",
"c9.ide.run": "#3349df7c52",
"c9.ide.run.build": "#915e48b363",
"c9.ide.run.debug.xdebug": "#b91d23f48b",
"c9.ide.save": "#a32a8f4346",

Wyświetl plik

@ -289,14 +289,14 @@ define(function(require, exports, module) {
var newPath = e.args[1];
var parent = findNode(dirname(newPath));
//Validation
// Validation
var toNode = findNode(newPath);
if (parent) { //Dir is in cache
if (parent) { // Dir is in cache
if (toNode)
deleteNode(toNode);
createNode(newPath, null, node); // Move node
createNode(newPath, null, node); // Move node
recurPathUpdate(node, oldPath, newPath);
e.undo = function(){
@ -480,6 +480,11 @@ define(function(require, exports, module) {
}
function createNode(path, stat, updateNode, updating) {
if (!/^[!~/]/.test(path)) {
var e = new Error("Refusing to add a node with misformed path to fs.cache");
return reportError(e, { path: path });
}
if (orphans[path]) {
updateNode = orphans[path];
delete orphans[path];

Wyświetl plik

@ -62,6 +62,13 @@ define(function(require, exports, module) {
if (typeof args[args.length - 1] != "function")
throw new Error("Missing callback for " + name);
if (!/^[!~/]/.test(path)) {
var e = new Error("Invalid path passed to fs");
e.data = { name: name, path: path };
setTimeout(function() { throw e });
return args[args.length - 1](e);
}
var original_callback = args.pop();

Wyświetl plik

@ -1419,7 +1419,8 @@ window.TraceKit = TraceKit;
var blackListedErrors = {
'Error with empty message': {},
'Script error.': {}
'Script error.': {},
'DealPly is not defined': { factor: 10e5 }
};
function processUnhandledException(stackTrace, options) {
var stack = [],
@ -1479,7 +1480,7 @@ window.TraceKit = TraceKit;
if (blackListedErrors.hasOwnProperty(message)) {
var count = (blackListedErrors[message].count || 0) + 1;
blackListedErrors[message].count = count;
if (count % 10 !== 1) {
if (count % (blackListedErrors[message].factor || 10) !== 1) {
return;
}
finalCustomData.$blackList = blackListedErrors[message];

Wyświetl plik

@ -50,29 +50,29 @@ define(function(require, exports, module) {
oldOnError.apply(this, arguments);
};
//Catch all APF Routed errors
// ui.addEventListener("error", function(e) {
// var errorInfo = {
// agent : navigator.userAgent,
// type : "APF Error",
// message : e.message,
// tgt : e.currentTarget && e.currentTarget.serialize(),
// url : e.url,
// state : e.state,
// e : e.error,
// workspaceId : plugin.workspaceId
// };
//
// emit("error", errorInfo);
//
// http.request("/api/debug", {
// method : "POST",
// contentType : "application/json",
// body : errorInfo
// }, function(err) {
// if (err) console.error(err);
// });
// });
// Catch all APF Routed errors
// ui.addEventListener("error", function(e) {
// var errorInfo = {
// agent : navigator.userAgent,
// type : "APF Error",
// message : e.message,
// tgt : e.currentTarget && e.currentTarget.serialize(),
// url : e.url,
// state : e.state,
// e : e.error,
// workspaceId : plugin.workspaceId
// };
// emit("error", errorInfo);
// http.request("/api/debug", {
// method : "POST",
// contentType : "application/json",
// body : errorInfo
// }, function(err) {
// if (err) console.error(err);
// });
// });
}
}
@ -87,8 +87,11 @@ define(function(require, exports, module) {
// });
}
function reportError(exception) {
console.error(exception.stack || exception);
function reportError(exception, customData) {
if (customData)
console.error(exception, customData);
else
console.error(exception.stack || exception);
submitError(exception);
}
@ -98,6 +101,10 @@ define(function(require, exports, module) {
load();
});
plugin.on("unload", function(){
loaded = false;
});
/***** Register and define API *****/
plugin.freezePublicAPI({

Wyświetl plik

@ -211,7 +211,7 @@
left : -2px;
vertical-align : top;
margin-right : 2px !important;
margin-left : 1px !important;
margin-left : @datagrid-row-toggler-loading !important;
}
.blackdg .loading.selected .toggler{
background : url("@{datagrid-selected-spinner}") no-repeat 0 0;

Wyświetl plik

@ -705,6 +705,7 @@
@datagrid-row-padding: 2px 0 2px 4px;
@datagrid-row-height: 18px;
@datagrid-row-toggler: -1px 4px -3px 3px;
@datagrid-row-toggler-loading: 1px;
@datagrid-editor-box-shadow: 0px 0px 10px 1px rgba(0,0,0,0.5) inset;

Wyświetl plik

@ -705,6 +705,7 @@
@datagrid-row-padding: 2px 0 2px 4px;
@datagrid-row-height: 18px;
@datagrid-row-toggler: -1px 4px -3px 3px;
@datagrid-row-toggler-loading: 1px;
@datagrid-editor-box-shadow: 0px 0px 10px 1px rgba(0,0,0,0.5) inset;

Wyświetl plik

@ -363,7 +363,7 @@
@pane-button-running-top: 6px;
@pane-button-running-animation: rotation 2s infinite steps(16);
@pane-button-save-image: "@{image-path}/tab-save-spinner-active_flat_light.png";
@pane-button-save-image-width: 360px;
@pane-button-save-image-width: 336px;
@pane-button-save-image-height: 14px;
@pane-button-save-width: 14px;
@pane-button-save-height: 14px;
@ -705,6 +705,7 @@
@datagrid-row-padding: 5px 0 5px 7px;
@datagrid-row-height: 24px;
@datagrid-row-toggler: -1px 4px -3px -2px;
@datagrid-row-toggler-loading: -4px;
@datagrid-editor-box-shadow: none;
@ -1493,8 +1494,8 @@
@share-textbox-border-color: @textbox-border-color;
@share-textbox-width: 378px;
@share-textbox-margin: 5px 0 0 0;
@share-access-right: 150px;
@share-access-top: 36px;
@share-access-right: 140px;
@share-access-top: 66px;
@share-invite-button-width: 120px;
@share-invite-button-height: 30px;
@share-invite-button-right: 10px;

Wyświetl plik

@ -705,6 +705,7 @@
@datagrid-row-padding: 2px 0 2px 4px;
@datagrid-row-height: 18px;
@datagrid-row-toggler: -1px 4px -3px 3px;
@datagrid-row-toggler-loading: 1px;
@datagrid-editor-box-shadow: 0px 0px 10px 1px rgba(0,0,0,0.5) inset;

Wyświetl plik

@ -705,6 +705,7 @@
@datagrid-row-padding: 2px 0 2px 4px;
@datagrid-row-height: 18px;
@datagrid-row-toggler: -1px 4px -3px 3px;
@datagrid-row-toggler-loading: 1px;
@datagrid-editor-box-shadow: 0px 0px 10px 1px rgba(0,0,0,0.5) inset;

Wyświetl plik

@ -4,106 +4,133 @@
* @copyright 2013, Ajax.org B.V.
*/
"use strict";
define(function(require, exports, module) {
"use strict";
main.consumes = ["Plugin", "connect.static"];
main.provides = ["c9.static.plugins"];
return main;
main.consumes = [
"connect.static"
];
main.provides = ["c9.static.plugins"];
module.exports = main;
function main(options, imports, register) {
var statics = imports["connect.static"];
var fs = require("fs");
function main(options, imports, register) {
var Plugin = imports.Plugin;
var statics = imports["connect.static"];
var fs = require("fs");
var whitelist = options.whitelist;
var blacklist = options.blacklist;
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
var loaded = false;
function load(){
if (loaded) return false;
loaded = true;
var requirePaths = {
ace: "lib/ace/lib/ace",
ace_tree: "lib/ace_tree/lib/ace_tree",
treehugger: "lib/treehugger/lib/treehugger",
acorn: "lib/treehugger/lib/treehugger/js",
tern: "lib/tern",
tern_from_ts: "lib/tern_from_ts",
ui: "lib/ui",
c9: "lib/c9",
frontdoor: "lib/frontdoor",
};
if (whitelist === "*") {
statics.addStatics([{
path: __dirname + "/../../node_modules",
mount: "/lib"
}]);
var whitelist = options.whitelist;
var blacklist = options.blacklist;
var requirePaths = {
ace: "lib/ace/lib/ace",
ace_tree: "lib/ace_tree/lib/ace_tree",
treehugger: "lib/treehugger/lib/treehugger",
acorn: "lib/treehugger/lib/treehugger/js",
tern: "lib/tern",
ui: "lib/ui",
c9: "lib/c9",
frontdoor: "lib/frontdoor",
};
if (whitelist === "*") {
statics.addStatics([{
path: __dirname + "/../../node_modules",
mount: "/lib"
}]);
statics.addStatics([{
path: __dirname + "/../../plugins",
mount: "/plugins",
rjs: requirePaths
}]);
} else {
[
"ace_tree",
"acorn",
"tern",
"treehugger",
"pivottable",
"architect",
"source-map",
"rusha",
"c9",
"ui",
"emmet",
"frontdoor",
"mocha", // TESTING
"chai", // TESTING
].forEach(function(name) {
statics.addStatics([{
path: __dirname + "/../../plugins",
mount: "/plugins",
rjs: requirePaths
}]);
} else {
[
"ace_tree",
"acorn",
"tern",
"tern_from_ts",
"treehugger",
"pivottable",
"architect",
"source-map",
"rusha",
"c9",
"ui",
"emmet",
"frontdoor",
"mocha", // TESTING
"chai", // TESTING
].forEach(function(name) {
statics.addStatics([{
path: __dirname + "/../../node_modules/" + name,
mount: "/lib/" + name
}]);
});
statics.addStatics([{
path: __dirname + "/../../node_modules/ace",
mount: "/lib/ace",
rjs: requirePaths
}]);
statics.addStatics(fs.readdirSync(__dirname + "/../")
.filter(function(path) {
if (path in blacklist)
return false;
else if (path in whitelist)
return true;
else if (path.indexOf("c9.ide.") === 0)
return true;
else if (path.indexOf("c9.account") === 0)
return true;
else
return false;
})
.map(function(path) {
return {
path: __dirname + "/../../plugins/" + path,
mount: "/plugins/" + path
};
})
);
}
statics.addStatics([{
path: __dirname + "/../../node_modules/" + name,
mount: "/lib/" + name
path: __dirname + "/www",
mount: "/"
}]);
statics.addStatics([{
path: __dirname + "/../../docs",
mount: "/docs"
}]);
}
/***** Lifecycle *****/
plugin.on("load", function(){
load();
});
plugin.on("unload", function(){
loaded = false;
});
statics.addStatics([{
path: __dirname + "/../../node_modules/ace",
mount: "/lib/ace",
rjs: requirePaths
}]);
/***** Register and define API *****/
statics.addStatics(fs.readdirSync(__dirname + "/../")
.filter(function(path) {
if (path in blacklist)
return false;
else if (path in whitelist)
return true;
else if (path.indexOf("c9.ide.") === 0)
return true;
else if (path.indexOf("c9.account") === 0)
return true;
else
return false;
})
.map(function(path) {
return {
path: __dirname + "/../../plugins/" + path,
mount: "/plugins/" + path
};
})
);
plugin.freezePublicAPI({});
register(null, {
"c9.static.plugins": plugin
});
}
statics.addStatics([{
path: __dirname + "/www",
mount: "/"
}]);
statics.addStatics([{
path: __dirname + "/../../docs",
mount: "/docs"
}]);
register(null, {
"c9.static.plugins": {}
});
}
});

Wyświetl plik

@ -158,6 +158,10 @@ define(function(require, exports, module) {
if (!/(https?|ftp|file):/.test(href)) {
href = "http://" + href;
}
href = href.replace(/(^https?:\/\/)(0.0.0.0|localhost)(?=:|\/|$)/, function(_, protocol, host) {
host = c9.hostname || window.location.host;
return protocol + host.replace(/:\d+/, "");
});
if (e.metaKey || e.ctrlKey)
window.open(href);
else

Wyświetl plik

@ -738,6 +738,8 @@ define(function(require, exports, module) {
terminal.on("afterWrite", function() {
clearTmuxBorders(terminal);
});
session.getEmitter().sticky("terminalReady", session);
}
/***** Lifecycle *****/

Wyświetl plik

@ -227,7 +227,7 @@ define(function(require, exports, module) {
// Fetch UI elements
container = plugin.getElement("container");
winFilesViewer = options.aml
winFilesViewer = options.aml;
// Create the Ace Tree
tree = new Tree(container.$int);
@ -244,6 +244,16 @@ define(function(require, exports, module) {
return "<span class='filetree-icon " + icon + "'></span>";
};
fsCache.model.getTooltipText = function(node) {
var size = node.size;
return node.label + (node.link ? " => " + node.link + "\n" : "")
+ (size ? " | " + (
size < 0x400 ? size + " bytes" :
size < 0x100000 ? (size / 0x400).toFixed(2) + "KB" :
(size / 0x100000).toFixed(2) + "MB"
) : "");
};
if (settings.get("user/general/@treestyle") == "alternative")
ui.setStyleClass(container.$int, "alternative");
@ -951,10 +961,15 @@ define(function(require, exports, module) {
if (node === false || path.charAt(0) == "!")
return increment();
if (!/^[!~/]/.test(path)) {
console.error("invalid path", path);
delete expandedList[path];
return increment();
}
if (node && node.status == "loaded") {
expandNode(node);
increment();
return;
return increment();
}
fs.readdir(path, function(err, data) {

Wyświetl plik

@ -330,7 +330,10 @@ define(function(require, exports, module) {
}
function updateChangedPath(err, path, data) {
var doc = changedPaths[path].tab.document;
var tab = changedPaths[path].tab || tabManager.findTab(path);
if (!tab)
return changedPaths[path] && changedPaths[path].resolve();
var doc = tab.document;
doc.setBookmarkedValue(data, true);
doc.meta.timestamp = Date.now() - settings.timeOffset;
changedPaths[path].resolve();

Wyświetl plik

@ -311,7 +311,7 @@ define(function(require, exports, module) {
"content-length": data.length + inject.length,
"content-type": request.headers["content-type"],
"etag": request.headers.etag,
"date": request.headers.data,
"date": request.headers.date,
"access-control-allow-origin": "https://ide." + ideHost
});
res.write(data);

Wyświetl plik

@ -1,7 +1,7 @@
define(function(require, exports, module) {
"use strict";
main.consumes = ["Plugin", "auth", "http", "api"];
main.consumes = ["Plugin", "auth", "http", "api", "error_handler"];
main.provides = ["vfs.endpoint"];
return main;
@ -10,6 +10,7 @@ define(function(require, exports, module) {
var auth = imports.auth;
var http = imports.http;
var api = imports.api;
var errorHandler = imports.error_handler;
/***** Initialization *****/
@ -43,29 +44,32 @@ define(function(require, exports, module) {
var servers;
var pendingServerReqs = [];
if (options.getServers)
options.getServers(initDefaultServers);
else
initDefaultServers();
initDefaultServers();
options.pid = options.pid || 1;
/***** Methods *****/
function initDefaultServers(baseURI) {
options.getServers = undefined;
var loc = require("url").parse(baseURI || document.baseURI || window.location.href);
var defaultServers = [{
url: loc.protocol + "//" + loc.hostname + (loc.port ? ":" + loc.port : "") + "/vfs",
region: "default"
}];
servers = (urlServers || options.servers || defaultServers).map(function(server) {
server.url = server.url.replace(/\/*$/, "");
return server;
});
pendingServerReqs.forEach(function(cb) {
cb(null, servers);
});
if (options.getServers)
return options.getServers(init);
init();
function init() {
options.getServers = undefined;
var loc = require("url").parse(baseURI || document.baseURI || window.location.href);
var defaultServers = [{
url: loc.protocol + "//" + loc.hostname + (loc.port ? ":" + loc.port : "") + "/vfs",
region: "default"
}];
servers = (urlServers || options.servers || defaultServers).map(function(server) {
server.url = server.url.replace(/\/*$/, "");
return server;
});
pendingServerReqs.forEach(function(cb) {
cb(null, servers);
});
}
}
function getServers(callback) {
@ -90,10 +94,14 @@ define(function(require, exports, module) {
}
function getVfsEndpoint(version, callback) {
getServers(function(err, servers) {
if (err) return callback(err);
getServers(function(err, _servers) {
if (err) {
errorHandler.reportError(err);
initDefaultServers();
_servers = servers;
}
getVfsUrl(version, servers, function(err, vfsid, url, region) {
getVfsUrl(version, _servers, function(err, vfsid, url, region) {
if (err) return callback(err);
callback(null, {
@ -166,7 +174,7 @@ define(function(require, exports, module) {
var server = servers[i];
auth.request(server.url + "/" + options.pid, {
method: "POST",
timeout: 20000,
timeout: 120000,
body: {
version: version
},
@ -206,6 +214,9 @@ define(function(require, exports, module) {
return;
}
else if (err.code == 403) {
if (res.error.blocked)
callback(fatalError(res.error.message, "dashboard"));
// forbidden. User doesn't have access
// wait a while before trying again
setTimeout(function() {

Wyświetl plik

@ -7,7 +7,7 @@
define(function(require, exports, module) {
"use strict";
main.consumes = ["Plugin", "auth", "vfs.endpoint", "dialog.error", "dialog.alert"];
main.consumes = ["Plugin", "auth", "vfs.endpoint", "dialog.error", "dialog.alert", "error_handler"];
main.provides = ["vfs"];
return main;
@ -33,6 +33,7 @@ define(function(require, exports, module) {
var showError = errorDialog.show;
var hideError = errorDialog.hide;
var showAlert = imports["dialog.alert"].show;
var errorHandler = imports.error_handler;
var eio = require("engine.io");
var Consumer = require("vfs-socket/consumer").Consumer;
@ -123,6 +124,7 @@ define(function(require, exports, module) {
});
function disconnect() {
pingUrl = null;
reconnect(function(err) {
if (err && err.fatal)
return;
@ -275,6 +277,7 @@ define(function(require, exports, module) {
consumer.connect(transport, function(err, _vfs) {
// TODO
if (err) {
errorHandler.reportError(new Error("Error connecting to VFS", { err: err }));
console.error("error connecting to VFS", err);
return;
}

Wyświetl plik

@ -63,7 +63,7 @@ updatePackage() {
}
updateAllPackages() {
c9packages=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`);
c9packages=`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`;
count=${#c9packages[@]}
i=0
for m in ${c9packages[@]}; do echo $m;