@@ -44,10 +44,6 @@ function installDir(): string | undefined {
4444 return undefined ;
4545}
4646
47- function ensureDir ( path : string ) {
48- return ! ! path && stat ( path ) . catch ( ( ) => mkdir ( path , { recursive : true } ) ) ;
49- }
50-
5147interface RustAnalyzerConfig {
5248 askBeforeDownload ?: boolean ;
5349 package : {
@@ -80,38 +76,39 @@ export async function getServer(
8076 'about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we ' +
8177 'will consider it.' ,
8278 ) ;
83- return undefined ;
79+ return ;
8480 }
8581
8682 const dir = installDir ( ) ;
8783 if ( ! dir ) {
8884 return ;
85+ } else {
86+ await stat ( dir ) . catch ( ( ) => mkdir ( dir , { recursive : true } ) ) ;
8987 }
90- await ensureDir ( dir ) ;
9188
9289 const dest = path . join ( dir , binaryName ) ;
9390 const exists = await stat ( dest ) . catch ( ( ) => false ) ;
9491
9592 if ( ! exists ) {
96- await state . updateReleaseTag ( undefined ) ;
97- } else if ( state . releaseTag === config . package . releaseTag ) {
98- return dest ;
93+ await state . updateInstalledRelease ( undefined ) ;
9994 }
10095
101- if ( config . askBeforeDownload ) {
102- const userResponse = await vs . window . showInformationMessage (
103- `${
104- state . releaseTag && state . releaseTag !== config . package . releaseTag
105- ? `You seem to have installed release \`${ state . releaseTag } \` but requested a different one.`
106- : ''
107- }
108- Release \`${
109- config . package . releaseTag
110- } \` of rust-analyzer is not installed.\n
111- Install to ${ dir } ?` ,
112- 'Download' ,
113- ) ;
114- if ( userResponse !== 'Download' ) {
96+ const now = Date . now ( ) ;
97+ if ( state . installedRelease ?. tag == config . package . releaseTag ) {
98+ // Release tags that are *moving* - these are expected to point to different
99+ // commits and update as the time goes on. Make sure to poll the GitHub API
100+ // (at most once per hour) to see if we need to update.
101+ const MOVING_TAGS = [ 'nightly' ] ;
102+ const POLL_INTERVAL = 60 * 60 * 1000 ;
103+
104+ const shouldCheckForNewRelease = MOVING_TAGS . includes (
105+ config . package . releaseTag ,
106+ )
107+ ? state . installedRelease === undefined ||
108+ now - ( state . lastCheck ?? 0 ) > POLL_INTERVAL
109+ : false ;
110+
111+ if ( ! shouldCheckForNewRelease ) {
115112 return dest ;
116113 }
117114 }
@@ -121,19 +118,47 @@ export async function getServer(
121118 'rust-analyzer' ,
122119 config . package . releaseTag ,
123120 ) ;
121+
122+ if ( state . installedRelease ?. id === release . id ) {
123+ return dest ;
124+ }
125+
124126 const artifact = release . assets . find ( asset => asset . name === binaryName ) ;
125127 if ( ! artifact ) {
126128 throw new Error ( `Bad release: ${ JSON . stringify ( release ) } ` ) ;
127129 }
128130
131+ if ( config . askBeforeDownload ) {
132+ const userResponse = await vs . window . showInformationMessage (
133+ `${
134+ state . installedRelease &&
135+ state . installedRelease . tag !== config . package . releaseTag
136+ ? `You seem to have installed release \`${ state . installedRelease ?. tag } \` but requested a different one.`
137+ : ''
138+ }
139+ Release \`${ config . package . releaseTag } \` of rust-analyzer ${
140+ ! state . installedRelease ? 'is not installed' : 'can be updated'
141+ } .\n
142+ Install to ${ dir } ?` ,
143+ 'Download' ,
144+ ) ;
145+ if ( userResponse !== 'Download' ) {
146+ return exists ? dest : undefined ;
147+ }
148+ }
149+
129150 await download ( {
130151 url : artifact . browser_download_url ,
131152 dest,
132153 progressTitle : 'Downloading rust-analyzer server' ,
133154 mode : 0o755 ,
134155 } ) ;
135156
136- await state . updateReleaseTag ( config . package . releaseTag ) ;
157+ await state . updateLastCheck ( now ) ;
158+ await state . updateInstalledRelease ( {
159+ id : release . id ,
160+ tag : config . package . releaseTag ,
161+ } ) ;
137162
138163 return dest ;
139164}
@@ -167,34 +192,25 @@ export async function createLanguageClient(
167192 await rustup . ensureComponents ( config . rustup , REQUIRED_COMPONENTS ) ;
168193 }
169194
170- if ( ! config . rustAnalyzer . path ) {
171- await getServer (
195+ const binPath =
196+ config . rustAnalyzer . path ||
197+ ( await getServer (
172198 {
173199 askBeforeDownload : true ,
174200 package : { releaseTag : config . rustAnalyzer . releaseTag } ,
175201 } ,
176202 new PersistentState ( state ) ,
177- ) ;
203+ ) ) ;
204+
205+ if ( ! binPath ) {
206+ throw new Error ( "Couldn't fetch Rust Analyzer binary" ) ;
178207 }
179208
180209 if ( INSTANCE ) {
181210 return INSTANCE ;
182211 }
183212
184213 const serverOptions : lc . ServerOptions = async ( ) => {
185- const binPath =
186- config . rustAnalyzer . path ||
187- ( await getServer (
188- {
189- package : { releaseTag : config . rustAnalyzer . releaseTag } ,
190- } ,
191- new PersistentState ( state ) ,
192- ) ) ;
193-
194- if ( ! binPath ) {
195- throw new Error ( "Couldn't fetch Rust Analyzer binary" ) ;
196- }
197-
198214 const childProcess = child_process . exec ( binPath ) ;
199215 if ( config . logToFile ) {
200216 const logPath = path . join ( folder . uri . fsPath , `ra-${ Date . now ( ) } .log` ) ;
0 commit comments