@sap/cli-core
Version:
Command-Line Interface (CLI) Core Module
197 lines (196 loc) • 7.09 kB
JavaScript
;
/* eslint-disable */
var fs = require("fs-extra");
var http = require("https");
var path = require("path");
var childProcess = require("child_process");
process.on("message", (m) => {
if (m.kill) {
module.exports.kill().then(() => {
process.send({ killed: true });
});
}
});
// Define exec
var processes = {};
var killCallbacks = {};
var exec = function (cmd, args, options) {
options = options || {};
options.stdio = options.stdio || [0, 1, 2];
options.cwd = options.cwd || path.resolve(__dirname);
console.log("Executing command: " + cmd + " " + args.join(" "));
return new Promise((resolve, reject) => {
var output = [];
var proc = childProcess.spawn(cmd, args, options);
processes[proc.pid] = proc;
if (proc.stdout) {
proc.stdout.on("data", (chunk) => {
output.push(`${chunk}`);
});
}
proc.on("error", reject);
proc.on("exit", (code, signal) => {
if (processes[proc.pid] === proc) {
delete processes[proc.pid];
}
if (typeof killCallbacks[proc.pid] === "function") {
console.log("Killed process: " + proc.spawnargs.join(" "));
return killCallbacks[proc.pid]();
}
if (code !== 0) {
return reject(new Error("Failed command: " +
cmd +
" " +
args.join(" ") +
` (exited ${code})`));
}
return resolve(output.join(""));
});
});
};
var kill = function () {
var pids = Object.keys(processes);
var proms = [];
for (const pid of pids) {
var curProc = processes[pid];
if (!curProc.iskilled) {
proms.push(
// NOSONAR
new Promise((resolve) => {
setTimeout(resolve, 30 * 1000);
killCallbacks[curProc.pid] = resolve;
console.log("Killing process: " + curProc.spawnargs.join(" "));
curProc.kill();
}));
}
}
return Promise.all(proms);
};
module.exports.exec = exec;
module.exports.kill = kill;
module.exports.getResults = { stdio: [0, "pipe", 2] };
// Define cf
var cfReady;
var cfCmd = "cf";
process.env.CF_DEBUG = "1";
var internalMessaging = process.env.CF_DEBUG === "1" ? "inherit" : "ignore";
var checkCF = function () {
var win = process.platform === "win32";
var mac = process.platform === "darwin";
var plat = win ? "windows64-exe" : mac ? "macosx64-binary" : "linux64-binary";
var tmpFolder = path.resolve(__dirname, "../.tmp/cf");
var cfZipFile = path.resolve(tmpFolder, "client.zip");
var cfExeFile = path.resolve(tmpFolder, "cf.exe");
var cfBinFile = path.resolve(tmpFolder, "cf");
var downloadLink = `https://packages.cloudfoundry.org/stable?release=${plat}&source=github`;
if (cfReady) {
return cfReady;
}
cfReady = exec("cf", ["version"], { stdio: internalMessaging })
.then(() => {
console.log("Using global cf client");
cfCmd = "cf";
})
.catch(() => {
// TODO: enable local cf client after downloading
return (fs
.ensureDir(tmpFolder)
.then(() => fs.exists(cfZipFile))
.then((exists) => {
if (exists) {
return;
}
return new Promise((resolve, reject) => {
console.log(`Downloading cf client for platform ${plat}`);
console.log(downloadLink);
var file = fs.createWriteStream(cfZipFile, { mode: 777 });
var fnDownload = function (url) {
http.get(url, (res, err) => {
if (err) {
return reject(err);
}
if (res.statusCode === 302 &&
res.headers &&
res.headers.location) {
return fnDownload(res.headers.location);
}
res.pipe(file).on("finish", resolve);
});
};
fnDownload(downloadLink);
}).then(() => console.log("Downloading cf client Finished ..."));
})
// Unzip
.then(() => {
if (win) {
console.log("Unzipping cf client");
return fs
.readFile(cfZipFile)
.then((data) => {
var jsZip = require("jszip");
// NOSONAR we're dealing with cf and we're pretty sure nobody messes it up
return jsZip.loadAsync(data);
})
.then((zip) => {
var prom = [];
Object.keys(zip.files).forEach((filename) => {
if (zip.files[filename].dir) {
return;
}
prom.push(zip.files[filename]
.async("nodebuffer")
.then((fileData) => {
let dest = path.resolve(tmpFolder, filename);
return fs.outputFile(dest, fileData);
}));
});
return Promise.all(prom)
.then(() => console.log("Unzipping cf client finished"))
.then(() => {
cfCmd = cfExeFile;
});
});
}
else {
// Could be done with node as well
// TODO: test for linux and mac os
console.log("Unzipping cf client");
console.log(cfZipFile);
return exec("tar", ["-xf", cfZipFile, "-C", tmpFolder])
.then(() => console.log("Unzipping cf client finished"))
.then(() => {
cfCmd = cfBinFile;
});
}
}));
})
.then(() => {
// This is expected
});
return cfReady;
};
var execCF = function (args, options) {
return checkCF().then(() => exec(cfCmd, args, options));
};
module.exports.cf = execCF;
// Define npm
var execNpm = function (args, options) {
if (typeof args === "string") {
return execNpmRun(args);
}
var cmd = process.platform === "win32" ? "npm.cmd" : "npm";
options = options || {};
options.cwd = options.cwd || path.resolve(__dirname, "..");
return exec(cmd, args, options);
};
var execNpmRun = function (script) {
return execNpm(["run", script], { cwd: path.resolve(__dirname, "..") });
};
module.exports.npm = execNpm;
// Define git
var execGit = function (args, options) {
options = options || {};
options.stdio = options.stdio || ["pipe", 1, 2];
return exec("git", args, options);
};
module.exports.git = execGit;