1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 08:33:43 -05:00

Revert "feat(std/node/fs): adding readdir, rename, and some others (#7666)" (#7917)

This reverts commit 40324ff748.
This commit is contained in:
Bartek Iwańczuk 2020-10-10 15:05:19 +02:00 committed by GitHub
parent 9e9ec9784a
commit 7af5041a06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 0 additions and 1366 deletions

View file

@ -1,59 +0,0 @@
import {
BigIntStats,
CFISBIS,
statCallback,
statCallbackBigInt,
statOptions,
Stats,
} from "./_fs_stat.ts";
export function lstat(path: string | URL, callback: statCallback): void;
export function lstat(
path: string | URL,
options: { bigint: false },
callback: statCallback,
): void;
export function lstat(
path: string | URL,
options: { bigint: true },
callback: statCallbackBigInt,
): void;
export function lstat(
path: string | URL,
optionsOrCallback: statCallback | statCallbackBigInt | statOptions,
maybeCallback?: statCallback | statCallbackBigInt,
) {
const callback =
(typeof optionsOrCallback === "function"
? optionsOrCallback
: maybeCallback) as (
err: Error | undefined,
stat: BigIntStats | Stats,
) => void;
const options = typeof optionsOrCallback === "object"
? optionsOrCallback
: { bigint: false };
if (!callback) throw new Error("No callback function supplied");
Deno.lstat(path)
.then((stat) => callback(undefined, CFISBIS(stat, options.bigint)))
.catch((err) => callback(err, err));
}
export function lstatSync(path: string | URL): Stats;
export function lstatSync(
path: string | URL,
options: { bigint: false },
): Stats;
export function lstatSync(
path: string | URL,
options: { bigint: true },
): BigIntStats;
export function lstatSync(
path: string | URL,
options?: statOptions,
): Stats | BigIntStats {
const origin = Deno.lstatSync(path);
return CFISBIS(origin, options?.bigint || false);
}

View file

@ -1,56 +0,0 @@
import { lstat, lstatSync } from "./_fs_lstat.ts";
import { fail } from "../../testing/asserts.ts";
import { assertStats, assertStatsBigInt } from "./_fs_stat_test.ts";
import type { BigIntStats, Stats } from "./_fs_stat.ts";
Deno.test({
name: "ASYNC: get a file Stats (lstat)",
async fn() {
const file = Deno.makeTempFileSync();
await new Promise<Stats>((resolve, reject) => {
lstat(file, (err, stat) => {
if (err) reject(err);
resolve(stat);
});
})
.then((stat) => {
assertStats(stat, Deno.lstatSync(file));
})
.catch(() => fail())
.finally(() => {
Deno.removeSync(file);
});
},
});
Deno.test({
name: "SYNC: get a file Stats (lstat)",
fn() {
const file = Deno.makeTempFileSync();
assertStats(lstatSync(file), Deno.lstatSync(file));
},
});
Deno.test({
name: "ASYNC: get a file BigInt Stats (lstat)",
async fn() {
const file = Deno.makeTempFileSync();
await new Promise<BigIntStats>((resolve, reject) => {
lstat(file, { bigint: true }, (err, stat) => {
if (err) reject(err);
resolve(stat);
});
})
.then((stat) => assertStatsBigInt(stat, Deno.lstatSync(file)))
.catch(() => fail())
.finally(() => Deno.removeSync(file));
},
});
Deno.test({
name: "SYNC: BigInt Stats (lstat)",
fn() {
const file = Deno.makeTempFileSync();
assertStatsBigInt(lstatSync(file, { bigint: true }), Deno.lstatSync(file));
},
});

View file

@ -1,103 +0,0 @@
import { existsSync } from "../../fs/mod.ts";
import { fromFileUrl } from "../path.ts";
import { getOpenOptions } from "./_fs_common.ts";
type openFlags =
| "a"
| "ax"
| "a+"
| "ax+"
| "as"
| "as+"
| "r"
| "r+"
| "rs+"
| "w"
| "wx"
| "w+"
| "wx+";
type openCallback = (err: Error | undefined, fd: number) => void;
function convertFlagAndModeToOptions(
flag?: openFlags,
mode?: number,
): Deno.OpenOptions | undefined {
if (!flag && !mode) return undefined;
if (!flag && mode) return { mode };
return { ...getOpenOptions(flag), mode };
}
export function open(path: string | URL, callback: openCallback): void;
export function open(
path: string | URL,
flags: openFlags,
callback: openCallback,
): void;
export function open(
path: string | URL,
flags: openFlags,
mode: number,
callback: openCallback,
): void;
export function open(
path: string | URL,
flagsOrCallback: openCallback | openFlags,
callbackOrMode?: openCallback | number,
maybeCallback?: openCallback,
) {
const flags = typeof flagsOrCallback === "string"
? flagsOrCallback
: undefined;
const callback = typeof flagsOrCallback === "function"
? flagsOrCallback
: typeof callbackOrMode === "function"
? callbackOrMode
: maybeCallback;
const mode = typeof callbackOrMode === "number" ? callbackOrMode : undefined;
path = path instanceof URL ? fromFileUrl(path) : path;
if (!callback) throw new Error("No callback function supplied");
if (["ax", "ax+", "wx", "wx+"].includes(flags || "") && existsSync(path)) {
const err = new Error(`EEXIST: file already exists, open '${path}'`);
callback(err, 0);
} else {
if (flags === "as" || flags === "as+") {
try {
const res = openSync(path, flags, mode);
callback(undefined, res);
} catch (error) {
callback(error, error);
}
return;
}
Deno.open(path, convertFlagAndModeToOptions(flags, mode))
.then((file) => callback(undefined, file.rid))
.catch((err) => callback(err, err));
}
}
export function openSync(path: string | URL): number;
export function openSync(path: string | URL, flags?: openFlags): number;
export function openSync(path: string | URL, mode?: number): number;
export function openSync(
path: string | URL,
flags?: openFlags,
mode?: number,
): number;
export function openSync(
path: string | URL,
flagsOrMode?: openFlags | number,
maybeMode?: number,
) {
const flags = typeof flagsOrMode === "string" ? flagsOrMode : undefined;
const mode = typeof flagsOrMode === "number" ? flagsOrMode : maybeMode;
path = path instanceof URL ? fromFileUrl(path) : path;
if (["ax", "ax+", "wx", "wx+"].includes(flags || "") && existsSync(path)) {
throw new Error(`EEXIST: file already exists, open '${path}'`);
}
return Deno.openSync(path, convertFlagAndModeToOptions(flags, mode)).rid;
}

View file

@ -1,217 +0,0 @@
import {
assert,
assertEquals,
assertThrows,
fail,
} from "../../testing/asserts.ts";
import { open, openSync } from "./_fs_open.ts";
import { join, parse } from "../../path/mod.ts";
import { existsSync } from "../../fs/mod.ts";
import { closeSync } from "./_fs_close.ts";
const temp_dir = parse(Deno.makeTempFileSync()).dir;
Deno.test({
name: "ASYNC: open file",
async fn() {
const file = Deno.makeTempFileSync();
let fd1: number;
await new Promise<number>((resolve, reject) => {
open(file, (err, fd) => {
if (err) reject(err);
resolve(fd);
});
})
.then((fd) => {
fd1 = fd;
assert(Deno.resources()[fd], `${fd}`);
})
.catch(() => fail())
.finally(() => closeSync(fd1));
},
});
Deno.test({
name: "SYNC: open file",
fn() {
const file = Deno.makeTempFileSync();
const fd = openSync(file);
assert(Deno.resources()[fd]);
closeSync(fd);
},
});
Deno.test({
name: "open with flag 'a'",
fn() {
const file = join(temp_dir, "some_random_file");
const fd = openSync(file, "a");
assertEquals(typeof fd, "number");
assertEquals(existsSync(file), true);
assert(Deno.resources()[fd]);
closeSync(fd);
},
});
Deno.test({
name: "open with flag 'ax'",
fn() {
const file = Deno.makeTempFileSync();
assertThrows(
() => {
openSync(file, "ax");
},
Error,
`EEXIST: file already exists, open '${file}'`,
);
Deno.removeSync(file);
},
});
Deno.test({
name: "open with flag 'a+'",
fn() {
const file = join(temp_dir, "some_random_file2");
const fd = openSync(file, "a+");
assertEquals(typeof fd, "number");
assertEquals(existsSync(file), true);
closeSync(fd);
},
});
Deno.test({
name: "open with flag 'ax+'",
fn() {
const file = Deno.makeTempFileSync();
assertThrows(
() => {
openSync(file, "ax+");
},
Error,
`EEXIST: file already exists, open '${file}'`,
);
Deno.removeSync(file);
},
});
Deno.test({
name: "open with flag 'as'",
fn() {
const file = join(temp_dir, "some_random_file10");
const fd = openSync(file, "as");
assertEquals(existsSync(file), true);
assertEquals(typeof fd, "number");
closeSync(fd);
},
});
Deno.test({
name: "open with flag 'as+'",
fn() {
const file = join(temp_dir, "some_random_file10");
const fd = openSync(file, "as+");
assertEquals(existsSync(file), true);
assertEquals(typeof fd, "number");
closeSync(fd);
},
});
Deno.test({
name: "open with flag 'r'",
fn() {
const file = join(temp_dir, "some_random_file3");
assertThrows(
() => {
openSync(file, "r");
},
Error,
"No such file or directory (os error 2)",
);
},
});
Deno.test({
name: "open with flag 'r+'",
fn() {
const file = join(temp_dir, "some_random_file4");
assertThrows(
() => {
openSync(file, "r+");
},
Error,
"No such file or directory (os error 2)",
);
},
});
Deno.test({
name: "open with flag 'w'",
fn() {
const file = Deno.makeTempFileSync();
Deno.writeTextFileSync(file, "hi there");
const fd = openSync(file, "w");
assertEquals(typeof fd, "number");
assertEquals(Deno.readTextFileSync(file), "");
closeSync(fd);
const file2 = join(temp_dir, "some_random_file5");
const fd2 = openSync(file2, "w");
assertEquals(typeof fd2, "number");
assertEquals(existsSync(file2), true);
closeSync(fd2);
},
});
Deno.test({
name: "open with flag 'wx'",
fn() {
const file = Deno.makeTempFileSync();
Deno.writeTextFileSync(file, "hi there");
const fd = openSync(file, "w");
assertEquals(typeof fd, "number");
assertEquals(Deno.readTextFileSync(file), "");
closeSync(fd);
const file2 = Deno.makeTempFileSync();
assertThrows(
() => {
openSync(file2, "wx");
},
Error,
`EEXIST: file already exists, open '${file2}'`,
);
},
});
Deno.test({
name: "open with flag 'w+'",
fn() {
const file = Deno.makeTempFileSync();
Deno.writeTextFileSync(file, "hi there");
const fd = openSync(file, "w+");
assertEquals(typeof fd, "number");
assertEquals(Deno.readTextFileSync(file), "");
closeSync(fd);
const file2 = join(temp_dir, "some_random_file6");
const fd2 = openSync(file2, "w+");
assertEquals(typeof fd2, "number");
assertEquals(existsSync(file2), true);
closeSync(fd2);
},
});
Deno.test({
name: "open with flag 'wx+'",
fn() {
const file = Deno.makeTempFileSync();
assertThrows(
() => {
openSync(file, "wx+");
},
Error,
`EEXIST: file already exists, open '${file}'`,
);
Deno.removeSync(file);
},
});

View file

@ -1,117 +0,0 @@
import { asyncIterableToCallback } from "./_fs_watch.ts";
import Dirent from "./_fs_dirent.ts";
import { fromFileUrl } from "../path.ts";
function toDirent(val: Deno.DirEntry): Dirent {
return new Dirent(val);
}
type readDirOptions = {
encoding?: string;
withFileTypes?: boolean;
};
type readDirCallback = (err: Error | undefined, files: string[]) => void;
type readDirCallbackDirent = (err: Error | undefined, files: Dirent[]) => void;
type readDirBoth = (
err: Error | undefined,
files: string[] | Dirent[] | Array<string | Dirent>,
) => void;
export function readdir(
path: string | URL,
options: { withFileTypes?: false; encoding?: string },
callback: readDirCallback,
): void;
export function readdir(
path: string | URL,
options: { withFileTypes: true; encoding?: string },
callback: readDirCallbackDirent,
): void;
export function readdir(path: string | URL, callback: readDirCallback): void;
export function readdir(
path: string | URL,
optionsOrCallback: readDirOptions | readDirCallback | readDirCallbackDirent,
maybeCallback?: readDirCallback | readDirCallbackDirent,
) {
const callback =
(typeof optionsOrCallback === "function"
? optionsOrCallback
: maybeCallback) as readDirBoth | undefined;
const options = typeof optionsOrCallback === "object"
? optionsOrCallback
: null;
const result: Array<string | Dirent> = [];
path = path instanceof URL ? fromFileUrl(path) : path;
if (!callback) throw new Error("No callback function supplied");
if (options?.encoding) {
try {
new TextDecoder(options.encoding);
} catch (error) {
throw new Error(
`TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${options.encoding}" is invalid for option "encoding"`,
);
}
}
try {
asyncIterableToCallback(Deno.readDir(path), (val, done) => {
if (typeof path !== "string") return;
if (done) {
callback(undefined, result);
return;
}
if (options?.withFileTypes) {
result.push(toDirent(val));
} else result.push(decode(val.name));
});
} catch (error) {
callback(error, result);
}
}
function decode(str: string, encoding?: string): string {
if (!encoding) return str;
else {
const decoder = new TextDecoder(encoding);
const encoder = new TextEncoder();
return decoder.decode(encoder.encode(str));
}
}
export function readdirSync(
path: string | URL,
options: { withFileTypes: true; encoding?: string },
): Dirent[];
export function readdirSync(
path: string | URL,
options?: { withFileTypes?: false; encoding?: string },
): string[];
export function readdirSync(
path: string | URL,
options?: readDirOptions,
): Array<string | Dirent> {
const result = [];
path = path instanceof URL ? fromFileUrl(path) : path;
if (options?.encoding) {
try {
new TextDecoder(options.encoding);
} catch (error) {
throw new Error(
`TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${options.encoding}" is invalid for option "encoding"`,
);
}
}
for (const file of Deno.readDirSync(path)) {
if (options?.withFileTypes) {
result.push(toDirent(file));
} else result.push(decode(file.name));
}
return result;
}

View file

@ -1,59 +0,0 @@
import { assertEquals, fail } from "../../testing/asserts.ts";
import { readdir, readdirSync } from "./_fs_readdir.ts";
import { join } from "../../path/mod.ts";
Deno.test({
name: "ASYNC: reading empty directory",
async fn() {
const dir = Deno.makeTempDirSync();
await new Promise<string[]>((resolve, reject) => {
readdir(dir, (err, files) => {
if (err) reject(err);
resolve(files);
});
})
.then((files) => assertEquals(files, []))
.catch(() => fail())
.finally(() => Deno.removeSync(dir));
},
});
Deno.test({
name: "ASYNC: reading non-empty directory",
async fn() {
const dir = Deno.makeTempDirSync();
Deno.writeTextFileSync(join(dir, "file1.txt"), "hi");
Deno.writeTextFileSync(join(dir, "file2.txt"), "hi");
Deno.mkdirSync(join(dir, "some_dir"));
await new Promise((resolve, reject) => {
readdir(dir, (err, files) => {
if (err) reject(err);
resolve(files);
});
})
.then((files) =>
assertEquals(files, ["file1.txt", "some_dir", "file2.txt"])
)
.catch(() => fail())
.finally(() => Deno.removeSync(dir, { recursive: true }));
},
});
Deno.test({
name: "SYNC: reading empty the directory",
fn() {
const dir = Deno.makeTempDirSync();
assertEquals(readdirSync(dir), []);
},
});
Deno.test({
name: "SYNC: reading a non-empty directory",
fn() {
const dir = Deno.makeTempDirSync();
Deno.writeTextFileSync(join(dir, "file1.txt"), "hi");
Deno.writeTextFileSync(join(dir, "file2.txt"), "hi");
Deno.mkdirSync(join(dir, "some_dir"));
assertEquals(readdirSync(dir), ["file1.txt", "some_dir", "file2.txt"]);
},
});

View file

@ -1,23 +0,0 @@
import { fromFileUrl } from "../path.ts";
export function rename(
oldPath: string | URL,
newPath: string | URL,
callback: (err?: Error) => void,
) {
oldPath = oldPath instanceof URL ? fromFileUrl(oldPath) : oldPath;
newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath;
if (!callback) throw new Error("No callback function supplied");
Deno.rename(oldPath, newPath)
.then((_) => callback())
.catch(callback);
}
export function renameSync(oldPath: string | URL, newPath: string | URL) {
oldPath = oldPath instanceof URL ? fromFileUrl(oldPath) : oldPath;
newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath;
Deno.renameSync(oldPath, newPath);
}

View file

@ -1,34 +0,0 @@
import { assertEquals, fail } from "../../testing/asserts.ts";
import { rename, renameSync } from "./_fs_rename.ts";
import { existsSync } from "../../fs/mod.ts";
import { join, parse } from "../../path/mod.ts";
Deno.test({
name: "ASYNC: renaming a file",
async fn() {
const file = Deno.makeTempFileSync();
const newPath = join(parse(file).dir, `${parse(file).base}_renamed`);
await new Promise((resolve, reject) => {
rename(file, newPath, (err) => {
if (err) reject(err);
});
})
.then(() => {
assertEquals(existsSync(newPath), true);
assertEquals(existsSync(file), false);
})
.catch(() => fail())
.finally(() => Deno.removeSync(file));
},
});
Deno.test({
name: "SYNC: renaming a file",
fn() {
const file = Deno.makeTempFileSync();
const newPath = join(parse(file).dir, `${parse(file).base}_renamed`);
renameSync(file, newPath);
assertEquals(existsSync(newPath), true);
assertEquals(existsSync(file), false);
},
});

View file

@ -1,36 +0,0 @@
type rmdirOptions = {
maxRetries?: number;
recursive?: boolean;
retryDelay?: number;
};
type rmdirCallback = (err?: Error) => void;
export function rmdir(path: string | URL, callback: rmdirCallback): void;
export function rmdir(
path: string | URL,
options: rmdirOptions,
callback: rmdirCallback,
): void;
export function rmdir(
path: string | URL,
optionsOrCallback: rmdirOptions | rmdirCallback,
maybeCallback?: rmdirCallback,
) {
const callback = typeof optionsOrCallback === "function"
? optionsOrCallback
: maybeCallback;
const options = typeof optionsOrCallback === "object"
? optionsOrCallback
: undefined;
if (!callback) throw new Error("No callback function supplied");
Deno.remove(path, { recursive: options?.recursive })
.then((_) => callback())
.catch(callback);
}
export function rmdirSync(path: string | URL, options?: rmdirOptions) {
Deno.removeSync(path, { recursive: options?.recursive });
}

View file

@ -1,66 +0,0 @@
import { assertEquals, fail } from "../../testing/asserts.ts";
import { rmdir, rmdirSync } from "./_fs_rmdir.ts";
import { existsSync } from "../../fs/mod.ts";
import { join } from "../../path/mod.ts";
Deno.test({
name: "ASYNC: removing empty folder",
async fn() {
const dir = Deno.makeTempDirSync();
await new Promise((resolve, reject) => {
rmdir(dir, (err) => {
if (err) reject(err);
resolve();
});
})
.then(() => assertEquals(existsSync(dir), false))
.catch(() => fail())
.finally(() => {
if (existsSync(dir)) Deno.removeSync(dir);
});
},
});
Deno.test({
name: "SYNC: removing empty folder",
fn() {
const dir = Deno.makeTempDirSync();
rmdirSync(dir);
assertEquals(existsSync(dir), false);
},
});
Deno.test({
name: "ASYNC: removing non-empty folder",
async fn() {
const dir = Deno.makeTempDirSync();
Deno.createSync(join(dir, "file1.txt"));
Deno.createSync(join(dir, "file2.txt"));
Deno.mkdirSync(join(dir, "some_dir"));
Deno.createSync(join(dir, "some_dir", "file.txt"));
await new Promise((resolve, reject) => {
rmdir(dir, { recursive: true }, (err) => {
if (err) reject(err);
resolve();
});
})
.then(() => assertEquals(existsSync(dir), false))
.catch(() => fail())
.finally(() => {
if (existsSync(dir)) Deno.removeSync(dir, { recursive: true });
});
},
});
Deno.test({
name: "SYNC: removing non-empty folder",
fn() {
const dir = Deno.makeTempDirSync();
Deno.createSync(join(dir, "file1.txt"));
Deno.createSync(join(dir, "file2.txt"));
Deno.mkdirSync(join(dir, "some_dir"));
Deno.createSync(join(dir, "some_dir", "file.txt"));
rmdirSync(dir, { recursive: true });
assertEquals(existsSync(dir), false);
},
});

View file

@ -1,284 +0,0 @@
export type statOptions = {
bigint: boolean;
};
export type Stats = {
/** ID of the device containing the file.
*
* _Linux/Mac OS only._ */
dev: number | null;
/** Inode number.
*
* _Linux/Mac OS only._ */
ino: number | null;
/** **UNSTABLE**: Match behavior with Go on Windows for `mode`.
*
* The underlying raw `st_mode` bits that contain the standard Unix
* permissions for this file/directory. */
mode: number | null;
/** Number of hard links pointing to this file.
*
* _Linux/Mac OS only._ */
nlink: number | null;
/** User ID of the owner of this file.
*
* _Linux/Mac OS only._ */
uid: number | null;
/** Group ID of the owner of this file.
*
* _Linux/Mac OS only._ */
gid: number | null;
/** Device ID of this file.
*
* _Linux/Mac OS only._ */
rdev: number | null;
/** The size of the file, in bytes. */
size: number;
/** Blocksize for filesystem I/O.
*
* _Linux/Mac OS only._ */
blksize: number | null;
/** Number of blocks allocated to the file, in 512-byte units.
*
* _Linux/Mac OS only._ */
blocks: number | null;
/** 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. */
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. */
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. */
birthtime: Date | null;
/** change time */
ctime: Date | null;
/** atime in milliseconds */
atimeMs: number | null;
/** atime in milliseconds */
mtimeMs: number | null;
/** atime in milliseconds */
ctimeMs: number | null;
/** atime in milliseconds */
birthtimeMs: number | null;
isBlockDevice: () => boolean;
isCharacterDevice: () => boolean;
isDirectory: () => boolean;
isFIFO: () => boolean;
isFile: () => boolean;
isSocket: () => boolean;
isSymbolicLink: () => boolean;
};
export type BigIntStats = {
/** ID of the device containing the file.
*
* _Linux/Mac OS only._ */
dev: BigInt | null;
/** Inode number.
*
* _Linux/Mac OS only._ */
ino: BigInt | null;
/** **UNSTABLE**: Match behavior with Go on Windows for `mode`.
*
* The underlying raw `st_mode` bits that contain the standard Unix
* permissions for this file/directory. */
mode: BigInt | null;
/** Number of hard links pointing to this file.
*
* _Linux/Mac OS only._ */
nlink: BigInt | null;
/** User ID of the owner of this file.
*
* _Linux/Mac OS only._ */
uid: BigInt | null;
/** Group ID of the owner of this file.
*
* _Linux/Mac OS only._ */
gid: BigInt | null;
/** Device ID of this file.
*
* _Linux/Mac OS only._ */
rdev: BigInt | null;
/** The size of the file, in bytes. */
size: BigInt;
/** Blocksize for filesystem I/O.
*
* _Linux/Mac OS only._ */
blksize: BigInt | null;
/** Number of blocks allocated to the file, in 512-byte units.
*
* _Linux/Mac OS only._ */
blocks: BigInt | null;
/** 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. */
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. */
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. */
birthtime: Date | null;
/** change time */
ctime: Date | null;
/** atime in milliseconds */
atimeMs: BigInt | null;
/** atime in milliseconds */
mtimeMs: BigInt | null;
/** atime in milliseconds */
ctimeMs: BigInt | null;
/** atime in nanoseconds */
birthtimeMs: BigInt | null;
/** atime in nanoseconds */
atimeNs: BigInt | null;
/** atime in nanoseconds */
mtimeNs: BigInt | null;
/** atime in nanoseconds */
ctimeNs: BigInt | null;
/** atime in nanoseconds */
birthtimeNs: BigInt | null;
isBlockDevice: () => boolean;
isCharacterDevice: () => boolean;
isDirectory: () => boolean;
isFIFO: () => boolean;
isFile: () => boolean;
isSocket: () => boolean;
isSymbolicLink: () => boolean;
};
export function convertFileInfoToStats(origin: Deno.FileInfo): Stats {
return {
dev: origin.dev,
ino: origin.ino,
mode: origin.mode,
nlink: origin.nlink,
uid: origin.uid,
gid: origin.gid,
rdev: origin.rdev,
size: origin.size,
blksize: origin.blksize,
blocks: origin.blocks,
mtime: origin.mtime,
atime: origin.atime,
birthtime: origin.birthtime,
mtimeMs: origin.mtime?.getTime() || null,
atimeMs: origin.atime?.getTime() || null,
birthtimeMs: origin.birthtime?.getTime() || null,
isFile: () => origin.isFile,
isDirectory: () => origin.isDirectory,
isSymbolicLink: () => origin.isSymlink,
// not sure about those
isBlockDevice: () => false,
isFIFO: () => false,
isCharacterDevice: () => false,
isSocket: () => false,
ctime: origin.mtime,
ctimeMs: origin.mtime?.getTime() || null,
};
}
export function convertFileInfoToBigIntStats(
origin: Deno.FileInfo,
): BigIntStats {
return {
dev: BigInt(origin.dev),
ino: BigInt(origin.ino),
mode: BigInt(origin.mode),
nlink: BigInt(origin.nlink),
uid: BigInt(origin.uid),
gid: BigInt(origin.gid),
rdev: BigInt(origin.rdev),
size: BigInt(origin.size),
blksize: BigInt(origin.blksize),
blocks: BigInt(origin.blocks),
mtime: origin.mtime,
atime: origin.atime,
birthtime: origin.birthtime,
mtimeMs: origin.mtime ? BigInt(origin.mtime.getTime()) : null,
atimeMs: origin.atime ? BigInt(origin.atime.getTime()) : null,
birthtimeMs: origin.birthtime ? BigInt(origin.birthtime.getTime()) : null,
mtimeNs: origin.mtime ? BigInt(origin.mtime.getTime()) * 1000000n : null,
atimeNs: origin.atime ? BigInt(origin.atime.getTime()) * 1000000n : null,
birthtimeNs: origin.birthtime
? BigInt(origin.birthtime.getTime()) * 1000000n
: null,
isFile: () => origin.isFile,
isDirectory: () => origin.isDirectory,
isSymbolicLink: () => origin.isSymlink,
// not sure about those
isBlockDevice: () => false,
isFIFO: () => false,
isCharacterDevice: () => false,
isSocket: () => false,
ctime: origin.mtime,
ctimeMs: origin.mtime ? BigInt(origin.mtime.getTime()) : null,
ctimeNs: origin.mtime ? BigInt(origin.mtime.getTime()) * 1000000n : null,
};
}
// shortcut for Convert File Info to Stats or BigIntStats
export function CFISBIS(fileInfo: Deno.FileInfo, bigInt: boolean) {
if (bigInt) return convertFileInfoToBigIntStats(fileInfo);
return convertFileInfoToStats(fileInfo);
}
export type statCallbackBigInt = (
err: Error | undefined,
stat: BigIntStats,
) => void;
export type statCallback = (err: Error | undefined, stat: Stats) => void;
export function stat(path: string | URL, callback: statCallback): void;
export function stat(
path: string | URL,
options: { bigint: false },
callback: statCallback,
): void;
export function stat(
path: string | URL,
options: { bigint: true },
callback: statCallbackBigInt,
): void;
export function stat(
path: string | URL,
optionsOrCallback: statCallback | statCallbackBigInt | statOptions,
maybeCallback?: statCallback | statCallbackBigInt,
) {
const callback =
(typeof optionsOrCallback === "function"
? optionsOrCallback
: maybeCallback) as (
err: Error | undefined,
stat: BigIntStats | Stats,
) => void;
const options = typeof optionsOrCallback === "object"
? optionsOrCallback
: { bigint: false };
if (!callback) throw new Error("No callback function supplied");
Deno.stat(path)
.then((stat) => callback(undefined, CFISBIS(stat, options.bigint)))
.catch((err) => callback(err, err));
}
export function statSync(path: string | URL): Stats;
export function statSync(path: string | URL, options: { bigint: false }): Stats;
export function statSync(
path: string | URL,
options: { bigint: true },
): BigIntStats;
export function statSync(
path: string | URL,
options: statOptions = { bigint: false },
): Stats | BigIntStats {
const origin = Deno.statSync(path);
return CFISBIS(origin, options.bigint);
}

View file

@ -1,107 +0,0 @@
import { BigIntStats, stat, Stats, statSync } from "./_fs_stat.ts";
import { assertEquals, fail } from "../../testing/asserts.ts";
export function assertStats(actual: Stats, expected: Deno.FileInfo) {
assertEquals(actual.dev, expected.dev);
assertEquals(actual.gid, expected.gid);
assertEquals(actual.size, expected.size);
assertEquals(actual.blksize, expected.blksize);
assertEquals(actual.blocks, expected.blocks);
assertEquals(actual.ino, expected.ino);
assertEquals(actual.gid, expected.gid);
assertEquals(actual.mode, expected.mode);
assertEquals(actual.nlink, expected.nlink);
assertEquals(actual.rdev, expected.rdev);
assertEquals(actual.uid, expected.uid);
assertEquals(actual.atime?.getTime(), expected.atime?.getTime());
assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime());
assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime());
assertEquals(actual.atimeMs, expected.atime?.getTime());
assertEquals(actual.mtimeMs, expected.mtime?.getTime());
assertEquals(actual.birthtimeMs, expected.birthtime?.getTime());
assertEquals(actual.isFile(), expected.isFile);
assertEquals(actual.isDirectory(), expected.isDirectory);
assertEquals(actual.isSymbolicLink(), expected.isSymlink);
// assertEquals(actual.ctimeMs === expected.ctime?.getTime());
// assertEquals(actual.ctime?.getTime() === expected.ctime?.getTime());
}
export function assertStatsBigInt(
actual: BigIntStats,
expected: Deno.FileInfo,
) {
assertEquals(actual.dev, BigInt(expected.dev));
assertEquals(actual.gid, BigInt(expected.gid));
assertEquals(actual.size, BigInt(expected.size));
assertEquals(actual.blksize, BigInt(expected.blksize));
assertEquals(actual.blocks, BigInt(expected.blocks));
assertEquals(actual.ino, BigInt(expected.ino));
assertEquals(actual.gid, BigInt(expected.gid));
assertEquals(actual.mode, BigInt(expected.mode));
assertEquals(actual.nlink, BigInt(expected.nlink));
assertEquals(actual.rdev, BigInt(expected.rdev));
assertEquals(actual.uid, BigInt(expected.uid));
assertEquals(actual.atime?.getTime(), expected.atime?.getTime());
assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime());
assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime());
assertEquals(Number(actual.atimeMs), expected.atime?.getTime());
assertEquals(Number(actual.mtimeMs), expected.mtime?.getTime());
assertEquals(Number(actual.birthtimeMs), expected.birthtime?.getTime());
assertEquals(Number(actual.atimeNs) / 1e6, expected.atime?.getTime());
assertEquals(Number(actual.mtimeNs) / 1e6, expected.atime?.getTime());
assertEquals(Number(actual.birthtimeNs) / 1e6, expected.atime?.getTime());
assertEquals(actual.isFile(), expected.isFile);
assertEquals(actual.isDirectory(), expected.isDirectory);
assertEquals(actual.isSymbolicLink(), expected.isSymlink);
// assertEquals(actual.ctime?.getTime() === expected.ctime?.getTime());
// assertEquals(Number(actual.ctimeMs) === expected.ctime?.getTime());
// assertEquals(Number(actual.ctimeNs) / 1e+6 === expected.ctime?.getTime());
}
Deno.test({
name: "ASYNC: get a file Stats",
async fn() {
const file = Deno.makeTempFileSync();
await new Promise<Stats>((resolve, reject) => {
stat(file, (err, stat) => {
if (err) reject(err);
resolve(stat);
});
})
.then((stat) => assertStats(stat, Deno.statSync(file)))
.catch(() => fail())
.finally(() => Deno.removeSync(file));
},
});
Deno.test({
name: "SYNC: get a file Stats",
fn() {
const file = Deno.makeTempFileSync();
assertStats(statSync(file), Deno.statSync(file));
},
});
Deno.test({
name: "ASYNC: get a file BigInt Stats",
async fn() {
const file = Deno.makeTempFileSync();
await new Promise<BigIntStats>((resolve, reject) => {
stat(file, { bigint: true }, (err, stat) => {
if (err) reject(err);
resolve(stat);
});
})
.then((stat) => assertStatsBigInt(stat, Deno.statSync(file)))
.catch(() => fail())
.finally(() => Deno.removeSync(file));
},
});
Deno.test({
name: "SYNC: get a file BigInt Stats",
fn() {
const file = Deno.makeTempFileSync();
assertStatsBigInt(statSync(file, { bigint: true }), Deno.statSync(file));
},
});

View file

@ -1,10 +0,0 @@
export function unlink(path: string | URL, callback: (err?: Error) => void) {
if (!callback) throw new Error("No callback function supplied");
Deno.remove(path)
.then((_) => callback())
.catch(callback);
}
export function unlinkSync(path: string | URL) {
Deno.removeSync(path);
}

View file

@ -1,30 +0,0 @@
import { assertEquals, fail } from "../../testing/asserts.ts";
import { existsSync } from "../../fs/mod.ts";
import { unlink, unlinkSync } from "./_fs_unlink.ts";
Deno.test({
name: "ASYNC: deleting a file",
async fn() {
const file = Deno.makeTempFileSync();
await new Promise((resolve, reject) => {
unlink(file, (err) => {
if (err) reject(err);
resolve();
});
})
.then(() => assertEquals(existsSync(file), false))
.catch(() => fail())
.finally(() => {
if (existsSync(file)) Deno.removeSync(file);
});
},
});
Deno.test({
name: "SYNC: Test deleting a file",
fn() {
const file = Deno.makeTempFileSync();
unlinkSync(file);
assertEquals(existsSync(file), false);
},
});

View file

@ -1,111 +0,0 @@
import { fromFileUrl } from "../path.ts";
import { EventEmitter } from "../events.ts";
import { notImplemented } from "../_utils.ts";
export function asyncIterableIteratorToCallback<T>(
iterator: AsyncIterableIterator<T>,
callback: (val: T, done?: boolean) => void,
) {
function next() {
iterator.next().then((obj) => {
if (obj.done) {
callback(obj.value, true);
return;
}
callback(obj.value);
next();
});
}
next();
}
export function asyncIterableToCallback<T>(
iter: AsyncIterable<T>,
callback: (val: T, done?: boolean) => void,
) {
const iterator = iter[Symbol.asyncIterator]();
function next() {
iterator.next().then((obj) => {
if (obj.done) {
callback(obj.value, true);
return;
}
callback(obj.value);
next();
});
}
next();
}
type watchOptions = {
persistent?: boolean;
recursive?: boolean;
encoding?: string;
};
type watchListener = (eventType: string, filename: string) => void;
export function watch(
filename: string | URL,
options: watchOptions,
listener: watchListener,
): FSWatcher;
export function watch(
filename: string | URL,
listener: watchListener,
): FSWatcher;
export function watch(
filename: string | URL,
options: watchOptions,
): FSWatcher;
export function watch(filename: string | URL): FSWatcher;
export function watch(
filename: string | URL,
optionsOrListener?: watchOptions | watchListener,
optionsOrListener2?: watchOptions | watchListener,
) {
const listener = typeof optionsOrListener === "function"
? optionsOrListener
: typeof optionsOrListener2 === "function"
? optionsOrListener2
: undefined;
const options = typeof optionsOrListener === "object"
? optionsOrListener
: typeof optionsOrListener2 === "object"
? optionsOrListener2
: undefined;
filename = filename instanceof URL ? fromFileUrl(filename) : filename;
const iterator = Deno.watchFs(filename, {
recursive: options?.recursive || false,
});
if (!listener) throw new Error("No callback function supplied");
const fsWatcher = new FSWatcher(() => {
if (iterator.return) iterator.return();
});
fsWatcher.on("change", listener);
asyncIterableIteratorToCallback<Deno.FsEvent>(iterator, (val, done) => {
if (done) return;
fsWatcher.emit("change", val.kind, val.paths[0]);
});
return fsWatcher;
}
class FSWatcher extends EventEmitter {
close: () => void;
constructor(closer: () => void) {
super();
this.close = closer;
}
ref() {
notImplemented("FSWatcher.ref() is not implemented");
}
unref() {
notImplemented("FSWatcher.unref() is not implemented");
}
}

View file

@ -1,29 +0,0 @@
import { watch } from "./_fs_watch.ts";
import { assertEquals } from "../../testing/asserts.ts";
function wait(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
}
Deno.test({
name: "watching a file",
async fn() {
const file = Deno.makeTempFileSync();
const result: Array<[string, string]> = [];
const watcher = watch(
file,
(eventType, filename) => result.push([eventType, filename]),
);
await wait(100);
Deno.writeTextFileSync(file, "something");
await wait(100);
watcher.close();
assertEquals(result, [
["modify", file],
["modify", file],
["access", file],
]);
},
});

View file

@ -11,15 +11,6 @@ import { exists, existsSync } from "./_fs/_fs_exists.ts";
import { mkdir, mkdirSync } from "./_fs/_fs_mkdir.ts"; import { mkdir, mkdirSync } from "./_fs/_fs_mkdir.ts";
import { copyFile, copyFileSync } from "./_fs/_fs_copy.ts"; import { copyFile, copyFileSync } from "./_fs/_fs_copy.ts";
import { writeFile, writeFileSync } from "./_fs/_fs_writeFile.ts"; import { writeFile, writeFileSync } from "./_fs/_fs_writeFile.ts";
import { readdir, readdirSync } from "./_fs/_fs_readdir.ts";
import { rename, renameSync } from "./_fs/_fs_rename.ts";
import { rmdir, rmdirSync } from "./_fs/_fs_rmdir.ts";
import { unlink, unlinkSync } from "./_fs/_fs_unlink.ts";
import { watch } from "./_fs/_fs_watch.ts";
import { open, openSync } from "./_fs/_fs_open.ts";
import { stat, statSync } from "./_fs/_fs_stat.ts";
import { lstat, lstatSync } from "./_fs/_fs_lstat.ts";
import * as promises from "./_fs/promises/mod.ts"; import * as promises from "./_fs/promises/mod.ts";
export { export {
@ -38,29 +29,13 @@ export {
copyFileSync, copyFileSync,
exists, exists,
existsSync, existsSync,
// not sure about those
lstat,
lstatSync,
mkdir, mkdir,
mkdirSync, mkdirSync,
open,
openSync,
promises, promises,
readdir,
readdirSync,
readFile, readFile,
readFileSync, readFileSync,
readlink, readlink,
readlinkSync, readlinkSync,
rename,
renameSync,
rmdir,
rmdirSync,
stat,
statSync,
unlink,
unlinkSync,
watch,
writeFile, writeFile,
writeFileSync, writeFileSync,
}; };