Skip to content

Commit

Permalink
adding lots of tests, clean up types
Browse files Browse the repository at this point in the history
Also, this fixes a but preventing `**/..` from working properly when
it's the last in the pattern.
  • Loading branch information
isaacs committed Feb 27, 2023
1 parent b12e6ba commit 5f21b46
Show file tree
Hide file tree
Showing 23 changed files with 723 additions and 151 deletions.
7 changes: 1 addition & 6 deletions changelog.md
Expand Up @@ -9,11 +9,6 @@ changes.
- Promise API instead of callbacks.
- Accept pattern as string or array of strings.
- Hybrid module distribution.

**Note:** `module.exports` in CommonJS mode is an object, not a
function. Use the exported `default` or `glob` members to
access the default function export in CommonJS modes.

- Full TypeScript support.
- Exported `Glob` class is no longer an event emitter.
- Exported `Glob` class has `walk()`, `walkSync()`, `stream()`,
Expand Down Expand Up @@ -69,7 +64,7 @@ changes.
or vice versa, may thus result in more or fewer matches than
expected. In general, it should only be used when the
filesystem is known to differ from the platform default.
- `realpath:true` no longer implies `absolute:true`. The
- `realpath:true` no longer implies `absolute:true`. The
relative path to the realpath will be emitted when `absolute`
is not set.

Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
@@ -1,7 +1,7 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "glob",
"description": "a little globber",
"description": "the most correct and second fastest glob implementation in JavaScript",
"version": "9.0.0-0",
"repository": {
"type": "git",
Expand All @@ -17,7 +17,7 @@
},
"require": {
"types": "./dist/cjs/index-cjs.d.ts",
"default": "./dist/cjs/index-cjs.js"
"default": "./dist/cjs/index.js"
}
}
},
Expand Down Expand Up @@ -59,7 +59,7 @@
},
"dependencies": {
"fs.realpath": "^1.0.0",
"minimatch": "^7.1.3",
"minimatch": "^7.1.4",
"minipass": "^4.2.1",
"path-scurry": "^1.4.0"
},
Expand Down
74 changes: 43 additions & 31 deletions src/glob.ts
Expand Up @@ -24,18 +24,26 @@ const defaultPlatform: NodeJS.Platform =
? process.platform
: 'linux'

export interface GlobOptions extends MinimatchOptions {
ignore?: string | string[] | Ignore
export interface GlobOptions {
absolute?: boolean
allowWindowsEscape?: boolean
cwd?: string
dot?: boolean
follow?: boolean
ignore?: string | string[] | Ignore
mark?: boolean
matchBase?: boolean
nobrace?: boolean
nocase?: boolean
nodir?: boolean
cwd?: string
noext?: boolean
noglobstar?: boolean
platform?: NodeJS.Platform
realpath?: boolean
absolute?: boolean
withFileTypes?: boolean
scurry?: PathScurry
platform?: NodeJS.Platform
signal?: AbortSignal
windowsPathsNoEscape?: boolean
withFileTypes?: boolean
}

export type GlobOptionsWithFileTypesTrue = GlobOptions & {
Expand All @@ -57,7 +65,7 @@ type Result<Opts> = Opts extends GlobOptionsWithFileTypesTrue
: Opts extends GlobOptionsWithFileTypesUnset
? string
: string | Path
type Results<Opts> = Result<Opts>[]
export type Results<Opts> = Result<Opts>[]

type FileTypes<Opts> = Opts extends GlobOptionsWithFileTypesTrue
? true
Expand All @@ -80,7 +88,6 @@ export class Glob<Opts extends GlobOptions> {
globSet: GlobSet
globParts: GlobParts
realpath: boolean
nonull: boolean
absolute: boolean
matchBase: boolean
windowsPathsNoEscape: boolean
Expand All @@ -95,6 +102,8 @@ export class Glob<Opts extends GlobOptions> {
platform: NodeJS.Platform
patterns: Pattern[]
signal?: AbortSignal
nobrace: boolean
noext: boolean

constructor(pattern: string | string[], opts: Opts) {
this.withFileTypes = !!opts.withFileTypes as FileTypes<Opts>
Expand All @@ -104,24 +113,16 @@ export class Glob<Opts extends GlobOptions> {
this.nodir = !!opts.nodir
this.mark = !!opts.mark
this.cwd = opts.cwd || ''
this.nobrace = !!opts.nobrace
this.noext = !!opts.noext
this.realpath = !!opts.realpath
this.nonull = !!opts.nonull
this.absolute = !!opts.absolute

this.noglobstar = !!opts.noglobstar
this.matchBase = !!opts.matchBase

// if we're returning Path objects, we can't do nonull, because
// the pattern is a string, not a Path
if (this.withFileTypes) {
if (this.nonull) {
throw new TypeError(
'cannot set nonull:true and withFileTypes:true'
)
}
if (this.absolute) {
throw new Error('cannot set absolute:true and withFileTypes:true')
}
if (this.withFileTypes && this.absolute) {
throw new Error('cannot set absolute:true and withFileTypes:true')
}

if (typeof pattern === 'string') {
Expand Down Expand Up @@ -149,6 +150,12 @@ export class Glob<Opts extends GlobOptions> {
this.opts = { ...opts, platform: this.platform }
if (opts.scurry) {
this.scurry = opts.scurry
if (
opts.nocase !== undefined &&
opts.nocase !== opts.scurry.nocase
) {
throw new Error('nocase option contradicts provided scurry option')
}
} else {
const Scurry =
opts.platform === 'win32'
Expand All @@ -170,13 +177,18 @@ export class Glob<Opts extends GlobOptions> {

const mmo: MinimatchOptions = {
// default nocase based on platform
nocase: this.nocase,
...opts,
nonegate: true,
nocomment: true,
dot: this.dot,
matchBase: this.matchBase,
nobrace: this.nobrace,
nocase: this.nocase,
nocaseMagicOnly: true,
nocomment: true,
noext: this.noext,
nonegate: true,
optimizationLevel: 2,
platform: this.platform,
windowsPathsNoEscape: this.windowsPathsNoEscape,
}

const mms = this.pattern.map(p => new Minimatch(p, mmo))
Expand Down Expand Up @@ -224,35 +236,35 @@ export class Glob<Opts extends GlobOptions> {
return [...matches]
}

stream(): Minipass<Result<Opts>>
stream(): Minipass<string | Path> {
stream(): Minipass<Result<Opts>, Result<Opts>>
stream(): Minipass<string | Path, string | Path> {
return new GlobStream(this.patterns, this.scurry.cwd, {
...this.opts,
platform: this.platform,
nocase: this.nocase,
}).stream()
}

streamSync(): Minipass<Result<Opts>>
streamSync(): Minipass<string | Path> {
streamSync(): Minipass<Result<Opts>, Result<Opts>>
streamSync(): Minipass<string | Path, string | Path> {
return new GlobStream(this.patterns, this.scurry.cwd, {
...this.opts,
platform: this.platform,
nocase: this.nocase,
}).streamSync()
}

iteratorSync(): Generator<Result<Opts>, void, void> {
iterateSync(): Generator<Result<Opts>, void, void> {
return this.streamSync()[Symbol.iterator]()
}
[Symbol.iterator]() {
return this.iteratorSync()
return this.iterateSync()
}

iterator(): AsyncGenerator<Result<Opts>, void, void> {
iterate(): AsyncGenerator<Result<Opts>, void, void> {
return this.stream()[Symbol.asyncIterator]()
}
[Symbol.asyncIterator]() {
return this.iterator()
return this.iterate()
}
}
21 changes: 13 additions & 8 deletions src/ignore.ts
Expand Up @@ -16,28 +16,33 @@ const defaultPlatform: NodeJS.Platform =
: 'linux'

export class Ignore {
platform: NodeJS.Platform
nocase: boolean
relative: Minimatch[]
relativeChildren: Minimatch[]
absolute: Minimatch[]
absoluteChildren: Minimatch[]

constructor(
ignored: string[],
{ platform = defaultPlatform, nocase }: GlobWalkerOpts
{
nobrace,
nocase,
noext,
noglobstar,
platform = defaultPlatform,
}: GlobWalkerOpts
) {
this.platform = platform
this.nocase = !!nocase
this.relative = []
this.absolute = []
this.relativeChildren = []
this.absoluteChildren = []
const mmopts = {
platform: this.platform,
optimizationLevel: 2,
dot: true,
nobrace,
nocase,
noext,
noglobstar,
optimizationLevel: 2,
platform,
}

// this is a little weird, but it gives us a clean set of optimized
Expand All @@ -57,7 +62,7 @@ export class Ignore {
for (let i = 0; i < mm.set.length; i++) {
const parsed = mm.set[i]
const globParts = mm.globParts[i]
const p = new Pattern(parsed, globParts, 0, this.platform)
const p = new Pattern(parsed, globParts, 0, platform)
const m = new Minimatch(p.globString(), mmopts)
const children = globParts[globParts.length - 1] === '**'
const absolute = p.isAbsolute()
Expand Down

0 comments on commit 5f21b46

Please sign in to comment.