From 6b2b949865c09536a27f17c3f33c0cd90a20764c Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Fri, 24 Jan 2025 02:00:00 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix!:=20writeFileSafely=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=82=92=E9=9D=9E=E5=90=8C=E6=9C=9F=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=81=97=E3=80=81=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/electron/fileHelper.ts | 9 ++--- .../backend/electron/fileHelper.node.spec.ts | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 tests/unit/backend/electron/fileHelper.node.spec.ts diff --git a/src/backend/electron/fileHelper.ts b/src/backend/electron/fileHelper.ts index 062389c845..1fdba47b77 100644 --- a/src/backend/electron/fileHelper.ts +++ b/src/backend/electron/fileHelper.ts @@ -1,5 +1,4 @@ import fs from "fs"; -import { moveFileSync } from "move-file"; import { uuid4 } from "@/helpers/random"; import { createLogger } from "@/helpers/log"; @@ -14,15 +13,13 @@ export function writeFileSafely( data: string | NodeJS.ArrayBufferView, ) { const tmpPath = `${path}-${uuid4()}.tmp`; - fs.writeFileSync(tmpPath, data, { flag: "wx" }); try { - moveFileSync(tmpPath, path, { - overwrite: true, - }); + fs.writeFileSync(tmpPath, data, { flag: "wx" }); + fs.renameSync(tmpPath, path); } catch (error) { if (fs.existsSync(tmpPath)) { - fs.promises.unlink(tmpPath).catch((reason) => { + void fs.promises.unlink(tmpPath).catch((reason) => { log.warn("Failed to remove %s\n %o", tmpPath, reason); }); } diff --git a/tests/unit/backend/electron/fileHelper.node.spec.ts b/tests/unit/backend/electron/fileHelper.node.spec.ts new file mode 100644 index 0000000000..18ef9a38e2 --- /dev/null +++ b/tests/unit/backend/electron/fileHelper.node.spec.ts @@ -0,0 +1,39 @@ +import fs from "fs"; +import path from "path"; +import os from "os"; +import { test, expect, beforeAll, afterAll } from "vitest"; +import { writeFileSafely } from "@/backend/electron/fileHelper"; +import { uuid4 } from "@/helpers/random"; + +let tmpDir: string; + +beforeAll(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), uuid4())); +}); + +afterAll(() => { + fs.rmdirSync(tmpDir, { recursive: true }); +}); + +describe("writeFileSafely", () => { + test("ファイルを書き込める", async () => { + const filePath = path.join(tmpDir, uuid4()); + const content = "Hello World"; + writeFileSafely(filePath, content); + expect(fs.readFileSync(filePath, "utf-8")).toBe(content); + }); + + test("ファイルを上書きできる", async () => { + const filePath = path.join(tmpDir, uuid4()); + fs.writeFileSync(filePath, "old content"); + const newContent = "new content"; + writeFileSafely(filePath, newContent); + expect(fs.readFileSync(filePath, "utf-8")).toBe(newContent); + }); + + test("存在しないディレクトリに書き込もうとするとエラー", async () => { + const nonExistentDir = path.join(tmpDir, uuid4(), "subdir"); + const filePath = path.join(nonExistentDir, "test.txt"); + await expect(writeFileSafely(filePath, "data")).rejects.toThrow(); + }); +}); From b09ceb1fae9b471315b530ff3ea0127e91a67b8c Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Fri, 24 Jan 2025 02:07:33 +0900 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E7=A2=BA=E8=AA=8D=E6=96=B9=E6=B3=95=E3=81=8C=E9=96=93=E9=81=95?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/backend/electron/fileHelper.node.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/backend/electron/fileHelper.node.spec.ts b/tests/unit/backend/electron/fileHelper.node.spec.ts index 18ef9a38e2..522db6bc7b 100644 --- a/tests/unit/backend/electron/fileHelper.node.spec.ts +++ b/tests/unit/backend/electron/fileHelper.node.spec.ts @@ -32,8 +32,8 @@ describe("writeFileSafely", () => { }); test("存在しないディレクトリに書き込もうとするとエラー", async () => { - const nonExistentDir = path.join(tmpDir, uuid4(), "subdir"); + const nonExistentDir = path.join(tmpDir, uuid4(), "not-exist"); const filePath = path.join(nonExistentDir, "test.txt"); - await expect(writeFileSafely(filePath, "data")).rejects.toThrow(); + expect(() => writeFileSafely(filePath, "data")).toThrow(); }); }); From ff477bf8415b51566595980cd1be5884f1d53ac9 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Fri, 24 Jan 2025 22:42:56 +0900 Subject: [PATCH 3/3] =?UTF-8?q?test:=20writeFileSafely=E9=96=A2=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=83=AA=E3=83=B3=E3=82=B0=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/backend/electron/fileHelper.node.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit/backend/electron/fileHelper.node.spec.ts b/tests/unit/backend/electron/fileHelper.node.spec.ts index 522db6bc7b..2530da26c0 100644 --- a/tests/unit/backend/electron/fileHelper.node.spec.ts +++ b/tests/unit/backend/electron/fileHelper.node.spec.ts @@ -36,4 +36,10 @@ describe("writeFileSafely", () => { const filePath = path.join(nonExistentDir, "test.txt"); expect(() => writeFileSafely(filePath, "data")).toThrow(); }); + + test("指定したパスにディレクトリが存在するとエラー", async () => { + const filePath = path.join(tmpDir, uuid4()); + fs.mkdirSync(filePath); + expect(() => writeFileSafely(filePath, "data")).toThrow(); + }); });