diff --git a/README.md b/README.md index 22e501a2..20811ff3 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,13 @@ Return only files. Return only directories. +#### followSymlinkedDirectories + + * Type: `boolean` + * Default: `true` + +Follow symlinked directories when expanding `**` patterns. + #### transform * Type: `Function` @@ -214,7 +221,7 @@ Not fully, because `fast-glob` not implements all options of `node-glob`. See ta | `matchBase` | – | | `nodir` | [`onlyFiles`](https://github.com/mrmlnc/fast-glob#onlyfiles) | | `ignore` | [`ignore`](https://github.com/mrmlnc/fast-glob#ignore) | -| `follow` | by default | +| `follow` | [`followSymlinkedDirectories`](https://github.com/mrmlnc/fast-glob#followsymlinkeddirectories) | | `realpath` | – | | `absolute` | – | diff --git a/src/managers/options.spec.ts b/src/managers/options.spec.ts index fcad4fed..5df8c028 100644 --- a/src/managers/options.spec.ts +++ b/src/managers/options.spec.ts @@ -13,6 +13,7 @@ describe('Managers → Options', () => { stats: false, onlyFiles: true, onlyDirectories: false, + followSymlinkedDirectories: true, transform: null }; @@ -30,6 +31,7 @@ describe('Managers → Options', () => { stats: true, onlyFiles: true, onlyDirectories: false, + followSymlinkedDirectories: true, transform: null }; diff --git a/src/managers/options.ts b/src/managers/options.ts index ac01c79b..80f9df9b 100644 --- a/src/managers/options.ts +++ b/src/managers/options.ts @@ -34,6 +34,10 @@ export interface IOptions { * Return only directories. */ onlyDirectories: boolean; + /** + * Follow symlinked directories when expanding `**` patterns. + */ + followSymlinkedDirectories: boolean; /** * Allows you to transform a path or `fs.Stats` object before sending to the array. */ @@ -51,6 +55,7 @@ export function prepare(options?: IPartialOptions): IOptions { stats: false, onlyFiles: true, onlyDirectories: false, + followSymlinkedDirectories: true, transform: null }, options); } diff --git a/src/providers/reader.spec.ts b/src/providers/reader.spec.ts index add535e7..62e2b7dd 100644 --- a/src/providers/reader.spec.ts +++ b/src/providers/reader.spec.ts @@ -304,6 +304,26 @@ describe('Providers → Reader', () => { assert.ok(!actual); }); + it('should returns true for symlinked directory when the «followSymlinkedDirectories» option is enabled', () => { + const reader = getReader(); + + const entry = getDirectoryEntry(false /** dot */, true /** isSymbolicLink */); + + const actual = reader.deep(entry, []); + + assert.ok(actual); + }); + + it('should returns false for symlinked directory when the «followSymlinkedDirectories» option is disabled', () => { + const reader = getReader({ followSymlinkedDirectories: false }); + + const entry = getDirectoryEntry(false /** dot */, true /** isSymbolicLink */); + + const actual = reader.deep(entry, []); + + assert.ok(!actual); + }); + it('should returns false if specified a limit of depth for «deep» option ', () => { const reader = getReader({ deep: 2 }); diff --git a/src/providers/reader.ts b/src/providers/reader.ts index fa00a714..bc599a9d 100644 --- a/src/providers/reader.ts +++ b/src/providers/reader.ts @@ -70,6 +70,11 @@ export default abstract class Reader { } } + // Skip reading if the directory is symlink and we don't want expand symlinks + if (this.filterBySymlinkType(entry)) { + return false; + } + // Skip reading if the directory name starting with a period and is not expected if (!this.options.dot && this.isDotDirectory(entry)) { return false; @@ -108,4 +113,11 @@ export default abstract class Reader { private filterByDirectoryType(entry: IEntry): boolean { return this.options.onlyDirectories && !entry.isDirectory(); } + + /** + * Returns true for symlinked directories if the «followSymlinks» option is enabled. + */ + private filterBySymlinkType(entry: IEntry): boolean { + return !this.options.followSymlinkedDirectories && entry.isSymbolicLink(); + } }