diff --git a/cli/tests/unit/utime_test.ts b/cli/tests/unit/utime_test.ts index 48f4f405ab..5101cb376f 100644 --- a/cli/tests/unit/utime_test.ts +++ b/cli/tests/unit/utime_test.ts @@ -27,6 +27,27 @@ Deno.test( }, ); +Deno.test( + { permissions: { read: true, write: true } }, + async function fsFileUtimeSyncSuccess() { + const testDir = await Deno.makeTempDir(); + const filename = testDir + "/file.txt"; + using file = await Deno.open(filename, { + create: true, + write: true, + }); + + const atime = 1000; + const mtime = 50000; + await file.utime(atime, mtime); + await file.dataSync(); + + const fileInfo = Deno.statSync(filename); + assertEquals(fileInfo.atime, new Date(atime * 1000)); + assertEquals(fileInfo.mtime, new Date(mtime * 1000)); + }, +); + Deno.test( { permissions: { read: true, write: true } }, function futimeSyncSuccess() { @@ -48,6 +69,27 @@ Deno.test( }, ); +Deno.test( + { permissions: { read: true, write: true } }, + function futimeSyncSuccess() { + const testDir = Deno.makeTempDirSync(); + const filename = testDir + "/file.txt"; + using file = Deno.openSync(filename, { + create: true, + write: true, + }); + + const atime = 1000; + const mtime = 50000; + file.utimeSync(atime, mtime); + file.dataSyncSync(); + + const fileInfo = Deno.statSync(filename); + assertEquals(fileInfo.atime, new Date(atime * 1000)); + assertEquals(fileInfo.mtime, new Date(mtime * 1000)); + }, +); + Deno.test( { permissions: { read: true, write: true } }, function utimeSyncFileSuccess() { diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index ff37abb84d..175276b66c 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -2632,6 +2632,32 @@ declare namespace Deno { * @category I/O */ dataSyncSync(): void; + /** + * Changes the access (`atime`) and modification (`mtime`) times of the + * file stream resource. Given times are either in seconds (UNIX epoch + * time) or as `Date` objects. + * + * ```ts + * using file = await Deno.open("file.txt", { create: true, write: true }); + * await file.utime(1556495550, new Date()); + * ``` + * + * @category File System + */ + utime(atime: number | Date, mtime: number | Date): Promise; + /** + * Synchronously changes the access (`atime`) and modification (`mtime`) + * times of the file stream resource. Given times are either in seconds + * (UNIX epoch time) or as `Date` objects. + * + * ```ts + * using file = Deno.openSync("file.txt", { create: true, write: true }); + * file.utime(1556495550, new Date()); + * ``` + * + * @category File System + */ + utimeSync(atime: number | Date, mtime: number | Date): void; /** Close the file. Closing a file when you are finished with it is * important to avoid leaking resources. * @@ -5379,6 +5405,9 @@ declare namespace Deno { * Deno.futimeSync(file.rid, 1556495550, new Date()); * ``` * + * @deprecated Use {@linkcode Deno.FsFile.utimeSync} instead. + * {@linkcode Deno.futimeSync} will be removed in Deno 2.0. + * * @category File System */ export function futimeSync( @@ -5397,6 +5426,9 @@ declare namespace Deno { * await Deno.futime(file.rid, 1556495550, new Date()); * ``` * + * @deprecated Use {@linkcode Deno.FsFile.utime} instead. + * {@linkcode Deno.futime} will be removed in Deno 2.0. + * * @category File System */ export function futime( diff --git a/ext/fs/30_fs.js b/ext/fs/30_fs.js index 8100899505..2136d88f65 100644 --- a/ext/fs/30_fs.js +++ b/ext/fs/30_fs.js @@ -752,6 +752,14 @@ class FsFile { op_fs_fsync_sync(this.#rid); } + async utime(atime, mtime) { + await futime(this.#rid, atime, mtime); + } + + utimeSync(atime, mtime) { + futimeSync(this.#rid, atime, mtime); + } + [SymbolDispose]() { core.tryClose(this.#rid); } diff --git a/ext/node/polyfills/_fs/_fs_futimes.ts b/ext/node/polyfills/_fs/_fs_futimes.ts index 8a29db26b3..9bd41e114f 100644 --- a/ext/node/polyfills/_fs/_fs_futimes.ts +++ b/ext/node/polyfills/_fs/_fs_futimes.ts @@ -4,6 +4,7 @@ // deno-lint-ignore-file prefer-primordials import type { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts"; +import { FsFile } from "ext:deno_fs/30_fs.js"; function getValidTime( time: number | string | Date, @@ -38,7 +39,8 @@ export function futimes( atime = getValidTime(atime, "atime"); mtime = getValidTime(mtime, "mtime"); - Deno.futime(fd, atime, mtime).then(() => callback(null), callback); + // TODO(@littledivy): Treat `fd` as real file descriptor. + new FsFile(fd).utime(atime, mtime).then(() => callback(null), callback); } export function futimesSync( @@ -49,5 +51,6 @@ export function futimesSync( atime = getValidTime(atime, "atime"); mtime = getValidTime(mtime, "mtime"); - Deno.futimeSync(fd, atime, mtime); + // TODO(@littledivy): Treat `fd` as real file descriptor. + new FsFile(fd).utimeSync(atime, mtime); } diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 72ba0c8d15..638e7afe70 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -108,8 +108,22 @@ const denoNs = { ); return fs.ftruncate(rid, len); }, - futime: fs.futime, - futimeSync: fs.futimeSync, + async futime(rid, atime, mtime) { + internals.warnOnDeprecatedApi( + "Deno.futime()", + new Error().stack, + "Use `Deno.FsFile.utime()` instead.", + ); + await fs.futime(rid, atime, mtime); + }, + futimeSync(rid, atime, mtime) { + internals.warnOnDeprecatedApi( + "Deno.futimeSync()", + new Error().stack, + "Use `Deno.FsFile.utimeSync()` instead.", + ); + fs.futimeSync(rid, atime, mtime); + }, errors: errors.errors, inspect: console.inspect, env: os.env,