From 559b9adea7f07e0056c5baaa70cdb3d4995b8277 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sun, 26 Feb 2023 01:13:00 -0800 Subject: [PATCH 1/2] add windowsNoMagicRoot --- README.md | 10 + changelog.md | 4 + src/index.ts | 27 ++- .../test/windows-no-magic-root.ts.test.cjs | 210 ++++++++++++++++++ test/windows-no-magic-root.ts | 31 +++ 5 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 tap-snapshots/test/windows-no-magic-root.ts.test.cjs create mode 100644 test/windows-no-magic-root.ts diff --git a/README.md b/README.md index 1a8173cb..184ceac4 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,16 @@ paths](#windows). For legacy reasons, this is also set if `options.allowWindowsEscape` is set to the exact value `false`. +### windowsNoMagicRoot + +When a pattern starts with a UNC path or drive letter, and in +`nocase:true` mode, do not convert the root portions of the +pattern into a case-insensitive regular expression, and instead +leave them as strings. + +This is the default when the platform is `win32` and +`nocase:true` is set. + ### preserveMultipleSlashes By default, multiple `/` characters (other than the leading `//` diff --git a/changelog.md b/changelog.md index b9f00ffa..b7048bc2 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # change log +## 7.2 + +- Add `windowsNoMagicRoot` option + ## 7.1 - Add `optimizationLevel` configuration option, and revert the diff --git a/src/index.ts b/src/index.ts index 5492d837..b14c22c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,7 @@ export interface MinimatchOptions { preserveMultipleSlashes?: boolean optimizationLevel?: number platform?: typeof process.platform + windowsNoMagicRoot?: boolean } export const minimatch = ( @@ -272,6 +273,7 @@ minimatch.match = match // replace stuff like \* with * const globUnescape = (s: string) => s.replace(/\\(.)/g, '$1') +const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/ const charUnescape = (s: string) => s.replace(/\\([^-\]])/g, '$1') const regExpEscape = (s: string) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') @@ -311,9 +313,11 @@ export class Minimatch { partial: boolean globSet: string[] globParts: string[][] + nocase: boolean isWindows: boolean platform: typeof process.platform + windowsNoMagicRoot: boolean regexp: false | null | MMRegExp constructor(pattern: string, options: MinimatchOptions = {}) { @@ -336,6 +340,11 @@ export class Minimatch { this.comment = false this.empty = false this.partial = !!options.partial + this.nocase = !!this.options.nocase + this.windowsNoMagicRoot = + options.windowsNoMagicRoot !== undefined + ? options.windowsNoMagicRoot + : !!(this.isWindows && this.nocase) this.globSet = [] this.globParts = [] @@ -388,7 +397,23 @@ export class Minimatch { this.debug(this.pattern, this.globParts) // glob --> regexps - let set = this.globParts.map((s, _, __) => s.map(ss => this.parse(ss))) + let set = this.globParts.map((s, _, __) => { + if (this.isWindows && this.windowsNoMagicRoot) { + // check if it's a drive or unc path. + const isUNC = + s[0] === '' && + s[1] === '' && + (s[2] === '?' || !globMagic.test(s[2])) && + !globMagic.test(s[3]) + const isDrive = /^[a-z]:/i.test(s[0]) + if (isUNC) { + return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))] + } else if (isDrive) { + return [s[0], ...s.slice(1).map(ss => this.parse(ss))] + } + } + return s.map(ss => this.parse(ss)) + }) this.debug(this.pattern, set) diff --git a/tap-snapshots/test/windows-no-magic-root.ts.test.cjs b/tap-snapshots/test/windows-no-magic-root.ts.test.cjs new file mode 100644 index 00000000..fd2a829d --- /dev/null +++ b/tap-snapshots/test/windows-no-magic-root.ts.test.cjs @@ -0,0 +1,210 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d: > default to true 1`] = ` +Array [ + Array [ + "", + "", + "?", + "d:", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d: > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^(?!\\.)(?=.)[^/]$/i, + /^d:$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d:/ > default to true 1`] = ` +Array [ + Array [ + "", + "", + "?", + "d:", + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d:/ > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^(?!\\.)(?=.)[^/]$/i, + /^d:$/i, + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d:/x/y/z > default to true 1`] = ` +Array [ + Array [ + "", + "", + "?", + "d:", + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //?/d:/x/y/z > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^(?!\\.)(?=.)[^/]$/i, + /^d:$/i, + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share > default to true 1`] = ` +Array [ + Array [ + "", + "", + "host", + "share", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^host$/i, + /^share$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share/ > default to true 1`] = ` +Array [ + Array [ + "", + "", + "host", + "share", + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share/ > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^host$/i, + /^share$/i, + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share/x/y/z > default to true 1`] = ` +Array [ + Array [ + "", + "", + "host", + "share", + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root //host/share/x/y/z > set explicitly false 1`] = ` +Array [ + Array [ + "", + "", + /^host$/i, + /^share$/i, + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d: > default to true 1`] = ` +Array [ + Array [ + "d:", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d: > set explicitly false 1`] = ` +Array [ + Array [ + /^d:$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d:/ > default to true 1`] = ` +Array [ + Array [ + "d:", + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d:/ > set explicitly false 1`] = ` +Array [ + Array [ + /^d:$/i, + "", + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d:/x/y/z > default to true 1`] = ` +Array [ + Array [ + "d:", + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` + +exports[`test/windows-no-magic-root.ts TAP no magic the root d:/x/y/z > set explicitly false 1`] = ` +Array [ + Array [ + /^d:$/i, + /^x$/i, + /^y$/i, + /^z$/i, + ], +] +` diff --git a/test/windows-no-magic-root.ts b/test/windows-no-magic-root.ts new file mode 100644 index 00000000..3d4a62d3 --- /dev/null +++ b/test/windows-no-magic-root.ts @@ -0,0 +1,31 @@ +import {Minimatch} from '../' +import t from 'tap' + +t.test('no magic the root', t => { + const patterns = [ + '//host/share/x/y/z', + '//host/share/', + '//host/share', + '//?/d:/x/y/z', + '//?/d:/', + '//?/d:', + 'd:/x/y/z', + 'd:/', + 'd:', + ] + t.plan(patterns.length) + for (const p of patterns) { + t.test(p, t => { + t.matchSnapshot(new Minimatch(p, { + platform: 'win32', + nocase: true, + }).set, 'default to true') + t.matchSnapshot(new Minimatch(p, { + windowsNoMagicRoot: false, + platform: 'win32', + nocase: true, + }).set, 'set explicitly false') + t.end() + }) + } +}) From be2394fd50c4c44bb82b2123bf362c2787ed7cf2 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sun, 26 Feb 2023 01:13:27 -0800 Subject: [PATCH 2/2] 7.2.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f47e361..7ed102f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "minimatch", - "version": "7.1.4", + "version": "7.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "minimatch", - "version": "7.1.4", + "version": "7.2.0", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" diff --git a/package.json b/package.json index ceca1d24..71d14b6d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Isaac Z. Schlueter (http://blog.izs.me)", "name": "minimatch", "description": "a glob matcher in javascript", - "version": "7.1.4", + "version": "7.2.0", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git"