kopia lustrzana https://github.com/c9/core
889 wiersze
36 KiB
JavaScript
889 wiersze
36 KiB
JavaScript
![]() |
define(function(require, exports, module) {
|
||
|
main.consumes = ["Plugin", "cli_commands", "proc", "api", "auth"];
|
||
|
main.provides = ["cli.publish"];
|
||
|
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 SHELLSCRIPT = require("text!./publish.git.sh").toString("utf8");
|
||
|
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 FormData = require("form-data");
|
||
|
var http = require(APIHOST.indexOf("localhost") > -1 ? "http" : "https");
|
||
|
var basename = require("path").basename;
|
||
|
|
||
|
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: "publish",
|
||
|
info: " Publishes a cloud9 package.",
|
||
|
usage: "[--verbose] [--force] [<newversion> | major | minor | patch | build]",
|
||
|
options: {
|
||
|
"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["newversion"])
|
||
|
throw new Error("Missing version");
|
||
|
},
|
||
|
exec: function(argv) {
|
||
|
verbose = argv["verbose"];
|
||
|
force = argv["force"];
|
||
|
|
||
|
publish(
|
||
|
argv._[1],
|
||
|
function(err, data){
|
||
|
if (err) {
|
||
|
if (err.message || typeof err == "string")
|
||
|
console.error(err.message || err);
|
||
|
|
||
|
if (!verbose)
|
||
|
console.error("\nTry running with --verbose flag for more information");
|
||
|
process.exit(1);
|
||
|
}
|
||
|
else {
|
||
|
console.log("Succesfully published version", data.version);
|
||
|
process.exit(0);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
cmd.addCommand({
|
||
|
name: "unpublish",
|
||
|
info: "Disables a cloud9 package.",
|
||
|
usage: "[--verbose]",
|
||
|
options: {
|
||
|
"verbose" : {
|
||
|
"description": "Output more information",
|
||
|
"alias": "v",
|
||
|
"default": false,
|
||
|
"boolean": true
|
||
|
}
|
||
|
},
|
||
|
check: function(argv) {},
|
||
|
exec: function(argv) {
|
||
|
verbose = argv["verbose"];
|
||
|
|
||
|
unpublish(
|
||
|
function(err, data){
|
||
|
if (err) {
|
||
|
console.error(err.message || err || "Terminated.");
|
||
|
process.exit(1);
|
||
|
}
|
||
|
else {
|
||
|
console.log("Succesfully disabled package");
|
||
|
process.exit(0);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
cmd.addCommand({
|
||
|
name: "install",
|
||
|
info: " Installs a cloud9 package.",
|
||
|
usage: "[--verbose] [--force] [--global] [--local] [--debug] <package>[@<version>]", // @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] <package>", // @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 *****/
|
||
|
|
||
|
function stringifyError(err){
|
||
|
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(version, callback) {
|
||
|
var cwd = process.cwd();
|
||
|
var packagePath = cwd + "/package.json";
|
||
|
fs.readFile(packagePath, function(err, data){
|
||
|
if (err) return callback(new Error("ERROR: Could not find package.json in " + cwd));
|
||
|
|
||
|
var json;
|
||
|
try { json = JSON.parse(data); }
|
||
|
catch(e) {
|
||
|
return callback(new Error("ERROR: Could not parse package.json: ", e.message));
|
||
|
}
|
||
|
|
||
|
// Basic Validation
|
||
|
if (!json.name)
|
||
|
return callback(new Error("ERROR: Missing name property in package.json"));
|
||
|
if (basename(cwd) != json.name) {
|
||
|
console.warn("WARNING: The name property in package.json is not equal to the directory name, which is " + basename(cwd));
|
||
|
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.categories || json.categories.length == 0)
|
||
|
return callback(new Error("ERROR: At least one category is required in package.json"));
|
||
|
|
||
|
// Validate README.md
|
||
|
if (!fs.existsSync(join(cwd, "README.md"))) {
|
||
|
console.warn("WARNING: README.md is missing.");
|
||
|
if (!force)
|
||
|
return callback(new Error("Use --force to ignore these warnings."));
|
||
|
}
|
||
|
|
||
|
// Validate plugins
|
||
|
var plugins = {};
|
||
|
fs.readdirSync(cwd).map(function(filename) {
|
||
|
if (/_test\.js$/.test(filename) || !/.js/.test(filename)) return;
|
||
|
var val = fs.readFileSync(cwd + "/" + filename);
|
||
|
if (!/\(options,\s*imports,\s*register\)/.test(val)) return;
|
||
|
if (!/consumes\s*=/.test(val)) return;
|
||
|
if (!/provides\s*=/.test(val)) return;
|
||
|
plugins[filename] = {};
|
||
|
});
|
||
|
|
||
|
var warned, failed;
|
||
|
Object.keys(plugins).forEach(function(name){
|
||
|
if (!json.plugins[name.replace(/\.js$/, "")]) {
|
||
|
console.warn("WARNING: Plugin '" + name + "' is not listed in package.json.");
|
||
|
warned = true;
|
||
|
}
|
||
|
// @TODO temporarily disabled the requirement for tests while tests cannot actually run yet
|
||
|
// else if (!fs.existsSync(join(cwd, name.replace(/\.js$/, "_test.js")))) {
|
||
|
// console.warn("ERROR: Plugin '" + name + "' has no test associated with it.");
|
||
|
// failed = true;
|
||
|
// }
|
||
|
});
|
||
|
|
||
|
if (failed)
|
||
|
return callback(new Error());
|
||
|
|
||
|
if (warned && !force)
|
||
|
return callback(new Error("Use --force to ignore these warnings."));
|
||
|
|
||
|
var v = (json.version || "0.0.1").split(".");
|
||
|
|
||
|
// Update the version field in the package.json file
|
||
|
if (version == "major") {
|
||
|
v[0]++;
|
||
|
v[1] = 0;
|
||
|
v[2] = 0;
|
||
|
}
|
||
|
else if (version == "minor") {
|
||
|
v[1]++;
|
||
|
v[2] = 0;
|
||
|
}
|
||
|
else if (version == "patch" || version == "build") v[2]++;
|
||
|
else if (version.match(/^\d+\.\d+\.\d+$/))
|
||
|
v = version.split(".");
|
||
|
else
|
||
|
return callback(new Error("Invalid version. Semver required: " + version));
|
||
|
|
||
|
json.version = v.join(".");
|
||
|
|
||
|
// Write the package.json file
|
||
|
fs.writeFile(packagePath, JSON.stringify(json, 1, " "), function(err){
|
||
|
if (err) return callback(err);
|
||
|
|
||
|
SHELLSCRIPT = SHELLSCRIPT
|
||
|
.replace(/\$1/, packagePath)
|
||
|
.replace(/\$2/, json.version);
|
||
|
|
||
|
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();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// Build the package
|
||
|
// @TODO use a proper package tool
|
||
|
// @TODO add a .c9exclude file that excludes files
|
||
|
var zipFilePath;
|
||
|
function build(){
|
||
|
zipFilePath = join(os.tmpDir(), json.name + "@" + json.version);
|
||
|
var tarArgs = ["-zcvf", zipFilePath, "."];
|
||
|
var c9ignore = process.env.HOME + "/.c9/.c9ignore";
|
||
|
fs.exists(c9ignore, function (exists) {
|
||
|
if (exists) {
|
||
|
tarArgs.push("--exclude-from=" + c9ignore);
|
||
|
}
|
||
|
proc.spawn(TAR, {
|
||
|
args: tarArgs
|
||
|
}, 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){
|
||
|
if (code !== 0)
|
||
|
return callback(new Error("ERROR: Could not package directory"));
|
||
|
|
||
|
console.log("Built package", json.name + "@" + json.version);
|
||
|
|
||
|
upload();
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Update c9.io with the new version being published.
|
||
|
function upload(){
|
||
|
// Check if the plugin is already registered
|
||
|
if (verbose)
|
||
|
console.log("Uploading package " + json.name);
|
||
|
|
||
|
api.packages.get(json.name, function(err, pkg){
|
||
|
if (err) {} // Ignore error, if we don't get a response it means this package hasn't been published yet
|
||
|
|
||
|
if (!pkg || pkg.error) {
|
||
|
if (verbose)
|
||
|
console.log("Package not registered, creating new.");
|
||
|
|
||
|
// Registers the package name on c9.io if it is being published for the first time.
|
||
|
api.user.get("", function(err, user){
|
||
|
if (err) return callback(new Error("ERROR: Failed to get user details from API - " + stringifyError(err)));
|
||
|
|
||
|
api.packages.post("", {
|
||
|
contentType: "application/json",
|
||
|
body: {
|
||
|
name: json.name,
|
||
|
description: json.description,
|
||
|
owner_type: "user", // @TODO implement this when adding orgs
|
||
|
owner_id: parseInt(user.id),
|
||
|
permissions: json.permissions || "world",
|
||
|
categories: json.categories,
|
||
|
repository: json.repository,
|
||
|
longname: json.longname,
|
||
|
website: json.website,
|
||
|
screenshots: json.screenshots || [],
|
||
|
pricing: json.pricing || {}
|
||
|
}
|
||
|
}, function(err, pkg){
|
||
|
if (err)
|
||
|
return callback(new Error("ERROR: Failed to upload new package to API - "
|
||
|
+ stringifyError(err)));
|
||
|
|
||
|
next(pkg);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
if (verbose)
|
||
|
console.log("Plugin already registered, updating.");
|
||
|
|
||
|
api.packages.put(json.name, {
|
||
|
contentType: "application/json",
|
||
|
body: {
|
||
|
permissions: json.permissions,
|
||
|
categories: json.categories,
|
||
|
repository: json.repository,
|
||
|
longname: json.longname,
|
||
|
website: json.website,
|
||
|
description: json.description,
|
||
|
screenshots: json.screenshots,
|
||
|
pricing: json.pricing,
|
||
|
enabled: true
|
||
|
}
|
||
|
}, function(err, pkg){
|
||
|
if (err)
|
||
|
return callback(new Error("ERROR: Failed to update existing package - "
|
||
|
+ stringifyError(err)));
|
||
|
if (verbose)
|
||
|
console.log("Successfully updated existing package");
|
||
|
|
||
|
next(pkg);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function next(pkg){
|
||
|
// Create Version
|
||
|
if (verbose)
|
||
|
console.log("Sending new version ", json.version);
|
||
|
|
||
|
var form = new FormData();
|
||
|
form.append('version', json.version);
|
||
|
form.append('options', JSON.stringify(json.plugins));
|
||
|
form.append('package', fs.createReadStream(zipFilePath));
|
||
|
|
||
|
var path = "/packages/" + json.name
|
||
|
+ "/versions?access_token="
|
||
|
+ encodeURIComponent(auth.accessToken);
|
||
|
var host = APIHOST.split(":")[0]
|
||
|
var port = parseInt(APIHOST.split(":")[1]) || null;
|
||
|
|
||
|
var request = http.request({
|
||
|
agent: false,
|
||
|
method: "post",
|
||
|
host: host,
|
||
|
port: port,
|
||
|
path: path,
|
||
|
auth: BASICAUTH,
|
||
|
headers: form.getHeaders()
|
||
|
});
|
||
|
|
||
|
form.pipe(request);
|
||
|
|
||
|
request.on('response', function(res) {
|
||
|
if (res.statusCode != 200)
|
||
|
return callback(new Error("ERROR: Unknown Error:" + res.statusCode));
|
||
|
|
||
|
// Create Version Complete
|
||
|
callback(null, json);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function unpublish(callback){
|
||
|
var packagePath = process.cwd() + "/package.json";
|
||
|
fs.readFile(packagePath, function(err, data){
|
||
|
if (err) return callback(err); // @TODO package.json not found
|
||
|
|
||
|
var json;
|
||
|
try { json = JSON.parse(data); }
|
||
|
catch(e) {
|
||
|
return callback(new Error("ERROR: Could not parse package.json: ", e.message));
|
||
|
}
|
||
|
|
||
|
if (!json.name)
|
||
|
return callback(new Error("ERROR: Missing name property in package.json"));
|
||
|
|
||
|
api.packages.put(json.name + "/disable", {}, callback);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
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));
|
||
|
|
||
|
if (verbose)
|
||
|
console.log("Unpacking", gzPath, "to", packagePath);
|
||
|
|
||
|
// Untargz package
|
||
|
proc.spawn(TAR, {
|
||
|
args: ["-C", packagePath, "-zxvf", 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;
|
||
|
|
||
|
// 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) + "/";
|
||
|
while (dirs.length > 0) {
|
||
|
var curDir = prevDir + dirs.splice(0,1);
|
||
|
if (! fs.existsSync(curDir) ) {
|
||
|
fs.mkdirSync(curDir);
|
||
|
}
|
||
|
prevDir = curDir + '/';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/***** 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 define API *****/
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
**/
|
||
|
plugin.freezePublicAPI({
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
publish: publish,
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
unpublish: unpublish,
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
install: install,
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
uninstall: uninstall,
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
list: list
|
||
|
});
|
||
|
|
||
|
register(null, {
|
||
|
"cli.publish": plugin
|
||
|
});
|
||
|
}
|
||
|
|
||
|
});
|