UNPKG

@sap/cli-core

Version:

Command-Line Interface (CLI) Core Module

197 lines (196 loc) 7.09 kB
"use strict"; /* 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;