mirror of
https://github.com/pnpm/pnpm.git
synced 2026-03-31 13:32:18 -04:00
5
.changeset/dirty-trains-perform.md
Normal file
5
.changeset/dirty-trains-perform.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/local-resolver": patch
|
||||
---
|
||||
|
||||
Don't fail if a local linked directory is not found (unless it should be injected). This is the intended behavior of the "link:" protocol as per Yarn's docs.
|
||||
6
.changeset/tiny-rules-wait.md
Normal file
6
.changeset/tiny-rules-wait.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/symlink-dependency": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Don't fail if a linked directory is not found. Just print a warning about it [#3746](https://github.com/pnpm/pnpm/issues/3746).
|
||||
@@ -151,3 +151,16 @@ test('fail if installing different types of dependencies in a project that uses
|
||||
|
||||
await install(manifest, newOpts)
|
||||
})
|
||||
|
||||
test('installation should not fail if a linked dependency points to a directory that does not exist', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
await install({
|
||||
dependencies: {
|
||||
'is-positive': '1.0.0',
|
||||
'not-exists': 'link:../not-exists',
|
||||
},
|
||||
}, await testDefaults())
|
||||
|
||||
await project.has('is-positive')
|
||||
})
|
||||
|
||||
@@ -55,25 +55,32 @@ export default async function resolveLocal (
|
||||
localDependencyManifest = await readProjectManifestOnly(spec.fetchSpec) as DependencyManifest
|
||||
} catch (internalErr: any) { // eslint-disable-line
|
||||
if (!existsSync(spec.fetchSpec)) {
|
||||
throw new PnpmError('LINKED_PKG_DIR_NOT_FOUND',
|
||||
`Could not install from "${spec.fetchSpec}" as it does not exist.`)
|
||||
}
|
||||
switch (internalErr.code) {
|
||||
case 'ENOTDIR': {
|
||||
throw new PnpmError('NOT_PACKAGE_DIRECTORY',
|
||||
`Could not install from "${spec.fetchSpec}" as it is not a directory.`)
|
||||
}
|
||||
case 'ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND':
|
||||
case 'ENOENT': {
|
||||
if (wantedDependency.injected) {
|
||||
throw new PnpmError('LINKED_PKG_DIR_NOT_FOUND',
|
||||
`Could not install from "${spec.fetchSpec}" as it does not exist.`)
|
||||
}
|
||||
localDependencyManifest = {
|
||||
name: path.basename(spec.fetchSpec),
|
||||
version: '0.0.0',
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
throw internalErr
|
||||
}
|
||||
} else {
|
||||
switch (internalErr.code) {
|
||||
case 'ENOTDIR': {
|
||||
throw new PnpmError('NOT_PACKAGE_DIRECTORY',
|
||||
`Could not install from "${spec.fetchSpec}" as it is not a directory.`)
|
||||
}
|
||||
case 'ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND':
|
||||
case 'ENOENT': {
|
||||
localDependencyManifest = {
|
||||
name: path.basename(spec.fetchSpec),
|
||||
version: '0.0.0',
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
throw internalErr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -107,14 +107,23 @@ test('fail when resolving tarball specified with the link: protocol', async () =
|
||||
}
|
||||
})
|
||||
|
||||
test('fail when resolving from not existing directory', async () => {
|
||||
const wantedDependency = { pref: 'link:./dir-does-not-exist' }
|
||||
test('fail when resolving from not existing directory an injected dependency', async () => {
|
||||
const wantedDependency = { injected: true, pref: 'link:./dir-does-not-exist' }
|
||||
const projectDir = __dirname
|
||||
await expect(
|
||||
resolveFromLocal(wantedDependency, { projectDir })
|
||||
).rejects.toThrow(`Could not install from "${path.join(projectDir, 'dir-does-not-exist')}" as it does not exist.`)
|
||||
})
|
||||
|
||||
test('do not fail when resolving from not existing directory', async () => {
|
||||
const wantedDependency = { pref: 'link:./dir-does-not-exist' }
|
||||
const resolveResult = await resolveFromLocal(wantedDependency, { projectDir: __dirname })
|
||||
expect(resolveResult?.manifest).toStrictEqual({
|
||||
name: 'dir-does-not-exist',
|
||||
version: '0.0.0',
|
||||
})
|
||||
})
|
||||
|
||||
test('throw error when the path: protocol is used', async () => {
|
||||
try {
|
||||
await resolveFromLocal({ pref: 'path:..' }, { projectDir: __dirname })
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
DependencyType,
|
||||
rootLogger,
|
||||
} from '@pnpm/core-loggers'
|
||||
import { globalWarn } from '@pnpm/logger'
|
||||
import { DependenciesField } from '@pnpm/types'
|
||||
import symlinkDir from 'symlink-dir'
|
||||
|
||||
@@ -43,15 +44,22 @@ export default async function symlinkDirectRootDependency (
|
||||
}
|
||||
}
|
||||
|
||||
const dependencyRealocation = await fs.realpath(dependencyLocation)
|
||||
let dependencyRealLocation!: string
|
||||
try {
|
||||
dependencyRealLocation = await fs.realpath(dependencyLocation)
|
||||
} catch (err: any) { // eslint-disable-line
|
||||
if (err.code !== 'ENOENT') throw err
|
||||
globalWarn(`Local dependency not found at ${dependencyLocation}`)
|
||||
return
|
||||
}
|
||||
|
||||
const dest = path.join(destModulesDirReal, importAs)
|
||||
const { reused } = await symlinkDir(dependencyRealocation, dest)
|
||||
const { reused } = await symlinkDir(dependencyRealLocation, dest)
|
||||
if (reused) return // if the link was already present, don't log
|
||||
rootLogger.debug({
|
||||
added: {
|
||||
dependencyType: opts.fromDependenciesField && DEP_TYPE_BY_DEPS_FIELD_NAME[opts.fromDependenciesField] as DependencyType,
|
||||
linkedFrom: dependencyRealocation,
|
||||
linkedFrom: dependencyRealLocation,
|
||||
name: importAs,
|
||||
realName: opts.linkedPackage.name,
|
||||
version: opts.linkedPackage.version,
|
||||
|
||||
Reference in New Issue
Block a user