diff --git a/.gitignore b/.gitignore
index 5226b321..8eccae7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,8 +70,8 @@ plugins/c9.proxy/proxy.cfg
plugins/c9.proxy/haproxy
plugins/c9.proxy/haproxy-*
**/.module-cache/
-plugins/c9.account.billing/node_modules/
plugins/c9.account/node_modules/
+plugins/c9.account.*/node_modules/
.c9revisions
.settings
diff --git a/configs/cli.js b/configs/cli.js
index fef801e9..8d95eff0 100644
--- a/configs/cli.js
+++ b/configs/cli.js
@@ -1,6 +1,12 @@
module.exports = function(options) {
+// workaround for api difference between node and c9 events modules
var EventEmitter = require("events").EventEmitter;
+var emit_ = EventEmitter.prototype.emit
+EventEmitter.prototype.emit = function() {
+ emit_.apply(this, arguments);
+ return true;
+}
var PID = process.env.C9_PID || 526;
var APIHOST = process.env.C9_APIHOST || "api.c9.io"; // "api.c9.io";
@@ -36,6 +42,16 @@ return [
projectId: PID,
apiHost: APIHOST
},
+ {
+ packagePath: "./c9.cli.publish/install",
+ projectId: PID,
+ apiHost: APIHOST
+ },
+ {
+ packagePath: "./c9.cli.publish/list",
+ projectId: PID,
+ apiHost: APIHOST
+ },
{
packagePath: "./c9.ide.auth/auth",
accessToken: "token",
@@ -65,11 +81,34 @@ return [
packagePath: "./c9.cli.open/restart",
platform: process.platform
},
+ "./c9.automate/automate",
+ "./c9.ide.installer/commands/centos",
+ "./c9.ide.installer/commands/darwin",
+ "./c9.ide.installer/commands/bash",
+ "./c9.ide.installer/commands/npm",
+ "./c9.ide.installer/commands/pip",
+ "./c9.ide.installer/commands/gem",
+ "./c9.ide.installer/commands/zip",
+ "./c9.ide.installer/commands/symlink",
+ "./c9.ide.installer/commands/message",
+ {
+ packagePath: "./c9.ide.installer/commands/tar.gz",
+ bashBin: "bash"
+ },
+ "./c9.ide.installer/commands/ubuntu",
+ "./c9.ide.installer/cli",
+ {
+ packagePath: "./c9.ide.installer/installer",
+ homeDir: process.env.HOME,
+ installSelfCheck: false,
+ installPath: process.env.HOME + "/.c9",
+ cli: true
+ },
// "./c9.cli.sync/sync",
//"./c9.ide.keys/commands",
{
consumes: [],
- provides: ["settings", "workspace", "cli_commands", "c9"],
+ provides: ["settings", "workspace", "cli_commands", "c9", "error_handler"],
setup: function(options, imports, register) {
register(null, {
// @todo share with ace min
@@ -78,7 +117,12 @@ return [
debug: true,
hosted: false,
local: true,
- setStatus: function(){}
+ home: process.env.HOME,
+ setStatus: function(){},
+ location: ""
+ },
+ error_handler: {
+ log: function(){}
},
workspace: (function(){
var ws = new EventEmitter();
diff --git a/configs/client-default.js b/configs/client-default.js
index 39874673..789b64f7 100644
--- a/configs/client-default.js
+++ b/configs/client-default.js
@@ -515,6 +515,7 @@ module.exports = function(options) {
},
"plugins/c9.ide.panels/panel",
"plugins/c9.ide.panels/area",
+ "plugins/c9.ide.processlist/processlist",
// Installer
{
@@ -523,9 +524,14 @@ module.exports = function(options) {
},
"plugins/c9.automate/automate",
"plugins/c9.ide.installer/commands/centos",
+ "plugins/c9.ide.installer/commands/darwin",
"plugins/c9.ide.installer/commands/bash",
"plugins/c9.ide.installer/commands/npm",
+ "plugins/c9.ide.installer/commands/pip",
+ "plugins/c9.ide.installer/commands/gem",
+ "plugins/c9.ide.installer/commands/zip",
"plugins/c9.ide.installer/commands/symlink",
+ "plugins/c9.ide.installer/commands/message",
{
packagePath: "plugins/c9.ide.installer/commands/tar.gz",
bashBin: options.bashBin
diff --git a/node_modules/ace/lib/ace/ext/modelist.js b/node_modules/ace/lib/ace/ext/modelist.js
index 7a5a1e9c..6bc79c8b 100644
--- a/node_modules/ace/lib/ace/ext/modelist.js
+++ b/node_modules/ace/lib/ace/ext/modelist.js
@@ -122,7 +122,7 @@ var supportedModes = {
Pascal: ["pas|p"],
Perl: ["pl|pm"],
pgSQL: ["pgsql"],
- PHP: ["php|phtml"],
+ PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"],
Powershell: ["ps1"],
Praat: ["praat|praatscript|psc|proc"],
Prolog: ["plg|prolog"],
diff --git a/node_modules/ace/lib/ace/layer/text.js b/node_modules/ace/lib/ace/layer/text.js
index ced2c5f1..1e80b684 100644
--- a/node_modules/ace/lib/ace/layer/text.js
+++ b/node_modules/ace/lib/ace/layer/text.js
@@ -52,7 +52,7 @@ var Text = function(parentEl) {
this.EOL_CHAR_LF = "\xAC";
this.EOL_CHAR_CRLF = "\xa4";
this.EOL_CHAR = this.EOL_CHAR_LF;
- this.TAB_CHAR = "\u2192"; //"\u21E5";
+ this.TAB_CHAR = "\u2014"; //"\u21E5";
this.SPACE_CHAR = "\xB7";
this.$padding = 0;
@@ -128,8 +128,7 @@ var Text = function(parentEl) {
for (var i = 1; i < tabSize + 1; i++) {
if (this.showInvisibles) {
tabStr.push(""
- + this.TAB_CHAR
- + lang.stringRepeat(" ", i - 1)
+ + lang.stringRepeat(this.TAB_CHAR, i)
+ "");
} else {
tabStr.push(lang.stringRepeat(" ", i));
@@ -145,7 +144,7 @@ var Text = function(parentEl) {
spaceClass = " ace_invisible_space";
tabClass = " ace_invisible_tab";
var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
- var tabContent = this.TAB_CHAR + lang.stringRepeat(" ", this.tabSize - 1);
+ var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
} else{
var spaceContent = lang.stringRepeat(" ", this.tabSize);
var tabContent = spaceContent;
diff --git a/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js b/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js
index 9dc27bf8..245edf99 100644
--- a/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js
+++ b/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js
@@ -144,6 +144,16 @@ module.exports = {
exec("selectleft", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), '("foo")');
+
+ editor.setValue("", 1);
+ exec("selectleft", 1);
+ exec("insertstring", 1, '"');
+ assert.equal(editor.getValue(), '""');
+ exec("insertstring", 1, '\\');
+ exec("insertstring", 1, 'n');
+ exec("insertstring", 1, '"');
+ assert.equal(editor.getValue(), '"\\n"');
+
},
"test: xml": function() {
editor = new Editor(new MockRenderer());
diff --git a/node_modules/ace/lib/ace/mode/behaviour/cstyle.js b/node_modules/ace/lib/ace/mode/behaviour/cstyle.js
index a1dce91e..dd1b0d14 100644
--- a/node_modules/ace/lib/ace/mode/behaviour/cstyle.js
+++ b/node_modules/ace/lib/ace/mode/behaviour/cstyle.js
@@ -269,8 +269,8 @@ var CstyleBehaviour = function() {
if (leftChar == "\\" && token && /escape/.test(token.type))
return null;
- var stringBefore = token && /string/.test(token.type);
- var stringAfter = !rightToken || /string/.test(rightToken.type);
+ var stringBefore = token && /string|escape/.test(token.type);
+ var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
var pair;
if (rightChar == quote) {
diff --git a/node_modules/ace/lib/ace/mode/handlebars.js b/node_modules/ace/lib/ace/mode/handlebars.js
index 3f2e7179..164ad43f 100644
--- a/node_modules/ace/lib/ace/mode/handlebars.js
+++ b/node_modules/ace/lib/ace/mode/handlebars.js
@@ -13,7 +13,6 @@ var Mode = function() {
HtmlMode.call(this);
this.HighlightRules = HandlebarsHighlightRules;
this.$behaviour = new HtmlBehaviour();
-
this.foldingRules = new HtmlFoldMode();
};
@@ -21,7 +20,7 @@ var Mode = function() {
oop.inherits(Mode, HtmlMode);
(function() {
- this.blockComment = {start: "{!--", end: "--}"};
+ this.blockComment = {start: "{{!--", end: "--}}"};
this.$id = "ace/mode/handlebars";
}).call(Mode.prototype);
diff --git a/node_modules/ace/lib/ace/theme/katzenmilch.css b/node_modules/ace/lib/ace/theme/katzenmilch.css
index 0b5a7a23..a4559a2a 100644
--- a/node_modules/ace/lib/ace/theme/katzenmilch.css
+++ b/node_modules/ace/lib/ace/theme/katzenmilch.css
@@ -40,7 +40,7 @@
.ace-katzenmilch .ace_marker-layer .ace_bracket {
margin: -1px 0 0 -1px;
- border: 1px solid #000000
+ border: 1px solid rgba(0, 0, 0, 0.33);
}
.ace-katzenmilch .ace_marker-layer .ace_active-line {
diff --git a/node_modules/architect-build/compress.js b/node_modules/architect-build/compress.js
index f4e52eaa..343f5d70 100644
--- a/node_modules/architect-build/compress.js
+++ b/node_modules/architect-build/compress.js
@@ -17,7 +17,7 @@ function compress(sources, opts) {
if (pkg.file) console.log("Adding '" + pkg.file + "'.");
toplevel = UglifyJS.parse(pkg.source, {
- filename: pkg.file.replace(new RegExp("^" + opts.basepath + "/"), ""), //@todo remove prefix
+ filename: (pkg.file || pkg.id).replace(new RegExp("^" + opts.basepath + "/"), ""), //@todo remove prefix
toplevel: toplevel
});
});
diff --git a/node_modules/architect-build/npm_build.js b/node_modules/architect-build/npm_build.js
index 8912b0df..1bc1a643 100644
--- a/node_modules/architect-build/npm_build.js
+++ b/node_modules/architect-build/npm_build.js
@@ -157,8 +157,9 @@ function build(base, args, cb) {
plugin.packagePath_orig = plugin.packagePath;
});
};
- server(args, null, function(err, config) {
+ server(args, null, function(err, config, configPath) {
addModule("server.js");
+ addModule(configPath);
config.forEach(function(plugin) {
if (plugin.packagePath)
addModule(relPath(plugin.packagePath));
diff --git a/node_modules/frontdoor/lib/route.js b/node_modules/frontdoor/lib/route.js
index 0c699ab7..56343a48 100644
--- a/node_modules/frontdoor/lib/route.js
+++ b/node_modules/frontdoor/lib/route.js
@@ -137,6 +137,10 @@ module.exports = function Route(route, options, handler, types) {
var key = keys[i];
var param = params[key];
var type = param.type;
+ if (param.optional && value == null) {
+ match[key] = value;
+ continue;
+ }
try {
value = type.parse(value);
} catch (e) {
@@ -157,6 +161,7 @@ module.exports = function Route(route, options, handler, types) {
* the decoded and validated parameters are stored in `req.params`
* otherwhise an error is returned.
*/
+ this.decodeParams = decodeParams;
function decodeParams(req, res, next) {
var urlParams = req.match;
if (!urlParams) return;
@@ -197,10 +202,12 @@ module.exports = function Route(route, options, handler, types) {
break;
value = body[key]; // body is already JSON parsed
+ if (param.optional && value == null)
+ break;
isValid = type.check(value);
break;
case "query":
- if (param.optional && !(key in query))
+ if (param.optional && query[key] == null)
break;
try {
@@ -211,7 +218,7 @@ module.exports = function Route(route, options, handler, types) {
isValid = isValid === false ? false : type.check(value);
break;
case "url":
- if (param.optional && !(key in urlParams))
+ if (param.optional && urlParams[key] == null)
break;
value = urlParams[key]; // is already parsed and checked
diff --git a/node_modules/frontdoor/lib/route_test.js b/node_modules/frontdoor/lib/route_test.js
index 9e11be1c..d1a1bacd 100644
--- a/node_modules/frontdoor/lib/route_test.js
+++ b/node_modules/frontdoor/lib/route_test.js
@@ -133,7 +133,65 @@ module.exports = {
assert.ok(!route.match(req, "/ts/353676299181"));
assert.ok(!route.match(req, "/ts/abc"));
- }
+ },
+
+ "test router: decode parameter in body": function(next) {
+ var route = new Route("/user", {
+ params: {
+ id: {
+ type: "int",
+ optional: true,
+ source: "body"
+ }
+ }
+ }, sinon.stub());
+
+ var req = {
+ match: "match",
+ parsedUrl: {
+ query: ""
+ },
+ body: { id: 15 }
+ };
+ var res = {};
+
+ // Note: usually optionals would say 'source: "body",'
+ // but this should work
+ route.decodeParams(req, res, function(err, result) {
+ assert.equal(err, null);
+ assert.equal(req.params.id, 15);
+ next();
+ });
+ },
+
+ "test router: optional number argument can be falsy": function(next) {
+ var route = new Route("/user", {
+ params: {
+ id: {
+ type: "int",
+ optional: true,
+ source: "body"
+ }
+ }
+ }, sinon.stub());
+
+ var req = {
+ match: "match",
+ parsedUrl: {
+ query: ""
+ },
+ body: { id: null }
+ };
+ var res = {};
+
+ // Note: usually optionals would say 'source: "body",'
+ // but this should work
+ route.decodeParams(req, res, function(err, result) {
+ assert.equal(err, null);
+ assert.equal(req.params.id, null);
+ next();
+ });
+ },
};
!module.parent && require("asyncjs").test.testcase(module.exports).exec();
diff --git a/node_modules/vfs-local/localfs.js b/node_modules/vfs-local/localfs.js
index 2ecf079e..d43c1756 100644
--- a/node_modules/vfs-local/localfs.js
+++ b/node_modules/vfs-local/localfs.js
@@ -2409,7 +2409,13 @@ module.exports = function setup(fsOptions) {
}
////////////////////////////////////////////////////////////////////////////////
-
+
+ if (fsOptions.extendApi) {
+ for (var i in fsOptions.extendApi) {
+ extend(i, fsOptions.extendApi[i], function() {});
+ }
+ }
+
return vfs;
};
diff --git a/package.json b/package.json
index 629af2af..2dc5c639 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
},
"dependencies": {
"acorn": ">=0.11.0",
- "amd-loader": "~0.0.5",
+ "amd-loader": "",
"async": "^0.9.0",
"base64id": "~0.1.0",
"c9": "",
@@ -60,30 +60,30 @@
"c9.ide.language.javascript.tern": "#7aab8b0b6a",
"c9.ide.language.javascript.infer": "#cfec494a3c",
"c9.ide.language.jsonalyzer": "#21b64e5820",
- "c9.ide.collab": "#504750d8f0",
+ "c9.ide.collab": "#edef363853",
"c9.ide.local": "#2bfd7ff051",
"c9.ide.find": "#6cc6d3379d",
"c9.ide.find.infiles": "#72582de3cd",
"c9.ide.find.replace": "#e4daf722b8",
"c9.ide.run.debug": "#638e6b00b3",
- "c9.automate": "#b1b0cca13a",
+ "c9.automate": "#47e2c429c9",
"c9.ide.ace.emmet": "#e5f1a92ac3",
"c9.ide.ace.gotoline": "#4d1a93172c",
"c9.ide.ace.keymaps": "#43445d6306",
"c9.ide.ace.repl": "#ada99852fa",
"c9.ide.ace.split": "#0ae0151c78",
"c9.ide.ace.statusbar": "#d7b45bb7c3",
- "c9.ide.ace.stripws": "#34426a03d1",
+ "c9.ide.ace.stripws": "#cf0f42ac59",
"c9.ide.behaviors": "#6aad7006a0",
"c9.ide.closeconfirmation": "#a28bfd8272",
"c9.ide.configuration": "#adf50fdaa2",
- "c9.ide.dialog.wizard": "#ea640aa5a1",
+ "c9.ide.dialog.wizard": "#7667ec79a8",
"c9.ide.fontawesome": "#781602c5d8",
"c9.ide.format": "#f51451ac57",
"c9.ide.help.support": "#60e88f5680",
"c9.ide.imgeditor": "#08bbc53578",
"c9.ide.immediate": "#6845a93705",
- "c9.ide.installer": "#4c25b26f70",
+ "c9.ide.installer": "#a1e01c07a3",
"c9.ide.mount": "#32e79866ee",
"c9.ide.navigate": "#64156c7f4a",
"c9.ide.newresource": "#f1f0624768",
diff --git a/plugins/c9.cli.publish/install.js b/plugins/c9.cli.publish/install.js
new file mode 100644
index 00000000..b1643e22
--- /dev/null
+++ b/plugins/c9.cli.publish/install.js
@@ -0,0 +1,590 @@
+define(function(require, exports, module) {
+ main.consumes = [
+ "Plugin", "cli_commands", "proc", "api", "auth", "installer",
+ "installer.cli"
+ ];
+ main.provides = ["cli.install"];
+ return main;
+
+ function main(options, imports, register) {
+ var Plugin = imports.Plugin;
+ var cmd = imports.cli_commands;
+ var proc = imports.proc;
+ var auth = imports.auth;
+ var api = imports.api;
+ var installer = imports.installer;
+ var installerCLI = imports["installer.cli"];
+
+ var dirname = require("path").dirname;
+
+ var TEST_MODE = !!process.env.C9_TEST_MODE;
+ var TAR = "tar";
+ var APIHOST = options.apiHost;
+ var BASICAUTH = process.env.C9_TEST_AUTH;
+ var SCM = {
+ "git": {
+ binary: "git",
+ clone: "clone"
+ },
+ "mercurial": {
+ binary: "hg",
+ clone: "clone"
+ },
+ "hg": {
+ binary: "hg",
+ clone: "clone"
+ }
+ };
+
+ var fs = require("fs");
+ var join = require("path").join;
+ var os = require("os");
+ var http = require(APIHOST.indexOf("localhost") > -1 ? "http" : "https");
+
+ var verbose = false;
+ var force = false;
+
+ // Set up basic auth for api if needed
+ if (BASICAUTH) api.basicAuth = BASICAUTH;
+
+ /***** Initialization *****/
+
+ var plugin = new Plugin("Ajax.org", main.consumes);
+ // var emit = plugin.getEmitter();
+
+ var loaded;
+ function load(){
+ if (loaded) return;
+ loaded = true;
+
+ cmd.addCommand({
+ name: "install",
+ info: " Installs a cloud9 package.",
+ usage: "[--verbose] [--force] [--global] [--local] [--debug] [[@] | . ]",
+ options: {
+ "local": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ "global": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ "debug": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ "package" : {
+ description: "",
+ "default": false
+ },
+ "verbose" : {
+ "description": "Output more information",
+ "alias": "v",
+ "default": false,
+ "boolean": true
+ },
+ "force" : {
+ "description": "Ignore warnings",
+ "alias": "f",
+ "default": false,
+ "boolean": true
+ }
+ },
+ check: function(argv) {
+ if (argv._.length < 2 && !argv["package"])
+ throw new Error("package");
+ },
+ exec: function(argv) {
+ verbose = argv["verbose"];
+ force = argv["force"];
+
+ if (argv.accessToken)
+ auth.accessToken = argv.accessToken;
+
+ if (!argv.local && !argv.debug) {
+ if (!process.env.C9_PID) {
+ console.warn("It looks like you are not running on c9.io. Will default to local installation of the package");
+ argv.local = true;
+ }
+ }
+
+ var name = argv._[1];
+ var test = name == ".";
+ if (test)
+ name = require("path").basename(process.cwd());
+
+ install(
+ name,
+ {
+ global: argv.global,
+ local: argv.local,
+ debug: argv.debug,
+ test: test
+ },
+ function(err, data){
+ if (err) {
+ console.error(err.message || "Terminated.");
+ process.exit(1);
+ }
+ else {
+ console.log("Succesfully installed", name + (argv.debug ? "" : "@" + data.version));
+ process.exit(0);
+ }
+ });
+ }
+ });
+
+ cmd.addCommand({
+ name: "remove",
+ info: " Removes a cloud9 package.",
+ usage: "[--verbose] [--global] [--local] ", // @TODO --global
+ options: {
+ "local": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ "global": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ "package" : {
+ description: ""
+ },
+ "verbose" : {
+ "description": "Output more information",
+ "alias": "v",
+ "default": false,
+ "boolean": true
+ }
+ },
+ check: function(argv) {
+ if (argv._.length < 2 && !argv["package"])
+ throw new Error("package");
+ },
+ exec: function(argv) {
+ verbose = argv["verbose"];
+
+ if (argv.accessToken)
+ auth.accessToken = argv.accessToken;
+
+ var name = argv._[1];
+ uninstall(
+ name,
+ {
+ global: argv.global,
+ local: argv.local
+ },
+ function(err, data){
+ if (err) {
+ console.error(err.message || "Terminated.");
+ process.exit(1);
+ }
+ else {
+ console.log("Succesfully removed", name);
+ process.exit(0);
+ }
+ });
+ }
+ });
+ }
+
+ /***** Methods *****/
+
+ function install(packageName, options, callback){
+ // Call install url
+ var parts = packageName.split("@");
+ var name = parts[0];
+ var version = parts[1];
+ var repository;
+
+ if ((!version || options.debug) && !options.test) {
+ if (verbose)
+ console.log("Retrieving package info");
+
+ api.packages.get(name, function (err, info) {
+ if (err) return callback(err);
+
+ if (verbose)
+ console.log("Found:", info);
+
+ version = info.latest;
+ repository = info.repository;
+
+ installPackage();
+ });
+ }
+ else {
+ installPackage();
+ }
+
+ function prepareDirectory(callback){
+ // Create package dir
+ var packagePath = process.env.HOME + "/.c9/plugins/" + name;
+ var exists = fs.existsSync(packagePath);
+
+ // Ignore when testing and in the same dir
+ if (options.test && process.cwd() == packagePath)
+ exists = false;
+
+ if (exists) {
+ if (!force && !options.test)
+ return callback(new Error("WARNING: Directory not empty: " + packagePath
+ + ". Use --force to overwrite."));
+
+ proc.execFile("rm", {
+ args: ["-Rf", packagePath]
+ }, function(){
+ mkdirP(packagePath);
+ callback(null, packagePath);
+ });
+ }
+ else {
+ mkdirP(packagePath);
+ callback(null, packagePath);
+ }
+ }
+
+ function installPackage(){
+ if (!version && !options.test)
+ return callback(new Error("No version found for this package"));
+
+ if (options.local) {
+ installLocal();
+ }
+ else if (options.debug) {
+ installDebug();
+ }
+ else {
+ installFull();
+ }
+ }
+
+ function installLocal(){
+ if (verbose)
+ console.log("Installing package locally");
+
+ prepareDirectory(function(err, packagePath){
+ if (err) return callback(err);
+
+ function installNPM(){
+ proc.spawn(join(process.env.HOME, ".c9/node/bin/npm"), {
+ args: ["install"],
+ cwd: packagePath
+ }, function(err, p){
+ if (err) return callback(err);
+
+ if (verbose) {
+ p.stdout.on("data", function(c){
+ process.stdout.write(c.toString("utf8"));
+ });
+ p.stderr.on("data", function(c){
+ process.stderr.write(c.toString("utf8"));
+ });
+ }
+
+ p.on("exit", function(code){
+ // Done
+ callback(err, {
+ version: version
+ });
+ });
+ });
+ }
+
+ if (options.test) {
+ try {
+ var json = JSON.parse(fs.readFileSync(join(process.cwd(), "package.json")));
+ if (json.private)
+ return callback(new Error("ERROR: Private flag in package.json prevents from installing"));
+ }
+ catch(e) {
+ return callback(new Error("ERROR: Invalid package: " + e.message));
+ }
+
+ if (process.cwd() == packagePath)
+ installNPM();
+ else {
+ proc.execFile("cp", {
+ args: ["-R", process.cwd(), dirname(packagePath)]
+ }, function(err){
+ if (err) return callback(err);
+
+ installNPM();
+ });
+ }
+
+ return;
+ }
+
+ // Download package
+ var gzPath = join(os.tmpDir(), name + "@" + version + ".tar.gz");
+ var file = fs.createWriteStream(gzPath);
+
+ var path = "/packages/" + name + "/versions/" + version
+ + "/download?access_token="
+ + encodeURIComponent(auth.accessToken);
+ var host = APIHOST.split(":")[0];
+ var port = parseInt(APIHOST.split(":")[1]) || null;
+
+ var request = http.get({
+ agent: false,
+ method: "get",
+ host: host,
+ port: port,
+ auth: BASICAUTH,
+ path: path
+ }, function(response){
+ response.pipe(file);
+ });
+
+ if (verbose)
+ console.log("Downloading package to", gzPath);
+
+ request.on('response', function(res) {
+ if (res.statusCode != 200)
+ return callback(new Error("Unknown Error:" + res.statusCode));
+ });
+
+ file.on('finish', function() {
+ if (verbose)
+ console.log("Unpacking", gzPath, "to", packagePath);
+
+ // Untargz package
+ proc.spawn(TAR, {
+ args: ["-C", normalizePath(packagePath), "-zxvf", normalizePath(gzPath)]
+ }, function(err, p){
+ if (err) return callback(err);
+
+ if (verbose) {
+ p.stdout.on("data", function(c){
+ process.stdout.write(c.toString("utf8"));
+ });
+ p.stderr.on("data", function(c){
+ process.stderr.write(c.toString("utf8"));
+ });
+ }
+
+ p.on("exit", function(code){
+ var err = code !== 0
+ ? new Error("Failed to unpack package")
+ : null;
+ if (err) return callback(err);
+
+ installNPM();
+ });
+ });
+ });
+ });
+ }
+
+ function installDebug(){
+ if (verbose)
+ console.log("Installing debug version of package");
+
+ if (!options.test)
+ return callback(new Error("Dry run is not supported for debug installations"));
+
+ prepareDirectory(function(err, packagePath){
+ if (err) return callback(err);
+
+ if (verbose)
+ console.log("Cloning repository: ", repository);
+
+ // Git clone repository
+ var scm = SCM[repository.type];
+ proc.spawn(scm.binary, {
+ args: [scm.clone, repository.url, packagePath]
+ }, function(err, p){
+ if (err) return callback(err);
+
+ if (verbose) {
+ p.stdout.on("data", function(c){
+ process.stdout.write(c.toString("utf8"));
+ });
+ p.stderr.on("data", function(c){
+ process.stderr.write(c.toString("utf8"));
+ });
+ }
+
+ p.on("exit", function(code){
+ var err = code !== 0
+ ? new Error("Failed to clone package from repository. Do you have access?")
+ : null;
+
+ // Done
+ callback(err);
+ });
+ });
+ });
+ }
+
+ function installFull(){
+ // Install Locally
+ options.local = true;
+ install(name + "@" + version, options, function(err){
+ if (err) return callback(err);
+
+ var path = process.env.HOME + "/.c9/plugins/" + name;
+ fs.readFile(path + "/package.json", "utf8", function(err, data){
+ if (err) return callback(new Error("Package.json not found in " + path));
+
+ var installPath;
+ try { installPath = JSON.parse(data).installer; }
+ catch(e){
+ return callback(new Error("Could not parse package.json in " + path));
+ }
+
+ if (installPath) {
+ installerCLI.verbose = verbose;
+ installer.createSession(name, version || "", require(path + "/" + installPath), function(err){
+ if (err) return callback(new Error("Error Installing Package " + name + "@" + version));
+ installToDatabase();
+ }, force || options.test);
+ }
+ else
+ installToDatabase();
+ });
+
+
+ function installToDatabase(){
+ if (options.test)
+ return callback(null, { version: "test" });
+
+ if (verbose)
+ console.log("Notifying c9.io that packages needs to be installed");
+
+ var endpoint = options.global ? api.user : api.project;
+ var url = "install/" + packageName + "/" + version + "?mode=silent";
+
+ endpoint.post(url, function(err, info){
+ callback(err, info);
+ });
+ }
+ });
+ }
+ }
+
+ function uninstall(packageName, options, callback){
+ // Call uninstall url
+ var parts = packageName.split("@");
+ var name = parts[0];
+ var version = parts[1];
+
+ if (!version) {
+ api.packages.get(name, function (err, info) {
+ if (err) return callback(err);
+ version = info.latest;
+
+ uninstallPackage();
+ });
+ }
+ else {
+ uninstallPackage();
+ }
+
+ function uninstallPackage(){
+ if (options.local || options.debug) {
+ // rm -Rf
+ var packagePath = process.env.HOME + "/.c9/plugins/" + name;
+ proc.spawn("rm", {
+ args: ["-rf", packagePath]
+ }, function(err, p){
+ if (err) return callback(err);
+
+ if (verbose) {
+ p.stdout.on("data", function(c){
+ process.stdout.write(c.toString("utf8"));
+ });
+ p.stderr.on("data", function(c){
+ process.stderr.write(c.toString("utf8"));
+ });
+ }
+
+ p.on("exit", function(code){
+ var err = code !== 0
+ ? new Error("Failed to remove package.")
+ : null;
+
+ // if debug > see if should be installed and put back original
+ // @TODO
+
+ // Done
+ callback(err);
+ });
+ });
+ }
+ else {
+ var endpoint = options.global ? api.user : api.project;
+ var url = "uninstall/" + packageName;
+
+ endpoint.post(url, function(err, info){
+ callback(err, info);
+ });
+ }
+ }
+ }
+
+ function mkdirP(path){
+ var dirs = path.split('/');
+ var prevDir = dirs.splice(0,1) + "/";
+ while (dirs.length > 0) {
+ var curDir = prevDir + dirs.splice(0,1);
+ if (! fs.existsSync(curDir) ) {
+ fs.mkdirSync(curDir);
+ }
+ prevDir = curDir + '/';
+ }
+ }
+
+ function normalizePath(p) {
+ if (process.platform == "win32")
+ p = p.replace(/\\/g, "/").replace(/^(\w):/, "/$1");
+ return p;
+ }
+
+ /***** Lifecycle *****/
+
+ plugin.on("load", function(){
+ load();
+ });
+ plugin.on("enable", function(){
+
+ });
+ plugin.on("disable", function(){
+
+ });
+ plugin.on("unload", function(){
+ loaded = false;
+ verbose = false;
+ force = false;
+ });
+
+ /***** Register and definfe API *****/
+
+ /**
+ *
+ **/
+ plugin.freezePublicAPI({
+ /**
+ *
+ */
+ install: install,
+
+ /**
+ *
+ */
+ uninstall: uninstall
+ });
+
+ register(null, {
+ "cli.install": plugin
+ });
+ }
+
+});
\ No newline at end of file
diff --git a/plugins/c9.cli.publish/list.js b/plugins/c9.cli.publish/list.js
new file mode 100644
index 00000000..c1511530
--- /dev/null
+++ b/plugins/c9.cli.publish/list.js
@@ -0,0 +1,131 @@
+define(function(require, exports, module) {
+ main.consumes = ["Plugin", "cli_commands", "api"];
+ main.provides = ["cli.list"];
+ return main;
+
+ function main(options, imports, register) {
+ var Plugin = imports.Plugin;
+ var cmd = imports.cli_commands;
+ var api = imports.api;
+
+ var BASICAUTH = process.env.C9_TEST_AUTH;
+ var verbose = false;
+
+ var LIGHTBlUE = "\x1b[01;94m";
+ var RESETCOLOR = "\x1b[0m";
+ var PADDING = 2;
+
+ // Set up basic auth for api if needed
+ if (BASICAUTH) api.basicAuth = BASICAUTH;
+
+ /***** Initialization *****/
+
+ var plugin = new Plugin("Ajax.org", main.consumes);
+ // var emit = plugin.getEmitter();
+
+ var loaded;
+ function load(){
+ if (loaded) return;
+ loaded = true;
+
+ cmd.addCommand({
+ name: "list",
+ info: " Lists all available packages.",
+ usage: "[--json]",
+ options: {
+ "json": {
+ description: "",
+ "default": false,
+ "boolean": true
+ },
+ },
+ check: function(argv) {},
+ exec: function(argv) {
+ verbose = argv["verbose"];
+
+ list(argv.json, function(err){
+ if (err)
+ console.error(err.message || err);
+ process.exit(err ? 1 : 0);
+ });
+ }
+ });
+ }
+
+ /***** Methods *****/
+
+ function stringifyError(err){
+ return (verbose ? JSON.stringify(err, 4, " ") : (typeof err == "string" ? err : err.message));
+ }
+
+ function pad(str, nr){
+ return str + Array(nr - str.length).join(" ");
+ }
+
+ function list(asJson, callback){
+ callback = callback || function(){};
+ api.packages.get("", function(err, list){
+ if (err) {
+ console.error("ERROR: Could not get list: ", stringifyError(err));
+ return callback(err);
+ }
+ // TODO if tty.isatty(process.stdout) use process.stdout.columns process.stdout.rows
+ // to give nicely wrapped output
+ if (asJson) {
+ console.log(JSON.stringify(list, 4, " "));
+ return callback(null, list);
+ }
+ else {
+ var max = [0, 0, 0, 0];
+ list.forEach(function(item){
+ max[0] = Math.max(max[0], item.name.length);
+ max[1] = Math.max(max[1], Math.min(50, item.description.split(".")[0].length));
+ max[2] = Math.max(max[2], item.name.length + 33);
+ max[3] = Math.max(max[3], (item.website || item.repository.url).length);
+ });
+ list.forEach(function(item){
+ console.log(
+ pad(item.name, max[0] + PADDING),
+ pad(item.description.split(".")[0], max[1] + PADDING),
+ LIGHTBlUE + pad("https://c9.io/profile/packages/" + item.name, max[2] + PADDING) + RESETCOLOR,
+ item.website || item.repository.url); // do not pad last item
+ });
+ return callback(null, list);
+ }
+ });
+ }
+
+ /***** Lifecycle *****/
+
+ plugin.on("load", function(){
+ load();
+ });
+ plugin.on("enable", function(){
+
+ });
+ plugin.on("disable", function(){
+
+ });
+ plugin.on("unload", function(){
+ loaded = false;
+ verbose = false;
+ });
+
+ /***** Register and definfe API *****/
+
+ /**
+ *
+ **/
+ plugin.freezePublicAPI({
+ /**
+ *
+ */
+ list: list
+ });
+
+ register(null, {
+ "cli.list": plugin
+ });
+ }
+
+});
diff --git a/plugins/c9.cli.publish/publish.git.sh b/plugins/c9.cli.publish/publish.git.sh
index f1208cb4..bf32c8d7 100644
--- a/plugins/c9.cli.publish/publish.git.sh
+++ b/plugins/c9.cli.publish/publish.git.sh
@@ -1,13 +1,13 @@
-PACKAGE_PATH=$1
-VERSION=$2
-CWD=${PWD}
+VERSION="$1"
+PACKAGE_PATH="$2"
+CWD="${PWD}"
if [ ! -d .git ]; then
echo "$CWD is not a git repository" 1>&2
exit 1
fi
-if [ ! -e $PACKAGE_PATH ]; then
+if [ ! -f "$PACKAGE_PATH" ]; then
echo "Could not find package.json" 1>&2
exit 1
fi
diff --git a/plugins/c9.cli.publish/publish.js b/plugins/c9.cli.publish/publish.js
index 2ab55d97..8bb04348 100644
--- a/plugins/c9.cli.publish/publish.js
+++ b/plugins/c9.cli.publish/publish.js
@@ -11,7 +11,7 @@ define(function(require, exports, module) {
var api = imports.api;
var TEST_MODE = !!process.env.C9_TEST_MODE;
- var SHELLSCRIPT = TEST_MODE ? "" : require("text!./publish.git.sh").toString("utf8");
+ var SHELLSCRIPT = TEST_MODE ? "" : require("text!./publish.git.sh");
var TAR = "tar";
var APIHOST = options.apiHost;
var BASICAUTH = process.env.C9_TEST_AUTH;
@@ -43,6 +43,7 @@ define(function(require, exports, module) {
var verbose = false;
var force = false;
var dryRun = false;
+ var createTag = false;
// Set up basic auth for api if needed
if (BASICAUTH) api.basicAuth = BASICAUTH;
@@ -78,16 +79,23 @@ define(function(require, exports, module) {
"description": "Only build a test version",
"default": false,
"boolean": true
+ },
+ "tag" : {
+ "description": "Create git tag for published version",
+ "alias": "t",
+ "default": false,
+ "boolean": true
}
},
check: function(argv) {
- if (argv._.length < 2 && !argv["newversion"] && !argv["dry-run"])
- throw new Error("Missing version");
+ // if (argv._.length < 2 && !argv["newversion"] && !argv["dry-run"])
+ // throw new Error("Missing version");
},
exec: function(argv) {
verbose = argv["verbose"];
force = argv["force"];
dryRun = argv["dry-run"];
+ createTag = argv["tag"];
publish(
argv._[1],
@@ -108,9 +116,9 @@ define(function(require, exports, module) {
}
});
- cmd.addCommand({
+ cmd.addCommand({
name: "build",
- info: " Builds development version of package to load in non-debug mode.",
+ info: " Builds development version of package to load in non-debug mode.",
usage: "[--devel]",
options: {
"devel" : {
@@ -148,12 +156,12 @@ define(function(require, exports, module) {
.trim()
.replace(/PACKAGE_NAME/g, packageName);
- fs.writeFileSync(cwd + "/__installed__.js", code, "utf8")
- } else {
- dryRun = true
- publish({local: true}, function(err, data){});
+ fs.writeFileSync(cwd + "/__installed__.js", code, "utf8");
+ }
+ else {
+ dryRun = true;
+ publish({local: true}, function(){});
}
-
}
});
@@ -186,156 +194,6 @@ define(function(require, exports, module) {
});
}
});
-
- cmd.addCommand({
- name: "install",
- info: " Installs a cloud9 package.",
- usage: "[--verbose] [--force] [--global] [--local] [--debug] [@]", // @TODO --global, --debug, --local
- options: {
- "local": {
- description: "",
- "default": false,
- "boolean": true
- },
- "global": {
- description: "",
- "default": false,
- "boolean": true
- },
- "debug": {
- description: "",
- "default": false,
- "boolean": true
- },
- "package" : {
- description: "",
- "default": false
- },
- "verbose" : {
- "description": "Output more information",
- "alias": "v",
- "default": false,
- "boolean": true
- },
- "force" : {
- "description": "Ignore warnings",
- "alias": "f",
- "default": false,
- "boolean": true
- }
- },
- check: function(argv) {
- if (argv._.length < 2 && !argv["package"])
- throw new Error("package");
- },
- exec: function(argv) {
- verbose = argv["verbose"];
- force = argv["force"];
-
- if (argv.accessToken)
- auth.accessToken = argv.accessToken;
-
- if (!argv.local && !argv.debug) {
- if (!process.env.C9_PID) {
- console.warn("It looks like you are not running on c9.io. Will default to local installation of the package");
- argv.local = true;
- }
- }
-
- var name = argv._[1];
- install(
- name,
- {
- global: argv.global,
- local: argv.local,
- debug: argv.debug
- },
- function(err, data){
- if (err) {
- console.error(err.message || "Terminated.");
- process.exit(1);
- }
- else {
- console.log("Succesfully installed", name + (argv.debug ? "" : "@" + data.version));
- process.exit(0);
- }
- });
- }
- });
-
- cmd.addCommand({
- name: "remove",
- info: " Removes a cloud9 package.",
- usage: "[--verbose] [--global] [--local] ", // @TODO --global
- options: {
- "local": {
- description: "",
- "default": false,
- "boolean": true
- },
- "global": {
- description: "",
- "default": false,
- "boolean": true
- },
- "package" : {
- description: ""
- },
- "verbose" : {
- "description": "Output more information",
- "alias": "v",
- "default": false,
- "boolean": true
- }
- },
- check: function(argv) {
- if (argv._.length < 2 && !argv["package"])
- throw new Error("package");
- },
- exec: function(argv) {
- verbose = argv["verbose"];
-
- if (argv.accessToken)
- auth.accessToken = argv.accessToken;
-
- var name = argv._[1];
- uninstall(
- name,
- {
- global: argv.global,
- local: argv.local
- },
- function(err, data){
- if (err) {
- console.error(err.message || "Terminated.");
- process.exit(1);
- }
- else {
- console.log("Succesfully removed", name);
- process.exit(0);
- }
- });
- }
- });
-
- cmd.addCommand({
- name: "list",
- info: " Lists all available packages.",
- usage: "[--json]",
- options: {
- "json": {
- description: "",
- "default": false,
- "boolean": true
- },
- },
- check: function(argv) {},
- exec: function(argv) {
- verbose = argv["verbose"];
-
- list(argv.json);
- }
- });
}
/***** Methods *****/
@@ -344,27 +202,6 @@ define(function(require, exports, module) {
return (verbose ? JSON.stringify(err, 4, " ") : (typeof err == "string" ? err : err.message));
}
- function list(asJson, callback){
- callback = callback || function(){};
- api.packages.get("", function(err, list){
- if (err) {
- console.error("ERROR: Could not get list: ", stringifyError(err));
- return callback(err);
- }
-
- if (asJson) {
- console.log(JSON.stringify(list, 4, " "));
- return callback(null, list);
- }
- else {
- list.forEach(function(item){
- console.log(item.name, "https://c9.io/packages/" + item.name);
- });
- return callback(null, list);
- }
- });
- }
-
function publish(options, callback) {
if (typeof options != "object")
options = {version: options};
@@ -372,7 +209,7 @@ define(function(require, exports, module) {
var version = options.version;
var cwd = process.cwd();
var packagePath = cwd + "/package.json";
- fs.readFile(packagePath, function(err, data){
+ fs.readFile(packagePath, "utf8", function(err, data){
if (err) return callback(new Error("ERROR: Could not find package.json in " + cwd));
var json;
@@ -382,6 +219,8 @@ define(function(require, exports, module) {
}
// Basic Validation
+ if (json.private)
+ return callback(new Error("ERROR: Private flag in package.json prevents from publishing"));
if (!json.name)
return callback(new Error("ERROR: Missing name property in package.json"));
if (basename(cwd) != json.name) {
@@ -389,10 +228,10 @@ define(function(require, exports, module) {
if (!force)
return callback(new Error("Use --force to ignore this warning."));
}
- if (!json.description)
- return callback(new Error("ERROR: Missing description property in package.json"));
if (!json.repository)
return callback(new Error("ERROR: Missing repository property in package.json"));
+ if (!json.repository.url)
+ return callback(new Error("ERROR: Missing repository.url property in package.json"));
if (!json.categories || json.categories.length == 0)
return callback(new Error("ERROR: At least one category is required in package.json"));
@@ -403,6 +242,12 @@ define(function(require, exports, module) {
return callback(new Error("Use --force to ignore these warnings."));
}
+ if (json.description)
+ console.warn("WARNING: Description property in package.json will be ignored. README.md will be used.");
+
+ var description = fs.readFileSync(join(cwd, "README.md"), "utf8")
+ .replace(/^\#.*\n*/, "");
+
// Validate plugins
var plugins = {};
fs.readdirSync(cwd).forEach(function(filename) {
@@ -437,7 +282,7 @@ define(function(require, exports, module) {
if (warned && !force && !dryRun)
return callback(new Error("Use --force to ignore these warnings."));
- if (!dryRun) {
+ if (version) {
var v = (json.version || "0.0.1").split(".");
// Update the version field in the package.json file
if (version == "major") {
@@ -458,47 +303,26 @@ define(function(require, exports, module) {
json.version = v.join(".");
}
- if (dryRun)
- return build();
+ return build();
- // Write the package.json file
- fs.writeFile(packagePath, JSON.stringify(json, null, " "), function(err){
- if (err) return callback(err);
+ function updatePackageJSON(next) {
+ if (!version)
+ return next();
- if (dryRun) return build();
-
- SHELLSCRIPT = SHELLSCRIPT
- .replace(/\$1/, packagePath)
- .replace(/\$2/, json.version);
-
- // commit
- proc.spawn("bash", {
- args: ["-c", SHELLSCRIPT]
- }, function(err, p){
- if (err) return callback(err);
-
- if (verbose) {
- p.stdout.on("data", function(c){
- process.stdout.write(c.toString("utf8"));
- });
- p.stderr.on("data", function(c){
- process.stderr.write(c.toString("utf8"));
- });
- }
-
- p.on("exit", function(code, stderr, stdout){
- if (code !== 0)
- return callback(new Error("ERROR: publish failed with exit code " + code));
-
- console.log("Created tag and updated package.json to version", json.version);
-
- build();
+ // Write the package.json file
+ var indent = data.match(/{\n\r?^ {4}"/) ? 4 : 2;
+ var newData = JSON.stringify(json, null, indent);
+ fs.writeFile(cwd + "/.c9/.build/package.json", newData, function(){
+ if (dryRun)
+ return next(); // if dry-run is passed only update path in .build
+ fs.writeFile(packagePath, newData, function(err){
+ if (err) return callback(err);
+ return next();
});
});
- });
+ }
// Build the package
- // @TODO use a proper package tool
// @TODO add a .c9exclude file that excludes files
var zipFilePath;
function build(){
@@ -622,7 +446,7 @@ define(function(require, exports, module) {
extraCode.push({
type: "installer",
filename: json.installer,
- data: version
+ data: installerVersion
});
}
@@ -718,38 +542,62 @@ define(function(require, exports, module) {
});
},
function(next) {
- var filename = options.local ? "__installed__.js" : "__packed__.js";
- fs.writeFile(filename, result.code, "utf8", next);
+ if (options.local)
+ fs.writeFile(cwd + "__installed__.js", result.code, "utf8", callback);
+ next();
},
function(next) {
- // console.log(packedFiles)
- if (options.local)
- return callback();
- zip(packedFiles);
+ proc.execFile("rm", {
+ args: ["-rf", ".c9/.build"],
+ cwd: cwd
+ }, function() {
+ mkdirP(cwd + "/.c9/.build");
+ fs.writeFile(cwd + "/.c9/.build/__installed__.js", result.code, "utf8", next);
+ });
+ },
+ function(next) {
+ var copy = require("architect-build/copy");
+
+ var excludeRe = /^\.(gitignore|hgignore|git|c9|hg)$/;
+ var excludeMap = Object.create(null);
+
+ packedFiles.push(cwd + "/__installed__.js");
+ packedFiles.forEach(function(p) {
+ p = "/" + normalizePath(Path.relative(cwd, p));
+ excludeMap[p] = 1;
+ });
+ copy(cwd, cwd + "/.c9/.build", {
+ exclude: function(name, parent) {
+ if (excludeRe.test(name))
+ return true;
+ var fullPath = parent.substr(cwd.length) + "/" + name;
+ if (excludeMap[fullPath])
+ return true;
+ return false;
+ }
+ });
+ next();
+ },
+ updatePackageJSON,
+ function(next) {
+ zip();
}
]);
}
- function zip(ignore){
+ function zip(){
zipFilePath = join(os.tmpDir(), json.name + "@" + json.version) + ".tar.gz";
- var tarArgs = ["-zcvf", normalizePath(zipFilePath), "."];
+ var tarArgs = ["-zcvf", normalizePath(zipFilePath)];
var c9ignore = normalizePath(process.env.HOME + "/.c9/.c9ignore");
fs.exists(c9ignore, function (exists) {
if (exists) {
tarArgs.push("--exclude-from=" + c9ignore);
}
- ignore.forEach(function(p) {
- p = Path.relative(cwd, p);
- if (!/^\.+\//.test(p)) {
- tarArgs.push("--exclude=./" + normalizePath(p));
- }
- });
- tarArgs.push("--transform='flags=r;s|__packed__|__installed__|'");
- // console.log(tarArgs)
+ tarArgs.push(".");
proc.spawn(TAR, {
args: tarArgs,
- cwd: cwd
+ cwd: cwd + "/.c9/.build"
}, function(err, p){
if (err) return callback(err);
@@ -798,7 +646,7 @@ define(function(require, exports, module) {
contentType: "application/json",
body: {
name: json.name,
- description: json.description,
+ description: description,
owner_type: "user", // @TODO implement this when adding orgs
owner_id: parseInt(user.id),
permissions: json.permissions || "world",
@@ -830,7 +678,7 @@ define(function(require, exports, module) {
repository: json.repository,
longname: json.longname,
website: json.website,
- description: json.description,
+ description: description,
screenshots: json.screenshots,
pricing: json.pricing,
enabled: true
@@ -840,7 +688,7 @@ define(function(require, exports, module) {
return callback(new Error("ERROR: Failed to update existing package - "
+ stringifyError(err)));
if (verbose)
- console.log("Successfully updated existing package");
+ console.log("Successfully updated metadata of existing package");
next(pkg);
});
@@ -875,15 +723,47 @@ define(function(require, exports, module) {
form.pipe(request);
request.on('response', function(res) {
+ // TODO better handle version exists error
+ if (res.statusCode == 412 && !version)
+ console.error("ERROR: most likely version " + json.version + " already exisits, try increasing version");
if (res.statusCode != 200)
return callback(new Error("ERROR: Unknown Error:" + res.statusCode));
- // Create Version Complete
- callback(null, json);
+ commitAndPush();
});
}
});
}
+
+ function commitAndPush() {
+ // Create Version Complete
+ if (!createTag)
+ callback(null, json);
+
+ proc.spawn("bash", {
+ args: ["-c", SHELLSCRIPT, "--", json.version, normalizePath(packagePath)]
+ }, function(err, p){
+ if (err) return callback(err);
+
+ if (verbose) {
+ p.stdout.on("data", function(c){
+ process.stdout.write(c.toString("utf8"));
+ });
+ p.stderr.on("data", function(c){
+ process.stderr.write(c.toString("utf8"));
+ });
+ }
+
+ p.on("exit", function(code, stderr, stdout){
+ if (code !== 0)
+ return callback(new Error("ERROR: publish failed with exit code " + code));
+
+ console.log("Created tag and updated package.json to version", json.version);
+
+ callback(null, json);
+ });
+ });
+ }
});
}
@@ -905,258 +785,6 @@ define(function(require, exports, module) {
});
}
- function install(packageName, options, callback){
- // Call install url
- var parts = packageName.split("@");
- var name = parts[0];
- var version = parts[1];
- var repository;
-
- if (!version || options.debug) {
- if (verbose)
- console.log("Retrieving package info");
-
- api.packages.get(name, function (err, info) {
- if (err) return callback(err);
-
- if (verbose)
- console.log("Found:", info);
-
- version = info.latest;
- repository = info.repository;
-
- installPackage();
- });
- }
- else {
- installPackage();
- }
-
- function prepareDirectory(callback){
- // Create package dir
- var packagePath = process.env.HOME + "/.c9/plugins/" + name;
- var exists = fs.existsSync(packagePath) ;
- if (exists) {
- if (!force)
- return callback(new Error("WARNING: Directory not empty: " + packagePath
- + ". Use --force to overwrite."));
-
- proc.execFile("rm", {
- args: ["-Rf", packagePath]
- }, function(){
- mkdirP(packagePath);
- callback(null, packagePath);
- });
- }
- else {
- mkdirP(packagePath);
- callback(null, packagePath);
- }
- }
-
- function installPackage(){
- if (!version)
- return callback(new Error("No version found for this package"));
-
- if (options.local) {
- if (verbose)
- console.log("Installing package locally");
-
- prepareDirectory(function(err, packagePath){
- if (err) return callback(err);
-
- // Download package
- var gzPath = join(os.tmpDir(), name + "@" + version + ".tar.gz");
- var file = fs.createWriteStream(gzPath);
-
- var path = "/packages/" + name + "/versions/" + version
- + "/download?access_token="
- + encodeURIComponent(auth.accessToken);
- var host = APIHOST.split(":")[0];
- var port = parseInt(APIHOST.split(":")[1]) || null;
-
- var request = http.get({
- agent: false,
- method: "get",
- host: host,
- port: port,
- auth: BASICAUTH,
- path: path
- }, function(response){
- response.pipe(file);
- });
-
- if (verbose)
- console.log("Downloading package to", gzPath);
-
- request.on('response', function(res) {
- if (res.statusCode != 200)
- return callback(new Error("Unknown Error:" + res.statusCode));
- });
-
- file.on('finish', function(err) {
- if (verbose)
- console.log("Unpacking", gzPath, "to", packagePath);
-
- // Untargz package
- proc.spawn(TAR, {
- args: ["-C", normalizePath(packagePath), "-zxvf", normalizePath(gzPath)]
- }, function(err, p){
- if (err) return callback(err);
-
- if (verbose) {
- p.stdout.on("data", function(c){
- process.stdout.write(c.toString("utf8"));
- });
- p.stderr.on("data", function(c){
- process.stderr.write(c.toString("utf8"));
- });
- }
-
- p.on("exit", function(code){
- var err = code !== 0
- ? new Error("Failed to unpack package")
- : null;
- if (err) return callback(err);
-
- proc.spawn(join(process.env.HOME, ".c9/node/bin/npm"), {
- args: ["install"],
- cwd: packagePath
- }, function(err, p){
- if (err) return callback(err);
-
- if (verbose) {
- p.stdout.on("data", function(c){
- process.stdout.write(c.toString("utf8"));
- });
- p.stderr.on("data", function(c){
- process.stderr.write(c.toString("utf8"));
- });
- }
-
- p.on("exit", function(code){
- // Done
- callback(err, {
- version: version
- });
- });
- });
- });
- });
- });
- });
- }
- else if (options.debug) {
- if (verbose)
- console.log("Installing debug version of package");
-
- prepareDirectory(function(err, packagePath){
- if (err) return callback(err);
-
- if (verbose)
- console.log("Cloning repository: ", repository);
-
- // Git clone repository
- var scm = SCM[repository.type];
- proc.spawn(scm.binary, {
- args: [scm.clone, repository.url, packagePath]
- }, function(err, p){
- if (err) return callback(err);
-
- if (verbose) {
- p.stdout.on("data", function(c){
- process.stdout.write(c.toString("utf8"));
- });
- p.stderr.on("data", function(c){
- process.stderr.write(c.toString("utf8"));
- });
- }
-
- p.on("exit", function(code){
- var err = code !== 0
- ? new Error("Failed to clone package from repository. Do you have access?")
- : null;
-
- // Done
- callback(err);
- });
- });
- });
- }
- else {
- if (verbose)
- console.log("Notifying c9.io that packages needs to be installed");
-
- var endpoint = options.global ? api.user : api.project;
- var url = "install/" + packageName + "/" + version;
-
- endpoint.post(url, function(err, info){
- callback(err, info);
- });
- }
- }
- }
-
- function uninstall(packageName, options, callback){
- // Call uninstall url
- var parts = packageName.split("@");
- var name = parts[0];
- var version = parts[1];
-
- if (!version) {
- api.packages.get(name, function (err, info) {
- if (err) return callback(err);
- version = info.latest;
-
- uninstallPackage();
- });
- }
- else {
- uninstallPackage();
- }
-
- function uninstallPackage(){
- if (options.local || options.debug) {
- // rm -Rf
- var packagePath = process.env.HOME + "/.c9/plugins/" + name;
- proc.spawn("rm", {
- args: ["-rf", packagePath]
- }, function(err, p){
- if (err) return callback(err);
-
- if (verbose) {
- p.stdout.on("data", function(c){
- process.stdout.write(c.toString("utf8"));
- });
- p.stderr.on("data", function(c){
- process.stderr.write(c.toString("utf8"));
- });
- }
-
- p.on("exit", function(code){
- var err = code !== 0
- ? new Error("Failed to remove package.")
- : null;
-
- // if debug > see if should be installed and put back original
- // @TODO
-
- // Done
- callback(err);
- });
- });
- }
- else {
- var endpoint = options.global ? api.user : api.project;
- var url = "uninstall/" + packageName;
-
- endpoint.post(url, function(err, info){
- callback(err, info);
- });
- }
- }
- }
-
function mkdirP(path){
var dirs = path.split('/');
var prevDir = dirs.splice(0,1) + "/";
@@ -1206,22 +834,7 @@ define(function(require, exports, module) {
/**
*
*/
- unpublish: unpublish,
-
- /**
- *
- */
- install: install,
-
- /**
- *
- */
- uninstall: uninstall,
-
- /**
- *
- */
- list: list
+ unpublish: unpublish
});
register(null, {
diff --git a/plugins/c9.cli/cli.js b/plugins/c9.cli/cli.js
index ab533f32..4a5923fc 100755
--- a/plugins/c9.cli/cli.js
+++ b/plugins/c9.cli/cli.js
@@ -29,11 +29,6 @@ define(function(require, exports, module) {
return false;
});
- if (!commands[module] && process.argv.length > 2 && process.argv.every(function(n){ return !n.match(/^--/)})) {
- process.argv.splice(2, 0, "open");
- module = "open";
- }
-
optimist = require('optimist');
if (!module || !commands[module]) {
diff --git a/plugins/c9.core/http-xhr.js b/plugins/c9.core/http-xhr.js
index aeb2e9d1..9d8eafcd 100644
--- a/plugins/c9.core/http-xhr.js
+++ b/plugins/c9.core/http-xhr.js
@@ -29,6 +29,8 @@ define(function(require, module, exports) {
var timeout = options.hasOwnProperty("timeout") ? options.timeout : 10000;
var async = options.sync !== true;
var parsedUrl = parseUrl(url, options.query);
+ if (contentType === "application/json")
+ headers.Accept = headers.Accept || "application/json";
if (options.username) {
headers.Authorization = "Basic " + btoa(options.username + ":" + options.password);
diff --git a/plugins/c9.fs/fs.js b/plugins/c9.fs/fs.js
index e725d694..a3145076 100644
--- a/plugins/c9.fs/fs.js
+++ b/plugins/c9.fs/fs.js
@@ -18,7 +18,7 @@ define(function(require, exports, module) {
var vfs = imports.vfs;
var Plugin = imports.Plugin;
- var stream = require("./fs.streams")(vfs, options.base, options.baseProc);
+ var stream = require("./fs.streams")(vfs, options.base, options.baseProc, options.cli);
var xhr = options.cli ? stream : require("./fs.xhr")(vfs.rest);
var uCaseFirst = require("c9/string").uCaseFirst;
@@ -54,6 +54,8 @@ define(function(require, exports, module) {
if (loaded) return false;
loaded = true;
+ if (options.cli)
+ plugin.on("error", function(e){ console.error(e.error); });
}
function wrap(name, fn) {
@@ -104,6 +106,7 @@ define(function(require, exports, module) {
original_callback.__cb__ = cb;
var event = { path: path, args: args, fn: fn };
+
if (emit("before" + uCaseFirst(name), event) === false)
return false;
diff --git a/plugins/c9.fs/fs.streams.js b/plugins/c9.fs/fs.streams.js
index 8ab60423..19a5fbfe 100644
--- a/plugins/c9.fs/fs.streams.js
+++ b/plugins/c9.fs/fs.streams.js
@@ -3,10 +3,14 @@ define(function(require, exports, module) {
var Stream = require("stream").Stream;
var PATH = require("path");
-return function(vfs, base, baseProc) {
+return function(vfs, base, baseProc, cli) {
var resolvePath = function(path, basePath) {
- if (path.charAt(0) == "~") return path;
+ if (path.charAt(0) == "~") {
+ if (cli)
+ return process.env.HOME + "/" + path.substr(1);
+ return path;
+ }
if (!basePath)
basePath = base;
@@ -20,7 +24,7 @@ return function(vfs, base, baseProc) {
};
function readFile(path, encoding, callback) {
- if (!callback) {
+ if (!callback || typeof encoding == "function") {
callback = encoding;
encoding = null;
}
@@ -28,7 +32,7 @@ return function(vfs, base, baseProc) {
var options = {};
if (encoding)
options.encoding = encoding;
-
+
vfs.readfile(resolvePath(path), options, function(err, meta) {
if (err)
return callback(err);
@@ -54,7 +58,7 @@ return function(vfs, base, baseProc) {
}
function writeFile(path, data, encoding, callback) {
- if (!callback) {
+ if (!callback || typeof encoding == "function") {
callback = encoding;
encoding = null;
}
diff --git a/plugins/c9.fs/proc2pty.js b/plugins/c9.fs/proc2pty.js
index 249cda20..d9b9d562 100644
--- a/plugins/c9.fs/proc2pty.js
+++ b/plugins/c9.fs/proc2pty.js
@@ -4,7 +4,7 @@ define(function(require, exports, module) {
module.exports = function(process){
var pty = new EventEmitter();
pty.write = function(data){
- process.stdin.write(data);
+ process.stdin.write(data.replace(/\r/g, "\n"));
};
pty.resize = function(){};
pty.destroy =
@@ -23,5 +23,5 @@ define(function(require, exports, module) {
});
return pty;
- }
+ };
});
\ No newline at end of file
diff --git a/plugins/c9.ide.errorhandler/raygun_error_handler.js b/plugins/c9.ide.errorhandler/raygun_error_handler.js
index 12be8f71..3c3dcca8 100644
--- a/plugins/c9.ide.errorhandler/raygun_error_handler.js
+++ b/plugins/c9.ide.errorhandler/raygun_error_handler.js
@@ -62,7 +62,9 @@ define(function(require, exports, module) {
exception = new Error(exception);
if (!exception)
exception = new Error("Unspecified error");
- console.error(exception.stack);
+ console.error(exception);
+ if (customData)
+ console.log(customData);
Raygun.send(exception, customData, tags);
}
diff --git a/plugins/c9.ide.experiment/mock_experiment.js b/plugins/c9.ide.experiment/mock_experiment.js
new file mode 100644
index 00000000..e3b80734
--- /dev/null
+++ b/plugins/c9.ide.experiment/mock_experiment.js
@@ -0,0 +1,26 @@
+/**
+ * Dummy implementation of experiments.
+ */
+"use strict";
+
+plugin.consumes = [];
+plugin.provides = ["experiment"];
+
+module.exports = plugin;
+
+function plugin(options, imports, register) {
+
+ register(null, {
+ "experiment": {
+ configure: function() {},
+ onStart: function() {
+ var chain = {
+ variation: function() {
+ return chain;
+ }
+ };
+ return chain;
+ }
+ }
+ });
+}
\ No newline at end of file
diff --git a/plugins/c9.ide.layout.classic/themes/default-dark-gray.less b/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
index 6c792f2a..b3ad5668 100644
--- a/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
+++ b/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
@@ -52,7 +52,7 @@
@ace-cloud9-day-background: lighten(#F8F8F8, @lighten-chrome);
@ace-cloud9-night-gutter: @panel-background;
@ace-cloud9-night-background: lighten(#181818, @lighten-chrome);
-@ace-cloud9-night-active-line: lighten(#292929, @lighten-chrome);
+@ace-cloud9-night-active-line: rgba(68, 68, 68, 0.78); // todo make selection lighter #5A5A5A too?
@ace-gutter-font-smoothing: true;
@ace-gutter-shadow: 1px 0 rgba(255, 255, 255, 0.75) inset;
diff --git a/plugins/c9.ide.plugins/loader.js b/plugins/c9.ide.plugins/loader.js
index 93ad2aea..7b21a959 100644
--- a/plugins/c9.ide.plugins/loader.js
+++ b/plugins/c9.ide.plugins/loader.js
@@ -57,8 +57,11 @@ define(function(require, exports, module) {
if (loadFromDisk) {
fs.readdir("~/.c9/plugins", function handle(err, files){
if (err) {
- if (err.code == "EDISCONNECT")
- fs.readdir("~/.c9/plugins", handle);
+ if (err.code == "EDISCONNECT") {
+ c9.once("connect", function(){
+ fs.readdir("~/.c9/plugins", handle);
+ });
+ }
console.error(err);
return;
}
diff --git a/plugins/c9.ide.terminal/aceterm/hover_link.js b/plugins/c9.ide.terminal/aceterm/hover_link.js
index 409749a8..d38f554b 100644
--- a/plugins/c9.ide.terminal/aceterm/hover_link.js
+++ b/plugins/c9.ide.terminal/aceterm/hover_link.js
@@ -254,6 +254,45 @@ var HoverLink = function(editor) {
match.value = value.replace(/:[^\d][^:]*$/, "");
// match.basePath = "";
}
+ else if (prompt.command === "ack" || prompt.command === "ag" || prompt.command === "ack-grep") {
+ match.type = "path";
+ var fontColor = lineData[column] && lineData[column][0];
+ if (match.start !== 0) {
+ if (fontColor == session.term.defAttr)
+ return;
+
+ var col = column;
+ while (lineData[col] && lineData[col][0] == fontColor)
+ col--;
+ match.start = col + 1;
+ col = column;
+ while (lineData[col] && lineData[col][0] == fontColor)
+ col++;
+ match.value = line.substring(match.start, col);
+ }
+
+ var jumpLine = line.match(/^(\d*:)?/)[0];
+ var jumpColumn = Math.max(match.start - jumpLine.length, 0);
+
+ if (match.start == 0 && jumpLine)
+ match.value = jumpLine;
+
+ var pathLine = line;
+ while (/^\d+/.test(pathLine) && row > prompt.row) {
+ lineData = session.getLineData(row);
+ if (!lineData.wrapped) {
+ pathLine = session.getLine(row);
+ }
+ row--;
+ }
+
+ match.path = pathLine;
+ if (jumpLine)
+ match.path += ":" + jumpLine + jumpColumn;
+
+ if (match.start == 0 && jumpLine)
+ match.action = "open";
+ }
else if (/^(~|\.\.?)?[\/\\]/.test(value) || /\w:[\\]/.test(value)) {
match.type = "path";
match.value = value.replace(/['">)}\].,;:]+$/, "");
@@ -325,7 +364,8 @@ var HoverLink = function(editor) {
command: command,
index: m.index,
args: args,
- lineData: lineData
+ lineData: lineData,
+ row: row
};
}
if (lineData.isUserInput)
diff --git a/plugins/c9.ide.terminal/link_handler.js b/plugins/c9.ide.terminal/link_handler.js
index 9435a794..bce11fb9 100644
--- a/plugins/c9.ide.terminal/link_handler.js
+++ b/plugins/c9.ide.terminal/link_handler.js
@@ -127,6 +127,8 @@ define(function(require, exports, module) {
function showMenu(e) {
if (e.type == "link" && (tabManager.focussedTab || 0).editorType)
return open(e);
+ if (e.action == "open")
+ return open(e);
createMenu(e);
@@ -206,7 +208,7 @@ define(function(require, exports, module) {
}
function buildPath(e) {
- var path = e.value;
+ var path = e.path || e.value;
var abs = false;
if (c9.platform == "win32") {
diff --git a/plugins/c9.ide.ui/forms.js b/plugins/c9.ide.ui/forms.js
index 20503017..e181909c 100644
--- a/plugins/c9.ide.ui/forms.js
+++ b/plugins/c9.ide.ui/forms.js
@@ -202,19 +202,24 @@ define(function(require, exports, module) {
}).join("");
if (data) model.load("" + data + "");
+ var dd;
childNodes = [
new ui.label({ width : width, maxwidth: maxwidth, caption: name + ":" }),
- new ui.dropdown({
+ dd = new ui.dropdown({
model: model,
width: options.width || widths.dropdown,
skin: "black_dropdown",
margin: "-1 0 0 0",
zindex: 100,
- onafterchange: options.onchange && function(e) {
- options.onchange({ value: e.value || e.args[2] });
+ onafterchange: function(e) {
+ if (options.path)
+ settings.set(options.path, e.value);
+
+ if (options.onchange)
+ options.onchange({ value: e.value || e.args[2] });
},
- value: options.path
- ? createBind(options.path) //{settings.model}::
+ value: options.path
+ ? settings.get(options.path)
: (options.defaultValue || ""),
each: options.each || "[item]",
caption: options.caption || "[text()]",
@@ -222,6 +227,10 @@ define(function(require, exports, module) {
"empty-message" : options["empty-message"]
})
];
+
+ settings.on(options.path, function(){
+ dd.setValue(settings.get(options.path));
+ }, plugin);
break;
case "spinner":
childNodes = [
diff --git a/plugins/c9.vfs.extend/collab-server.js b/plugins/c9.vfs.extend/collab-server.js
index 8e77d0fe..89ac7283 100644
--- a/plugins/c9.vfs.extend/collab-server.js
+++ b/plugins/c9.vfs.extend/collab-server.js
@@ -1,7 +1,4 @@
-// Uglify
-// uglifyjs -c -m -o collab-server.js plugins/c9.vfs.extend/collab-server.js
-// Deploy to shared space:
-// scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -i c9/node_modules/settings/keys/deploy collab-server.js 52ee501f50044657c4000005@project-livec99d49a9ef92.rhcloud.com:/var/lib/openshift/52ee501f50044657c4000005/app-root/data/759814/root/c9-vfs-extend/collab-server.js
+
"use strict";
var Fs = require("fs");
var Path = require("path");
@@ -2763,48 +2760,10 @@ var exports = module.exports = function(vfs, options, register) {
exports.Store = Store;
exports.compressDocument = compressDocument;
-/* Google diff match patch library: https://code.google.com/p/google-diff-match-patch/ */
-
var DIFF_EQUAL = 0;
var DIFF_INSERT = 1;
var DIFF_DELETE = -1;
-function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}
-diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b),c=a.substring(0,f),a=a.substring(f),b=b.substring(f),f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f),a=a.substring(0,a.length-f),b=b.substring(0,b.length-f),a=this.diff_compute_(a,b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
-diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);if(-1!=g)return c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c;if(1==f.length)return[[-1,a],[1,b]];return(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100c);u++){for(var n=-u+q;n<=u-s;n+=2){var l=g+n,m;m=n==-u||n!=u&&j[l-1]d)s+=2;else if(r>e)q+=2;else if(p&&(l=g+k-n,0<=l&&l=t)return this.diff_bisectSplit_(a,b,m,r,c)}}for(n=-u+o;n<=u-v;n+=2){l=g+n;t=n==-u||n!=u&&i[l-1]d)v+=2;else if(m>e)o+=2;else if(!p&&(l=g+k-n,0<=l&&l=t)))return this.diff_bisectSplit_(a,b,m,r,c)}}return[[-1,a],[1,b]]};
-diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d),a=a.substring(c),b=b.substring(d),f=this.diff_main(f,g,!1,e),e=this.diff_main(a,b,!1,e);return f.concat(e)};
-diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;fd?a=a.substring(c-d):c=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.lengthd[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
-diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};
-diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
-diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;fb)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};
-diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=//g,f=/\n/g,g=0;g");switch(h){case 1:b[g]=''+j+"";break;case -1:b[g]=''+j+"";break;case 0:b[g]=""+j+""}}return b.join("")};
-diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;ci)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};
-diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
-diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<=i;o--){var v=e[a.charAt(o-1)];k[o]=0===s?(k[o+1]<<1|1)&v:(k[o+1]<<1|1)&v|(q[o+1]|q[o])<<1|1|q[o+1];if(k[o]&j&&(v=d(s,o-1),v<=g))if(g=v,h=o-1,h>c)i=Math.max(1,2*c-h);else break}if(d(s+1,c)>g)break;q=k}return h};
-diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};
-diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;cthis.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;ie[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
-diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};
-diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b),c=a.substring(0,f),a=a.substring(f),b=b.substring(f),f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f),a=a.substring(0,a.length-f),b=b.substring(0,b.length-f),a=this.diff_compute_(a,b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
+diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);if(-1!=g)return c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c;if(1==f.length)return[[-1,a],[1,b]];return(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100c);u++){for(var n=-u+q;n<=u-s;n+=2){var l=g+n,m;m=n==-u||n!=u&&j[l-1]d)s+=2;else if(r>e)q+=2;else if(p&&(l=g+k-n,0<=l&&l=t)return this.diff_bisectSplit_(a,b,m,r,c)}}for(n=-u+o;n<=u-v;n+=2){l=g+n;t=n==-u||n!=u&&i[l-1]d)v+=2;else if(m>e)o+=2;else if(!p&&(l=g+k-n,0<=l&&l=t)))return this.diff_bisectSplit_(a,b,m,r,c)}}return[[-1,a],[1,b]]};
+diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d),a=a.substring(c),b=b.substring(d),f=this.diff_main(f,g,!1,e),e=this.diff_main(a,b,!1,e);return f.concat(e)};
+diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;fd?a=a.substring(c-d):c=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.lengthd[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
+diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};
+diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
+diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;fb)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};
+diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=//g,f=/\n/g,g=0;g");switch(h){case 1:b[g]=''+j+"";break;case -1:b[g]=''+j+"";break;case 0:b[g]=""+j+""}}return b.join("")};
+diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;ci)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};
+diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
+diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<=i;o--){var v=e[a.charAt(o-1)];k[o]=0===s?(k[o+1]<<1|1)&v:(k[o+1]<<1|1)&v|(q[o+1]|q[o])<<1|1|q[o+1];if(k[o]&j&&(v=d(s,o-1),v<=g))if(g=v,h=o-1,h>c)i=Math.max(1,2*c-h);else break}if(d(s+1,c)>g)break;q=k}return h};
+diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};
+diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;cthis.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;ie[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
+diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};
+diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c