Skip to content

Commit 65a55b6

Browse files
committed
add setting to prompt before upgrade
1 parent 1cd689a commit 65a55b6

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,20 @@
151151
"type": "string",
152152
"default": "",
153153
"description": "Manually set a language server executable. Can be something on the $PATH or a path to an executable itself. Works with ~, ${HOME} and ${workspaceFolder}."
154+
},
155+
"haskell.hlsUpdateBehavior": {
156+
"scope": "machine",
157+
"type": "string",
158+
"enum": [
159+
"keep-up-to-date",
160+
"prompt"
161+
],
162+
"enumDescriptions": [
163+
"Always download the latest available version when it is published",
164+
"Prompt before downloading a newer version"
165+
],
166+
"default": true,
167+
"markdownDescription": "Only applicable with `#haskell.languageServerVariant#` set to `haskell-language-server`. Determine what to do when a new version of the language server is available."
154168
}
155169
}
156170
},

src/hlsBinaries.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as https from 'https';
44
import * as os from 'os';
55
import * as path from 'path';
66
import { promisify } from 'util';
7-
import { env, ExtensionContext, ProgressLocation, Uri, window, WorkspaceFolder } from 'vscode';
7+
import { env, ExtensionContext, ProgressLocation, Uri, window, workspace, WorkspaceFolder } from 'vscode';
88
import { downloadFile, executableExists, httpsGetSilently } from './utils';
99
import * as validate from './validation';
1010

@@ -20,6 +20,8 @@ interface IAsset {
2020
name: string;
2121
}
2222

23+
type UpdateBehaviour = 'keep-up-to-date' | 'prompt';
24+
2325
const assetValidator: validate.Validator<IAsset> = validate.object({
2426
browser_download_url: validate.string(),
2527
name: validate.string(),
@@ -162,22 +164,57 @@ async function getLatestReleaseMetadata(context: ExtensionContext): Promise<IRel
162164
host: 'api.github.com',
163165
path: '/repos/haskell/haskell-language-server/releases',
164166
};
165-
const offlineCache = path.join(context.globalStoragePath, 'latestRelease.cache.json');
167+
168+
const offlineCache = path.join(context.globalStoragePath, 'latestApprovedRelease.cache.json');
169+
170+
async function readCachedReleaseData(): Promise<IRelease | null> {
171+
try {
172+
const cachedInfo = await promisify(fs.readFile)(offlineCache, { encoding: 'utf-8' });
173+
return validate.parseAndValidate(cachedInfo, cachedReleaseValidator);
174+
} catch (err) {
175+
// If file doesn't exist, return null, otherwise consider it a failure
176+
if (err.code === 'ENOENT') {
177+
return null;
178+
}
179+
throw err;
180+
}
181+
}
166182

167183
try {
168184
const releaseInfo = await httpsGetSilently(opts);
169185
const latestInfoParsed =
170186
validate.parseAndValidate(releaseInfo, githubReleaseApiValidator).find((x) => !x.prerelease) || null;
171187

188+
// Not all users want to upgrade right away, in that case prompt
189+
const updateBehaviour = workspace.getConfiguration('haskell').get('hlsUpdateBehavior') as UpdateBehaviour;
190+
if (updateBehaviour === 'prompt') {
191+
const cachedInfoParsed = await readCachedReleaseData();
192+
193+
if (
194+
latestInfoParsed !== null &&
195+
(cachedInfoParsed === null || latestInfoParsed.tag_name !== cachedInfoParsed.tag_name)
196+
) {
197+
const promptMessage =
198+
cachedInfoParsed === null
199+
? 'No version of the haskell-language-server is installed, would you like to install it now?'
200+
: 'A new version of the haskell-language-server is available, would you like to upgrade now?';
201+
202+
const decision = await window.showInformationMessage(promptMessage, 'Download', 'Nevermind');
203+
if (decision !== 'Download') {
204+
// If not upgrade, bail and don't overwrite cached version information
205+
return cachedInfoParsed;
206+
}
207+
}
208+
}
209+
172210
// Cache the latest successfully fetched release information
173211
await promisify(fs.writeFile)(offlineCache, JSON.stringify(latestInfoParsed), { encoding: 'utf-8' });
174212
return latestInfoParsed;
175213
} catch (githubError) {
176214
// Attempt to read from the latest cached file
177215
try {
178-
const cachedInfo = await promisify(fs.readFile)(offlineCache, { encoding: 'utf-8' });
216+
const cachedInfoParsed = await readCachedReleaseData();
179217

180-
const cachedInfoParsed = validate.parseAndValidate(cachedInfo, cachedReleaseValidator);
181218
window.showWarningMessage(
182219
`Couldn't get the latest haskell-language-server releases from GitHub, used local cache instead:\n${githubError.message}`
183220
);

0 commit comments

Comments
 (0)