summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/js/lib.deno.ns.d.ts10
-rw-r--r--cli/js/ops/fs/stat.ts18
-rw-r--r--cli/js/tests/stat_test.ts81
-rw-r--r--cli/js/tests/utime_test.ts68
-rw-r--r--cli/ops/fs.rs31
5 files changed, 111 insertions, 97 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 9813b11fb..7a0477682 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -1316,15 +1316,15 @@ declare namespace Deno {
/** The last modification time of the file. This corresponds to the `mtime`
* field from `stat` on Linux/Mac OS and `ftLastWriteTime` on Windows. This
* may not be available on all platforms. */
- modified: number | null;
+ mtime: Date | null;
/** The last access time of the file. This corresponds to the `atime`
* field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not
* be available on all platforms. */
- accessed: number | null;
+ atime: Date | null;
/** The creation time of the file. This corresponds to the `birthtime`
- * field from `stat` on Mac/BSD and `ftCreationTime` on Windows. This may not
- * be available on all platforms. */
- created: number | null;
+ * field from `stat` on Mac/BSD and `ftCreationTime` on Windows. This may
+ * not be available on all platforms. */
+ birthtime: Date | null;
/** ID of the device containing the file.
*
* _Linux/Mac OS only._ */
diff --git a/cli/js/ops/fs/stat.ts b/cli/js/ops/fs/stat.ts
index 6b7e5ea93..7f28614d2 100644
--- a/cli/js/ops/fs/stat.ts
+++ b/cli/js/ops/fs/stat.ts
@@ -4,9 +4,9 @@ import { build } from "../../build.ts";
export interface FileInfo {
size: number;
- modified: number | null;
- accessed: number | null;
- created: number | null;
+ mtime: Date | null;
+ atime: Date | null;
+ birthtime: Date | null;
dev: number | null;
ino: number | null;
mode: number | null;
@@ -26,9 +26,9 @@ export interface StatResponse {
isDirectory: boolean;
isSymlink: boolean;
size: number;
- modified: number;
- accessed: number;
- created: number;
+ mtime: number | null;
+ atime: number | null;
+ birthtime: number | null;
// Null for stat(), but exists for readdir().
name: string | null;
// Unix only members
@@ -51,9 +51,9 @@ export function parseFileInfo(response: StatResponse): FileInfo {
isDirectory: response.isDirectory,
isSymlink: response.isSymlink,
size: response.size,
- modified: response.modified ? response.modified : null,
- accessed: response.accessed ? response.accessed : null,
- created: response.created ? response.created : null,
+ mtime: response.mtime != null ? new Date(response.mtime) : null,
+ atime: response.atime != null ? new Date(response.atime) : null,
+ birthtime: response.birthtime != null ? new Date(response.birthtime) : null,
// Only non-null if on Unix
dev: isUnix ? response.dev : null,
ino: isUnix ? response.ino : null,
diff --git a/cli/js/tests/stat_test.ts b/cli/js/tests/stat_test.ts
index e4f4ae61e..70ec5dc2e 100644
--- a/cli/js/tests/stat_test.ts
+++ b/cli/js/tests/stat_test.ts
@@ -1,21 +1,31 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { unitTest, assert, assertEquals } from "./test_util.ts";
-// TODO Add tests for modified, accessed, and created fields once there is a way
-// to create temp files.
-unitTest({ perms: { read: true } }, function statSyncSuccess(): void {
- const packageInfo = Deno.statSync("README.md");
- assert(packageInfo.isFile);
- assert(!packageInfo.isSymlink);
-
- const modulesInfo = Deno.statSync("cli/tests/symlink_to_subdir");
- assert(modulesInfo.isDirectory);
- assert(!modulesInfo.isSymlink);
-
- const testsInfo = Deno.statSync("cli/tests");
- assert(testsInfo.isDirectory);
- assert(!testsInfo.isSymlink);
-});
+unitTest(
+ { perms: { read: true, write: true } },
+ function statSyncSuccess(): void {
+ const packageInfo = Deno.statSync("README.md");
+ assert(packageInfo.isFile);
+ assert(!packageInfo.isSymlink);
+
+ const modulesInfo = Deno.statSync("cli/tests/symlink_to_subdir");
+ assert(modulesInfo.isDirectory);
+ assert(!modulesInfo.isSymlink);
+
+ const testsInfo = Deno.statSync("cli/tests");
+ assert(testsInfo.isDirectory);
+ assert(!testsInfo.isSymlink);
+
+ const tempFile = Deno.makeTempFileSync();
+ const tempInfo = Deno.statSync(tempFile);
+ const now = Date.now();
+ assert(tempInfo.atime !== null && now - tempInfo.atime.valueOf() < 1000);
+ assert(tempInfo.mtime !== null && now - tempInfo.mtime.valueOf() < 1000);
+ assert(
+ tempInfo.birthtime === null || now - tempInfo.birthtime.valueOf() < 1000
+ );
+ }
+);
unitTest({ perms: { read: false } }, function statSyncPerm(): void {
let caughtError = false;
@@ -83,21 +93,32 @@ unitTest({ perms: { read: true } }, function lstatSyncNotFound(): void {
assertEquals(badInfo, undefined);
});
-unitTest({ perms: { read: true } }, async function statSuccess(): Promise<
- void
-> {
- const packageInfo = await Deno.stat("README.md");
- assert(packageInfo.isFile);
- assert(!packageInfo.isSymlink);
-
- const modulesInfo = await Deno.stat("cli/tests/symlink_to_subdir");
- assert(modulesInfo.isDirectory);
- assert(!modulesInfo.isSymlink);
-
- const testsInfo = await Deno.stat("cli/tests");
- assert(testsInfo.isDirectory);
- assert(!testsInfo.isSymlink);
-});
+unitTest(
+ { perms: { read: true, write: true } },
+ async function statSuccess(): Promise<void> {
+ const packageInfo = await Deno.stat("README.md");
+ assert(packageInfo.isFile);
+ assert(!packageInfo.isSymlink);
+
+ const modulesInfo = await Deno.stat("cli/tests/symlink_to_subdir");
+ assert(modulesInfo.isDirectory);
+ assert(!modulesInfo.isSymlink);
+
+ const testsInfo = await Deno.stat("cli/tests");
+ assert(testsInfo.isDirectory);
+ assert(!testsInfo.isSymlink);
+
+ const tempFile = await Deno.makeTempFile();
+ const tempInfo = await Deno.stat(tempFile);
+ const now = Date.now();
+ assert(tempInfo.atime !== null && now - tempInfo.atime.valueOf() < 1000);
+ assert(tempInfo.mtime !== null && now - tempInfo.mtime.valueOf() < 1000);
+
+ assert(
+ tempInfo.birthtime === null || now - tempInfo.birthtime.valueOf() < 1000
+ );
+ }
+);
unitTest({ perms: { read: false } }, async function statPerm(): Promise<void> {
let caughtError = false;
diff --git a/cli/js/tests/utime_test.ts b/cli/js/tests/utime_test.ts
index a81600e54..63727ae62 100644
--- a/cli/js/tests/utime_test.ts
+++ b/cli/js/tests/utime_test.ts
@@ -4,9 +4,9 @@ import { unitTest, assert } from "./test_util.ts";
// Allow 10 second difference.
// Note this might not be enough for FAT (but we are not testing on such fs).
// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function assertFuzzyTimestampEquals(t1: any, t2: number): void {
- assert(typeof t1 === "number");
- assert(Math.abs(t1 - t2) < 10);
+function assertFuzzyTimestampEquals(t1: Date | null, t2: Date): void {
+ assert(t1 instanceof Date);
+ assert(Math.abs(t1.valueOf() - t2.valueOf()) < 10_000);
}
unitTest(
@@ -23,8 +23,8 @@ unitTest(
Deno.utimeSync(filename, atime, mtime);
const fileInfo = Deno.statSync(filename);
- assertFuzzyTimestampEquals(fileInfo.accessed, atime);
- assertFuzzyTimestampEquals(fileInfo.modified, mtime);
+ assertFuzzyTimestampEquals(fileInfo.atime, new Date(atime * 1000));
+ assertFuzzyTimestampEquals(fileInfo.mtime, new Date(mtime * 1000));
}
);
@@ -38,8 +38,8 @@ unitTest(
Deno.utimeSync(testDir, atime, mtime);
const dirInfo = Deno.statSync(testDir);
- assertFuzzyTimestampEquals(dirInfo.accessed, atime);
- assertFuzzyTimestampEquals(dirInfo.modified, mtime);
+ assertFuzzyTimestampEquals(dirInfo.atime, new Date(atime * 1000));
+ assertFuzzyTimestampEquals(dirInfo.mtime, new Date(mtime * 1000));
}
);
@@ -48,13 +48,13 @@ unitTest(
function utimeSyncDateSuccess(): void {
const testDir = Deno.makeTempDirSync();
- const atime = 1000;
- const mtime = 50000;
- Deno.utimeSync(testDir, new Date(atime * 1000), new Date(mtime * 1000));
+ const atime = new Date(1000_000);
+ const mtime = new Date(50000_000);
+ Deno.utimeSync(testDir, atime, mtime);
const dirInfo = Deno.statSync(testDir);
- assertFuzzyTimestampEquals(dirInfo.accessed, atime);
- assertFuzzyTimestampEquals(dirInfo.modified, mtime);
+ assertFuzzyTimestampEquals(dirInfo.atime, atime);
+ assertFuzzyTimestampEquals(dirInfo.mtime, mtime);
}
);
@@ -71,15 +71,8 @@ unitTest(
Deno.utimeSync(filename, atime, mtime);
const fileInfo = Deno.statSync(filename);
- // atime and mtime must be scaled by a factor of 1000 to be recorded in seconds
- assertFuzzyTimestampEquals(
- fileInfo.accessed,
- Math.trunc(atime.valueOf() / 1000)
- );
- assertFuzzyTimestampEquals(
- fileInfo.modified,
- Math.trunc(mtime.valueOf() / 1000)
- );
+ assertFuzzyTimestampEquals(fileInfo.atime, atime);
+ assertFuzzyTimestampEquals(fileInfo.mtime, mtime);
}
);
@@ -95,8 +88,8 @@ unitTest(
Deno.utimeSync(testDir, atime, mtime);
const dirInfo = Deno.statSync(testDir);
- assertFuzzyTimestampEquals(dirInfo.accessed, atime);
- assertFuzzyTimestampEquals(dirInfo.modified, mtime);
+ assertFuzzyTimestampEquals(dirInfo.atime, new Date(atime * 1000));
+ assertFuzzyTimestampEquals(dirInfo.mtime, new Date(mtime * 1000));
}
);
@@ -148,8 +141,8 @@ unitTest(
await Deno.utime(filename, atime, mtime);
const fileInfo = Deno.statSync(filename);
- assertFuzzyTimestampEquals(fileInfo.accessed, atime);
- assertFuzzyTimestampEquals(fileInfo.modified, mtime);
+ assertFuzzyTimestampEquals(fileInfo.atime, new Date(atime * 1000));
+ assertFuzzyTimestampEquals(fileInfo.mtime, new Date(mtime * 1000));
}
);
@@ -163,8 +156,8 @@ unitTest(
await Deno.utime(testDir, atime, mtime);
const dirInfo = Deno.statSync(testDir);
- assertFuzzyTimestampEquals(dirInfo.accessed, atime);
- assertFuzzyTimestampEquals(dirInfo.modified, mtime);
+ assertFuzzyTimestampEquals(dirInfo.atime, new Date(atime * 1000));
+ assertFuzzyTimestampEquals(dirInfo.mtime, new Date(mtime * 1000));
}
);
@@ -173,13 +166,13 @@ unitTest(
async function utimeDateSuccess(): Promise<void> {
const testDir = Deno.makeTempDirSync();
- const atime = 1000;
- const mtime = 50000;
- await Deno.utime(testDir, new Date(atime * 1000), new Date(mtime * 1000));
+ const atime = new Date(100_000);
+ const mtime = new Date(5000_000);
+ await Deno.utime(testDir, atime, mtime);
const dirInfo = Deno.statSync(testDir);
- assertFuzzyTimestampEquals(dirInfo.accessed, atime);
- assertFuzzyTimestampEquals(dirInfo.modified, mtime);
+ assertFuzzyTimestampEquals(dirInfo.atime, atime);
+ assertFuzzyTimestampEquals(dirInfo.mtime, mtime);
}
);
@@ -197,15 +190,8 @@ unitTest(
await Deno.utime(filename, atime, mtime);
const fileInfo = Deno.statSync(filename);
- // The dates must be scaled by a factored of 1000 to make them seconds
- assertFuzzyTimestampEquals(
- fileInfo.accessed,
- Math.trunc(atime.valueOf() / 1000)
- );
- assertFuzzyTimestampEquals(
- fileInfo.modified,
- Math.trunc(mtime.valueOf() / 1000)
- );
+ assertFuzzyTimestampEquals(fileInfo.atime, atime);
+ assertFuzzyTimestampEquals(fileInfo.mtime, mtime);
}
);
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index 5ab534810..84ac4ed51 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -12,7 +12,9 @@ use deno_core::ZeroCopyBuf;
use futures::future::FutureExt;
use std::convert::From;
use std::env::{current_dir, set_current_dir, temp_dir};
+use std::io;
use std::path::{Path, PathBuf};
+use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use rand::{thread_rng, Rng};
@@ -441,14 +443,19 @@ fn op_copy_file(
})
}
-macro_rules! to_seconds {
- ($time:expr) => {{
- // Unwrap is safe here as if the file is before the unix epoch
- // something is very wrong.
- $time
- .and_then(|t| Ok(t.duration_since(UNIX_EPOCH).unwrap().as_secs()))
- .unwrap_or(0)
- }};
+fn to_msec(maybe_time: Result<SystemTime, io::Error>) -> serde_json::Value {
+ match maybe_time {
+ Ok(time) => {
+ let msec = time
+ .duration_since(UNIX_EPOCH)
+ .map(|t| t.as_secs_f64() * 1000f64)
+ .unwrap_or_else(|err| err.duration().as_secs_f64() * -1000f64);
+ serde_json::Number::from_f64(msec)
+ .map(serde_json::Value::Number)
+ .unwrap_or(serde_json::Value::Null)
+ }
+ Err(_) => serde_json::Value::Null,
+ }
}
#[inline(always)]
@@ -477,10 +484,10 @@ fn get_stat_json(
"isDirectory": metadata.is_dir(),
"isSymlink": metadata.file_type().is_symlink(),
"size": metadata.len(),
- // In seconds. Available on both Unix or Windows.
- "modified":to_seconds!(metadata.modified()),
- "accessed":to_seconds!(metadata.accessed()),
- "created":to_seconds!(metadata.created()),
+ // In milliseconds, like JavaScript. Available on both Unix or Windows.
+ "mtime": to_msec(metadata.modified()),
+ "atime": to_msec(metadata.accessed()),
+ "birthtime": to_msec(metadata.created()),
// Following are only valid under Unix.
"dev": usm!(dev),
"ino": usm!(ino),