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 <tony.f.sullivan@outlook.com>
Co-authored-by: Nate Moore <nate@skypack.dev>
This commit is contained in:
Fred K. Schott 2022-03-10 09:53:59 -08:00 committed by GitHub
parent 55f007f30a
commit 3d56123f25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 80 deletions

View file

@ -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<string>): 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);
}
}

View file

@ -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<string>, internals: BuildInternals, ext: 'js' | 'mjs'): VitePlugin {

View file

@ -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<string>): 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 = `<?xml version="1.0" encoding="utf-8"?>