UNPKG

@crowdin/cli

Version:

Crowdin CLI is a command line tool that allows you to manage and synchronize your localization resources with your Crowdin project

628 lines (536 loc) 18.4 kB
#! /usr/bin/env node var jarName = "crowdin-cli.jar"; var mainClass = "{{MAIN_CLASS}}"; var classPath = "{{CLASSPATH}}"; var port = "0"; var warPath = ""; var javaVersionString = "17"; var tryJavaHomeFirst = false; var javafx = false; var bundleType = 'jre'; if ('{{JAVAFX}}' === 'true') { javafx = true; } if ('{{JDK}}' === 'true') { bundleType = 'jdk'; } var jdk = (bundleType === 'jdk'); var jdkProvider = 'zulu'; function njreWrap() { 'use strict' const path = require('path') const fs = require('fs') const os = require('os') const crypto = require('crypto') const fetch = require('node-fetch') const yauzl = require('yauzl') const tar = require('tar') function createDir (dir) { return new Promise((resolve, reject) => { fs.access(dir, err => { if (err && err.code === 'ENOENT') { fs.mkdir(dir, err => { if (err) reject(err) resolve() }) } else if (!err) resolve() else reject(err) }) }) } function download (dir, url) { if (url.indexOf("?") > 0 || jdkProvider === 'zulu') { var ext = ".zip"; switch (process.platform) { case 'linux': ext = ".tar.gz"; break; } var destName = bundleType + ext; } else { destName = path.basename(url); } return new Promise((resolve, reject) => { createDir(dir) .then(() => fetch(url)) .then(response => { const destFile = path.join(dir, destName) const destStream = fs.createWriteStream(destFile) response.body.pipe(destStream).on('finish', () => resolve(destFile)) }) .catch(err => reject(err)) }) } function downloadAll (dir, url) { return download(dir, url + '.sha256.txt').then(() => download(dir, url)) } function genChecksum (file) { return new Promise((resolve, reject) => { fs.readFile(file, (err, data) => { if (err) reject(err) resolve( crypto .createHash('sha256') .update(data) .digest('hex') ) }) }) } function verify (file) { return new Promise((resolve, reject) => { fs.readFile(file + '.sha256.txt', 'utf-8', (err, data) => { if (err) reject(err) genChecksum(file).then(checksum => { checksum === data.split(' ')[0] ? resolve(file) : reject(new Error('File and checksum don\'t match')) }) }) }) } function move (file) { return new Promise((resolve, reject) => { const jdeployDir = path.join(os.homedir(), '.jdeploy'); if (!fs.existsSync(jdeployDir)) { fs.mkdirSync(jdeployDir); } var jreDir = path.join(jdeployDir, bundleType); if (!fs.existsSync(jreDir)) { fs.mkdirSync(jreDir); } var vs = javaVersionString; if (javafx) { vs += 'fx'; } jreDir = path.join(jreDir, vs); if (!fs.existsSync(jreDir)) { fs.mkdirSync(jreDir); } const newFile = path.join(jreDir, file.split(path.sep).slice(-1)[0]) //console.log("Copying file "+file+" to "+newFile); fs.copyFile(file, newFile, err => { if (err) reject(err) fs.unlink(file, err => { if (err) reject(err) resolve(newFile) }) }) }) } function extractZip (file, dir) { //console.log("Extracting "+file+" to "+dir); return new Promise((resolve, reject) => { yauzl.open(file, { lazyEntries: true }, (err, zipFile) => { if (err) reject(err) zipFile.readEntry() zipFile.on('entry', entry => { const entryPath = path.join(dir, entry.fileName) if (/\/$/.test(entry.fileName)) { fs.mkdir(entryPath, { recursive: true }, err => { if (err && err.code !== 'EEXIST') reject(err) zipFile.readEntry() }) } else { zipFile.openReadStream(entry, (err, readStream) => { if (err) reject(err) readStream.on('end', () => { zipFile.readEntry() }) readStream.pipe(fs.createWriteStream(entryPath)) }) } }) zipFile.once('close', () => { fs.unlink(file, err => { if (err) reject(err) resolve(dir) }) }) }) }) } function extractTarGz (file, dir) { return tar.x({ file: file, cwd: dir }).then(() => { return new Promise((resolve, reject) => { fs.unlink(file, err => { if (err) reject(err) resolve(dir) }) }) }) } function extract (file) { var dirString = jdk? 'jdk' : 'jre'; const dir = path.join(path.dirname(file), dirString) //console.log("About to extract "+file+" to "+dir); return createDir(dir).then(() => { return path.extname(file) === '.zip' ? extractZip(file, dir) : extractTarGz(file, dir) }) } /** * Installs a JRE copy for the app * @param {number} [version = 8] - Java Version (`8`/`9`/`10`/`11`/`12`) * @param {object} [options] - Installation Options * @param {string} [options.os] - Operating System (defaults to current) (`windows`/`mac`/`linux`/`solaris`/`aix`) * @param {string} [options.arch] - Architecture (defaults to current) (`x64`/`x32`/`ppc64`/`s390x`/`ppc64le`/`aarch64`/`sparcv9`) * @param {string} [options.openjdk_impl = hotspot] - OpenJDK Implementation (`hotspot`/`openj9`) * @param {string} [options.release = latest] - Release * @param {string} [options.type = jre] - Binary Type (`jre`/`jdk`) * @param {string} [options.heap_size] - Heap Size (`normal`/`large`) * @return Promise<string> - Resolves to the installation directory or rejects an error * @example * const njre = require('njre') * * // Use default options * njre.install() * .then(dir => { * // Do stuff * }) * .catch(err => { * // Handle the error * }) * * // or custom ones * njre.install(11, { os: 'aix', arch: 'ppc64', openjdk_impl: 'openj9' }) * .then(dir => { * // Do stuff * }) * .catch(err => { * // Handle the error * }) */ function install (version = 11, options = {}) { const { openjdk_impl = 'hotspot', release = 'latest', type = 'jre', javafx = false, provider = 'zulu' } = options options = { ...options, openjdk_impl, release, type } if (provider === 'zulu') { return installZulu(version, options); } let url = 'https://api.adoptopenjdk.net/v2/info/releases/openjdk' + version + '?' if (!options.os) { switch (process.platform) { case 'aix': options.os = 'aix' break case 'darwin': options.os = 'mac' break case 'linux': options.os = 'linux' break case 'sunos': options.os = 'solaris' break case 'win32': options.os = 'windows' break default: return Promise.reject(new Error('Unsupported operating system')) } } if (!options.arch) { if (options.os == 'mac') { // For now, for compatibility reasons use x64 always options.arch = 'x64'; } else if (/^ppc64|s390x|x32|x64$/g.test(process.arch)) options.arch = process.arch else if (process.arch === 'ia32') options.arch = 'x32' else return Promise.reject(new Error('Unsupported architecture')) } Object.keys(options).forEach(key => { url += key + '=' + options[key] + '&' }) const tmpdir = path.join(os.tmpdir(), 'njre') return fetch(url) .then(response => response.json()) .then(json => downloadAll(tmpdir, json.binaries[0]['binary_link'])) .then(verify) .then(move) .then(extract) } function installZulu(version = 11, options = {}) { const { type = 'jre', javafx = false } = options var q = { java_version: version, ext: 'zip', bundle_type: type, javafx: ''+javafx, arch: 'x86', hw_bitness: '64', }; var zuluBaseURL = "https://api.azul.com/zulu/download/community/v1.0/bundles/latest/binary?" if (!options.os) { switch (process.platform) { case 'darwin': q.os = 'macos' break case 'linux': q.os = 'linux' q.ext = 'tar.gz' break case 'win32': case 'win64': q.os = 'windows' break default: return Promise.reject(new Error('Unsupported operating system')) } } var url = zuluBaseURL; Object.keys(q).forEach(key => { url += key + '=' + q[key] + '&' }) const tmpdir = path.join(os.tmpdir(), 'njre') //console.log("Downloading "+url); return download(tmpdir, url) .then(move) .then(extract) } return {install:install}; } var fs = require('fs'); var os = require('os'); var path = require('path'); const njre = njreWrap(); const targetJavaVersion = parseInt(javaVersionString); var shell = require("shelljs/global"); function getJdeploySupportDir() { return os.homedir() + path.sep + ".jdeploy"; } function getJavaVersion(binPath) { var oldPath = env['PATH']; if (binPath) { env['PATH'] = binPath + path.delimiter + env['PATH']; } try { var javaVersionProc = exec('java -version', {silent:true}); if (javaVersionProc.code !== 0) { return false; } var stdout = javaVersionProc.stderr; var regexp = /version "(.*?)"/; var match = regexp.exec(stdout); var parts = match[1].split('.'); var join = '.'; var versionStr = ''; parts.forEach(function(v) { versionStr += v; if (join !== null) { versionStr += join; join = null; } }); versionStr = versionStr.replace('_', ''); return parseFloat(versionStr); } catch (e) { return false; } finally { env['PATH'] = oldPath; } } var getDirectories = dirPath => fs.readdirSync(dirPath).filter( file => fs.statSync(path.join(dirPath, file)).isDirectory() ); function getJavaHomeInPath(basepath) { var dirs = null; try { dirs = getDirectories(basepath); } catch (e) { return null; } if (dirs && dirs.length > 0) { basepath = path.join(basepath, dirs[0]); if (os.platform() != 'darwin') { return basepath; } if (fs.existsSync(path.join(basepath, 'Contents', 'Home'))) { return path.join(basepath, 'Contents', 'Home'); } var adapterDirectories = getDirectories(basepath).filter(subdir => { return subdir.match(/^zulu/) && fs.existsSync(path.join(basepath, subdir, 'Contents', 'Home')); }); if (adapterDirectories && adapterDirectories.length > 0) { return path.join(basepath, adapterDirectories[0], 'Contents', 'Home'); } } return null; } function findSupportedRuntime(javaVersion, jdk, javafx) { var jdeployDir = path.join(os.homedir(), ".jdeploy"); var JAVA_HOME_OVERRIDE = env['JDEPLOY_JAVA_HOME_OVERRIDE']; if (JAVA_HOME_OVERRIDE && fs.existsSync(JAVA_HOME_OVERRIDE)) { return JAVA_HOME_OVERRIDE; } // First check for the full-meal deal var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jdk', javaVersion+'fx', 'jdk')); if (_javaHomePath && fs.existsSync(_javaHomePath)) { return _javaHomePath; } if (!javafx) { var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jdk', javaVersion, 'jdk')); if (_javaHomePath && fs.existsSync(_javaHomePath)) { return _javaHomePath; } } if (!jdk) { var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jre', javaVersion+'fx', 'jre')); if (_javaHomePath && fs.existsSync(_javaHomePath)) { return _javaHomePath; } } if (!jdk && !javafx) { var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jre', javaVersion, 'jre')); if (_javaHomePath && fs.existsSync(_javaHomePath)) { return _javaHomePath; } } return null; } function getEmbeddedJavaHome() { var _platform = os.platform(); var _driver = ''; switch (_platform) { case 'darwin': _platform = 'macosx'; _driver = 'Contents' + path.sep + 'Home'; break; case 'win32': _platform = 'windows'; _driver = ''; break; case 'linux': _driver = ''; break; default: fail('unsupported platform: ' + _platform); } var vs = javaVersionString; if (javafx) { vs += 'fx'; } var typeDir = jdk ? 'jdk' : 'jre'; var jreDir = path.join(os.homedir(), '.jdeploy', 'jre', vs, 'jre'); try { var out = jreDir + path.sep + getDirectories(jreDir)[0] + (_driver ? (path.sep + _driver) : ''); return out; } catch (e) { return null; } } function javaVersionMatch(v1, v2) { if (v1 === 8) v1 = 1.8; if (v2 === 8) v2 = 1.8; if (Math.floor(v1) !== Math.floor(v2)) { return false; } if (v1 < 2) { // Up to 1.8, the version would be like 1.7, 1.8, etc.. // So we need to check the minor version for equivalency return (Math.floor(v1*10) === Math.floor(v2*10)); } else { // Starting with Java 9, the version is like 9, 10, 11, etc.. // so we just compare major version. return (Math.floor(v1) === Math.floor(v2)); } } var done = false; if (tryJavaHomeFirst) { if (env['JAVA_HOME']) { var javaHomeVersion = getJavaVersion(path.join(env['JAVA_HOME'], 'bin')); if (javaVersionMatch(javaHomeVersion, targetJavaVersion)) { done = true; env['PATH'] = path.join(env['JAVA_HOME'], 'bin') + path.delimiter + env['PATH']; run(env['JAVA_HOME']); } } if (!done) { var javaVersion = getJavaVersion(); if (javaVersionMatch(javaVersion, targetJavaVersion)) { done = true; run(); } } } if (!done) { var _javaHome = findSupportedRuntime(javaVersionString, bundleType === 'jdk', javafx); if (_javaHome && fs.existsSync(_javaHome)) { var javaVersion = getJavaVersion(path.join(_javaHome, 'bin')); if (javaVersionMatch(javaVersion, targetJavaVersion)) { env['PATH'] = path.join(_javaHome, 'bin') + path.delimiter + env['PATH']; env['JAVA_HOME'] = _javaHome; done = true; run(_javaHome); } } } if (!done) { console.log("Downloading java runtime environment for version "+targetJavaVersion); njre.install(targetJavaVersion, {type: bundleType, javafx: javafx}).then(function(dir) { var _javaHome = getJavaHomeInPath(dir); if (_javaHome == null) if (!_javaHome || !fs.existsSync(_javaHome)) { throw new Error("After install, could not find java home at "+_javaHome); } env['JAVA_HOME'] = _javaHome; var javaBinary = path.join(_javaHome, 'bin', 'java'); if (!fs.existsSync(javaBinary)) { javaBinary += '.exe'; } fs.chmodSync(javaBinary, 0o755); env['PATH'] = path.join(env['JAVA_HOME'], 'bin') + path.delimiter + env['PATH']; run(env['JAVA_HOME']); }).catch(function(err) { console.log("Failed to install JRE", err); }); } function run(_javaHome) { var fail = reason => { console.error(reason); process.exit(1); }; classPath = classPath.split(':'); var classPathStr = ''; var first = true; classPath.forEach(function(part) { if (!first) classPathStr += path.delimiter; first = false; classPathStr += __dirname + '/' + part; }); classPath = classPathStr; var userArgs = process.argv.slice(2); var javaArgs = []; javaArgs.push('-Djdeploy.base='+__dirname); javaArgs.push('-Djdeploy.port='+port); javaArgs.push('-Djdeploy.war.path='+warPath); var programArgs = []; userArgs.forEach(function(arg) { if (arg.startsWith('-D') || arg.startsWith('-X')) { javaArgs.push(arg); } else { programArgs.push(arg); } }); var cmd = 'java'; if (!_javaHome) { env['PATH'] = path.join(getEmbeddedJavaHome(), 'bin') + path.delimiter + env['PATH']; if (env['JAVA_HOME']) { env['PATH'] = env['JAVA_HOME'] + path.sep + 'bin' + path.delimiter + env['PATH']; } } else { env['JAVA_HOME'] = _javaHome; cmd = _javaHome + path.sep + 'bin' + path.sep + 'java'; } javaArgs.forEach(function(arg) { cmd += ' "'+arg+'"'; }); if (jarName !== '{'+'{JAR_NAME}}') { cmd += ' -jar "'+__dirname+'/'+jarName+'" '; } else { cmd += ' -cp "'+classPath+'" '+mainClass+' '; } programArgs.forEach(function(arg) { cmd += ' "'+arg+'"'; }); var child = exec(cmd, {async: true}); process.stdin.setEncoding('utf8'); process.stdin.on('readable', function() { var chunk = null; while (null !== (chunk = process.stdin.read())) { try { child.stdin.write(chunk); } catch(e){} } }); child.on('close', function(code) { process.exit(code); }); }