Skip to content

feat(fs/unstable): add utime and utimeSync #6446

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _tools/check_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const ENTRY_POINTS = [
"../fs/unstable_symlink.ts",
"../fs/unstable_truncate.ts",
"../fs/unstable_types.ts",
"../fs/unstable_utime.ts",
"../html/mod.ts",
"../html/unstable_is_valid_custom_element_name.ts",
"../http/mod.ts",
Expand Down
1 change: 1 addition & 0 deletions _tools/node_test_runner/run_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import "../../fs/unstable_symlink_test.ts";
import "../../fs/unstable_truncate_test.ts";
import "../../fs/unstable_lstat_test.ts";
import "../../fs/unstable_chmod_test.ts";
import "../../fs/unstable_utime_test.ts";

for (const testDef of testDefinitions) {
test(testDef.name, testDef.fn);
Expand Down
1 change: 1 addition & 0 deletions fs/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"./unstable-real-path": "./unstable_real_path.ts",
"./unstable-rename": "./unstable_rename.ts",
"./unstable-stat": "./unstable_stat.ts",
"./unstable-utime": "./unstable_utime.ts",
"./unstable-symlink": "./unstable_symlink.ts",
"./unstable-truncate": "./unstable_truncate.ts",
"./unstable-types": "./unstable_types.ts",
Expand Down
95 changes: 95 additions & 0 deletions fs/unstable_utime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2018-2025 the Deno authors. MIT license.

import { getNodeFs, isDeno } from "./_utils.ts";
import { mapError } from "./_map_error.ts";

/** Changes the access (`atime`) and modification (`mtime`) times of a file
* system object referenced by `path`. Given times are either in seconds
* (UNIX epoch time) or as `Date` objects.
*
* Requires `allow-write` permission for the target path
*
* @example Usage
*
* ```ts
* import { assert } from "@std/assert"
* import { utime } from "@std/fs/unstable-utime";
* import { stat } from "@std/fs/unstable-stat"
*
* const newAccessDate = new Date()
* const newModifiedDate = new Date()
*
* const fileBefore = await Deno.stat("README.md")
* await Deno.utime("README.md", newAccessDate, newModifiedDate)
* const fileAfter = await Deno.stat("README.md")
*
* assert(fileBefore.atime !== fileAfter.atime)
* assert(fileBefore.mtime !== fileAfter.mtime)
* ```
* @tags allow-write
* @category File System
* @param path The path to the file to be updated
* @param atime The new access time
* @param mtime The new modification time
*/
export async function utime(
path: string | URL,
atime: number | Date,
mtime: number | Date,
): Promise<void> {
if (isDeno) {
await Deno.utime(path, atime, mtime);
} else {
try {
await getNodeFs().promises.utimes(path, atime, mtime);
return;
} catch (error) {
throw mapError(error);
}
}

Check warning on line 49 in fs/unstable_utime.ts

View check run for this annotation

Codecov / codecov/patch

fs/unstable_utime.ts#L43-L49

Added lines #L43 - L49 were not covered by tests
}

/** 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.
*
* Requires `allow-write` permission for the target path
*
* @example Usage
*
* ```ts
* import { assert } from "@std/assert"
* import { utimeSync } from "@std/fs/unstable-utime";
* import { stat } from "@std/fs/unstable-stat"
*
* const newAccessDate = new Date()
* const newModifiedDate = new Date()
*
* const fileBefore = await Deno.stat("README.md")
* Deno.utimeSync("README.md", newAccessDate, newModifiedDate)
* const fileAfter = await Deno.stat("README.md")
*
* assert(fileBefore.atime !== fileAfter.atime)
* assert(fileBefore.mtime !== fileAfter.mtime)
* ```
* @tags allow-write
* @category File System
* @param path The path to the file to be updated
* @param atime The new access time
* @param mtime The new modification time
*/
export function utimeSync(
path: string | URL,
atime: number | Date,
mtime: number | Date,
): void {
if (isDeno) {
return Deno.utimeSync(path, atime, mtime);
} else {
try {
getNodeFs().utimesSync(path, atime, mtime);
} catch (error) {
throw mapError(error);
}
}

Check warning on line 94 in fs/unstable_utime.ts

View check run for this annotation

Codecov / codecov/patch

fs/unstable_utime.ts#L89-L94

Added lines #L89 - L94 were not covered by tests
}
47 changes: 47 additions & 0 deletions fs/unstable_utime_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2018-2025 the Deno authors. MIT license.
import { assert, assertRejects, assertThrows } from "@std/assert";
import { utime, utimeSync } from "./unstable_utime.ts";
import { NotFound } from "./unstable_errors.js";

import { statSync } from "node:fs";

const now = new Date();
const filePath = "fs/testdata/copy_file.txt";

Deno.test("utime() change atime and mtime date", async () => {
const fileBefore = statSync(filePath);

await utime(filePath, now, now);

const fileAfter = statSync(filePath);

assert(fileBefore.atime != fileAfter.atime);
assert(fileBefore.mtime != fileAfter.mtime);
});

Deno.test("utime() fail on NotFound file", async () => {
const randomFile = "foo.txt";

await assertRejects(async () => {
await utime(randomFile, now, now);
}, NotFound);
});

Deno.test("utimeSync() change atime and mtime data", () => {
const fileBefore = statSync(filePath);

utimeSync(filePath, now, now);

const fileAfter = statSync(filePath);

assert(fileBefore.atime != fileAfter.atime);
assert(fileBefore.mtime != fileAfter.mtime);
});

Deno.test("utimeSync() fail on NotFound file", () => {
const randomFile = "foo.txt";

assertThrows(() => {
utimeSync(randomFile, now, now);
}, NotFound);
});
Loading