diff --git a/Makefile b/Makefile index cd5ba44..c1ea720 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,9 @@ export PATH := bin:$(PATH) +.PHONY: debug +debug: + node builder/build.js python riju-lang-python.deb + .PHONY: build-image build-image: docker build . -f docker/Dockerfile.build -t riju:build diff --git a/build/build.js b/build/build.js deleted file mode 100644 index e69de29..0000000 diff --git a/builder/build.js b/builder/build.js new file mode 100644 index 0000000..64a4e2f --- /dev/null +++ b/builder/build.js @@ -0,0 +1,95 @@ +const child_process = require("child_process"); +const fs = require("fs").promises; +const path = require("path"); +const process = require("process"); + +const tmp = require("tmp-promise"); +const YAML = require("yaml"); + +// The build scripts in the language configs assume a specific build +// environment, with these parameters: +// +// * the working directory starts out empty +// * the ${pkg} environment variable has been set to an absolute path +// to the directory where the package should be built +// * we are using bash with 'set -euxo pipefail' + +// Read the YAML config file for the language with the given string ID +// and return it as an object. +async function readLangConfig(lang) { + return YAML.parse(await fs.readFile(`langs/${lang}.yaml`, "utf-8")); +} + +// Given a shell command as a string, execute it with Bash. +async function runCommand(cmd) { + return new Promise((resolve, reject) => { + const proc = child_process.spawn("bash", ["-c", ...cmd]); + proc.on("error", reject); + proc.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`command exited with code ${code}`)); + } + }); + }); +} + +// Given a language config object, assuming that the environment has +// already been set up properly (see top of this file for details), +// run all the commands needed to build a package, and put the +// resulting deb file into debPath. +async function buildPackage(langConfig, debPath) { + const { + id, + name, + install: { apt, pip, manual }, + } = langConfig; + const timestamp = new Date().getTime(); + let debianControlData = `\ +Package: riju-lang-${id} +Version: ${timestamp} +Architecture: amd64 +Maintainer: Radon Rosborough +Description: The ${name} language packaged for Riju +`; + if (apt.length > 0) { + debianControlData += `\ +Depends: ${apt.join(", ")} +`; + } + await fs.mkdir("DEBIAN"); + await fs.writeFile("DEBIAN/control", debianControlData); + await runCommand([ + "fakeroot", + "dpkg-deb", + "--build", + process.env.pkg, + debPath, + ]); +} + +async function main() { + const args = process.argv.slice(2); + if (args.length !== 2) { + console.error("usage: build.js LANG DEB"); + process.exit(1); + } + let [lang, debPath] = args; + debPath = path.join(process.cwd(), debPath); + const langConfig = await readLangConfig(lang); + await tmp.withDir(async (o) => { + const buildDir = o.path; + await tmp.withDir(async (o) => { + const pkgDir = o.path; + process.chdir(buildDir); + process.env.pkg = pkgDir; + await buildPackage(langConfig, debPath); + }); + }); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/build/debug.js b/builder/debug.js similarity index 100% rename from build/debug.js rename to builder/debug.js diff --git a/langs/python.yaml b/langs/python.yaml index c2df720..608d390 100644 --- a/langs/python.yaml +++ b/langs/python.yaml @@ -15,11 +15,11 @@ install: manual: - | xml="$(curl -sSL "https://pvsc.blob.core.windows.net/python-language-server-stable?restype=container&comp=list&prefix=Python-Language-Server-linux-x64")" - nupkg="$(echo "$xml" | grep -Eo 'https://[^<]+\.nupkg' | tail -n1)" - wget "${nupkg}" - unzip -d /opt/mspyls Python-Language-Server-linux-x64.*.nupkg - chmod +x /opt/mspyls/Microsoft.Python.LanguageServer - ln -s /opt/mspyls/Microsoft.Python.LanguageServer /usr/local/bin/Microsoft.Python.LanguageServer + url="$(echo "${xml}" | grep -Eo 'https://[^<]+\.nupkg' | tail -n1)" + wget "${url}" + unzip -d "${pkg}/opt/mspyls" Python-Language-Server-linux-x64.*.nupkg + chmod +x "${pkg}/opt/mspyls/Microsoft.Python.LanguageServer" + ln -s "${pkg}/opt/mspyls/Microsoft.Python.LanguageServer" /usr/local/bin/Microsoft.Python.LanguageServer repl: >- python3 -u diff --git a/package.json b/package.json index 7b0e167..d414df1 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "license": "MIT", "private": true, "dependencies": { + "tmp-promise": "^3.0.2", "yaml": "^1.10.0" } } diff --git a/yarn.lock b/yarn.lock index a24537e..5ecae73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,99 @@ # yarn lockfile v1 +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +tmp-promise@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.2.tgz#6e933782abff8b00c3119d63589ca1fb9caaa62a" + integrity sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA== + dependencies: + tmp "^0.2.0" + +tmp@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + yaml@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"