Skip to content

Commit

Permalink
fix: ensure rimraf bin dir can always be resolved (#3614)
Browse files Browse the repository at this point in the history
  • Loading branch information
tada5hi committed Mar 24, 2023
1 parent e2349ad commit 0fe5faf
Showing 1 changed file with 40 additions and 17 deletions.
57 changes: 40 additions & 17 deletions libs/core/src/lib/rimraf-dir.ts
@@ -1,36 +1,59 @@
"use strict";

import log from "npmlog";
import path from "path";
import path from "node:path";
import fs from "node:fs";
import pathExists from "path-exists";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const childProcess = require("@lerna/child-process");

// NOTE: if rimraf moves the location of its executable, this will need to be updated
const RIMRAF_CLI = require.resolve("rimraf/bin");
let rimrafBinPath: string | undefined;

export function rimrafDir(dirPath: string) {
async function useRimrafBinPath(): Promise<string> {
if (typeof rimrafBinPath === "string") {
return rimrafBinPath;
}

const filePath = require.resolve("rimraf");
const directoryPath = path.basename(filePath);

try {
const rawFile = await fs.promises.readFile(path.join(directoryPath, "package.json"), {
encoding: "utf-8",
});
const file = JSON.parse(rawFile);

rimrafBinPath = file.bin || require.resolve("rimraf/bin");
} catch (e) {
rimrafBinPath = require.resolve("rimraf/bin");
}

return rimrafBinPath as string;
}

export async function rimrafDir(dirPath: string) {
log.silly("rimrafDir", dirPath);
// Shelling out to a child process for a noop is expensive.
// Checking if `dirPath` exists to be removed is cheap.
// This lets us short-circuit if we don't have anything to do.

return pathExists(dirPath).then((exists) => {
if (!exists) {
return;
}
const fileExists = await pathExists(dirPath);
if (!fileExists) {
return;
}

// globs only return directories with a trailing slash
const slashed = path.normalize(`${dirPath}/`);
const args = [RIMRAF_CLI, "--no-glob", slashed];
const cliPath = await useRimrafBinPath();

// We call this resolved CLI path in the "path/to/node path/to/cli <..args>"
// pattern to avoid Windows hangups with shebangs (e.g., WSH can't handle it)
return childProcess.spawn(process.execPath, args).then(() => {
log.verbose("rimrafDir", "removed", dirPath);
// globs only return directories with a trailing slash
const slashed = path.normalize(`${dirPath}/`);
const args = [cliPath, "--no-glob", slashed];

return dirPath;
});
// We call this resolved CLI path in the "path/to/node path/to/cli <..args>"
// pattern to avoid Windows hangups with shebangs (e.g., WSH can't handle it)
return childProcess.spawn(process.execPath, args).then(() => {
log.verbose("rimrafDir", "removed", dirPath);

return dirPath;
});
}

0 comments on commit 0fe5faf

Please sign in to comment.