diff --git a/.gitattributes b/.gitattributes index 62ebebc..572b831 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,9 @@ * text=auto # don't diff machine generated files -dist/ -diff package-lock.json -diff pnpm-lock.yaml -diff + +# Built files +dist/ -diff +dist/** filter=lfs diff=lfs merge=lfs -text diff --git a/package.json b/package.json index fc7db42..cba4625 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ }, "scripts": { "format": "prettier --write .", - "test.format": "prettier . --check", - "lint": "eslint . --fix", - "test.lint": "eslint .", + "test.format": "prettier . --check", + "lint": "eslint . --fix", + "test.lint": "eslint .", "test": "atom --test spec", "clean": "shx rm -rf dist", "tsc": "tsc -p src/tsconfig.json", @@ -31,7 +31,7 @@ "build": "npm run tsc", "dev": "npm run tsc.dev", "get.grammars": "node ./scripts/get-grammars.js", - "get.serve-d": "node ./scripts/get-serve-d.js", + "get.serve-d": "ts-node -P ./scripts/tsconfig.json ./scripts/get-serve-d.ts", "build-commit": "build-commit -o dist", "prepare": "npm run build" }, @@ -85,8 +85,10 @@ "devDependencies": { "@terascope/fetch-github-release": "^0.7.4", "@types/atom": "1.40.7", + "@types/decompress": "^4.2.3", "@types/fs-extra": "^9.0.7", "@types/node": "^14.14.31", + "@types/semver": "^7.3.4", "build-commit": "0.1.4", "cross-env": "7.0.3", "decompress": "^4.2.1", @@ -95,7 +97,9 @@ "eslint-config-atomic": "^1.10.2", "gitly": "^2.0.2", "prettier": "^2.2.1", + "semver": "^7.3.4", "shx": "0.3.3", + "ts-node": "^9.1.1", "typescript": "^4.2.2" }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48f8a28..6b89425 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,8 +5,10 @@ dependencies: devDependencies: '@terascope/fetch-github-release': 0.7.4 '@types/atom': 1.40.7 + '@types/decompress': 4.2.3 '@types/fs-extra': 9.0.7 '@types/node': 14.14.31 + '@types/semver': 7.3.4 build-commit: 0.1.4 cross-env: 7.0.3 decompress: 4.2.1 @@ -15,7 +17,9 @@ devDependencies: eslint-config-atomic: 1.10.2_eslint@7.20.0 gitly: 2.0.2 prettier: 2.2.1 + semver: 7.3.4 shx: 0.3.3 + ts-node: 9.1.1_typescript@4.2.2 typescript: 4.2.2 lockfileVersion: 5.2 packages: @@ -276,6 +280,12 @@ packages: dev: true resolution: integrity: sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== + /@types/decompress/4.2.3: + dependencies: + '@types/node': 14.14.31 + dev: true + resolution: + integrity: sha512-W24e3Ycz1UZPgr1ZEDHlK4XnvOr+CpJH3qNsFeqXwwlW/9END9gxn3oJSsp7gYdiQxrXUHwUUd3xuzVz37MrZQ== /@types/fs-extra/9.0.7: dependencies: '@types/node': 14.14.28 @@ -318,6 +328,10 @@ packages: dev: true resolution: integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + /@types/semver/7.3.4: + dev: true + resolution: + integrity: sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== /@types/yauzl/2.9.1: dependencies: '@types/node': 14.14.22 @@ -529,6 +543,10 @@ packages: dev: true resolution: integrity: sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + /arg/4.1.3: + dev: true + resolution: + integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== /argparse/1.0.10: dependencies: sprintf-js: 1.0.3 @@ -801,6 +819,10 @@ packages: dev: true resolution: integrity: sha1-+PeLdniYiO858gXNY39o5wISKyw= + /buffer-from/1.1.1: + dev: true + resolution: + integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== /buffer/5.7.1: dependencies: base64-js: 1.5.1 @@ -1025,6 +1047,10 @@ packages: dev: true resolution: integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + /create-require/1.1.1: + dev: true + resolution: + integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== /cross-env/7.0.3: dependencies: cross-spawn: 7.0.3 @@ -1191,6 +1217,12 @@ packages: hasBin: true resolution: integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + /diff/4.0.2: + dev: true + engines: + node: '>=0.3.1' + resolution: + integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== /dir-glob/3.0.1: dependencies: path-type: 4.0.0 @@ -2489,6 +2521,10 @@ packages: node: '>=4' resolution: integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + /make-error/1.3.6: + dev: true + resolution: + integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== /marked/1.2.9: dev: false engines: @@ -3261,12 +3297,25 @@ packages: node: '>=10' resolution: integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + /source-map-support/0.5.19: + dependencies: + buffer-from: 1.1.1 + source-map: 0.6.1 + dev: true + resolution: + integrity: sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== /source-map/0.5.7: dev: true engines: node: '>=0.10.0' resolution: integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + /source-map/0.6.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== /spdx-correct/3.1.1: dependencies: spdx-expression-parse: 3.0.1 @@ -3519,6 +3568,23 @@ packages: node: '>=8.0' resolution: integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + /ts-node/9.1.1_typescript@4.2.2: + dependencies: + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + source-map-support: 0.5.19 + typescript: 4.2.2 + yn: 3.1.1 + dev: true + engines: + node: '>=10.0.0' + hasBin: true + peerDependencies: + typescript: '>=2.7' + resolution: + integrity: sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== /tsconfig-paths/3.9.0: dependencies: '@types/json5': 0.0.29 @@ -3693,6 +3759,12 @@ packages: dev: true resolution: integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + /yn/3.1.1: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== /zadeh/2.0.2: dependencies: bindings: 1.5.0 @@ -3705,8 +3777,10 @@ packages: specifiers: '@terascope/fetch-github-release': ^0.7.4 '@types/atom': 1.40.7 + '@types/decompress': ^4.2.3 '@types/fs-extra': ^9.0.7 '@types/node': ^14.14.31 + '@types/semver': ^7.3.4 atom-languageclient: ^1.2.2 build-commit: 0.1.4 cross-env: 7.0.3 @@ -3718,5 +3792,7 @@ specifiers: gitly: ^2.0.2 path-exists: ^4.0.0 prettier: ^2.2.1 + semver: ^7.3.4 shx: 0.3.3 + ts-node: ^9.1.1 typescript: ^4.2.2 diff --git a/scripts/get-serve-d.js b/scripts/get-serve-d.js deleted file mode 100644 index 72804ba..0000000 --- a/scripts/get-serve-d.js +++ /dev/null @@ -1,26 +0,0 @@ -// script to download serve-d binaries from GitHub - -const downloadRelease = require("@terascope/fetch-github-release") -const { join, dirname, basename, extname } = require("path") -const { remove, ensureDir } = require("fs-extra") -const decompress = require("decompress") -const decompressTarxz = require("decompress-tarxz") - -;(async () => { - const distFolder = join(dirname(__dirname), "dist") - await remove(distFolder) - await ensureDir(distFolder) - const assets = await downloadRelease("Pure-D", "serve-d", distFolder, undefined, undefined, true) - for (const asset of assets) { - const platform = basename(asset).match(/windows|linux|osx/)[0] - extname(asset) - if (extname(asset) === ".xz") { - await decompress(asset, join(distFolder, platform), { - plugins: [decompressTarxz()], - }) - } else { - await decompress(asset, join(distFolder, platform)) - } - remove(asset) - } -})() diff --git a/scripts/get-serve-d.ts b/scripts/get-serve-d.ts new file mode 100644 index 0000000..72f3506 --- /dev/null +++ b/scripts/get-serve-d.ts @@ -0,0 +1,41 @@ +import downloadRelease from "@terascope/fetch-github-release" +import { join, dirname, extname, basename } from "path" +import { remove, ensureDir } from "fs-extra" +import decompress from "decompress" +import decompressTarxz from "decompress-tarxz" + +// function to download serve-d binaries from GitHub +export async function getServeD() { + const distFolder = join(dirname(__dirname), "dist") + + await remove(distFolder) + await ensureDir(distFolder) + + const assets = ((await downloadRelease( + /* username */ "Pure-D", + /* repo */ "serve-d", + /* download folder */ distFolder, + /* filter release */ undefined, + /* filter asset */ undefined, // (asset) => asset.name.indexOf(platform) >= 0, + true + )) as unknown) as string[] + + for (const asset of assets) { + const platform = basename(asset).match(/windows|linux|osx/)[0] + const downloadFolder = join(distFolder, platform) + if (extname(asset) === ".xz") { + await decompress(asset, downloadFolder, { + plugins: [decompressTarxz()], + }) + } else { + await decompress(asset, downloadFolder) + } + remove(asset) + } +} + +getServeD() + .then(() => console.log("Done")) + .catch((e) => { + throw e + }) diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json new file mode 100644 index 0000000..0a677a1 --- /dev/null +++ b/scripts/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../src/tsconfig.json" +} diff --git a/src/installation.ts b/src/installation.ts index 8105dc9..a2d0be5 100644 --- a/src/installation.ts +++ b/src/installation.ts @@ -1,6 +1,11 @@ import { copy } from "fs-extra" import pathExists from "path-exists" import { join, dirname } from "path" +import semverCompare from "semver/functions/compare" + +import { execFile as execFileRaw } from "child_process" +import { promisify } from "util" +const execFile = promisify(execFileRaw) const distFolder = join(dirname(__dirname), "dist") @@ -28,12 +33,38 @@ async function isServeDInstalled(serveDPath: string) { return pathExists(serveDPath) } +/** get the version of serve-d */ +async function getServeDVersion(file: string) { + try { + const output = (await execFile(file, ["--version"])).stderr + const version = output.match(/v(\d\S*)\s/)[1] + return version + } catch (e) { + console.error(e) + return null + } +} + +/** Check if the given serve-d is up to date against the target version */ +export async function isServeDUpToDate(givenFile: string, targetFile: string) { + const givenVersion = await getServeDVersion(givenFile) + const targetVersion = await getServeDVersion(targetFile) + return givenVersion && targetVersion && semverCompare(givenVersion, targetVersion) !== -1 +} + +async function copyServeD(codeDBinFolder: string) { + atom.notifications.addInfo("Installing serve-d...") + // copy the whole served folder + await copy(bundledServerMap[process.platform], codeDBinFolder, { overwrite: true }) + atom.notifications.addSuccess("Serve-d was installed") +} + export async function installServeD() { const codeDBinFolder = await getCodeDBinFolder() const serveDPath = join(codeDBinFolder, serveDExeFileName) - if (!(await isServeDInstalled(serveDPath))) { - // copy the whole served folder - await copy(bundledServerMap[process.platform], codeDBinFolder) + const bundledServeDPath = join(bundledServerMap[process.platform], serveDExeFileName) + if (!(await isServeDInstalled(serveDPath)) || !(await isServeDUpToDate(serveDPath, bundledServeDPath))) { + await copyServeD(codeDBinFolder) } return serveDPath }