Skip to content

Commit

Permalink
feat: ignore EACCES on linking
Browse files Browse the repository at this point in the history
  • Loading branch information
antongolub authored and reggi committed May 24, 2024
1 parent af7e347 commit 9648a7d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
16 changes: 11 additions & 5 deletions lib/link-gently.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@

const { resolve, dirname } = require('path')
const { lstat, mkdir, readlink, rm, symlink } = require('fs/promises')
const throwNonEnoent = er => {
if (er.code !== 'ENOENT') {
throw er
const { log } = require('proc-log')
const throwSignificant = er => {
if (er.code === 'ENOENT') {
return
}
if (er.code === 'EACCES') {
log.warn('error adding file', er.message)
return
}
throw er
}

const rmOpts = {
Expand Down Expand Up @@ -37,8 +43,8 @@ const linkGently = async ({ path, to, from, absFrom, force }) => {
// or at least a warning, but npm has always behaved this
// way in the past, so it'd be a breaking change
return Promise.all([
lstat(absFrom).catch(throwNonEnoent),
lstat(to).catch(throwNonEnoent),
lstat(absFrom).catch(throwSignificant),
lstat(to).catch(throwSignificant),
]).then(([stFrom, stTo]) => {
// not present in package, skip it
if (!stFrom) {
Expand Down
43 changes: 43 additions & 0 deletions test/link-gently.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const t = require('tap')
const linkGently = require('../lib/link-gently.js')
const fs = require('fs')
const fsp = require('fs/promises')
const requireInject = require('require-inject')

t.test('make links gently', async t => {
Expand Down Expand Up @@ -87,6 +88,48 @@ t.test('make links gently', async t => {
linkGently.resetSeen()
})

t.test('handles link errors', async t => {
const dir = t.testdir({
pkg: {
'hello.js': `#!/usr/bin/env node\nconsole.log('hello')`,
},
})
const fspMock = {
...fsp,
lstat: (ref) => {
const code = (/\/(e\w+)$/.exec(ref) || [])[1]
if (code) {
return Promise.reject(Object.assign(new Error(), { code: code.toUpperCase() }))
}

return fsp.lstat(ref)
},
}
const mockedLinkGently = requireInject('../lib/link-gently.js', {
'fs/promises': fspMock,
})
await mockedLinkGently({
path: `${dir}/pkg`,
to: `${dir}/bin/eacces`,
from: `../pkg/hello.js`,
absFrom: `${dir}/pkg/hello.js`,
})

await mockedLinkGently({
path: `${dir}/pkg`,
to: `${dir}/bin/enoent`,
from: `../pkg/hello.js`,
absFrom: `${dir}/pkg/hello.js`,
})

await t.rejects(mockedLinkGently({
path: `${dir}/pkg`,
to: `${dir}/bin/eperm`,
from: `../pkg/hello.js`,
absFrom: `${dir}/pkg/hello.js`,
}), { code: 'EPERM' })
})

t.test('racey race', async t => {
const fsMock = {
...fs,
Expand Down

0 comments on commit 9648a7d

Please sign in to comment.