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:
parent
55f007f30a
commit
3d56123f25
3 changed files with 21 additions and 80 deletions
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,10 +15,9 @@ import glob from 'fast-glob';
|
||||||
import * as vite from 'vite';
|
import * as vite from 'vite';
|
||||||
import { debug, error } from '../../core/logger.js';
|
import { debug, error } from '../../core/logger.js';
|
||||||
import { prependForwardSlash, appendForwardSlash } from '../../core/path.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 { createBuildInternals } from '../../core/build/internal.js';
|
||||||
import { rollupPluginAstroBuildCSS } from '../../vite-plugin-build-css/index.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 { vitePluginHoistedScripts } from './vite-plugin-hoisted-scripts.js';
|
||||||
import { RouteCache } from '../render/route-cache.js';
|
import { RouteCache } from '../render/route-cache.js';
|
||||||
import { serializeRouteData } from '../routing/index.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
|
// 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
|
// but because we are running 2 vite builds in parallel, that would cause a race
|
||||||
// condition, so we are doing it ourselves
|
// condition, so we are doing it ourselves
|
||||||
prepareOutDir(astroConfig);
|
emptyDir(astroConfig.dist, new Set('.git'));
|
||||||
|
|
||||||
// Run the SSR build and client build in parallel
|
// Run the SSR build and client build in parallel
|
||||||
const [ssrResult] = (await Promise.all([ssrBuild(opts, internals, pageInput), clientBuild(opts, internals, jsInput)])) as RollupOutput[];
|
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));
|
await removeDir(serverAssets);
|
||||||
|
|
||||||
if (fs.existsSync(serverAssets)) {
|
|
||||||
await fs.promises.rmdir(serverAssets);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function vitePluginNewBuild(input: Set<string>, internals: BuildInternals, ext: 'js' | 'mjs'): VitePlugin {
|
export function vitePluginNewBuild(input: Set<string>, internals: BuildInternals, ext: 'js' | 'mjs'): VitePlugin {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import type { ErrorPayload } from 'vite';
|
||||||
import eol from 'eol';
|
import eol from 'eol';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import slash from 'slash';
|
import slash from 'slash';
|
||||||
|
import fs from 'fs';
|
||||||
import { fileURLToPath, pathToFileURL } from 'url';
|
import { fileURLToPath, pathToFileURL } from 'url';
|
||||||
import resolve from 'resolve';
|
import resolve from 'resolve';
|
||||||
|
|
||||||
|
@ -97,6 +98,23 @@ export function viteID(filePath: URL): string {
|
||||||
return slash(fileURLToPath(filePath));
|
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
|
// Vendored from https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl
|
||||||
/** Basic stylesheet for RSS feeds */
|
/** Basic stylesheet for RSS feeds */
|
||||||
export const PRETTY_FEED_V3 = `<?xml version="1.0" encoding="utf-8"?>
|
export const PRETTY_FEED_V3 = `<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
Loading…
Reference in a new issue