diff options
Diffstat (limited to 'scripts/docs')
| -rw-r--r-- | scripts/docs/snapshot.mjs | 14 | ||||
| -rw-r--r-- | scripts/docs/versions.integration.test.ts | 17 |
2 files changed, 23 insertions, 8 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`); } } diff --git a/scripts/docs/versions.integration.test.ts b/scripts/docs/versions.integration.test.ts index 9731d3c0..214bfef9 100644 --- a/scripts/docs/versions.integration.test.ts +++ b/scripts/docs/versions.integration.test.ts @@ -100,9 +100,20 @@ describe('documentation release publishing', () => { correctedArchivedDocs, ); const linkedPage = resolve(archivedDocsRoot, 'linked.mdx'); - await symlink('index.mdx', linkedPage); - expect(() => runScript(root, ['check'])).toThrow(); - await rm(linkedPage); + if (process.platform === 'win32') { + // A normal Windows terminal cannot create file symlinks without Developer + // Mode or elevation, but a directory junction is creatable without + // either. Link to an empty directory outside the snapshot so the walk + // stays finite and only the non-ordinary-file rejection can satisfy the + // assertion below. + const linkTarget = await mkdtemp(join(tmpdir(), 'herdr-docs-link-')); + temporaryDirectories.push(linkTarget); + await symlink(linkTarget, linkedPage, 'junction'); + } else { + await symlink('index.mdx', linkedPage); + } + expect(() => runScript(root, ['check'])).toThrow(/is not an ordinary documentation file/); + await rm(linkedPage, { recursive: true, force: true }); runScript(root, ['check']); delete archivedManifest.versions[0].commit; |
