|
|
@@ -9,7 +9,7 @@
|
|
|
*/
|
|
|
|
|
|
import { existsSync, globSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
|
-import { resolve } from 'node:path'
|
|
|
+import { dirname, resolve } from 'node:path'
|
|
|
import * as yaml from 'js-yaml'
|
|
|
import { parse as parseToml, type TomlTableWithoutBigInt, type TomlValueWithoutBigInt } from 'smol-toml'
|
|
|
import parseSpdx from 'spdx-expression-parse'
|
|
|
@@ -248,38 +248,72 @@ export function claudeDistributionFromManifest(
|
|
|
*
|
|
|
* @param virtual - the `.pnpm` virtual store directory to scan.
|
|
|
* @param name - the external package name, exactly as `node_modules` spells it.
|
|
|
+ * @param expectedVersion - exact version required when the store retains more than one.
|
|
|
* @returns the parsed manifest, or `undefined` when neither the prefix match
|
|
|
- * nor the content scan finds the package's `package.json`.
|
|
|
+ * nor the content scan finds the requested package version.
|
|
|
*/
|
|
|
-export function virtualManifest(virtual: string, name: string): VirtualManifest | undefined {
|
|
|
+export function virtualManifest(
|
|
|
+ virtual: string,
|
|
|
+ name: string,
|
|
|
+ expectedVersion?: string,
|
|
|
+): VirtualManifest | undefined {
|
|
|
const prefix = `${name.replace('/', '+')}@`
|
|
|
- const entry = readdirSync(virtual).find(dir => dir.startsWith(prefix))
|
|
|
- if (entry !== undefined) {
|
|
|
- return JSON.parse(readFileSync(resolve(virtual, entry, 'node_modules', name, 'package.json'), 'utf8')) as VirtualManifest
|
|
|
+ const entries = readdirSync(virtual)
|
|
|
+ for (const entry of entries.filter(dir => dir.startsWith(prefix))) {
|
|
|
+ const manifest = JSON.parse(readFileSync(resolve(virtual, entry, 'node_modules', name, 'package.json'), 'utf8')) as VirtualManifest
|
|
|
+ if (expectedVersion === undefined || manifest.version === expectedVersion) return manifest
|
|
|
}
|
|
|
- for (const dir of readdirSync(virtual)) {
|
|
|
+ for (const dir of entries) {
|
|
|
const candidate = resolve(virtual, dir, 'node_modules', name, 'package.json')
|
|
|
if (existsSync(candidate)) {
|
|
|
- return JSON.parse(readFileSync(candidate, 'utf8')) as VirtualManifest
|
|
|
+ const manifest = JSON.parse(readFileSync(candidate, 'utf8')) as VirtualManifest
|
|
|
+ if (expectedVersion === undefined || manifest.version === expectedVersion) return manifest
|
|
|
}
|
|
|
}
|
|
|
return undefined
|
|
|
}
|
|
|
|
|
|
+const workspaceLinkedManifestCache = new Map<string, VirtualManifest | undefined>()
|
|
|
+
|
|
|
+/**
|
|
|
+ * Resolve the package version selected for a declaring workspace instead of an
|
|
|
+ * unrelated historical version that still occupies the shared virtual store.
|
|
|
+ * @param name - external package identity.
|
|
|
+ * @returns the first current workspace link for that package, when installed.
|
|
|
+ */
|
|
|
+function workspaceLinkedManifest(name: string): VirtualManifest | undefined {
|
|
|
+ if (workspaceLinkedManifestCache.has(name)) return workspaceLinkedManifestCache.get(name)
|
|
|
+ for (const [path, manifest] of loadWorkspaceManifests().manifests) {
|
|
|
+ if (!ALL_KINDS.some(kind => name in (manifest[kind] ?? {}))) continue
|
|
|
+ const linked = resolve(root, dirname(path), 'node_modules', name, 'package.json')
|
|
|
+ if (!existsSync(linked)) continue
|
|
|
+ const found = JSON.parse(readFileSync(linked, 'utf8')) as VirtualManifest
|
|
|
+ workspaceLinkedManifestCache.set(name, found)
|
|
|
+ return found
|
|
|
+ }
|
|
|
+ workspaceLinkedManifestCache.set(name, undefined)
|
|
|
+ return undefined
|
|
|
+}
|
|
|
+
|
|
|
/** Resolve one installed external package manifest from either pnpm store. */
|
|
|
-function installedManifest(name: string): VirtualManifest | undefined {
|
|
|
+function installedManifest(name: string, expectedVersion?: string): VirtualManifest | undefined {
|
|
|
+ const linked = workspaceLinkedManifest(name)
|
|
|
+ if (linked !== undefined && (expectedVersion === undefined || linked.version === expectedVersion)) return linked
|
|
|
let manifest: (Manifest & { license?: string; repository?: string | { url?: string }; homepage?: string }) | undefined
|
|
|
// Workspace-local link farms can expose a dependency that is not linked at
|
|
|
// the repository root; both are backed by the root workspace's lockfile.
|
|
|
for (const store of ['node_modules', 'native/landlock-run/node_modules']) {
|
|
|
const direct = resolve(root, store, name, 'package.json')
|
|
|
if (existsSync(direct)) {
|
|
|
- manifest = JSON.parse(readFileSync(direct, 'utf8')) as typeof manifest
|
|
|
- break
|
|
|
+ const candidate = JSON.parse(readFileSync(direct, 'utf8')) as typeof manifest
|
|
|
+ if (expectedVersion === undefined || candidate?.version === expectedVersion) {
|
|
|
+ manifest = candidate
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
const virtual = resolve(root, store, '.pnpm')
|
|
|
if (!existsSync(virtual)) continue
|
|
|
- manifest = virtualManifest(virtual, name)
|
|
|
+ manifest = virtualManifest(virtual, name, expectedVersion)
|
|
|
if (manifest !== undefined) break
|
|
|
}
|
|
|
return manifest
|
|
|
@@ -308,7 +342,7 @@ function collectClaudeDistribution(): ClaudeDistribution {
|
|
|
const distribution = claudeDistributionFromManifest(manifest)
|
|
|
let installedPayloads = 0
|
|
|
for (const payload of distribution.payloads) {
|
|
|
- const installed = installedManifest(payload.name)
|
|
|
+ const installed = installedManifest(payload.name, payload.version)
|
|
|
if (installed === undefined) continue
|
|
|
installedPayloads += 1
|
|
|
if (
|