From ae91c8f23d39ea550a6bc67b1ce30882819d44f2 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Fri, 5 Jun 2026 17:03:16 +0000 Subject: [PATCH] fix(tools): use pnpm update for global self updates --- changelog.md | 8 +++++ ts/mod_tools/classes.packagemanager.ts | 49 ++++++++++++++++++++++++-- ts/mod_tools/index.ts | 2 +- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index 26cd6cd..094df58 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## Pending + +### Fixes + +- make global tool self-updates verify and use pnpm's update path + - Uses `pnpm update -g --latest` before falling back to install for latest-version updates. + - Verifies installed package versions through `pnpm list -g` so pnpm v11 hash roots are handled correctly. + ## 2026-06-05 - 2.19.6 ### Fixes diff --git a/ts/mod_tools/classes.packagemanager.ts b/ts/mod_tools/classes.packagemanager.ts index bd0976f..9d014a6 100644 --- a/ts/mod_tools/classes.packagemanager.ts +++ b/ts/mod_tools/classes.packagemanager.ts @@ -425,14 +425,48 @@ export class PackageManagerUtil { return false; } - const packageSpecifier = `${packageName}@${version}`; - console.log(` Installing ${packageSpecifier} via pnpm...`); + let effectiveVersion = version; + if (version === "latest") { + const latestVersion = await this.getLatestMatureVersion(packageName); + console.log(` Updating ${packageName} via pnpm...`); + try { + const updateResult = await this.shell.exec( + `${pnpmCommand} update -g ${shellQuote(packageName)} --latest`, + ); + const installedVersion = await this.getCurrentInstalledPackageVersion( + packageName, + ); + if ( + updateResult.exitCode === 0 && + installedVersion && + (!latestVersion || installedVersion === latestVersion) + ) { + return true; + } + } catch { + // Missing globals need an add instead of update. + } + effectiveVersion = latestVersion || version; + } + + const packageSpecifier = `${packageName}@${effectiveVersion}`; + console.log(` Installing ${packageSpecifier} via pnpm...`); try { const result = await this.shell.exec( `${pnpmCommand} add -g ${shellQuote(packageSpecifier)}`, ); - return result.exitCode === 0; + if (result.exitCode !== 0) { + return false; + } + if (effectiveVersion === "latest") { + return true; + } + + const installedVersion = await this.getCurrentInstalledPackageVersion( + packageName, + ); + return installedVersion === effectiveVersion; } catch { return false; } @@ -636,6 +670,15 @@ export class PackageManagerUtil { return Array.from(packageMap.values()); } + private async getCurrentInstalledPackageVersion( + packageName: string, + ): Promise { + const installedPackage = (await this.getCurrentInstalledPackages()).find( + (packageInfo) => packageInfo.name === packageName, + ); + return installedPackage?.version || null; + } + private async inspectGlobalRoot( globalDir: string, current: boolean, diff --git a/ts/mod_tools/index.ts b/ts/mod_tools/index.ts index c3c2ef8..f5fbe4e 100644 --- a/ts/mod_tools/index.ts +++ b/ts/mod_tools/index.ts @@ -328,7 +328,7 @@ async function handleSelfUpdate( return false; } - const success = await pmUtil.installLatest("@git.zone/cli", latestVersion); + const success = await pmUtil.installLatest("@git.zone/cli"); if (!success) { console.log( "\ngitzone self-update failed. Continuing with the current version.\n",