mirror of
https://github.com/oven-sh/bun
synced 2026-02-19 07:12:24 +00:00
160 lines
3.9 KiB
TypeScript
160 lines
3.9 KiB
TypeScript
import crypto from "crypto";
|
|
import fs from "fs";
|
|
import os from "os";
|
|
import path from "path";
|
|
import { debug } from "./console";
|
|
|
|
export function join(...paths: (string | string[])[]): string {
|
|
return path.join(...paths.flat(2));
|
|
}
|
|
|
|
export function basename(...paths: (string | string[])[]): string {
|
|
return path.basename(join(...paths));
|
|
}
|
|
|
|
export function tmp(): string {
|
|
const tmpdir = process.env["RUNNER_TEMP"] ?? os.tmpdir();
|
|
const dir = fs.mkdtempSync(join(tmpdir, "bun-"));
|
|
debug("tmp", dir);
|
|
return dir;
|
|
}
|
|
|
|
export function rm(path: string): void {
|
|
debug("rm", path);
|
|
try {
|
|
fs.rmSync(path, { recursive: true });
|
|
return;
|
|
} catch (error) {
|
|
debug("fs.rmSync failed", error);
|
|
// Did not exist before Node.js v14.
|
|
// Attempt again with older, slower implementation.
|
|
}
|
|
let stats: fs.Stats;
|
|
try {
|
|
stats = fs.lstatSync(path);
|
|
} catch (error) {
|
|
debug("fs.lstatSync failed", error);
|
|
// The file was likely deleted, so return early.
|
|
return;
|
|
}
|
|
if (!stats.isDirectory()) {
|
|
fs.unlinkSync(path);
|
|
return;
|
|
}
|
|
try {
|
|
fs.rmdirSync(path, { recursive: true });
|
|
return;
|
|
} catch (error) {
|
|
debug("fs.rmdirSync failed", error);
|
|
// Recursive flag did not exist before Node.js X.
|
|
// Attempt again with older, slower implementation.
|
|
}
|
|
for (const filename of fs.readdirSync(path)) {
|
|
rm(join(path, filename));
|
|
}
|
|
fs.rmdirSync(path);
|
|
}
|
|
|
|
export function rename(path: string, newPath: string): void {
|
|
debug("rename", path, newPath);
|
|
try {
|
|
fs.renameSync(path, newPath);
|
|
return;
|
|
} catch (error) {
|
|
debug("fs.renameSync failed", error);
|
|
// If there is an error, delete the new path and try again.
|
|
}
|
|
try {
|
|
rm(newPath);
|
|
} catch (error) {
|
|
debug("rm failed", error);
|
|
// The path could have been deleted already.
|
|
}
|
|
fs.renameSync(path, newPath);
|
|
}
|
|
|
|
export function write(dst: string, content: string | ArrayBuffer | ArrayBufferView): void {
|
|
debug("write", dst);
|
|
try {
|
|
fs.writeFileSync(dst, content);
|
|
return;
|
|
} catch (error) {
|
|
debug("fs.writeFileSync failed", error);
|
|
// If there is an error, ensure the parent directory
|
|
// exists and try again.
|
|
try {
|
|
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
} catch (error) {
|
|
debug("fs.mkdirSync failed", error);
|
|
// The directory could have been created already.
|
|
}
|
|
fs.writeFileSync(dst, content);
|
|
}
|
|
}
|
|
|
|
export function writeJson(path: string, json: object, force?: boolean): void {
|
|
let value = json;
|
|
if (!force && exists(path)) {
|
|
try {
|
|
const existing = JSON.parse(read(path));
|
|
value = {
|
|
...existing,
|
|
...json,
|
|
};
|
|
} catch {
|
|
value = json;
|
|
}
|
|
}
|
|
write(path, `${JSON.stringify(value, undefined, 2)}\n`);
|
|
}
|
|
|
|
export function read(path: string): string {
|
|
debug("read", path);
|
|
return fs.readFileSync(path, "utf-8");
|
|
}
|
|
|
|
export function blob(path: string): Blob {
|
|
debug("blob", path);
|
|
if ("Bun" in globalThis) {
|
|
return Bun.file(path);
|
|
}
|
|
const buffer = fs.readFileSync(path);
|
|
return new Blob([buffer], {
|
|
type: path.endsWith(".zip") ? "application/zip" : path.endsWith(".txt") ? "text/plain" : "application/octet-stream",
|
|
});
|
|
}
|
|
|
|
export function hash(content: string | crypto.BinaryLike): string {
|
|
debug("hash", content);
|
|
return crypto
|
|
.createHash("sha256")
|
|
.update(typeof content === "string" ? fs.readFileSync(content) : content)
|
|
.digest("hex");
|
|
}
|
|
|
|
export function chmod(path: string, mode: fs.Mode): void {
|
|
debug("chmod", path, mode);
|
|
fs.chmodSync(path, mode);
|
|
}
|
|
|
|
export function copy(path: string, newPath: string): void {
|
|
debug("copy", path, newPath);
|
|
try {
|
|
fs.copyFileSync(path, newPath);
|
|
return;
|
|
} catch (error) {
|
|
debug("fs.copyFileSync failed", error);
|
|
}
|
|
write(newPath, read(path));
|
|
}
|
|
|
|
export function exists(path: string): boolean {
|
|
debug("exists", path);
|
|
try {
|
|
return fs.existsSync(path);
|
|
} catch (error) {
|
|
debug("fs.existsSync failed", error);
|
|
}
|
|
return false;
|
|
}
|