@@ -44,10 +44,6 @@ function installDir(): string | undefined {
44
44
return undefined ;
45
45
}
46
46
47
- function ensureDir ( path : string ) {
48
- return ! ! path && stat ( path ) . catch ( ( ) => mkdir ( path , { recursive : true } ) ) ;
49
- }
50
-
51
47
interface RustAnalyzerConfig {
52
48
askBeforeDownload ?: boolean ;
53
49
package : {
@@ -80,38 +76,39 @@ export async function getServer(
80
76
'about that [here](https://github.com/rust-analyzer/rust-analyzer/issues) and we ' +
81
77
'will consider it.' ,
82
78
) ;
83
- return undefined ;
79
+ return ;
84
80
}
85
81
86
82
const dir = installDir ( ) ;
87
83
if ( ! dir ) {
88
84
return ;
85
+ } else {
86
+ await stat ( dir ) . catch ( ( ) => mkdir ( dir , { recursive : true } ) ) ;
89
87
}
90
- await ensureDir ( dir ) ;
91
88
92
89
const dest = path . join ( dir , binaryName ) ;
93
90
const exists = await stat ( dest ) . catch ( ( ) => false ) ;
94
91
95
92
if ( ! exists ) {
96
- await state . updateReleaseTag ( undefined ) ;
97
- } else if ( state . releaseTag === config . package . releaseTag ) {
98
- return dest ;
93
+ await state . updateInstalledRelease ( undefined ) ;
99
94
}
100
95
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 ) {
115
112
return dest ;
116
113
}
117
114
}
@@ -121,19 +118,47 @@ export async function getServer(
121
118
'rust-analyzer' ,
122
119
config . package . releaseTag ,
123
120
) ;
121
+
122
+ if ( state . installedRelease ?. id === release . id ) {
123
+ return dest ;
124
+ }
125
+
124
126
const artifact = release . assets . find ( asset => asset . name === binaryName ) ;
125
127
if ( ! artifact ) {
126
128
throw new Error ( `Bad release: ${ JSON . stringify ( release ) } ` ) ;
127
129
}
128
130
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
+
129
150
await download ( {
130
151
url : artifact . browser_download_url ,
131
152
dest,
132
153
progressTitle : 'Downloading rust-analyzer server' ,
133
154
mode : 0o755 ,
134
155
} ) ;
135
156
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
+ } ) ;
137
162
138
163
return dest ;
139
164
}
@@ -167,34 +192,25 @@ export async function createLanguageClient(
167
192
await rustup . ensureComponents ( config . rustup , REQUIRED_COMPONENTS ) ;
168
193
}
169
194
170
- if ( ! config . rustAnalyzer . path ) {
171
- await getServer (
195
+ const binPath =
196
+ config . rustAnalyzer . path ||
197
+ ( await getServer (
172
198
{
173
199
askBeforeDownload : true ,
174
200
package : { releaseTag : config . rustAnalyzer . releaseTag } ,
175
201
} ,
176
202
new PersistentState ( state ) ,
177
- ) ;
203
+ ) ) ;
204
+
205
+ if ( ! binPath ) {
206
+ throw new Error ( "Couldn't fetch Rust Analyzer binary" ) ;
178
207
}
179
208
180
209
if ( INSTANCE ) {
181
210
return INSTANCE ;
182
211
}
183
212
184
213
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
-
198
214
const childProcess = child_process . exec ( binPath ) ;
199
215
if ( config . logToFile ) {
200
216
const logPath = path . join ( folder . uri . fsPath , `ra-${ Date . now ( ) } .log` ) ;
0 commit comments