diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 3850424b..5f33451c 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -33,9 +33,10 @@ "which": "^1.3.1" }, "scripts": { - "prepare": "yarn download-cli && yarn run clean && yarn run build", + "prepare": "yarn download-cli && yarn download-ls && yarn run clean && yarn run build", "clean": "rimraf lib", "download-cli": "node ./scripts/download-cli.js", + "download-ls": "node ./scripts/download-ls.js", "generate-protocol": "node ./scripts/generate-protocol.js", "lint": "tslint -c ./tslint.json --project ./tsconfig.json", "build": "tsc && ncp ./src/node/cli-protocol/ ./lib/node/cli-protocol/ && yarn lint", diff --git a/arduino-ide-extension/scripts/download-cli.js b/arduino-ide-extension/scripts/download-cli.js index 62506946..d37b1093 100755 --- a/arduino-ide-extension/scripts/download-cli.js +++ b/arduino-ide-extension/scripts/download-cli.js @@ -8,29 +8,14 @@ // [...] // redirecting to latest generated builds by replacing latest with the latest available build date, using the format YYYYMMDD (i.e for 2019/Aug/06 latest is replaced with 20190806 -(async () => { +(() => { const DEFAULT_VERSION = 'latest'; // require('moment')().format('YYYYMMDD'); const os = require('os'); - const fs = require('fs'); const path = require('path'); const shell = require('shelljs'); - const download = require('download'); - const decompress = require('decompress'); - const unzip = require('decompress-unzip'); - const untargz = require('decompress-targz'); - - process.on('unhandledRejection', (reason, _) => { - shell.echo(String(reason)); - shell.exit(1); - throw reason; - }); - process.on('uncaughtException', error => { - shell.echo(String(error)); - shell.exit(1); - throw error; - }); + const downloader = require('./downloader'); const yargs = require('yargs') .option('cli-version', { @@ -50,23 +35,8 @@ const { platform, arch } = process; const build = path.join(__dirname, '..', 'build'); - const downloads = path.join(__dirname, '..', 'downloads'); const cli = path.join(build, `arduino-cli${os.platform() === 'win32' ? '.exe' : ''}`); - if (fs.existsSync(cli) && !force) { - shell.echo(`The 'arduino-cli' already exists at ${cli}. Skipping download.`); - shell.exit(0); - } - if (!fs.existsSync(build)) { - if (shell.mkdir('-p', build).code !== 0) { - shell.echo('Could not create new directory.'); - shell.exit(1); - } - } - if (shell.rm('-rf', cli, downloads).code !== 0) { - shell.exit(1); - } - const suffix = (() => { switch (platform) { case 'darwin': return 'macOS_64bit.tar.gz'; @@ -87,36 +57,6 @@ } const url = `https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-${version}_${suffix}`; - shell.echo(`>>> Downloading 'arduino-cli' from '${url}'...`); - const data = await download(url); - shell.echo(`<<< Download succeeded.`); - shell.echo('>>> Decompressing CLI...'); - const files = await decompress(data, downloads, { - plugins: [ - unzip(), - untargz() - ] - }); - if (files.length === 0) { - shell.echo('Error ocurred when decompressing the CLI.'); - shell.exit(1); - } - const cliIndex = files.findIndex(f => f.path.startsWith('arduino-cli')); - if (cliIndex === -1) { - shell.echo('The downloaded artifact does not contains the CLI.'); - shell.exit(1); - } - shell.echo('<<< Decompressing succeeded.'); - - if (shell.mv('-f', path.join(downloads, files[cliIndex].path), cli).code !== 0) { - shell.echo(`Could not move file to ${cli}.`); - shell.exit(1); - } - if (!fs.existsSync(cli)) { - shell.echo(`Could not find CLI at ${cli}.`); - shell.exit(1); - } else { - shell.echo('Done.'); - } + downloader.download(url, cli, 'arduino-cli', force); })(); \ No newline at end of file diff --git a/arduino-ide-extension/scripts/download-ls.js b/arduino-ide-extension/scripts/download-ls.js new file mode 100755 index 00000000..930841f4 --- /dev/null +++ b/arduino-ide-extension/scripts/download-ls.js @@ -0,0 +1,72 @@ +// @ts-check +// The links to the downloads as of today (28.08.2019) are the following: +// - https://downloads.arduino.cc/arduino-language-server/nightly/arduino-language-server_${SUFFIX} +// - https://downloads.arduino.cc/arduino-language-server/clangd/clangd_${VERSION}_${SUFFIX} + +(() => { + + const DEFAULT_ALS_VERSION = 'nightly'; + const DEFAULT_CLANGD_VERSION = '8.0.1'; + + const os = require('os'); + const path = require('path'); + const shell = require('shelljs'); + const downloader = require('./downloader'); + + const yargs = require('yargs') + .option('ls-version', { + alias: 'lv', + default: DEFAULT_ALS_VERSION, + choices: ['nightly'], + describe: `The version of the 'arduino-language-server' to download. Defaults to ${DEFAULT_ALS_VERSION}.` + }) + .option('clangd-version', { + alias: 'cv', + default: DEFAULT_CLANGD_VERSION, + choices: ['8.0.1'], + describe: `The version of 'clangd' to download. Defaults to ${DEFAULT_CLANGD_VERSION}.` + }) + .option('force-download', { + alias: 'fd', + default: false, + describe: `If set, this script force downloads the 'arduino-language-server' even if it already exists on the file system.` + }) + .version(false).parse(); + + const alsVersion = yargs['ls-version']; + const clangdVersion = yargs['clangd-version'] + const force = yargs['force-download']; + const { platform, arch } = process; + + const build = path.join(__dirname, '..', 'build'); + const als = path.join(build, `arduino-language-server${os.platform() === 'win32' ? '.exe' : ''}`); + const clangd = path.join(build, `clangd${os.platform() === 'win32' ? '.exe' : ''}`); + + let alsSuffix, clangdSuffix; + switch (platform) { + case 'darwin': + alsSuffix = 'Darwin_amd64.zip'; + clangdSuffix = 'macos.zip'; + break; + case 'win32': + alsSuffix = 'Windows_NT_amd64.zip'; + clangdSuffix = 'windows.zip'; + break; + case 'linux': + alsSuffix = 'Linux_amd64.zip'; + break; + } + if (!alsSuffix) { + shell.echo(`The arduino-language-server is not available for ${platform} ${arch}.`); + shell.exit(1); + } + + const alsUrl = `https://downloads.arduino.cc/arduino-language-server/${alsVersion === 'nightly' ? 'nightly/arduino-language-server' : 'arduino-language-server_' + alsVersion}_${alsSuffix}`; + downloader.download(alsUrl, als, 'arduino-language-server', force); + + if (clangdSuffix) { + const clangdUrl = `https://downloads.arduino.cc/arduino-language-server/clangd/clangd_${clangdVersion}_${clangdSuffix}`; + downloader.download(clangdUrl, clangd, 'clangd', force); + } + +})(); \ No newline at end of file diff --git a/arduino-ide-extension/scripts/downloader.js b/arduino-ide-extension/scripts/downloader.js new file mode 100644 index 00000000..929404c9 --- /dev/null +++ b/arduino-ide-extension/scripts/downloader.js @@ -0,0 +1,71 @@ +const fs = require('fs'); +const path = require('path'); +const shell = require('shelljs'); +const download = require('download'); +const decompress = require('decompress'); +const unzip = require('decompress-unzip'); +const untargz = require('decompress-targz'); + +process.on('unhandledRejection', (reason, _) => { + shell.echo(String(reason)); + shell.exit(1); + throw reason; +}); +process.on('uncaughtException', error => { + shell.echo(String(error)); + shell.exit(1); + throw error; +}); + +exports.download = async (url, targetFile, filePrefix, force) => { + const { platform, arch } = process; + + if (fs.existsSync(targetFile) && !force) { + shell.echo(`Skipping download because file already exists: ${targetFile}`); + return; + } + if (!fs.existsSync(path.dirname(targetFile))) { + if (shell.mkdir('-p', path.dirname(targetFile)).code !== 0) { + shell.echo('Could not create new directory.'); + shell.exit(1); + } + } + + const downloads = path.join(__dirname, '..', 'downloads'); + if (shell.rm('-rf', targetFile, downloads).code !== 0) { + shell.exit(1); + } + + shell.echo(`>>> Downloading from '${url}'...`); + const data = await download(url); + shell.echo(`<<< Download succeeded.`); + + shell.echo('>>> Decompressing...'); + const files = await decompress(data, downloads, { + plugins: [ + unzip(), + untargz() + ] + }); + if (files.length === 0) { + shell.echo('Error ocurred while decompressing the archive.'); + shell.exit(1); + } + const fileIndex = files.findIndex(f => f.path.startsWith(filePrefix)); + if (fileIndex === -1) { + shell.echo(`The downloaded artifact does not contain any file with prefix ${filePrefix}.`); + shell.exit(1); + } + shell.echo('<<< Decompressing succeeded.'); + + if (shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile).code !== 0) { + shell.echo(`Could not move file to target path: ${targetFile}`); + shell.exit(1); + } + if (!fs.existsSync(targetFile)) { + shell.echo(`Could not find file: ${targetFile}`); + shell.exit(1); + } else { + shell.echo(`Done: ${targetFile}`); + } +}