fix: import method selection on unknown errors

close #2869
PR #2870
This commit is contained in:
Zoltan Kochan
2020-09-18 01:25:02 +03:00
committed by GitHub
parent 3165c5fb7d
commit d94b19b39e
3 changed files with 15 additions and 14 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/package-store": patch
---
Unless an EXDEV error is thrown during hard linking, always choose hard linking for importing packages from the store.

View File

@@ -70,18 +70,16 @@ function createAutoImporter (): ImportFunction {
auto = hardlinkPkg.bind(null, linkOrCopy)
return 'hardlink'
} catch (err) {
if (err.code === 'EINVAL') {
// This error sometimes happens on Windows.
// We still choose hard linking that will fall back to copying in edge cases.
packageImportMethodLogger.debug({ method: 'hardlink' })
auto = hardlinkPkg.bind(null, linkOrCopy)
if (err.message.startsWith('EXDEV: cross-device link not permitted')) {
globalWarn(err.message)
globalInfo('Falling back to copying packages from store')
packageImportMethodLogger.debug({ method: 'copy' })
auto = copyPkg
return auto(to, opts)
}
if (!err.message.startsWith('EXDEV: cross-device link not permitted')) throw err
globalWarn(err.message)
globalInfo('Falling back to copying packages from store')
packageImportMethodLogger.debug({ method: 'copy' })
auto = copyPkg
// We still choose hard linking that will fall back to copying in edge cases.
packageImportMethodLogger.debug({ method: 'hardlink' })
auto = hardlinkPkg.bind(null, linkOrCopy)
return auto(to, opts)
}
}

View File

@@ -71,7 +71,7 @@ test('packageImportMethod=auto: link files if cloning fails', async () => {
expect(fsMock.link).toBeCalledWith(path.join('hash2'), path.join('project2', '_tmp', 'index.js'))
})
test('packageImportMethod=auto: link files if cloning fails and even hard linking fails but with an EINVAL error', async () => {
test('packageImportMethod=auto: link files if cloning fails and even hard linking fails but not with EXDEV error', async () => {
const importPackage = createImportPackage('auto')
fsMock.copyFile = jest.fn(() => {
throw new Error('This file system does not support cloning')
@@ -80,9 +80,7 @@ test('packageImportMethod=auto: link files if cloning fails and even hard linkin
fsMock.link = jest.fn(() => {
if (linkFirstCall) {
linkFirstCall = false
const err = new Error('')
err['code'] = 'EINVAL'
throw err
throw new Error()
}
})
fsMock.rename = jest.fn()