From 61cc5a21d3383a36e0c738f3ca183ddc69bee47e Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 30 Aug 2023 14:32:19 -0700 Subject: [PATCH] join string pattern sections properly Fix: https://github.com/isaacs/node-glob/issues/547 --- benchmark.sh | 1 + patterns.sh | 2 ++ src/bin.ts | 5 ++++- src/processor.ts | 13 ++++--------- test/bin.ts | 14 ++++++++++---- test/progra-tilde.ts | 24 ++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 test/progra-tilde.ts diff --git a/benchmark.sh b/benchmark.sh index 3bde5228..3f8ded82 100644 --- a/benchmark.sh +++ b/benchmark.sh @@ -41,6 +41,7 @@ t () { # warm up the fs cache so we don't get a spurious slow first result bash -c 'for i in **; do :; done' +cd "$wd/bench-working-dir/fixture" for p in "${patterns[@]}"; do echo diff --git a/patterns.sh b/patterns.sh index 6dfb492e..12f2d907 100644 --- a/patterns.sh +++ b/patterns.sh @@ -1,4 +1,6 @@ patterns=( + '{0000,0,1111,1}/{0000,0,1111,1}/{0000,0,1111,1}/**' + '**' '**/..' diff --git a/src/bin.ts b/src/bin.ts index 1413c383..64230507 100755 --- a/src/bin.ts +++ b/src/bin.ts @@ -2,6 +2,7 @@ import { foregroundChild } from 'foreground-child' import { existsSync } from 'fs' import { jack } from 'jackspeak' +import { join } from 'path' import { version } from '../package.json' import { globStream } from './index.js' @@ -234,7 +235,9 @@ try { const patterns = values.all ? positionals : positionals.filter(p => !existsSync(p)) - const matches = values.all ? [] : positionals.filter(p => existsSync(p)) + const matches = values.all + ? [] + : positionals.filter(p => existsSync(p)).map(p => join(p)) const stream = globStream(patterns, { absolute: values.absolute, cwd: values.cwd, diff --git a/src/processor.ts b/src/processor.ts index b0949ceb..4d2c18ea 100644 --- a/src/processor.ts +++ b/src/processor.ts @@ -146,8 +146,6 @@ export class Processor { (rest = pattern.rest()) ) { const c = t.resolve(p) - // we can be reasonably sure that .. is a readable dir - if (c.isUnknown() && p !== '..') break t = c pattern = rest changed = true @@ -163,13 +161,10 @@ export class Processor { // more strings for an unknown entry, // or a pattern starting with magic, mounted on t. if (typeof p === 'string') { - // must be final entry - if (!rest) { - const ifDir = p === '..' || p === '' || p === '.' - this.matches.add(t.resolve(p), absolute, ifDir) - } else { - this.subwalks.add(t, pattern) - } + // must not be final entry, otherwise we would have + // concatenated it earlier. + const ifDir = p === '..' || p === '' || p === '.' + this.matches.add(t.resolve(p), absolute, ifDir) continue } else if (p === GLOBSTAR) { // if no rest, match and subwalk pattern diff --git a/test/bin.ts b/test/bin.ts index 0828d5f6..cbaff44b 100644 --- a/test/bin.ts +++ b/test/bin.ts @@ -1,6 +1,6 @@ import { spawn, SpawnOptions } from 'child_process' -import t from 'tap' import { sep } from 'path' +import t from 'tap' import { version } from '../package.json' const bin = require.resolve('../dist/cjs/src/bin.js') @@ -66,8 +66,14 @@ t.test('finds matches for a pattern', async t => { const c = `node -p "process.argv.map(s=>s.toUpperCase())"` const cmd = await run(['**/*.y', '-c', c], { cwd }) - t.match(cmd.stdout, `'a${sep}x.y'`.toUpperCase()) - t.match(cmd.stdout, `'a${sep}b${sep}z.y'`.toUpperCase()) + t.match(cmd.stdout, `'a${sep.replace(/\\/g, '\\\\')}x.y'`.toUpperCase()) + t.match( + cmd.stdout, + `'a${sep.replace(/\\/g, '\\\\')}b${sep.replace( + /\\/g, + '\\\\' + )}z.y'`.toUpperCase() + ) }) t.test('prioritizes exact match if exists, unless --all', async t => { @@ -76,7 +82,7 @@ t.test('prioritizes exact match if exists, unless --all', async t => { '[id].tsx': '', 'i.tsx': '', 'd.tsx': '', - } + }, }) const res = await run(['routes/[id].tsx'], { cwd }) t.equal(res.stdout, `routes${sep}[id].tsx\n`) diff --git a/test/progra-tilde.ts b/test/progra-tilde.ts new file mode 100644 index 00000000..b15ea0ae --- /dev/null +++ b/test/progra-tilde.ts @@ -0,0 +1,24 @@ +// https://github.com/isaacs/node-glob/issues/547 +import t from 'tap' + +import { globSync } from '../dist/cjs/src/index.js' + +if (process.platform !== 'win32') { + t.pass('no need to test this except on windows') + process.exit(0) +} + +const dir = t.testdir({ + 'program files': { + a: '', + b: '', + c: '', + }, +}) + +t.strictSame( + globSync('progra~1\\*', { cwd: dir, windowsPathsNoEscape: true }).sort( + (a, b) => a.localeCompare(b, 'en') + ), + ['a', 'b', 'c'] +)