From b6e592b36be09733728c6482b460324416480bb2 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Sat, 5 Aug 2023 10:44:11 -0400 Subject: [PATCH] feat: PathRef - renameToDir --- src/path.test.ts | 29 +++++++++++++++++++++++++++++ src/path.ts | 28 ++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/path.test.ts b/src/path.test.ts index c80a634..1e9d9d9 100644 --- a/src/path.test.ts +++ b/src/path.test.ts @@ -708,6 +708,35 @@ Deno.test("rename", async () => { }); }); +Deno.test("renameToDir", async () => { + await withTempDir(async () => { + const path = createPathRef("file.txt") + .writeTextSync("text"); + const dir = createPathRef("dir").mkdirSync(); + const newPath = await path.renameToDir(dir); + assert(!path.existsSync()); + assert(newPath.existsSync()); + assertEquals(dir.join("file.txt").toString(), newPath.toString()); + assertEquals(newPath.readTextSync(), "text"); + const dir2 = createPathRef("dir2").mkdirSync(); + const newPath2 = newPath.renameToDirSync(dir2); + assert(!newPath.existsSync()); + assert(newPath2.existsSync()); + assertEquals(newPath2.readTextSync(), "text"); + assertEquals(newPath2.toString(), dir2.join("file.txt").toString()); + + // now try a directory + await dir2.renameToDir(dir); + assert(dir.join("dir2").join("file.txt").existsSync()); + + // try a directory sync + const subDir = dir.join("subdir"); + subDir.mkdirSync(); + dir.join("dir2").renameToDirSync(subDir); + assert(subDir.join("dir2").join("file.txt").existsSync()); + }); +}); + Deno.test("pipeTo", async () => { await withTempDir(async () => { const largeText = "asdf".repeat(100_000); diff --git a/src/path.ts b/src/path.ts index 7f00ca9..c63cb3d 100644 --- a/src/path.ts +++ b/src/path.ts @@ -268,12 +268,12 @@ export class PathRef { return stdPath.relative(this.resolve().#path, toPathRef.resolve().#path); } - /** Gets if the path exists. Beaware of TOCTOU issues. */ + /** Gets if the path exists. Beware of TOCTOU issues. */ exists(): Promise { return this.lstat().then((info) => info != null); } - /** Synchronously gets if the path exists. Beaware of TOCTOU issues. */ + /** Synchronously gets if the path exists. Beware of TOCTOU issues. */ existsSync(): boolean { return this.lstatSync() != null; } @@ -842,7 +842,7 @@ export class PathRef { } /** - * Renames the file or directory returning a promise that resolves to + * Moves the file or directory returning a promise that resolves to * the renamed path. */ rename(newPath: string | URL | PathRef): Promise { @@ -851,7 +851,7 @@ export class PathRef { } /** - * Renames the file or directory returning a promise that resolves to + * Moves the file or directory returning a promise that resolves to * the renamed path synchronously. */ renameSync(newPath: string | URL | PathRef): PathRef { @@ -860,6 +860,26 @@ export class PathRef { return pathRef; } + /** + * Moves the file or directory to the specified directory. + * @returns The destination file path. + */ + renameToDir(destinationDirPath: string | URL | PathRef): Promise { + const destinationPath = ensurePathRef(destinationDirPath) + .join(this.basename()); + return this.rename(destinationPath); + } + + /** + * Moves the file or directory to the specified directory synchronously. + * @returns The destination file path. + */ + renameToDirSync(destinationDirPath: string | URL | PathRef): PathRef { + const destinationPath = ensurePathRef(destinationDirPath) + .join(this.basename()); + return this.renameSync(destinationPath); + } + /** Opens the file and pipes it to the writable stream. */ async pipeTo(dest: WritableStream, options?: PipeOptions): Promise { const file = await Deno.open(this.#path, { read: true });