Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Commit 2ebc079

Browse files
authored
Toolchain handling II (#43)
* Improve ongoing toolchain updates and checks - Check a toolchain has rls before install - Provide hint to latest dated toolchain with rls - Allow updating from dated toolchain * Improve eslint rules + jsdoc * Add new toolchain handling features to readme * Restart servers after installation * Update to atom-languageclient 0.8.2 * Add check for updates every 6 hours * Add check for updates when enabling update checking config
1 parent b59d80c commit 2ebc079

File tree

7 files changed

+314
-129
lines changed

7 files changed

+314
-129
lines changed

.eslintrc.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ module.exports = {
66
browser: true,
77
},
88
rules: {
9-
semi: ["error", "never"],
9+
semi: ["warn", "never"],
1010
"no-console": "off",
11+
"valid-jsdoc": ["warn", {
12+
requireParamDescription: false,
13+
requireReturn: false,
14+
requireReturnDescription: false,
15+
}],
1116
},
1217
globals: {
1318
atom: true,

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Rust language support for Atom-IDE, powered by the Rust Language Server (RLS).
1515
# rls.toml
1616
features = ["serde"]
1717
```
18+
- Graceful handling of Rls being missing from the distribution _(which is somewhat common on the nightly channel)_
19+
* Warns before installing a rust version without Rls or when using an already installed one
20+
* Automatic detection of, and prompt to install, the latest working dated release
1821

1922
## Install
2023
You can install from the command line with:

lib/dist-fetch.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const https = require('https')
2+
const _ = require('underscore-plus')
3+
4+
const datedNightlyHasRlsCache = new Map()
5+
const DATED_REGEX = /(^[^-]+)-(\d{4,}-\d{2}-\d{2})$/
6+
7+
/**
8+
* @param {Date|string} date
9+
* @param {string=} channel
10+
* @return {Promise<string>} toolchain name
11+
*/
12+
function checkDatedNightlyHasRls(date, channel='nightly') {
13+
const dateString = _.isString(date) ? date : date.toISOString().split('T')[0]
14+
const cacheKey = `${channel}-${dateString}`
15+
16+
let fetch = datedNightlyHasRlsCache.get(cacheKey) || new Promise((resolve, reject) => {
17+
https.get(`https://static.rust-lang.org/dist/${dateString}/channel-rust-${channel}.toml`, res => {
18+
if (res.statusCode !== 200) {
19+
return reject(new Error(`Failed, status: ${res.statusCode}`))
20+
}
21+
res.setEncoding("utf8")
22+
let body = ""
23+
res.on("data", data => {
24+
body += data
25+
if (body.includes('rls-preview')) resolve(cacheKey)
26+
})
27+
res.on("end", () => reject(new Error("no 'rls-preview'")))
28+
})
29+
.on("error", e => {
30+
datedNightlyHasRlsCache.delete(cacheKey)
31+
reject(e)
32+
})
33+
})
34+
35+
if (!datedNightlyHasRlsCache.has(cacheKey)) {
36+
datedNightlyHasRlsCache.set(cacheKey, fetch)
37+
}
38+
39+
return fetch
40+
}
41+
42+
/** @return {Promise<string>} latest nightly dated version with rls-preview */
43+
function fetchLatestDatedNightlyWithRls() {
44+
const aDayMillis = 24 * 60 * 60 * 1000
45+
const minDate = new Date(Date.now() - 30 * aDayMillis)
46+
47+
const check = day => {
48+
return checkDatedNightlyHasRls(day)
49+
.catch(e => {
50+
if (e && e.code === 'ENOTFOUND') throw e
51+
52+
const yesterday = new Date(day - aDayMillis)
53+
if (yesterday >= minDate) return check(yesterday)
54+
else throw new Error("No nightly with 'rls-preview'")
55+
})
56+
}
57+
58+
return check(new Date())
59+
}
60+
61+
/**
62+
* @param {string} arg.toolchain toolchain to check
63+
* @param {string} [arg.currentVersion] current installed rustc version
64+
* @return {Promise<?string>} new version of update available (falsy otherwise)
65+
*/
66+
function fetchLatestDist({ toolchain, currentVersion="none" }) {
67+
return new Promise((resolve, reject) => {
68+
https.get(`https://static.rust-lang.org/dist/channel-rust-${toolchain}.toml`, res => {
69+
if (res.statusCode !== 200) {
70+
return reject(new Error(`check for toolchain update failed, status: ${res.statusCode}`))
71+
}
72+
73+
res.setEncoding("utf8")
74+
let body = ""
75+
res.on("data", data => body += data)
76+
res.on("end", () => {
77+
// use a subsection as toml is slow to parse fully
78+
let rustcInfo = body.match(/(\[pkg\.rustc\][^[]*)/m)
79+
if (!rustcInfo) return reject(new Error('could not split channel toml output'))
80+
let rustcVersion = require('toml').parse(rustcInfo[1]).pkg.rustc.version.trim()
81+
resolve(
82+
!currentVersion.trim().endsWith(rustcVersion) &&
83+
body.includes('rls-preview') &&
84+
`rustc ${rustcVersion}`
85+
)
86+
})
87+
})
88+
})
89+
}
90+
91+
/**
92+
* Check a toolchain has rls, this can be done before installing
93+
* @param {string} toolchain
94+
* @return {Promise<boolean>}
95+
*/
96+
function checkHasRls(toolchain) {
97+
let dated = toolchain.match(DATED_REGEX)
98+
if (dated) {
99+
return checkDatedNightlyHasRls(dated[2], dated[1]).then(() => true).catch(() => false)
100+
}
101+
return fetchLatestDist({ toolchain }).then(v => !!v).catch(() => false)
102+
}
103+
104+
module.exports = {
105+
fetchLatestDatedNightlyWithRls,
106+
fetchLatestDist,
107+
checkHasRls,
108+
DATED_REGEX,
109+
}

0 commit comments

Comments
 (0)