diff options
author | Casper Beyer <caspervonb@pm.me> | 2020-09-01 02:29:43 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-31 14:29:43 -0400 |
commit | 32de714dc72ad865a625d417cf7af95dbc31b798 (patch) | |
tree | a1e74c4c4d9fe32519598fa788f3f4ac496c61a4 /cli | |
parent | c82c3b982edfaade0b64119bb00183966b8ab749 (diff) |
feat(unstable): add Deno.futime and Deno.futimeSync (#7266)
Diffstat (limited to 'cli')
-rw-r--r-- | cli/Cargo.toml | 1 | ||||
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 34 | ||||
-rw-r--r-- | cli/ops/fs.rs | 65 | ||||
-rw-r--r-- | cli/rt/30_fs.js | 28 | ||||
-rw-r--r-- | cli/rt/90_deno_ns.js | 2 | ||||
-rw-r--r-- | cli/tests/unit/utime_test.ts | 44 | ||||
-rw-r--r-- | cli/tsc/99_main_compiler.js | 2 |
7 files changed, 176 insertions, 0 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml index e0f75da15..7c8414e55 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -42,6 +42,7 @@ dlopen = "0.1.8" encoding_rs = "0.8.23" dprint-plugin-typescript = "0.30.2" futures = "0.3.5" +filetime = "0.2.12" http = "0.2.1" idna = "0.2.0" indexmap = "1.5.1" diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 14079f300..9c5590f97 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1247,6 +1247,40 @@ declare namespace Deno { export function createHttpClient( options: CreateHttpClientOptions, ): HttpClient; + + /** **UNSTABLE**: needs investigation into high precision time. + * + * Synchronously changes the access (`atime`) and modification (`mtime`) times + * of a file stream resource referenced by `rid`. Given times are either in + * seconds (UNIX epoch time) or as `Date` objects. + * + * ```ts + * const file = Deno.openSync("file.txt", { create: true }); + * Deno.futimeSync(file.rid, 1556495550, new Date()); + * ``` + */ + export function futimeSync( + rid: number, + atime: number | Date, + mtime: number | Date, + ): void; + + /** **UNSTABLE**: needs investigation into high precision time. + * + * Changes the access (`atime`) and modification (`mtime`) times of a file + * stream resource referenced by `rid`. Given times are either in seconds + * (UNIX epoch time) or as `Date` objects. + * + * ```ts + * const file = await Deno.open("file.txt", { create: true }); + * await Deno.futime(file.rid, 1556495550, new Date()); + * ``` + */ + export function futime( + rid: number, + atime: number | Date, + mtime: number | Date, + ): Promise<void>; } declare function fetch( diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs index 3b8946057..794518e2c 100644 --- a/cli/ops/fs.rs +++ b/cli/ops/fs.rs @@ -174,6 +174,12 @@ pub fn init(i: &mut CoreIsolate, s: &Rc<State>) { i.register_op("op_cwd", s.stateful_json_op_sync(t, op_cwd)); + i.register_op("op_futime_sync", s.stateful_json_op_sync(t, op_futime_sync)); + i.register_op( + "op_futime_async", + s.stateful_json_op_async(t, op_futime_async), + ); + i.register_op("op_utime_sync", s.stateful_json_op_sync(t, op_utime_sync)); i.register_op( "op_utime_async", @@ -1675,6 +1681,65 @@ async fn op_make_temp_file_async( #[derive(Deserialize)] #[serde(rename_all = "camelCase")] +struct FutimeArgs { + rid: i32, + atime: i64, + mtime: i64, +} + +fn op_futime_sync( + state: &State, + resource_table: &mut ResourceTable, + args: Value, + _zero_copy: &mut [ZeroCopyBuf], +) -> Result<Value, ErrBox> { + state.check_unstable("Deno.futimeSync"); + let args: FutimeArgs = serde_json::from_value(args)?; + let rid = args.rid as u32; + let atime = filetime::FileTime::from_unix_time(args.atime, 0); + let mtime = filetime::FileTime::from_unix_time(args.mtime, 0); + + std_file_resource(resource_table, rid, |r| match r { + Ok(std_file) => { + filetime::set_file_handle_times(std_file, Some(atime), Some(mtime)) + .map_err(ErrBox::from) + } + Err(_) => Err(ErrBox::type_error( + "cannot futime on this type of resource".to_string(), + )), + })?; + + Ok(json!({})) +} + +async fn op_futime_async( + state: Rc<State>, + resource_table: Rc<RefCell<ResourceTable>>, + args: Value, + _zero_copy: BufVec, +) -> Result<Value, ErrBox> { + state.check_unstable("Deno.futime"); + let args: FutimeArgs = serde_json::from_value(args)?; + let rid = args.rid as u32; + let atime = filetime::FileTime::from_unix_time(args.atime, 0); + let mtime = filetime::FileTime::from_unix_time(args.mtime, 0); + + let mut resource_table = resource_table.borrow_mut(); + std_file_resource(&mut resource_table, rid, |r| match r { + Ok(std_file) => { + filetime::set_file_handle_times(std_file, Some(atime), Some(mtime)) + .map_err(ErrBox::from) + } + Err(_) => Err(ErrBox::type_error( + "cannot futime on this type of resource".to_string(), + )), + })?; + + Ok(json!({})) +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] struct UtimeArgs { path: String, atime: i64, diff --git a/cli/rt/30_fs.js b/cli/rt/30_fs.js index d8171bdac..750c3c1ba 100644 --- a/cli/rt/30_fs.js +++ b/cli/rt/30_fs.js @@ -268,6 +268,32 @@ return v instanceof Date ? Math.trunc(v.valueOf() / 1000) : v; } + function futimeSync( + rid, + atime, + mtime, + ) { + sendSync("op_futime_sync", { + rid, + // TODO(caspervonb) split atime, mtime into [seconds, nanoseconds] tuple + atime: toSecondsFromEpoch(atime), + mtime: toSecondsFromEpoch(mtime), + }); + } + + async function futime( + rid, + atime, + mtime, + ) { + await sendAsync("op_futime_async", { + rid, + // TODO(caspervonb) split atime, mtime into [seconds, nanoseconds] tuple + atime: toSecondsFromEpoch(atime), + mtime: toSecondsFromEpoch(mtime), + }); + } + function utimeSync( path, atime, @@ -364,6 +390,8 @@ umask, link, linkSync, + futime, + futimeSync, utime, utimeSync, symlink, diff --git a/cli/rt/90_deno_ns.js b/cli/rt/90_deno_ns.js index ac22410f6..82acdef3c 100644 --- a/cli/rt/90_deno_ns.js +++ b/cli/rt/90_deno_ns.js @@ -118,6 +118,8 @@ __bootstrap.denoNsUnstable = { umask: __bootstrap.fs.umask, link: __bootstrap.fs.link, linkSync: __bootstrap.fs.linkSync, + futime: __bootstrap.fs.futime, + futimeSync: __bootstrap.fs.futimeSync, utime: __bootstrap.fs.utime, utimeSync: __bootstrap.fs.utimeSync, symlink: __bootstrap.fs.symlink, diff --git a/cli/tests/unit/utime_test.ts b/cli/tests/unit/utime_test.ts index cc68e90cd..185187ef4 100644 --- a/cli/tests/unit/utime_test.ts +++ b/cli/tests/unit/utime_test.ts @@ -15,6 +15,50 @@ function assertFuzzyTimestampEquals(t1: Date | null, t2: Date): void { unitTest( { perms: { read: true, write: true } }, + async function futimeSyncSuccess(): Promise<void> { + const testDir = await Deno.makeTempDir(); + const filename = testDir + "/file.txt"; + const file = await Deno.open(filename, { + create: true, + write: true, + }); + + const atime = 1000; + const mtime = 50000; + await Deno.futime(file.rid, atime, mtime); + await Deno.fdatasync(file.rid); + + const fileInfo = Deno.statSync(filename); + assertFuzzyTimestampEquals(fileInfo.atime, new Date(atime * 1000)); + assertFuzzyTimestampEquals(fileInfo.mtime, new Date(mtime * 1000)); + file.close(); + }, +); + +unitTest( + { perms: { read: true, write: true } }, + function futimeSyncSuccess(): void { + const testDir = Deno.makeTempDirSync(); + const filename = testDir + "/file.txt"; + const file = Deno.openSync(filename, { + create: true, + write: true, + }); + + const atime = 1000; + const mtime = 50000; + Deno.futimeSync(file.rid, atime, mtime); + Deno.fdatasyncSync(file.rid); + + const fileInfo = Deno.statSync(filename); + assertFuzzyTimestampEquals(fileInfo.atime, new Date(atime * 1000)); + assertFuzzyTimestampEquals(fileInfo.mtime, new Date(mtime * 1000)); + file.close(); + }, +); + +unitTest( + { perms: { read: true, write: true } }, function utimeSyncFileSuccess(): void { const testDir = Deno.makeTempDirSync(); const filename = testDir + "/file.txt"; diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index 79af46e31..aa334907a 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -86,6 +86,8 @@ delete Object.prototype.__proto__; "fdatasync", "fdatasyncSync", "formatDiagnostics", + "futime", + "futimeSync", "fstat", "fstatSync", "fsync", |