@@ -92,6 +92,7 @@ export async function download(opts: DownloadOpts) {
92
92
// This also avoids overwriting running executables
93
93
const randomHex = crypto . randomBytes ( 5 ) . toString ( "hex" ) ;
94
94
const rawDest = path . parse ( opts . dest . fsPath ) ;
95
+ const oldServerPath = vscode . Uri . joinPath ( vscode . Uri . file ( rawDest . dir ) , `${ rawDest . name } -stale-${ randomHex } ${ rawDest . ext } ` ) ;
95
96
const tempFilePath = vscode . Uri . joinPath ( vscode . Uri . file ( rawDest . dir ) , `${ rawDest . name } ${ randomHex } ` ) ;
96
97
97
98
await vscode . window . withProgress (
@@ -116,7 +117,46 @@ export async function download(opts: DownloadOpts) {
116
117
}
117
118
) ;
118
119
119
- await vscode . workspace . fs . rename ( tempFilePath , opts . dest , { overwrite : true } ) ;
120
+ // Try to rename a running server to avoid EPERM on Windows
121
+ // NB: this can lead to issues if a running Code instance tries to restart the server.
122
+ try {
123
+ await vscode . workspace . fs . rename ( opts . dest , oldServerPath , { overwrite : true } ) ;
124
+ log . info ( `Renamed old server binary ${ opts . dest . fsPath } to ${ oldServerPath . fsPath } ` ) ;
125
+ } catch ( err ) {
126
+ const fsErr = err as vscode . FileSystemError ;
127
+ // This is supposed to return `FileNotFound`, alas...
128
+ if ( ! fsErr . code || fsErr . code !== "FileNotFound" && fsErr . code !== "EntryNotFound" ) {
129
+ log . error ( `Cannot rename existing server instance: ${ err } ` ) ;
130
+ }
131
+ }
132
+ try {
133
+ await vscode . workspace . fs . rename ( tempFilePath , opts . dest , { overwrite : true } ) ;
134
+ } catch ( err ) {
135
+ log . error ( `Cannot update server binary: ${ err } ` ) ;
136
+ }
137
+
138
+ // Now try to remove any stale server binaries
139
+ const serverDir = vscode . Uri . file ( rawDest . dir ) ;
140
+ try {
141
+ const entries = await vscode . workspace . fs . readDirectory ( serverDir ) ;
142
+ for ( const [ entry , _ ] of entries ) {
143
+ try {
144
+ if ( entry . includes ( `${ rawDest . name } -stale-` ) ) {
145
+ const uri = vscode . Uri . joinPath ( serverDir , entry ) ;
146
+ try {
147
+ await vscode . workspace . fs . delete ( uri ) ;
148
+ log . info ( `Removed old server binary ${ uri . fsPath } ` ) ;
149
+ } catch ( err ) {
150
+ log . error ( `Unable to remove old server binary ${ uri . fsPath } ` ) ;
151
+ }
152
+ }
153
+ } catch ( err ) {
154
+ log . error ( `Unable to parse ${ entry } ` ) ;
155
+ }
156
+ }
157
+ } catch ( err ) {
158
+ log . error ( `Unable to enumerate contents of ${ serverDir . fsPath } ` ) ;
159
+ }
120
160
}
121
161
122
162
async function downloadFile (
0 commit comments