aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-release/src/fs.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/bun-release/src/fs.ts')
-rw-r--r--packages/bun-release/src/fs.ts166
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;
+}