From 71893c2d5a0837a063fb122cd66fd3c963d8e938 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 18 Aug 2020 23:05:40 +0200 Subject: [PATCH] Wholly use `vscode.Memento` API to store installed RA release tag --- src/rust-analyzer/persistent_state.ts | 79 ++------------------------- src/rust-analyzer/rustAnalyzer.ts | 32 +++++------ 2 files changed, 19 insertions(+), 92 deletions(-) diff --git a/src/rust-analyzer/persistent_state.ts b/src/rust-analyzer/persistent_state.ts index 1dfbae72..2022c6c3 100644 --- a/src/rust-analyzer/persistent_state.ts +++ b/src/rust-analyzer/persistent_state.ts @@ -1,75 +1,8 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import { promisify } from 'util'; import * as vscode from 'vscode'; -const stat = promisify(fs.stat); -const mkdir = promisify(fs.mkdir); -const readFile = promisify(fs.readFile); -const writeFile = promisify(fs.writeFile); - -/** Returns a path where persistent data for rust-analyzer should be installed. */ -function metadataDir(): string | undefined { - if (process.platform === 'linux' || process.platform === 'darwin') { - // Prefer, in this order: - // 1. $XDG_CONFIG_HOME/rust-analyzer - // 2. $HOME/.config/rust-analyzer - const { HOME, XDG_CONFIG_HOME } = process.env; - const baseDir = XDG_CONFIG_HOME || (HOME && path.join(HOME, '.config')); - - return baseDir && path.resolve(path.join(baseDir, 'rust-analyzer')); - } else if (process.platform === 'win32') { - // %LocalAppData%\rust-analyzer\ - const { LocalAppData } = process.env; - return ( - LocalAppData && path.resolve(path.join(LocalAppData, 'rust-analyzer')) - ); - } - - return undefined; -} - -export interface Metadata { - releaseTag: string; -} - -export async function readMetadata(): Promise> { - const stateDir = metadataDir(); - if (!stateDir) { - throw new Error('Not supported'); - } - - const filePath = path.join(stateDir, 'metadata.json'); - if (!(await stat(filePath).catch(() => false))) { - throw new Error('File missing'); - } - - const contents = await readFile(filePath, 'utf8'); - const obj = JSON.parse(contents) as unknown; - return typeof obj === 'object' ? obj || {} : {}; -} - -export async function writeMetadata(config: Metadata) { - const stateDir = metadataDir(); - if (!stateDir) { - return false; - } - - if (!(await ensureDir(stateDir))) { - return false; - } - - const filePath = path.join(stateDir, 'metadata.json'); - return writeFile(filePath, JSON.stringify(config)).then(() => true); -} - -function ensureDir(path: string) { - return !!path && stat(path).catch(() => mkdir(path, { recursive: true })); -} - export class PersistentState { constructor(private readonly globalState: vscode.Memento) { - const { lastCheck, releaseId, serverVersion } = this; + const { lastCheck, releaseId, releaseTag: serverVersion } = this; console.info('PersistentState:', { lastCheck, releaseId, serverVersion }); } @@ -95,13 +28,13 @@ export class PersistentState { } /** - * Version of the extension that installed the server. + * Release tag of the installed server. * Used to check if we need to update the server. */ - get serverVersion(): string | undefined { - return this.globalState.get('serverVersion'); + get releaseTag(): string | undefined { + return this.globalState.get('releaseTag'); } - async updateServerVersion(value: string | undefined) { - await this.globalState.update('serverVersion', value); + async updateReleaseTag(value: string | undefined) { + await this.globalState.update('releaseTag', value); } } diff --git a/src/rust-analyzer/rustAnalyzer.ts b/src/rust-analyzer/rustAnalyzer.ts index 289d6a87..6c4b3734 100644 --- a/src/rust-analyzer/rustAnalyzer.ts +++ b/src/rust-analyzer/rustAnalyzer.ts @@ -10,12 +10,7 @@ import { WorkspaceProgress } from '../extension'; import { download, fetchRelease } from '../net'; import * as rustup from '../rustup'; import { Observable } from '../utils/observable'; -import { - Metadata, - readMetadata, - writeMetadata, - PersistentState, -} from './persistent_state'; +import { PersistentState } from './persistent_state'; const stat = promisify(fs.stat); const mkdir = promisify(fs.mkdir); @@ -64,8 +59,6 @@ export async function getServer( config: RustAnalyzerConfig, state: PersistentState, ): Promise { - const { askBeforeDownload, package: pkg } = config; - let binaryName: string | undefined; if (process.arch === 'x64' || process.arch === 'ia32') { if (process.platform === 'linux') { @@ -96,22 +89,25 @@ export async function getServer( } await ensureDir(dir); - const metadata: Partial = await readMetadata().catch(() => ({})); - const dest = path.join(dir, binaryName); const exists = await stat(dest).catch(() => false); - if (exists && metadata.releaseTag === pkg.releaseTag) { + + if (!exists) { + await state.updateReleaseTag(undefined); + } else if (state.releaseTag === config.package.releaseTag) { return dest; } - if (askBeforeDownload) { + if (config.askBeforeDownload) { const userResponse = await vs.window.showInformationMessage( `${ - metadata.releaseTag && metadata.releaseTag !== pkg.releaseTag - ? `You seem to have installed release \`${metadata.releaseTag}\` but requested a different one.` + state.releaseTag && state.releaseTag !== config.package.releaseTag + ? `You seem to have installed release \`${state.releaseTag}\` but requested a different one.` : '' } - Release \`${pkg.releaseTag}\` of rust-analyzer is not installed.\n + Release \`${ + config.package.releaseTag + }\` of rust-analyzer is not installed.\n Install to ${dir}?`, 'Download', ); @@ -123,7 +119,7 @@ export async function getServer( const release = await fetchRelease( 'rust-analyzer', 'rust-analyzer', - pkg.releaseTag, + config.package.releaseTag, ); const artifact = release.assets.find(asset => asset.name === binaryName); if (!artifact) { @@ -137,9 +133,7 @@ export async function getServer( mode: 0o755, }); - await writeMetadata({ releaseTag: pkg.releaseTag }).catch(() => { - vs.window.showWarningMessage(`Couldn't save rust-analyzer metadata`); - }); + await state.updateReleaseTag(config.package.releaseTag); return dest; }