aboutsummaryrefslogtreecommitdiff
path: root/editors/vscode/src
diff options
context:
space:
mode:
authorFabian Sperber <fabian.sperber@gmx.net>2023-03-10 08:11:45 +0100
committerFabian Sperber <fabian.sperber@gmx.net>2023-03-10 08:11:45 +0100
commitf2232b56a3ce259cdda4b8d5d6f68769b2bebf45 (patch)
tree26370ed4720a84ba302cfc4cf63d27c64d31af63 /editors/vscode/src
parent233fcf32e859518df211e82cd5dc7251dce7ca33 (diff)
Put ols binaries into their own folder by release id, so an update can be done in parallel while still being in use (windows)
Diffstat (limited to 'editors/vscode/src')
-rw-r--r--editors/vscode/src/extension.ts60
1 files changed, 52 insertions, 8 deletions
diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts
index 5d288bb..49a30c9 100644
--- a/editors/vscode/src/extension.ts
+++ b/editors/vscode/src/extension.ts
@@ -154,6 +154,8 @@ async function bootstrap(config: Config, state: PersistentState): Promise<string
const path = await bootstrapServer(config, state);
+ await removeOldServers(config, state);
+
return path;
}
@@ -178,6 +180,37 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise<
return path;
}
+async function removeOldServers(config: Config, state: PersistentState): Promise<void> {
+ if (process.platform != "win32") {
+ // only on windows, releases are put into their separate folders, so no cleanup needed
+ return;
+ }
+ const releasesFolder = config.globalStorageUri.fsPath;
+
+ // get list of all old releases
+ const currentRelease = state.releaseId?.toString() ?? ""
+ const releases = (await fs.readdir(releasesFolder, { withFileTypes: true }))
+ .filter(dirent => dirent.isDirectory() && dirent.name != currentRelease)
+ .map(dirent => dirent.name)
+
+ // try to delete all old releases
+ for (const release of releases) {
+ try {
+ let pathToRemove = path.join(releasesFolder, release)
+ if (release[0] !== '_') {
+ // windows: rename path first to ensure it is not in use anymore
+ const renamedPath = path.join(releasesFolder, '_' + release)
+ await fs.rename(pathToRemove, renamedPath)
+ pathToRemove = renamedPath
+ }
+ fs.rm(pathToRemove, { recursive: true, force: true })
+ } catch {
+ // ignore if the release can't be renamed/removed, probably still in use
+ continue;
+ }
+ }
+}
+
export function createOlsConfig(ctx: Ctx) {
const odinPath = getPathForExecutable("odin");
@@ -245,10 +278,14 @@ async function getServer(config: Config, state: PersistentState): Promise<string
}
*/
- const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : "";
- const destFolder = config.globalStorageUri.fsPath;
- const destExecutable = path.join(destFolder, `ols-${platform}${ext}`);
-
+ const isWindows = platform.indexOf("-windows-") !== -1;
+ const ext = isWindows ? ".exe" : "";
+ // use a separate folder for each release on windows because we can't overwrite files while they are still in use
+ const getDestFolder = (releaseId: number | undefined) => path.join(config.globalStorageUri.fsPath, (releaseId ?? 0).toString());
+ const getExecutable = (releaseId: number | undefined) => path.join(getDestFolder(releaseId), `ols-${platform}${ext}`);
+ const zipFolder = config.globalStorageUri.fsPath;
+ const destExecutable = getExecutable(state.releaseId);
+
const exists = await fs.stat(destExecutable).then(() => true, () => false);
if (!exists) {
@@ -284,7 +321,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
const artifact = release.assets.find(artifact => artifact.name === `ols-${platform}.zip`);
assert(!!artifact, `Bad release: ${JSON.stringify(release)}`);
- const destZip = path.join(destFolder, `ols-${platform}.zip`);
+ const destZip = path.join(zipFolder, `ols-${platform}.zip`);
await downloadWithRetryDialog(state, async () => {
await download({
@@ -297,10 +334,17 @@ async function getServer(config: Config, state: PersistentState): Promise<string
var zip = new AdmZip(destZip);
- zip.extractAllTo(destFolder, true);
+ const latestDestFolder = getDestFolder(release.id);
+ const latestExecutable = getExecutable(release.id);
+
+ if (!await fs.stat(latestDestFolder).then(() => true, () => false)) {
+ await fs.mkdir(latestDestFolder)
+ }
+
+ zip.extractAllTo(latestDestFolder, true);
if (ext !== ".exe") {
- fs.chmod(destExecutable, 0o755);
+ fs.chmod(latestExecutable, 0o755);
}
await state.updateServerVersion(config.package.version);
@@ -308,7 +352,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
await state.updateLastCheck(Date.now());
await vscode.commands.executeCommand("workbench.action.reloadWindow");
- return destExecutable;
+ return latestExecutable;
}
async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> {