diff --git a/fs/expand_glob_test.ts b/fs/expand_glob_test.ts index 61d1993fd6e8..4a2970ffcb44 100644 --- a/fs/expand_glob_test.ts +++ b/fs/expand_glob_test.ts @@ -51,6 +51,7 @@ Deno.test("expandGlobWildcard", async function () { "abc", "abcdef", "abcdefghi", + "link", "subdir", ]); }); @@ -70,6 +71,7 @@ Deno.test("expandGlobParent", async function () { "abc", "abcdef", "abcdefghi", + "link", "subdir", ]); }); @@ -118,6 +120,7 @@ Deno.test("expandGlobGlobstarFalseWithGlob", async function () { "abc", "abcdef", "abcdefghi", + "link", "subdir", ]); }); diff --git a/fs/walk.ts b/fs/walk.ts index 05323f63b69c..9153c29ea036 100644 --- a/fs/walk.ts +++ b/fs/walk.ts @@ -55,6 +55,8 @@ export interface WalkOptions { includeFiles?: boolean; /** @default {true} */ includeDirs?: boolean; + /** @default {true} */ + includeSymlinks?: boolean; /** @default {false} */ followSymlinks?: boolean; exts?: string[]; @@ -84,6 +86,7 @@ export async function* walk( maxDepth = Infinity, includeFiles = true, includeDirs = true, + includeSymlinks = true, followSymlinks = false, exts = undefined, match = undefined, @@ -108,7 +111,12 @@ export async function* walk( let { isSymlink, isDirectory } = entry; if (isSymlink) { - if (!followSymlinks) continue; + if (!followSymlinks) { + if (includeSymlinks && include(path, exts, match, skip)) { + yield { path, ...entry }; + } + continue; + } path = await Deno.realPath(path); // Caveat emptor: don't assume |path| is not a symlink. realpath() // resolves symlinks but another process can replace the file system @@ -121,6 +129,7 @@ export async function* walk( maxDepth: maxDepth - 1, includeFiles, includeDirs, + includeSymlinks, followSymlinks, exts, match, @@ -142,6 +151,7 @@ export function* walkSync( maxDepth = Infinity, includeFiles = true, includeDirs = true, + includeSymlinks = true, followSymlinks = false, exts = undefined, match = undefined, @@ -171,7 +181,12 @@ export function* walkSync( let { isSymlink, isDirectory } = entry; if (isSymlink) { - if (!followSymlinks) continue; + if (!followSymlinks) { + if (includeSymlinks && include(path, exts, match, skip)) { + yield { path, ...entry }; + } + continue; + } path = Deno.realPathSync(path); // Caveat emptor: don't assume |path| is not a symlink. realpath() // resolves symlinks but another process can replace the file system @@ -184,6 +199,7 @@ export function* walkSync( maxDepth: maxDepth - 1, includeFiles, includeDirs, + includeSymlinks, followSymlinks, exts, match, diff --git a/fs/walk_test.ts b/fs/walk_test.ts index a37b5e190afc..a82768cad20c 100644 --- a/fs/walk_test.ts +++ b/fs/walk_test.ts @@ -78,6 +78,12 @@ Deno.test("[fs/walk] symlink", async () => followSymlinks: true, })); +Deno.test("[fs/walk] symlink without followSymlink", async () => { + await assertWalkPaths("symlink", [".", "x", "y"], { + followSymlinks: false, + }); +}); + Deno.test("[fs/walk] non-existent root", async () => { const root = resolve(testdataDir, "non_existent"); await assertRejects(