diff --git a/lib/normalize.js b/lib/normalize.js index 682d234..3adec01 100644 --- a/lib/normalize.js +++ b/lib/normalize.js @@ -127,13 +127,9 @@ function unixifyPath (ref) { return ref.replace(/\\|:/g, '/') } -function securePath (ref) { - const secured = path.join('.', path.join('/', unixifyPath(ref))) - return secured.startsWith('.') ? '' : secured -} - function secureAndUnixifyPath (ref) { - return unixifyPath(securePath(ref)) + const secured = unixifyPath(path.join('.', path.join('/', unixifyPath(ref)))) + return secured.startsWith('./') ? '' : secured } // We don't want the `changes` array in here by default because this is a hot @@ -376,7 +372,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // expand "directories.bin" if (steps.includes('binDir') && data.directories?.bin && !data.bin) { - const binsDir = path.resolve(pkg.path, securePath(data.directories.bin)) + const binsDir = path.resolve(pkg.path, secureAndUnixifyPath(data.directories.bin)) const bins = await lazyLoadGlob()('**', { cwd: binsDir }) data.bin = bins.reduce((acc, binFile) => { if (binFile && !binFile.startsWith('.')) { diff --git a/test/prepare.js b/test/prepare.js index c6d85fe..ec65320 100644 --- a/test/prepare.js +++ b/test/prepare.js @@ -156,6 +156,19 @@ for (const [name, testPrepare] of Object.entries(testMethods)) { t.strictSame(content.bin, { echo: 'bin/echo' }) }) + t.test('bin handles hidden folders', async t => { + const { content } = await testPrepare(t, ({ + 'package.json': JSON.stringify({ + name: 'bin-test', + bin: { + echo: '..\\..\\..\\.bin\\echo', + }, + }), + bin: { echo: '#!/bin/sh\n\necho "hello world"' }, + })) + t.strictSame(content.bin, { echo: '.bin/echo' }) + }) + t.test('directories.bin with bin', async t => { const { content } = await testPrepare(t, ({ 'package.json': JSON.stringify({ @@ -175,6 +188,25 @@ for (const [name, testPrepare] of Object.entries(testMethods)) { t.strictSame(content.bin, { echo: 'bin/echo' }) }) + t.test('directories.bin with hidden bin dir', async t => { + const { content } = await testPrepare(t, ({ + 'package.json': JSON.stringify({ + name: 'bin-test', + directories: { + bin: './.bin', + }, + bin: { + echo: './.bin/echo', + }, + }), + bin: { + echo: '#!/bin/sh\n\necho "hello world"', + echo2: '#!/bin/sh\n\necho "hello world2"', + }, + })) + t.strictSame(content.bin, { echo: '.bin/echo' }) + }) + t.end() }) @@ -189,6 +221,16 @@ for (const [name, testPrepare] of Object.entries(testMethods)) { t.strictSame(content.man, ['man/man1/test.1']) }) + t.test('resolves hidden directory', async t => { + const { content } = await testPrepare(t, ({ + 'package.json': JSON.stringify({ + directories: { man: './.man' }, + }), + '.man': { man1: { 'test.1': 'man test file' } }, + })) + t.strictSame(content.man, ['.man/man1/test.1']) + }) + if (name === '@npmcli/package-json') { t.test('non-string', async t => { const { content } = await testPrepare(t, ({