mirror of
https://github.com/pnpm/pnpm.git
synced 2026-01-11 00:18:32 -05:00
6
.changeset/purple-days-punch.md
Normal file
6
.changeset/purple-days-punch.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-script-runners": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
When dlx uses cache, use the real directory path not the symlink to the cache.
|
||||
@@ -71,29 +71,29 @@ export async function handler (
|
||||
[command, ...args]: string[]
|
||||
): Promise<{ exitCode: number }> {
|
||||
const pkgs = opts.package ?? [command]
|
||||
const { cacheLink, prepareDir } = findCache(pkgs, {
|
||||
const { cacheLink, cacheExists, cachedDir } = findCache(pkgs, {
|
||||
dlxCacheMaxAge: opts.dlxCacheMaxAge,
|
||||
cacheDir: opts.cacheDir,
|
||||
registries: opts.registries,
|
||||
})
|
||||
if (prepareDir) {
|
||||
fs.mkdirSync(prepareDir, { recursive: true })
|
||||
if (!cacheExists) {
|
||||
fs.mkdirSync(cachedDir, { recursive: true })
|
||||
await add.handler({
|
||||
// Ideally the config reader should ignore these settings when the dlx command is executed.
|
||||
// This is a temporary solution until "@pnpm/config" is refactored.
|
||||
...omit(['workspaceDir', 'rootProjectManifest'], opts),
|
||||
bin: path.join(prepareDir, 'node_modules/.bin'),
|
||||
dir: prepareDir,
|
||||
lockfileDir: prepareDir,
|
||||
rootProjectManifestDir: prepareDir, // This property won't be used as rootProjectManifest will be undefined
|
||||
bin: path.join(cachedDir, 'node_modules/.bin'),
|
||||
dir: cachedDir,
|
||||
lockfileDir: cachedDir,
|
||||
rootProjectManifestDir: cachedDir, // This property won't be used as rootProjectManifest will be undefined
|
||||
saveProd: true, // dlx will be looking for the package in the "dependencies" field!
|
||||
saveDev: false,
|
||||
saveOptional: false,
|
||||
savePeer: false,
|
||||
}, pkgs)
|
||||
await symlinkDir(prepareDir, cacheLink, { overwrite: true })
|
||||
await symlinkDir(cachedDir, cacheLink, { overwrite: true })
|
||||
}
|
||||
const modulesDir = path.join(cacheLink, 'node_modules')
|
||||
const modulesDir = path.join(cachedDir, 'node_modules')
|
||||
const binsDir = path.join(modulesDir, '.bin')
|
||||
const env = makeEnv({
|
||||
userAgent: opts.userAgent,
|
||||
@@ -101,7 +101,7 @@ export async function handler (
|
||||
})
|
||||
const binName = opts.package
|
||||
? command
|
||||
: await getBinName(modulesDir, await getPkgName(cacheLink))
|
||||
: await getBinName(modulesDir, await getPkgName(cachedDir))
|
||||
try {
|
||||
await execa(binName, args, {
|
||||
cwd: process.cwd(),
|
||||
@@ -161,12 +161,15 @@ function findCache (pkgs: string[], opts: {
|
||||
cacheDir: string
|
||||
dlxCacheMaxAge: number
|
||||
registries: Record<string, string>
|
||||
}): { cacheLink: string, prepareDir: string | null } {
|
||||
}): { cacheLink: string, cacheExists: boolean, cachedDir: string } {
|
||||
const dlxCommandCacheDir = createDlxCommandCacheDir(pkgs, opts)
|
||||
const cacheLink = path.join(dlxCommandCacheDir, 'pkg')
|
||||
const valid = isCacheValid(cacheLink, opts.dlxCacheMaxAge)
|
||||
const prepareDir = valid ? null : getPrepareDir(dlxCommandCacheDir)
|
||||
return { cacheLink, prepareDir }
|
||||
const cachedDir = getValidCacheDir(cacheLink, opts.dlxCacheMaxAge)
|
||||
return {
|
||||
cacheLink,
|
||||
cachedDir: cachedDir ?? getPrepareDir(dlxCommandCacheDir),
|
||||
cacheExists: cachedDir != null,
|
||||
}
|
||||
}
|
||||
|
||||
function createDlxCommandCacheDir (
|
||||
@@ -190,17 +193,25 @@ export function createCacheKey (pkgs: string[], registries: Record<string, strin
|
||||
return createBase32Hash(hashStr)
|
||||
}
|
||||
|
||||
function isCacheValid (cacheLink: string, dlxCacheMaxAge: number): boolean {
|
||||
function getValidCacheDir (cacheLink: string, dlxCacheMaxAge: number): string | undefined {
|
||||
let stats: Stats
|
||||
let target: string
|
||||
try {
|
||||
stats = fs.lstatSync(cacheLink)
|
||||
if (stats.isSymbolicLink()) {
|
||||
target = fs.realpathSync(cacheLink)
|
||||
if (!target) return undefined
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
} catch (err) {
|
||||
if (util.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT') {
|
||||
return false
|
||||
return undefined
|
||||
}
|
||||
throw err
|
||||
}
|
||||
return stats.mtime.getTime() + dlxCacheMaxAge * 60_000 >= new Date().getTime()
|
||||
const isValid = stats.mtime.getTime() + dlxCacheMaxAge * 60_000 >= new Date().getTime()
|
||||
return isValid ? target : undefined
|
||||
}
|
||||
|
||||
function getPrepareDir (cachePath: string): string {
|
||||
|
||||
Reference in New Issue
Block a user