2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2024-07-24 06:31:05 +00:00
|
|
|
import { walk, type WalkOptions, walkSync } from "./walk.ts";
|
2021-04-30 06:49:41 +00:00
|
|
|
import {
|
2023-07-23 08:47:21 +00:00
|
|
|
assertArrayIncludes,
|
2021-04-30 06:49:41 +00:00
|
|
|
assertEquals,
|
2021-08-09 05:59:52 +00:00
|
|
|
assertRejects,
|
2021-04-30 06:49:41 +00:00
|
|
|
assertThrows,
|
2024-04-29 02:57:30 +00:00
|
|
|
} from "@std/assert";
|
|
|
|
import { fromFileUrl, resolve } from "@std/path";
|
2020-03-15 12:03:25 +00:00
|
|
|
|
2023-07-23 08:47:21 +00:00
|
|
|
const testdataDir = resolve(fromFileUrl(import.meta.url), "../testdata/walk");
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-07-23 08:47:21 +00:00
|
|
|
async function assertWalkPaths(
|
|
|
|
rootPath: string,
|
|
|
|
expectedPaths: string[],
|
|
|
|
options?: WalkOptions,
|
|
|
|
) {
|
|
|
|
const root = resolve(testdataDir, rootPath);
|
2023-11-10 19:00:28 +00:00
|
|
|
const entries = await Array.fromAsync(walk(root, options));
|
2023-07-23 08:47:21 +00:00
|
|
|
|
|
|
|
const expected = expectedPaths.map((path) => resolve(root, path));
|
|
|
|
assertEquals(entries.length, expected.length);
|
|
|
|
assertArrayIncludes(entries.map(({ path }) => path), expected);
|
2019-02-15 16:20:59 +00:00
|
|
|
}
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
function assertWalkSyncPaths(
|
|
|
|
rootPath: string,
|
|
|
|
expectedPaths: string[],
|
|
|
|
options?: WalkOptions,
|
|
|
|
) {
|
|
|
|
const root = resolve(testdataDir, rootPath);
|
|
|
|
const entriesSync = Array.from(walkSync(root, options));
|
|
|
|
|
|
|
|
const expected = expectedPaths.map((path) => resolve(root, path));
|
|
|
|
assertEquals(entriesSync.length, expected.length);
|
|
|
|
assertArrayIncludes(entriesSync.map(({ path }) => path), expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
Deno.test("walk() returns current dir for empty dir", async () => {
|
2023-07-23 08:47:21 +00:00
|
|
|
const emptyDir = resolve(testdataDir, "empty_dir");
|
|
|
|
await Deno.mkdir(emptyDir);
|
|
|
|
await assertWalkPaths("empty_dir", ["."]);
|
|
|
|
await Deno.remove(emptyDir);
|
|
|
|
});
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() returns current dir for empty dir", async () => {
|
|
|
|
const emptyDir = resolve(testdataDir, "empty_dir");
|
|
|
|
await Deno.mkdir(emptyDir);
|
|
|
|
assertWalkSyncPaths("empty_dir", ["."]);
|
|
|
|
await Deno.remove(emptyDir);
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test("walk() returns current dir and single file", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("single_file", [".", "x"]));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() returns current dir and single file", () =>
|
|
|
|
assertWalkSyncPaths("single_file", [".", "x"]));
|
|
|
|
|
|
|
|
Deno.test("walk() returns current dir, subdir, and nested file", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("nested_single_file", [".", "a", "a/x"]));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() returns current dir, subdir, and nested file", () =>
|
|
|
|
assertWalkSyncPaths("nested_single_file", [".", "a", "a/x"]));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts maxDepth option", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("depth", [".", "a", "a/b", "a/b/c"], { maxDepth: 3 }));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts maxDepth option", () =>
|
|
|
|
assertWalkSyncPaths("depth", [".", "a", "a/b", "a/b/c"], { maxDepth: 3 }));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts includeDirs option set to false", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("depth", ["a/b/c/d/x"], { includeDirs: false }));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts includeDirs option set to false", () =>
|
|
|
|
assertWalkSyncPaths("depth", ["a/b/c/d/x"], { includeDirs: false }));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts includeFiles option set to false", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("depth", [".", "a", "a/b", "a/b/c", "a/b/c/d"], {
|
|
|
|
includeFiles: false,
|
|
|
|
}));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts includeFiles option set to false", () =>
|
|
|
|
assertWalkSyncPaths("depth", [".", "a", "a/b", "a/b/c", "a/b/c/d"], {
|
|
|
|
includeFiles: false,
|
|
|
|
}));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts ext option as strings", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("ext", ["y.rs", "x.ts"], {
|
|
|
|
exts: [".rs", ".ts"],
|
|
|
|
}));
|
2019-02-15 16:20:59 +00:00
|
|
|
|
2024-07-08 00:41:32 +00:00
|
|
|
Deno.test("walk() accepts ext option as strings (excluding period prefix)", async () =>
|
|
|
|
await assertWalkPaths("ext", ["y.rs", "x.ts"], {
|
|
|
|
exts: ["rs", "ts"],
|
|
|
|
}));
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts ext option as strings", () =>
|
|
|
|
assertWalkSyncPaths("ext", ["y.rs", "x.ts"], {
|
|
|
|
exts: [".rs", ".ts"],
|
|
|
|
}));
|
|
|
|
|
2024-07-08 00:41:32 +00:00
|
|
|
Deno.test("walkSync() accepts ext option as strings (excluding period prefix)", () =>
|
|
|
|
assertWalkSyncPaths("ext", ["y.rs", "x.ts"], {
|
|
|
|
exts: [".rs", ".ts"],
|
|
|
|
}));
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walk() accepts ext option as regExps", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("match", ["x", "y"], {
|
|
|
|
match: [/x/, /y/],
|
|
|
|
}));
|
2021-04-30 06:49:41 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts ext option as regExps", () =>
|
|
|
|
assertWalkSyncPaths("match", ["x", "y"], {
|
|
|
|
match: [/x/, /y/],
|
|
|
|
}));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts skip option as regExps", async () =>
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("match", [".", "z"], {
|
|
|
|
skip: [/x/, /y/],
|
|
|
|
}));
|
2023-03-29 12:07:50 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts skip option as regExps", () =>
|
|
|
|
assertWalkSyncPaths("match", [".", "z"], {
|
|
|
|
skip: [/x/, /y/],
|
|
|
|
}));
|
|
|
|
|
2021-11-12 03:52:46 +00:00
|
|
|
// https://github.com/denoland/deno_std/issues/1358
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walk() accepts followSymlinks option set to true", async () =>
|
2023-10-16 13:32:15 +00:00
|
|
|
await assertWalkPaths("symlink", [".", "a", "a/z", "a", "a/z", "x", "x"], {
|
2023-07-23 08:47:21 +00:00
|
|
|
followSymlinks: true,
|
|
|
|
}));
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts followSymlinks option set to true", () =>
|
|
|
|
assertWalkSyncPaths("symlink", [".", "a", "a/z", "a", "a/z", "x", "x"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
}));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts followSymlinks option set to true with canonicalize option set to false", async () =>
|
2023-10-16 13:32:15 +00:00
|
|
|
await assertWalkPaths("symlink", [".", "a", "a/z", "b", "b/z", "x", "y"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
canonicalize: false,
|
|
|
|
}));
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts followSymlinks option set to true with canonicalize option set to false", () =>
|
|
|
|
assertWalkSyncPaths("symlink", [".", "a", "a/z", "b", "b/z", "x", "y"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
canonicalize: false,
|
|
|
|
}));
|
|
|
|
|
|
|
|
Deno.test("walk() accepts followSymlinks option set to false", async () => {
|
2023-10-16 13:32:15 +00:00
|
|
|
await assertWalkPaths("symlink", [".", "a", "a/z", "b", "x", "y"], {
|
2023-07-27 13:07:44 +00:00
|
|
|
followSymlinks: false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test("walkSync() accepts followSymlinks option set to false", () => {
|
|
|
|
assertWalkSyncPaths("symlink", [".", "a", "a/z", "b", "x", "y"], {
|
|
|
|
followSymlinks: false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test("walk() rejects Deno.errors.NotFound for non-existent root", async () => {
|
2023-07-23 08:47:21 +00:00
|
|
|
const root = resolve(testdataDir, "non_existent");
|
|
|
|
await assertRejects(
|
2023-11-10 19:00:28 +00:00
|
|
|
async () => await Array.fromAsync(walk(root)),
|
2023-07-23 08:47:21 +00:00
|
|
|
Deno.errors.NotFound,
|
|
|
|
);
|
2023-11-23 06:59:59 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test("walkSync() throws Deno.errors.NotFound for non-existent root", () => {
|
|
|
|
const root = resolve(testdataDir, "non_existent");
|
2023-07-23 08:47:21 +00:00
|
|
|
assertThrows(() => Array.from(walkSync(root)), Deno.errors.NotFound);
|
|
|
|
});
|
2021-11-12 03:52:46 +00:00
|
|
|
|
2022-01-20 07:50:14 +00:00
|
|
|
// https://github.com/denoland/deno_std/issues/1789
|
2023-07-23 08:47:21 +00:00
|
|
|
Deno.test({
|
2023-11-23 06:59:59 +00:00
|
|
|
name: "walk() walks unix socket",
|
2023-07-23 08:47:21 +00:00
|
|
|
ignore: Deno.build.os === "windows",
|
|
|
|
async fn() {
|
2023-07-27 13:09:18 +00:00
|
|
|
const path = resolve(testdataDir, "socket", "a.sock");
|
|
|
|
try {
|
2024-01-14 21:35:50 +00:00
|
|
|
using _listener = Deno.listen({ path, transport: "unix" });
|
2023-07-27 13:09:18 +00:00
|
|
|
await assertWalkPaths("socket", [".", "a.sock", ".gitignore"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
await Deno.remove(path);
|
|
|
|
}
|
2022-01-20 07:50:14 +00:00
|
|
|
},
|
2023-07-23 08:47:21 +00:00
|
|
|
});
|
2022-01-20 07:50:14 +00:00
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
// https://github.com/denoland/deno_std/issues/1789
|
2023-07-23 08:47:21 +00:00
|
|
|
Deno.test({
|
2023-11-23 06:59:59 +00:00
|
|
|
name: "walkSync() walks unix socket",
|
|
|
|
ignore: Deno.build.os === "windows",
|
|
|
|
async fn() {
|
|
|
|
const path = resolve(testdataDir, "socket", "a.sock");
|
|
|
|
try {
|
2024-01-14 21:35:50 +00:00
|
|
|
using _listener = Deno.listen({ path, transport: "unix" });
|
2023-11-23 06:59:59 +00:00
|
|
|
assertWalkSyncPaths("socket", [".", "a.sock", ".gitignore"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
await Deno.remove(path);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "walk() walks fifo files on unix",
|
2023-07-23 08:47:21 +00:00
|
|
|
ignore: Deno.build.os === "windows",
|
|
|
|
async fn() {
|
|
|
|
const command = new Deno.Command("mkfifo", {
|
|
|
|
args: [resolve(testdataDir, "fifo", "fifo")],
|
|
|
|
});
|
2022-11-15 06:00:59 +00:00
|
|
|
await command.output();
|
2023-07-23 08:47:21 +00:00
|
|
|
await assertWalkPaths("fifo", [".", "fifo", ".gitignore"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2023-11-23 06:59:59 +00:00
|
|
|
Deno.test({
|
|
|
|
name: "walkSync() walks fifo files on unix",
|
|
|
|
ignore: Deno.build.os === "windows",
|
|
|
|
async fn() {
|
|
|
|
const command = new Deno.Command("mkfifo", {
|
|
|
|
args: [resolve(testdataDir, "fifo", "fifo")],
|
|
|
|
});
|
|
|
|
await command.output();
|
|
|
|
assertWalkSyncPaths("fifo", [".", "fifo", ".gitignore"], {
|
|
|
|
followSymlinks: true,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2024-07-24 06:31:05 +00:00
|
|
|
Deno.test("walk() rejects with `Deno.errors.NotFound` when root is removed during execution", async () => {
|
2023-07-23 08:47:21 +00:00
|
|
|
const root = resolve(testdataDir, "error");
|
|
|
|
await Deno.mkdir(root);
|
2023-11-23 06:59:59 +00:00
|
|
|
try {
|
2024-07-24 06:31:05 +00:00
|
|
|
await assertRejects(
|
|
|
|
async () => {
|
|
|
|
await Array.fromAsync(
|
|
|
|
walk(root),
|
|
|
|
async () => await Deno.remove(root, { recursive: true }),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
Deno.errors.NotFound,
|
|
|
|
);
|
2023-11-23 06:59:59 +00:00
|
|
|
} catch (err) {
|
|
|
|
await Deno.remove(root, { recursive: true });
|
|
|
|
throw err;
|
|
|
|
}
|
2023-07-23 08:47:21 +00:00
|
|
|
});
|