diff options
| author | JJ Liebig <jonathan.liebig@gmail.com> | 2026-09-26 17:15:50 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-26 17:15:50 +0200 |
| commit | c34dd6b2acd432cb7acbe9de568b245853e3b8c7 (patch) | |
| tree | a68818659f64e7f760a6d1f16176b0d843d97568 /scripts/docs/snapshot.mjs | |
| parent | 804a4aaf3ec21e681a09d3021d96b33206280b16 (diff) | |
fix: create a symlink on non-elevated windows in docs test (#4654)
* fix: create a symlink on non-elevated windows in docs test
Windows terminals without Developer Mode or elevation cannot create file
symlinks, so the versions publishing integration test failed with EPERM
before it could reach the non-ordinary-file rejection. Fall back to a
directory junction, which is creatable without elevation and hits the
same rejection path.
* fix: detect docs snapshot reparse points with lstat
Classify entries with lstat instead of the readdir dirent so symlinks and
Windows junctions are rejected regardless of how a runtime classifies
them. This keeps the versions integration test's non-ordinary-file
assertion meaningful on non-elevated Windows, where the fixture can only
create a directory junction.
Diffstat (limited to 'scripts/docs/snapshot.mjs')
| -rw-r--r-- | scripts/docs/snapshot.mjs | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/scripts/docs/snapshot.mjs b/scripts/docs/snapshot.mjs index e9eaf92c..7610715a 100644 --- a/scripts/docs/snapshot.mjs +++ b/scripts/docs/snapshot.mjs @@ -1,5 +1,5 @@ import { execFileSync } from 'node:child_process'; -import { mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'; +import { lstat, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'; import { dirname, relative, resolve } from 'node:path'; export function createGit(repoRoot) { @@ -92,10 +92,14 @@ export async function compareGitTree(git, ref, sourceRoot, snapshotRoot) { export async function listDocumentationPaths(root) { const paths = []; async function walk(directory) { - for (const entry of await readdir(directory, { withFileTypes: true })) { - const path = resolve(directory, entry.name); - if (entry.isDirectory()) await walk(path); - else if (entry.isFile()) paths.push(relative(root, path)); + for (const name of await readdir(directory)) { + const path = resolve(directory, name); + // lstat does not follow links, so symlinks and Windows junctions stay + // non-ordinary here even if a runtime classifies them as directories in + // the readdir entry. + const stats = await lstat(path); + if (stats.isDirectory()) await walk(path); + else if (stats.isFile()) paths.push(relative(root, path)); else throw new Error(`${path} is not an ordinary documentation file`); } } |
