Skip to content

Commit

Permalink
add windowsPathsNoEscape option
Browse files Browse the repository at this point in the history
Fix: #468
  • Loading branch information
isaacs committed May 16, 2022
1 parent d844b2c commit a51ce0f
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,26 @@ parallel glob operations will be sped up by sharing information about
the filesystem.

* `cwd` The current working directory in which to search. Defaults
to `process.cwd()`.
to `process.cwd()`. This option is always coerced to use
forward-slashes as a path separator, because it is not tested
as a glob pattern, so there is no need to escape anything.
* `root` The place where patterns starting with `/` will be mounted
onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix
systems, and `C:\` or some such on Windows.)
systems, and `C:\` or some such on Windows.) This option is
always coerced to use forward-slashes as a path separator,
because it is not tested as a glob pattern, so there is no need
to escape anything.
* `windowsPathsNoEscape` Use `\\` as a path separator _only_, and
_never_ as an escape character. If set, all `\\` characters
are replaced with `/` in the pattern. Note that this makes it
**impossible** to match against paths containing literal glob
pattern characters, but allows matching with patterns constructed
using `path.join()` and `path.resolve()` on Windows platforms,
mimicking the (buggy!) behavior of Glob v7 and before on
Windows. Please use with caution, and be mindful of [the caveat
below about Windows paths](#windows). (For legacy reasons,
this is also set if `allowWindowsEscape` is set to the exact
value `false`.)
* `dot` Include `.dot` files in normal matches and `globstar` matches.
Note that an explicit dot in a portion of the pattern will always
match dot files.
Expand Down Expand Up @@ -332,6 +348,11 @@ Results from absolute patterns such as `/foo/*` are mounted onto the
root setting using `path.join`. On windows, this will by default result
in `/foo/*` matching `C:\foo\bar.txt`.

To automatically coerce all `\` characters to `/` in pattern
strings, **thus making it impossible to escape literal glob
characters**, you may set the `windowsPathsNoEscape` option to
`true`.

## Race Conditions

Glob searching, by its very nature, is susceptible to race conditions,
Expand Down
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 8.1

- Add `windowsPathsNoEscape` option

## 8.0

- Only support node v12 and higher
Expand Down
8 changes: 6 additions & 2 deletions common.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ function setopts (self, pattern, options) {
pattern = "**/" + pattern
}

self.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
options.allowWindowsEscape === false
if (self.windowsPathsNoEscape) {
pattern = pattern.replace(/\\/g, '/')
}

self.silent = !!options.silent
self.pattern = pattern
self.strict = options.strict !== false
Expand Down Expand Up @@ -112,8 +118,6 @@ function setopts (self, pattern, options) {
// Note that they are not supported in Glob itself anyway.
options.nonegate = true
options.nocomment = true
// always treat \ in patterns as escapes, not path separators
options.allowWindowsEscape = true

self.minimatch = new Minimatch(pattern, options)
self.options = self.minimatch.options
Expand Down
45 changes: 45 additions & 0 deletions test/windows-paths-no-escape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const t = require('tap')
const g = require('../')

const platforms = ['win32', 'posix']
const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform')
for (const p of platforms) {
t.test(p, t => {
Object.defineProperty(process, 'platform', {
value: p,
enumerable: true,
configurable: true,
writable: true,
})
t.equal(process.platform, p, 'gut check: actually set platform')
const pattern = '/a/b/c/x\\[a-b\\]y\\*'
const def = new g.Glob(pattern, { noprocess: true })
const winpath = new g.Glob(pattern, {
windowsPathsNoEscape: true,
noprocess: true,
})
const winpathLegacy = new g.Glob(pattern, {
allowWindowsEscape: false,
noprocess: true,
})
const nowinpath = new g.Glob(pattern, {
windowsPathsNoEscape: false,
noprocess: true,
})

t.strictSame([
def.pattern,
nowinpath.pattern,
winpath.pattern,
winpathLegacy.pattern,
], [
'/a/b/c/x\\[a-b\\]y\\*',
'/a/b/c/x\\[a-b\\]y\\*',
'/a/b/c/x/[a-b/]y/*',
'/a/b/c/x/[a-b/]y/*',
])
t.end()
})
}

Object.defineProperty(process, 'platform', originalPlatform)

0 comments on commit a51ce0f

Please sign in to comment.