Skip to content

Commit

Permalink
Add dotRelative option
Browse files Browse the repository at this point in the history
Fix: #495
  • Loading branch information
isaacs committed Feb 28, 2023
1 parent bedc98c commit b119426
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 2 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ share the previously loaded cache.

- `cwd` String path or `file://` string or URL object. The
current working directory in which to search. Defaults to
`process.cwd()`. See also: "Windows, CWDs, Drive Letters, and
`process.cwd()`. See also: "Windows, CWDs, Drive Letters, and
UNC Paths", below.

This option may be eiher a string path or a `file://` URL
Expand All @@ -223,6 +223,16 @@ share the previously loaded cache.
matches. Note that an explicit dot in a portion of the pattern
will always match dot files.

- `dotRelative` Prepend all relative path strings with `./` (or
`.\` on Windows).

Without this option, returned relative paths are "bare", so
instead of returning `'./foo/bar'`, they are returned as
`'foo/bar'`.

Relative patterns starting with `'../'` are not prepended with
`./`, even if this option is set.

- `mark` Add a `/` character to directory matches. Note that this
requires additional stat calls.

Expand Down
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 9.1

- Add `dotRelative` option

## 9.0

This is a full rewrite, with significant API and algorithm
Expand Down
13 changes: 13 additions & 0 deletions src/glob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ export interface GlobOptions {
* will always match dot files.
*/
dot?: boolean

/**
* Prepend all relative path strings with `./` (or `.\` on Windows).
*
* Without this option, returned relative paths are "bare", so instead of
* returning `'./foo/bar'`, they are returned as `'foo/bar'`.
*
* Relative patterns starting with `'../'` are not prepended with `./`, even
* if this option is set.
*/
dotRelative?: boolean
/**
* Follow symlinked directories when expanding `**`
* patterns. This can result in a lot of duplicate references in
Expand Down Expand Up @@ -215,6 +226,7 @@ export class Glob<Opts extends GlobOptions> implements GlobOptions {
absolute: boolean
cwd: string
dot: boolean
dotRelative: boolean
follow: boolean
ignore?: Ignore
mark: boolean
Expand Down Expand Up @@ -259,6 +271,7 @@ export class Glob<Opts extends GlobOptions> implements GlobOptions {
this.signal = opts.signal
this.follow = !!opts.follow
this.dot = !!opts.dot
this.dotRelative = !!opts.dotRelative
this.nodir = !!opts.nodir
this.mark = !!opts.mark
if (!opts.cwd) {
Expand Down
5 changes: 4 additions & 1 deletion src/walker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface GlobWalkerOpts {
allowWindowsEscape?: boolean
cwd?: string | URL
dot?: boolean
dotRelative?: boolean
follow?: boolean
ignore?: string | string[] | Ignore
mark?: boolean
Expand Down Expand Up @@ -197,7 +198,9 @@ export abstract class GlobUtil<O extends GlobWalkerOpts = GlobWalkerOpts> {
this.matchEmit(e.fullpath() + mark)
} else {
const rel = e.relative()
this.matchEmit(!rel && mark ? './' : rel + mark)
const pre = this.opts.dotRelative && !rel.startsWith('..' + this.#sep)
? '.' + this.#sep : ''
this.matchEmit(!rel && mark ? '.' + mark : pre + rel + mark)
}
}

Expand Down
75 changes: 75 additions & 0 deletions test/dot-relative.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import t from 'tap'
import { Glob } from '../'
import { bashResults } from './bash-results'
import {resolve, sep} from 'path'

const pattern = 'a/b/**'
process.chdir(__dirname + '/fixtures')

const marks = [true, false]
for (const mark of marks) {
t.test('mark=' + mark, t => {
t.plan(3)

t.test('Emits relative matches prefixed with ./', async t => {
const g = new Glob(pattern, { dotRelative: true })
const results = await g.walk()

t.equal(
results.length,
bashResults[pattern].length,
'must match all files'
)
for (const m of results) {
t.ok(m.startsWith('.' + sep))
}
})

t.test('returns ./ prefixed matches synchronously', async t => {
const g = new Glob(pattern, { dotRelative: true })
const results = g.walkSync()

t.equal(
results.length,
bashResults[pattern].length,
'must match all files'
)
for (const m of results) {
t.ok(m.startsWith('.' + sep))
}
})

t.test('does not prefix with ./ unless dotRelative is true', async t => {
const g = new Glob(pattern, {})
const results = await g.walk()

t.equal(
results.length,
bashResults[pattern].length,
'must match all files'
)
for (const m of results) {
t.ok(mark && m === '.' + sep || !m.startsWith('.' + sep))
}
})
})
}

t.test('does not add ./ for patterns starting in ../', async t => {
t.plan(2)
const pattern = '../a/b/**'
const cwd = resolve(__dirname, 'fixtures/a')
t.test('async', async t => {
const g = new Glob(pattern, { dotRelative: true, cwd })
for await (const m of g) {
t.ok(!m.startsWith('.' + sep + '..' + sep))
}
})
t.test('sync', t => {
const g = new Glob(pattern, { dotRelative: true, cwd })
for (const m of g) {
t.ok(!m.startsWith('.' + sep + '..' + sep))
}
t.end()
})
})

0 comments on commit b119426

Please sign in to comment.