mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
feat(fs): introduce canonicalize
option to WalkOptions
(#3679)
This commit is contained in:
parent
65125db61f
commit
a62c90853a
@ -19,6 +19,12 @@ export interface ExpandGlobOptions extends Omit<GlobOptions, "os"> {
|
||||
exclude?: string[];
|
||||
includeDirs?: boolean;
|
||||
followSymlinks?: boolean;
|
||||
/**
|
||||
* Indicates whether the followed symlink's path should be canonicalized.
|
||||
* This option works only if `followSymlinks` is not `false`.
|
||||
* @default {true}
|
||||
*/
|
||||
canonicalize?: boolean;
|
||||
}
|
||||
|
||||
interface SplitPath {
|
||||
@ -80,6 +86,7 @@ export async function* expandGlob(
|
||||
globstar = true,
|
||||
caseInsensitive,
|
||||
followSymlinks,
|
||||
canonicalize,
|
||||
}: ExpandGlobOptions = {},
|
||||
): AsyncIterableIterator<WalkEntry> {
|
||||
const globOptions: GlobOptions = { extended, globstar, caseInsensitive };
|
||||
@ -134,6 +141,7 @@ export async function* expandGlob(
|
||||
skip: excludePatterns,
|
||||
maxDepth: globstar ? Infinity : 1,
|
||||
followSymlinks,
|
||||
canonicalize,
|
||||
});
|
||||
}
|
||||
const globPattern = globToRegExp(globSegment, globOptions);
|
||||
@ -202,6 +210,7 @@ export function* expandGlobSync(
|
||||
globstar = true,
|
||||
caseInsensitive,
|
||||
followSymlinks,
|
||||
canonicalize,
|
||||
}: ExpandGlobOptions = {},
|
||||
): IterableIterator<WalkEntry> {
|
||||
const globOptions: GlobOptions = { extended, globstar, caseInsensitive };
|
||||
@ -256,6 +265,7 @@ export function* expandGlobSync(
|
||||
skip: excludePatterns,
|
||||
maxDepth: globstar ? Infinity : 1,
|
||||
followSymlinks,
|
||||
canonicalize,
|
||||
});
|
||||
}
|
||||
const globPattern = globToRegExp(globSegment, globOptions);
|
||||
|
@ -156,3 +156,28 @@ Deno.test("expandGlobFollowSymlink", async function () {
|
||||
};
|
||||
assertEquals(await expandGlobArray("*", options), ["abc"]);
|
||||
});
|
||||
|
||||
Deno.test("expandGlobFollowSymlink with canonicalize", async function () {
|
||||
const options = {
|
||||
...EG_OPTIONS,
|
||||
root: join(EG_OPTIONS.root!, "."),
|
||||
followSymlinks: true,
|
||||
};
|
||||
assertEquals(
|
||||
await expandGlobArray("**/abc", options),
|
||||
["abc", join("subdir", "abc")],
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("expandGlobFollowSymlink without canonicalize", async function () {
|
||||
const options = {
|
||||
...EG_OPTIONS,
|
||||
root: join(EG_OPTIONS.root!, "."),
|
||||
followSymlinks: true,
|
||||
canonicalize: false,
|
||||
};
|
||||
assertEquals(
|
||||
await expandGlobArray("**/abc", options),
|
||||
["abc", join("link", "abc"), join("subdir", "abc")],
|
||||
);
|
||||
});
|
||||
|
0
fs/testdata/walk/symlink/a/z
vendored
Normal file
0
fs/testdata/walk/symlink/a/z
vendored
Normal file
1
fs/testdata/walk/symlink/b
vendored
Symbolic link
1
fs/testdata/walk/symlink/b
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
a
|
22
fs/walk.ts
22
fs/walk.ts
@ -75,6 +75,12 @@ export interface WalkOptions {
|
||||
* @default {false}
|
||||
*/
|
||||
followSymlinks?: boolean;
|
||||
/**
|
||||
* Indicates whether the followed symlink's path should be canonicalized.
|
||||
* This option works only if `followSymlinks` is not `false`.
|
||||
* @default {true}
|
||||
*/
|
||||
canonicalize?: boolean;
|
||||
/**
|
||||
* List of file extensions used to filter entries.
|
||||
* If specified, entries without the file extension specified by this option are excluded.
|
||||
@ -119,6 +125,7 @@ export async function* walk(
|
||||
includeDirs = true,
|
||||
includeSymlinks = true,
|
||||
followSymlinks = false,
|
||||
canonicalize = true,
|
||||
exts = undefined,
|
||||
match = undefined,
|
||||
skip = undefined,
|
||||
@ -147,11 +154,14 @@ export async function* walk(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
path = await Deno.realPath(path);
|
||||
const realPath = await Deno.realPath(path);
|
||||
if (canonicalize) {
|
||||
path = realPath;
|
||||
}
|
||||
// Caveat emptor: don't assume |path| is not a symlink. realpath()
|
||||
// resolves symlinks but another process can replace the file system
|
||||
// entity with a different type of entity before we call lstat().
|
||||
({ isSymlink, isDirectory } = await Deno.lstat(path));
|
||||
({ isSymlink, isDirectory } = await Deno.lstat(realPath));
|
||||
}
|
||||
|
||||
if (isSymlink || isDirectory) {
|
||||
@ -183,6 +193,7 @@ export function* walkSync(
|
||||
includeDirs = true,
|
||||
includeSymlinks = true,
|
||||
followSymlinks = false,
|
||||
canonicalize = true,
|
||||
exts = undefined,
|
||||
match = undefined,
|
||||
skip = undefined,
|
||||
@ -216,11 +227,14 @@ export function* walkSync(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
path = Deno.realPathSync(path);
|
||||
const realPath = Deno.realPathSync(path);
|
||||
if (canonicalize) {
|
||||
path = realPath;
|
||||
}
|
||||
// Caveat emptor: don't assume |path| is not a symlink. realpath()
|
||||
// resolves symlinks but another process can replace the file system
|
||||
// entity with a different type of entity before we call lstat().
|
||||
({ isSymlink, isDirectory } = Deno.lstatSync(path));
|
||||
({ isSymlink, isDirectory } = Deno.lstatSync(realPath));
|
||||
}
|
||||
|
||||
if (isSymlink || isDirectory) {
|
||||
|
@ -74,12 +74,18 @@ Deno.test("[fs/walk] skip", async () =>
|
||||
|
||||
// https://github.com/denoland/deno_std/issues/1358
|
||||
Deno.test("[fs/walk] symlink", async () =>
|
||||
await assertWalkPaths("symlink", [".", "x", "x"], {
|
||||
await assertWalkPaths("symlink", [".", "a", "a/z", "a", "a/z", "x", "x"], {
|
||||
followSymlinks: true,
|
||||
}));
|
||||
|
||||
Deno.test("[fs/walk] symlink without canonicalize", async () =>
|
||||
await assertWalkPaths("symlink", [".", "a", "a/z", "b", "b/z", "x", "y"], {
|
||||
followSymlinks: true,
|
||||
canonicalize: false,
|
||||
}));
|
||||
|
||||
Deno.test("[fs/walk] symlink without followSymlink", async () => {
|
||||
await assertWalkPaths("symlink", [".", "x", "y"], {
|
||||
await assertWalkPaths("symlink", [".", "a", "a/z", "b", "x", "y"], {
|
||||
followSymlinks: false,
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user