11import * as vscode from "vscode" ;
22import * as path from "path" ;
3- import { promises as dns } from "dns" ;
43import { spawnSync } from "child_process" ;
54
65import { ArtifactSource } from "./interfaces" ;
76import { fetchArtifactReleaseInfo } from "./fetch_artifact_release_info" ;
8- import { downloadArtifact } from "./download_artifact " ;
7+ import { downloadArtifactWithProgressUi } from "./downloads " ;
98import { log , assert } from "../util" ;
9+ import { Config , NIGHTLY_TAG } from "../config" ;
10+
11+ export async function ensureServerBinary ( config : Config ) : Promise < null | string > {
12+ const source = config . serverSource ;
1013
11- export async function ensureServerBinary ( source : null | ArtifactSource ) : Promise < null | string > {
1214 if ( ! source ) {
1315 vscode . window . showErrorMessage (
1416 "Unfortunately we don't ship binaries for your platform yet. " +
@@ -35,18 +37,11 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
3537 return null ;
3638 }
3739 case ArtifactSource . Type . GithubRelease : {
38- const prebuiltBinaryPath = path . join ( source . dir , source . file ) ;
39-
40- const installedVersion : null | string = getServerVersion ( source . storage ) ;
41- const requiredVersion : string = source . tag ;
42-
43- log . debug ( "Installed version:" , installedVersion , "required:" , requiredVersion ) ;
44-
45- if ( isBinaryAvailable ( prebuiltBinaryPath ) && installedVersion === requiredVersion ) {
46- return prebuiltBinaryPath ;
40+ if ( ! shouldDownloadServer ( source , config ) ) {
41+ return path . join ( source . dir , source . file ) ;
4742 }
4843
49- if ( source . askBeforeDownload ) {
44+ if ( config . askBeforeDownload ) {
5045 const userResponse = await vscode . window . showInformationMessage (
5146 `Language server version ${ source . tag } for rust-analyzer is not installed. ` +
5247 "Do you want to download it now?" ,
@@ -55,38 +50,53 @@ export async function ensureServerBinary(source: null | ArtifactSource): Promise
5550 if ( userResponse !== "Download now" ) return null ;
5651 }
5752
58- if ( ! await downloadServer ( source ) ) return null ;
59-
60- return prebuiltBinaryPath ;
53+ return await downloadServer ( source , config ) ;
6154 }
6255 }
6356}
6457
65- async function downloadServer ( source : ArtifactSource . GithubRelease ) : Promise < boolean > {
58+ function shouldDownloadServer (
59+ source : ArtifactSource . GithubRelease ,
60+ config : Config
61+ ) : boolean {
62+ if ( ! isBinaryAvailable ( path . join ( source . dir , source . file ) ) ) return true ;
63+
64+ const installed = {
65+ tag : config . serverReleaseTag . get ( ) ,
66+ date : config . serverReleaseDate . get ( )
67+ } ;
68+ const required = {
69+ tag : source . tag ,
70+ date : config . installedNightlyExtensionReleaseDate . get ( )
71+ } ;
72+
73+ log . debug ( "Installed server:" , installed , "required:" , required ) ;
74+
75+ if ( required . tag !== NIGHTLY_TAG || installed . tag !== NIGHTLY_TAG ) {
76+ return required . tag !== installed . tag ;
77+ }
78+
79+ assert ( required . date !== null , "Extension release date should have been saved during its installation" ) ;
80+ assert ( installed . date !== null , "Server release date should have been saved during its installation" ) ;
81+
82+ return installed . date . getTime ( ) !== required . date . getTime ( ) ;
83+ }
84+
85+ async function downloadServer (
86+ source : ArtifactSource . GithubRelease ,
87+ config : Config ,
88+ ) : Promise < null | string > {
6689 try {
6790 const releaseInfo = await fetchArtifactReleaseInfo ( source . repo , source . file , source . tag ) ;
6891
69- await downloadArtifact ( releaseInfo , source . file , source . dir , "language server" ) ;
70- await setServerVersion ( source . storage , releaseInfo . releaseName ) ;
92+ await downloadArtifactWithProgressUi ( releaseInfo , source . file , source . dir , "language server" ) ;
93+ await Promise . all ( [
94+ config . serverReleaseTag . set ( releaseInfo . releaseName ) ,
95+ config . serverReleaseDate . set ( releaseInfo . releaseDate )
96+ ] ) ;
7197 } catch ( err ) {
72- vscode . window . showErrorMessage (
73- `Failed to download language server from ${ source . repo . name } ` +
74- `GitHub repository: ${ err . message } `
75- ) ;
76-
77- log . error ( err ) ;
78-
79- dns . resolve ( 'example.com' ) . then (
80- addrs => log . debug ( "DNS resolution for example.com was successful" , addrs ) ,
81- err => {
82- log . error (
83- "DNS resolution for example.com failed, " +
84- "there might be an issue with Internet availability"
85- ) ;
86- log . error ( err ) ;
87- }
88- ) ;
89- return false ;
98+ log . downloadError ( err , "language server" , source . repo . name ) ;
99+ return null ;
90100 }
91101
92102 const binaryPath = path . join ( source . dir , source . file ) ;
@@ -101,7 +111,7 @@ async function downloadServer(source: ArtifactSource.GithubRelease): Promise<boo
101111 "Rust analyzer language server was successfully installed 🦀"
102112 ) ;
103113
104- return true ;
114+ return binaryPath ;
105115}
106116
107117function isBinaryAvailable ( binaryPath : string ) : boolean {
@@ -115,14 +125,3 @@ function isBinaryAvailable(binaryPath: string): boolean {
115125
116126 return res . status === 0 ;
117127}
118-
119- function getServerVersion ( storage : vscode . Memento ) : null | string {
120- const version = storage . get < null | string > ( "server-version" , null ) ;
121- log . debug ( "Get server-version:" , version ) ;
122- return version ;
123- }
124-
125- async function setServerVersion ( storage : vscode . Memento , version : string ) : Promise < void > {
126- log . debug ( "Set server-version:" , version ) ;
127- await storage . update ( "server-version" , version . toString ( ) ) ;
128- }
0 commit comments