From 3d56123f25c11d02c43367808fe44952ec67ba41 Mon Sep 17 00:00:00 2001 From: "Fred K. Schott" Date: Thu, 10 Mar 2022 09:53:59 -0800 Subject: [PATCH] Refactor fs utils, fix flakey windows tests (#2749) * cleanup our fs util usage * fix fs url support for node v14 * update to fix windows * making sure the dir exists before calling readdirSync * chore: remove debug code Co-authored-by: Tony Sullivan Co-authored-by: Nate Moore --- packages/astro/src/core/build/fs.ts | 72 ------------------- packages/astro/src/core/build/static-build.ts | 11 +-- packages/astro/src/core/util.ts | 18 +++++ 3 files changed, 21 insertions(+), 80 deletions(-) delete mode 100644 packages/astro/src/core/build/fs.ts diff --git a/packages/astro/src/core/build/fs.ts b/packages/astro/src/core/build/fs.ts deleted file mode 100644 index 510f84c77..000000000 --- a/packages/astro/src/core/build/fs.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { AstroConfig } from '../../@types/astro'; - -import fs from 'fs'; -import npath from 'path'; -import { fileURLToPath } from 'url'; - -const isWindows = process.platform === 'win32'; - -export function emptyDir(dir: string, skip?: Set): void { - for (const file of fs.readdirSync(dir)) { - if (skip?.has(file)) { - continue; - } - const abs = npath.resolve(dir, file); - // baseline is Node 12 so can't use rmSync :( - let isDir = false; - try { - isDir = fs.lstatSync(abs).isDirectory(); - } catch (err: any) { - // Taken from: - // https://github.com/isaacs/rimraf/blob/9219c937be159edbdf1efa961f2904e863c3ce2d/rimraf.js#L293-L296 - if (err.code === 'EPERM' && isWindows) { - fixWinEPERMSync(abs, err); - } else { - throw err; - } - } - - if (isDir) { - emptyDir(abs); - fs.rmdirSync(abs); - } else { - fs.unlinkSync(abs); - } - } -} - -export function prepareOutDir(astroConfig: AstroConfig) { - const outDir = fileURLToPath(astroConfig.dist); - if (fs.existsSync(outDir)) { - return emptyDir(outDir, new Set(['.git'])); - } -} - -function fixWinEPERMSync(path: string, error: Error) { - try { - fs.chmodSync(path, 0o666); - } catch (er2: any) { - if (er2.code === 'ENOENT') { - return; - } else { - throw error; - } - } - - let stats; - try { - stats = fs.statSync(path); - } catch (er3: any) { - if (er3.code === 'ENOENT') { - return; - } else { - throw error; - } - } - - if (stats.isDirectory()) { - emptyDir(path); - } else { - fs.unlinkSync(path); - } -} diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index ec557c7d1..9c014f87c 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -15,10 +15,9 @@ import glob from 'fast-glob'; import * as vite from 'vite'; import { debug, error } from '../../core/logger.js'; import { prependForwardSlash, appendForwardSlash } from '../../core/path.js'; -import { resolveDependency } from '../../core/util.js'; +import { emptyDir, removeDir, resolveDependency } from '../../core/util.js'; import { createBuildInternals } from '../../core/build/internal.js'; import { rollupPluginAstroBuildCSS } from '../../vite-plugin-build-css/index.js'; -import { emptyDir, prepareOutDir } from './fs.js'; import { vitePluginHoistedScripts } from './vite-plugin-hoisted-scripts.js'; import { RouteCache } from '../render/route-cache.js'; import { serializeRouteData } from '../routing/index.js'; @@ -160,7 +159,7 @@ export async function staticBuild(opts: StaticBuildOptions) { // Empty out the dist folder, if needed. Vite has a config for doing this // but because we are running 2 vite builds in parallel, that would cause a race // condition, so we are doing it ourselves - prepareOutDir(astroConfig); + emptyDir(astroConfig.dist, new Set('.git')); // Run the SSR build and client build in parallel const [ssrResult] = (await Promise.all([ssrBuild(opts, internals, pageInput), clientBuild(opts, internals, jsInput)])) as RollupOutput[]; @@ -550,11 +549,7 @@ async function ssrMoveAssets(opts: StaticBuildOptions) { }) ); - await emptyDir(fileURLToPath(serverAssets)); - - if (fs.existsSync(serverAssets)) { - await fs.promises.rmdir(serverAssets); - } + await removeDir(serverAssets); } export function vitePluginNewBuild(input: Set, internals: BuildInternals, ext: 'js' | 'mjs'): VitePlugin { diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts index 58c7fc9d0..0ec989ed6 100644 --- a/packages/astro/src/core/util.ts +++ b/packages/astro/src/core/util.ts @@ -3,6 +3,7 @@ import type { ErrorPayload } from 'vite'; import eol from 'eol'; import path from 'path'; import slash from 'slash'; +import fs from 'fs'; import { fileURLToPath, pathToFileURL } from 'url'; import resolve from 'resolve'; @@ -97,6 +98,23 @@ export function viteID(filePath: URL): string { return slash(fileURLToPath(filePath)); } +/** An fs utility, similar to `rimraf` or `rm -rf` */ +export function removeDir(_dir: URL): void { + const dir = fileURLToPath(_dir); + fs.rmSync(dir, {recursive: true, force: true}); +} + +export function emptyDir(_dir: URL, skip?: Set): void { + const dir = fileURLToPath(_dir); + if (!fs.existsSync(dir)) return undefined; + for (const file of fs.readdirSync(dir)) { + if (skip?.has(file)) { + continue; + } + fs.rmSync(path.resolve(dir, file), {recursive: true, force: true}); + } +} + // Vendored from https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl /** Basic stylesheet for RSS feeds */ export const PRETTY_FEED_V3 = `