diff options
Diffstat (limited to 'packages/bun-release/src/fs.ts')
-rw-r--r-- | packages/bun-release/src/fs.ts | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/packages/bun-release/src/fs.ts b/packages/bun-release/src/fs.ts new file mode 100644 index 000000000..ef20c224a --- /dev/null +++ b/packages/bun-release/src/fs.ts @@ -0,0 +1,166 @@ +import path from "path"; +import fs from "fs"; +import os from "os"; +import crypto from "crypto"; +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; +} |