mirror of
https://github.com/earendil-works/pi.git
synced 2026-06-18 15:54:04 +08:00
89b64d9dd5
closes #4157
85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
import { copyFileSync, existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
|
|
import { basename, dirname, join, relative, resolve, toNamespacedPath } from "node:path";
|
|
import { getCwdRelativePath } from "./paths.js";
|
|
|
|
const QUARANTINE_DIR_NAME = ".pi-native-quarantine";
|
|
|
|
function normalizePath(path: string): string {
|
|
return toNamespacedPath(resolve(path));
|
|
}
|
|
|
|
function getQuarantineRoot(packageDir: string): string | undefined {
|
|
let current = resolve(packageDir);
|
|
while (true) {
|
|
if (basename(current).toLowerCase() === "node_modules") {
|
|
return join(current, QUARANTINE_DIR_NAME);
|
|
}
|
|
const parent = dirname(current);
|
|
if (parent === current) {
|
|
return undefined;
|
|
}
|
|
current = parent;
|
|
}
|
|
}
|
|
|
|
function getLoadedSharedObjectsInPackageDir(packageDir: string): string[] {
|
|
const sharedObjects = (process.report.getReport() as { sharedObjects?: unknown }).sharedObjects;
|
|
if (!Array.isArray(sharedObjects)) {
|
|
return [];
|
|
}
|
|
|
|
const root = normalizePath(packageDir).toLowerCase();
|
|
const seen = new Set<string>();
|
|
const loadedFiles: string[] = [];
|
|
for (const value of sharedObjects) {
|
|
if (typeof value !== "string") {
|
|
continue;
|
|
}
|
|
const filePath = normalizePath(value);
|
|
const comparisonPath = filePath.toLowerCase();
|
|
if (getCwdRelativePath(comparisonPath, root) === undefined || seen.has(comparisonPath)) {
|
|
continue;
|
|
}
|
|
seen.add(comparisonPath);
|
|
loadedFiles.push(filePath);
|
|
}
|
|
return loadedFiles;
|
|
}
|
|
|
|
export function cleanupWindowsSelfUpdateQuarantine(packageDir: string): void {
|
|
const quarantineRoot = getQuarantineRoot(packageDir);
|
|
if (!quarantineRoot) {
|
|
return;
|
|
}
|
|
try {
|
|
rmSync(quarantineRoot, { recursive: true, force: true });
|
|
} catch {
|
|
// A previous pi process may still be exiting and holding a native addon.
|
|
}
|
|
}
|
|
|
|
export function quarantineWindowsNativeDependencies(packageDir: string): void {
|
|
const resolvedPackageDir = normalizePath(packageDir);
|
|
const quarantineRoot = getQuarantineRoot(resolvedPackageDir);
|
|
if (!quarantineRoot) {
|
|
return;
|
|
}
|
|
|
|
const loadedFiles = getLoadedSharedObjectsInPackageDir(resolvedPackageDir);
|
|
if (loadedFiles.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const quarantineRunDir = join(quarantineRoot, `${Date.now()}-${process.pid}-${randomUUID()}`);
|
|
for (const loadedFile of loadedFiles) {
|
|
if (!existsSync(loadedFile)) {
|
|
continue;
|
|
}
|
|
const quarantinePath = join(quarantineRunDir, relative(resolvedPackageDir, loadedFile));
|
|
mkdirSync(dirname(quarantinePath), { recursive: true });
|
|
renameSync(loadedFile, quarantinePath);
|
|
copyFileSync(quarantinePath, loadedFile);
|
|
}
|
|
}
|