cloudcms-cli
Version:
Cloud CMS Command-Line client
1,551 lines (1,231 loc) • 145 kB
JavaScript
var prompt = require("prompt");
var program = require("commander");
var async = require("async");
var path = require("path");
var fs = require("fs");
var request = require("./util/request");
const url = require("url");
var opn = require("opn");
var mime = require("mime");
var Gitana = require("gitana");
var util = require("./util");
// start prompt
prompt.message = null;
prompt.delimiter = "";
prompt.start();
var exports = module.exports = function()
{
var r = {};
r.processOptions = function(schema, opts, command, callback) {
if (!schema) {
schema = {};
}
if (!schema.properties) {
schema.properties = [];
}
var options = {};
var fns = [];
for (var i = 0; i < schema.properties.length; i++)
{
var val = undefined;
if (schema.properties[i].args)
{
for (var j = 0; j < schema.properties[i].args.length; j++)
{
if (opts[schema.properties[i].args[j]])
{
val = opts[schema.properties[i].args[j]];
break;
}
}
}
if (typeof(val) !== "undefined")
{
options[schema.properties[i].name] = val;
}
else
{
if (typeof(schema.properties[i].default) !== "undefined") {
options[schema.properties[i].name] = schema.properties[i].default;
// } else {
// if (schema.properties[i].type === "boolean") {
// options[schema.properties[i].name] = false;
// }
}
if (schema.properties[i].required)
{
var fn = function (property) {
return function (done) {
if (property.prompt === "choice") {
if (property.description) {
console.log(property.description);
}
else if (property.helper) {
console.log(property.helper);
}
program.choose(property.choiceTitles, function (i) {
options[property.name] = property.choiceValues[i];
done();
});
}
else {
prompt.get([property], function (err, result) {
if (err) {
return done(err);
}
options[property.name] = result[property.name];
done();
});
}
}
}(schema.properties[i]);
fns.push(fn);
}
}
}
async.series(fns, function(err) {
callback(err, options);
});
};
r.generateSchemaSummary = function(schema)
{
var summary = "";
if (schema && schema.properties)
{
for (var propertyName in schema.properties)
{
var property = schema.properties[propertyName];
if (property.args && property.args.length > 0)
{
summary += " ";
if (!property.required)
{
summary += "[";
}
summary += "--" + property.args[0];
if (property.type === "boolean" && !property.required)
{
// skip
}
else
{
summary += " <" + property.name + ">";
}
if (!property.required)
{
summary += "]";
}
}
}
}
return summary;
};
var homeDirectory = r.homeDirectory = function()
{
return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
};
/**
* Connects to Cloud CMS using a pre-established .cloudcms credentials file.
*
* @param credentials
* @param callback
*/
var connect = r.connect = function(credentials, callback)
{
if (typeof(credentials) === "function")
{
callback = credentials;
credentials = null;
}
if (!credentials)
{
credentials = readCredentials();
}
if (!credentials)
{
return callback({
"message": "Unable to locate credentials.json file"
});
}
if (process.authenticator_code)
{
if (!Gitana.OAUTH2_TOKEN_REQUEST_HEADERS)
{
Gitana.OAUTH2_TOKEN_REQUEST_HEADERS = {};
}
Gitana.OAUTH2_TOKEN_REQUEST_HEADERS["authenticator_code"] = process.authenticator_code;
}
Gitana.connect(credentials, function(err) {
delete Gitana.OAUTH2_TOKEN_REQUEST_HEADERS["authenticator_code"];
callback.call(this, err);
});
};
/**
* Finds and hands back the credentials file.
*/
var readCredentials = r.readCredentials = function()
{
var text = null;
if (process.cloudcms_profile)
{
if (fs.existsSync(path.join(homeDirectory(), ".cloudcms", "credentials", process.cloudcms_profile + ".json")))
{
text = fs.readFileSync(path.join(homeDirectory(), ".cloudcms", "credentials", process.cloudcms_profile + ".json"));
}
}
if (!text)
{
if (fs.existsSync(path.join(homeDirectory(), ".cloudcms", "credentials.json")))
{
text = fs.readFileSync(path.join(homeDirectory(), ".cloudcms", "credentials.json"));
}
}
var credentials = null;
if (text)
{
credentials = JSON.parse(text);
}
if (credentials)
{
credentials.key = "credentials";
}
return credentials;
};
var appConnect = r.appConnect = function(callback) {
var credentials = readCredentials();
if (!credentials)
{
return callback({
"message": "Unable to find credentials file"
});
}
var gitanaJson = {
"clientKey": credentials.clientKey,
"clientSecret": credentials.clientSecret,
"username": credentials.username,
"password": credentials.password,
"baseURL": credentials.baseURL,
"_apiURL": credentials._apiURL,
"_uiURL": credentials._uiURL
};
connect(gitanaJson, function (err) {
if (err)
{
console.log("Unable to connect to Cloud CMS");
return callback(err);
}
callback.call(this, null, gitanaJson);
});
};
var downloadArchive = r.downloadArchive = function(vaultId, group, artifact, version, callback)
{
appConnect(function(err, _gitanaJson) {
if (err) {
return callback(err);
}
var gitana = this;
Chain(this).trap(function(e) {
// failed to find vault?
callback(e);
return false;
}).readVault(vaultId).then(function() {
// NOTE: this = vault
this.lookupArchive(group, artifact, version).then(function() {
// NOTE: this = archive
var packageFilePath = path.join(".", group + "-" + artifact + "-" + version + ".zip");
var downloadUri = _gitanaJson.baseURL + this.getUri() + "/download";
// headers
var headers = {};
//headers["Content-Type"] = "application/zip";
// add "authorization" for OAuth2 bearer token
var headers2 = gitana.getDriver().getHttpHeaders();
headers["Authorization"] = headers2["Authorization"];
var progressBar = createProgressBar();
request({
"method": "GET",
"url": downloadUri,
"qs": {},
"headers": headers,
"responseType": "stream",
"timeout": pickTimeout(120 * 1000) // 2 minutes
}, function (err, httpResponse, fromStream) {
if (err) {
return callback(err);
}
if (httpResponse.status >= 200 && httpResponse.status <= 204)
{
// ok
}
else
{
console.log("Download failed");
return callback({
"message": "Status: " + httpResponse.status + ", Message: " + body
});
}
// set progress bar length
var contentLength = httpResponse.headers["content-length"];
if (contentLength) {
contentLength = parseInt("" + contentLength);
progressBar.setTotal(contentLength);
}
// track progress
var callbackTriggered = false;
var progressCurrent = 0;
fromStream.on("data", function(data) {
if (data && data.length)
{
progressCurrent += data.length;
progressBar.update(progressCurrent);
}
});
fromStream.on("end", function() {
progressBar.stop();
if (!callbackTriggered) {
callbackTriggered = true;
callback();
}
});
fromStream.on("error", function(err) {
console.log("Caught error on stream", err);
progressBar.stop();
if (!callbackTriggered) {
callbackTriggered = true;
callback(err);
}
});
// pipe streams from->to
var toStream = fs.createWriteStream(packageFilePath);
fromStream.pipe(toStream);
});
});
});
});
};
var uploadArchive = r.uploadArchive = function(vaultId, group, artifact, version, callback)
{
appConnect(function(err, _gitanaJson) {
if (err) {
return callback(err);
}
var gitana = this;
Chain(this).trap(function(e) {
// failed to find vault?
callback(e);
return false;
}).readVault(vaultId).then(function() {
// NOTE: this = vault
var vault = this;
var doUpload = function(archiveGroup, archiveName, archiveVersion, type, completionCallback) {
var packageFilePath = path.join(".", archiveGroup + "-" + archiveName + "-" + archiveVersion + ".zip");
var uploadUri = _gitanaJson.baseURL + vault.getUri() + "/archives?group=" + archiveGroup + "&artifact=" + archiveName + "&version=" + archiveVersion + "&type=branch";
// headers
var headers = {};
headers["Content-Type"] = "application/zip";
// add "authorization" for OAuth2 bearer token
var headers2 = gitana.getDriver().getHttpHeaders();
headers["Authorization"] = headers2["Authorization"];
var progressBar = createProgressBar();
var fromLength = fs.statSync(packageFilePath).size;
progressBar.setTotal(fromLength);
var fromStream = fs.createReadStream(packageFilePath);
request({
"method": "POST",
"url": uploadUri,
"qs": {},
"headers": headers,
"responseType": "stream",
"timeout": pickTimeout(120 * 1000) // 2 minutes
}, function (err, httpResponse, toStream) {
if (err) {
return completionCallback(err);
}
if (httpResponse.status >= 200 && httpResponse.status <= 204)
{
// ok
//console.log("Upload complete: " + packageFilePath);
//completionCallback();
}
else
{
console.log("Upload failed for: " + packageFilePath);
return completionCallback({
"message": "Status: " + httpResponse.status + ", Message: " + body
});
}
// track progress
var callbackTriggered = false;
var progressCurrent = 0;
fromStream.on("data", function(data) {
if (data && data.length)
{
progressCurrent += data.length;
progressBar.update(progressCurrent);
}
});
fromStream.on("end", function() {
progressBar.stop();
if (!callbackTriggered) {
callbackTriggered = true;
callback();
}
});
fromStream.on("error", function(err) {
console.log("Caught error on stream", err);
progressBar.stop();
if (!callbackTriggered) {
callbackTriggered = true;
callback(err);
}
});
// pipe streams from->to
fromStream.pipe(toStream);
});
};
var fns = [];
// upload parts if they exist
var i = 0;
var partsDone = false;
do
{
var packageFilePath = path.join(".", "archives/" + group + "-" + artifact + "_part" + i + "-" + version + ".zip");
if (fs.existsSync(packageFilePath))
{
var fn = function(partIndex) {
return function(done) {
doUpload(group, artifact + "_part" + partIndex, version, "branch", function(err) {
done(err);
});
};
}(i);
fns.push(fn);
}
else
{
partsDone = true;
}
i++;
}
while (!partsDone);
// upload the main archive itself
var fn = function() {
return function(done) {
doUpload(group, artifact, version, "branch", function(err) {
done(err);
});
};
}();
fns.push(fn);
// run all functions in serial
async.series(fns, function(err) {
callback(err);
});
});
});
};
var importArchiveToBranch = r.importArchiveToBranch = function(repositoryId, branchId, group, artifact, version, callback)
{
appConnect(function(err, _gitanaJson) {
if (err) {
return callback(err);
}
this.readRepository(repositoryId).readBranch(branchId).then(function() {
var branch = this;
// import the branch archive into the repository
this.importArchive({
"vault": "primary",
"group": group,
"artifact": artifact,
"version": version,
"configuration": {
"childrenOnly": true
}
}, function(job) {
console.log("Import progress: " + job.progressCurrent + " / " + job.progressMax);
}).then(function() {
if (this.getState() === "ERROR")
{
console.log("Job Failed");
console.log(JSON.stringify(this, null, " "));
callback({
"message": JSON.stringify(this)
});
}
else
{
Chain(branch).reload().then(function () {
console.log("Successfully imported archive onto changeset: " + this.getTip());
callback();
});
}
});
});
});
};
var exportBranchToArchive = r.exportBranchToArchive = function(repositoryId, branchId, group, artifact, version, callback)
{
appConnect(function(err, _gitanaJson) {
if (err) {
return callback(err);
}
this.readRepository(repositoryId).readBranch(branchId).then(function() {
var branch = this;
// export the archive
this.exportArchive({
"vault": "primary",
"group": group,
"artifact": artifact,
"version": version,
"configuration": {
"tipChangesetOnly": true
}
}).then(function() {
if (this.getState() === "ERROR")
{
console.log("Job Failed");
console.log(JSON.stringify(this, null, " "));
callback({
"message": JSON.stringify(this)
});
}
else
{
Chain(branch).reload().then(function () {
console.log("Successfully exported archive: " + this.getId());
callback();
});
}
});
});
});
};
var registerModule = r.registerModule = function(id, sourceType, sourceUrl, sourcePath, sourceBranch, callback)
{
var source = {
"type": sourceType,
"uri": sourceUrl
};
if (sourcePath) {
source.path = sourcePath;
}
if (sourceBranch) {
source.branch = sourceBranch;
}
var json = {
"modules": [{
"id": id,
"source": source
}]
};
_handleGitanaPost("/oneteam/modules/register", null, json, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var unregisterModule = r.unregisterModule = function(id, callback)
{
_handleGitanaPost("/oneteam/modules/unregister", {
"id": id
}, null, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var deployModule = r.deployModule = function(id, callback)
{
_handleGitanaPost("/oneteam/modules/deploy", {
"id": id
}, null, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var undeployModule = r.undeployModule = function(id, callback)
{
_handleGitanaPost("/oneteam/modules/undeploy", {
"id": id
}, null, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var redeployModule = r.redeployModule = function(id, callback)
{
_handleGitanaPost("/oneteam/modules/redeploy", {
"id": id
}, null, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var listModules = r.listModules = function(callback)
{
_handleGitanaGet("/oneteam/modules", {}, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var fixBranchTip = r.fixBranchTip = function(repositoryId, branchId, commit, forceToTip, buildView, callback)
{
_handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId, {}, function(err, branch) {
var branchTipId = branch.tip;
console.log("TIP: " + branchTipId);
// query the changesets to find the actual tip
var p1 = {};
p1.sort = {
"revision": -1
};
p1.limit = 1;
_handleGitanaPost("/repositories/" + repositoryId + "/changesets/query", p1, {
"branch": branchId
}, function(err, results) {
var topChangesetId = null;
if (results && results.rows && results.rows.length > 0)
{
topChangesetId = results.rows[0]._doc;
}
if (forceToTip) {
//topChangesetId = "5067:ce8fda435b9ebea67256";
topChangesetId = forceToTip;
}
var resp = {
"branchTip": branchTipId,
"topChangeset": topChangesetId
};
if (!commit)
{
resp.commit = false;
return _handleJsonResponse(err, resp, function() {});
}
//console.log("Moving tip");
resp.commit = true;
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/admin/reset", {
"tip": topChangesetId
}, {}, function(err, response) {
if (buildView)
{
return buildBranchView(repositoryId, branchId, function(err) {
resp.buildView = true;
_handleJsonResponse(err, resp, callback);
});
}
resp.buildView = false;
_handleJsonResponse(err, response, callback);
});
});
});
};
var repairBranch = r.repairBranch = function(repositoryId, branchId, operations, commit, username, password, config, callback)
{
var params = {};
if (commit) {
params.commit = true;
}
// payload (optional support for operations)
var payload = {};
if (operations) {
payload.operations = operations;
}
if (config) {
payload.configuration = config;
}
// console.log("Payload: " + JSON.stringify(payload, null, 2));
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/repair/start", params, payload, function(err, jsonResponse) {
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
job.attachment("default").download(function(data) {
var result = JSON.parse(data);
_handleJsonResponse(null, result, callback);
});
});
});
};
var validateBranch = r.validateBranch = function(repositoryId, branchId, username, password, config, callback) {
var params = {};
if (config.repair) {
params.repair = true;
}
var body = {};
if (config.typeQNames)
{
body.typeQNames = config.typeQNames;
}
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/validate/start", params, body, function(err, jsonResponse) {
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
if (err)
{
_handleJsonResponse(err, null, callback);
return;
}
job.attachment("default").download(function(data) {
var result = JSON.parse(data);
if (result.errors)
{
result.errorLength = result.errors.length;
var nodes = result.nodes = {};
for (var i = 0; i < result.errors.length; i++)
{
var error = result.errors[i];
var nodeId = error.node;
var d = nodes[nodeId];
if (!d) {
d = nodes[nodeId] = {
"definitionPaths": []
};
}
var definitionPropertyPath = error.definitionPropertyPath;
if (definitionPropertyPath)
{
if (d.definitionPaths.indexOf(definitionPropertyPath) === -1)
{
d.definitionPaths.push(definitionPropertyPath);
}
}
}
result.nodesLength = 0;
for (var k in result.nodes) {
result.nodesLength++;
}
}
if (config.nodeList)
{
var array = [];
for (var nodeId in result.nodes)
{
array.push(nodeId);
}
_handleJsonResponse(null, array, callback);
}
else
{
_handleJsonResponse(null, result, callback);
}
});
});
});
};
var syncRepositoryAnchorSnapshots = r.syncRepositoryAnchorSnapshots = function(repositoryId, username, password, callback) {
_handleGitanaPost("/repositories/" + repositoryId + "/admin/syncanchors", {}, null, function(err, jsonResponse) {
if (err) {
return _handleJsonResponse(err, jsonResponse, callback);
}
_waitForAdminJobCompletion(jsonResponse._doc, username, password, function(err, job) {
if (err) {
return _handleJsonResponse(err, job, callback);
}
if (job.state === "ERROR") {
return _handleJsonResponse(err, job, callback);
}
callback(err, job);
});
});
};
var rebuildDatastoreIndexes = r.rebuildDatastoreIndexes = function(datastoreTypeId, datastoreId, children, username, password, callback) {
var qs = {
"type": datastoreTypeId,
"id": datastoreId,
"recursive": (children ? "true": "false")
};
_handleAdminGitanaPost("/maint/datastore/reindex", qs, null, username, password, function(err, jsonResponse) {
if (err) {
return _handleJsonResponse(err, jsonResponse, callback);
}
console.log(jsonResponse);
_waitForAdminJobCompletion(jsonResponse._doc, username, password, function(err, job) {
if (err) {
return _handleJsonResponse(err, job, callback);
}
if (job.state === "ERROR") {
return _handleJsonResponse(err, job, callback);
}
callback(err, job);
});
});
};
var listPatches = r.listPatches = function(username, password, callback)
{
_handleAdminGitanaGet("/maint/patches/all", {}, username, password, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var applyPatches = r.applyPatches = function(datastoreTypeId, datastoreId, patchIds, force, username, password, callback)
{
_handleAdminGitanaPost("/maint/patches/apply", {
"type": datastoreTypeId,
"id": datastoreId
}, {
"patchIds": patchIds,
"force": (force ? "true": "false")
}, username, password, function(err, jsonResponse) {
if (err) {
return _handleJsonResponse(err, jsonResponse, callback);
}
var jobId = jsonResponse._doc;
waitForAdminCompletionWithProgressBar(jobId, username, password, function(err, job) {
if (err) {
return _handleJsonResponse(err, job, callback);
}
if (job.state === "ERROR") {
return _handleJsonResponse(err, job, callback);
}
callback(err, job);
});
});
};
var listJobs = r.listJobs = function(state, callback) {
var pagination = {
"limit": 20,
"options": {
"countTotal": false
}
};
var json = {};
if (state) {
json.state = state;
}
_handleGitanaPost("/jobs/query", pagination, json, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var getActiveJobsSummary = r.getJobsSummary = function(callback) {
_handleGitanaPost("/jobs/summary", {}, {}, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var watchJob = r.watchJob = function(jobId, callback)
{
waitForCompletionWithProgressBar(jobId, function(err, job) {
if (err) {
return _handleJsonResponse(err, job, callback);
}
if (job.state === "ERROR") {
return _handleJsonResponse(err, job, callback);
}
callback(err, job);
});
};
var readJob = r.readJob = function(jobId, callback) {
_handleGitanaGet("/jobs/" + jobId, {}, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var readNode = r.readNode = function(repositoryId, branchId, nodeId, nodePath, callback) {
var params = {};
if (process.metadata) {
params["metadata"] = "true";
}
if (nodePath) {
params["path"] = nodePath;
}
if (!nodeId) {
nodeId = "root";
}
_handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/" + nodeId, params, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var readBranch = r.readBranch = function(repositoryId, branchId, callback) {
var params = {};
if (process.metadata) {
params["metadata"] = "true";
}
_handleGitanaGet("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var deleteBranch = r.deleteBranch = function(repositoryId, branchId, callback) {
var params = {};
_handleGitanaDelete("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var deleteSnapshot = r.deleteSnapshot = function(repositoryId, branchId, callback) {
var params = {};
_handleGitanaDelete("/repositories/" + repositoryId + "/branches/" + branchId, params, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var readChangeset = r.readChangeset = function(repositoryId, changesetId, callback) {
var params = {};
if (process.metadata) {
params["metadata"] = "true";
}
_handleGitanaGet("/repositories/" + repositoryId + "/changesets/" + changesetId, params, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var createNode = r.createNode = function(repositoryId, branchId, objectString, callback) {
var object = {};
if (objectString) {
objectString = objectString.replace(/'/g, '"');
object = JSON.parse(objectString);
}
var params = {};
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes", params, object, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var ingest = r.ingest = function(repositoryId, branchId, filePath, config, cb) {
var callback = function(err, jsonResponse)
{
_handleJsonResponse(err, jsonResponse, cb);
};
if (!config) {
config = {};
}
appConnect(function(err, _gitanaJson) {
var gitana = this;
var uploadUri = _gitanaJson.baseURL + "/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/ingest";
// determine content type from file path?
var contentType = lookupMimeType(filePath);
// headers
var headers = {};
headers["Content-Type"] = contentType;
// add "authorization" for OAuth2 bearer token
var headers2 = gitana.getDriver().getHttpHeaders();
headers["Authorization"] = headers2["Authorization"];
var fromStream = fs.createReadStream(filePath);
var fromLength = fs.statSync(filePath).size;
// build progress bar
var progressBar = createProgressBar();
progressBar.setTotal(fromLength);
// track progress
var progressCurrent = 0;
fromStream.on("data", function(data) {
if (data && data.length)
{
progressCurrent += data.length;
progressBar.update(progressCurrent);
}
});
fromStream.on("end", function() {
progressBar.stop();
});
fromStream.on("error", function(err) {
console.log("Caught error on stream", err);
progressBar.stop();
});
request({
"method": "POST",
"url": uploadUri,
"qs": {},
"headers": headers,
"data": fromStream,
"responseType": "json",
"timeout": pickTimeout(120 * 1000) // 2 minutes
}, function (err, httpResponse, data) {
progressBar.stop();
if (err) {
return callback(err);
}
if (httpResponse.status >= 200 && httpResponse.status <= 204)
{
return callback(null, data);
}
else
{
console.log("Upload failed for: " + filePath);
return callback({
"message": "Status: " + httpResponse.status + ", Message: " + body
});
}
});
});
};
var createSnapshot = r.createSnapshot = function(repositoryId, rootChangesetId, callback)
{
var params = {
"changeset": rootChangesetId
};
_handleGitanaPost("/repositories/" + repositoryId + "/snapshots/start", params, {}, function(err, jsonResponse) {
if (err) {
return _handleJsonResponse(err, jsonResponse, callback);
}
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
_handleJsonResponse(null, job, callback);
});
});
};
var revertBranch = r.revertBranch = function(repositoryId, branchId, tipChangesetId, callback)
{
var params = {
"id": tipChangesetId
};
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/revert/start", params, null, function(err, jsonResponse) {
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
_handleJsonResponse(null, job, callback);
});
});
};
var resetBranch = r.resetBranch = function(repositoryId, branchId, tipChangesetId, callback)
{
var params = {
"id": tipChangesetId
};
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/reset/start", params, null, function(err, jsonResponse) {
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
_handleJsonResponse(err, job, callback);
});
});
};
var rebaseBranch = r.rebaseBranch = function(repositoryId, branchId, rootChangesetId, callback)
{
var params = {
"id": rootChangesetId
};
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/rebase/start", params, null, function(err, jsonResponse) {
var jobId = jsonResponse["_doc"];
waitForCompletionWithProgressBar(jobId, function(err, job) {
console.log("");
_handleJsonResponse(err, job, callback);
});
});
};
var waitForCompletion = r.waitForCompletion = function(jobId, completeFn, progressFn)
{
appConnect(function(err) {
if (err) {
return completeFn(err);
}
var platform = this;
// wait for the job to finish
Chain(platform.getCluster()).waitForJobCompletion(jobId, function(job) {
completeFn(null, job);
}, function(job){
// progress
progressFn(job);
});
});
};
var waitForAdminCompletionWithProgressBar = r.waitForAdminCompletionWithProgressBar = function(jobId, username, password, completeFn, title)
{
var progressBar = createProgressBar(-1, -1, title);
_waitForAdminJobCompletion(jobId, username, password, function(err, job) {
progressBar.stop();
completeFn(err, job);
}, function(job) {
var progressCurrent = job.progressCurrent || 0;
var progressMax = job.progressMax || 100;
progressBar.setTotal(progressMax);
progressBar.update(progressCurrent);
});
};
var waitForCompletionWithProgressBar = r.waitForCompletionWithProgressBar = function(jobId, completeFn)
{
var progressBar = createProgressBar();
waitForCompletion(jobId, function(err, job) {
progressBar.stop();
completeFn(err, job);
}, function(job) {
var progressCurrent = job.progressCurrent || 0;
var progressMax = job.progressMax || 100;
progressBar.setTotal(progressMax);
progressBar.update(progressCurrent);
});
};
var createProgressBar = r.createProgressBar = function(max, current, title)
{
var _cliProgress = require('cli-progress');
var format = "{bar} {percentage}% | Duration: {duration_formatted} | ETA: {eta_formatted} | {value}/{total}";
if (title)
{
format = title + " " + format;
}
// create a new progress bar instance and use shades_classic theme
var bar1 = new _cliProgress.Bar({
format: format
}, _cliProgress.Presets.shades_classic);
if (!max) {
max = 100;
}
if (!current) {
current = 0;
}
bar1.start(max, 0);
return bar1;
};
var queryChangesets = r.queryChangesets = function(repositoryId, queryString, skipString, limitString, sortString, callback) {
var query = {};
if (queryString) {
queryString = queryString.replace(/'/g, '"');
query = JSON.parse(queryString);
}
var pagination = {};
if (skipString) {
pagination.skip = parseInt(skipString);
}
if (limitString) {
pagination.limit = parseInt(limitString);
}
if (sortString) {
sortString = sortString.replace(/'/g, '"');
pagination.sort = JSON.parse(sortString);
}
appConnect(function(err) {
if (err) {
return callback(err);
}
this.readRepository(repositoryId).then(function() {
this.queryChangesets(query, pagination).then(function() {
var jsonResponse = toResultMap(this);
_handleJsonResponse(err, jsonResponse, callback);
});
});
});
};
var listChangesets = r.listChangesets = function(repositoryId, skipString, limitString, sortString, callback) {
return queryChangesets(repositoryId, "{}", skipString, limitString, sortString, callback);
};
var queryNodes = r.queryNodes = function(repositoryId, branchId, queryString, skipString, limitString, sortString, callback) {
var query = {};
if (queryString) {
queryString = queryString.replace(/'/g, '"');
query = JSON.parse(queryString);
}
var params = {};
if (skipString) {
params.skip = parseInt(skipString);
}
if (limitString) {
params.limit = parseInt(limitString);
}
if (sortString) {
sortString = sortString.replace(/'/g, '"');
params.sort = JSON.parse(sortString);
}
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/query", params, query, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var searchNodes = r.searchNodes = function(repositoryId, branchId, queryString, text, skipString, limitString, sortString, callback) {
var query = null;
if (queryString) {
queryString = queryString.replace(/'/g, '"');
query = JSON.parse(queryString);
}
if (text) {
query = {
search: {
query_string: {
query: text
}
}
}
}
var params = {};
if (skipString) {
params.skip = parseInt(skipString);
}
if (limitString) {
params.limit = parseInt(limitString);
}
if (sortString) {
sortString = sortString.replace(/'/g, '"');
params.sort = JSON.parse(sortString);
}
_handleGitanaPost("/repositories/" + repositoryId + "/branches/" + branchId + "/nodes/search", params, query, function(err, jsonResponse) {
_handleJsonResponse(err, jsonResponse, callback);
});
};
var startServer = r.startServer = function(appServerBasePath, callback)
{
// tries to connect using a local gitana.json and, if not found, uses credentials.json
var connect = function(callback)
{
var exists = fs.existsSync("./gitana.json");
if (exists) {
var _gitanaJson = JSON.parse("" + fs.readFileSync("./gitana.json"));
return callback(null, _gitanaJson);
}
return appConnect(function(err, _gitanaJson) {
callback(err, _gitanaJson);
});
};
connect(function(err, _gitanaJson) {
if (err) {
return callback(err);
}
var myURL = url.parse(_gitanaJson.baseURL);
// assume CONFIG1
// set environment variables to inform the app server of how our local stuff is configured
process.env.CLOUDCMS_APPSERVER_BASE_PATH = appServerBasePath;
process.env.GITANA_PROXY_HOST = myURL.hostname;
if (myURL.protocol === "https:") {
process.env.GITANA_PROXY_SCHEME = "https";
}
else if (myURL.protocol === "http:") {
process.env.GITANA_PROXY_SCHEME = "http";
}
if (myURL.port) {
process.env.GITANA_PROXY_PORT = myURL.port;
}
process.env.CLOUDCMS_STORE_CONFIGURATION = "default";
// allow WCM page cache to operate if we're in production mode
process.env.FORCE_CLOUDCMS_WCM_PAGE_CACHE = true;
var port = process.env.PORT || 2999;
var cpuCount = require('os').cpus().length;
console.log("");
console.log("Starting Cloud CMS Application Server (Command Line)...");
console.log("");
var appJsPath = path.join(__dirname, "..", "node_modules", "cloudcms-server", "server");
var spawn = function(command, errorHandler)
{
var active = true;
var child = require('child_process').spawn("" + command, ["standalone.js"], {
"cwd": appJsPath
});
child.stdout.on('data', function (data) {
if (active)
{
process.stdout.write("" + data);
}
});
child.stderr.on('data', function (data) {
if (active)
{
console.log('ERROR: ' + "" + data);
}
});
child.on('error', function (err) {
active = false;
if (errorHandler)
{
errorHandler(err);
}
else
{
console.log('spawn error', err);
}
});
child.on('close', function (code) {
});
};
if (!process.env.CLOUDCMS_NODE_EXEC)
{
process.env.CLOUDCMS_NODE_EXEC = "node";
}
// yes they have node-dev, so we'll use that
spawn(process.env.CLOUDCMS_NODE_EXEC, function(err) {
console.log("Failed to launch with node executable: " + process.env.CLOUDCMS_NODE_EXEC);
console.log(err);
});
// NOTE: don't call back because we want to leave this running
//callback();
});
};
var toResultMap = function(col)
{
var map = {};
map.rows = col.asArray();
map.total_rows = col.__totalRows();
map.offset = col.__offset();
map.size = col.__size();
return map;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var print = r.print = function(text, newline)
{
if (n